From 6375d40322f06925f5f24cd555b12567c830502b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 20 Dec 2018 11:55:22 +0800 Subject: brcmsmac: remove set but not used variables 'phybw40, maxtargetpwr' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c:1202:5: warning: variable 'phybw40' set but not used [-Wunused-but-set-variable] drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c:4625:5: warning: variable 'phybw40' set but not used [-Wunused-but-set-variable] drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c:4834:5: warning: variable 'phybw40' set but not used [-Wunused-but-set-variable] drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c:3085:17: warning: variable 'maxtargetpwr' set but not used [-Wunused-but-set-variable] drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c:4215:17: warning: variable 'maxtargetpwr' set but not used [-Wunused-but-set-variable] Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- .../net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c index e78a93a45741..c6e107f41948 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c @@ -1199,8 +1199,6 @@ wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, { int wait_count = 0; bool result = true; - u8 phybw40; - phybw40 = CHSPEC_IS40(pi->radio_chanspec); mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5); @@ -3082,7 +3080,7 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) u8 bbmult; struct phytbl_info tab; s32 a1, b0, b1; - s32 tssi, pwr, maxtargetpwr, mintargetpwr; + s32 tssi, pwr, mintargetpwr; bool suspend; struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); @@ -3119,7 +3117,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) b0 = pi->txpa_2g[0]; b1 = pi->txpa_2g[1]; a1 = pi->txpa_2g[2]; - maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1); mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; @@ -4212,7 +4209,7 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi) s8 index; struct phytbl_info tab; s32 a1, b0, b1; - s32 tssi, pwr, maxtargetpwr, mintargetpwr; + s32 tssi, pwr, mintargetpwr; struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; pi->phy_lastcal = pi->sh->now; @@ -4249,7 +4246,6 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi) b0 = pi->txpa_2g[0]; b1 = pi->txpa_2g[1]; a1 = pi->txpa_2g[2]; - maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1); mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; @@ -4622,13 +4618,10 @@ static void wlc_lcnphy_radio_init(struct brcms_phy *pi) static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) { uint idx; - u8 phybw40; struct phytbl_info tab; const struct phytbl_info *tb; u32 val; - phybw40 = CHSPEC_IS40(pi->radio_chanspec); - for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]); @@ -4831,9 +4824,7 @@ static void wlc_lcnphy_baseband_init(struct brcms_phy *pi) void wlc_phy_init_lcnphy(struct brcms_phy *pi) { - u8 phybw40; struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; - phybw40 = CHSPEC_IS40(pi->radio_chanspec); pi_lcn->lcnphy_cal_counter = 0; pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense; -- cgit v1.2.3 From ba2ffc96321c8433606ceeb85c9e722b8113e5a7 Mon Sep 17 00:00:00 2001 From: Zumeng Chen Date: Wed, 19 Dec 2018 15:50:29 +0800 Subject: wlcore: Fix memory leak in case wl12xx_fetch_firmware failure Release fw_status, raw_fw_status, and tx_res_if when wl12xx_fetch_firmware failed instead of meaningless goto out to avoid the following memory leak reports(Only the last one listed): unreferenced object 0xc28a9a00 (size 512): comm "kworker/0:4", pid 31298, jiffies 2783204 (age 203.290s) hex dump (first 32 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<6624adab>] kmemleak_alloc+0x40/0x74 [<500ddb31>] kmem_cache_alloc_trace+0x1ac/0x270 [] wl12xx_chip_wakeup+0xc4/0x1fc [wlcore] [<76c5db53>] wl1271_op_add_interface+0x4a4/0x8f4 [wlcore] [] drv_add_interface+0xa4/0x1a0 [mac80211] [<65bac325>] ieee80211_reconfig+0x9c0/0x1644 [mac80211] [<2817c80e>] ieee80211_restart_work+0x90/0xc8 [mac80211] [<7e1d425a>] process_one_work+0x284/0x42c [<55f9432e>] worker_thread+0x2fc/0x48c [] kthread+0x148/0x160 [<63144b13>] ret_from_fork+0x14/0x2c [< (null)>] (null) [<1f6e7715>] 0xffffffff Signed-off-by: Zumeng Chen Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 26b187336875..2e12de813a5b 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1085,8 +1085,11 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) goto out; ret = wl12xx_fetch_firmware(wl, plt); - if (ret < 0) - goto out; + if (ret < 0) { + kfree(wl->fw_status); + kfree(wl->raw_fw_status); + kfree(wl->tx_res_if); + } out: return ret; -- cgit v1.2.3 From 72255c807156adeb167444c4206c9e5eece22287 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 20 Dec 2018 14:05:50 +0000 Subject: ray_cs: fix array out-of-bounds access Currently array element org[3] is being accessed, however the array is only 3 elements in size, so this looks like an off-by-one out-of-bounds error. Fix this by using org[2], which I believe was the original intent. This issue has existed in the driver back in the pre-git days, so no idea when it was introduced. Detected by CoverityScan, CID#711344 ("Out-of-bounds read") Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ray_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 33ad87528d9a..8b2741c8edf2 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -959,7 +959,7 @@ static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, if (proto == htons(ETH_P_AARP) || proto == htons(ETH_P_IPX)) { /* This is the selective translation table, only 2 entries */ writeb(0xf8, - &((struct snaphdr_t __iomem *)ptx->var)->org[3]); + &((struct snaphdr_t __iomem *)ptx->var)->org[2]); } /* Copy body of ethernet packet without ethernet header */ memcpy_toio((void __iomem *)&ptx->var + -- cgit v1.2.3 From 4d95f99c59b8b814bcf09ba86020d937ec7caa86 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 20 Dec 2018 17:40:58 +0100 Subject: brcmfmac: Add DMI nvram filename quirk for PoV TAB-P1006W-232 tablet The Point of View TAB-P1006W-232 tablet contains quite generic names in the sys_vendor and product_name DMI strings, without this patch brcmfmac will try to load: brcmfmac43340-sdio.Insyde-BayTrail.txt as nvram file which is a bit too generic. Add a DMI quirk so that a unique and clearly identifiable nvram file name is used on the PoV TAB-P1006W-232 tablet. Signed-off-by: Hans de Goede Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c index 51d76ac45075..7535cb0d4ac0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c @@ -43,6 +43,10 @@ static const struct brcmf_dmi_data meegopad_t08_data = { BRCM_CC_43340_CHIP_ID, 2, "meegopad-t08" }; +static const struct brcmf_dmi_data pov_tab_p1006w_data = { + BRCM_CC_43340_CHIP_ID, 2, "pov-tab-p1006w-data" +}; + static const struct dmi_system_id dmi_platform_data[] = { { /* Match for the GPDwin which unfortunately uses somewhat @@ -81,6 +85,17 @@ static const struct dmi_system_id dmi_platform_data[] = { }, .driver_data = (void *)&meegopad_t08_data, }, + { + /* Point of View TAB-P1006W-232 */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "BayTrail"), + /* Note 105b is Foxcon's USB/PCI vendor id */ + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "105B"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "0E57"), + }, + .driver_data = (void *)&pov_tab_p1006w_data, + }, {} }; -- cgit v1.2.3 From 51c8d24101c79ffce3e79137e2cee5dfeb956dd7 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 22 Dec 2018 10:34:54 +0000 Subject: cw1200: fix missing unlock on error in cw1200_hw_scan() Add the missing unlock before return from function cw1200_hw_scan() in the error handling case. Fixes: 4f68ef64cd7f ("cw1200: Fix concurrency use-after-free bugs in cw1200_hw_scan()") Signed-off-by: Wei Yongjun Acked-by: Jia-Ju Bai Signed-off-by: Kalle Valo --- drivers/net/wireless/st/cw1200/scan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c index 0a9eac93dd01..71e9b91cf15b 100644 --- a/drivers/net/wireless/st/cw1200/scan.c +++ b/drivers/net/wireless/st/cw1200/scan.c @@ -84,8 +84,11 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0, req->ie_len); - if (!frame.skb) + if (!frame.skb) { + mutex_unlock(&priv->conf_mutex); + up(&priv->scan.lock); return -ENOMEM; + } if (req->ie_len) skb_put_data(frame.skb, req->ie, req->ie_len); -- cgit v1.2.3 From 06605b0d38b491c6dc52f4aee3e588e1309fbfaf Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 23 Dec 2018 09:57:15 +0100 Subject: cw1200: drop useless LIST_HEAD Drop LIST_HEAD where the variable it declares has never been used. The semantic patch that fixes this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier x; @@ - LIST_HEAD(x); ... when != x // Fixes: a910e4a94f692 ("cw1200: add driver for the ST-E CW1100 & CW1200 WLAN chipsets") Signed-off-by: Julia Lawall Signed-off-by: Kalle Valo --- drivers/net/wireless/st/cw1200/queue.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/st/cw1200/queue.c b/drivers/net/wireless/st/cw1200/queue.c index 7c31b63b8258..7895efefa95d 100644 --- a/drivers/net/wireless/st/cw1200/queue.c +++ b/drivers/net/wireless/st/cw1200/queue.c @@ -283,7 +283,6 @@ int cw1200_queue_put(struct cw1200_queue *queue, struct cw1200_txpriv *txpriv) { int ret = 0; - LIST_HEAD(gc_list); struct cw1200_queue_stats *stats = queue->stats; if (txpriv->link_id >= queue->stats->map_capacity) -- cgit v1.2.3 From 42daad3343be4a4e1ee03e30a5f5cc731dadfef5 Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Tue, 25 Dec 2018 19:22:24 -0600 Subject: brcmfmac: add a check for the status of usb_register usb_register() may fail, so let's check its status and issue an error message if it fails. Signed-off-by: Kangjie Lu Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index a4308c6e72d7..76cfaf6999c8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -1550,6 +1550,10 @@ void brcmf_usb_exit(void) void brcmf_usb_register(void) { + int ret; + brcmf_dbg(USB, "Enter\n"); - usb_register(&brcmf_usbdrvr); + ret = usb_register(&brcmf_usbdrvr); + if (ret) + brcmf_err("usb_register failed %d\n", ret); } -- cgit v1.2.3 From 7fdcb8e1266093eb2ff1bc3ab430daf4775388ad Mon Sep 17 00:00:00 2001 From: Prameela Rani Garnepudi Date: Thu, 27 Dec 2018 14:56:18 +0530 Subject: rsi: add support for hardware scan offload With the current approach of scanning, roaming delays are observed. Firmware has support for back ground scanning. To get this advantage, mac80211 hardware scan is implemented, which decides type of scan to do based on connected state. When station is in not connected, driver returns with special value 1 to trigger software scan in mac80211. In case of connected state, background scan will be triggered. Signed-off-by: Prameela Rani Garnepudi Signed-off-by: Siva Rebbagondla Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_hal.c | 3 + drivers/net/wireless/rsi/rsi_91x_mac80211.c | 67 ++++++++++++++ drivers/net/wireless/rsi/rsi_91x_main.c | 1 + drivers/net/wireless/rsi/rsi_91x_mgmt.c | 133 ++++++++++++++++++++++++++++ drivers/net/wireless/rsi/rsi_main.h | 22 +++++ drivers/net/wireless/rsi/rsi_mgmt.h | 35 ++++++++ 6 files changed, 261 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index 182b06629371..1dbaab2a96b7 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c @@ -100,6 +100,9 @@ int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb) mgmt_desc->frame_type = TX_DOT11_MGMT; mgmt_desc->header_len = MIN_802_11_HDR_LEN; mgmt_desc->xtend_desc_size = header_size - FRAME_DESC_SZ; + + if (ieee80211_is_probe_req(wh->frame_control)) + mgmt_desc->frame_info = cpu_to_le16(RSI_INSERT_SEQ_IN_FW); mgmt_desc->frame_info |= cpu_to_le16(RATE_INFO_ENABLE); if (is_broadcast_ether_addr(wh->addr1)) mgmt_desc->frame_info |= cpu_to_le16(RSI_BROADCAST_PKT); diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index e56fc83faf0e..aded1ae4fad5 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -229,6 +229,68 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band) /* sbands->ht_cap.mcs.rx_highest = 0x82; */ } +static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req) +{ + struct cfg80211_scan_request *scan_req = &hw_req->req; + struct rsi_hw *adapter = hw->priv; + struct rsi_common *common = adapter->priv; + struct ieee80211_bss_conf *bss = &vif->bss_conf; + + rsi_dbg(INFO_ZONE, "***** Hardware scan start *****\n"); + + if (common->fsm_state != FSM_MAC_INIT_DONE) + return -ENODEV; + + if ((common->wow_flags & RSI_WOW_ENABLED) || + scan_req->n_channels == 0) + return -EINVAL; + + /* Scan already in progress. So return */ + if (common->bgscan_en) + return -EBUSY; + + /* If STA is not connected, return with special value 1, in order + * to start sw_scan in mac80211 + */ + if (!bss->assoc) + return 1; + + mutex_lock(&common->mutex); + common->hwscan = scan_req; + if (!rsi_send_bgscan_params(common, RSI_START_BGSCAN)) { + if (!rsi_send_bgscan_probe_req(common, vif)) { + rsi_dbg(INFO_ZONE, "Background scan started...\n"); + common->bgscan_en = true; + } + } + mutex_unlock(&common->mutex); + + return 0; +} + +static void rsi_mac80211_cancel_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rsi_hw *adapter = hw->priv; + struct rsi_common *common = adapter->priv; + struct cfg80211_scan_info info; + + rsi_dbg(INFO_ZONE, "***** Hardware scan stop *****\n"); + mutex_lock(&common->mutex); + + if (common->bgscan_en) { + if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN)) + common->bgscan_en = false; + info.aborted = false; + ieee80211_scan_completed(adapter->hw, &info); + rsi_dbg(INFO_ZONE, "Back ground scan cancelled\b\n"); + } + common->hwscan = NULL; + mutex_unlock(&common->mutex); +} + /** * rsi_mac80211_detach() - This function is used to de-initialize the * Mac80211 stack. @@ -1917,6 +1979,8 @@ static const struct ieee80211_ops mac80211_ops = { .suspend = rsi_mac80211_suspend, .resume = rsi_mac80211_resume, #endif + .hw_scan = rsi_mac80211_hw_scan_start, + .cancel_hw_scan = rsi_mac80211_cancel_hw_scan, }; /** @@ -1999,6 +2063,9 @@ int rsi_mac80211_attach(struct rsi_common *common) common->max_stations = wiphy->max_ap_assoc_sta; rsi_dbg(ERR_ZONE, "Max Stations Allowed = %d\n", common->max_stations); hw->sta_data_size = sizeof(struct rsi_sta); + + wiphy->max_scan_ssids = RSI_MAX_SCAN_SSIDS; + wiphy->max_scan_ie_len = RSI_MAX_SCAN_IE_LEN; wiphy->flags = WIPHY_FLAG_REPORTS_OBSS; wiphy->flags |= WIPHY_FLAG_AP_UAPSD; wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c index 01d99ed985ee..ca3a55ed72e4 100644 --- a/drivers/net/wireless/rsi/rsi_91x_main.c +++ b/drivers/net/wireless/rsi/rsi_91x_main.c @@ -328,6 +328,7 @@ struct rsi_hw *rsi_91x_init(u16 oper_mode) } rsi_default_ps_params(adapter); + init_bgscan_params(common); spin_lock_init(&adapter->ps_lock); timer_setup(&common->roc_timer, rsi_roc_timeout, 0); init_completion(&common->wlan_init_completion); diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 1095df7d9573..404241424a62 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -15,6 +15,7 @@ */ #include +#include #include "rsi_mgmt.h" #include "rsi_common.h" #include "rsi_ps.h" @@ -236,6 +237,18 @@ static void rsi_set_default_parameters(struct rsi_common *common) common->dtim_cnt = RSI_DTIM_COUNT; } +void init_bgscan_params(struct rsi_common *common) +{ + memset((u8 *)&common->bgscan, 0, sizeof(struct rsi_bgscan_params)); + common->bgscan.bgscan_threshold = RSI_DEF_BGSCAN_THRLD; + common->bgscan.roam_threshold = RSI_DEF_ROAM_THRLD; + common->bgscan.bgscan_periodicity = RSI_BGSCAN_PERIODICITY; + common->bgscan.num_bgscan_channels = 0; + common->bgscan.two_probe = 1; + common->bgscan.active_scan_duration = RSI_ACTIVE_SCAN_TIME; + common->bgscan.passive_scan_duration = RSI_PASSIVE_SCAN_TIME; +} + /** * rsi_set_contention_vals() - This function sets the contention values for the * backoff procedure. @@ -1628,6 +1641,107 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags, } #endif +int rsi_send_bgscan_params(struct rsi_common *common, int enable) +{ + struct rsi_bgscan_params *params = &common->bgscan; + struct cfg80211_scan_request *scan_req = common->hwscan; + struct rsi_bgscan_config *bgscan; + struct sk_buff *skb; + u16 frame_len = sizeof(*bgscan); + u8 i; + + rsi_dbg(MGMT_TX_ZONE, "%s: Sending bgscan params frame\n", __func__); + + skb = dev_alloc_skb(frame_len); + if (!skb) + return -ENOMEM; + memset(skb->data, 0, frame_len); + + bgscan = (struct rsi_bgscan_config *)skb->data; + rsi_set_len_qno(&bgscan->desc_dword0.len_qno, + (frame_len - FRAME_DESC_SZ), RSI_WIFI_MGMT_Q); + bgscan->desc_dword0.frame_type = BG_SCAN_PARAMS; + bgscan->bgscan_threshold = cpu_to_le16(params->bgscan_threshold); + bgscan->roam_threshold = cpu_to_le16(params->roam_threshold); + if (enable) + bgscan->bgscan_periodicity = + cpu_to_le16(params->bgscan_periodicity); + bgscan->active_scan_duration = + cpu_to_le16(params->active_scan_duration); + bgscan->passive_scan_duration = + cpu_to_le16(params->passive_scan_duration); + bgscan->two_probe = params->two_probe; + + bgscan->num_bgscan_channels = scan_req->n_channels; + for (i = 0; i < bgscan->num_bgscan_channels; i++) + bgscan->channels2scan[i] = + cpu_to_le16(scan_req->channels[i]->hw_value); + + skb_put(skb, frame_len); + + return rsi_send_internal_mgmt_frame(common, skb); +} + +/* This function sends the probe request to be used by firmware in + * background scan + */ +int rsi_send_bgscan_probe_req(struct rsi_common *common, + struct ieee80211_vif *vif) +{ + struct cfg80211_scan_request *scan_req = common->hwscan; + struct rsi_bgscan_probe *bgscan; + struct sk_buff *skb; + struct sk_buff *probereq_skb; + u16 frame_len = sizeof(*bgscan); + size_t ssid_len = 0; + u8 *ssid = NULL; + + rsi_dbg(MGMT_TX_ZONE, + "%s: Sending bgscan probe req frame\n", __func__); + + if (common->priv->sc_nvifs <= 0) + return -ENODEV; + + if (scan_req->n_ssids) { + ssid = scan_req->ssids[0].ssid; + ssid_len = scan_req->ssids[0].ssid_len; + } + + skb = dev_alloc_skb(frame_len + MAX_BGSCAN_PROBE_REQ_LEN); + if (!skb) + return -ENOMEM; + memset(skb->data, 0, frame_len + MAX_BGSCAN_PROBE_REQ_LEN); + + bgscan = (struct rsi_bgscan_probe *)skb->data; + bgscan->desc_dword0.frame_type = BG_SCAN_PROBE_REQ; + bgscan->flags = cpu_to_le16(HOST_BG_SCAN_TRIG); + if (common->band == NL80211_BAND_5GHZ) { + bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_6); + bgscan->def_chan = cpu_to_le16(40); + } else { + bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_1); + bgscan->def_chan = cpu_to_le16(11); + } + bgscan->channel_scan_time = cpu_to_le16(RSI_CHANNEL_SCAN_TIME); + + probereq_skb = ieee80211_probereq_get(common->priv->hw, vif->addr, ssid, + ssid_len, scan_req->ie_len); + + memcpy(&skb->data[frame_len], probereq_skb->data, probereq_skb->len); + + bgscan->probe_req_length = cpu_to_le16(probereq_skb->len); + + rsi_set_len_qno(&bgscan->desc_dword0.len_qno, + (frame_len - FRAME_DESC_SZ + probereq_skb->len), + RSI_WIFI_MGMT_Q); + + skb_put(skb, frame_len + probereq_skb->len); + + dev_kfree_skb(probereq_skb); + + return rsi_send_internal_mgmt_frame(common, skb); +} + /** * rsi_handle_ta_confirm_type() - This function handles the confirm frames. * @common: Pointer to the driver private structure. @@ -1771,9 +1885,28 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, return 0; } break; + + case SCAN_REQUEST: + rsi_dbg(INFO_ZONE, "Set channel confirm\n"); + break; + case WAKEUP_SLEEP_REQUEST: rsi_dbg(INFO_ZONE, "Wakeup/Sleep confirmation.\n"); return rsi_handle_ps_confirm(adapter, msg); + + case BG_SCAN_PROBE_REQ: + rsi_dbg(INFO_ZONE, "BG scan complete event\n"); + if (common->bgscan_en) { + struct cfg80211_scan_info info; + + if (!rsi_send_bgscan_params(common, RSI_STOP_BGSCAN)) + common->bgscan_en = 0; + info.aborted = false; + ieee80211_scan_completed(adapter->hw, &info); + } + rsi_dbg(INFO_ZONE, "Background scan completed\n"); + break; + default: rsi_dbg(INFO_ZONE, "%s: Invalid TA confirm pkt received\n", __func__); diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index a084f224bb03..4dc0c0123469 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -164,6 +164,24 @@ struct transmit_q_stats { u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 2]; }; +#define MAX_BGSCAN_CHANNELS_DUAL_BAND 38 +#define MAX_BGSCAN_PROBE_REQ_LEN 0x64 +#define RSI_DEF_BGSCAN_THRLD 0x0 +#define RSI_DEF_ROAM_THRLD 0xa +#define RSI_BGSCAN_PERIODICITY 0x1e +#define RSI_ACTIVE_SCAN_TIME 0x14 +#define RSI_PASSIVE_SCAN_TIME 0x46 +#define RSI_CHANNEL_SCAN_TIME 20 +struct rsi_bgscan_params { + u16 bgscan_threshold; + u16 roam_threshold; + u16 bgscan_periodicity; + u8 num_bgscan_channels; + u8 two_probe; + u16 active_scan_duration; + u16 passive_scan_duration; +}; + struct vif_priv { bool is_ht; bool sgi; @@ -289,6 +307,10 @@ struct rsi_common { bool eapol4_confirm; void *bt_adapter; + + struct cfg80211_scan_request *hwscan; + struct rsi_bgscan_params bgscan; + u8 bgscan_en; }; struct eepromrw_info { diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h index 359fbdf85739..ea83faa15c7e 100644 --- a/drivers/net/wireless/rsi/rsi_mgmt.h +++ b/drivers/net/wireless/rsi/rsi_mgmt.h @@ -228,6 +228,9 @@ #define RSI_MAX_TX_AGGR_FRMS 8 #define RSI_MAX_RX_AGGR_FRMS 8 +#define RSI_MAX_SCAN_SSIDS 16 +#define RSI_MAX_SCAN_IE_LEN 256 + enum opmode { RSI_OPMODE_UNSUPPORTED = -1, RSI_OPMODE_AP = 0, @@ -623,6 +626,34 @@ struct rsi_wowlan_req { u16 host_sleep_status; } __packed; +#define RSI_START_BGSCAN 1 +#define RSI_STOP_BGSCAN 0 +#define HOST_BG_SCAN_TRIG BIT(4) +struct rsi_bgscan_config { + struct rsi_cmd_desc_dword0 desc_dword0; + __le64 reserved; + __le32 reserved1; + __le16 bgscan_threshold; + __le16 roam_threshold; + __le16 bgscan_periodicity; + u8 num_bgscan_channels; + u8 two_probe; + __le16 active_scan_duration; + __le16 passive_scan_duration; + __le16 channels2scan[MAX_BGSCAN_CHANNELS_DUAL_BAND]; +} __packed; + +struct rsi_bgscan_probe { + struct rsi_cmd_desc_dword0 desc_dword0; + __le64 reserved; + __le32 reserved1; + __le16 mgmt_rate; + __le16 flags; + __le16 def_chan; + __le16 channel_scan_time; + __le16 probe_req_length; +} __packed; + static inline u32 rsi_get_queueno(u8 *addr, u16 offset) { return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12; @@ -694,4 +725,8 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags, #endif int rsi_send_ps_request(struct rsi_hw *adapter, bool enable, struct ieee80211_vif *vif); +void init_bgscan_params(struct rsi_common *common); +int rsi_send_bgscan_params(struct rsi_common *common, int enable); +int rsi_send_bgscan_probe_req(struct rsi_common *common, + struct ieee80211_vif *vif); #endif -- cgit v1.2.3 From 5a1c18b761ddb299a06746948b9ec2814b04fa92 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 2 Jan 2019 00:00:01 +0100 Subject: bcma: keep a direct pointer to the struct device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accessing struct device is pretty useful/common so having a direct pointer: 1) Simplifies some code 2) Makes bcma_bus_get_host_dev() unneeded 3) Allows further improvements like using dev_* printing helpers Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/bcma_private.h | 1 - drivers/bcma/driver_gpio.c | 2 +- drivers/bcma/host_pci.c | 2 ++ drivers/bcma/host_soc.c | 4 ++-- drivers/bcma/main.c | 45 ++++++++++----------------------------------- include/linux/bcma/bcma.h | 11 +++-------- 6 files changed, 18 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index a4aac370f21f..1f0e66310b23 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -33,7 +33,6 @@ int __init bcma_bus_early_register(struct bcma_bus *bus); int bcma_bus_suspend(struct bcma_bus *bus); int bcma_bus_resume(struct bcma_bus *bus); #endif -struct device *bcma_bus_get_host_dev(struct bcma_bus *bus); /* scan.c */ void bcma_detect_chip(struct bcma_bus *bus); diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c index 2c0ffb77d738..a5df3d111334 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -183,7 +183,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) chip->direction_input = bcma_gpio_direction_input; chip->direction_output = bcma_gpio_direction_output; chip->owner = THIS_MODULE; - chip->parent = bcma_bus_get_host_dev(bus); + chip->parent = bus->dev; #if IS_BUILTIN(CONFIG_OF) chip->of_node = cc->core->dev.of_node; #endif diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 63410ecfe640..f52239feb4cb 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -196,6 +196,8 @@ static int bcma_host_pci_probe(struct pci_dev *dev, goto err_pci_release_regions; } + bus->dev = &dev->dev; + /* Map MMIO */ err = -ENOMEM; bus->mmio = pci_iomap(dev, 0, ~0UL); diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c index 2dce34789329..c8073b509a2b 100644 --- a/drivers/bcma/host_soc.c +++ b/drivers/bcma/host_soc.c @@ -179,7 +179,6 @@ int __init bcma_host_soc_register(struct bcma_soc *soc) /* Host specific */ bus->hosttype = BCMA_HOSTTYPE_SOC; bus->ops = &bcma_host_soc_ops; - bus->host_pdev = NULL; /* Initialize struct, detect chip */ bcma_init_bus(bus); @@ -213,6 +212,8 @@ static int bcma_host_soc_probe(struct platform_device *pdev) if (!bus) return -ENOMEM; + bus->dev = dev; + /* Map MMIO */ bus->mmio = of_iomap(np, 0); if (!bus->mmio) @@ -221,7 +222,6 @@ static int bcma_host_soc_probe(struct platform_device *pdev) /* Host specific */ bus->hosttype = BCMA_HOSTTYPE_SOC; bus->ops = &bcma_host_soc_ops; - bus->host_pdev = pdev; /* Initialize struct, detect chip */ bcma_init_bus(bus); diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index fc1f4acdd189..6535614a7dc1 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -223,8 +223,8 @@ unsigned int bcma_core_irq(struct bcma_device *core, int num) mips_irq = bcma_core_mips_irq(core); return mips_irq <= 4 ? mips_irq + 2 : 0; } - if (bus->host_pdev) - return bcma_of_get_irq(&bus->host_pdev->dev, core, num); + if (bus->dev) + return bcma_of_get_irq(bus->dev, core, num); return 0; case BCMA_HOSTTYPE_SDIO: return 0; @@ -239,18 +239,18 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) core->dev.release = bcma_release_core_dev; core->dev.bus = &bcma_bus_type; dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); - core->dev.parent = bcma_bus_get_host_dev(bus); - if (core->dev.parent) - bcma_of_fill_device(core->dev.parent, core); + core->dev.parent = bus->dev; + if (bus->dev) + bcma_of_fill_device(bus->dev, core); switch (bus->hosttype) { case BCMA_HOSTTYPE_PCI: - core->dma_dev = &bus->host_pci->dev; + core->dma_dev = bus->dev; core->irq = bus->host_pci->irq; break; case BCMA_HOSTTYPE_SOC: - if (IS_ENABLED(CONFIG_OF) && bus->host_pdev) { - core->dma_dev = &bus->host_pdev->dev; + if (IS_ENABLED(CONFIG_OF) && bus->dev) { + core->dma_dev = bus->dev; } else { core->dev.dma_mask = &core->dev.coherent_dma_mask; core->dma_dev = &core->dev; @@ -261,28 +261,6 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) } } -struct device *bcma_bus_get_host_dev(struct bcma_bus *bus) -{ - switch (bus->hosttype) { - case BCMA_HOSTTYPE_PCI: - if (bus->host_pci) - return &bus->host_pci->dev; - else - return NULL; - case BCMA_HOSTTYPE_SOC: - if (bus->host_pdev) - return &bus->host_pdev->dev; - else - return NULL; - case BCMA_HOSTTYPE_SDIO: - if (bus->host_sdio) - return &bus->host_sdio->dev; - else - return NULL; - } - return NULL; -} - void bcma_init_bus(struct bcma_bus *bus) { mutex_lock(&bcma_buses_mutex); @@ -402,7 +380,6 @@ int bcma_bus_register(struct bcma_bus *bus) { int err; struct bcma_device *core; - struct device *dev; /* Scan for devices (cores) */ err = bcma_bus_scan(bus); @@ -425,10 +402,8 @@ int bcma_bus_register(struct bcma_bus *bus) bcma_core_pci_early_init(&bus->drv_pci[0]); } - dev = bcma_bus_get_host_dev(bus); - if (dev) { - of_platform_default_populate(dev->of_node, NULL, dev); - } + if (bus->dev) + of_platform_default_populate(bus->dev->of_node, NULL, bus->dev); /* Cores providing flash access go before SPROM init */ list_for_each_entry(core, &bus->cores, list) { diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index ef61f3607e99..60b94b944e9f 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -332,6 +332,8 @@ extern int bcma_arch_register_fallback_sprom( struct ssb_sprom *out)); struct bcma_bus { + struct device *dev; + /* The MMIO area. */ void __iomem *mmio; @@ -339,14 +341,7 @@ struct bcma_bus { enum bcma_hosttype hosttype; bool host_is_pcie2; /* Used for BCMA_HOSTTYPE_PCI only */ - union { - /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ - struct pci_dev *host_pci; - /* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */ - struct sdio_func *host_sdio; - /* Pointer to platform device (only for BCMA_HOSTTYPE_SOC) */ - struct platform_device *host_pdev; - }; + struct pci_dev *host_pci; /* PCI bus pointer (BCMA_HOSTTYPE_PCI only) */ struct bcma_chipinfo chipinfo; -- cgit v1.2.3 From 777bc4801a6868fcbff09ffb6e30f023e7c5ed38 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 2 Jan 2019 00:00:02 +0100 Subject: bcma: use dev_* printing functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It provides more meaningful messages. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/bcma_private.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 1f0e66310b23..6eded32d1aac 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -10,13 +10,13 @@ #include #define bcma_err(bus, fmt, ...) \ - pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) + dev_err((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) #define bcma_warn(bus, fmt, ...) \ - pr_warn("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) + dev_warn((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) #define bcma_info(bus, fmt, ...) \ - pr_info("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) + dev_info((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) #define bcma_debug(bus, fmt, ...) \ - pr_debug("bus%d: " fmt, (bus)->num, ##__VA_ARGS__) + dev_dbg((bus)->dev, "bus%d: " fmt, (bus)->num, ##__VA_ARGS__) struct bcma_bus; -- cgit v1.2.3 From 3a33bd840523aaa06f4429fbfd38922bf0dc2e8d Mon Sep 17 00:00:00 2001 From: Lo-Hsiang Lo Date: Mon, 7 Jan 2019 08:46:16 +0000 Subject: brcmfmac: fix system warning message during wowl suspend There is a system warning message, warn_slowpath-fmt, during suspend while using supplicant join AP and enable wowl feature by IW command. It's caused by brcmf_pno_remove_request path can't find the reqid. This fix will not go to remove pno request function if there is no pno scan. Acked-by: Arend van Spriel Signed-off-by: Lo-Hsiang Lo Signed-off-by: Chi-Hsien Lin Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c index ffa243e2e2d0..37b403877228 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c @@ -496,6 +496,11 @@ int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid) brcmf_dbg(TRACE, "reqid=%llu\n", reqid); pi = ifp_to_pno(ifp); + + /* No PNO request */ + if (!pi->n_reqs) + return 0; + err = brcmf_pno_remove_request(pi, reqid); if (err) return err; -- cgit v1.2.3 From 4ad0be160544ffbdafb7cec39bb8e6dd0a97317a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 7 Jan 2019 14:33:27 +0100 Subject: brcmfmac: Use firmware_request_nowarn for the clm_blob The linux-firmware brcmfmac firmware files contain an embedded table with per country allowed channels and strength info. For recent hardware these versions of the firmware are specially build for linux-firmware, the firmware files directly available from Cypress rely on a separate clm_blob file for this info. For some unknown reason Cypress refuses to provide the standard firmware files + clm_blob files it uses elsewhere for inclusion into linux-firmware, instead relying on these special builds with the clm_blob info embedded. This means that the linux-firmware firmware versions often lag behind, but I digress. The brcmfmac driver does support the separate clm_blob file and always tries to load this. Currently we use request_firmware for this. This means that on any standard install, using the standard combo of linux-kernel + linux-firmware, we will get a warning: "Direct firmware load for ... failed with error -2" On top of this, brcmfmac itself prints: "no clm_blob available (err=-2), device may have limited channels available". This commit switches to firmware_request_nowarn, fixing almost any brcmfmac device logging the warning (it leaves the brcmfmac info message in place). Signed-off-by: Hans de Goede Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 1f1e95a15a17..0ce1d8174e6d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -149,7 +149,7 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) return err; } - err = request_firmware(&clm, clm_name, bus->dev); + err = firmware_request_nowarn(&clm, clm_name, bus->dev); if (err) { brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n", err); -- cgit v1.2.3 From ce938231bd3b1d7af3cbd8836f084801090470e1 Mon Sep 17 00:00:00 2001 From: "Daniel F. Dickinson" Date: Sat, 22 Dec 2018 01:09:13 -0500 Subject: ath9k: Avoid OF no-EEPROM quirks without qca,no-eeprom ath9k_of_init() function[0] was initially written on the assumption that if someone had an explicit ath9k OF node that "there must be something wrong, why would someone add an OF node if everything is fine"[1] (Quoting Martin Blumenstingl ) "it turns out it's not that simple. with your requirements I'm now aware of two use-cases where the current code in ath9k_of_init() doesn't work without modifications"[1] The "your requirements" Martin speaks of is the result of the fact that I have a device (PowerCloud Systems CR5000) has some kind of default - not unique mac address - set and requires to set the correct MAC address via mac-address devicetree property, however: "some cards come with a physical EEPROM chip [or OTP] so "qca,no-eeprom" should not be set (your use-case). in this case AH_USE_EEPROM should be set (which is the default when there is no OF node)"[1] The other use case is: the firmware on some PowerMac G5 seems to add a OF node for the ath9k card automatically. depending on the EEPROM on the card AH_NO_EEP_SWAP should be unset (which is the default when there is no OF node). see [3] After this patch to ath9k_of_init() the new behavior will be: if there's no OF node then everything is the same as before if there's an empty OF node then ath9k will use the hardware EEPROM (before ath9k would fail to initialize because no EEPROM data was provided by userspace) if there's an OF node with only a MAC address then ath9k will use the MAC address and the hardware EEPROM (see the case above) with "qca,no-eeprom" EEPROM data from userspace will be requested. the behavior here will not change [1] Martin provides additional background on EEPROM swapping[1]. Thanks to Christian Lamparter for all his help on troubleshooting this issue and the basis for this patch. [0]https://elixir.bootlin.com/linux/v4.20-rc7/source/drivers/net/wireless/ath/ath9k/init.c#L615 [1]https://github.com/openwrt/openwrt/pull/1645#issuecomment-448027058 [2]https://github.com/openwrt/openwrt/pull/1613 [3]https://patchwork.kernel.org/patch/10241731/ Fixes: 138b41253d9c ("ath9k: parse the device configuration from an OF node") Reviewed-by: Martin Blumenstingl Tested-by: Martin Blumenstingl Signed-off-by: Daniel F. Dickinson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index c070a9e51ebf..fae572b38416 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -636,15 +636,15 @@ static int ath9k_of_init(struct ath_softc *sc) ret = ath9k_eeprom_request(sc, eeprom_name); if (ret) return ret; + + ah->ah_flags &= ~AH_USE_EEPROM; + ah->ah_flags |= AH_NO_EEP_SWAP; } mac = of_get_mac_address(np); if (mac) ether_addr_copy(common->macaddr, mac); - ah->ah_flags &= ~AH_USE_EEPROM; - ah->ah_flags |= AH_NO_EEP_SWAP; - return 0; } -- cgit v1.2.3 From fc6a6521556c8250e356ddc6a3f2391aa62dc976 Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Wed, 26 Dec 2018 00:43:28 -0600 Subject: ath6kl: return error code in ath6kl_wmi_set_roam_lrssi_cmd() ath6kl_wmi_cmd_send could fail, so let's return its error code upstream. Signed-off-by: Kangjie Lu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/wmi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 9d7ac1ab2d02..68854c45d0a4 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -776,10 +776,8 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi) cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR; cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS; - ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID, + return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID, NO_SYNC_WMIFLAG); - - return 0; } int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) -- cgit v1.2.3 From 9fe310546559d123103c39dc85eb54dc1316f450 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 6 Nov 2018 12:29:44 +0100 Subject: mt76: add size check for additional rx fragments So far the code only validates the buffer size of the first skb. Extend this check to cover additional fragments as well, in case the size is corrupted during a DMA reset. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index e2ba26378575..710a77fccf63 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -430,6 +430,14 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) if (!data) break; + if (q->buf_size < len + q->buf_offset) { + dev_kfree_skb(q->rx_head); + q->rx_head = NULL; + + skb_free_frag(data); + continue; + } + if (q->rx_head) { mt76_add_fragment(dev, q, data, len, more); continue; -- cgit v1.2.3 From cbbfd73767cd7a43fbebe712cb837d7ff06b99f2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 29 Nov 2018 13:13:54 +0100 Subject: mt76: throttle transmission of buffered multicast packets Avoids drowning out regular transmissions Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 66315410aebe..6974acc75e2b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -121,9 +121,10 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg) ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), IEEE80211_IFACE_ITER_RESUME_ALL, mt76x02_add_buffered_bc, &data); - } while (nframes != skb_queue_len(&data.q)); + } while (nframes != skb_queue_len(&data.q) && + skb_queue_len(&data.q) < 8); - if (!nframes) + if (!skb_queue_len(&data.q)) return; for (i = 0; i < ARRAY_SIZE(data.tail); i++) { -- cgit v1.2.3 From 7267a7965dd7b0f2a0800538c8080f3e683846fc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 13 Nov 2018 20:54:17 +0100 Subject: mt76: request tx status for powersave released EOSP packet Allows mac80211 to keep track of the service period Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 7b711058807d..f08509c1670d 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -330,7 +330,8 @@ mt76_queue_ps_skb(struct mt76_dev *dev, struct ieee80211_sta *sta, info->control.flags |= IEEE80211_TX_CTRL_PS_RESPONSE; if (last) - info->flags |= IEEE80211_TX_STATUS_EOSP; + info->flags |= IEEE80211_TX_STATUS_EOSP | + IEEE80211_TX_CTL_REQ_TX_STATUS; mt76_skb_set_moredata(skb, !last); dev->queue_ops->tx_queue_skb(dev, hwq, skb, wcid, sta); -- cgit v1.2.3 From 4d4b12bc56d33d68ad04382f4c15c42bf4616270 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 1 Dec 2018 10:55:06 +0100 Subject: mt76: dma: remove napi from mt76_dma_rx_fill signature Remove napi from mt76_dma_rx_fill routine signature since it is a leftover of a previous implementation and it is no longer used Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 710a77fccf63..b7fd2e110663 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -318,7 +318,7 @@ free: EXPORT_SYMBOL_GPL(mt76_dma_tx_queue_skb); static int -mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q, bool napi) +mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) { dma_addr_t addr; void *buf; @@ -392,7 +392,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid) mt76_dma_rx_cleanup(dev, q); mt76_dma_sync_idx(dev, q); - mt76_dma_rx_fill(dev, q, false); + mt76_dma_rx_fill(dev, q); } static void @@ -471,7 +471,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) dev->drv->rx_skb(dev, q - dev->q_rx, skb); } - mt76_dma_rx_fill(dev, q, true); + mt76_dma_rx_fill(dev, q); return done; } @@ -512,7 +512,7 @@ mt76_dma_init(struct mt76_dev *dev) for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, 64); - mt76_dma_rx_fill(dev, &dev->q_rx[i], false); + mt76_dma_rx_fill(dev, &dev->q_rx[i]); skb_queue_head_init(&dev->rx_skb[i]); napi_enable(&dev->napi[i]); } -- cgit v1.2.3 From 0ecf94dc3695a494dd4f495fc0913049d0e99891 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 1 Dec 2018 15:01:19 +0100 Subject: mt76: usb: do not build the skb if reported len does not fit in buf_size Precompute data length in order to avoid to allocate the related skb data structure if reported length does not fit in queue buf_size Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index b061263453d4..14ff06c5764e 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -407,17 +407,15 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) if (len < 0) return 0; + data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN); + if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size)) + return 0; + skb = build_skb(data, q->buf_size); if (!skb) return 0; - data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN); skb_reserve(skb, MT_DMA_HDR_LEN); - if (skb->tail + data_len > skb->end) { - dev_kfree_skb(skb); - return 1; - } - __skb_put(skb, data_len); len -= data_len; -- cgit v1.2.3 From 85b7e2acd31bf975c5163e0c6d949fa3742921b1 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sun, 2 Dec 2018 13:06:34 +0100 Subject: mt76: Add missing include of linux/module.h MODULE_FIRMWARE() is used in usb_mcu.c and provided by linux/module.h, but this header file is not directly included. This causes problems in backports with some kernel versions. Add the missing include. Signed-off-by: Hauke Mehrtens Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c index 9d7585029df9..f391d2d21fbc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c @@ -15,6 +15,7 @@ */ #include #include +#include #include "mt76x0.h" #include "mcu.h" -- cgit v1.2.3 From 374eb1b55540c99af4e2417a2d51ff5f56cfdb70 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 6 Dec 2018 12:40:23 +0100 Subject: mt76: fix typo in mt76x02_check_mac_err routine Reconfigure properly MT_MAC_SYS_CTRL register after mac sw-reset in mt76x02_check_mac_err routine Fixes: 73556561ab9f ("mt76x0: use mt76x02_mac_work as stats handler") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index c08bf371e527..490368dc9325 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -774,8 +774,8 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev) mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR); udelay(10); - mt76_clear(dev, MT_MAC_SYS_CTRL, - MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); + mt76_wr(dev, MT_MAC_SYS_CTRL, + MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); } void mt76x02_mac_work(struct work_struct *work) -- cgit v1.2.3 From 4989338ed3053372fcf5173a2a4800ac99de07d9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 6 Dec 2018 17:07:39 +0100 Subject: mt76: mac: run mt76x02_mac_work routine atomically Grab mt76_dev mutex in mt76x02_mac_work handler since it runs concurrently with mt76x{0,2}_set_channel routines Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 490368dc9325..64841f40cdcf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -784,6 +784,8 @@ void mt76x02_mac_work(struct work_struct *work) mac_work.work); int i, idx; + mutex_lock(&dev->mt76.mutex); + mt76x02_update_channel(&dev->mt76); for (i = 0, idx = 0; i < 16; i++) { u32 val = mt76_rr(dev, MT_TX_AGG_CNT(i)); @@ -796,6 +798,8 @@ void mt76x02_mac_work(struct work_struct *work) if (!dev->beacon_mask) mt76x02_check_mac_err(dev); + mutex_unlock(&dev->mt76.mutex); + mt76_tx_status_check(&dev->mt76, NULL, false); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, -- cgit v1.2.3 From e207afa0232d40606e025059c18c70b89a7d5912 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 6 Dec 2018 19:11:55 +0100 Subject: mt76: usb: avoid queue/status spinlocks while passing tx status to mac80211 As already done for pcie code in commit 79d1c94c9c78 ("mt76: avoid queue/status spinlocks while passing tx status to mac80211") make sure that no tx related spinlocks are taken during the ieee80211_tx_status call Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 14ff06c5764e..6a2507524c6c 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -583,6 +583,7 @@ static void mt76u_stop_rx(struct mt76_dev *dev) static void mt76u_tx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; + struct mt76_queue_entry entry; struct mt76u_buf *buf; struct mt76_queue *q; bool wake; @@ -597,17 +598,18 @@ static void mt76u_tx_tasklet(unsigned long data) if (!buf->done || !q->queued) break; - dev->drv->tx_complete_skb(dev, q, - &q->entry[q->head], - false); - if (q->entry[q->head].schedule) { q->entry[q->head].schedule = false; q->swq_queued--; } + entry = q->entry[q->head]; q->head = (q->head + 1) % q->ndesc; q->queued--; + + spin_unlock_bh(&q->lock); + dev->drv->tx_complete_skb(dev, q, &entry, false); + spin_lock_bh(&q->lock); } mt76_txq_schedule(dev, q); wake = i < IEEE80211_NUM_ACS && q->queued < q->ndesc - 8; -- cgit v1.2.3 From b9f81643b6aea47602adc3a61edf5ad207d640ec Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 10 Dec 2018 11:22:00 +0100 Subject: mt76x0: pci: fix ACS support Fix Automatic Channel Selection (ACS) support in mt76x0e driver configuring properly MT_CH_TIME_CFG register Fixes: 6250318694ca ("mt76x0: pci: add get_survey support") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index d895b6f3dc44..1906cc62690f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -141,6 +141,14 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev) mt76_clear(dev, 0x110, BIT(9)); mt76_set(dev, MT_MAX_LEN_CFG, BIT(13)); + mt76_wr(dev, MT_CH_TIME_CFG, + MT_CH_TIME_CFG_TIMER_EN | + MT_CH_TIME_CFG_TX_AS_BUSY | + MT_CH_TIME_CFG_RX_AS_BUSY | + MT_CH_TIME_CFG_NAV_AS_BUSY | + MT_CH_TIME_CFG_EIFS_AS_BUSY | + FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1)); + err = mt76x0_register_device(dev); if (err < 0) return err; -- cgit v1.2.3 From 20ce270e5a7da08fdf946ed674ba10c71d18fdfb Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Dec 2018 11:53:55 +0100 Subject: mt76x02: do not set protection on set_rts_threshold callback Use set_rts_threshold calback to enable/disable threshold only for legacy traffic. Protection for HT and VHT traffic is defined by HT operation element and it's provided by remote AP or by hostapd. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 16 +--------------- drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +- 3 files changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 64841f40cdcf..d3f1d57fb758 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -715,7 +715,7 @@ void mt76x02_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, } EXPORT_SYMBOL_GPL(mt76x02_tx_complete_skb); -void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val) +void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val) { u32 data = 0; @@ -729,20 +729,6 @@ void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val) MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); mt76_rmw(dev, MT_OFDM_PROT_CFG, MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); - mt76_rmw(dev, MT_MM20_PROT_CFG, - MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); - mt76_rmw(dev, MT_MM40_PROT_CFG, - MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); - mt76_rmw(dev, MT_GF20_PROT_CFG, - MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); - mt76_rmw(dev, MT_GF40_PROT_CFG, - MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); - mt76_rmw(dev, MT_TX_PROT_CFG6, - MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); - mt76_rmw(dev, MT_TX_PROT_CFG7, - MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); - mt76_rmw(dev, MT_TX_PROT_CFG8, - MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); } void mt76x02_update_channel(struct mt76_dev *mdev) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 4e597004c445..d1a8ed171537 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -194,7 +194,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, struct mt76x02_tx_status *stat, u8 *update); int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, void *rxi); -void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, u32 val); +void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val); void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr); void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 38bd466cff16..364e7b2ebf99 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -463,7 +463,7 @@ int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val) return -EINVAL; mutex_lock(&dev->mt76.mutex); - mt76x02_mac_set_tx_protection(dev, val); + mt76x02_mac_set_rts_thresh(dev, val); mutex_unlock(&dev->mt76.mutex); return 0; -- cgit v1.2.3 From 493d2dfab34bb88563a6a64801c7d604537ca958 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Dec 2018 11:53:56 +0100 Subject: mt76x02: fixup MT_PROT_RATE_* defines On new mt76 chips, phy mode is configured by last 3 bits of rate value. Hence OFDM bit is marked by 0x2000 instead of 0x4000. Acked-by: Lorenzo Bianconi Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index f7de77d09d28..d1ac847adce5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -440,9 +440,9 @@ #define MT_PROT_TXOP_ALLOW_GF40 BIT(25) #define MT_PROT_RTS_THR_EN BIT(26) #define MT_PROT_RATE_CCK_11 0x0003 -#define MT_PROT_RATE_OFDM_6 0x4000 -#define MT_PROT_RATE_OFDM_24 0x4004 -#define MT_PROT_RATE_DUP_OFDM_24 0x4084 +#define MT_PROT_RATE_OFDM_6 0x2000 +#define MT_PROT_RATE_OFDM_24 0x2004 +#define MT_PROT_RATE_DUP_OFDM_24 0x2084 #define MT_PROT_TXOP_ALLOW_ALL GENMASK(25, 20) #define MT_PROT_TXOP_ALLOW_BW20 (MT_PROT_TXOP_ALLOW_ALL & \ ~MT_PROT_TXOP_ALLOW_MM40 & \ -- cgit v1.2.3 From 26a7b5473191d362b09a190fafd0dc2059cbf527 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Dec 2018 11:53:57 +0100 Subject: mt76x02: set protection according to ht operation element Configure protection based on information that are provided to us either by remote AP or by hostapd via HT operation IE. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 83 +++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 + drivers/net/wireless/mediatek/mt76/mt76x02_regs.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 4 ++ 4 files changed, 90 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index d3f1d57fb758..ddc1c3146feb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -731,6 +731,89 @@ void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val) MT_PROT_CFG_CTRL | MT_PROT_CFG_RTS_THRESH, data); } +void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot, + int ht_mode) +{ + int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION; + bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); + u32 prot[6]; + u32 vht_prot[3]; + int i; + u16 rts_thr; + + for (i = 0; i < ARRAY_SIZE(prot); i++) { + prot[i] = mt76_rr(dev, MT_CCK_PROT_CFG + i * 4); + prot[i] &= ~MT_PROT_CFG_CTRL; + if (i >= 2) + prot[i] &= ~MT_PROT_CFG_RATE; + } + + for (i = 0; i < ARRAY_SIZE(vht_prot); i++) { + vht_prot[i] = mt76_rr(dev, MT_TX_PROT_CFG6 + i * 4); + vht_prot[i] &= ~(MT_PROT_CFG_CTRL | MT_PROT_CFG_RATE); + } + + rts_thr = mt76_get_field(dev, MT_TX_RTS_CFG, MT_TX_RTS_CFG_THRESH); + + if (rts_thr != 0xffff) + prot[0] |= MT_PROT_CTRL_RTS_CTS; + + if (legacy_prot) { + prot[1] |= MT_PROT_CTRL_CTS2SELF; + + prot[2] |= MT_PROT_RATE_CCK_11; + prot[3] |= MT_PROT_RATE_CCK_11; + prot[4] |= MT_PROT_RATE_CCK_11; + prot[5] |= MT_PROT_RATE_CCK_11; + + vht_prot[0] |= MT_PROT_RATE_CCK_11; + vht_prot[1] |= MT_PROT_RATE_CCK_11; + vht_prot[2] |= MT_PROT_RATE_CCK_11; + } else { + if (rts_thr != 0xffff) + prot[1] |= MT_PROT_CTRL_RTS_CTS; + + prot[2] |= MT_PROT_RATE_OFDM_24; + prot[3] |= MT_PROT_RATE_DUP_OFDM_24; + prot[4] |= MT_PROT_RATE_OFDM_24; + prot[5] |= MT_PROT_RATE_DUP_OFDM_24; + + vht_prot[0] |= MT_PROT_RATE_OFDM_24; + vht_prot[1] |= MT_PROT_RATE_DUP_OFDM_24; + vht_prot[2] |= MT_PROT_RATE_SGI_OFDM_24; + } + + switch (mode) { + case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER: + case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: + prot[2] |= MT_PROT_CTRL_RTS_CTS; + prot[3] |= MT_PROT_CTRL_RTS_CTS; + prot[4] |= MT_PROT_CTRL_RTS_CTS; + prot[5] |= MT_PROT_CTRL_RTS_CTS; + vht_prot[0] |= MT_PROT_CTRL_RTS_CTS; + vht_prot[1] |= MT_PROT_CTRL_RTS_CTS; + vht_prot[2] |= MT_PROT_CTRL_RTS_CTS; + break; + case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: + prot[3] |= MT_PROT_CTRL_RTS_CTS; + prot[5] |= MT_PROT_CTRL_RTS_CTS; + vht_prot[1] |= MT_PROT_CTRL_RTS_CTS; + vht_prot[2] |= MT_PROT_CTRL_RTS_CTS; + break; + } + + if (non_gf) { + prot[4] |= MT_PROT_CTRL_RTS_CTS; + prot[5] |= MT_PROT_CTRL_RTS_CTS; + } + + for (i = 0; i < ARRAY_SIZE(prot); i++) + mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]); + + for (i = 0; i < ARRAY_SIZE(vht_prot); i++) + mt76_wr(dev, MT_TX_PROT_CFG6 + i * 4, vht_prot[i]); +} + void mt76x02_update_channel(struct mt76_dev *mdev) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index d1a8ed171537..91c76a050f7e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -194,6 +194,8 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, struct mt76x02_tx_status *stat, u8 *update); int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, void *rxi); +void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot, + int ht_mode); void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val); void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr); void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index d1ac847adce5..20ad07638699 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -443,6 +443,7 @@ #define MT_PROT_RATE_OFDM_6 0x2000 #define MT_PROT_RATE_OFDM_24 0x2004 #define MT_PROT_RATE_DUP_OFDM_24 0x2084 +#define MT_PROT_RATE_SGI_OFDM_24 0x2104 #define MT_PROT_TXOP_ALLOW_ALL GENMASK(25, 20) #define MT_PROT_TXOP_ALLOW_BW20 (MT_PROT_TXOP_ALLOW_ALL & \ ~MT_PROT_TXOP_ALLOW_MM40 & \ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 364e7b2ebf99..aac64d0969b8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -661,6 +661,10 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, tasklet_enable(&dev->pre_tbtt_tasklet); } + if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) + mt76x02_mac_set_tx_protection(dev, info->use_cts_prot, + info->ht_operation_mode); + if (changed & BSS_CHANGED_BEACON_INT) { mt76_rmw_field(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_INTVAL, -- cgit v1.2.3 From 9bc29420d745e775d36d224e4a6999ee77a600e1 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 10 Dec 2018 11:53:58 +0100 Subject: mt76x0: configure MT_VHT_HT_FBK_CFG1 Configure MT_VHT_HT_FBK_CFG1 values similar like vendor driver. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h index a1657922758e..0290ba5869a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/initvals.h @@ -88,6 +88,7 @@ static const struct mt76_reg_pair mt76x0_mac_reg_table[] = { { MT_TX_PROT_CFG6, 0xe3f42004 }, { MT_TX_PROT_CFG7, 0xe3f42084 }, { MT_TX_PROT_CFG8, 0xe3f42104 }, + { MT_VHT_HT_FBK_CFG1, 0xedcba980 }, }; static const struct mt76_reg_pair mt76x0_bbp_init_tab[] = { -- cgit v1.2.3 From bf349ce16ef45bf5a0290586124be18a09826860 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 10 Dec 2018 12:54:05 +0100 Subject: mt76x2: add static qualifier to mt76x2_init_hardware Add static qualifier to mt76x2_init_hardware routine since it is used just in pci_init.c Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h | 1 - drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index b259e4b50f1e..28ec19acf9db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -53,7 +53,6 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev); int mt76x2_register_device(struct mt76x02_dev *dev); void mt76x2_phy_power_on(struct mt76x02_dev *dev); -int mt76x2_init_hardware(struct mt76x02_dev *dev); void mt76x2_stop_hardware(struct mt76x02_dev *dev); int mt76x2_eeprom_init(struct mt76x02_dev *dev); int mt76x2_apply_calibration_data(struct mt76x02_dev *dev, int channel); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 7f4ea2d00f42..2f05eacb8946 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -260,7 +260,7 @@ mt76x2_power_on(struct mt76x02_dev *dev) mt76x2_power_on_rf(dev, 1); } -int mt76x2_init_hardware(struct mt76x02_dev *dev) +static int mt76x2_init_hardware(struct mt76x02_dev *dev) { int ret; -- cgit v1.2.3 From 35c572818ca2a1d9bd3a76eab6366b9a299f0a0b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 12 Dec 2018 22:51:53 +0100 Subject: mt76: dfs: run mt76x02_dfs_set_domain atomically Grab mt76_dev mutex in mt76x02_dfs_set_domain since it runs concurrently with mt76x{0,2}_set_channel routines Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 054609c634a2..5bd523b091b6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -881,12 +881,14 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, { struct mt76x02_dfs_pattern_detector *dfs_pd = &dev->dfs_pd; + mutex_lock(&dev->mt76.mutex); if (dfs_pd->region != region) { tasklet_disable(&dfs_pd->dfs_tasklet); dfs_pd->region = region; mt76x02_dfs_init_params(dev); tasklet_enable(&dfs_pd->dfs_tasklet); } + mutex_unlock(&dev->mt76.mutex); } void mt76x02_regd_notifier(struct wiphy *wiphy, -- cgit v1.2.3 From 3fd612df8ac79d8ac902985cb570f1723a82e979 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 12 Dec 2018 22:51:54 +0100 Subject: mt76x2: init: set default value for MT_TX_LINK_CFG Update default value for MT_TX_LINK_CFG according to vendor driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c index 54a9b5fac787..f8534362e2c8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/init.c @@ -143,6 +143,7 @@ void mt76_write_mac_initvals(struct mt76x02_dev *dev) { MT_VHT_HT_FBK_CFG1, 0xedcba980 }, { MT_PROT_AUTO_TX_CFG, 0x00830083 }, { MT_HT_CTRL_CFG, 0x000001ff }, + { MT_TX_LINK_CFG, 0x00001020 }, }; struct mt76_reg_pair prot_vals[] = { { MT_CCK_PROT_CFG, DEFAULT_PROT_CFG_CCK }, -- cgit v1.2.3 From f82ce8d9bd49ed1c3487662c734badfbf560cfe0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 12 Dec 2018 22:51:55 +0100 Subject: mt76: add energy detect CCA support to mt76x{0,2}e drivers Ported from the reference driver. Should fix compliance with ETSI regulatories on preventing transmission while energy detect values are above the threshold. The code has been tested using an ath9k device running tx99 as noise generator Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 1 + drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 2 + drivers/net/wireless/mediatek/mt76/mt76x02.h | 6 ++ drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c | 4 + drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 85 ++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 + drivers/net/wireless/mediatek/mt76/mt76x02_regs.h | 8 ++ .../net/wireless/mediatek/mt76/mt76x2/pci_init.c | 1 + .../net/wireless/mediatek/mt76/mt76x2/pci_phy.c | 2 + 9 files changed, 111 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 1906cc62690f..720b05e325a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -147,6 +147,7 @@ static int mt76x0e_register_device(struct mt76x02_dev *dev) MT_CH_TIME_CFG_RX_AS_BUSY | MT_CH_TIME_CFG_NAV_AS_BUSY | MT_CH_TIME_CFG_EIFS_AS_BUSY | + MT_CH_CCA_RC_EN | FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1)); err = mt76x0_register_device(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 1eb1a802ed20..b2b38b9fcac7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -1013,6 +1013,8 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev, mt76x0_phy_calibrate(dev, false); mt76x0_phy_set_txpower(dev); + mt76x02_edcca_init(dev); + ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6782665049dd..f383fdd914c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -101,6 +101,12 @@ struct mt76x02_dev { u8 slottime; struct mt76x02_dfs_pattern_detector dfs_pd; + + /* edcca monitor */ + bool ed_tx_blocked; + bool ed_monitor; + u8 ed_trigger; + u8 ed_silent; }; extern struct ieee80211_rate mt76x02_rates[12]; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 5bd523b091b6..19fdcab746a0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -884,6 +884,10 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, mutex_lock(&dev->mt76.mutex); if (dfs_pd->region != region) { tasklet_disable(&dfs_pd->dfs_tasklet); + + dev->ed_monitor = region == NL80211_DFS_ETSI; + mt76x02_edcca_init(dev); + dfs_pd->region = region; mt76x02_dfs_init_params(dev); tasklet_enable(&dfs_pd->dfs_tasklet); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index ddc1c3146feb..2e06e1f41810 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -847,6 +847,88 @@ static void mt76x02_check_mac_err(struct mt76x02_dev *dev) MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); } +static void +mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable) +{ + if (enable) { + u32 data; + + mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); + mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_EN); + /* enable pa-lna */ + data = mt76_rr(dev, MT_TX_PIN_CFG); + data |= MT_TX_PIN_CFG_TXANT | + MT_TX_PIN_CFG_RXANT | + MT_TX_PIN_RFTR_EN | + MT_TX_PIN_TRSW_EN; + mt76_wr(dev, MT_TX_PIN_CFG, data); + } else { + mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); + mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_EN); + /* disable pa-lna */ + mt76_clear(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT); + mt76_clear(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_RXANT); + } + dev->ed_tx_blocked = !enable; +} + +void mt76x02_edcca_init(struct mt76x02_dev *dev) +{ + dev->ed_trigger = 0; + dev->ed_silent = 0; + + if (dev->ed_monitor) { + struct ieee80211_channel *chan = dev->mt76.chandef.chan; + u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20; + + mt76_clear(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN); + mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); + mt76_rmw(dev, MT_BBP(AGC, 2), GENMASK(15, 0), + ed_th << 8 | ed_th); + if (!is_mt76x2(dev)) + mt76_set(dev, MT_TXOP_HLDR_ET, + MT_TXOP_HLDR_TX40M_BLK_EN); + } else { + mt76_set(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN); + mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); + if (is_mt76x2(dev)) { + mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); + } else { + mt76_wr(dev, MT_BBP(AGC, 2), 0x003a6464); + mt76_clear(dev, MT_TXOP_HLDR_ET, + MT_TXOP_HLDR_TX40M_BLK_EN); + } + } + mt76x02_edcca_tx_enable(dev, true); +} +EXPORT_SYMBOL_GPL(mt76x02_edcca_init); + +#define MT_EDCCA_TH 90 +#define MT_EDCCA_BLOCK_TH 2 +static void mt76x02_edcca_check(struct mt76x02_dev *dev) +{ + u32 val, busy; + + val = mt76_rr(dev, MT_ED_CCA_TIMER); + busy = (val * 100) / jiffies_to_usecs(MT_CALIBRATE_INTERVAL); + busy = min_t(u32, busy, 100); + + if (busy > MT_EDCCA_TH) { + dev->ed_trigger++; + dev->ed_silent = 0; + } else { + dev->ed_silent++; + dev->ed_trigger = 0; + } + + if (dev->ed_trigger > MT_EDCCA_BLOCK_TH && + !dev->ed_tx_blocked) + mt76x02_edcca_tx_enable(dev, false); + else if (dev->ed_silent > MT_EDCCA_BLOCK_TH && + dev->ed_tx_blocked) + mt76x02_edcca_tx_enable(dev, true); +} + void mt76x02_mac_work(struct work_struct *work) { struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, @@ -867,6 +949,9 @@ void mt76x02_mac_work(struct work_struct *work) if (!dev->beacon_mask) mt76x02_check_mac_err(dev); + if (dev->ed_monitor) + mt76x02_edcca_check(dev); + mutex_unlock(&dev->mt76.mutex); mt76_tx_status_check(&dev->mt76, NULL, false); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 91c76a050f7e..735fe96440ba 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -212,4 +212,6 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, struct sk_buff *skb); void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, bool val); + +void mt76x02_edcca_init(struct mt76x02_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index 20ad07638699..b8d1ffbac6b5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -318,6 +318,7 @@ #define MT_CH_TIME_CFG_NAV_AS_BUSY BIT(3) #define MT_CH_TIME_CFG_EIFS_AS_BUSY BIT(4) #define MT_CH_TIME_CFG_MDRDY_CNT_EN BIT(5) +#define MT_CH_CCA_RC_EN BIT(6) #define MT_CH_TIME_CFG_CH_TIMER_CLR GENMASK(9, 8) #define MT_CH_TIME_CFG_MDRDY_CLR GENMASK(11, 10) @@ -378,6 +379,9 @@ #define MT_TX_PWR_CFG_4 0x1324 #define MT_TX_PIN_CFG 0x1328 #define MT_TX_PIN_CFG_TXANT GENMASK(3, 0) +#define MT_TX_PIN_CFG_RXANT GENMASK(11, 8) +#define MT_TX_PIN_RFTR_EN BIT(16) +#define MT_TX_PIN_TRSW_EN BIT(18) #define MT_TX_BAND_CFG 0x132c #define MT_TX_BAND_CFG_UPPER_40M BIT(0) @@ -398,6 +402,7 @@ #define MT_TXOP_CTRL_CFG 0x1340 #define MT_TXOP_TRUN_EN GENMASK(5, 0) #define MT_TXOP_EXT_CCA_DLY GENMASK(15, 8) +#define MT_TXOP_ED_CCA_EN BIT(20) #define MT_TX_RTS_CFG 0x1344 #define MT_TX_RTS_CFG_RETRY_LIMIT GENMASK(7, 0) @@ -409,6 +414,7 @@ #define MT_TX_RETRY_CFG 0x134c #define MT_TX_LINK_CFG 0x1350 +#define MT_TX_CFACK_EN BIT(12) #define MT_VHT_HT_FBK_CFG0 0x1354 #define MT_VHT_HT_FBK_CFG1 0x1358 #define MT_LG_FBK_CFG0 0x135c @@ -512,6 +518,7 @@ #define MT_RX_FILTR_CFG_CTRL_RSV BIT(16) #define MT_AUTO_RSP_CFG 0x1404 +#define MT_AUTO_RSP_EN BIT(0) #define MT_AUTO_RSP_PREAMB_SHORT BIT(4) #define MT_LEGACY_BASIC_RATE 0x1408 #define MT_HT_BASIC_RATE 0x140c @@ -533,6 +540,7 @@ #define MT_PN_PAD_MODE 0x150c #define MT_TXOP_HLDR_ET 0x1608 +#define MT_TXOP_HLDR_TX40M_BLK_EN BIT(1) #define MT_PROT_AUTO_TX_CFG 0x1648 #define MT_PROT_AUTO_TX_CFG_PROT_PADJ GENMASK(11, 8) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 2f05eacb8946..9f313824eead 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -151,6 +151,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) MT_CH_TIME_CFG_RX_AS_BUSY | MT_CH_TIME_CFG_NAV_AS_BUSY | MT_CH_TIME_CFG_EIFS_AS_BUSY | + MT_CH_CCA_RC_EN | FIELD_PREP(MT_CH_TIME_CFG_CH_TIMER_CLR, 1)); mt76x02_set_tx_ackto(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index da7cd40f56ff..65ed62229a5b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -254,6 +254,8 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, 0x38); } + mt76x02_edcca_init(dev); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); -- cgit v1.2.3 From c09f4d0a1f81720342d4d0e1d4a2b601903f132a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 28 Dec 2018 11:00:47 +0100 Subject: mt76: mac: minor optimizations in mt76x02_mac_tx_rate_val Do not set bw variable to zero for legacy rates since it is already initialized to zero. Moreover set nss to 1 just for legacy rates since nss will be properly set for VHT/HT rates Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 2e06e1f41810..cc584ea4a8d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -130,10 +130,8 @@ static __le16 mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, const struct ieee80211_tx_rate *rate, u8 *nss_val) { + u8 phy, rate_idx, nss, bw = 0; u16 rateval; - u8 phy, rate_idx; - u8 nss = 1; - u8 bw = 0; if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { rate_idx = rate->idx; @@ -164,7 +162,7 @@ mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev, phy = val >> 8; rate_idx = val & 0xff; - bw = 0; + nss = 1; } rateval = FIELD_PREP(MT_RXWI_RATE_INDEX, rate_idx); -- cgit v1.2.3 From 87e86f90196fa074f8f6ac0e77d1287d9239878b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 3 Dec 2018 15:34:24 +0100 Subject: mt76: dma: do not build skb if reported len does not fit in buf_size Precompute data length in order to avoid to allocate the related skb data structure if reported length does not fit in queue buf_size Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index b7fd2e110663..1db163c40dcf 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -417,10 +417,9 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, static int mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) { + int len, data_len, done = 0; struct sk_buff *skb; unsigned char *data; - int len; - int done = 0; bool more; while (done < budget) { @@ -430,7 +429,12 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) if (!data) break; - if (q->buf_size < len + q->buf_offset) { + if (q->rx_head) + data_len = q->buf_size; + else + data_len = SKB_WITH_OVERHEAD(q->buf_size); + + if (data_len < len + q->buf_offset) { dev_kfree_skb(q->rx_head); q->rx_head = NULL; @@ -448,12 +452,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget) skb_free_frag(data); continue; } - skb_reserve(skb, q->buf_offset); - if (skb->tail + len > skb->end) { - dev_kfree_skb(skb); - continue; - } if (q == &dev->q_rx[MT_RXQ_MCU]) { u32 *rxfce = (u32 *) skb->cb; -- cgit v1.2.3 From c1e0d2be0acff5e99a59ddcc5af415e48abc6c5e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 28 Dec 2018 15:44:09 +0100 Subject: mt76: mmio: introduce mt76x02_check_tx_hang watchdog Port mt76x02_check_tx_hang watchdog from vendor driver in order to perform a device reset when tx mac/dma logic hangs. Tx mac/dma stuck has been observed when the device is heavy loaded or in a noisy environment. Moreover introduce wdt delayed work in order to run tx_hang watchdog. For the moment run mt76x02_check_tx_hang watchdog just on mt76x2 devices since the issue has not been observed on mt76x0 driver yet Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02.h | 8 ++ .../net/wireless/mediatek/mt76/mt76x02_debugfs.c | 2 + drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 1 - drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 124 +++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 + .../net/wireless/mediatek/mt76/mt76x2/pci_init.c | 1 + .../net/wireless/mediatek/mt76/mt76x2/pci_main.c | 2 + 8 files changed, 140 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 5cd508a68609..8ef430d8afc4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -421,6 +421,7 @@ struct mt76_dev { struct mt76_queue q_tx[__MT_TXQ_MAX]; struct mt76_queue q_rx[__MT_RXQ_MAX]; const struct mt76_queue_ops *queue_ops; + int tx_dma_idx[4]; wait_queue_head_t tx_wait; struct sk_buff_head status_list; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index f383fdd914c5..f594e8c82500 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -28,6 +28,9 @@ #define MT_CALIBRATE_INTERVAL HZ +#define MT_WATCHDOG_TIME (HZ / 10) +#define MT_TX_HANG_TH 10 + #define MT_MAX_CHAINS 2 struct mt76x02_rx_freq_cal { s8 high_gain[MT_MAX_CHAINS]; @@ -79,6 +82,7 @@ struct mt76x02_dev { struct tasklet_struct pre_tbtt_tasklet; struct delayed_work cal_work; struct delayed_work mac_work; + struct delayed_work wdt_work; u32 aggr_stats[32]; @@ -89,6 +93,9 @@ struct mt76x02_dev { u8 tbtt_count; u16 beacon_int; + u32 tx_hang_reset; + u8 tx_hang_check; + struct mt76x02_calibration cal; s8 target_power; @@ -142,6 +149,7 @@ s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev, const struct ieee80211_tx_rate *rate); s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr, s8 max_txpwr_adj); +void mt76x02_wdt_work(struct work_struct *work); void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr); void mt76x02_set_tx_ackto(struct mt76x02_dev *dev); void mt76x02_set_coverage_class(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c index a9d52ba1e270..7580c5c986ff 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_debugfs.c @@ -133,5 +133,7 @@ void mt76x02_init_debugfs(struct mt76x02_dev *dev) read_txpower); debugfs_create_devm_seqfile(dev->mt76.dev, "agc", dir, read_agc); + + debugfs_create_u32("tx_hang_reset", 0400, dir, &dev->tx_hang_reset); } EXPORT_SYMBOL_GPL(mt76x02_init_debugfs); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index cc584ea4a8d7..6adea0278284 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -943,7 +943,6 @@ void mt76x02_mac_work(struct work_struct *work) dev->aggr_stats[idx++] += val >> 16; } - /* XXX: check beacon stuck for ap mode */ if (!dev->beacon_mask) mt76x02_check_mac_err(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 6974acc75e2b..6236c6121c01 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -385,3 +385,127 @@ void mt76x02_mac_start(struct mt76x02_dev *dev) MT_INT_TX_STAT); } EXPORT_SYMBOL_GPL(mt76x02_mac_start); + +static bool mt76x02_tx_hang(struct mt76x02_dev *dev) +{ + u32 dma_idx, prev_dma_idx; + struct mt76_queue *q; + int i; + + for (i = 0; i < 4; i++) { + q = &dev->mt76.q_tx[i]; + + if (!q->queued) + continue; + + prev_dma_idx = dev->mt76.tx_dma_idx[i]; + dma_idx = ioread32(&q->regs->dma_idx); + dev->mt76.tx_dma_idx[i] = dma_idx; + + if (prev_dma_idx == dma_idx) + break; + } + + return i < 4; +} + +static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) +{ + u32 mask = dev->mt76.mmio.irqmask; + int i; + + ieee80211_stop_queues(dev->mt76.hw); + set_bit(MT76_RESET, &dev->mt76.state); + + tasklet_disable(&dev->pre_tbtt_tasklet); + tasklet_disable(&dev->tx_tasklet); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) + napi_disable(&dev->mt76.napi[i]); + + mutex_lock(&dev->mt76.mutex); + + if (dev->beacon_mask) + mt76_clear(dev, MT_BEACON_TIME_CFG, + MT_BEACON_TIME_CFG_BEACON_TX | + MT_BEACON_TIME_CFG_TBTT_EN); + + mt76x02_irq_disable(dev, mask); + + /* perform device reset */ + mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); + mt76_wr(dev, MT_MAC_SYS_CTRL, 0); + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN); + usleep_range(5000, 10000); + mt76_wr(dev, MT_INT_SOURCE_CSR, 0xffffffff); + + /* let fw reset DMA */ + mt76_set(dev, 0x734, 0x3); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) + mt76_queue_tx_cleanup(dev, i, true); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_queue_rx_reset(dev, i); + + mt76_wr(dev, MT_MAC_SYS_CTRL, + MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); + mt76_set(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN); + if (dev->ed_monitor) + mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); + + if (dev->beacon_mask) + mt76_set(dev, MT_BEACON_TIME_CFG, + MT_BEACON_TIME_CFG_BEACON_TX | + MT_BEACON_TIME_CFG_TBTT_EN); + + mt76x02_irq_enable(dev, mask); + + mutex_unlock(&dev->mt76.mutex); + + clear_bit(MT76_RESET, &dev->mt76.state); + + tasklet_enable(&dev->tx_tasklet); + tasklet_schedule(&dev->tx_tasklet); + + tasklet_enable(&dev->pre_tbtt_tasklet); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) { + napi_enable(&dev->mt76.napi[i]); + napi_schedule(&dev->mt76.napi[i]); + } + + ieee80211_wake_queues(dev->mt76.hw); + + mt76_txq_schedule_all(&dev->mt76); +} + +static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) +{ + if (mt76x02_tx_hang(dev)) { + if (++dev->tx_hang_check < MT_TX_HANG_TH) + return; + + mt76x02_watchdog_reset(dev); + + dev->tx_hang_reset++; + dev->tx_hang_check = 0; + memset(dev->mt76.tx_dma_idx, 0xff, + sizeof(dev->mt76.tx_dma_idx)); + } else { + dev->tx_hang_check = 0; + } +} + +void mt76x02_wdt_work(struct work_struct *work) +{ + struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, + wdt_work.work); + + mt76x02_check_tx_hang(dev); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, + MT_WATCHDOG_TIME); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index aac64d0969b8..3c878f18e05d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -93,6 +93,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev) MT_DMA_HDR_LEN; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); } else { + INIT_DELAYED_WORK(&dev->wdt_work, mt76x02_wdt_work); + mt76x02_dfs_init_detector(dev); wiphy->reg_notifier = mt76x02_regd_notifier; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 9f313824eead..34418e575542 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -301,6 +301,7 @@ void mt76x2_stop_hardware(struct mt76x02_dev *dev) { cancel_delayed_work_sync(&dev->cal_work); cancel_delayed_work_sync(&dev->mac_work); + cancel_delayed_work_sync(&dev->wdt_work); mt76x02_mcu_set_radio_state(dev, false); mt76x2_mac_stop(dev, false); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index b54a32397486..6a87b88eb036 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -34,6 +34,8 @@ mt76x2_start(struct ieee80211_hw *hw) ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, MT_CALIBRATE_INTERVAL); + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, + MT_WATCHDOG_TIME); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); -- cgit v1.2.3 From 32fb47fd9c5553ab77ad0380e1ac421d7b3ac564 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 30 Dec 2018 13:26:40 +0000 Subject: mt76: make const array 'data' static, shrinks object size Don't populate the const array 'data' on the stack but instead make it static. Makes the object code smaller by 78 bytes: Before: text data bss dec hex filename 5438 1080 0 6518 1976 mediatek/mt76/mt76x2/usb_mcu.o After: text data bss dec hex filename 5296 1144 0 6440 1928 mediatek/mt76/mt76x2/usb_mcu.o (gcc version 8.2.0 x86_64) Signed-off-by: Colin Ian King Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c index 45a95ee3a415..152d41fe9ff5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c @@ -39,7 +39,7 @@ static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev) static void mt76x2u_mcu_enable_patch(struct mt76x02_dev *dev) { struct mt76_usb *usb = &dev->mt76.usb; - const u8 data[] = { + static const u8 data[] = { 0x6f, 0xfc, 0x08, 0x01, 0x20, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, -- cgit v1.2.3 From e76deac6f00bd855215454228fbb70f2f5f0eea4 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 31 Dec 2018 15:42:54 +0100 Subject: mt76: dma: avoid indirect call in mt76_dma_tx_queue_skb Call mt76_dma_add_buf routine directly in mt76_dma_tx_queue_skb and avoid indirect call if not necessary Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 1db163c40dcf..e769c8a555dd 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -300,7 +300,7 @@ int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, if (q->queued + (n + 1) / 2 >= q->ndesc - 1) goto unmap; - return dev->queue_ops->add_buf(dev, q, buf, n, tx_info, skb, t); + return mt76_dma_add_buf(dev, q, buf, n, tx_info, skb, t); unmap: ret = -ENOMEM; -- cgit v1.2.3 From 3121742915b552f1994775f9d34512ccc0a82e66 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 10 Jan 2019 12:14:04 +0100 Subject: mt76: use proper name for __MT76x02_H macro Use proper name for __MT76x02_H macro in mt76x02.h Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index f594e8c82500..d8bd0509a790 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -15,8 +15,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef __MT76X02_UTIL_H -#define __MT76X02_UTIL_H +#ifndef __MT76x02_H +#define __MT76x02_H #include @@ -238,4 +238,4 @@ mt76x02_rx_get_sta_wcid(struct mt76x02_sta *sta, bool unicast) return &sta->vif->group_wcid; } -#endif +#endif /* __MT76x02_H */ -- cgit v1.2.3 From 5c9decdfbb409d3c410c3e2308cb6110557eb0a7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 10 Jan 2019 14:27:06 +0100 Subject: mt76: add led support to mt76x0e driver Move mt76x02 led support in mt76x02-lib module in order to add tpt led trigger to mt76x0e driver Tested-by: LGA1150 Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_regs.h | 23 +++++++++ drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 59 ++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h | 23 --------- .../net/wireless/mediatek/mt76/mt76x2/pci_init.c | 54 -------------------- 4 files changed, 82 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h index b8d1ffbac6b5..7401cb94fb72 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h @@ -230,6 +230,29 @@ #define MT_COM_REG2 0x0738 #define MT_COM_REG3 0x073C +#define MT_LED_CTRL 0x0770 +#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n))) +#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n))) +#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n))) +#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n))) + +#define MT_LED_TX_BLINK_0 0x0774 +#define MT_LED_TX_BLINK_1 0x0778 + +#define MT_LED_S0_BASE 0x077C +#define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n)) +#define MT_LED_S1_BASE 0x0780 +#define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n)) +#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24) +#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \ + MT_LED_STATUS_OFF_MASK) +#define MT_LED_STATUS_ON_MASK GENMASK(23, 16) +#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \ + MT_LED_STATUS_ON_MASK) +#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8) +#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \ + MT_LED_STATUS_DURATION_MASK) + #define MT_FCE_PSE_CTRL 0x0800 #define MT_FCE_PARAMETERS 0x0804 #define MT_FCE_CSO 0x0808 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 3c878f18e05d..d80c8eb5a0ec 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -75,6 +75,58 @@ static const struct ieee80211_iface_combination mt76x02_if_comb[] = { } }; +static void +mt76x02_led_set_config(struct mt76_dev *mdev, u8 delay_on, + u8 delay_off) +{ + struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, + mt76); + u32 val; + + val = MT_LED_STATUS_DURATION(0xff) | + MT_LED_STATUS_OFF(delay_off) | + MT_LED_STATUS_ON(delay_on); + + mt76_wr(dev, MT_LED_S0(mdev->led_pin), val); + mt76_wr(dev, MT_LED_S1(mdev->led_pin), val); + + val = MT_LED_CTRL_REPLAY(mdev->led_pin) | + MT_LED_CTRL_KICK(mdev->led_pin); + if (mdev->led_al) + val |= MT_LED_CTRL_POLARITY(mdev->led_pin); + mt76_wr(dev, MT_LED_CTRL, val); +} + +static int +mt76x02_led_set_blink(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev, + led_cdev); + u8 delta_on, delta_off; + + delta_off = max_t(u8, *delay_off / 10, 1); + delta_on = max_t(u8, *delay_on / 10, 1); + + mt76x02_led_set_config(mdev, delta_on, delta_off); + + return 0; +} + +static void +mt76x02_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct mt76_dev *mdev = container_of(led_cdev, struct mt76_dev, + led_cdev); + + if (!brightness) + mt76x02_led_set_config(mdev, 0, 0xff); + else + mt76x02_led_set_config(mdev, 0xff, 0); +} + void mt76x02_init_device(struct mt76x02_dev *dev) { struct ieee80211_hw *hw = mt76_hw(dev); @@ -109,6 +161,13 @@ void mt76x02_init_device(struct mt76x02_dev *dev) BIT(NL80211_IFTYPE_ADHOC); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + + /* init led callbacks */ + if (IS_ENABLED(CONFIG_MT76_LEDS)) { + dev->mt76.led_cdev.brightness_set = + mt76x02_led_set_brightness; + dev->mt76.led_cdev.blink_set = mt76x02_led_set_blink; + } } hw->sta_data_size = sizeof(struct mt76x02_sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h index acfa2b570c7c..40ef43926c06 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.h @@ -26,29 +26,6 @@ #define MT_MCU_PCIE_REMAP_BASE2 0x0744 #define MT_MCU_PCIE_REMAP_BASE3 0x0748 -#define MT_LED_CTRL 0x0770 -#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n))) -#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n))) -#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n))) -#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n))) - -#define MT_LED_TX_BLINK_0 0x0774 -#define MT_LED_TX_BLINK_1 0x0778 - -#define MT_LED_S0_BASE 0x077C -#define MT_LED_S0(_n) (MT_LED_S0_BASE + 8 * (_n)) -#define MT_LED_S1_BASE 0x0780 -#define MT_LED_S1(_n) (MT_LED_S1_BASE + 8 * (_n)) -#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24) -#define MT_LED_STATUS_OFF(_v) (((_v) << __ffs(MT_LED_STATUS_OFF_MASK)) & \ - MT_LED_STATUS_OFF_MASK) -#define MT_LED_STATUS_ON_MASK GENMASK(23, 16) -#define MT_LED_STATUS_ON(_v) (((_v) << __ffs(MT_LED_STATUS_ON_MASK)) & \ - MT_LED_STATUS_ON_MASK) -#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 8) -#define MT_LED_STATUS_DURATION(_v) (((_v) << __ffs(MT_LED_STATUS_DURATION_MASK)) & \ - MT_LED_STATUS_DURATION_MASK) - #define MT_MCU_ROM_PATCH_OFFSET 0x80000 #define MT_MCU_ROM_PATCH_ADDR 0x90000 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 34418e575542..4347d5e7a915 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -342,54 +342,6 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev) return dev; } -static void mt76x2_led_set_config(struct mt76_dev *mt76, u8 delay_on, - u8 delay_off) -{ - struct mt76x02_dev *dev = container_of(mt76, struct mt76x02_dev, - mt76); - u32 val; - - val = MT_LED_STATUS_DURATION(0xff) | - MT_LED_STATUS_OFF(delay_off) | - MT_LED_STATUS_ON(delay_on); - - mt76_wr(dev, MT_LED_S0(mt76->led_pin), val); - mt76_wr(dev, MT_LED_S1(mt76->led_pin), val); - - val = MT_LED_CTRL_REPLAY(mt76->led_pin) | - MT_LED_CTRL_KICK(mt76->led_pin); - if (mt76->led_al) - val |= MT_LED_CTRL_POLARITY(mt76->led_pin); - mt76_wr(dev, MT_LED_CTRL, val); -} - -static int mt76x2_led_set_blink(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, - led_cdev); - u8 delta_on, delta_off; - - delta_off = max_t(u8, *delay_off / 10, 1); - delta_on = max_t(u8, *delay_on / 10, 1); - - mt76x2_led_set_config(mt76, delta_on, delta_off); - return 0; -} - -static void mt76x2_led_set_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, - led_cdev); - - if (!brightness) - mt76x2_led_set_config(mt76, 0, 0xff); - else - mt76x2_led_set_config(mt76, 0xff, 0); -} - int mt76x2_register_device(struct mt76x02_dev *dev) { int ret; @@ -404,12 +356,6 @@ int mt76x2_register_device(struct mt76x02_dev *dev) mt76x02_config_mac_addr_list(dev); - /* init led callbacks */ - if (IS_ENABLED(CONFIG_MT76_LEDS)) { - dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness; - dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink; - } - ret = mt76_register_device(&dev->mt76, true, mt76x02_rates, ARRAY_SIZE(mt76x02_rates)); if (ret) -- cgit v1.2.3 From 73f5a82bb3c9fce550da4a74a32b8cb064b50663 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Sun, 13 Jan 2019 15:57:04 +0200 Subject: RDMA/mad: Reduce MAD scope to mlx5_ib only Management Datagram Interface (MAD) is applicable only when physical port is Infiniband. It makes MAD command logic to be completely unrelated to eth/core parts of mlx5. Signed-off-by: Leon Romanovsky Acked-by: Jason Gunthorpe --- drivers/infiniband/hw/mlx5/cmd.c | 37 ++++++++++++ drivers/infiniband/hw/mlx5/cmd.h | 2 + drivers/infiniband/hw/mlx5/mad.c | 11 ++-- drivers/infiniband/hw/mlx5/mlx5_ib.h | 3 - drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/mad.c | 75 ------------------------ include/linux/mlx5/driver.h | 2 - 7 files changed, 47 insertions(+), 85 deletions(-) delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/mad.c (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/cmd.c b/drivers/infiniband/hw/mlx5/cmd.c index 356bccc715ee..6bcc63aaa50b 100644 --- a/drivers/infiniband/hw/mlx5/cmd.c +++ b/drivers/infiniband/hw/mlx5/cmd.c @@ -345,3 +345,40 @@ int mlx5_cmd_alloc_q_counter(struct mlx5_core_dev *dev, u16 *counter_id, counter_set_id); return err; } + +int mlx5_cmd_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb, + u16 opmod, u8 port) +{ + int outlen = MLX5_ST_SZ_BYTES(mad_ifc_out); + int inlen = MLX5_ST_SZ_BYTES(mad_ifc_in); + int err = -ENOMEM; + void *data; + void *resp; + u32 *out; + u32 *in; + + in = kzalloc(inlen, GFP_KERNEL); + out = kzalloc(outlen, GFP_KERNEL); + if (!in || !out) + goto out; + + MLX5_SET(mad_ifc_in, in, opcode, MLX5_CMD_OP_MAD_IFC); + MLX5_SET(mad_ifc_in, in, op_mod, opmod); + MLX5_SET(mad_ifc_in, in, port, port); + + data = MLX5_ADDR_OF(mad_ifc_in, in, mad); + memcpy(data, inb, MLX5_FLD_SZ_BYTES(mad_ifc_in, mad)); + + err = mlx5_cmd_exec(dev, in, inlen, out, outlen); + if (err) + goto out; + + resp = MLX5_ADDR_OF(mad_ifc_out, out, response_mad_packet); + memcpy(outb, resp, + MLX5_FLD_SZ_BYTES(mad_ifc_out, response_mad_packet)); + +out: + kfree(out); + kfree(in); + return err; +} diff --git a/drivers/infiniband/hw/mlx5/cmd.h b/drivers/infiniband/hw/mlx5/cmd.h index 1e76dc67a369..923a7b93f507 100644 --- a/drivers/infiniband/hw/mlx5/cmd.h +++ b/drivers/infiniband/hw/mlx5/cmd.h @@ -63,4 +63,6 @@ int mlx5_cmd_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn, u16 uid); int mlx5_cmd_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn, u16 uid); int mlx5_cmd_alloc_q_counter(struct mlx5_core_dev *dev, u16 *counter_id, u16 uid); +int mlx5_cmd_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb, + u16 opmod, u8 port); #endif /* MLX5_IB_CMD_H */ diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c index 558638468edb..6c529e6f3a01 100644 --- a/drivers/infiniband/hw/mlx5/mad.c +++ b/drivers/infiniband/hw/mlx5/mad.c @@ -36,6 +36,7 @@ #include #include #include "mlx5_ib.h" +#include "cmd.h" enum { MLX5_IB_VENDOR_CLASS1 = 0x9, @@ -51,9 +52,10 @@ static bool can_do_mad_ifc(struct mlx5_ib_dev *dev, u8 port_num, return dev->mdev->port_caps[port_num - 1].has_smi; } -int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, - u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, - const void *in_mad, void *response_mad) +static int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, + int ignore_bkey, u8 port, const struct ib_wc *in_wc, + const struct ib_grh *in_grh, const void *in_mad, + void *response_mad) { u8 op_modifier = 0; @@ -68,7 +70,8 @@ int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, if (ignore_bkey || !in_wc) op_modifier |= 0x2; - return mlx5_core_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, port); + return mlx5_cmd_mad_ifc(dev->mdev, in_mad, response_mad, op_modifier, + port); } static int process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index b06d3b1efea8..efe383c0ac86 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -1038,9 +1038,6 @@ void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db) void __mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq); void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq); void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index); -int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey, - u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh, - const void *in_mad, void *response_mad); struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr, u32 flags, struct ib_udata *udata); int mlx5_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 9de9abacf7f6..0257731e6d42 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_MLX5_CORE) += mlx5_core.o # mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \ health.o mcg.o cq.o alloc.o qp.o port.o mr.o pd.o \ - mad.o transobj.o vport.o sriov.o fs_cmd.o fs_core.o \ + transobj.o vport.o sriov.o fs_cmd.o fs_core.o \ fs_counters.o rl.o lag.o dev.o events.o wq.o lib/gid.o \ lib/devcom.o diag/fs_tracepoint.o diag/fw_tracer.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mad.c b/drivers/net/ethernet/mellanox/mlx5/core/mad.c deleted file mode 100644 index 3a3b0005fd2b..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/mad.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include "mlx5_core.h" - -int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb, - u16 opmod, u8 port) -{ - int outlen = MLX5_ST_SZ_BYTES(mad_ifc_out); - int inlen = MLX5_ST_SZ_BYTES(mad_ifc_in); - int err = -ENOMEM; - void *data; - void *resp; - u32 *out; - u32 *in; - - in = kzalloc(inlen, GFP_KERNEL); - out = kzalloc(outlen, GFP_KERNEL); - if (!in || !out) - goto out; - - MLX5_SET(mad_ifc_in, in, opcode, MLX5_CMD_OP_MAD_IFC); - MLX5_SET(mad_ifc_in, in, op_mod, opmod); - MLX5_SET(mad_ifc_in, in, port, port); - - data = MLX5_ADDR_OF(mad_ifc_in, in, mad); - memcpy(data, inb, MLX5_FLD_SZ_BYTES(mad_ifc_in, mad)); - - err = mlx5_cmd_exec(dev, in, inlen, out, outlen); - if (err) - goto out; - - resp = MLX5_ADDR_OF(mad_ifc_out, out, response_mad_packet); - memcpy(outb, resp, - MLX5_FLD_SZ_BYTES(mad_ifc_out, response_mad_packet)); - -out: - kfree(out); - kfree(in); - return err; -} -EXPORT_SYMBOL_GPL(mlx5_core_mad_ifc); diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 54299251d40d..4e444863054a 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -897,8 +897,6 @@ int mlx5_core_query_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mkey *mkey, u32 *out, int outlen); int mlx5_core_alloc_pd(struct mlx5_core_dev *dev, u32 *pdn); int mlx5_core_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn); -int mlx5_core_mad_ifc(struct mlx5_core_dev *dev, const void *inb, void *outb, - u16 opmod, u8 port); int mlx5_pagealloc_init(struct mlx5_core_dev *dev); void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev); void mlx5_pagealloc_start(struct mlx5_core_dev *dev); -- cgit v1.2.3 From 3d505147178b9f310008da4fad14743824d235a9 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 19 Dec 2018 10:03:20 -0800 Subject: ice: Fix unused variable build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 2fd527b72bb6 ("net: ndo_bridge_setlink: Add extack") added a new parameter "extack" to ice_bridge_setlink but this parameter isn't used by the function. This results in a warning: unused parameter ‘extack’ [-Wunused-parameter]. Fix that by adding an "__always_unused" qualifier. Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 8725569d11f0..90773b477d19 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3641,7 +3641,8 @@ static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode) */ static int ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, - u16 __always_unused flags, struct netlink_ext_ack *extack) + u16 __always_unused flags, + struct netlink_ext_ack __always_unused *extack) { struct ice_netdev_priv *np = netdev_priv(dev); struct ice_pf *pf = np->vsi->back; -- cgit v1.2.3 From 1f9c7840e81ad81dd99cf5ad74843316b935402f Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Wed, 19 Dec 2018 10:03:21 -0800 Subject: ice: Refactor a few Tx scheduler functions The following functions were refactored to call a new common function, ice_aqc_send_sched_elem_cmd(): - ice_aq_add_sched_elems() - ice_aq_delete_sched_elems() - ice_aq_move_sched_elems() - ice_aq_query_sched_elems() - ice_aq_cfg_sched_elems() - ice_aq_suspend_sched_elems() - ice_aq_resume_sched_elems() Signed-off-by: Greg Priest Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 22 ++--- drivers/net/ethernet/intel/ice/ice_sched.c | 122 +++++++++--------------- 2 files changed, 53 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index fcdcd80b18e7..4c7e3af07254 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -657,8 +657,13 @@ struct ice_aqc_get_topo { /* Update TSE (indirect 0x0403) * Get TSE (indirect 0x0404) + * Add TSE (indirect 0x0401) + * Delete TSE (indirect 0x040F) + * Move TSE (indirect 0x0408) + * Suspend Nodes (indirect 0x0409) + * Resume Nodes (indirect 0x040A) */ -struct ice_aqc_get_cfg_elem { +struct ice_aqc_sched_elem_cmd { __le16 num_elem_req; /* Used by commands */ __le16 num_elem_resp; /* Used by responses */ __le32 reserved; @@ -674,18 +679,6 @@ struct ice_aqc_suspend_resume_elem { __le32 teid[1]; }; -/* Add TSE (indirect 0x0401) - * Delete TSE (indirect 0x040F) - * Move TSE (indirect 0x0408) - */ -struct ice_aqc_add_move_delete_elem { - __le16 num_grps_req; - __le16 num_grps_updated; - __le32 reserved; - __le32 addr_high; - __le32 addr_low; -}; - struct ice_aqc_elem_info_bw { __le16 bw_profile_idx; __le16 bw_alloc; @@ -1344,9 +1337,8 @@ struct ice_aq_desc { struct ice_aqc_get_sw_cfg get_sw_conf; struct ice_aqc_sw_rules sw_rules; struct ice_aqc_get_topo get_topo; - struct ice_aqc_get_cfg_elem get_update_elem; + struct ice_aqc_sched_elem_cmd sched_elem_cmd; struct ice_aqc_query_txsched_res query_sched_res; - struct ice_aqc_add_move_delete_elem add_move_delete_elem; struct ice_aqc_nvm nvm; struct ice_aqc_pf_vf_msg virt; struct ice_aqc_get_set_rss_lut get_set_rss_lut; diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index a1681853df2e..99d51990bd54 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -85,36 +85,58 @@ ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid) } /** - * ice_aq_query_sched_elems - query scheduler elements + * ice_aqc_send_sched_elem_cmd - send scheduling elements cmd * @hw: pointer to the hw struct - * @elems_req: number of elements to query + * @cmd_opc: cmd opcode + * @elems_req: number of elements to request * @buf: pointer to buffer * @buf_size: buffer size in bytes - * @elems_ret: returns total number of elements returned + * @elems_resp: returns total number of elements response * @cd: pointer to command details structure or NULL * - * Query scheduling elements (0x0404) + * This function sends a scheduling elements cmd (cmd_opc) */ static enum ice_status -ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req, - struct ice_aqc_get_elem *buf, u16 buf_size, - u16 *elems_ret, struct ice_sq_cd *cd) +ice_aqc_send_sched_elem_cmd(struct ice_hw *hw, enum ice_adminq_opc cmd_opc, + u16 elems_req, void *buf, u16 buf_size, + u16 *elems_resp, struct ice_sq_cd *cd) { - struct ice_aqc_get_cfg_elem *cmd; + struct ice_aqc_sched_elem_cmd *cmd; struct ice_aq_desc desc; enum ice_status status; - cmd = &desc.params.get_update_elem; - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sched_elems); + cmd = &desc.params.sched_elem_cmd; + ice_fill_dflt_direct_cmd_desc(&desc, cmd_opc); cmd->num_elem_req = cpu_to_le16(elems_req); desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); - if (!status && elems_ret) - *elems_ret = le16_to_cpu(cmd->num_elem_resp); + if (!status && elems_resp) + *elems_resp = le16_to_cpu(cmd->num_elem_resp); return status; } +/** + * ice_aq_query_sched_elems - query scheduler elements + * @hw: pointer to the hw struct + * @elems_req: number of elements to query + * @buf: pointer to buffer + * @buf_size: buffer size in bytes + * @elems_ret: returns total number of elements returned + * @cd: pointer to command details structure or NULL + * + * Query scheduling elements (0x0404) + */ +static enum ice_status +ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req, + struct ice_aqc_get_elem *buf, u16 buf_size, + u16 *elems_ret, struct ice_sq_cd *cd) +{ + return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_get_sched_elems, + elems_req, (void *)buf, buf_size, + elems_ret, cd); +} + /** * ice_sched_query_elem - query element information from hw * @hw: pointer to the hw struct @@ -218,20 +240,9 @@ ice_aq_delete_sched_elems(struct ice_hw *hw, u16 grps_req, struct ice_aqc_delete_elem *buf, u16 buf_size, u16 *grps_del, struct ice_sq_cd *cd) { - struct ice_aqc_add_move_delete_elem *cmd; - struct ice_aq_desc desc; - enum ice_status status; - - cmd = &desc.params.add_move_delete_elem; - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_delete_sched_elems); - desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); - cmd->num_grps_req = cpu_to_le16(grps_req); - - status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); - if (!status && grps_del) - *grps_del = le16_to_cpu(cmd->num_grps_updated); - - return status; + return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_delete_sched_elems, + grps_req, (void *)buf, buf_size, + grps_del, cd); } /** @@ -442,52 +453,9 @@ ice_aq_add_sched_elems(struct ice_hw *hw, u16 grps_req, struct ice_aqc_add_elem *buf, u16 buf_size, u16 *grps_added, struct ice_sq_cd *cd) { - struct ice_aqc_add_move_delete_elem *cmd; - struct ice_aq_desc desc; - enum ice_status status; - - cmd = &desc.params.add_move_delete_elem; - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_sched_elems); - desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); - - cmd->num_grps_req = cpu_to_le16(grps_req); - status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); - if (!status && grps_added) - *grps_added = le16_to_cpu(cmd->num_grps_updated); - - return status; -} - -/** - * ice_suspend_resume_elems - suspend/resume scheduler elements - * @hw: pointer to the hw struct - * @elems_req: number of elements to suspend - * @buf: pointer to buffer - * @buf_size: buffer size in bytes - * @elems_ret: returns total number of elements suspended - * @cd: pointer to command details structure or NULL - * @cmd_code: command code for suspend or resume - * - * suspend/resume scheduler elements - */ -static enum ice_status -ice_suspend_resume_elems(struct ice_hw *hw, u16 elems_req, - struct ice_aqc_suspend_resume_elem *buf, u16 buf_size, - u16 *elems_ret, struct ice_sq_cd *cd, - enum ice_adminq_opc cmd_code) -{ - struct ice_aqc_get_cfg_elem *cmd; - struct ice_aq_desc desc; - enum ice_status status; - - cmd = &desc.params.get_update_elem; - ice_fill_dflt_direct_cmd_desc(&desc, cmd_code); - cmd->num_elem_req = cpu_to_le16(elems_req); - desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); - status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); - if (!status && elems_ret) - *elems_ret = le16_to_cpu(cmd->num_elem_resp); - return status; + return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_add_sched_elems, + grps_req, (void *)buf, buf_size, + grps_added, cd); } /** @@ -506,8 +474,9 @@ ice_aq_suspend_sched_elems(struct ice_hw *hw, u16 elems_req, struct ice_aqc_suspend_resume_elem *buf, u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd) { - return ice_suspend_resume_elems(hw, elems_req, buf, buf_size, elems_ret, - cd, ice_aqc_opc_suspend_sched_elems); + return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_suspend_sched_elems, + elems_req, (void *)buf, buf_size, + elems_ret, cd); } /** @@ -526,8 +495,9 @@ ice_aq_resume_sched_elems(struct ice_hw *hw, u16 elems_req, struct ice_aqc_suspend_resume_elem *buf, u16 buf_size, u16 *elems_ret, struct ice_sq_cd *cd) { - return ice_suspend_resume_elems(hw, elems_req, buf, buf_size, elems_ret, - cd, ice_aqc_opc_resume_sched_elems); + return ice_aqc_send_sched_elem_cmd(hw, ice_aqc_opc_resume_sched_elems, + elems_req, (void *)buf, buf_size, + elems_ret, cd); } /** -- cgit v1.2.3 From 27a98affa66000d7f96527a4a267f0d13aaecf7b Mon Sep 17 00:00:00 2001 From: Md Fahad Iqbal Polash Date: Wed, 19 Dec 2018 10:03:22 -0800 Subject: ice: Configure RSS LUT and HASH KEY in rebuild path This patch configures the RSS lookup table and hash key post reset. Signed-off-by: Md Fahad Iqbal Polash Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 29b1dcfd4331..3bd24173b39c 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2581,6 +2581,12 @@ int ice_vsi_rebuild(struct ice_vsi *vsi) goto err_vectors; ice_vsi_map_rings_to_vectors(vsi); + /* Do not exit if configuring RSS had an issue, at least + * receive traffic on first queue. Hence no need to capture + * return value + */ + if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) + ice_vsi_cfg_rss_lut_key(vsi); break; case ICE_VSI_VF: ret = ice_vsi_alloc_q_vectors(vsi); -- cgit v1.2.3 From 8e151d50a1450350009822b4f705c6caf83383d4 Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Wed, 19 Dec 2018 10:03:23 -0800 Subject: ice: Add ethtool set_phys_id handler Add led blinking handler to ethtool. Since led blinking is controlled by FW/HW only ETHTOOL_ID_ACTIVE and ETHTOOL_ID_INACTIVE are really needed. Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 12 +++++++++++ drivers/net/ethernet/intel/ice/ice_common.c | 28 +++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_common.h | 4 ++++ drivers/net/ethernet/intel/ice/ice_ethtool.c | 24 +++++++++++++++++++++ 4 files changed, 68 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 4c7e3af07254..245068b21982 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -1048,6 +1048,16 @@ struct ice_aqc_set_event_mask { u8 reserved1[6]; }; +/* Set Port Identification LED (direct, 0x06E9) */ +struct ice_aqc_set_port_id_led { + u8 lport_num; + u8 lport_num_valid; + u8 ident_mode; +#define ICE_AQC_PORT_IDENT_LED_BLINK BIT(0) +#define ICE_AQC_PORT_IDENT_LED_ORIG 0 + u8 rsvd[13]; +}; + /* NVM Read command (indirect 0x0701) * NVM Erase commands (direct 0x0702) * NVM Update commands (indirect 0x0703) @@ -1334,6 +1344,7 @@ struct ice_aq_desc { struct ice_aqc_get_phy_caps get_phy; struct ice_aqc_set_phy_cfg set_phy; struct ice_aqc_restart_an restart_an; + struct ice_aqc_set_port_id_led set_port_id_led; struct ice_aqc_get_sw_cfg get_sw_conf; struct ice_aqc_sw_rules sw_rules; struct ice_aqc_get_topo get_topo; @@ -1434,6 +1445,7 @@ enum ice_adminq_opc { ice_aqc_opc_restart_an = 0x0605, ice_aqc_opc_get_link_status = 0x0607, ice_aqc_opc_set_event_mask = 0x0613, + ice_aqc_opc_set_port_id_led = 0x06E9, /* NVM commands */ ice_aqc_opc_nvm_read = 0x0701, diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 4c1d35da940d..2bcd8230d35e 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -2031,6 +2031,34 @@ ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link, return ice_aq_send_cmd(pi->hw, &desc, NULL, 0, cd); } +/** + * ice_aq_set_port_id_led + * @pi: pointer to the port information + * @is_orig_mode: is this LED set to original mode (by the net-list) + * @cd: pointer to command details structure or NULL + * + * Set LED value for the given port (0x06e9) + */ +enum ice_status +ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode, + struct ice_sq_cd *cd) +{ + struct ice_aqc_set_port_id_led *cmd; + struct ice_hw *hw = pi->hw; + struct ice_aq_desc desc; + + cmd = &desc.params.set_port_id_led; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_id_led); + + if (is_orig_mode) + cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_ORIG; + else + cmd->ident_mode = ICE_AQC_PORT_IDENT_LED_BLINK; + + return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); +} + /** * __ice_aq_get_set_rss_lut * @hw: pointer to the hardware structure diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index cf760c24a6aa..b86cfe540045 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -86,6 +86,10 @@ enum ice_status ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link, struct ice_sq_cd *cd); enum ice_status +ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode, + struct ice_sq_cd *cd); + +enum ice_status ice_dis_vsi_txq(struct ice_port_info *pi, u8 num_queues, u16 *q_ids, u32 *q_teids, enum ice_disq_rst_src rst_src, u16 vmvf_num, struct ice_sq_cd *cmd_details); diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 3b6e387f5440..6facb0a7eed4 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -249,6 +249,29 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) } } +static int +ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) +{ + struct ice_netdev_priv *np = netdev_priv(netdev); + bool led_active; + + switch (state) { + case ETHTOOL_ID_ACTIVE: + led_active = true; + break; + case ETHTOOL_ID_INACTIVE: + led_active = false; + break; + default: + return -EINVAL; + } + + if (ice_aq_set_port_id_led(np->vsi->port_info, !led_active, NULL)) + return -EIO; + + return 0; +} + static int ice_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { @@ -1677,6 +1700,7 @@ static const struct ethtool_ops ice_ethtool_ops = { .set_msglevel = ice_set_msglevel, .get_link = ethtool_op_get_link, .get_strings = ice_get_strings, + .set_phys_id = ice_set_phys_id, .get_ethtool_stats = ice_get_ethtool_stats, .get_sset_count = ice_get_sset_count, .get_rxnfc = ice_get_rxnfc, -- cgit v1.2.3 From 4c98ab550cc624eb94b0cdb32f5deb1ebbb4f593 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 19 Dec 2018 10:03:24 -0800 Subject: ice: Implement support for normal get_eeprom[_len] ethtool ops Add support for get_eeprom and get_eeprom_len ethtool ops Specification states that PF software accesses NVM (shadow-ram) via AQ commands (e.g. NVM Read, NVM Write) in the range 0x000000-0x00FFFF (64KB), so the get_eeprom_len op should return 64KB. If additional regions of the 16MB NVM must be read, another access method must be used. The ethtool kernel code, by default, will ask for multiple page-size hunks of the NVM not to exceed the value returned by ice_get_eeprom_len(). ice_read_sr_buf() deals with arch page sizes different than 4KB. Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.h | 2 + drivers/net/ethernet/intel/ice/ice_ethtool.c | 51 ++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_nvm.c | 81 ++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index b86cfe540045..81c1bb77a9fc 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -28,6 +28,8 @@ ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res, enum ice_aq_res_access_type access, u32 timeout); void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res); enum ice_status ice_init_nvm(struct ice_hw *hw); +enum ice_status ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, + u16 *data); enum ice_status ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, struct ice_aq_desc *desc, void *buf, u16 buf_size, diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 6facb0a7eed4..2a0bcd460d23 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -203,6 +203,55 @@ static void ice_set_msglevel(struct net_device *netdev, u32 data) #endif /* !CONFIG_DYNAMIC_DEBUG */ } +static int ice_get_eeprom_len(struct net_device *netdev) +{ + struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_pf *pf = np->vsi->back; + + return (int)(pf->hw.nvm.sr_words * sizeof(u16)); +} + +static int +ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, + u8 *bytes) +{ + struct ice_netdev_priv *np = netdev_priv(netdev); + u16 first_word, last_word, nwords; + struct ice_vsi *vsi = np->vsi; + struct ice_pf *pf = vsi->back; + struct ice_hw *hw = &pf->hw; + enum ice_status status; + struct device *dev; + int ret = 0; + u16 *buf; + + dev = &pf->pdev->dev; + + eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + nwords = last_word - first_word + 1; + + buf = devm_kcalloc(dev, nwords, sizeof(u16), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + status = ice_read_sr_buf(hw, first_word, &nwords, buf); + if (status) { + dev_err(dev, "ice_read_sr_buf failed, err %d aq_err %d\n", + status, hw->adminq.sq_last_status); + eeprom->len = sizeof(u16) * nwords; + ret = -EIO; + goto out; + } + + memcpy(bytes, (u8 *)buf + (eeprom->offset & 1), eeprom->len); +out: + devm_kfree(dev, buf); + return ret; +} + static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { struct ice_netdev_priv *np = netdev_priv(netdev); @@ -1699,6 +1748,8 @@ static const struct ethtool_ops ice_ethtool_ops = { .get_msglevel = ice_get_msglevel, .set_msglevel = ice_set_msglevel, .get_link = ethtool_op_get_link, + .get_eeprom_len = ice_get_eeprom_len, + .get_eeprom = ice_get_eeprom, .get_strings = ice_get_strings, .set_phys_id = ice_set_phys_id, .get_ethtool_stats = ice_get_ethtool_stats, diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c index 3274c543283c..ce64cecdae9c 100644 --- a/drivers/net/ethernet/intel/ice/ice_nvm.c +++ b/drivers/net/ethernet/intel/ice/ice_nvm.c @@ -124,6 +124,62 @@ ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data) return status; } +/** + * ice_read_sr_buf_aq - Reads Shadow RAM buf via AQ + * @hw: pointer to the HW structure + * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) + * @words: (in) number of words to read; (out) number of words actually read + * @data: words read from the Shadow RAM + * + * Reads 16 bit words (data buf) from the SR using the ice_read_sr_aq + * method. Ownership of the NVM is taken before reading the buffer and later + * released. + */ +static enum ice_status +ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) +{ + enum ice_status status; + bool last_cmd = false; + u16 words_read = 0; + u16 i = 0; + + do { + u16 read_size, off_w; + + /* Calculate number of bytes we should read in this step. + * It's not allowed to read more than one page at a time or + * to cross page boundaries. + */ + off_w = offset % ICE_SR_SECTOR_SIZE_IN_WORDS; + read_size = off_w ? + min(*words, + (u16)(ICE_SR_SECTOR_SIZE_IN_WORDS - off_w)) : + min((*words - words_read), ICE_SR_SECTOR_SIZE_IN_WORDS); + + /* Check if this is last command, if so set proper flag */ + if ((words_read + read_size) >= *words) + last_cmd = true; + + status = ice_read_sr_aq(hw, offset, read_size, + data + words_read, last_cmd); + if (status) + goto read_nvm_buf_aq_exit; + + /* Increment counter for words already read and move offset to + * new read location + */ + words_read += read_size; + offset += read_size; + } while (words_read < *words); + + for (i = 0; i < *words; i++) + data[i] = le16_to_cpu(((__le16 *)data)[i]); + +read_nvm_buf_aq_exit: + *words = words_read; + return status; +} + /** * ice_acquire_nvm - Generic request for acquiring the NVM ownership * @hw: pointer to the HW structure @@ -234,3 +290,28 @@ enum ice_status ice_init_nvm(struct ice_hw *hw) return status; } + +/** + * ice_read_sr_buf - Reads Shadow RAM buf and acquire lock if necessary + * @hw: pointer to the HW structure + * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) + * @words: (in) number of words to read; (out) number of words actually read + * @data: words read from the Shadow RAM + * + * Reads 16 bit words (data buf) from the SR using the ice_read_nvm_buf_aq + * method. The buf read is preceded by the NVM ownership take + * and followed by the release. + */ +enum ice_status +ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) +{ + enum ice_status status; + + status = ice_acquire_nvm(hw, ICE_RES_READ); + if (!status) { + status = ice_read_sr_buf_aq(hw, offset, words, data); + ice_release_nvm(hw); + } + + return status; +} -- cgit v1.2.3 From b6f934f027bbdb53b7e2653b23758e222f3dd65a Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Wed, 19 Dec 2018 10:03:25 -0800 Subject: ice: Set physical link up/down when an interface is set up/down When a netdev is set up/down we need to set the phsyical link state accordingly. This patch adds that functionality by calling ice_force_phys_link_state(vsi, link_up) in both the ice_stop() and ice_open() paths. In order to force link, ice_force_phys_link_state(vsi, link_up) will first determine the current phy capabilities. If link has not changed there is nothing to do. If link has changed, previous PHY capabilities are saved and the "Enable Automatic Link Update" and "Link Establishment State Machine (LESM)" enable bits are set. Then the new PHY config is saved. The "Enable Automatic Link Update" will force the FW to execute Setup link and restart auto-negotiation. This *should* then result in a "Link Status Event (LSE)" which will cause the driver to get the current link status. Signed-off-by: Brett Creeley Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 4 +- drivers/net/ethernet/intel/ice/ice_main.c | 97 ++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 245068b21982..526224ede3fa 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -851,7 +851,7 @@ struct ice_aqc_get_phy_caps { struct ice_aqc_get_phy_caps_data { __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */ - __le64 reserved; + __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */ u8 caps; #define ICE_AQC_PHY_EN_TX_LINK_PAUSE BIT(0) #define ICE_AQC_PHY_EN_RX_LINK_PAUSE BIT(1) @@ -916,7 +916,7 @@ struct ice_aqc_set_phy_cfg { /* Set PHY config command data structure */ struct ice_aqc_set_phy_cfg_data { __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */ - __le64 rsvd0; + __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */ u8 caps; #define ICE_AQ_PHY_ENA_TX_PAUSE_ABILITY BIT(0) #define ICE_AQ_PHY_ENA_RX_PAUSE_ABILITY BIT(1) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 90773b477d19..b27bc7d6d605 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2944,13 +2944,92 @@ static void ice_napi_disable_all(struct ice_vsi *vsi) } } +/** + * ice_force_phys_link_state - Force the physical link state + * @vsi: VSI to force the physical link state to up/down + * @link_up: true/false indicates to set the physical link to up/down + * + * Force the physical link state by getting the current PHY capabilities from + * hardware and setting the PHY config based on the determined capabilities. If + * link changes a link event will be triggered because both the Enable Automatic + * Link Update and LESM Enable bits are set when setting the PHY capabilities. + * + * Returns 0 on success, negative on failure + */ +static int ice_force_phys_link_state(struct ice_vsi *vsi, bool link_up) +{ + struct ice_aqc_get_phy_caps_data *pcaps; + struct ice_aqc_set_phy_cfg_data *cfg; + struct ice_port_info *pi; + struct device *dev; + int retcode; + + if (!vsi || !vsi->port_info || !vsi->back) + return -EINVAL; + if (vsi->type != ICE_VSI_PF) + return 0; + + dev = &vsi->back->pdev->dev; + + pi = vsi->port_info; + + pcaps = devm_kzalloc(dev, sizeof(*pcaps), GFP_KERNEL); + if (!pcaps) + return -ENOMEM; + + retcode = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, + NULL); + if (retcode) { + dev_err(dev, + "Failed to get phy capabilities, VSI %d error %d\n", + vsi->vsi_num, retcode); + retcode = -EIO; + goto out; + } + + /* No change in link */ + if (link_up == !!(pcaps->caps & ICE_AQC_PHY_EN_LINK) && + link_up == !!(pi->phy.link_info.link_info & ICE_AQ_LINK_UP)) + goto out; + + cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL); + if (!cfg) { + retcode = -ENOMEM; + goto out; + } + + cfg->phy_type_low = pcaps->phy_type_low; + cfg->phy_type_high = pcaps->phy_type_high; + cfg->caps = pcaps->caps | ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; + cfg->low_power_ctrl = pcaps->low_power_ctrl; + cfg->eee_cap = pcaps->eee_cap; + cfg->eeer_value = pcaps->eeer_value; + cfg->link_fec_opt = pcaps->link_fec_options; + if (link_up) + cfg->caps |= ICE_AQ_PHY_ENA_LINK; + else + cfg->caps &= ~ICE_AQ_PHY_ENA_LINK; + + retcode = ice_aq_set_phy_cfg(&vsi->back->hw, pi->lport, cfg, NULL); + if (retcode) { + dev_err(dev, "Failed to set phy config, VSI %d error %d\n", + vsi->vsi_num, retcode); + retcode = -EIO; + } + + devm_kfree(dev, cfg); +out: + devm_kfree(dev, pcaps); + return retcode; +} + /** * ice_down - Shutdown the connection * @vsi: The VSI being stopped */ int ice_down(struct ice_vsi *vsi) { - int i, tx_err, rx_err; + int i, tx_err, rx_err, link_err; /* Caller of this function is expected to set the * vsi->state __ICE_DOWN bit @@ -2975,13 +3054,19 @@ int ice_down(struct ice_vsi *vsi) ice_napi_disable_all(vsi); + link_err = ice_force_phys_link_state(vsi, false); + if (link_err) + netdev_err(vsi->netdev, + "Failed to set physical link down, VSI %d error %d\n", + vsi->vsi_num, link_err); + ice_for_each_txq(vsi, i) ice_clean_tx_ring(vsi->tx_rings[i]); ice_for_each_rxq(vsi, i) ice_clean_rx_ring(vsi->rx_rings[i]); - if (tx_err || rx_err) { + if (tx_err || rx_err || link_err) { netdev_err(vsi->netdev, "Failed to close VSI 0x%04X on switch 0x%04X\n", vsi->vsi_num, vsi->vsw->sw_id); @@ -3815,8 +3900,14 @@ static int ice_open(struct net_device *netdev) netif_carrier_off(netdev); - err = ice_vsi_open(vsi); + err = ice_force_phys_link_state(vsi, true); + if (err) { + netdev_err(netdev, + "Failed to set physical link up, error %d\n", err); + return err; + } + err = ice_vsi_open(vsi); if (err) netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n", vsi->vsi_num, vsi->vsw->sw_id); -- cgit v1.2.3 From ab4ab73fc1ec6dec548fa36c5e383ef5faa7b4c1 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 19 Dec 2018 10:03:26 -0800 Subject: ice: Add ethtool private flag to make forcing link down optional Add new infrastructure for implementing ethtool private flags using the existing pf->flags bitmap to store them, and add the link-down-on-close ethtool private flag to optionally bring down the PHY link when the interface is administratively downed. Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 1 + drivers/net/ethernet/intel/ice/ice_ethtool.c | 86 ++++++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_main.c | 14 +++-- 3 files changed, 95 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index a385575600f6..8af882a2b070 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -270,6 +270,7 @@ enum ice_pf_flags { ICE_FLAG_RSS_ENA, ICE_FLAG_SRIOV_ENA, ICE_FLAG_SRIOV_CAPABLE, + ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, ICE_PF_FLAGS_NBITS /* must be last */ }; diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 2a0bcd460d23..24c8aeaea2d5 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -114,6 +114,22 @@ static const u32 ice_regs_dump_list[] = { QRX_ITR(0), }; +struct ice_priv_flag { + char name[ETH_GSTRING_LEN]; + u32 bitno; /* bit position in pf->flags */ +}; + +#define ICE_PRIV_FLAG(_name, _bitno) { \ + .name = _name, \ + .bitno = _bitno, \ +} + +static const struct ice_priv_flag ice_gstrings_priv_flags[] = { + ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA), +}; + +#define ICE_PRIV_FLAG_ARRAY_SIZE ARRAY_SIZE(ice_gstrings_priv_flags) + /** * ice_nvm_version_str - format the NVM version strings * @hw: ptr to the hardware info @@ -152,6 +168,7 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, pci_name(pf->pdev), sizeof(drvinfo->bus_info)); + drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE; } static int ice_get_regs_len(struct net_device __always_unused *netdev) @@ -292,6 +309,13 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) p += ETH_GSTRING_LEN; } + break; + case ETH_SS_PRIV_FLAGS: + for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { + snprintf(p, ETH_GSTRING_LEN, "%s", + ice_gstrings_priv_flags[i].name); + p += ETH_GSTRING_LEN; + } break; default: break; @@ -321,6 +345,64 @@ ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) return 0; } +/** + * ice_get_priv_flags - report device private flags + * @netdev: network interface device structure + * + * The get string set count and the string set should be matched for each + * flag returned. Add new strings for each flag to the ice_gstrings_priv_flags + * array. + * + * Returns a u32 bitmap of flags. + */ +static u32 ice_get_priv_flags(struct net_device *netdev) +{ + struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_vsi *vsi = np->vsi; + struct ice_pf *pf = vsi->back; + u32 i, ret_flags = 0; + + for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { + const struct ice_priv_flag *priv_flag; + + priv_flag = &ice_gstrings_priv_flags[i]; + + if (test_bit(priv_flag->bitno, pf->flags)) + ret_flags |= BIT(i); + } + + return ret_flags; +} + +/** + * ice_set_priv_flags - set private flags + * @netdev: network interface device structure + * @flags: bit flags to be set + */ +static int ice_set_priv_flags(struct net_device *netdev, u32 flags) +{ + struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_vsi *vsi = np->vsi; + struct ice_pf *pf = vsi->back; + u32 i; + + if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE)) + return -EINVAL; + + for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { + const struct ice_priv_flag *priv_flag; + + priv_flag = &ice_gstrings_priv_flags[i]; + + if (flags & BIT(i)) + set_bit(priv_flag->bitno, pf->flags); + else + clear_bit(priv_flag->bitno, pf->flags); + } + + return 0; +} + static int ice_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { @@ -344,6 +426,8 @@ static int ice_get_sset_count(struct net_device *netdev, int sset) * not safe. */ return ICE_ALL_STATS_LEN(netdev); + case ETH_SS_PRIV_FLAGS: + return ICE_PRIV_FLAG_ARRAY_SIZE; default: return -EOPNOTSUPP; } @@ -1753,6 +1837,8 @@ static const struct ethtool_ops ice_ethtool_ops = { .get_strings = ice_get_strings, .set_phys_id = ice_set_phys_id, .get_ethtool_stats = ice_get_ethtool_stats, + .get_priv_flags = ice_get_priv_flags, + .set_priv_flags = ice_set_priv_flags, .get_sset_count = ice_get_sset_count, .get_rxnfc = ice_get_rxnfc, .get_ringparam = ice_get_ringparam, diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index b27bc7d6d605..e36db981f047 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3029,7 +3029,7 @@ out: */ int ice_down(struct ice_vsi *vsi) { - int i, tx_err, rx_err, link_err; + int i, tx_err, rx_err, link_err = 0; /* Caller of this function is expected to set the * vsi->state __ICE_DOWN bit @@ -3054,11 +3054,13 @@ int ice_down(struct ice_vsi *vsi) ice_napi_disable_all(vsi); - link_err = ice_force_phys_link_state(vsi, false); - if (link_err) - netdev_err(vsi->netdev, - "Failed to set physical link down, VSI %d error %d\n", - vsi->vsi_num, link_err); + if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) { + link_err = ice_force_phys_link_state(vsi, false); + if (link_err) + netdev_err(vsi->netdev, + "Failed to set physical link down, VSI %d error %d\n", + vsi->vsi_num, link_err); + } ice_for_each_txq(vsi, i) ice_clean_tx_ring(vsi->tx_rings[i]); -- cgit v1.2.3 From 03f7a986684597607de02f3023aa6c3657a78ab5 Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Wed, 19 Dec 2018 10:03:27 -0800 Subject: ice: Rework queue management code for reuse This patch reworks the queue management code to allow for reuse with the XDP feature (to be added in a future patch). Signed-off-by: Maciej Fijalkowski Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 11 ++ drivers/net/ethernet/intel/ice/ice_lib.c | 236 ++++++++++++----------- drivers/net/ethernet/intel/ice/ice_lib.h | 5 +- drivers/net/ethernet/intel/ice/ice_main.c | 6 +- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 24 ++- 5 files changed, 159 insertions(+), 123 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 8af882a2b070..ffe4ffe16912 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -129,6 +129,17 @@ struct ice_res_tracker { u16 list[1]; }; +struct ice_qs_cfg { + struct mutex *qs_mutex; /* will be assgined to &pf->avail_q_mutex */ + unsigned long *pf_map; + unsigned long pf_map_size; + unsigned int q_count; + unsigned int scatter_count; + u16 *vsi_map; + u16 vsi_map_offset; + u8 mapping_mode; +}; + struct ice_sw { struct ice_pf *pf; u16 sw_id; /* switch ID for this switch */ diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 3bd24173b39c..a1f523a9d39d 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -514,109 +514,88 @@ unlock_pf: } /** - * ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI - * @vsi: the VSI getting queues + * __ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI + * @qs_cfg: gathered variables needed for PF->VSI queues assignment * - * Return 0 on success and a negative value on error + * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap */ -static int ice_vsi_get_qs_contig(struct ice_vsi *vsi) +static int __ice_vsi_get_qs_contig(struct ice_qs_cfg *qs_cfg) { - struct ice_pf *pf = vsi->back; - int offset, ret = 0; - - mutex_lock(&pf->avail_q_mutex); - /* look for contiguous block of queues for Tx */ - offset = bitmap_find_next_zero_area(pf->avail_txqs, ICE_MAX_TXQS, - 0, vsi->alloc_txq, 0); - if (offset < ICE_MAX_TXQS) { - int i; + int offset, i; - bitmap_set(pf->avail_txqs, offset, vsi->alloc_txq); - for (i = 0; i < vsi->alloc_txq; i++) - vsi->txq_map[i] = i + offset; - } else { - ret = -ENOMEM; - vsi->tx_mapping_mode = ICE_VSI_MAP_SCATTER; + mutex_lock(qs_cfg->qs_mutex); + offset = bitmap_find_next_zero_area(qs_cfg->pf_map, qs_cfg->pf_map_size, + 0, qs_cfg->q_count, 0); + if (offset >= qs_cfg->pf_map_size) { + mutex_unlock(qs_cfg->qs_mutex); + return -ENOMEM; } - /* look for contiguous block of queues for Rx */ - offset = bitmap_find_next_zero_area(pf->avail_rxqs, ICE_MAX_RXQS, - 0, vsi->alloc_rxq, 0); - if (offset < ICE_MAX_RXQS) { - int i; - - bitmap_set(pf->avail_rxqs, offset, vsi->alloc_rxq); - for (i = 0; i < vsi->alloc_rxq; i++) - vsi->rxq_map[i] = i + offset; - } else { - ret = -ENOMEM; - vsi->rx_mapping_mode = ICE_VSI_MAP_SCATTER; - } - mutex_unlock(&pf->avail_q_mutex); + bitmap_set(qs_cfg->pf_map, offset, qs_cfg->q_count); + for (i = 0; i < qs_cfg->q_count; i++) + qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = i + offset; + mutex_unlock(qs_cfg->qs_mutex); - return ret; + return 0; } /** - * ice_vsi_get_qs_scatter - Assign a scattered queues to VSI - * @vsi: the VSI getting queues + * __ice_vsi_get_qs_sc - Assign a scattered queues from PF to VSI + * @qs_cfg: gathered variables needed for PF->VSI queues assignment * - * Return 0 on success and a negative value on error + * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap */ -static int ice_vsi_get_qs_scatter(struct ice_vsi *vsi) +static int __ice_vsi_get_qs_sc(struct ice_qs_cfg *qs_cfg) { - struct ice_pf *pf = vsi->back; int i, index = 0; - mutex_lock(&pf->avail_q_mutex); - - if (vsi->tx_mapping_mode == ICE_VSI_MAP_SCATTER) { - for (i = 0; i < vsi->alloc_txq; i++) { - index = find_next_zero_bit(pf->avail_txqs, - ICE_MAX_TXQS, index); - if (index < ICE_MAX_TXQS) { - set_bit(index, pf->avail_txqs); - vsi->txq_map[i] = index; - } else { - goto err_scatter_tx; - } - } - } - - if (vsi->rx_mapping_mode == ICE_VSI_MAP_SCATTER) { - for (i = 0; i < vsi->alloc_rxq; i++) { - index = find_next_zero_bit(pf->avail_rxqs, - ICE_MAX_RXQS, index); - if (index < ICE_MAX_RXQS) { - set_bit(index, pf->avail_rxqs); - vsi->rxq_map[i] = index; - } else { - goto err_scatter_rx; - } - } + mutex_lock(qs_cfg->qs_mutex); + for (i = 0; i < qs_cfg->q_count; i++) { + index = find_next_zero_bit(qs_cfg->pf_map, + qs_cfg->pf_map_size, index); + if (index >= qs_cfg->pf_map_size) + goto err_scatter; + set_bit(index, qs_cfg->pf_map); + qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = index; } + mutex_unlock(qs_cfg->qs_mutex); - mutex_unlock(&pf->avail_q_mutex); return 0; - -err_scatter_rx: - /* unflag any queues we have grabbed (i is failed position) */ +err_scatter: for (index = 0; index < i; index++) { - clear_bit(vsi->rxq_map[index], pf->avail_rxqs); - vsi->rxq_map[index] = 0; - } - i = vsi->alloc_txq; -err_scatter_tx: - /* i is either position of failed attempt or vsi->alloc_txq */ - for (index = 0; index < i; index++) { - clear_bit(vsi->txq_map[index], pf->avail_txqs); - vsi->txq_map[index] = 0; + clear_bit(qs_cfg->vsi_map[index], qs_cfg->pf_map); + qs_cfg->vsi_map[index + qs_cfg->vsi_map_offset] = 0; } + mutex_unlock(qs_cfg->qs_mutex); - mutex_unlock(&pf->avail_q_mutex); return -ENOMEM; } +/** + * __ice_vsi_get_qs - helper function for assigning queues from PF to VSI + * @qs_cfg: gathered variables needed for PF->VSI queues assignment + * + * This is an internal function for assigning queues from the PF to VSI and + * initially tries to find contiguous space. If it is not successful to find + * contiguous space, then it tries with the scatter approach. + * + * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap + */ +static int __ice_vsi_get_qs(struct ice_qs_cfg *qs_cfg) +{ + int ret = 0; + + ret = __ice_vsi_get_qs_contig(qs_cfg); + if (ret) { + /* contig failed, so try with scatter approach */ + qs_cfg->mapping_mode = ICE_VSI_MAP_SCATTER; + qs_cfg->q_count = min_t(u16, qs_cfg->q_count, + qs_cfg->scatter_count); + ret = __ice_vsi_get_qs_sc(qs_cfg); + } + return ret; +} + /** * ice_vsi_get_qs - Assign queues from PF to VSI * @vsi: the VSI to assign queues to @@ -625,25 +604,35 @@ err_scatter_tx: */ static int ice_vsi_get_qs(struct ice_vsi *vsi) { + struct ice_pf *pf = vsi->back; + struct ice_qs_cfg tx_qs_cfg = { + .qs_mutex = &pf->avail_q_mutex, + .pf_map = pf->avail_txqs, + .pf_map_size = ICE_MAX_TXQS, + .q_count = vsi->alloc_txq, + .scatter_count = ICE_MAX_SCATTER_TXQS, + .vsi_map = vsi->txq_map, + .vsi_map_offset = 0, + .mapping_mode = vsi->tx_mapping_mode + }; + struct ice_qs_cfg rx_qs_cfg = { + .qs_mutex = &pf->avail_q_mutex, + .pf_map = pf->avail_rxqs, + .pf_map_size = ICE_MAX_RXQS, + .q_count = vsi->alloc_rxq, + .scatter_count = ICE_MAX_SCATTER_RXQS, + .vsi_map = vsi->rxq_map, + .vsi_map_offset = 0, + .mapping_mode = vsi->rx_mapping_mode + }; int ret = 0; vsi->tx_mapping_mode = ICE_VSI_MAP_CONTIG; vsi->rx_mapping_mode = ICE_VSI_MAP_CONTIG; - /* NOTE: ice_vsi_get_qs_contig() will set the Rx/Tx mapping - * modes individually to scatter if assigning contiguous queues - * to Rx or Tx fails - */ - ret = ice_vsi_get_qs_contig(vsi); - if (ret < 0) { - if (vsi->tx_mapping_mode == ICE_VSI_MAP_SCATTER) - vsi->alloc_txq = max_t(u16, vsi->alloc_txq, - ICE_MAX_SCATTER_TXQS); - if (vsi->rx_mapping_mode == ICE_VSI_MAP_SCATTER) - vsi->alloc_rxq = max_t(u16, vsi->alloc_rxq, - ICE_MAX_SCATTER_RXQS); - ret = ice_vsi_get_qs_scatter(vsi); - } + ret = __ice_vsi_get_qs(&tx_qs_cfg); + if (!ret) + ret = __ice_vsi_get_qs(&rx_qs_cfg); return ret; } @@ -1614,11 +1603,14 @@ setup_rings: /** * ice_vsi_cfg_txqs - Configure the VSI for Tx * @vsi: the VSI being configured + * @rings: Tx ring array to be configured + * @offset: offset within vsi->txq_map * * Return 0 on success and a negative value on error * Configure the Tx VSI for operation. */ -int ice_vsi_cfg_txqs(struct ice_vsi *vsi) +static int +ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings, int offset) { struct ice_aqc_add_tx_qgrp *qg_buf; struct ice_aqc_add_txqs_perq *txq; @@ -1626,7 +1618,7 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi) u8 num_q_grps, q_idx = 0; enum ice_status status; u16 buf_len, i, pf_q; - int err = 0, tc = 0; + int err = 0, tc; buf_len = sizeof(struct ice_aqc_add_tx_qgrp); qg_buf = devm_kzalloc(&pf->pdev->dev, buf_len, GFP_KERNEL); @@ -1644,9 +1636,8 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi) for (i = 0; i < vsi->tc_cfg.tc_info[tc].qcount_tx; i++) { struct ice_tlan_ctx tlan_ctx = { 0 }; - pf_q = vsi->txq_map[q_idx]; - ice_setup_tx_ctx(vsi->tx_rings[q_idx], &tlan_ctx, - pf_q); + pf_q = vsi->txq_map[q_idx + offset]; + ice_setup_tx_ctx(rings[q_idx], &tlan_ctx, pf_q); /* copy context contents into the qg_buf */ qg_buf->txqs[0].txq_id = cpu_to_le16(pf_q); ice_set_ctx((u8 *)&tlan_ctx, qg_buf->txqs[0].txq_ctx, @@ -1655,7 +1646,7 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi) /* init queue specific tail reg. It is referred as * transmit comm scheduler queue doorbell. */ - vsi->tx_rings[q_idx]->tail = + rings[q_idx]->tail = pf->hw.hw_addr + QTX_COMM_DBELL(pf_q); status = ice_ena_vsi_txq(vsi->port_info, vsi->idx, tc, num_q_grps, qg_buf, buf_len, @@ -1674,7 +1665,7 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi) */ txq = &qg_buf->txqs[0]; if (pf_q == le16_to_cpu(txq->txq_id)) - vsi->tx_rings[q_idx]->txq_teid = + rings[q_idx]->txq_teid = le32_to_cpu(txq->q_teid); q_idx++; @@ -1685,6 +1676,18 @@ err_cfg_txqs: return err; } +/** + * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx + * @vsi: the VSI being configured + * + * Return 0 on success and a negative value on error + * Configure the Tx VSI for operation. + */ +int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi) +{ + return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, 0); +} + /** * ice_intrl_usec_to_reg - convert interrupt rate limit to register value * @intrl: interrupt rate limit in usecs @@ -1897,9 +1900,12 @@ int ice_vsi_stop_rx_rings(struct ice_vsi *vsi) * @vsi: the VSI being configured * @rst_src: reset source * @rel_vmvf_num: Relative id of VF/VM + * @rings: Tx ring array to be stopped + * @offset: offset within vsi->txq_map */ -int ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, - u16 rel_vmvf_num) +static int +ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, + u16 rel_vmvf_num, struct ice_ring **rings, int offset) { struct ice_pf *pf = vsi->back; struct ice_hw *hw = &pf->hw; @@ -1927,19 +1933,18 @@ int ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, ice_for_each_txq(vsi, i) { u16 v_idx; - if (!vsi->tx_rings || !vsi->tx_rings[i] || - !vsi->tx_rings[i]->q_vector) { + if (!rings || !rings[i] || !rings[i]->q_vector) { err = -EINVAL; goto err_out; } - q_ids[i] = vsi->txq_map[i]; - q_teids[i] = vsi->tx_rings[i]->txq_teid; + q_ids[i] = vsi->txq_map[i + offset]; + q_teids[i] = rings[i]->txq_teid; /* clear cause_ena bit for disabled queues */ - val = rd32(hw, QINT_TQCTL(vsi->tx_rings[i]->reg_idx)); + val = rd32(hw, QINT_TQCTL(rings[i]->reg_idx)); val &= ~QINT_TQCTL_CAUSE_ENA_M; - wr32(hw, QINT_TQCTL(vsi->tx_rings[i]->reg_idx), val); + wr32(hw, QINT_TQCTL(rings[i]->reg_idx), val); /* software is expected to wait for 100 ns */ ndelay(100); @@ -1947,7 +1952,7 @@ int ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, /* trigger a software interrupt for the vector associated to * the queue to schedule NAPI handler */ - v_idx = vsi->tx_rings[i]->q_vector->v_idx; + v_idx = rings[i]->q_vector->v_idx; wr32(hw, GLINT_DYN_CTL(vsi->hw_base_vector + v_idx), GLINT_DYN_CTL_SWINT_TRIG_M | GLINT_DYN_CTL_INTENA_MSK_M); } @@ -1976,6 +1981,19 @@ err_alloc_q_ids: return err; } +/** + * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings + * @vsi: the VSI being configured + * @rst_src: reset source + * @rel_vmvf_num: Relative id of VF/VM + */ +int ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, + enum ice_disq_rst_src rst_src, u16 rel_vmvf_num) +{ + return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings, + 0); +} + /** * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI * @vsi: VSI to enable or disable VLAN pruning on diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h index 3831b4f0960a..7988a53729a9 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_lib.h @@ -15,7 +15,7 @@ void ice_update_eth_stats(struct ice_vsi *vsi); int ice_vsi_cfg_rxqs(struct ice_vsi *vsi); -int ice_vsi_cfg_txqs(struct ice_vsi *vsi); +int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi); void ice_vsi_cfg_msix(struct ice_vsi *vsi); @@ -31,7 +31,8 @@ int ice_vsi_start_rx_rings(struct ice_vsi *vsi); int ice_vsi_stop_rx_rings(struct ice_vsi *vsi); -int ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, +int +ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, u16 rel_vmvf_num); int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index e36db981f047..093708b5c0ef 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2546,7 +2546,8 @@ static int ice_vsi_cfg(struct ice_vsi *vsi) if (err) return err; } - err = ice_vsi_cfg_txqs(vsi); + + err = ice_vsi_cfg_lan_txqs(vsi); if (!err) err = ice_vsi_cfg_rxqs(vsi); @@ -3040,7 +3041,8 @@ int ice_down(struct ice_vsi *vsi) } ice_vsi_dis_irq(vsi); - tx_err = ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0); + + tx_err = ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0); if (tx_err) netdev_err(vsi->netdev, "Failed stop Tx rings, VSI %d error %d\n", diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 05ff4f910649..80b50e67cbef 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -224,13 +224,15 @@ void ice_free_vfs(struct ice_pf *pf) /* Avoid wait time by stopping all VFs at the same time */ for (i = 0; i < pf->num_alloc_vfs; i++) { + struct ice_vsi *vsi; + if (!test_bit(ICE_VF_STATE_ENA, pf->vf[i].vf_states)) continue; + vsi = pf->vsi[pf->vf[i].lan_vsi_idx]; /* stop rings without wait time */ - ice_vsi_stop_tx_rings(pf->vsi[pf->vf[i].lan_vsi_idx], - ICE_NO_RESET, i); - ice_vsi_stop_rx_rings(pf->vsi[pf->vf[i].lan_vsi_idx]); + ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, i); + ice_vsi_stop_rx_rings(vsi); clear_bit(ICE_VF_STATE_ENA, pf->vf[i].vf_states); } @@ -831,6 +833,7 @@ static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) { struct ice_pf *pf = vf->pf; struct ice_hw *hw = &pf->hw; + struct ice_vsi *vsi; bool rsd = false; u32 reg; int i; @@ -843,17 +846,18 @@ static bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) ice_trigger_vf_reset(vf, is_vflr); + vsi = pf->vsi[vf->lan_vsi_idx]; + if (test_bit(ICE_VF_STATE_ENA, vf->vf_states)) { - ice_vsi_stop_tx_rings(pf->vsi[vf->lan_vsi_idx], ICE_VF_RESET, - vf->vf_id); - ice_vsi_stop_rx_rings(pf->vsi[vf->lan_vsi_idx]); + ice_vsi_stop_lan_tx_rings(vsi, ICE_VF_RESET, vf->vf_id); + ice_vsi_stop_rx_rings(vsi); clear_bit(ICE_VF_STATE_ENA, vf->vf_states); } else { /* Call Disable LAN Tx queue AQ call even when queues are not * enabled. This is needed for successful completiom of VFR */ - ice_dis_vsi_txq(pf->vsi[vf->lan_vsi_idx]->port_info, 0, - NULL, NULL, ICE_VF_RESET, vf->vf_id, NULL); + ice_dis_vsi_txq(vsi->port_info, 0, NULL, NULL, ICE_VF_RESET, + vf->vf_id, NULL); } /* poll VPGEN_VFRSTAT reg to make sure @@ -1614,7 +1618,7 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg) goto error_param; } - if (ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, vf->vf_id)) { + if (ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, vf->vf_id)) { dev_err(&vsi->back->pdev->dev, "Failed to stop tx rings on VSI %d\n", vsi->vsi_num); @@ -1784,7 +1788,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) vsi->num_txq = qci->num_queue_pairs; vsi->num_rxq = qci->num_queue_pairs; - if (!ice_vsi_cfg_txqs(vsi) && !ice_vsi_cfg_rxqs(vsi)) + if (!ice_vsi_cfg_lan_txqs(vsi) && !ice_vsi_cfg_rxqs(vsi)) aq_ret = 0; else aq_ret = ICE_ERR_PARAM; -- cgit v1.2.3 From 9be1d6f8c33731acd67586a4e40c0f3d56a23366 Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Wed, 19 Dec 2018 10:03:28 -0800 Subject: ice: Move aggregator list into ice_hw instance The aggregator list needs to be preserved for use after a reset. This patch moves it out of the port_info instance and into the ice_hw instance. Signed-off-by: Tarun Singh Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 2 ++ drivers/net/ethernet/intel/ice/ice_sched.c | 34 ++++++++++++++++++----------- drivers/net/ethernet/intel/ice/ice_sched.h | 2 ++ drivers/net/ethernet/intel/ice/ice_type.h | 2 +- 4 files changed, 26 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 2bcd8230d35e..19695749f903 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -750,6 +750,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw) status = ICE_ERR_CFG; goto err_unroll_sched; } + INIT_LIST_HEAD(&hw->agg_list); status = ice_init_fltr_mgmt_struct(hw); if (status) @@ -800,6 +801,7 @@ void ice_deinit_hw(struct ice_hw *hw) ice_cleanup_fltr_mgmt_struct(hw); ice_sched_cleanup_all(hw); + ice_sched_clear_agg(hw); if (hw->port_info) { devm_kfree(ice_hw_to_dev(hw), hw->port_info); diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index 99d51990bd54..fb38e8be1e2e 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -561,23 +561,18 @@ ice_sched_suspend_resume_elems(struct ice_hw *hw, u8 num_nodes, u32 *node_teids, } /** - * ice_sched_clear_tx_topo - clears the schduler tree nodes - * @pi: port information structure + * ice_sched_clear_agg - clears the agg related information + * @hw: pointer to the hardware structure * - * This function removes all the nodes from HW as well as from SW DB. + * This function removes agg list and free up agg related memory + * previously allocated. */ -static void ice_sched_clear_tx_topo(struct ice_port_info *pi) +void ice_sched_clear_agg(struct ice_hw *hw) { struct ice_sched_agg_info *agg_info; struct ice_sched_agg_info *atmp; - struct ice_hw *hw; - - if (!pi) - return; - hw = pi->hw; - - list_for_each_entry_safe(agg_info, atmp, &pi->agg_list, list_entry) { + list_for_each_entry_safe(agg_info, atmp, &hw->agg_list, list_entry) { struct ice_sched_agg_vsi_info *agg_vsi_info; struct ice_sched_agg_vsi_info *vtmp; @@ -586,8 +581,21 @@ static void ice_sched_clear_tx_topo(struct ice_port_info *pi) list_del(&agg_vsi_info->list_entry); devm_kfree(ice_hw_to_dev(hw), agg_vsi_info); } + list_del(&agg_info->list_entry); + devm_kfree(ice_hw_to_dev(hw), agg_info); } +} +/** + * ice_sched_clear_tx_topo - clears the scheduler tree nodes + * @pi: port information structure + * + * This function removes all the nodes from HW as well as from SW DB. + */ +static void ice_sched_clear_tx_topo(struct ice_port_info *pi) +{ + if (!pi) + return; if (pi->root) { ice_free_sched_node(pi, pi->root); pi->root = NULL; @@ -1005,7 +1013,6 @@ enum ice_status ice_sched_init_port(struct ice_port_info *pi) /* initialize the port for handling the scheduler tree */ pi->port_state = ICE_SCHED_PORT_STATE_READY; mutex_init(&pi->sched_lock); - INIT_LIST_HEAD(&pi->agg_list); err_init_port: if (status && pi->root) { @@ -1588,7 +1595,8 @@ ice_sched_rm_agg_vsi_info(struct ice_port_info *pi, u16 vsi_handle) struct ice_sched_agg_info *agg_info; struct ice_sched_agg_info *atmp; - list_for_each_entry_safe(agg_info, atmp, &pi->agg_list, list_entry) { + list_for_each_entry_safe(agg_info, atmp, &pi->hw->agg_list, + list_entry) { struct ice_sched_agg_vsi_info *agg_vsi_info; struct ice_sched_agg_vsi_info *vtmp; diff --git a/drivers/net/ethernet/intel/ice/ice_sched.h b/drivers/net/ethernet/intel/ice/ice_sched.h index da5b4c166da8..bee8221ad146 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.h +++ b/drivers/net/ethernet/intel/ice/ice_sched.h @@ -28,6 +28,8 @@ enum ice_status ice_sched_init_port(struct ice_port_info *pi); enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw); void ice_sched_clear_port(struct ice_port_info *pi); void ice_sched_cleanup_all(struct ice_hw *hw); +void ice_sched_clear_agg(struct ice_hw *hw); + struct ice_sched_node * ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid); enum ice_status diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 0ea428104215..a078e2c98871 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -272,7 +272,6 @@ struct ice_port_info { struct ice_mac_info mac; struct ice_phy_info phy; struct mutex sched_lock; /* protect access to TXSched tree */ - struct list_head agg_list; /* lists all aggregator */ u8 lport; #define ICE_LPORT_MASK 0xff u8 is_vf; @@ -326,6 +325,7 @@ struct ice_hw { u8 max_cgds; u8 sw_entry_point_layer; u16 max_children[ICE_AQC_TOPO_MAX_LEVEL_NUM]; + struct list_head agg_list; /* lists all aggregator */ struct ice_vsi_ctx *vsi_ctx[ICE_MAX_VSI]; u8 evb_veb; /* true for VEB, false for VEPA */ -- cgit v1.2.3 From 63f545ed1285a5f904c260ff22c958609c3c11c5 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Wed, 19 Dec 2018 10:03:29 -0800 Subject: ice: Add support for adaptive interrupt moderation Currently the driver does not support adaptive/dynamic interrupt moderation. This patch adds support for this. Also, adaptive/dynamic interrupt moderation is turned on by default upon driver load. In order to support adaptive interrupt moderation, two functions were added, ice_update_itr() and ice_itr_divisor(). These are used to determine the current packet load and to determine a divisor based on link speed respectively. This patch also adds the ICE_ITR_GRAN_S define that is used in the hot-path when setting a new ITR value. The shift is used to pet two birds with one hand, set the ITR value while re-enabling the interrupt. Also, the ICE_ITR_GRAN_S is defined as 1 because the device has a ITR granularity of 2usecs. Signed-off-by: Brett Creeley Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_hw_autogen.h | 1 + drivers/net/ethernet/intel/ice/ice_lib.c | 24 ++++++--- drivers/net/ethernet/intel/ice/ice_main.c | 23 +++++++-- drivers/net/ethernet/intel/ice/ice_txrx.c | 65 ++++++++++++++++++++++++- drivers/net/ethernet/intel/ice/ice_txrx.h | 30 +++++++----- 5 files changed, 120 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index 5507928c8fbe..f9a38f2cd470 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -110,6 +110,7 @@ #define GLINT_DYN_CTL_CLEARPBA_M BIT(1) #define GLINT_DYN_CTL_SWINT_TRIG_M BIT(2) #define GLINT_DYN_CTL_ITR_INDX_S 3 +#define GLINT_DYN_CTL_INTERVAL_S 5 #define GLINT_DYN_CTL_SW_ITR_INDX_M ICE_M(0x3, 25) #define GLINT_DYN_CTL_INTENA_MSK_M BIT(31) #define GLINT_ITR(_i, _INT) (0x00154000 + ((_i) * 8192 + (_INT) * 4)) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index a1f523a9d39d..27c3760ae5cb 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1717,22 +1717,34 @@ static u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran) static void ice_cfg_itr(struct ice_hw *hw, struct ice_q_vector *q_vector, u16 vector) { - u8 itr_gran = hw->itr_gran; - if (q_vector->num_ring_rx) { struct ice_ring_container *rc = &q_vector->rx; - rc->itr = ITR_TO_REG(ICE_DFLT_RX_ITR, itr_gran); + /* if this value is set then don't overwrite with default */ + if (!rc->itr_setting) + rc->itr_setting = ICE_DFLT_RX_ITR; + + rc->target_itr = ITR_TO_REG(rc->itr_setting); + rc->next_update = jiffies + 1; + rc->current_itr = rc->target_itr; rc->latency_range = ICE_LOW_LATENCY; - wr32(hw, GLINT_ITR(rc->itr_idx, vector), rc->itr); + wr32(hw, GLINT_ITR(rc->itr_idx, vector), + ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S); } if (q_vector->num_ring_tx) { struct ice_ring_container *rc = &q_vector->tx; - rc->itr = ITR_TO_REG(ICE_DFLT_TX_ITR, itr_gran); + /* if this value is set then don't overwrite with default */ + if (!rc->itr_setting) + rc->itr_setting = ICE_DFLT_TX_ITR; + + rc->target_itr = ITR_TO_REG(rc->itr_setting); + rc->next_update = jiffies + 1; + rc->current_itr = rc->target_itr; rc->latency_range = ICE_LOW_LATENCY; - wr32(hw, GLINT_ITR(rc->itr_idx, vector), rc->itr); + wr32(hw, GLINT_ITR(rc->itr_idx, vector), + ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S); } } diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 093708b5c0ef..e59f8b29af49 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1389,7 +1389,6 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) { struct ice_hw *hw = &pf->hw; int oicr_idx, err = 0; - u8 itr_gran; u32 val; if (!pf->int_name[0]) @@ -1453,10 +1452,8 @@ skip_req_irq: PFINT_MBX_CTL_CAUSE_ENA_M); wr32(hw, PFINT_MBX_CTL, val); - itr_gran = hw->itr_gran; - wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx), - ITR_TO_REG(ICE_ITR_8K, itr_gran)); + ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); ice_flush(hw); ice_irq_dynamic_ena(hw, NULL, NULL); @@ -1997,6 +1994,23 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf) return 0; } +/** + * ice_verify_itr_gran - verify driver's assumption of ITR granularity + * @pf: pointer to the PF structure + * + * There is no error returned here because the driver will be able to handle a + * different ITR granularity, but interrupt moderation will not be accurate if + * the driver's assumptions are not verified. This assumption is made so we can + * use constants in the hot path instead of accessing structure members. + */ +static void ice_verify_itr_gran(struct ice_pf *pf) +{ + if (pf->hw.itr_gran != (ICE_ITR_GRAN_S << 1)) + dev_warn(&pf->pdev->dev, + "%d ITR granularity assumption is invalid, actual ITR granularity is %d. Interrupt moderation will be inaccurate!\n", + (ICE_ITR_GRAN_S << 1), pf->hw.itr_gran); +} + /** * ice_verify_cacheline_size - verify driver's assumption of 64 Byte cache lines * @pf: pointer to the PF structure @@ -2163,6 +2177,7 @@ static int ice_probe(struct pci_dev *pdev, mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period)); ice_verify_cacheline_size(pf); + ice_verify_itr_gran(pf); return 0; diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 49fc38094185..384ac5c82e00 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1052,6 +1052,69 @@ static int ice_clean_rx_irq(struct ice_ring *rx_ring, int budget) return failure ? budget : (int)total_rx_pkts; } +/** + * ice_buildreg_itr - build value for writing to the GLINT_DYN_CTL register + * @itr_idx: interrupt throttling index + * @reg_itr: interrupt throttling value adjusted based on ITR granularity + */ +static u32 ice_buildreg_itr(int itr_idx, u16 reg_itr) +{ + return GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M | + (itr_idx << GLINT_DYN_CTL_ITR_INDX_S) | + (reg_itr << GLINT_DYN_CTL_INTERVAL_S); +} + +/** + * ice_update_ena_itr - Update ITR and re-enable MSIX interrupt + * @vsi: the VSI associated with the q_vector + * @q_vector: q_vector for which ITR is being updated and interrupt enabled + */ +static void +ice_update_ena_itr(struct ice_vsi *vsi, struct ice_q_vector *q_vector) +{ + struct ice_hw *hw = &vsi->back->hw; + struct ice_ring_container *rc; + u32 itr_val; + + /* This block of logic allows us to get away with only updating + * one ITR value with each interrupt. The idea is to perform a + * pseudo-lazy update with the following criteria. + * + * 1. Rx is given higher priority than Tx if both are in same state + * 2. If we must reduce an ITR that is given highest priority. + * 3. We then give priority to increasing ITR based on amount. + */ + if (q_vector->rx.target_itr < q_vector->rx.current_itr) { + rc = &q_vector->rx; + /* Rx ITR needs to be reduced, this is highest priority */ + itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr); + rc->current_itr = rc->target_itr; + } else if ((q_vector->tx.target_itr < q_vector->tx.current_itr) || + ((q_vector->rx.target_itr - q_vector->rx.current_itr) < + (q_vector->tx.target_itr - q_vector->tx.current_itr))) { + rc = &q_vector->tx; + /* Tx ITR needs to be reduced, this is second priority + * Tx ITR needs to be increased more than Rx, fourth priority + */ + itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr); + rc->current_itr = rc->target_itr; + } else if (q_vector->rx.current_itr != q_vector->rx.target_itr) { + rc = &q_vector->rx; + /* Rx ITR needs to be increased, third priority */ + itr_val = ice_buildreg_itr(rc->itr_idx, rc->target_itr); + rc->current_itr = rc->target_itr; + } else { + /* Still have to re-enable the interrupts */ + itr_val = ice_buildreg_itr(ICE_ITR_NONE, 0); + } + + if (!test_bit(__ICE_DOWN, vsi->state)) { + int vector = vsi->hw_base_vector + q_vector->v_idx; + + wr32(hw, GLINT_DYN_CTL(vector), itr_val); + } +} + /** * ice_napi_poll - NAPI polling Rx/Tx cleanup routine * @napi: napi struct with our devices info in it @@ -1108,7 +1171,7 @@ int ice_napi_poll(struct napi_struct *napi, int budget) */ if (likely(napi_complete_done(napi, work_done))) if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) - ice_irq_dynamic_ena(&vsi->back->hw, vsi, q_vector); + ice_update_ena_itr(vsi, q_vector); return min(work_done, budget - 1); } diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h index 75d0eaf6c9dd..aa646002d653 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.h +++ b/drivers/net/ethernet/intel/ice/ice_txrx.h @@ -116,16 +116,15 @@ enum ice_rx_dtype { /* indices into GLINT_ITR registers */ #define ICE_RX_ITR ICE_IDX_ITR0 #define ICE_TX_ITR ICE_IDX_ITR1 -#define ICE_ITR_DYNAMIC 0x8000 /* use top bit as a flag */ -#define ICE_ITR_8K 125 +#define ICE_ITR_8K 124 #define ICE_ITR_20K 50 -#define ICE_DFLT_TX_ITR ICE_ITR_20K -#define ICE_DFLT_RX_ITR ICE_ITR_20K -/* apply ITR granularity translation to program the register. itr_gran is either - * 2 or 4 usecs so we need to divide by 2 first then shift by that value - */ -#define ITR_TO_REG(val, itr_gran) (((val) & ~ICE_ITR_DYNAMIC) >> \ - ((itr_gran) / 2)) +#define ICE_DFLT_TX_ITR (ICE_ITR_20K | ICE_ITR_DYNAMIC) +#define ICE_DFLT_RX_ITR (ICE_ITR_20K | ICE_ITR_DYNAMIC) +#define ICE_ITR_DYNAMIC 0x8000 /* used as flag for itr_setting */ +#define ITR_TO_REG(setting) ((setting) & ~ICE_ITR_DYNAMIC) +#define ICE_ITR_GRAN_S 1 /* Assume ITR granularity is 2us */ +#define ICE_ITR_MASK 0x1FFE /* ITR register value alignment mask */ +#define ITR_REG_ALIGN(setting) __ALIGN_MASK(setting, ~ICE_ITR_MASK) #define ICE_DFLT_INTRL 0 @@ -180,13 +179,20 @@ enum ice_latency_range { }; struct ice_ring_container { - /* array of pointers to rings */ + /* head of linked-list of rings */ struct ice_ring *ring; + unsigned long next_update; /* jiffies value of next queue update */ unsigned int total_bytes; /* total bytes processed this int */ unsigned int total_pkts; /* total packets processed this int */ enum ice_latency_range latency_range; - int itr_idx; /* index in the interrupt vector */ - u16 itr; + int itr_idx; /* index in the interrupt vector */ + u16 target_itr; /* value in usecs divided by the hw->itr_gran */ + u16 current_itr; /* value in usecs divided by the hw->itr_gran */ + /* high bit set means dynamic ITR, rest is used to store user + * readable ITR value in usecs and must be converted before programming + * to a register. + */ + u16 itr_setting; }; /* iterator for handling rings in ring container */ -- cgit v1.2.3 From 67fe64d78c437d3f5a280a074e8467fa9b16216d Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Wed, 19 Dec 2018 10:03:30 -0800 Subject: ice: Implement getting and setting ethtool coalesce This patch includes the following ethtool operations: 1. get_coalesce 2. set_coalesce 3. get_per_q_coalesce 4. set_per_q_coalesce Each ITR value (current_itr/target_itr) are stored on a per ice_ring_container basis. This is because each valid ice_ring_container can have 1 or more rings that are tied to the same q_vector ITR index. Signed-off-by: Brett Creeley Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 3 + drivers/net/ethernet/intel/ice/ice_ethtool.c | 256 +++++++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_txrx.h | 2 + 3 files changed, 261 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index ffe4ffe16912..ac8bf7491d08 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -110,6 +110,9 @@ extern const char ice_drv_ver[]; #define ice_for_each_alloc_rxq(vsi, i) \ for ((i) = 0; (i) < (vsi)->alloc_rxq; (i)++) +#define ice_for_each_q_vector(vsi, i) \ + for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++) + struct ice_tc_info { u16 qoffset; u16 qcount_tx; diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 24c8aeaea2d5..02316e32dfb3 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -1823,6 +1823,258 @@ static int ice_set_rxfh(struct net_device *netdev, const u32 *indir, return 0; } +enum ice_container_type { + ICE_RX_CONTAINER, + ICE_TX_CONTAINER, +}; + +/** + * ice_get_rc_coalesce - get ITR values for specific ring container + * @ec: ethtool structure to fill with driver's coalesce settings + * @c_type: container type, RX or TX + * @rc: ring container that the ITR values will come from + * + * Query the device for ice_ring_container specific ITR values. This is + * done per ice_ring_container because each q_vector can have 1 or more rings + * and all of said ring(s) will have the same ITR values. + * + * Returns 0 on success, negative otherwise. + */ +static int +ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, + struct ice_ring_container *rc) +{ + struct ice_pf *pf = rc->ring->vsi->back; + + switch (c_type) { + case ICE_RX_CONTAINER: + ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); + ec->rx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; + break; + case ICE_TX_CONTAINER: + ec->use_adaptive_tx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); + ec->tx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; + break; + default: + dev_dbg(&pf->pdev->dev, "Invalid c_type %d\n", c_type); + return -EINVAL; + } + + return 0; +} + +/** + * __ice_get_coalesce - get ITR/INTRL values for the device + * @netdev: pointer to the netdev associated with this query + * @ec: ethtool structure to fill with driver's coalesce settings + * @q_num: queue number to get the coalesce settings for + */ +static int +__ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, + int q_num) +{ + struct ice_netdev_priv *np = netdev_priv(netdev); + int tx = -EINVAL, rx = -EINVAL; + struct ice_vsi *vsi = np->vsi; + + if (q_num < 0) { + rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, + &vsi->rx_rings[0]->q_vector->rx); + tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, + &vsi->tx_rings[0]->q_vector->tx); + + goto update_coalesced_frames; + } + + if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { + rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, + &vsi->rx_rings[q_num]->q_vector->rx); + tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, + &vsi->tx_rings[q_num]->q_vector->tx); + } else if (q_num < vsi->num_rxq) { + rx = ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, + &vsi->rx_rings[q_num]->q_vector->rx); + } else if (q_num < vsi->num_txq) { + tx = ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, + &vsi->tx_rings[q_num]->q_vector->tx); + } else { + /* q_num is invalid for both Rx and Tx queues */ + return -EINVAL; + } + +update_coalesced_frames: + /* either q_num is invalid for both Rx and Tx queues or setting coalesce + * failed completely + */ + if (tx && rx) + return -EINVAL; + + if (q_num < vsi->num_txq) + ec->tx_max_coalesced_frames_irq = vsi->work_lmt; + + if (q_num < vsi->num_rxq) + ec->rx_max_coalesced_frames_irq = vsi->work_lmt; + + return 0; +} + +static int +ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) +{ + return __ice_get_coalesce(netdev, ec, -1); +} + +static int ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num, + struct ethtool_coalesce *ec) +{ + return __ice_get_coalesce(netdev, ec, q_num); +} + +/** + * ice_set_rc_coalesce - set ITR values for specific ring container + * @c_type: container type, RX or TX + * @ec: ethtool structure from user to update ITR settings + * @rc: ring container that the ITR values will come from + * @vsi: VSI associated to the ring container + * + * Set specific ITR values. This is done per ice_ring_container because each + * q_vector can have 1 or more rings and all of said ring(s) will have the same + * ITR values. + * + * Returns 0 on success, negative otherwise. + */ +static int +ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec, + struct ice_ring_container *rc, struct ice_vsi *vsi) +{ + struct ice_pf *pf = vsi->back; + u16 itr_setting; + + if (!rc->ring) + return -EINVAL; + + itr_setting = rc->itr_setting & ~ICE_ITR_DYNAMIC; + + switch (c_type) { + case ICE_RX_CONTAINER: + if (ec->rx_coalesce_usecs != itr_setting && + ec->use_adaptive_rx_coalesce) { + netdev_info(vsi->netdev, + "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n"); + return -EINVAL; + } + + if (ec->rx_coalesce_usecs > ICE_ITR_MAX) { + netdev_info(vsi->netdev, + "Invalid value, rx-usecs range is 0-%d\n", + ICE_ITR_MAX); + return -EINVAL; + } + + if (ec->use_adaptive_rx_coalesce) { + rc->itr_setting |= ICE_ITR_DYNAMIC; + } else { + rc->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs); + rc->target_itr = ITR_TO_REG(rc->itr_setting); + } + break; + case ICE_TX_CONTAINER: + if (ec->tx_coalesce_usecs != itr_setting && + ec->use_adaptive_tx_coalesce) { + netdev_info(vsi->netdev, + "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n"); + return -EINVAL; + } + + if (ec->tx_coalesce_usecs > ICE_ITR_MAX) { + netdev_info(vsi->netdev, + "Invalid value, tx-usecs range is 0-%d\n", + ICE_ITR_MAX); + return -EINVAL; + } + + if (ec->use_adaptive_tx_coalesce) { + rc->itr_setting |= ICE_ITR_DYNAMIC; + } else { + rc->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs); + rc->target_itr = ITR_TO_REG(rc->itr_setting); + } + break; + default: + dev_dbg(&pf->pdev->dev, "Invalid container type %d\n", c_type); + return -EINVAL; + } + + return 0; +} + +static int +__ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, + int q_num) +{ + struct ice_netdev_priv *np = netdev_priv(netdev); + int rx = -EINVAL, tx = -EINVAL; + struct ice_vsi *vsi = np->vsi; + + if (q_num < 0) { + int i; + + ice_for_each_q_vector(vsi, i) { + struct ice_q_vector *q_vector = vsi->q_vectors[i]; + + if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, + &q_vector->rx, vsi) || + ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, + &q_vector->tx, vsi)) + return -EINVAL; + } + + goto set_work_lmt; + } + + if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { + rx = ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, + &vsi->rx_rings[q_num]->q_vector->rx, + vsi); + tx = ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, + &vsi->tx_rings[q_num]->q_vector->tx, + vsi); + } else if (q_num < vsi->num_rxq) { + rx = ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, + &vsi->rx_rings[q_num]->q_vector->rx, + vsi); + } else if (q_num < vsi->num_txq) { + tx = ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, + &vsi->tx_rings[q_num]->q_vector->tx, + vsi); + } + + /* either q_num is invalid for both Rx and Tx queues or setting coalesce + * failed completely + */ + if (rx && tx) + return -EINVAL; + +set_work_lmt: + if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) + vsi->work_lmt = max(ec->tx_max_coalesced_frames_irq, + ec->rx_max_coalesced_frames_irq); + + return 0; +} + +static int +ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) +{ + return __ice_set_coalesce(netdev, ec, -1); +} + +static int ice_set_per_q_coalesce(struct net_device *netdev, u32 q_num, + struct ethtool_coalesce *ec) +{ + return __ice_set_coalesce(netdev, ec, q_num); +} + static const struct ethtool_ops ice_ethtool_ops = { .get_link_ksettings = ice_get_link_ksettings, .set_link_ksettings = ice_set_link_ksettings, @@ -1834,6 +2086,8 @@ static const struct ethtool_ops ice_ethtool_ops = { .get_link = ethtool_op_get_link, .get_eeprom_len = ice_get_eeprom_len, .get_eeprom = ice_get_eeprom, + .get_coalesce = ice_get_coalesce, + .set_coalesce = ice_set_coalesce, .get_strings = ice_get_strings, .set_phys_id = ice_set_phys_id, .get_ethtool_stats = ice_get_ethtool_stats, @@ -1850,6 +2104,8 @@ static const struct ethtool_ops ice_ethtool_ops = { .get_rxfh_indir_size = ice_get_rxfh_indir_size, .get_rxfh = ice_get_rxfh, .set_rxfh = ice_set_rxfh, + .get_per_queue_coalesce = ice_get_per_q_coalesce, + .set_per_queue_coalesce = ice_set_per_q_coalesce, }; /** diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h index aa646002d653..fc358ea81816 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.h +++ b/drivers/net/ethernet/intel/ice/ice_txrx.h @@ -118,9 +118,11 @@ enum ice_rx_dtype { #define ICE_TX_ITR ICE_IDX_ITR1 #define ICE_ITR_8K 124 #define ICE_ITR_20K 50 +#define ICE_ITR_MAX 8160 #define ICE_DFLT_TX_ITR (ICE_ITR_20K | ICE_ITR_DYNAMIC) #define ICE_DFLT_RX_ITR (ICE_ITR_20K | ICE_ITR_DYNAMIC) #define ICE_ITR_DYNAMIC 0x8000 /* used as flag for itr_setting */ +#define ITR_IS_DYNAMIC(setting) (!!((setting) & ICE_ITR_DYNAMIC)) #define ITR_TO_REG(setting) ((setting) & ~ICE_ITR_DYNAMIC) #define ICE_ITR_GRAN_S 1 /* Assume ITR granularity is 2us */ #define ICE_ITR_MASK 0x1FFE /* ITR register value alignment mask */ -- cgit v1.2.3 From a8939784a17a54566e8d8ab26e9a9c36e4598281 Mon Sep 17 00:00:00 2001 From: Tony Nguyen Date: Wed, 19 Dec 2018 10:03:31 -0800 Subject: ice: Allow for software timestamping Use ethtool_op_get_ts_info to provide software timestamping. Signed-off-by: Tony Nguyen Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 02316e32dfb3..1f6a5f073e91 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -2104,6 +2104,7 @@ static const struct ethtool_ops ice_ethtool_ops = { .get_rxfh_indir_size = ice_get_rxfh_indir_size, .get_rxfh = ice_get_rxfh, .set_rxfh = ice_set_rxfh, + .get_ts_info = ethtool_op_get_ts_info, .get_per_queue_coalesce = ice_get_per_q_coalesce, .set_per_queue_coalesce = ice_set_per_q_coalesce, }; -- cgit v1.2.3 From cf909e19acf373a2e1d9bd877846a11bc8e20a54 Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Wed, 19 Dec 2018 10:03:32 -0800 Subject: ice: Offload SCTP checksum This patch adds the ability to offload SCTP checksum calculations to the NIC. Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 1 + drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h | 1 + drivers/net/ethernet/intel/ice/ice_main.c | 1 + drivers/net/ethernet/intel/ice/ice_txrx.c | 6 ++++++ 4 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index ac8bf7491d08..55944e089558 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h index bb51dd7defb5..bd7c01db8c63 100644 --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h @@ -346,6 +346,7 @@ enum ice_tx_desc_cmd_bits { ICE_TX_DESC_CMD_IIPT_IPV4 = 0x0040, /* 2 BITS */ ICE_TX_DESC_CMD_IIPT_IPV4_CSUM = 0x0060, /* 2 BITS */ ICE_TX_DESC_CMD_L4T_EOFT_TCP = 0x0100, /* 2 BITS */ + ICE_TX_DESC_CMD_L4T_EOFT_SCTP = 0x0200, /* 2 BITS */ ICE_TX_DESC_CMD_L4T_EOFT_UDP = 0x0300, /* 2 BITS */ }; diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index e59f8b29af49..f4bf6bda32a9 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1528,6 +1528,7 @@ static int ice_cfg_netdev(struct ice_vsi *vsi) csumo_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM | + NETIF_F_SCTP_CRC | NETIF_F_IPV6_CSUM; vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER | diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 384ac5c82e00..2357fcac996b 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1465,6 +1465,12 @@ int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off) offset |= l4_len << ICE_TX_DESC_LEN_L4_LEN_S; break; case IPPROTO_SCTP: + /* enable SCTP checksum offload */ + cmd |= ICE_TX_DESC_CMD_L4T_EOFT_SCTP; + l4_len = sizeof(struct sctphdr) >> 2; + offset |= l4_len << ICE_TX_DESC_LEN_L4_LEN_S; + break; + default: if (first->tx_flags & ICE_TX_FLAGS_TSO) return -1; -- cgit v1.2.3 From aef74145f088478aa4ff3834395015b6a742c15a Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Wed, 19 Dec 2018 10:03:33 -0800 Subject: ice: Add support for new PHY types This patch adds code for the detection and operation of several additional PHY types that support higher link speeds. Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_adminq_cmd.h | 39 +++- drivers/net/ethernet/intel/ice/ice_common.c | 124 ++++++++++- drivers/net/ethernet/intel/ice/ice_common.h | 3 +- drivers/net/ethernet/intel/ice/ice_ethtool.c | 262 +++++++++++++++++++++++- drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h | 2 + drivers/net/ethernet/intel/ice/ice_sriov.c | 9 + drivers/net/ethernet/intel/ice/ice_type.h | 2 + 7 files changed, 418 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 526224ede3fa..242c78469181 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -847,7 +847,42 @@ struct ice_aqc_get_phy_caps { #define ICE_PHY_TYPE_LOW_40GBASE_KR4 BIT_ULL(33) #define ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC BIT_ULL(34) #define ICE_PHY_TYPE_LOW_40G_XLAUI BIT_ULL(35) +#define ICE_PHY_TYPE_LOW_50GBASE_CR2 BIT_ULL(36) +#define ICE_PHY_TYPE_LOW_50GBASE_SR2 BIT_ULL(37) +#define ICE_PHY_TYPE_LOW_50GBASE_LR2 BIT_ULL(38) +#define ICE_PHY_TYPE_LOW_50GBASE_KR2 BIT_ULL(39) +#define ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC BIT_ULL(40) +#define ICE_PHY_TYPE_LOW_50G_LAUI2 BIT_ULL(41) +#define ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC BIT_ULL(42) +#define ICE_PHY_TYPE_LOW_50G_AUI2 BIT_ULL(43) +#define ICE_PHY_TYPE_LOW_50GBASE_CP BIT_ULL(44) +#define ICE_PHY_TYPE_LOW_50GBASE_SR BIT_ULL(45) +#define ICE_PHY_TYPE_LOW_50GBASE_FR BIT_ULL(46) +#define ICE_PHY_TYPE_LOW_50GBASE_LR BIT_ULL(47) +#define ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4 BIT_ULL(48) +#define ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC BIT_ULL(49) +#define ICE_PHY_TYPE_LOW_50G_AUI1 BIT_ULL(50) +#define ICE_PHY_TYPE_LOW_100GBASE_CR4 BIT_ULL(51) +#define ICE_PHY_TYPE_LOW_100GBASE_SR4 BIT_ULL(52) +#define ICE_PHY_TYPE_LOW_100GBASE_LR4 BIT_ULL(53) +#define ICE_PHY_TYPE_LOW_100GBASE_KR4 BIT_ULL(54) +#define ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC BIT_ULL(55) +#define ICE_PHY_TYPE_LOW_100G_CAUI4 BIT_ULL(56) +#define ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC BIT_ULL(57) +#define ICE_PHY_TYPE_LOW_100G_AUI4 BIT_ULL(58) +#define ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 BIT_ULL(59) +#define ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 BIT_ULL(60) +#define ICE_PHY_TYPE_LOW_100GBASE_CP2 BIT_ULL(61) +#define ICE_PHY_TYPE_LOW_100GBASE_SR2 BIT_ULL(62) +#define ICE_PHY_TYPE_LOW_100GBASE_DR BIT_ULL(63) #define ICE_PHY_TYPE_LOW_MAX_INDEX 63 +/* The second set of defines is for phy_type_high. */ +#define ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4 BIT_ULL(0) +#define ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC BIT_ULL(1) +#define ICE_PHY_TYPE_HIGH_100G_CAUI2 BIT_ULL(2) +#define ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC BIT_ULL(3) +#define ICE_PHY_TYPE_HIGH_100G_AUI2 BIT_ULL(4) +#define ICE_PHY_TYPE_HIGH_MAX_INDEX 19 struct ice_aqc_get_phy_caps_data { __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */ @@ -1025,10 +1060,12 @@ struct ice_aqc_get_link_status_data { #define ICE_AQ_LINK_SPEED_20GB BIT(6) #define ICE_AQ_LINK_SPEED_25GB BIT(7) #define ICE_AQ_LINK_SPEED_40GB BIT(8) +#define ICE_AQ_LINK_SPEED_50GB BIT(9) +#define ICE_AQ_LINK_SPEED_100GB BIT(10) #define ICE_AQ_LINK_SPEED_UNKNOWN BIT(15) __le32 reserved3; /* Aligns next field to 8-byte boundary */ __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */ - __le64 reserved4; + __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */ }; /* Set event mask command (direct 0x0613) */ diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 19695749f903..ab308fc88920 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -165,8 +165,10 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode, cmd->param0 |= cpu_to_le16(report_mode); status = ice_aq_send_cmd(pi->hw, &desc, pcaps, pcaps_size, cd); - if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP) + if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP) { pi->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low); + pi->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high); + } return status; } @@ -183,6 +185,9 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi) return ICE_MEDIA_UNKNOWN; hw_link_info = &pi->phy.link_info; + if (hw_link_info->phy_type_low && hw_link_info->phy_type_high) + /* If more than one media type is selected, report unknown */ + return ICE_MEDIA_UNKNOWN; if (hw_link_info->phy_type_low) { switch (hw_link_info->phy_type_low) { @@ -196,6 +201,15 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi) case ICE_PHY_TYPE_LOW_25G_AUI_C2C: case ICE_PHY_TYPE_LOW_40GBASE_SR4: case ICE_PHY_TYPE_LOW_40GBASE_LR4: + case ICE_PHY_TYPE_LOW_50GBASE_SR2: + case ICE_PHY_TYPE_LOW_50GBASE_LR2: + case ICE_PHY_TYPE_LOW_50GBASE_SR: + case ICE_PHY_TYPE_LOW_50GBASE_FR: + case ICE_PHY_TYPE_LOW_50GBASE_LR: + case ICE_PHY_TYPE_LOW_100GBASE_SR4: + case ICE_PHY_TYPE_LOW_100GBASE_LR4: + case ICE_PHY_TYPE_LOW_100GBASE_SR2: + case ICE_PHY_TYPE_LOW_100GBASE_DR: return ICE_MEDIA_FIBER; case ICE_PHY_TYPE_LOW_100BASE_TX: case ICE_PHY_TYPE_LOW_1000BASE_T: @@ -209,6 +223,11 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi) case ICE_PHY_TYPE_LOW_25GBASE_CR_S: case ICE_PHY_TYPE_LOW_25GBASE_CR1: case ICE_PHY_TYPE_LOW_40GBASE_CR4: + case ICE_PHY_TYPE_LOW_50GBASE_CR2: + case ICE_PHY_TYPE_LOW_50GBASE_CP: + case ICE_PHY_TYPE_LOW_100GBASE_CR4: + case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: + case ICE_PHY_TYPE_LOW_100GBASE_CP2: return ICE_MEDIA_DA; case ICE_PHY_TYPE_LOW_1000BASE_KX: case ICE_PHY_TYPE_LOW_2500BASE_KX: @@ -219,10 +238,18 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi) case ICE_PHY_TYPE_LOW_25GBASE_KR1: case ICE_PHY_TYPE_LOW_25GBASE_KR_S: case ICE_PHY_TYPE_LOW_40GBASE_KR4: + case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: + case ICE_PHY_TYPE_LOW_50GBASE_KR2: + case ICE_PHY_TYPE_LOW_100GBASE_KR4: + case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: + return ICE_MEDIA_BACKPLANE; + } + } else { + switch (hw_link_info->phy_type_high) { + case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: return ICE_MEDIA_BACKPLANE; } } - return ICE_MEDIA_UNKNOWN; } @@ -274,6 +301,7 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse, /* update current link status information */ hw_link_info->link_speed = le16_to_cpu(link_data.link_speed); hw_link_info->phy_type_low = le64_to_cpu(link_data.phy_type_low); + hw_link_info->phy_type_high = le64_to_cpu(link_data.phy_type_high); *hw_media_type = ice_get_media_type(pi); hw_link_info->link_info = link_data.link_info; hw_link_info->an_info = link_data.an_info; @@ -1707,16 +1735,20 @@ void ice_clear_pxe_mode(struct ice_hw *hw) /** * ice_get_link_speed_based_on_phy_type - returns link speed * @phy_type_low: lower part of phy_type + * @phy_type_high: higher part of phy_type * - * This helper function will convert a phy_type_low to its corresponding link + * This helper function will convert an entry in phy type structure + * [phy_type_low, phy_type_high] to its corresponding link speed. + * Note: In the structure of [phy_type_low, phy_type_high], there should + * be one bit set, as this function will convert one phy type to its * speed. - * Note: In the structure of phy_type_low, there should be one bit set, as - * this function will convert one phy type to its speed. * If no bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned * If more than one bit gets set, ICE_LINK_SPEED_UNKNOWN will be returned */ -static u16 ice_get_link_speed_based_on_phy_type(u64 phy_type_low) +static u16 +ice_get_link_speed_based_on_phy_type(u64 phy_type_low, u64 phy_type_high) { + u16 speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; u16 speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN; switch (phy_type_low) { @@ -1770,41 +1802,110 @@ static u16 ice_get_link_speed_based_on_phy_type(u64 phy_type_low) case ICE_PHY_TYPE_LOW_40G_XLAUI: speed_phy_type_low = ICE_AQ_LINK_SPEED_40GB; break; + case ICE_PHY_TYPE_LOW_50GBASE_CR2: + case ICE_PHY_TYPE_LOW_50GBASE_SR2: + case ICE_PHY_TYPE_LOW_50GBASE_LR2: + case ICE_PHY_TYPE_LOW_50GBASE_KR2: + case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC: + case ICE_PHY_TYPE_LOW_50G_LAUI2: + case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC: + case ICE_PHY_TYPE_LOW_50G_AUI2: + case ICE_PHY_TYPE_LOW_50GBASE_CP: + case ICE_PHY_TYPE_LOW_50GBASE_SR: + case ICE_PHY_TYPE_LOW_50GBASE_FR: + case ICE_PHY_TYPE_LOW_50GBASE_LR: + case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: + case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC: + case ICE_PHY_TYPE_LOW_50G_AUI1: + speed_phy_type_low = ICE_AQ_LINK_SPEED_50GB; + break; + case ICE_PHY_TYPE_LOW_100GBASE_CR4: + case ICE_PHY_TYPE_LOW_100GBASE_SR4: + case ICE_PHY_TYPE_LOW_100GBASE_LR4: + case ICE_PHY_TYPE_LOW_100GBASE_KR4: + case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC: + case ICE_PHY_TYPE_LOW_100G_CAUI4: + case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC: + case ICE_PHY_TYPE_LOW_100G_AUI4: + case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: + case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: + case ICE_PHY_TYPE_LOW_100GBASE_CP2: + case ICE_PHY_TYPE_LOW_100GBASE_SR2: + case ICE_PHY_TYPE_LOW_100GBASE_DR: + speed_phy_type_low = ICE_AQ_LINK_SPEED_100GB; + break; default: speed_phy_type_low = ICE_AQ_LINK_SPEED_UNKNOWN; break; } - return speed_phy_type_low; + switch (phy_type_high) { + case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: + case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC: + case ICE_PHY_TYPE_HIGH_100G_CAUI2: + case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC: + case ICE_PHY_TYPE_HIGH_100G_AUI2: + speed_phy_type_high = ICE_AQ_LINK_SPEED_100GB; + break; + default: + speed_phy_type_high = ICE_AQ_LINK_SPEED_UNKNOWN; + break; + } + + if (speed_phy_type_low == ICE_AQ_LINK_SPEED_UNKNOWN && + speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN) + return ICE_AQ_LINK_SPEED_UNKNOWN; + else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN && + speed_phy_type_high != ICE_AQ_LINK_SPEED_UNKNOWN) + return ICE_AQ_LINK_SPEED_UNKNOWN; + else if (speed_phy_type_low != ICE_AQ_LINK_SPEED_UNKNOWN && + speed_phy_type_high == ICE_AQ_LINK_SPEED_UNKNOWN) + return speed_phy_type_low; + else + return speed_phy_type_high; } /** * ice_update_phy_type * @phy_type_low: pointer to the lower part of phy_type + * @phy_type_high: pointer to the higher part of phy_type * @link_speeds_bitmap: targeted link speeds bitmap * * Note: For the link_speeds_bitmap structure, you can check it at * [ice_aqc_get_link_status->link_speed]. Caller can pass in * link_speeds_bitmap include multiple speeds. * - * The value of phy_type_low will present a certain link speed. This helper - * function will turn on bits in the phy_type_low based on the value of + * Each entry in this [phy_type_low, phy_type_high] structure will + * present a certain link speed. This helper function will turn on bits + * in [phy_type_low, phy_type_high] structure based on the value of * link_speeds_bitmap input parameter. */ -void ice_update_phy_type(u64 *phy_type_low, u16 link_speeds_bitmap) +void +ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high, + u16 link_speeds_bitmap) { u16 speed = ICE_AQ_LINK_SPEED_UNKNOWN; + u64 pt_high; u64 pt_low; int index; /* We first check with low part of phy_type */ for (index = 0; index <= ICE_PHY_TYPE_LOW_MAX_INDEX; index++) { pt_low = BIT_ULL(index); - speed = ice_get_link_speed_based_on_phy_type(pt_low); + speed = ice_get_link_speed_based_on_phy_type(pt_low, 0); if (link_speeds_bitmap & speed) *phy_type_low |= BIT_ULL(index); } + + /* We then check with high part of phy_type */ + for (index = 0; index <= ICE_PHY_TYPE_HIGH_MAX_INDEX; index++) { + pt_high = BIT_ULL(index); + speed = ice_get_link_speed_based_on_phy_type(0, pt_high); + + if (link_speeds_bitmap & speed) + *phy_type_high |= BIT_ULL(index); + } } /** @@ -1936,6 +2037,7 @@ ice_set_fc(struct ice_port_info *pi, u8 *aq_failures, bool ena_auto_link_update) if (ena_auto_link_update) cfg.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; /* Copy over all the old settings */ + cfg.phy_type_high = pcaps->phy_type_high; cfg.phy_type_low = pcaps->phy_type_low; cfg.low_power_ctrl = pcaps->low_power_ctrl; cfg.eee_cap = pcaps->eee_cap; diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 81c1bb77a9fc..17e21874b75b 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -72,7 +72,8 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode, struct ice_aqc_get_phy_caps_data *caps, struct ice_sq_cd *cd); void -ice_update_phy_type(u64 *phy_type_low, u16 link_speeds_bitmap); +ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high, + u16 link_speeds_bitmap); enum ice_status ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags, struct ice_sq_cd *cd); diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 1f6a5f073e91..a82f0202652d 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -493,16 +493,20 @@ ice_get_ethtool_stats(struct net_device *netdev, * @netdev: network interface device structure * @ks: ethtool link ksettings struct to fill out */ -static void ice_phy_type_to_ethtool(struct net_device *netdev, - struct ethtool_link_ksettings *ks) +static void +ice_phy_type_to_ethtool(struct net_device *netdev, + struct ethtool_link_ksettings *ks) { struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_link_status *hw_link_info; + bool need_add_adv_mode = false; struct ice_vsi *vsi = np->vsi; + u64 phy_types_high; u64 phy_types_low; hw_link_info = &vsi->port_info->phy.link_info; phy_types_low = vsi->port_info->phy.phy_type_low; + phy_types_high = vsi->port_info->phy.phy_type_high; ethtool_link_ksettings_zero_link_mode(ks, supported); ethtool_link_ksettings_zero_link_mode(ks, advertising); @@ -651,6 +655,95 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev, ethtool_link_ksettings_add_link_mode(ks, advertising, 40000baseLR4_Full); } + if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || + phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC || + phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2 || + phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC || + phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2 || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR || + phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC || + phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 50000baseCR2_Full); + if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 50000baseCR2_Full); + } + if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 50000baseKR2_Full); + if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 50000baseKR2_Full); + } + if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR2 || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR2 || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_FR || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 50000baseSR2_Full); + if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 50000baseSR2_Full); + } + if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || + phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC || + phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4 || + phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC || + phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4 || + phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 || + phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2 || + phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC || + phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2 || + phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC || + phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseCR4_Full); + if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) + need_add_adv_mode = true; + } + if (need_add_adv_mode) { + need_add_adv_mode = false; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100000baseCR4_Full); + } + if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4 || + phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseSR4_Full); + if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) + need_add_adv_mode = true; + } + if (need_add_adv_mode) { + need_add_adv_mode = false; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100000baseSR4_Full); + } + if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_LR4 || + phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_DR) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseLR4_ER4_Full); + if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) + need_add_adv_mode = true; + } + if (need_add_adv_mode) { + need_add_adv_mode = false; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100000baseLR4_ER4_Full); + } + if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || + phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || + phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseKR4_Full); + if (hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) + need_add_adv_mode = true; + } + if (need_add_adv_mode) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100000baseKR4_Full); /* Autoneg PHY types */ if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || @@ -676,6 +769,24 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev, ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); } + if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || + phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { + ethtool_link_ksettings_add_link_mode(ks, supported, + Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + Autoneg); + } + if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || + phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || + phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || + phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) { + ethtool_link_ksettings_add_link_mode(ks, supported, + Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + Autoneg); + } } #define TEST_SET_BITS_TIMEOUT 50 @@ -687,13 +798,15 @@ static void ice_phy_type_to_ethtool(struct net_device *netdev, * @ks: ethtool ksettings to fill in * @netdev: network interface device structure */ -static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks, - struct net_device *netdev) +static void +ice_get_settings_link_up(struct ethtool_link_ksettings *ks, + struct net_device *netdev) { struct ice_netdev_priv *np = netdev_priv(netdev); struct ethtool_link_ksettings cap_ksettings; struct ice_link_status *link_info; struct ice_vsi *vsi = np->vsi; + bool unrecog_phy_high = false; bool unrecog_phy_low = false; link_info = &vsi->port_info->phy.link_info; @@ -855,14 +968,116 @@ static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks, ethtool_link_ksettings_add_link_mode(ks, advertising, 40000baseKR4_Full); break; + case ICE_PHY_TYPE_LOW_50GBASE_CR2: + case ICE_PHY_TYPE_LOW_50GBASE_CP: + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 50000baseCR2_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 50000baseCR2_Full); + break; + case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC: + case ICE_PHY_TYPE_LOW_50G_LAUI2: + case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC: + case ICE_PHY_TYPE_LOW_50G_AUI2: + case ICE_PHY_TYPE_LOW_50GBASE_SR: + case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC: + case ICE_PHY_TYPE_LOW_50G_AUI1: + ethtool_link_ksettings_add_link_mode(ks, supported, + 50000baseCR2_Full); + break; + case ICE_PHY_TYPE_LOW_50GBASE_KR2: + case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 50000baseKR2_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 50000baseKR2_Full); + break; + case ICE_PHY_TYPE_LOW_50GBASE_SR2: + case ICE_PHY_TYPE_LOW_50GBASE_LR2: + case ICE_PHY_TYPE_LOW_50GBASE_FR: + case ICE_PHY_TYPE_LOW_50GBASE_LR: + ethtool_link_ksettings_add_link_mode(ks, supported, + 50000baseSR2_Full); + break; + case ICE_PHY_TYPE_LOW_100GBASE_CR4: + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseCR4_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100000baseCR4_Full); + break; + case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC: + case ICE_PHY_TYPE_LOW_100G_CAUI4: + case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC: + case ICE_PHY_TYPE_LOW_100G_AUI4: + case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseCR4_Full); + break; + case ICE_PHY_TYPE_LOW_100GBASE_CP2: + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseCR4_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100000baseCR4_Full); + break; + case ICE_PHY_TYPE_LOW_100GBASE_SR4: + case ICE_PHY_TYPE_LOW_100GBASE_SR2: + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseSR4_Full); + break; + case ICE_PHY_TYPE_LOW_100GBASE_LR4: + case ICE_PHY_TYPE_LOW_100GBASE_DR: + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseLR4_ER4_Full); + break; + case ICE_PHY_TYPE_LOW_100GBASE_KR4: + case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseKR4_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100000baseKR4_Full); + break; default: unrecog_phy_low = true; } - if (unrecog_phy_low) { + switch (link_info->phy_type_high) { + case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseKR4_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100000baseKR4_Full); + break; + case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC: + case ICE_PHY_TYPE_HIGH_100G_CAUI2: + case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC: + case ICE_PHY_TYPE_HIGH_100G_AUI2: + ethtool_link_ksettings_add_link_mode(ks, supported, + 100000baseCR4_Full); + break; + default: + unrecog_phy_high = true; + } + + if (unrecog_phy_low && unrecog_phy_high) { /* if we got here and link is up something bad is afoot */ - netdev_info(netdev, "WARNING: Unrecognized PHY_Low (0x%llx).\n", + netdev_info(netdev, + "WARNING: Unrecognized PHY_Low (0x%llx).\n", (u64)link_info->phy_type_low); + netdev_info(netdev, + "WARNING: Unrecognized PHY_High (0x%llx).\n", + (u64)link_info->phy_type_high); } /* Now that we've worked out everything that could be supported by the @@ -874,6 +1089,12 @@ static void ice_get_settings_link_up(struct ethtool_link_ksettings *ks, ethtool_intersect_link_masks(ks, &cap_ksettings); switch (link_info->link_speed) { + case ICE_AQ_LINK_SPEED_100GB: + ks->base.speed = SPEED_100000; + break; + case ICE_AQ_LINK_SPEED_50GB: + ks->base.speed = SPEED_50000; + break; case ICE_AQ_LINK_SPEED_40GB: ks->base.speed = SPEED_40000; break; @@ -1067,6 +1288,23 @@ ice_ksettings_find_adv_link_speed(const struct ethtool_link_ksettings *ks) ethtool_link_ksettings_test_link_mode(ks, advertising, 40000baseKR4_Full)) adv_link_speed |= ICE_AQ_LINK_SPEED_40GB; + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 50000baseCR2_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 50000baseKR2_Full)) + adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 50000baseSR2_Full)) + adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 100000baseCR4_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 100000baseSR4_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 100000baseLR4_ER4_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 100000baseKR4_Full)) + adv_link_speed |= ICE_AQ_LINK_SPEED_100GB; return adv_link_speed; } @@ -1137,8 +1375,9 @@ ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks, * * Set speed/duplex per media_types advertised/forced */ -static int ice_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *ks) +static int +ice_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *ks) { u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT, lport = 0; struct ice_netdev_priv *np = netdev_priv(netdev); @@ -1150,6 +1389,7 @@ static int ice_set_link_ksettings(struct net_device *netdev, struct ice_port_info *p; u8 autoneg_changed = 0; enum ice_status status; + u64 phy_type_high; u64 phy_type_low; int err = 0; bool linkup; @@ -1265,7 +1505,7 @@ static int ice_set_link_ksettings(struct net_device *netdev, adv_link_speed = curr_link_speed; /* Convert the advertise link speeds to their corresponded PHY_TYPE */ - ice_update_phy_type(&phy_type_low, adv_link_speed); + ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed); if (!autoneg_changed && adv_link_speed == curr_link_speed) { netdev_info(netdev, "Nothing changed, exiting without setting anything.\n"); @@ -1284,7 +1524,9 @@ static int ice_set_link_ksettings(struct net_device *netdev, /* set link and auto negotiation so changes take effect */ config.caps |= ICE_AQ_PHY_ENA_LINK; - if (phy_type_low) { + if (phy_type_low || phy_type_high) { + config.phy_type_high = cpu_to_le64(phy_type_high) & + abilities->phy_type_high; config.phy_type_low = cpu_to_le64(phy_type_low) & abilities->phy_type_low; } else { diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h index bd7c01db8c63..ef4c79b5aa32 100644 --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h @@ -489,5 +489,7 @@ static inline struct ice_rx_ptype_decoded ice_decode_rx_desc_ptype(u16 ptype) #define ICE_LINK_SPEED_20000MBPS 20000 #define ICE_LINK_SPEED_25000MBPS 25000 #define ICE_LINK_SPEED_40000MBPS 40000 +#define ICE_LINK_SPEED_50000MBPS 50000 +#define ICE_LINK_SPEED_100000MBPS 100000 #endif /* _ICE_LAN_TX_RX_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c index 533b989a23e1..d2db0d04e117 100644 --- a/drivers/net/ethernet/intel/ice/ice_sriov.c +++ b/drivers/net/ethernet/intel/ice/ice_sriov.c @@ -85,6 +85,12 @@ u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed) case ICE_AQ_LINK_SPEED_40GB: speed = ICE_LINK_SPEED_40000MBPS; break; + case ICE_AQ_LINK_SPEED_50GB: + speed = ICE_LINK_SPEED_50000MBPS; + break; + case ICE_AQ_LINK_SPEED_100GB: + speed = ICE_LINK_SPEED_100000MBPS; + break; default: speed = ICE_LINK_SPEED_UNKNOWN; break; @@ -116,6 +122,9 @@ u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed) break; case ICE_AQ_LINK_SPEED_40GB: /* fall through */ + case ICE_AQ_LINK_SPEED_50GB: + /* fall through */ + case ICE_AQ_LINK_SPEED_100GB: speed = (u32)VIRTCHNL_LINK_SPEED_40GB; break; default: diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index a078e2c98871..17086d5b5c33 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -90,6 +90,7 @@ enum ice_vsi_type { struct ice_link_status { /* Refer to ice_aq_phy_type for bits definition */ u64 phy_type_low; + u64 phy_type_high; u16 max_frame_size; u16 link_speed; u16 req_speeds; @@ -118,6 +119,7 @@ struct ice_phy_info { struct ice_link_status link_info; struct ice_link_status link_info_old; u64 phy_type_low; + u64 phy_type_high; enum ice_media_type media_type; u8 get_link_info; }; -- cgit v1.2.3 From d671e3e0dac9f637e2f49178923b7a0ac435e447 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 19 Dec 2018 10:03:34 -0800 Subject: ice: add const qualifier to mac_addr parameter The function ice_aq_manage_mac_write takes a pointer to a MAC address. The parameter is not marked const, even though the function doesn't need to modify it. This prevents passing a parameter that is already marked const. Update the function prototype to take a const pointer, to allow passing constant pointers to this function. Signed-off-by: Jacob Keller Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 6 +++--- drivers/net/ethernet/intel/ice/ice_common.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index ab308fc88920..b17ade424423 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -1685,7 +1685,7 @@ enum ice_status ice_get_caps(struct ice_hw *hw) * This function is used to write MAC address to the NVM (0x0108). */ enum ice_status -ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags, +ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags, struct ice_sq_cd *cd) { struct ice_aqc_manage_mac_write *cmd; @@ -1697,8 +1697,8 @@ ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags, cmd->flags = flags; /* Prep values for flags, sah, sal */ - cmd->sah = htons(*((u16 *)mac_addr)); - cmd->sal = htonl(*((u32 *)(mac_addr + 2))); + cmd->sah = htons(*((const u16 *)mac_addr)); + cmd->sal = htonl(*((const u32 *)(mac_addr + 2))); return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); } diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 17e21874b75b..d7c7c2ed8823 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -75,7 +75,7 @@ void ice_update_phy_type(u64 *phy_type_low, u64 *phy_type_high, u16 link_speeds_bitmap); enum ice_status -ice_aq_manage_mac_write(struct ice_hw *hw, u8 *mac_addr, u8 flags, +ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags, struct ice_sq_cd *cd); enum ice_status ice_clear_pf_cfg(struct ice_hw *hw); enum ice_status -- cgit v1.2.3 From 2285ec872d9dd5bd6a5c517cfd774be259e5f478 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 15 Jan 2019 17:05:39 -0600 Subject: mlxsw: spectrum_acl_bloom_filter: use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); This issue was detected with the help of Coccinelle. Reviewed-by: Ido Schimmel Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c index 505b87846acc..f5c381dcb015 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c @@ -234,8 +234,8 @@ mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks) * is 2^ACL_MAX_BF_LOG */ bf_bank_size = 1 << MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_BF_LOG); - bf = kzalloc(sizeof(*bf) + bf_bank_size * num_erp_banks * - sizeof(*bf->refcnt), GFP_KERNEL); + bf = kzalloc(struct_size(bf, refcnt, bf_bank_size * num_erp_banks), + GFP_KERNEL); if (!bf) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From faa311e950e37eaa1a3ca30eb42a2aee858ecbf7 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 15 Jan 2019 17:14:29 -0600 Subject: mlxsw: spectrum_nve: Use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = kzalloc(sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); This issue was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c index fb1c48c698f2..9019548d731b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c @@ -267,8 +267,8 @@ mlxsw_sp_nve_mc_record_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nve_mc_record *mc_record; int err; - mc_record = kzalloc(sizeof(*mc_record) + num_max_entries * - sizeof(struct mlxsw_sp_nve_mc_entry), GFP_KERNEL); + mc_record = kzalloc(struct_size(mc_record, entries, num_max_entries), + GFP_KERNEL); if (!mc_record) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From 9fb0969f75823e59f1af14d587aec279c66bf4a7 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 14 Jan 2019 15:15:16 +0000 Subject: bnx2x: fix various indentation issues There are lines that have indentation issues, fix these. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 176 +++++++++++------------ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 12 +- 4 files changed, 94 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h index 46ee2c01f4c5..066765fbef06 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h @@ -449,7 +449,7 @@ static inline void bnx2x_init_fw_wrr(const struct cmng_init_input *input_data, ccd[cos] = (u32)input_data->cos_min_rate[cos] * 100 * (T_FAIR_COEF / (8 * 100 * cosWeightSum)); - if (ccd[cos] < pdata->fair_vars.fair_threshold + if (ccd[cos] < pdata->fair_vars.fair_threshold + MIN_ABOVE_THRESH) { ccd[cos] = pdata->fair_vars.fair_threshold + diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 98d4c5a3ff21..29738dfa878c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -837,49 +837,45 @@ static int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp, switch (cos_entry) { case 0: - nig_reg_adress_crd_weight = - (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 : - NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0; - pbf_reg_adress_crd_weight = (port) ? - PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0; - break; + nig_reg_adress_crd_weight = + (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 : + NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0; + pbf_reg_adress_crd_weight = (port) ? + PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0; + break; case 1: - nig_reg_adress_crd_weight = (port) ? - NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 : - NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1; - pbf_reg_adress_crd_weight = (port) ? - PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0; - break; + nig_reg_adress_crd_weight = (port) ? + NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 : + NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1; + pbf_reg_adress_crd_weight = (port) ? + PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0; + break; case 2: - nig_reg_adress_crd_weight = (port) ? - NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 : - NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2; + nig_reg_adress_crd_weight = (port) ? + NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 : + NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2; - pbf_reg_adress_crd_weight = (port) ? - PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0; - break; + pbf_reg_adress_crd_weight = (port) ? + PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0; + break; case 3: - if (port) + if (port) return -EINVAL; - nig_reg_adress_crd_weight = - NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3; - pbf_reg_adress_crd_weight = - PBF_REG_COS3_WEIGHT_P0; - break; + nig_reg_adress_crd_weight = NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3; + pbf_reg_adress_crd_weight = PBF_REG_COS3_WEIGHT_P0; + break; case 4: - if (port) - return -EINVAL; - nig_reg_adress_crd_weight = - NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4; - pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0; - break; + if (port) + return -EINVAL; + nig_reg_adress_crd_weight = NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4; + pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0; + break; case 5: - if (port) - return -EINVAL; - nig_reg_adress_crd_weight = - NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5; - pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0; - break; + if (port) + return -EINVAL; + nig_reg_adress_crd_weight = NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5; + pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0; + break; } REG_WR(bp, nig_reg_adress_crd_weight, cos_bw_nig); @@ -966,7 +962,7 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params, if (pri >= max_num_of_cos) { DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid " "parameter Illegal strict priority\n"); - return -EINVAL; + return -EINVAL; } if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) { @@ -1845,28 +1841,28 @@ static int bnx2x_emac_enable(struct link_params *params, bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE, EMAC_TX_MODE_RESET); - /* pause enable/disable */ - bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE, - EMAC_RX_MODE_FLOW_EN); + /* pause enable/disable */ + bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE, + EMAC_RX_MODE_FLOW_EN); - bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE, - (EMAC_TX_MODE_EXT_PAUSE_EN | - EMAC_TX_MODE_FLOW_EN)); - if (!(params->feature_config_flags & - FEATURE_CONFIG_PFC_ENABLED)) { - if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX) - bnx2x_bits_en(bp, emac_base + - EMAC_REG_EMAC_RX_MODE, - EMAC_RX_MODE_FLOW_EN); - - if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) - bnx2x_bits_en(bp, emac_base + - EMAC_REG_EMAC_TX_MODE, - (EMAC_TX_MODE_EXT_PAUSE_EN | - EMAC_TX_MODE_FLOW_EN)); - } else - bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE, - EMAC_TX_MODE_FLOW_EN); + bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE, + (EMAC_TX_MODE_EXT_PAUSE_EN | + EMAC_TX_MODE_FLOW_EN)); + if (!(params->feature_config_flags & + FEATURE_CONFIG_PFC_ENABLED)) { + if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX) + bnx2x_bits_en(bp, emac_base + + EMAC_REG_EMAC_RX_MODE, + EMAC_RX_MODE_FLOW_EN); + + if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) + bnx2x_bits_en(bp, emac_base + + EMAC_REG_EMAC_TX_MODE, + (EMAC_TX_MODE_EXT_PAUSE_EN | + EMAC_TX_MODE_FLOW_EN)); + } else + bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE, + EMAC_TX_MODE_FLOW_EN); /* KEEP_VLAN_TAG, promiscuous */ val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE); @@ -6478,9 +6474,9 @@ int bnx2x_test_link(struct link_params *params, struct link_vars *vars, MDIO_REG_BANK_GP_STATUS, MDIO_GP_STATUS_TOP_AN_STATUS1, &gp_status); - /* Link is up only if both local phy and external phy are up */ - if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)) - return -ESRCH; + /* Link is up only if both local phy and external phy are up */ + if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)) + return -ESRCH; } /* In XGXS loopback mode, do not check external PHY */ if (params->loopback_mode == LOOPBACK_XGXS) @@ -7293,8 +7289,8 @@ static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy) DP(NETIF_MSG_LINK, "XAUI workaround has completed\n"); return 0; - } - usleep_range(3000, 6000); + } + usleep_range(3000, 6000); } break; } @@ -12675,39 +12671,39 @@ static void bnx2x_init_bmac_loopback(struct link_params *params, struct link_vars *vars) { struct bnx2x *bp = params->bp; - vars->link_up = 1; - vars->line_speed = SPEED_10000; - vars->duplex = DUPLEX_FULL; - vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; - vars->mac_type = MAC_TYPE_BMAC; + vars->link_up = 1; + vars->line_speed = SPEED_10000; + vars->duplex = DUPLEX_FULL; + vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; + vars->mac_type = MAC_TYPE_BMAC; - vars->phy_flags = PHY_XGXS_FLAG; + vars->phy_flags = PHY_XGXS_FLAG; - bnx2x_xgxs_deassert(params); + bnx2x_xgxs_deassert(params); - /* Set bmac loopback */ - bnx2x_bmac_enable(params, vars, 1, 1); + /* Set bmac loopback */ + bnx2x_bmac_enable(params, vars, 1, 1); - REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); + REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); } static void bnx2x_init_emac_loopback(struct link_params *params, struct link_vars *vars) { struct bnx2x *bp = params->bp; - vars->link_up = 1; - vars->line_speed = SPEED_1000; - vars->duplex = DUPLEX_FULL; - vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; - vars->mac_type = MAC_TYPE_EMAC; + vars->link_up = 1; + vars->line_speed = SPEED_1000; + vars->duplex = DUPLEX_FULL; + vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; + vars->mac_type = MAC_TYPE_EMAC; - vars->phy_flags = PHY_XGXS_FLAG; + vars->phy_flags = PHY_XGXS_FLAG; - bnx2x_xgxs_deassert(params); - /* Set bmac loopback */ - bnx2x_emac_enable(params, vars, 1); - bnx2x_emac_program(params, vars); - REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); + bnx2x_xgxs_deassert(params); + /* Set bmac loopback */ + bnx2x_emac_enable(params, vars, 1); + bnx2x_emac_program(params, vars); + REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port * 4, 0); } static void bnx2x_init_xmac_loopback(struct link_params *params, @@ -13073,12 +13069,12 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars, REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); } - if (!CHIP_IS_E3(bp)) { - bnx2x_set_bmac_rx(bp, params->chip_id, port, 0); - } else { - bnx2x_set_xmac_rxtx(params, 0); - bnx2x_set_umac_rxtx(params, 0); - } + if (!CHIP_IS_E3(bp)) { + bnx2x_set_bmac_rx(bp, params->chip_id, port, 0); + } else { + bnx2x_set_xmac_rxtx(params, 0); + bnx2x_set_umac_rxtx(params, 0); + } /* Disable emac */ if (!CHIP_IS_E3(bp)) REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 3b5b47e98c73..0cec82450e19 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11298,7 +11298,7 @@ static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg) dev_info.port_hw_config[port].external_phy_config), SHMEM_RD(bp, dev_info.port_hw_config[port].external_phy_config2)); - return; + return; } if (CHIP_IS_E3(bp)) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index a9eaaf3e73a4..7b22a6d8514c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -2977,8 +2977,8 @@ static inline void bnx2x_mcast_hdl_pending_del_e2(struct bnx2x *bp, cmd_pos->data.macs_num--; - DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n", - cmd_pos->data.macs_num, cnt); + DP(BNX2X_MSG_SP, "Deleting MAC. %d left,cnt is %d\n", + cmd_pos->data.macs_num, cnt); /* Break if we reached the maximum * number of rules. @@ -3597,8 +3597,8 @@ static int bnx2x_mcast_validate_e1(struct bnx2x *bp, /* RESTORE command will restore the entire multicast configuration */ case BNX2X_MCAST_CMD_RESTORE: p->mcast_list_len = reg_sz; - DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n", - cmd, p->mcast_list_len); + DP(BNX2X_MSG_SP, "Command %d, p->mcast_list_len=%d\n", + cmd, p->mcast_list_len); break; case BNX2X_MCAST_CMD_ADD: @@ -3735,8 +3735,8 @@ static inline int bnx2x_mcast_handle_restore_cmd_e1( i++; - DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n", - cfg_data.mac); + DP(BNX2X_MSG_SP, "About to configure %pM mcast MAC\n", + cfg_data.mac); } *rdata_idx = i; -- cgit v1.2.3 From eedfb2234bf77f2c17b68e702ce5c51ed4c72fbd Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 14 Jan 2019 15:37:01 +0000 Subject: drivers: net: atp: fix various indentation issues There are various lines that have indentation issues, fix these. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/atp.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c index 7e011c1c1e6e..cfb67b746595 100644 --- a/drivers/net/ethernet/realtek/atp.c +++ b/drivers/net/ethernet/realtek/atp.c @@ -454,14 +454,14 @@ static void hardware_init(struct net_device *dev) { struct net_local *lp = netdev_priv(dev); long ioaddr = dev->base_addr; - int i; + int i; /* Turn off the printer multiplexer on the 8012. */ for (i = 0; i < 8; i++) outb(mux_8012[i], ioaddr + PAR_DATA); write_reg_high(ioaddr, CMR1, CMR1h_RESET); - for (i = 0; i < 6; i++) + for (i = 0; i < 6; i++) write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]); write_reg_high(ioaddr, CMR2, lp->addr_mode); @@ -471,15 +471,15 @@ static void hardware_init(struct net_device *dev) (read_nibble(ioaddr, CMR2_h) >> 3) & 0x0f); } - write_reg(ioaddr, CMR2, CMR2_IRQOUT); - write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE); + write_reg(ioaddr, CMR2, CMR2_IRQOUT); + write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE); /* Enable the interrupt line from the serial port. */ outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL); /* Unmask the interesting interrupts. */ - write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK); - write_reg_high(ioaddr, IMR, ISRh_RxErr); + write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK); + write_reg_high(ioaddr, IMR, ISRh_RxErr); lp->tx_unit_busy = 0; lp->pac_cnt_in_tx_buf = 0; @@ -610,10 +610,12 @@ static irqreturn_t atp_interrupt(int irq, void *dev_instance) write_reg(ioaddr, CMR2, CMR2_NULL); write_reg(ioaddr, IMR, 0); - if (net_debug > 5) printk(KERN_DEBUG "%s: In interrupt ", dev->name); - while (--boguscount > 0) { + if (net_debug > 5) + printk(KERN_DEBUG "%s: In interrupt ", dev->name); + while (--boguscount > 0) { int status = read_nibble(ioaddr, ISR); - if (net_debug > 5) printk("loop status %02x..", status); + if (net_debug > 5) + printk("loop status %02x..", status); if (status & (ISR_RxOK<<3)) { handled = 1; @@ -640,7 +642,8 @@ static irqreturn_t atp_interrupt(int irq, void *dev_instance) } while (--boguscount > 0); } else if (status & ((ISR_TxErr + ISR_TxOK)<<3)) { handled = 1; - if (net_debug > 6) printk("handling Tx done.."); + if (net_debug > 6) + printk("handling Tx done.."); /* Clear the Tx interrupt. We should check for too many failures and reinitialize the adapter. */ write_reg(ioaddr, ISR, ISR_TxErr + ISR_TxOK); @@ -680,7 +683,7 @@ static irqreturn_t atp_interrupt(int irq, void *dev_instance) break; } else break; - } + } /* This following code fixes a rare (and very difficult to track down) problem where the adapter forgets its ethernet address. */ @@ -694,7 +697,7 @@ static irqreturn_t atp_interrupt(int irq, void *dev_instance) } /* Tell the adapter that it can go back to using the output line as IRQ. */ - write_reg(ioaddr, CMR2, CMR2_IRQOUT); + write_reg(ioaddr, CMR2, CMR2_IRQOUT); /* Enable the physical interrupt line, which is sure to be low until.. */ outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL); /* .. we enable the interrupt sources. */ -- cgit v1.2.3 From bdbe8cc1a30c7280bc5e6119fb5d37bfdd723c47 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 14 Jan 2019 15:41:25 +0000 Subject: net: sungem: fix indentation, remove a tab The declaration of variable 'found' is one level too deep, fix this by removing a tab. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sungem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index b9221fc1674d..3e7631160384 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -2760,7 +2760,7 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr) void __iomem *p = pci_map_rom(pdev, &size); if (p) { - int found; + int found; found = readb(p) == 0x55 && readb(p + 1) == 0xaa && -- cgit v1.2.3 From 96439889b40b83b487fa08637dcc74b1243362af Mon Sep 17 00:00:00 2001 From: Fred Lotter Date: Tue, 15 Jan 2019 19:06:51 -0800 Subject: nfp: flower: increase cmesg reply timeout QA tests report occasional timeouts on REIFY message replies. Profiling of the two cmesg reply types under burst conditions, with a 12-core host under heavy cpu and io load (stress --cpu 12 --io 12), show both PHY MTU change and REIFY replies can exceed the 10ms timeout. The maximum MTU reply wait under burst is 16ms, while the maximum REIFY wait under 40 VF burst is 12ms. Using a 4 VF REIFY burst results in an 8ms maximum wait. A larger VF burst does increase the delay, but not in a linear enough way to justify a scaled REIFY delay. The worse case values between MTU and REIFY appears close enough to justify a common timeout. Pick a conservative 40ms to make a safer future proof common reply timeout. The delay only effects the failure case. Change the REIFY timeout mechanism to use wait_event_timeout() instead of wait_event_interruptible_timeout(), to match the MTU code. In the current implementation, theoretically, a signal could interrupt the REIFY waiting period, with a return code of ERESTARTSYS. However, this is caught under the general timeout error code EIO. I cannot see the benefit of exposing the REIFY waiting period to signals with such a short delay (40ms), while the MTU mechnism does not use the same logic. In the absence of any reply (wakeup() call), both reply types will wake up the task after the timeout period. The REIFY timeout applies to the entire representor group being instantiated (e.g. VFs), while the MTU timeout apples to a single PHY MTU change. Signed-off-by: Fred Lotter Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 2 +- drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 3 +++ drivers/net/ethernet/netronome/nfp/flower/main.c | 18 +++++++----------- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c index 4c5eaf36d5bb..56b22ea32474 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c @@ -203,7 +203,7 @@ nfp_flower_cmsg_portreify_rx(struct nfp_app *app, struct sk_buff *skb) } atomic_inc(&priv->reify_replies); - wake_up_interruptible(&priv->reify_wait_queue); + wake_up(&priv->reify_wait_queue); } static void diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h index 15f41cfef9f1..4fcaf11ed56e 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h @@ -97,6 +97,9 @@ #define NFP_FLOWER_WORKQ_MAX_SKBS 30000 +/* Cmesg reply (empirical) timeout*/ +#define NFP_FL_REPLY_TIMEOUT msecs_to_jiffies(40) + #define nfp_flower_cmsg_warn(app, fmt, args...) \ do { \ if (net_ratelimit()) \ diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index 5059110a1768..8ce20bd38965 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -107,16 +107,14 @@ static int nfp_flower_wait_repr_reify(struct nfp_app *app, atomic_t *replies, int tot_repl) { struct nfp_flower_priv *priv = app->priv; - int err; if (!tot_repl) return 0; lockdep_assert_held(&app->pf->lock); - err = wait_event_interruptible_timeout(priv->reify_wait_queue, - atomic_read(replies) >= tot_repl, - msecs_to_jiffies(10)); - if (err <= 0) { + if (!wait_event_timeout(priv->reify_wait_queue, + atomic_read(replies) >= tot_repl, + NFP_FL_REPLY_TIMEOUT)) { nfp_warn(app->cpp, "Not all reprs responded to reify\n"); return -EIO; } @@ -601,7 +599,7 @@ nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev, { struct nfp_flower_priv *app_priv = app->priv; struct nfp_repr *repr = netdev_priv(netdev); - int err, ack; + int err; /* Only need to config FW for physical port MTU change. */ if (repr->port->type != NFP_PORT_PHYS_PORT) @@ -628,11 +626,9 @@ nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev, } /* Wait for fw to ack the change. */ - ack = wait_event_timeout(app_priv->mtu_conf.wait_q, - nfp_flower_check_ack(app_priv), - msecs_to_jiffies(10)); - - if (!ack) { + if (!wait_event_timeout(app_priv->mtu_conf.wait_q, + nfp_flower_check_ack(app_priv), + NFP_FL_REPLY_TIMEOUT)) { spin_lock_bh(&app_priv->mtu_conf.lock); app_priv->mtu_conf.requested_val = 0; spin_unlock_bh(&app_priv->mtu_conf.lock); -- cgit v1.2.3 From 467322e2627f863c8b48b0229674d9a22027e559 Mon Sep 17 00:00:00 2001 From: Pieter Jansen van Vuuren Date: Tue, 15 Jan 2019 19:06:52 -0800 Subject: nfp: flower: support multiple memory units for filter offloads Adds support for multiple memory units which are used for filter offloads. Each filter is assigned a stats id, the MSBs of the id are used to determine which memory unit the filter should be offloaded to. The number of available memory units that could be used for filter offload is obtained from HW. A simple round robin technique is used to allocate and distribute the ids across memory units. Signed-off-by: Pieter Jansen van Vuuren Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/main.c | 23 ++++++++++++++++-- drivers/net/ethernet/netronome/nfp/flower/main.h | 10 +++++++- .../net/ethernet/netronome/nfp/flower/metadata.c | 27 ++++++++++++++++------ 3 files changed, 50 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index 8ce20bd38965..c370fbcbcc38 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -474,8 +474,8 @@ err_clear_nn: static int nfp_flower_init(struct nfp_app *app) { + u64 version, features, ctx_count, num_mems; const struct nfp_pf *pf = app->pf; - u64 version, features, ctx_count; struct nfp_flower_priv *app_priv; int err; @@ -500,6 +500,23 @@ static int nfp_flower_init(struct nfp_app *app) return err; } + num_mems = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_SPLIT", + &err); + if (err) { + nfp_warn(app->cpp, + "FlowerNIC: unsupported host context memory: %d\n", + err); + err = 0; + num_mems = 1; + } + + if (!FIELD_FIT(NFP_FL_STAT_ID_MU_NUM, num_mems) || !num_mems) { + nfp_warn(app->cpp, + "FlowerNIC: invalid host context memory: %llu\n", + num_mems); + return -EINVAL; + } + ctx_count = nfp_rtsym_read_le(app->pf->rtbl, "CONFIG_FC_HOST_CTX_COUNT", &err); if (err) { @@ -520,6 +537,8 @@ static int nfp_flower_init(struct nfp_app *app) if (!app_priv) return -ENOMEM; + app_priv->total_mem_units = num_mems; + app_priv->active_mem_unit = 0; app_priv->stats_ring_size = roundup_pow_of_two(ctx_count); app->priv = app_priv; app_priv->app = app; @@ -531,7 +550,7 @@ static int nfp_flower_init(struct nfp_app *app) init_waitqueue_head(&app_priv->mtu_conf.wait_q); spin_lock_init(&app_priv->mtu_conf.lock); - err = nfp_flower_metadata_init(app, ctx_count); + err = nfp_flower_metadata_init(app, ctx_count, num_mems); if (err) goto err_free_app_priv; diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index b858bac47621..324b7fe3192f 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -20,6 +20,9 @@ struct nfp_fl_pre_lag; struct net_device; struct nfp_app; +#define NFP_FL_STAT_ID_MU_NUM GENMASK(31, 22) +#define NFP_FL_STAT_ID_STAT GENMASK(21, 0) + #define NFP_FL_STATS_ELEM_RS FIELD_SIZEOF(struct nfp_fl_stats_id, \ init_unalloc) #define NFP_FLOWER_MASK_ENTRY_RS 256 @@ -130,6 +133,8 @@ struct nfp_fl_lag { * @mtu_conf: Configuration of repr MTU value * @nfp_lag: Link aggregation data block * @indr_block_cb_priv: List of priv data passed to indirect block cbs + * @active_mem_unit: Current active memory unit for flower rules + * @total_mem_units: Total number of available memory units for flower rules */ struct nfp_flower_priv { struct nfp_app *app; @@ -163,6 +168,8 @@ struct nfp_flower_priv { struct nfp_mtu_conf mtu_conf; struct nfp_fl_lag nfp_lag; struct list_head indr_block_cb_priv; + unsigned int active_mem_unit; + unsigned int total_mem_units; }; /** @@ -217,7 +224,8 @@ struct nfp_fl_stats_frame { __be64 stats_cookie; }; -int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count); +int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, + unsigned int host_ctx_split); void nfp_flower_metadata_cleanup(struct nfp_app *app); int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev, diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c b/drivers/net/ethernet/netronome/nfp/flower/metadata.c index 573a4400a26c..492837b852b6 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c +++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -52,8 +53,17 @@ static int nfp_get_stats_entry(struct nfp_app *app, u32 *stats_context_id) freed_stats_id = priv->stats_ring_size; /* Check for unallocated entries first. */ if (priv->stats_ids.init_unalloc > 0) { - *stats_context_id = priv->stats_ids.init_unalloc - 1; - priv->stats_ids.init_unalloc--; + if (priv->active_mem_unit == priv->total_mem_units) { + priv->stats_ids.init_unalloc--; + priv->active_mem_unit = 0; + } + + *stats_context_id = + FIELD_PREP(NFP_FL_STAT_ID_STAT, + priv->stats_ids.init_unalloc - 1) | + FIELD_PREP(NFP_FL_STAT_ID_MU_NUM, + priv->active_mem_unit); + priv->active_mem_unit++; return 0; } @@ -381,10 +391,11 @@ const struct rhashtable_params nfp_flower_table_params = { .automatic_shrinking = true, }; -int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count) +int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, + unsigned int host_num_mems) { struct nfp_flower_priv *priv = app->priv; - int err; + int err, stats_size; hash_init(priv->mask_table); @@ -417,10 +428,12 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count) if (!priv->stats_ids.free_list.buf) goto err_free_last_used; - priv->stats_ids.init_unalloc = host_ctx_count; + priv->stats_ids.init_unalloc = div_u64(host_ctx_count, host_num_mems); - priv->stats = kvmalloc_array(priv->stats_ring_size, - sizeof(struct nfp_fl_stats), GFP_KERNEL); + stats_size = FIELD_PREP(NFP_FL_STAT_ID_STAT, host_ctx_count) | + FIELD_PREP(NFP_FL_STAT_ID_MU_NUM, host_num_mems - 1); + priv->stats = kvmalloc_array(stats_size, sizeof(struct nfp_fl_stats), + GFP_KERNEL); if (!priv->stats) goto err_free_ring_buf; -- cgit v1.2.3 From f3b975778c176b01eba10f869a5a64c6b8550c23 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 15 Jan 2019 19:06:53 -0800 Subject: nfp: flower: tidy tunnel related private data Recent additions to the flower app private data have grouped the variables of a given feature into a struct and added that struct to the main private data struct. In keeping with this, move all tunnel related private data to their own struct. This has no affect on functionality but improves readability and maintenance of the code. Signed-off-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/main.h | 52 ++++---- .../ethernet/netronome/nfp/flower/tunnel_conf.c | 144 ++++++++++----------- 2 files changed, 102 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 324b7fe3192f..977667ae0b5a 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -56,6 +56,34 @@ struct nfp_fl_stats_id { u8 repeated_em_count; }; +/** + * struct nfp_fl_tunnel_offloads - priv data for tunnel offloads + * @mac_off_list: List of MAC addresses to offload + * @mac_index_list: List of unique 8-bit indexes for non NFP netdevs + * @ipv4_off_list: List of IPv4 addresses to offload + * @neigh_off_list: List of neighbour offloads + * @mac_off_lock: Lock for the MAC address list + * @mac_index_lock: Lock for the MAC index list + * @ipv4_off_lock: Lock for the IPv4 address list + * @neigh_off_lock: Lock for the neighbour address list + * @mac_off_ids: IDA to manage id assignment for offloaded MACs + * @mac_off_count: Number of MACs in address list + * @neigh_nb: Notifier to monitor neighbour state + */ +struct nfp_fl_tunnel_offloads { + struct list_head mac_off_list; + struct list_head mac_index_list; + struct list_head ipv4_off_list; + struct list_head neigh_off_list; + struct mutex mac_off_lock; + struct mutex mac_index_lock; + struct mutex ipv4_off_lock; + spinlock_t neigh_off_lock; + struct ida mac_off_ids; + int mac_off_count; + struct notifier_block neigh_nb; +}; + /** * struct nfp_mtu_conf - manage MTU setting * @portnum: NFP port number of repr with requested MTU change @@ -116,17 +144,7 @@ struct nfp_fl_lag { * processing * @cmsg_skbs_low: List of lower priority skbs for control message * processing - * @nfp_mac_off_list: List of MAC addresses to offload - * @nfp_mac_index_list: List of unique 8-bit indexes for non NFP netdevs - * @nfp_ipv4_off_list: List of IPv4 addresses to offload - * @nfp_neigh_off_list: List of neighbour offloads - * @nfp_mac_off_lock: Lock for the MAC address list - * @nfp_mac_index_lock: Lock for the MAC index list - * @nfp_ipv4_off_lock: Lock for the IPv4 address list - * @nfp_neigh_off_lock: Lock for the neighbour address list - * @nfp_mac_off_ids: IDA to manage id assignment for offloaded macs - * @nfp_mac_off_count: Number of MACs in address list - * @nfp_tun_neigh_nb: Notifier to monitor neighbour state + * @tun: Tunnel offload data * @reify_replies: atomically stores the number of replies received * from firmware for repr reify * @reify_wait_queue: wait queue for repr reify response counting @@ -152,17 +170,7 @@ struct nfp_flower_priv { struct work_struct cmsg_work; struct sk_buff_head cmsg_skbs_high; struct sk_buff_head cmsg_skbs_low; - struct list_head nfp_mac_off_list; - struct list_head nfp_mac_index_list; - struct list_head nfp_ipv4_off_list; - struct list_head nfp_neigh_off_list; - struct mutex nfp_mac_off_lock; - struct mutex nfp_mac_index_lock; - struct mutex nfp_ipv4_off_lock; - spinlock_t nfp_neigh_off_lock; - struct ida nfp_mac_off_ids; - int nfp_mac_off_count; - struct notifier_block nfp_tun_neigh_nb; + struct nfp_fl_tunnel_offloads tun; atomic_t reify_replies; wait_queue_head_t reify_wait_queue; struct nfp_mtu_conf mtu_conf; diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index 2d9f26a725c2..3026ab178fd2 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -205,15 +205,15 @@ static bool nfp_tun_has_route(struct nfp_app *app, __be32 ipv4_addr) struct nfp_ipv4_route_entry *entry; struct list_head *ptr, *storage; - spin_lock_bh(&priv->nfp_neigh_off_lock); - list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) { + spin_lock_bh(&priv->tun.neigh_off_lock); + list_for_each_safe(ptr, storage, &priv->tun.neigh_off_list) { entry = list_entry(ptr, struct nfp_ipv4_route_entry, list); if (entry->ipv4_addr == ipv4_addr) { - spin_unlock_bh(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->tun.neigh_off_lock); return true; } } - spin_unlock_bh(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->tun.neigh_off_lock); return false; } @@ -223,24 +223,24 @@ static void nfp_tun_add_route_to_cache(struct nfp_app *app, __be32 ipv4_addr) struct nfp_ipv4_route_entry *entry; struct list_head *ptr, *storage; - spin_lock_bh(&priv->nfp_neigh_off_lock); - list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) { + spin_lock_bh(&priv->tun.neigh_off_lock); + list_for_each_safe(ptr, storage, &priv->tun.neigh_off_list) { entry = list_entry(ptr, struct nfp_ipv4_route_entry, list); if (entry->ipv4_addr == ipv4_addr) { - spin_unlock_bh(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->tun.neigh_off_lock); return; } } entry = kmalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) { - spin_unlock_bh(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->tun.neigh_off_lock); nfp_flower_cmsg_warn(app, "Mem error when storing new route.\n"); return; } entry->ipv4_addr = ipv4_addr; - list_add_tail(&entry->list, &priv->nfp_neigh_off_list); - spin_unlock_bh(&priv->nfp_neigh_off_lock); + list_add_tail(&entry->list, &priv->tun.neigh_off_list); + spin_unlock_bh(&priv->tun.neigh_off_lock); } static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr) @@ -249,8 +249,8 @@ static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr) struct nfp_ipv4_route_entry *entry; struct list_head *ptr, *storage; - spin_lock_bh(&priv->nfp_neigh_off_lock); - list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) { + spin_lock_bh(&priv->tun.neigh_off_lock); + list_for_each_safe(ptr, storage, &priv->tun.neigh_off_list) { entry = list_entry(ptr, struct nfp_ipv4_route_entry, list); if (entry->ipv4_addr == ipv4_addr) { list_del(&entry->list); @@ -258,7 +258,7 @@ static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr) break; } } - spin_unlock_bh(&priv->nfp_neigh_off_lock); + spin_unlock_bh(&priv->tun.neigh_off_lock); } static void @@ -326,7 +326,7 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event, if (!nfp_netdev_is_nfp_repr(n->dev)) return NOTIFY_DONE; - app_priv = container_of(nb, struct nfp_flower_priv, nfp_tun_neigh_nb); + app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb); app = app_priv->app; /* Only concerned with changes to routes already added to NFP. */ @@ -401,11 +401,11 @@ static void nfp_tun_write_ipv4_list(struct nfp_app *app) int count; memset(&payload, 0, sizeof(struct nfp_tun_ipv4_addr)); - mutex_lock(&priv->nfp_ipv4_off_lock); + mutex_lock(&priv->tun.ipv4_off_lock); count = 0; - list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) { + list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) { if (count >= NFP_FL_IPV4_ADDRS_MAX) { - mutex_unlock(&priv->nfp_ipv4_off_lock); + mutex_unlock(&priv->tun.ipv4_off_lock); nfp_flower_cmsg_warn(app, "IPv4 offload exceeds limit.\n"); return; } @@ -413,7 +413,7 @@ static void nfp_tun_write_ipv4_list(struct nfp_app *app) payload.ipv4_addr[count++] = entry->ipv4_addr; } payload.count = cpu_to_be32(count); - mutex_unlock(&priv->nfp_ipv4_off_lock); + mutex_unlock(&priv->tun.ipv4_off_lock); nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_IPS, sizeof(struct nfp_tun_ipv4_addr), @@ -426,26 +426,26 @@ void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4) struct nfp_ipv4_addr_entry *entry; struct list_head *ptr, *storage; - mutex_lock(&priv->nfp_ipv4_off_lock); - list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) { + mutex_lock(&priv->tun.ipv4_off_lock); + list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) { entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list); if (entry->ipv4_addr == ipv4) { entry->ref_count++; - mutex_unlock(&priv->nfp_ipv4_off_lock); + mutex_unlock(&priv->tun.ipv4_off_lock); return; } } entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) { - mutex_unlock(&priv->nfp_ipv4_off_lock); + mutex_unlock(&priv->tun.ipv4_off_lock); nfp_flower_cmsg_warn(app, "Mem error when offloading IP address.\n"); return; } entry->ipv4_addr = ipv4; entry->ref_count = 1; - list_add_tail(&entry->list, &priv->nfp_ipv4_off_list); - mutex_unlock(&priv->nfp_ipv4_off_lock); + list_add_tail(&entry->list, &priv->tun.ipv4_off_list); + mutex_unlock(&priv->tun.ipv4_off_lock); nfp_tun_write_ipv4_list(app); } @@ -456,8 +456,8 @@ void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4) struct nfp_ipv4_addr_entry *entry; struct list_head *ptr, *storage; - mutex_lock(&priv->nfp_ipv4_off_lock); - list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) { + mutex_lock(&priv->tun.ipv4_off_lock); + list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) { entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list); if (entry->ipv4_addr == ipv4) { entry->ref_count--; @@ -468,7 +468,7 @@ void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4) break; } } - mutex_unlock(&priv->nfp_ipv4_off_lock); + mutex_unlock(&priv->tun.ipv4_off_lock); nfp_tun_write_ipv4_list(app); } @@ -481,25 +481,25 @@ void nfp_tunnel_write_macs(struct nfp_app *app) struct list_head *ptr, *storage; int mac_count, err, pay_size; - mutex_lock(&priv->nfp_mac_off_lock); - if (!priv->nfp_mac_off_count) { - mutex_unlock(&priv->nfp_mac_off_lock); + mutex_lock(&priv->tun.mac_off_lock); + if (!priv->tun.mac_off_count) { + mutex_unlock(&priv->tun.mac_off_lock); return; } pay_size = sizeof(struct nfp_tun_mac_addr) + - sizeof(struct index_mac_addr) * priv->nfp_mac_off_count; + sizeof(struct index_mac_addr) * priv->tun.mac_off_count; payload = kzalloc(pay_size, GFP_KERNEL); if (!payload) { - mutex_unlock(&priv->nfp_mac_off_lock); + mutex_unlock(&priv->tun.mac_off_lock); return; } - payload->count = cpu_to_be16(priv->nfp_mac_off_count); + payload->count = cpu_to_be16(priv->tun.mac_off_count); mac_count = 0; - list_for_each_safe(ptr, storage, &priv->nfp_mac_off_list) { + list_for_each_safe(ptr, storage, &priv->tun.mac_off_list) { entry = list_entry(ptr, struct nfp_tun_mac_offload_entry, list); payload->addresses[mac_count].index = entry->index; @@ -514,21 +514,21 @@ void nfp_tunnel_write_macs(struct nfp_app *app) kfree(payload); if (err) { - mutex_unlock(&priv->nfp_mac_off_lock); + mutex_unlock(&priv->tun.mac_off_lock); /* Write failed so retain list for future retry. */ return; } /* If list was successfully offloaded, flush it. */ - list_for_each_safe(ptr, storage, &priv->nfp_mac_off_list) { + list_for_each_safe(ptr, storage, &priv->tun.mac_off_list) { entry = list_entry(ptr, struct nfp_tun_mac_offload_entry, list); list_del(&entry->list); kfree(entry); } - priv->nfp_mac_off_count = 0; - mutex_unlock(&priv->nfp_mac_off_lock); + priv->tun.mac_off_count = 0; + mutex_unlock(&priv->tun.mac_off_lock); } static int nfp_tun_get_mac_idx(struct nfp_app *app, int ifindex) @@ -538,32 +538,32 @@ static int nfp_tun_get_mac_idx(struct nfp_app *app, int ifindex) struct list_head *ptr, *storage; int idx; - mutex_lock(&priv->nfp_mac_index_lock); - list_for_each_safe(ptr, storage, &priv->nfp_mac_index_list) { + mutex_lock(&priv->tun.mac_index_lock); + list_for_each_safe(ptr, storage, &priv->tun.mac_index_list) { entry = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, list); if (entry->ifindex == ifindex) { idx = entry->index; - mutex_unlock(&priv->nfp_mac_index_lock); + mutex_unlock(&priv->tun.mac_index_lock); return idx; } } - idx = ida_simple_get(&priv->nfp_mac_off_ids, 0, + idx = ida_simple_get(&priv->tun.mac_off_ids, 0, NFP_MAX_MAC_INDEX, GFP_KERNEL); if (idx < 0) { - mutex_unlock(&priv->nfp_mac_index_lock); + mutex_unlock(&priv->tun.mac_index_lock); return idx; } entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) { - mutex_unlock(&priv->nfp_mac_index_lock); + mutex_unlock(&priv->tun.mac_index_lock); return -ENOMEM; } entry->ifindex = ifindex; entry->index = idx; - list_add_tail(&entry->list, &priv->nfp_mac_index_list); - mutex_unlock(&priv->nfp_mac_index_lock); + list_add_tail(&entry->list, &priv->tun.mac_index_list); + mutex_unlock(&priv->tun.mac_index_lock); return idx; } @@ -574,18 +574,18 @@ static void nfp_tun_del_mac_idx(struct nfp_app *app, int ifindex) struct nfp_tun_mac_non_nfp_idx *entry; struct list_head *ptr, *storage; - mutex_lock(&priv->nfp_mac_index_lock); - list_for_each_safe(ptr, storage, &priv->nfp_mac_index_list) { + mutex_lock(&priv->tun.mac_index_lock); + list_for_each_safe(ptr, storage, &priv->tun.mac_index_list) { entry = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, list); if (entry->ifindex == ifindex) { - ida_simple_remove(&priv->nfp_mac_off_ids, + ida_simple_remove(&priv->tun.mac_off_ids, entry->index); list_del(&entry->list); kfree(entry); break; } } - mutex_unlock(&priv->nfp_mac_index_lock); + mutex_unlock(&priv->tun.mac_index_lock); } static void nfp_tun_add_to_mac_offload_list(struct net_device *netdev, @@ -633,10 +633,10 @@ static void nfp_tun_add_to_mac_offload_list(struct net_device *netdev, entry->index = cpu_to_be16(nfp_mac_idx); ether_addr_copy(entry->addr, netdev->dev_addr); - mutex_lock(&priv->nfp_mac_off_lock); - priv->nfp_mac_off_count++; - list_add_tail(&entry->list, &priv->nfp_mac_off_list); - mutex_unlock(&priv->nfp_mac_off_lock); + mutex_lock(&priv->tun.mac_off_lock); + priv->tun.mac_off_count++; + list_add_tail(&entry->list, &priv->tun.mac_off_list); + mutex_unlock(&priv->tun.mac_off_lock); } int nfp_tunnel_mac_event_handler(struct nfp_app *app, @@ -662,23 +662,23 @@ int nfp_tunnel_config_start(struct nfp_app *app) struct nfp_flower_priv *priv = app->priv; /* Initialise priv data for MAC offloading. */ - priv->nfp_mac_off_count = 0; - mutex_init(&priv->nfp_mac_off_lock); - INIT_LIST_HEAD(&priv->nfp_mac_off_list); - mutex_init(&priv->nfp_mac_index_lock); - INIT_LIST_HEAD(&priv->nfp_mac_index_list); - ida_init(&priv->nfp_mac_off_ids); + priv->tun.mac_off_count = 0; + mutex_init(&priv->tun.mac_off_lock); + INIT_LIST_HEAD(&priv->tun.mac_off_list); + mutex_init(&priv->tun.mac_index_lock); + INIT_LIST_HEAD(&priv->tun.mac_index_list); + ida_init(&priv->tun.mac_off_ids); /* Initialise priv data for IPv4 offloading. */ - mutex_init(&priv->nfp_ipv4_off_lock); - INIT_LIST_HEAD(&priv->nfp_ipv4_off_list); + mutex_init(&priv->tun.ipv4_off_lock); + INIT_LIST_HEAD(&priv->tun.ipv4_off_list); /* Initialise priv data for neighbour offloading. */ - spin_lock_init(&priv->nfp_neigh_off_lock); - INIT_LIST_HEAD(&priv->nfp_neigh_off_list); - priv->nfp_tun_neigh_nb.notifier_call = nfp_tun_neigh_event_handler; + spin_lock_init(&priv->tun.neigh_off_lock); + INIT_LIST_HEAD(&priv->tun.neigh_off_list); + priv->tun.neigh_nb.notifier_call = nfp_tun_neigh_event_handler; - return register_netevent_notifier(&priv->nfp_tun_neigh_nb); + return register_netevent_notifier(&priv->tun.neigh_nb); } void nfp_tunnel_config_stop(struct nfp_app *app) @@ -690,10 +690,10 @@ void nfp_tunnel_config_stop(struct nfp_app *app) struct nfp_ipv4_addr_entry *ip_entry; struct list_head *ptr, *storage; - unregister_netevent_notifier(&priv->nfp_tun_neigh_nb); + unregister_netevent_notifier(&priv->tun.neigh_nb); /* Free any memory that may be occupied by MAC list. */ - list_for_each_safe(ptr, storage, &priv->nfp_mac_off_list) { + list_for_each_safe(ptr, storage, &priv->tun.mac_off_list) { mac_entry = list_entry(ptr, struct nfp_tun_mac_offload_entry, list); list_del(&mac_entry->list); @@ -701,24 +701,24 @@ void nfp_tunnel_config_stop(struct nfp_app *app) } /* Free any memory that may be occupied by MAC index list. */ - list_for_each_safe(ptr, storage, &priv->nfp_mac_index_list) { + list_for_each_safe(ptr, storage, &priv->tun.mac_index_list) { mac_idx = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, list); list_del(&mac_idx->list); kfree(mac_idx); } - ida_destroy(&priv->nfp_mac_off_ids); + ida_destroy(&priv->tun.mac_off_ids); /* Free any memory that may be occupied by ipv4 list. */ - list_for_each_safe(ptr, storage, &priv->nfp_ipv4_off_list) { + list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) { ip_entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list); list_del(&ip_entry->list); kfree(ip_entry); } /* Free any memory that may be occupied by the route list. */ - list_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) { + list_for_each_safe(ptr, storage, &priv->tun.neigh_off_list) { route_entry = list_entry(ptr, struct nfp_ipv4_route_entry, list); list_del(&route_entry->list); -- cgit v1.2.3 From 41da0b5ef3447cf49c3a9dafc9e97a753a785296 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 15 Jan 2019 19:06:54 -0800 Subject: nfp: flower: ignore offload of VF and PF repr MAC addresses Currently MAC addresses of all repr netdevs, along with selected non-NFP controlled netdevs, are offloaded to FW as potential tunnel end-points. However, the addresses of VF and PF reprs are meaningless outside of internal communication and it is only those of physical port reprs required. Modify the MAC address offload selection code to ignore VF/PF repr devs. Signed-off-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index 3026ab178fd2..4e509c8c1aca 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -614,11 +614,7 @@ static void nfp_tun_add_to_mac_offload_list(struct net_device *netdev, if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) == NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT) { nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT; - } else if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) == - NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT) { - port = FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC, port); - nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT; - } else { + } else if (!port) { /* Must assign our own unique 8-bit index. */ int idx = nfp_tun_get_mac_idx(app, netdev->ifindex); @@ -628,6 +624,9 @@ static void nfp_tun_add_to_mac_offload_list(struct net_device *netdev, return; } nfp_mac_idx = idx << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; + } else { + kfree(entry); + return; } entry->index = cpu_to_be16(nfp_mac_idx); -- cgit v1.2.3 From 0115dcc31446adfdce6b37197e988bd4c2b8c6d3 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 15 Jan 2019 19:06:55 -0800 Subject: nfp: flower: remove list infastructure from MAC offload Potential MAC destination addresses for tunnel end-points are offloaded to firmware. This was done by building a list of such MACs and writing to firmware as blocks of addresses. Simplify this code by removing the list format and sending a new message for each offloaded MAC. This is in preparation for delete MAC messages. There will be one delete flag per message so we cannot assume that this applies to all addresses in a list. Signed-off-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/main.h | 7 - drivers/net/ethernet/netronome/nfp/flower/match.c | 3 - .../ethernet/netronome/nfp/flower/tunnel_conf.c | 159 +++++---------------- 3 files changed, 37 insertions(+), 132 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 977667ae0b5a..1b9d6fd084d8 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -58,29 +58,23 @@ struct nfp_fl_stats_id { /** * struct nfp_fl_tunnel_offloads - priv data for tunnel offloads - * @mac_off_list: List of MAC addresses to offload * @mac_index_list: List of unique 8-bit indexes for non NFP netdevs * @ipv4_off_list: List of IPv4 addresses to offload * @neigh_off_list: List of neighbour offloads - * @mac_off_lock: Lock for the MAC address list * @mac_index_lock: Lock for the MAC index list * @ipv4_off_lock: Lock for the IPv4 address list * @neigh_off_lock: Lock for the neighbour address list * @mac_off_ids: IDA to manage id assignment for offloaded MACs - * @mac_off_count: Number of MACs in address list * @neigh_nb: Notifier to monitor neighbour state */ struct nfp_fl_tunnel_offloads { - struct list_head mac_off_list; struct list_head mac_index_list; struct list_head ipv4_off_list; struct list_head neigh_off_list; - struct mutex mac_off_lock; struct mutex mac_index_lock; struct mutex ipv4_off_lock; spinlock_t neigh_off_lock; struct ida mac_off_ids; - int mac_off_count; struct notifier_block neigh_nb; }; @@ -268,7 +262,6 @@ void nfp_tunnel_config_stop(struct nfp_app *app); int nfp_tunnel_mac_event_handler(struct nfp_app *app, struct net_device *netdev, unsigned long event, void *ptr); -void nfp_tunnel_write_macs(struct nfp_app *app); void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4); void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4); void nfp_tunnel_request_route(struct nfp_app *app, struct sk_buff *skb); diff --git a/drivers/net/ethernet/netronome/nfp/flower/match.c b/drivers/net/ethernet/netronome/nfp/flower/match.c index cdf75595f627..c04a0d6b0184 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/match.c +++ b/drivers/net/ethernet/netronome/nfp/flower/match.c @@ -403,9 +403,6 @@ int nfp_flower_compile_flow_match(struct nfp_app *app, ext += sizeof(struct nfp_flower_ipv4_udp_tun); msk += sizeof(struct nfp_flower_ipv4_udp_tun); - /* Configure tunnel end point MAC. */ - nfp_tunnel_write_macs(app); - /* Store the tunnel destination in the rule data. * This must be present and be an exact match. */ diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index 4e509c8c1aca..9b8c73bfcb5b 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -99,32 +99,17 @@ struct nfp_ipv4_addr_entry { }; /** - * struct nfp_tun_mac_addr - configure MAC address of tunnel EP on NFP + * struct nfp_tun_mac_addr_offload - configure MAC address of tunnel EP on NFP * @reserved: reserved for future use - * @count: number of MAC addresses in the message - * @addresses.index: index of MAC address in the lookup table - * @addresses.addr: interface MAC address - * @addresses: series of MACs to offload + * @count: number of MAC addresses in the message (should be 1) + * @index: index of MAC address in the lookup table + * @addr: interface MAC address */ -struct nfp_tun_mac_addr { +struct nfp_tun_mac_addr_offload { __be16 reserved; __be16 count; - struct index_mac_addr { - __be16 index; - u8 addr[ETH_ALEN]; - } addresses[]; -}; - -/** - * struct nfp_tun_mac_offload_entry - list of MACs to offload - * @index: index of MAC address for offloading - * @addr: interface MAC address - * @list: list pointer - */ -struct nfp_tun_mac_offload_entry { __be16 index; u8 addr[ETH_ALEN]; - struct list_head list; }; #define NFP_MAX_MAC_INDEX 0xff @@ -473,64 +458,6 @@ void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4) nfp_tun_write_ipv4_list(app); } -void nfp_tunnel_write_macs(struct nfp_app *app) -{ - struct nfp_flower_priv *priv = app->priv; - struct nfp_tun_mac_offload_entry *entry; - struct nfp_tun_mac_addr *payload; - struct list_head *ptr, *storage; - int mac_count, err, pay_size; - - mutex_lock(&priv->tun.mac_off_lock); - if (!priv->tun.mac_off_count) { - mutex_unlock(&priv->tun.mac_off_lock); - return; - } - - pay_size = sizeof(struct nfp_tun_mac_addr) + - sizeof(struct index_mac_addr) * priv->tun.mac_off_count; - - payload = kzalloc(pay_size, GFP_KERNEL); - if (!payload) { - mutex_unlock(&priv->tun.mac_off_lock); - return; - } - - payload->count = cpu_to_be16(priv->tun.mac_off_count); - - mac_count = 0; - list_for_each_safe(ptr, storage, &priv->tun.mac_off_list) { - entry = list_entry(ptr, struct nfp_tun_mac_offload_entry, - list); - payload->addresses[mac_count].index = entry->index; - ether_addr_copy(payload->addresses[mac_count].addr, - entry->addr); - mac_count++; - } - - err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_MAC, - pay_size, payload, GFP_KERNEL); - - kfree(payload); - - if (err) { - mutex_unlock(&priv->tun.mac_off_lock); - /* Write failed so retain list for future retry. */ - return; - } - - /* If list was successfully offloaded, flush it. */ - list_for_each_safe(ptr, storage, &priv->tun.mac_off_list) { - entry = list_entry(ptr, struct nfp_tun_mac_offload_entry, - list); - list_del(&entry->list); - kfree(entry); - } - - priv->tun.mac_off_count = 0; - mutex_unlock(&priv->tun.mac_off_lock); -} - static int nfp_tun_get_mac_idx(struct nfp_app *app, int ifindex) { struct nfp_flower_priv *priv = app->priv; @@ -588,28 +515,35 @@ static void nfp_tun_del_mac_idx(struct nfp_app *app, int ifindex) mutex_unlock(&priv->tun.mac_index_lock); } -static void nfp_tun_add_to_mac_offload_list(struct net_device *netdev, - struct nfp_app *app) +static int __nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx) +{ + struct nfp_tun_mac_addr_offload payload; + + memset(&payload, 0, sizeof(payload)); + + /* FW supports multiple MACs per cmsg but restrict to single. */ + payload.count = cpu_to_be16(1); + payload.index = cpu_to_be16(idx); + ether_addr_copy(payload.addr, mac); + + return nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_MAC, + sizeof(struct nfp_tun_mac_addr_offload), + &payload, GFP_KERNEL); +} + +static int +nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev) { - struct nfp_flower_priv *priv = app->priv; - struct nfp_tun_mac_offload_entry *entry; u16 nfp_mac_idx; int port = 0; - /* Check if MAC should be offloaded. */ - if (!is_valid_ether_addr(netdev->dev_addr)) - return; - if (nfp_netdev_is_nfp_repr(netdev)) port = nfp_repr_get_port_id(netdev); else if (!nfp_fl_is_netdev_to_offload(netdev)) - return; + return 0; - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - nfp_flower_cmsg_warn(app, "Mem fail when offloading MAC.\n"); - return; - } + if (!is_valid_ether_addr(netdev->dev_addr)) + return -EINVAL; if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) == NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT) { @@ -618,40 +552,33 @@ static void nfp_tun_add_to_mac_offload_list(struct net_device *netdev, /* Must assign our own unique 8-bit index. */ int idx = nfp_tun_get_mac_idx(app, netdev->ifindex); - if (idx < 0) { - nfp_flower_cmsg_warn(app, "Can't assign non-repr MAC index.\n"); - kfree(entry); - return; - } + if (idx < 0) + return idx; + nfp_mac_idx = idx << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; } else { - kfree(entry); - return; + return 0; } - entry->index = cpu_to_be16(nfp_mac_idx); - ether_addr_copy(entry->addr, netdev->dev_addr); - - mutex_lock(&priv->tun.mac_off_lock); - priv->tun.mac_off_count++; - list_add_tail(&entry->list, &priv->tun.mac_off_list); - mutex_unlock(&priv->tun.mac_off_lock); + return __nfp_tunnel_offload_mac(app, netdev->dev_addr, nfp_mac_idx); } int nfp_tunnel_mac_event_handler(struct nfp_app *app, struct net_device *netdev, unsigned long event, void *ptr) { + int err; + if (event == NETDEV_DOWN || event == NETDEV_UNREGISTER) { /* If non-nfp netdev then free its offload index. */ if (nfp_fl_is_netdev_to_offload(netdev)) nfp_tun_del_mac_idx(app, netdev->ifindex); } else if (event == NETDEV_UP || event == NETDEV_CHANGEADDR || event == NETDEV_REGISTER) { - nfp_tun_add_to_mac_offload_list(netdev, app); - - /* Force a list write to keep NFP up to date. */ - nfp_tunnel_write_macs(app); + err = nfp_tunnel_offload_mac(app, netdev); + if (err) + nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n", + netdev_name(netdev)); } return NOTIFY_OK; } @@ -661,9 +588,6 @@ int nfp_tunnel_config_start(struct nfp_app *app) struct nfp_flower_priv *priv = app->priv; /* Initialise priv data for MAC offloading. */ - priv->tun.mac_off_count = 0; - mutex_init(&priv->tun.mac_off_lock); - INIT_LIST_HEAD(&priv->tun.mac_off_list); mutex_init(&priv->tun.mac_index_lock); INIT_LIST_HEAD(&priv->tun.mac_index_list); ida_init(&priv->tun.mac_off_ids); @@ -682,7 +606,6 @@ int nfp_tunnel_config_start(struct nfp_app *app) void nfp_tunnel_config_stop(struct nfp_app *app) { - struct nfp_tun_mac_offload_entry *mac_entry; struct nfp_flower_priv *priv = app->priv; struct nfp_ipv4_route_entry *route_entry; struct nfp_tun_mac_non_nfp_idx *mac_idx; @@ -691,14 +614,6 @@ void nfp_tunnel_config_stop(struct nfp_app *app) unregister_netevent_notifier(&priv->tun.neigh_nb); - /* Free any memory that may be occupied by MAC list. */ - list_for_each_safe(ptr, storage, &priv->tun.mac_off_list) { - mac_entry = list_entry(ptr, struct nfp_tun_mac_offload_entry, - list); - list_del(&mac_entry->list); - kfree(mac_entry); - } - /* Free any memory that may be occupied by MAC index list. */ list_for_each_safe(ptr, storage, &priv->tun.mac_index_list) { mac_idx = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, -- cgit v1.2.3 From 49402b0b7ff706eba22cb67fe7e2dff9f04ce255 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 15 Jan 2019 19:06:56 -0800 Subject: nfp: flower: ensure deletion of old offloaded MACs When a potential tunnel end point goes down then its MAC address should not be matchable on the NFP. Implement a delete message for offloaded MACs and call this on net device down. While at it, remove the actions on register and unregister netdev events. A MAC should only be offloaded if the device is up. Note that the netdev notifier will replay any notifications for UP devices on registration so NFP can still offload ports that exist before the driver is loaded. Similarly, devices need to go down before they can be unregistered so removal of offloaded MACs is only required on down events. Signed-off-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../ethernet/netronome/nfp/flower/tunnel_conf.c | 99 ++++++++++++++++------ 1 file changed, 74 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index 9b8c73bfcb5b..46d8a222bd55 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -98,20 +98,27 @@ struct nfp_ipv4_addr_entry { struct list_head list; }; +#define NFP_TUN_MAC_OFFLOAD_DEL_FLAG 0x2 + /** * struct nfp_tun_mac_addr_offload - configure MAC address of tunnel EP on NFP - * @reserved: reserved for future use + * @flags: MAC address offload options * @count: number of MAC addresses in the message (should be 1) * @index: index of MAC address in the lookup table * @addr: interface MAC address */ struct nfp_tun_mac_addr_offload { - __be16 reserved; + __be16 flags; __be16 count; __be16 index; u8 addr[ETH_ALEN]; }; +enum nfp_flower_mac_offload_cmd { + NFP_TUNNEL_MAC_OFFLOAD_ADD = 0, + NFP_TUNNEL_MAC_OFFLOAD_DEL = 1, +}; + #define NFP_MAX_MAC_INDEX 0xff /** @@ -515,12 +522,16 @@ static void nfp_tun_del_mac_idx(struct nfp_app *app, int ifindex) mutex_unlock(&priv->tun.mac_index_lock); } -static int __nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx) +static int +__nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx, bool del) { struct nfp_tun_mac_addr_offload payload; memset(&payload, 0, sizeof(payload)); + if (del) + payload.flags = cpu_to_be16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG); + /* FW supports multiple MACs per cmsg but restrict to single. */ payload.count = cpu_to_be16(1); payload.index = cpu_to_be16(idx); @@ -532,22 +543,12 @@ static int __nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx) } static int -nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev) +nfp_tunnel_get_mac_idx_from_port(struct nfp_app *app, struct net_device *netdev, + int port, u16 *nfp_mac_idx) { - u16 nfp_mac_idx; - int port = 0; - - if (nfp_netdev_is_nfp_repr(netdev)) - port = nfp_repr_get_port_id(netdev); - else if (!nfp_fl_is_netdev_to_offload(netdev)) - return 0; - - if (!is_valid_ether_addr(netdev->dev_addr)) - return -EINVAL; - if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) == NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT) { - nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT; + *nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT; } else if (!port) { /* Must assign our own unique 8-bit index. */ int idx = nfp_tun_get_mac_idx(app, netdev->ifindex); @@ -555,12 +556,58 @@ nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev) if (idx < 0) return idx; - nfp_mac_idx = idx << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; + *nfp_mac_idx = idx << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; + } else { + return -EOPNOTSUPP; + } + + return 0; +} + +static int +nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, + enum nfp_flower_mac_offload_cmd cmd) +{ + bool non_repr = false; + int err, port = 0; + u16 nfp_mac_idx; + + if (nfp_netdev_is_nfp_repr(netdev)) { + struct nfp_repr *repr; + + repr = netdev_priv(netdev); + if (repr->app != app) + return 0; + + port = nfp_repr_get_port_id(netdev); + } else if (nfp_fl_is_netdev_to_offload(netdev)) { + non_repr = true; } else { return 0; } - return __nfp_tunnel_offload_mac(app, netdev->dev_addr, nfp_mac_idx); + if (!is_valid_ether_addr(netdev->dev_addr)) + return -EINVAL; + + switch (cmd) { + case NFP_TUNNEL_MAC_OFFLOAD_ADD: + err = nfp_tunnel_get_mac_idx_from_port(app, netdev, port, + &nfp_mac_idx); + if (err) + return err; + + return __nfp_tunnel_offload_mac(app, netdev->dev_addr, + nfp_mac_idx, false); + case NFP_TUNNEL_MAC_OFFLOAD_DEL: + if (non_repr) + nfp_tun_del_mac_idx(app, netdev->ifindex); + + return __nfp_tunnel_offload_mac(app, netdev->dev_addr, 0, true); + default: + return -EINVAL; + } + + return 0; } int nfp_tunnel_mac_event_handler(struct nfp_app *app, @@ -569,13 +616,15 @@ int nfp_tunnel_mac_event_handler(struct nfp_app *app, { int err; - if (event == NETDEV_DOWN || event == NETDEV_UNREGISTER) { - /* If non-nfp netdev then free its offload index. */ - if (nfp_fl_is_netdev_to_offload(netdev)) - nfp_tun_del_mac_idx(app, netdev->ifindex); - } else if (event == NETDEV_UP || event == NETDEV_CHANGEADDR || - event == NETDEV_REGISTER) { - err = nfp_tunnel_offload_mac(app, netdev); + if (event == NETDEV_DOWN) { + err = nfp_tunnel_offload_mac(app, netdev, + NFP_TUNNEL_MAC_OFFLOAD_DEL); + if (err) + nfp_flower_cmsg_warn(app, "Failed to delete offload MAC on %s.\n", + netdev_name(netdev)); + } else if (event == NETDEV_UP || event == NETDEV_CHANGEADDR) { + err = nfp_tunnel_offload_mac(app, netdev, + NFP_TUNNEL_MAC_OFFLOAD_ADD); if (err) nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n", netdev_name(netdev)); -- cgit v1.2.3 From 05d2bee6bd76164f7d81f3fde83f7461d0ff12af Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 15 Jan 2019 19:06:57 -0800 Subject: nfp: flower: add infastructure for non-repr priv data NFP repr netdevs contain private data that can store per port information. In certain cases, the NFP driver offloads information from non-repr ports (e.g. tunnel ports). As the driver does not have control over non-repr netdevs, it cannot add/track private data directly to the netdev struct. Add infastructure to store private information on any non-repr netdev that is offloaded at a given time. This is used in a following patch to track offloaded MAC addresses for non-reprs and enable correct house keeping on address changes. Signed-off-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/main.c | 66 ++++++++++++++++++++++++ drivers/net/ethernet/netronome/nfp/flower/main.h | 22 ++++++++ 2 files changed, 88 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index c370fbcbcc38..837ef0c72f5c 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -32,6 +32,71 @@ static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app) return DEVLINK_ESWITCH_MODE_SWITCHDEV; } +static struct nfp_flower_non_repr_priv * +nfp_flower_non_repr_priv_lookup(struct nfp_app *app, struct net_device *netdev) +{ + struct nfp_flower_priv *priv = app->priv; + struct nfp_flower_non_repr_priv *entry; + + ASSERT_RTNL(); + + list_for_each_entry(entry, &priv->non_repr_priv, list) + if (entry->netdev == netdev) + return entry; + + return NULL; +} + +void +__nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv) +{ + non_repr_priv->ref_count++; +} + +struct nfp_flower_non_repr_priv * +nfp_flower_non_repr_priv_get(struct nfp_app *app, struct net_device *netdev) +{ + struct nfp_flower_priv *priv = app->priv; + struct nfp_flower_non_repr_priv *entry; + + entry = nfp_flower_non_repr_priv_lookup(app, netdev); + if (entry) + goto inc_ref; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return NULL; + + entry->netdev = netdev; + list_add(&entry->list, &priv->non_repr_priv); + +inc_ref: + __nfp_flower_non_repr_priv_get(entry); + return entry; +} + +void +__nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv) +{ + if (--non_repr_priv->ref_count) + return; + + list_del(&non_repr_priv->list); + kfree(non_repr_priv); +} + +void +nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev) +{ + struct nfp_flower_non_repr_priv *entry; + + entry = nfp_flower_non_repr_priv_lookup(app, netdev); + if (!entry) + return; + + __nfp_flower_non_repr_priv_put(entry); +} + static enum nfp_repr_type nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port) { @@ -575,6 +640,7 @@ static int nfp_flower_init(struct nfp_app *app) } INIT_LIST_HEAD(&app_priv->indr_block_cb_priv); + INIT_LIST_HEAD(&app_priv->non_repr_priv); return 0; diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 1b9d6fd084d8..2ce898bfc5be 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -145,6 +145,7 @@ struct nfp_fl_lag { * @mtu_conf: Configuration of repr MTU value * @nfp_lag: Link aggregation data block * @indr_block_cb_priv: List of priv data passed to indirect block cbs + * @non_repr_priv: List of offloaded non-repr ports and their priv data * @active_mem_unit: Current active memory unit for flower rules * @total_mem_units: Total number of available memory units for flower rules */ @@ -170,6 +171,7 @@ struct nfp_flower_priv { struct nfp_mtu_conf mtu_conf; struct nfp_fl_lag nfp_lag; struct list_head indr_block_cb_priv; + struct list_head non_repr_priv; unsigned int active_mem_unit; unsigned int total_mem_units; }; @@ -182,6 +184,18 @@ struct nfp_flower_repr_priv { unsigned long lag_port_flags; }; +/** + * struct nfp_flower_non_repr_priv - Priv data for non-repr offloaded ports + * @list: List entry of offloaded reprs + * @netdev: Pointer to non-repr net_device + * @ref_count: Number of references held for this priv data + */ +struct nfp_flower_non_repr_priv { + struct list_head list; + struct net_device *netdev; + int ref_count; +}; + struct nfp_fl_key_ls { u32 key_layer_two; u8 key_layer; @@ -282,4 +296,12 @@ int nfp_flower_reg_indir_block_handler(struct nfp_app *app, struct net_device *netdev, unsigned long event); +void +__nfp_flower_non_repr_priv_get(struct nfp_flower_non_repr_priv *non_repr_priv); +struct nfp_flower_non_repr_priv * +nfp_flower_non_repr_priv_get(struct nfp_app *app, struct net_device *netdev); +void +__nfp_flower_non_repr_priv_put(struct nfp_flower_non_repr_priv *non_repr_priv); +void +nfp_flower_non_repr_priv_put(struct nfp_app *app, struct net_device *netdev); #endif -- cgit v1.2.3 From 13cf71031d797d37bbc960a8260ba47505f6b597 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 15 Jan 2019 19:06:58 -0800 Subject: nfp: flower: ensure MAC cleanup on address change It is possible to receive a MAC address change notification without the net device being down (e.g. when an OvS bridge is assigned the same MAC as a port added to it). This means that an offloaded MAC address may not be removed if its device gets a new address. Maintain a record of the offloaded MAC addresses for each repr and netdev assigned a MAC offload index. Use this to delete the (now expired) MAC if a change of address event occurs. Only handle change address events if the device is already up - if not then the netdev up event will handle it. Signed-off-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/main.h | 8 ++ .../ethernet/netronome/nfp/flower/tunnel_conf.c | 106 +++++++++++++++++++-- 2 files changed, 104 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 2ce898bfc5be..15b794d0d1e4 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -179,9 +179,13 @@ struct nfp_flower_priv { /** * struct nfp_flower_repr_priv - Flower APP per-repr priv data * @lag_port_flags: Extended port flags to record lag state of repr + * @mac_offloaded: Flag indicating a MAC address is offloaded for repr + * @offloaded_mac_addr: MAC address that has been offloaded for repr */ struct nfp_flower_repr_priv { unsigned long lag_port_flags; + bool mac_offloaded; + u8 offloaded_mac_addr[ETH_ALEN]; }; /** @@ -189,11 +193,15 @@ struct nfp_flower_repr_priv { * @list: List entry of offloaded reprs * @netdev: Pointer to non-repr net_device * @ref_count: Number of references held for this priv data + * @mac_offloaded: Flag indicating a MAC address is offloaded for device + * @offloaded_mac_addr: MAC address that has been offloaded for dev */ struct nfp_flower_non_repr_priv { struct list_head list; struct net_device *netdev; int ref_count; + bool mac_offloaded; + u8 offloaded_mac_addr[ETH_ALEN]; }; struct nfp_fl_key_ls { diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index 46d8a222bd55..9d87c88507f3 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -117,6 +117,7 @@ struct nfp_tun_mac_addr_offload { enum nfp_flower_mac_offload_cmd { NFP_TUNNEL_MAC_OFFLOAD_ADD = 0, NFP_TUNNEL_MAC_OFFLOAD_DEL = 1, + NFP_TUNNEL_MAC_OFFLOAD_MOD = 2, }; #define NFP_MAX_MAC_INDEX 0xff @@ -568,46 +569,121 @@ static int nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, enum nfp_flower_mac_offload_cmd cmd) { - bool non_repr = false; + struct nfp_flower_non_repr_priv *nr_priv = NULL; + bool non_repr = false, *mac_offloaded; + u8 *off_mac = NULL; int err, port = 0; u16 nfp_mac_idx; if (nfp_netdev_is_nfp_repr(netdev)) { + struct nfp_flower_repr_priv *repr_priv; struct nfp_repr *repr; repr = netdev_priv(netdev); if (repr->app != app) return 0; + repr_priv = repr->app_priv; + mac_offloaded = &repr_priv->mac_offloaded; + off_mac = &repr_priv->offloaded_mac_addr[0]; port = nfp_repr_get_port_id(netdev); } else if (nfp_fl_is_netdev_to_offload(netdev)) { + nr_priv = nfp_flower_non_repr_priv_get(app, netdev); + if (!nr_priv) + return -ENOMEM; + + mac_offloaded = &nr_priv->mac_offloaded; + off_mac = &nr_priv->offloaded_mac_addr[0]; non_repr = true; } else { return 0; } - if (!is_valid_ether_addr(netdev->dev_addr)) - return -EINVAL; + if (!is_valid_ether_addr(netdev->dev_addr)) { + err = -EINVAL; + goto err_put_non_repr_priv; + } + + if (cmd == NFP_TUNNEL_MAC_OFFLOAD_MOD && !*mac_offloaded) + cmd = NFP_TUNNEL_MAC_OFFLOAD_ADD; switch (cmd) { case NFP_TUNNEL_MAC_OFFLOAD_ADD: err = nfp_tunnel_get_mac_idx_from_port(app, netdev, port, &nfp_mac_idx); if (err) - return err; + goto err_put_non_repr_priv; + + err = __nfp_tunnel_offload_mac(app, netdev->dev_addr, + nfp_mac_idx, false); + if (err) + goto err_free_mac_idx; - return __nfp_tunnel_offload_mac(app, netdev->dev_addr, - nfp_mac_idx, false); - case NFP_TUNNEL_MAC_OFFLOAD_DEL: if (non_repr) + __nfp_flower_non_repr_priv_get(nr_priv); + + *mac_offloaded = true; + ether_addr_copy(off_mac, netdev->dev_addr); + break; + case NFP_TUNNEL_MAC_OFFLOAD_DEL: + /* Only attempt delete if add was successful. */ + if (!*mac_offloaded) + break; + + if (non_repr) { nfp_tun_del_mac_idx(app, netdev->ifindex); + __nfp_flower_non_repr_priv_put(nr_priv); + } + + *mac_offloaded = false; + + err = __nfp_tunnel_offload_mac(app, netdev->dev_addr, 0, true); + if (err) + goto err_put_non_repr_priv; + + break; + case NFP_TUNNEL_MAC_OFFLOAD_MOD: + /* Ignore if changing to the same address. */ + if (ether_addr_equal(netdev->dev_addr, off_mac)) + break; - return __nfp_tunnel_offload_mac(app, netdev->dev_addr, 0, true); + err = nfp_tunnel_get_mac_idx_from_port(app, netdev, port, + &nfp_mac_idx); + if (err) + goto err_put_non_repr_priv; + + err = __nfp_tunnel_offload_mac(app, netdev->dev_addr, + nfp_mac_idx, false); + if (err) + goto err_put_non_repr_priv; + + /* Delete the previous MAC address. */ + err = __nfp_tunnel_offload_mac(app, off_mac, nfp_mac_idx, + true); + if (err) + nfp_flower_cmsg_warn(app, "Failed to remove offload of replaced MAC addr on %s.\n", + netdev_name(netdev)); + + ether_addr_copy(off_mac, netdev->dev_addr); + break; default: - return -EINVAL; + err = -EINVAL; + goto err_put_non_repr_priv; } + if (non_repr) + __nfp_flower_non_repr_priv_put(nr_priv); + return 0; + +err_free_mac_idx: + if (non_repr) + nfp_tun_del_mac_idx(app, netdev->ifindex); +err_put_non_repr_priv: + if (non_repr) + __nfp_flower_non_repr_priv_put(nr_priv); + + return err; } int nfp_tunnel_mac_event_handler(struct nfp_app *app, @@ -622,12 +698,22 @@ int nfp_tunnel_mac_event_handler(struct nfp_app *app, if (err) nfp_flower_cmsg_warn(app, "Failed to delete offload MAC on %s.\n", netdev_name(netdev)); - } else if (event == NETDEV_UP || event == NETDEV_CHANGEADDR) { + } else if (event == NETDEV_UP) { err = nfp_tunnel_offload_mac(app, netdev, NFP_TUNNEL_MAC_OFFLOAD_ADD); if (err) nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n", netdev_name(netdev)); + } else if (event == NETDEV_CHANGEADDR) { + /* Only offload addr change if netdev is already up. */ + if (!(netdev->flags & IFF_UP)) + return NOTIFY_OK; + + err = nfp_tunnel_offload_mac(app, netdev, + NFP_TUNNEL_MAC_OFFLOAD_MOD); + if (err) + nfp_flower_cmsg_warn(app, "Failed to offload MAC change on %s.\n", + netdev_name(netdev)); } return NOTIFY_OK; } -- cgit v1.2.3 From 20cce88650981ec504d328dbbdd004d991eb8535 Mon Sep 17 00:00:00 2001 From: John Hurley Date: Tue, 15 Jan 2019 19:06:59 -0800 Subject: nfp: flower: enable MAC address sharing for offloadable devs A MAC address is not necessarily a unique identifier for a netdev. Drivers such as Linux bonds, for example, can apply the same MAC address to the upper layer device and all lower layer devices. NFP MAC offload for tunnel decap includes port verification for reprs but also supports the offload of non-repr MAC addresses by assigning 'global' indexes to these. This means that the FW will not verify the incoming port of a packet matching this destination MAC. Modify the MAC offload logic to assign global indexes based on MAC address instead of net device (as it currently does). Use this to allow multiple devices to share the same MAC. In other words, if a repr shares its MAC address with another device then give the offloaded MAC a global index rather than associate it with an ingress port. Track this so that changes can be reverted as MACs stop being shared. Implement this by removing the current list based assignment of global indexes and replacing it with an rhashtable that maps an offloaded MAC address to the number of devices sharing it, distributing global indexes based on this. Signed-off-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/main.c | 2 + drivers/net/ethernet/netronome/nfp/flower/main.h | 10 +- .../ethernet/netronome/nfp/flower/tunnel_conf.c | 343 ++++++++++++++------- 3 files changed, 237 insertions(+), 118 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c index 837ef0c72f5c..408089133599 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.c +++ b/drivers/net/ethernet/netronome/nfp/flower/main.c @@ -286,6 +286,7 @@ nfp_flower_spawn_vnic_reprs(struct nfp_app *app, nfp_repr = netdev_priv(repr); nfp_repr->app_priv = repr_priv; + repr_priv->nfp_repr = nfp_repr; /* For now we only support 1 PF */ WARN_ON(repr_type == NFP_REPR_TYPE_PF && i); @@ -400,6 +401,7 @@ nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv) nfp_repr = netdev_priv(repr); nfp_repr->app_priv = repr_priv; + repr_priv->nfp_repr = nfp_repr; port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT, repr); if (IS_ERR(port)) { diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index 15b794d0d1e4..c0945a5fd1a4 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -58,20 +58,18 @@ struct nfp_fl_stats_id { /** * struct nfp_fl_tunnel_offloads - priv data for tunnel offloads - * @mac_index_list: List of unique 8-bit indexes for non NFP netdevs + * @offloaded_macs: Hashtable of the offloaded MAC addresses * @ipv4_off_list: List of IPv4 addresses to offload * @neigh_off_list: List of neighbour offloads - * @mac_index_lock: Lock for the MAC index list * @ipv4_off_lock: Lock for the IPv4 address list * @neigh_off_lock: Lock for the neighbour address list * @mac_off_ids: IDA to manage id assignment for offloaded MACs * @neigh_nb: Notifier to monitor neighbour state */ struct nfp_fl_tunnel_offloads { - struct list_head mac_index_list; + struct rhashtable offloaded_macs; struct list_head ipv4_off_list; struct list_head neigh_off_list; - struct mutex mac_index_lock; struct mutex ipv4_off_lock; spinlock_t neigh_off_lock; struct ida mac_off_ids; @@ -178,14 +176,18 @@ struct nfp_flower_priv { /** * struct nfp_flower_repr_priv - Flower APP per-repr priv data + * @nfp_repr: Back pointer to nfp_repr * @lag_port_flags: Extended port flags to record lag state of repr * @mac_offloaded: Flag indicating a MAC address is offloaded for repr * @offloaded_mac_addr: MAC address that has been offloaded for repr + * @mac_list: List entry of reprs that share the same offloaded MAC */ struct nfp_flower_repr_priv { + struct nfp_repr *nfp_repr; unsigned long lag_port_flags; bool mac_offloaded; u8 offloaded_mac_addr[ETH_ALEN]; + struct list_head mac_list; }; /** diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c index 9d87c88507f3..4d78be4ec4e9 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c +++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c @@ -123,15 +123,26 @@ enum nfp_flower_mac_offload_cmd { #define NFP_MAX_MAC_INDEX 0xff /** - * struct nfp_tun_mac_non_nfp_idx - converts non NFP netdev ifindex to 8-bit id - * @ifindex: netdev ifindex of the device - * @index: index of netdevs mac on NFP - * @list: list pointer + * struct nfp_tun_offloaded_mac - hashtable entry for an offloaded MAC + * @ht_node: Hashtable entry + * @addr: Offloaded MAC address + * @index: Offloaded index for given MAC address + * @ref_count: Number of devs using this MAC address + * @repr_list: List of reprs sharing this MAC address */ -struct nfp_tun_mac_non_nfp_idx { - int ifindex; - u8 index; - struct list_head list; +struct nfp_tun_offloaded_mac { + struct rhash_head ht_node; + u8 addr[ETH_ALEN]; + u16 index; + int ref_count; + struct list_head repr_list; +}; + +static const struct rhashtable_params offloaded_macs_params = { + .key_offset = offsetof(struct nfp_tun_offloaded_mac, addr), + .head_offset = offsetof(struct nfp_tun_offloaded_mac, ht_node), + .key_len = ETH_ALEN, + .automatic_shrinking = true, }; void nfp_tunnel_keep_alive(struct nfp_app *app, struct sk_buff *skb) @@ -466,63 +477,6 @@ void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4) nfp_tun_write_ipv4_list(app); } -static int nfp_tun_get_mac_idx(struct nfp_app *app, int ifindex) -{ - struct nfp_flower_priv *priv = app->priv; - struct nfp_tun_mac_non_nfp_idx *entry; - struct list_head *ptr, *storage; - int idx; - - mutex_lock(&priv->tun.mac_index_lock); - list_for_each_safe(ptr, storage, &priv->tun.mac_index_list) { - entry = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, list); - if (entry->ifindex == ifindex) { - idx = entry->index; - mutex_unlock(&priv->tun.mac_index_lock); - return idx; - } - } - - idx = ida_simple_get(&priv->tun.mac_off_ids, 0, - NFP_MAX_MAC_INDEX, GFP_KERNEL); - if (idx < 0) { - mutex_unlock(&priv->tun.mac_index_lock); - return idx; - } - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - mutex_unlock(&priv->tun.mac_index_lock); - return -ENOMEM; - } - entry->ifindex = ifindex; - entry->index = idx; - list_add_tail(&entry->list, &priv->tun.mac_index_list); - mutex_unlock(&priv->tun.mac_index_lock); - - return idx; -} - -static void nfp_tun_del_mac_idx(struct nfp_app *app, int ifindex) -{ - struct nfp_flower_priv *priv = app->priv; - struct nfp_tun_mac_non_nfp_idx *entry; - struct list_head *ptr, *storage; - - mutex_lock(&priv->tun.mac_index_lock); - list_for_each_safe(ptr, storage, &priv->tun.mac_index_list) { - entry = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, list); - if (entry->ifindex == ifindex) { - ida_simple_remove(&priv->tun.mac_off_ids, - entry->index); - list_del(&entry->list); - kfree(entry); - break; - } - } - mutex_unlock(&priv->tun.mac_index_lock); -} - static int __nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx, bool del) { @@ -543,26 +497,197 @@ __nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx, bool del) &payload, GFP_KERNEL); } -static int -nfp_tunnel_get_mac_idx_from_port(struct nfp_app *app, struct net_device *netdev, - int port, u16 *nfp_mac_idx) +static bool nfp_tunnel_port_is_phy_repr(int port) { if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) == - NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT) { - *nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT; - } else if (!port) { - /* Must assign our own unique 8-bit index. */ - int idx = nfp_tun_get_mac_idx(app, netdev->ifindex); + NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT) + return true; - if (idx < 0) - return idx; + return false; +} + +static u16 nfp_tunnel_get_mac_idx_from_phy_port_id(int port) +{ + return port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT; +} + +static u16 nfp_tunnel_get_global_mac_idx_from_ida(int id) +{ + return id << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; +} + +static int nfp_tunnel_get_ida_from_global_mac_idx(u16 nfp_mac_idx) +{ + return nfp_mac_idx >> 8; +} + +static bool nfp_tunnel_is_mac_idx_global(u16 nfp_mac_idx) +{ + return (nfp_mac_idx & 0xff) == NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; +} + +static struct nfp_tun_offloaded_mac * +nfp_tunnel_lookup_offloaded_macs(struct nfp_app *app, u8 *mac) +{ + struct nfp_flower_priv *priv = app->priv; + + return rhashtable_lookup_fast(&priv->tun.offloaded_macs, mac, + offloaded_macs_params); +} + +static void +nfp_tunnel_offloaded_macs_inc_ref_and_link(struct nfp_tun_offloaded_mac *entry, + struct net_device *netdev, bool mod) +{ + if (nfp_netdev_is_nfp_repr(netdev)) { + struct nfp_flower_repr_priv *repr_priv; + struct nfp_repr *repr; + + repr = netdev_priv(netdev); + repr_priv = repr->app_priv; - *nfp_mac_idx = idx << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT; + /* If modifing MAC, remove repr from old list first. */ + if (mod) + list_del(&repr_priv->mac_list); + + list_add_tail(&repr_priv->mac_list, &entry->repr_list); + } + + entry->ref_count++; +} + +static int +nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev, + int port, bool mod) +{ + struct nfp_flower_priv *priv = app->priv; + int ida_idx = NFP_MAX_MAC_INDEX, err; + struct nfp_tun_offloaded_mac *entry; + u16 nfp_mac_idx = 0; + + entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr); + if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) { + nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, netdev, mod); + return 0; + } + + /* Assign a global index if non-repr or MAC address is now shared. */ + if (entry || !port) { + ida_idx = ida_simple_get(&priv->tun.mac_off_ids, 0, + NFP_MAX_MAC_INDEX, GFP_KERNEL); + if (ida_idx < 0) + return ida_idx; + + nfp_mac_idx = nfp_tunnel_get_global_mac_idx_from_ida(ida_idx); } else { - return -EOPNOTSUPP; + nfp_mac_idx = nfp_tunnel_get_mac_idx_from_phy_port_id(port); + } + + if (!entry) { + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + err = -ENOMEM; + goto err_free_ida; + } + + ether_addr_copy(entry->addr, netdev->dev_addr); + INIT_LIST_HEAD(&entry->repr_list); + + if (rhashtable_insert_fast(&priv->tun.offloaded_macs, + &entry->ht_node, + offloaded_macs_params)) { + err = -ENOMEM; + goto err_free_entry; + } } + err = __nfp_tunnel_offload_mac(app, netdev->dev_addr, + nfp_mac_idx, false); + if (err) { + /* If not shared then free. */ + if (!entry->ref_count) + goto err_remove_hash; + goto err_free_ida; + } + + entry->index = nfp_mac_idx; + nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, netdev, mod); + return 0; + +err_remove_hash: + rhashtable_remove_fast(&priv->tun.offloaded_macs, &entry->ht_node, + offloaded_macs_params); +err_free_entry: + kfree(entry); +err_free_ida: + if (ida_idx != NFP_MAX_MAC_INDEX) + ida_simple_remove(&priv->tun.mac_off_ids, ida_idx); + + return err; +} + +static int +nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev, + u8 *mac, bool mod) +{ + struct nfp_flower_priv *priv = app->priv; + struct nfp_flower_repr_priv *repr_priv; + struct nfp_tun_offloaded_mac *entry; + struct nfp_repr *repr; + int ida_idx; + + entry = nfp_tunnel_lookup_offloaded_macs(app, mac); + if (!entry) + return 0; + + entry->ref_count--; + /* If del is part of a mod then mac_list is still in use elsewheree. */ + if (nfp_netdev_is_nfp_repr(netdev) && !mod) { + repr = netdev_priv(netdev); + repr_priv = repr->app_priv; + list_del(&repr_priv->mac_list); + } + + /* If MAC is now used by 1 repr set the offloaded MAC index to port. */ + if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) { + u16 nfp_mac_idx; + int port, err; + + repr_priv = list_first_entry(&entry->repr_list, + struct nfp_flower_repr_priv, + mac_list); + repr = repr_priv->nfp_repr; + port = nfp_repr_get_port_id(repr->netdev); + nfp_mac_idx = nfp_tunnel_get_mac_idx_from_phy_port_id(port); + err = __nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, false); + if (err) { + nfp_flower_cmsg_warn(app, "MAC offload index revert failed on %s.\n", + netdev_name(netdev)); + return 0; + } + + ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index); + ida_simple_remove(&priv->tun.mac_off_ids, ida_idx); + entry->index = nfp_mac_idx; + return 0; + } + + if (entry->ref_count) + return 0; + + WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs, + &entry->ht_node, + offloaded_macs_params)); + /* If MAC has global ID then extract and free the ida entry. */ + if (nfp_tunnel_is_mac_idx_global(entry->index)) { + ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index); + ida_simple_remove(&priv->tun.mac_off_ids, ida_idx); + } + + kfree(entry); + + return __nfp_tunnel_offload_mac(app, mac, 0, true); } static int @@ -573,7 +698,6 @@ nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, bool non_repr = false, *mac_offloaded; u8 *off_mac = NULL; int err, port = 0; - u16 nfp_mac_idx; if (nfp_netdev_is_nfp_repr(netdev)) { struct nfp_flower_repr_priv *repr_priv; @@ -587,6 +711,8 @@ nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, mac_offloaded = &repr_priv->mac_offloaded; off_mac = &repr_priv->offloaded_mac_addr[0]; port = nfp_repr_get_port_id(netdev); + if (!nfp_tunnel_port_is_phy_repr(port)) + return 0; } else if (nfp_fl_is_netdev_to_offload(netdev)) { nr_priv = nfp_flower_non_repr_priv_get(app, netdev); if (!nr_priv) @@ -609,16 +735,10 @@ nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, switch (cmd) { case NFP_TUNNEL_MAC_OFFLOAD_ADD: - err = nfp_tunnel_get_mac_idx_from_port(app, netdev, port, - &nfp_mac_idx); + err = nfp_tunnel_add_shared_mac(app, netdev, port, false); if (err) goto err_put_non_repr_priv; - err = __nfp_tunnel_offload_mac(app, netdev->dev_addr, - nfp_mac_idx, false); - if (err) - goto err_free_mac_idx; - if (non_repr) __nfp_flower_non_repr_priv_get(nr_priv); @@ -630,14 +750,13 @@ nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, if (!*mac_offloaded) break; - if (non_repr) { - nfp_tun_del_mac_idx(app, netdev->ifindex); + if (non_repr) __nfp_flower_non_repr_priv_put(nr_priv); - } *mac_offloaded = false; - err = __nfp_tunnel_offload_mac(app, netdev->dev_addr, 0, true); + err = nfp_tunnel_del_shared_mac(app, netdev, netdev->dev_addr, + false); if (err) goto err_put_non_repr_priv; @@ -647,19 +766,12 @@ nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, if (ether_addr_equal(netdev->dev_addr, off_mac)) break; - err = nfp_tunnel_get_mac_idx_from_port(app, netdev, port, - &nfp_mac_idx); - if (err) - goto err_put_non_repr_priv; - - err = __nfp_tunnel_offload_mac(app, netdev->dev_addr, - nfp_mac_idx, false); + err = nfp_tunnel_add_shared_mac(app, netdev, port, true); if (err) goto err_put_non_repr_priv; /* Delete the previous MAC address. */ - err = __nfp_tunnel_offload_mac(app, off_mac, nfp_mac_idx, - true); + err = nfp_tunnel_del_shared_mac(app, netdev, off_mac, true); if (err) nfp_flower_cmsg_warn(app, "Failed to remove offload of replaced MAC addr on %s.\n", netdev_name(netdev)); @@ -676,9 +788,6 @@ nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev, return 0; -err_free_mac_idx: - if (non_repr) - nfp_tun_del_mac_idx(app, netdev->ifindex); err_put_non_repr_priv: if (non_repr) __nfp_flower_non_repr_priv_put(nr_priv); @@ -721,10 +830,14 @@ int nfp_tunnel_mac_event_handler(struct nfp_app *app, int nfp_tunnel_config_start(struct nfp_app *app) { struct nfp_flower_priv *priv = app->priv; + int err; + + /* Initialise rhash for MAC offload tracking. */ + err = rhashtable_init(&priv->tun.offloaded_macs, + &offloaded_macs_params); + if (err) + return err; - /* Initialise priv data for MAC offloading. */ - mutex_init(&priv->tun.mac_index_lock); - INIT_LIST_HEAD(&priv->tun.mac_index_list); ida_init(&priv->tun.mac_off_ids); /* Initialise priv data for IPv4 offloading. */ @@ -736,27 +849,25 @@ int nfp_tunnel_config_start(struct nfp_app *app) INIT_LIST_HEAD(&priv->tun.neigh_off_list); priv->tun.neigh_nb.notifier_call = nfp_tun_neigh_event_handler; - return register_netevent_notifier(&priv->tun.neigh_nb); + err = register_netevent_notifier(&priv->tun.neigh_nb); + if (err) { + rhashtable_free_and_destroy(&priv->tun.offloaded_macs, + nfp_check_rhashtable_empty, NULL); + return err; + } + + return 0; } void nfp_tunnel_config_stop(struct nfp_app *app) { struct nfp_flower_priv *priv = app->priv; struct nfp_ipv4_route_entry *route_entry; - struct nfp_tun_mac_non_nfp_idx *mac_idx; struct nfp_ipv4_addr_entry *ip_entry; struct list_head *ptr, *storage; unregister_netevent_notifier(&priv->tun.neigh_nb); - /* Free any memory that may be occupied by MAC index list. */ - list_for_each_safe(ptr, storage, &priv->tun.mac_index_list) { - mac_idx = list_entry(ptr, struct nfp_tun_mac_non_nfp_idx, - list); - list_del(&mac_idx->list); - kfree(mac_idx); - } - ida_destroy(&priv->tun.mac_off_ids); /* Free any memory that may be occupied by ipv4 list. */ @@ -773,4 +884,8 @@ void nfp_tunnel_config_stop(struct nfp_app *app) list_del(&route_entry->list); kfree(route_entry); } + + /* Destroy rhash. Entries should be cleaned on netdev notifier unreg. */ + rhashtable_free_and_destroy(&priv->tun.offloaded_macs, + nfp_check_rhashtable_empty, NULL); } -- cgit v1.2.3 From 1868e3d72236cbaf92c99b89f0bc0d8bdb0c47d4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 15 Jan 2019 21:11:14 +0100 Subject: net: phy: remove preliminary workaround for not loading PHY driver This workaround attempt helped for some but not all affected users. With commit 11287b693d03 ("r8169: load Realtek PHY driver module before r8169") we have a better workaround now, so we an remove the first attempt. Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 51990002d495..a2423cbb218d 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2250,14 +2250,6 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner) new_driver->mdiodrv.driver.remove = phy_remove; new_driver->mdiodrv.driver.owner = owner; - /* The following works around an issue where the PHY driver doesn't bind - * to the device, resulting in the genphy driver being used instead of - * the dedicated driver. The root cause of the issue isn't known yet - * and seems to be in the base driver core. Once this is fixed we may - * remove this workaround. - */ - new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS; - retval = driver_register(&new_driver->mdiodrv.driver); if (retval) { pr_err("%s: Error %d in registering driver\n", -- cgit v1.2.3 From c3a6a174d53918b810b60b2bf3e7a46c9a0a19eb Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 15 Jan 2019 21:50:25 +0100 Subject: net: phy: improve logging in phylib Some time ago phydev_info() and friends have been added. They allow to improve and simplify logging. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 5 +---- drivers/net/phy/phy_device.c | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index d33e7b3caf03..c0802d4d084e 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -13,8 +13,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -814,8 +812,7 @@ int phy_start_interrupts(struct phy_device *phydev) if (request_threaded_irq(phydev->irq, NULL, phy_interrupt, IRQF_ONESHOT | IRQF_SHARED, phydev_name(phydev), phydev) < 0) { - pr_warn("%s: Can't get IRQ %d (PHY)\n", - phydev->mdio.bus->name, phydev->irq); + phydev_warn(phydev, "Can't get IRQ %d\n", phydev->irq); phydev->irq = PHY_POLL; return 0; } diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index a2423cbb218d..1c7fe7a4c970 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -819,13 +819,13 @@ int phy_device_register(struct phy_device *phydev) /* Run all of the fixups for this PHY */ err = phy_scan_fixups(phydev); if (err) { - pr_err("PHY %d failed to initialize\n", phydev->mdio.addr); + phydev_err(phydev, "failed to initialize\n"); goto out; } err = device_add(&phydev->mdio.dev); if (err) { - pr_err("PHY %d failed to add\n", phydev->mdio.addr); + phydev_err(phydev, "failed to add\n"); goto out; } -- cgit v1.2.3 From 3fcb3f9b68b048d6b44d5cfabe21ee3145b90424 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 15 Jan 2019 21:40:51 +0100 Subject: net: phy: don't include asm/irq.h directly There's no need to and one shouldn't include asm/irq.h directly. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 2 -- drivers/net/phy/phy.c | 2 -- drivers/net/phy/phy_device.c | 2 -- 3 files changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 2e59a8419b17..741f27228088 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -39,8 +39,6 @@ #include #include -#include - #define CREATE_TRACE_POINTS #include diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index c0802d4d084e..241fb83ef4de 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -34,8 +34,6 @@ #include #include -#include - #define PHY_STATE_STR(_state) \ case PHY_##_state: \ return __stringify(_state); \ diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 1c7fe7a4c970..bb1410821ce4 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -37,8 +37,6 @@ #include #include -#include - MODULE_DESCRIPTION("PHY library"); MODULE_AUTHOR("Andy Fleming"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 78c787c21f974fe87a9c4418f57a5f76ba880608 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 15 Jan 2019 15:44:52 -0600 Subject: cxgb4/l2t: Use struct_size() in kvzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = kvzalloc(sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kvzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/l2t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c index 4852febbfec3..1a407d3c1d67 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c @@ -646,7 +646,7 @@ struct l2t_data *t4_init_l2t(unsigned int l2t_start, unsigned int l2t_end) if (l2t_size < L2T_MIN_HASH_BUCKETS) return NULL; - d = kvzalloc(sizeof(*d) + l2t_size * sizeof(struct l2t_entry), GFP_KERNEL); + d = kvzalloc(struct_size(d, l2tab, l2t_size), GFP_KERNEL); if (!d) return NULL; -- cgit v1.2.3 From 013b2dff8153b4c01d2179dbefec6b9108383802 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 11 Jan 2019 13:37:43 +0100 Subject: mt76: fix tx status reporting for non-probing frames On MT76x2, the hardware does not report tx status in the FIFO register, if the packet id is 0. Change the allocation of packet IDs to use 0 for no-ack packets, 1 for non-probing packets and 2-255 for packets with tx status requested. Fixes rate control issues Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 4 +++- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 3 +-- drivers/net/wireless/mediatek/mt76/tx.c | 9 +++++---- 5 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8ef430d8afc4..8d56ab97abe3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -239,7 +239,9 @@ struct mt76_rx_tid { #define MT_TX_CB_TXS_FAILED BIT(2) #define MT_PACKET_ID_MASK GENMASK(7, 0) -#define MT_PACKET_ID_NO_ACK MT_PACKET_ID_MASK +#define MT_PACKET_ID_NO_ACK 0 +#define MT_PACKET_ID_NO_SKB 1 +#define MT_PACKET_ID_FIRST 2 #define MT_TX_STATUS_SKB_TIMEOUT HZ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 6adea0278284..38cd77d30f5c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -433,7 +433,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, } if (wcid) { - if (stat->pktid) + if (stat->pktid >= MT_PACKET_ID_FIRST) status.skb = mt76_tx_status_skb_get(mdev, wcid, stat->pktid, &list); if (status.skb) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 4598cb2cc3ff..a5413a309a0a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -177,7 +177,7 @@ int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, if (ret < 0) return ret; - if (pid && pid != MT_PACKET_ID_NO_ACK) + if (pid >= MT_PACKET_ID_FIRST) qsel = MT_QSEL_MGMT; *tx_info = FIELD_PREP(MT_TXD_INFO_QSEL, qsel) | diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 81970cf777c0..098d05e109e7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -87,8 +87,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, pid = mt76_tx_status_skb_add(mdev, wcid, skb); txwi->pktid = pid; - if ((pid && pid != MT_PACKET_ID_NO_ACK) || - q2ep(q->hw_idx) == MT_EP_OUT_HCCA) + if (pid >= MT_PACKET_ID_FIRST || q2ep(q->hw_idx) == MT_EP_OUT_HCCA) qsel = MT_QSEL_MGMT; else qsel = MT_QSEL_EDCA; diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index f08509c1670d..1ea08ce62713 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -170,21 +170,22 @@ mt76_tx_status_skb_add(struct mt76_dev *dev, struct mt76_wcid *wcid, int pid; if (!wcid) - return 0; + return MT_PACKET_ID_NO_ACK; if (info->flags & IEEE80211_TX_CTL_NO_ACK) return MT_PACKET_ID_NO_ACK; if (!(info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS | IEEE80211_TX_CTL_RATE_CTRL_PROBE))) - return 0; + return MT_PACKET_ID_NO_SKB; spin_lock_bh(&dev->status_list.lock); memset(cb, 0, sizeof(*cb)); wcid->packet_id = (wcid->packet_id + 1) & MT_PACKET_ID_MASK; - if (!wcid->packet_id || wcid->packet_id == MT_PACKET_ID_NO_ACK) - wcid->packet_id = 1; + if (wcid->packet_id == MT_PACKET_ID_NO_ACK || + wcid->packet_id == MT_PACKET_ID_NO_SKB) + wcid->packet_id = MT_PACKET_ID_FIRST; pid = wcid->packet_id; cb->wcid = wcid->idx; -- cgit v1.2.3 From f545540d5f6007def13cf235a914891b67693828 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 16 Jan 2019 22:33:18 +0100 Subject: mt76: set IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR flag The hardware does not deal with multiple WCID entries for the same station properly. Set IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR to avoid those cases Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 7b926dfa6b97..3d976ac4cb41 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -328,6 +328,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht, ieee80211_hw_set(hw, MFP_CAPABLE); ieee80211_hw_set(hw, AP_LINK_PS); ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); + ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); wiphy->flags |= WIPHY_FLAG_IBSS_RSN; -- cgit v1.2.3 From 9313faacbb4eeb03799a86cd013e97409a40b970 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 6 Dec 2018 14:27:34 +0100 Subject: mt76: move mt76x02_get_txpower to mt76 core It will be reused by mt7603 later Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 18 ++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 3 +++ drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02.h | 2 -- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 18 ------------------ drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- 8 files changed, 25 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 3d976ac4cb41..467b5a692ed1 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -710,3 +710,21 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return 0; } EXPORT_SYMBOL_GPL(mt76_sta_state); + +int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int *dbm) +{ + struct mt76_dev *dev = hw->priv; + int n_chains = __sw_hweight8(dev->antenna_mask); + + *dbm = dev->txpower_cur / 2; + + /* convert from per-chain power to combined + * output on 2x2 devices + */ + if (n_chains > 1) + *dbm += 3; + + return 0; +} +EXPORT_SYMBOL_GPL(mt76_get_txpower); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8d56ab97abe3..16b342f63d29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -680,6 +680,9 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb); +int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + int *dbm); + /* internal */ void mt76_tx_free(struct mt76_dev *dev); struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 720b05e325a5..1472c8699b29 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -99,7 +99,7 @@ static const struct ieee80211_ops mt76x0e_ops = { .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update, .wake_tx_queue = mt76_wake_tx_queue, .get_survey = mt76_get_survey, - .get_txpower = mt76x02_get_txpower, + .get_txpower = mt76_get_txpower, .flush = mt76x0e_flush, .set_tim = mt76x0e_set_tim, .release_buffered_frames = mt76_release_buffered_frames, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 0e6b43bb4678..f66e1b2f0980 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -155,7 +155,7 @@ static const struct ieee80211_ops mt76x0u_ops = { .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update, .set_rts_threshold = mt76x02_set_rts_threshold, .wake_tx_queue = mt76_wake_tx_queue, - .get_txpower = mt76x02_get_txpower, + .get_txpower = mt76_get_txpower, }; static int mt76x0u_register_device(struct mt76x02_dev *dev) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index d8bd0509a790..6d96766a6ed3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -172,8 +172,6 @@ void mt76x02_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const u8 *mac); void mt76x02_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -int mt76x02_get_txpower(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int *dbm); void mt76x02_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps); void mt76x02_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index d80c8eb5a0ec..59f50a957cd5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -607,24 +607,6 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(mt76x02_sw_scan_complete); -int mt76x02_get_txpower(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, int *dbm) -{ - struct mt76x02_dev *dev = hw->priv; - u8 nstreams = dev->mt76.chainmask & 0xf; - - *dbm = dev->mt76.txpower_cur / 2; - - /* convert from per-chain power to combined - * output on 2x2 devices - */ - if (nstreams > 1) - *dbm += 3; - - return 0; -} -EXPORT_SYMBOL_GPL(mt76x02_get_txpower); - void mt76x02_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 6a87b88eb036..06a26a152ba4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -191,7 +191,7 @@ const struct ieee80211_ops mt76x2_ops = { .sw_scan_complete = mt76x02_sw_scan_complete, .flush = mt76x2_flush, .ampdu_action = mt76x02_ampdu_action, - .get_txpower = mt76x02_get_txpower, + .get_txpower = mt76_get_txpower, .wake_tx_queue = mt76_wake_tx_queue, .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update, .release_buffered_frames = mt76_release_buffered_frames, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 2b48cc51a30d..286c7f451090 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -138,5 +138,5 @@ const struct ieee80211_ops mt76x2u_ops = { .sw_scan_start = mt76x02_sw_scan, .sw_scan_complete = mt76x02_sw_scan_complete, .sta_rate_tbl_update = mt76x02_sta_rate_tbl_update, - .get_txpower = mt76x02_get_txpower, + .get_txpower = mt76_get_txpower, }; -- cgit v1.2.3 From ef13edc0070818f5cddb3a1d31957cc618e25e9d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 5 Dec 2018 17:06:58 +0100 Subject: mt76: move mt76x02_phy_get_min_avg_rssi to mt76 core This will be used by mt7603 as well Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 8 +++- drivers/net/wireless/mediatek/mt76/mt76.h | 8 ++++ drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 4 +- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 5 --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 6 --- drivers/net/wireless/mediatek/mt76/mt76x02_phy.c | 47 ----------------------- drivers/net/wireless/mediatek/mt76/mt76x02_phy.h | 1 - drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 - drivers/net/wireless/mediatek/mt76/mt76x2/phy.c | 4 +- drivers/net/wireless/mediatek/mt76/util.c | 42 ++++++++++++++++++++ 10 files changed, 62 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 467b5a692ed1..226f98fff6ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -548,7 +548,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb) } static void -mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb) +mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) { struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; @@ -567,6 +567,9 @@ mt76_check_ps(struct mt76_dev *dev, struct sk_buff *skb) sta = container_of((void *) wcid, struct ieee80211_sta, drv_priv); + ewma_signal_add(&wcid->rssi, status->signal); + wcid->inactive_count = 0; + if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags)) return; @@ -626,7 +629,7 @@ void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q, __skb_queue_head_init(&frames); while ((skb = __skb_dequeue(&dev->rx_skb[q])) != NULL) { - mt76_check_ps(dev, skb); + mt76_check_sta(dev, skb); mt76_rx_aggr_reorder(skb, &frames); } @@ -660,6 +663,7 @@ mt76_sta_add(struct mt76_dev *dev, struct ieee80211_vif *vif, mt76_txq_init(dev, sta->txq[i]); } + ewma_signal_init(&wcid->rssi); rcu_assign_pointer(dev->wcid[wcid->idx], wcid); out: diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 16b342f63d29..2267163d2445 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "util.h" @@ -174,6 +175,8 @@ enum mt76_wcid_flags { #define MT76_N_WCIDS 128 +DECLARE_EWMA(signal, 10, 8); + struct mt76_wcid { struct mt76_rx_tid __rcu *aggr[IEEE80211_NUM_TIDS]; @@ -181,6 +184,9 @@ struct mt76_wcid { unsigned long flags; + struct ewma_signal rssi; + int inactive_count; + u8 idx; u8 hw_key_idx; @@ -680,6 +686,8 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *mt76_rx_convert(struct sk_buff *skb); +int mt76_get_min_avg_rssi(struct mt76_dev *dev); + int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index b2b38b9fcac7..5a4c6f34267e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -1077,7 +1077,9 @@ mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev) u8 gain_delta; int low_gain; - dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); + dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76); + if (!dev->cal.avg_rssi_all) + dev->cal.avg_rssi_all = -75; low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) + (dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev)); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 38cd77d30f5c..68d01e136fa0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -656,11 +656,6 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, status->tid = FIELD_GET(MT_RXWI_TID, tid_sn); status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn); - if (sta) { - ewma_signal_add(&sta->rssi, status->signal); - sta->inactive_count = 0; - } - return mt76x02_mac_process_rate(status, rate); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 735fe96440ba..940c07f665cd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -18,8 +18,6 @@ #ifndef __MT76X02_MAC_H #define __MT76X02_MAC_H -#include - struct mt76x02_dev; struct mt76x02_tx_status { @@ -41,8 +39,6 @@ struct mt76x02_vif { u8 idx; }; -DECLARE_EWMA(signal, 10, 8); - struct mt76x02_sta { struct mt76_wcid wcid; /* must be first */ @@ -50,8 +46,6 @@ struct mt76x02_sta { struct mt76x02_tx_status status; int n_frames; - struct ewma_signal rssi; - int inactive_count; }; #define MT_RXINFO_BA BIT(0) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c index 977a8e7e26df..a020c757ba5c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.c @@ -132,53 +132,6 @@ void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_1) } EXPORT_SYMBOL_GPL(mt76x02_phy_set_txpower); -int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev) -{ - struct mt76x02_sta *sta; - struct mt76_wcid *wcid; - int i, j, min_rssi = 0; - s8 cur_rssi; - - local_bh_disable(); - rcu_read_lock(); - - for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid_mask); i++) { - unsigned long mask = dev->mt76.wcid_mask[i]; - - if (!mask) - continue; - - for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) { - if (!(mask & 1)) - continue; - - wcid = rcu_dereference(dev->mt76.wcid[j]); - if (!wcid) - continue; - - sta = container_of(wcid, struct mt76x02_sta, wcid); - spin_lock(&dev->mt76.rx_lock); - if (sta->inactive_count++ < 5) - cur_rssi = ewma_signal_read(&sta->rssi); - else - cur_rssi = 0; - spin_unlock(&dev->mt76.rx_lock); - - if (cur_rssi < min_rssi) - min_rssi = cur_rssi; - } - } - - rcu_read_unlock(); - local_bh_enable(); - - if (!min_rssi) - return -75; - - return min_rssi; -} -EXPORT_SYMBOL_GPL(mt76x02_phy_get_min_avg_rssi); - void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl) { int core_val, agc_val; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h index 2b316cf7c70c..d2971db06f13 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_phy.h @@ -51,7 +51,6 @@ void mt76x02_limit_rate_power(struct mt76_rate_power *r, int limit); int mt76x02_get_max_rate_power(struct mt76_rate_power *r); void mt76x02_phy_set_rxpath(struct mt76x02_dev *dev); void mt76x02_phy_set_txdac(struct mt76x02_dev *dev); -int mt76x02_phy_get_min_avg_rssi(struct mt76x02_dev *dev); void mt76x02_phy_set_bw(struct mt76x02_dev *dev, int width, u8 ctrl); void mt76x02_phy_set_band(struct mt76x02_dev *dev, int band, bool primary_upper); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 59f50a957cd5..0bd23d64db24 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -250,8 +250,6 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, if (vif->type == NL80211_IFTYPE_AP) set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags); - ewma_signal_init(&msta->rssi); - return 0; } EXPORT_SYMBOL_GPL(mt76x02_sta_add); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index c9634a774705..e2ee5e498da7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -284,7 +284,9 @@ void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) int low_gain; u32 val; - dev->cal.avg_rssi_all = mt76x02_phy_get_min_avg_rssi(dev); + dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76); + if (!dev->cal.avg_rssi_all) + dev->cal.avg_rssi_all = -75; low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) + (dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev)); diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 0c35b8db58cd..6242421c6011 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -75,4 +75,46 @@ int mt76_wcid_alloc(unsigned long *mask, int size) } EXPORT_SYMBOL_GPL(mt76_wcid_alloc); +int mt76_get_min_avg_rssi(struct mt76_dev *dev) +{ + struct mt76_wcid *wcid; + int i, j, min_rssi = 0; + s8 cur_rssi; + + local_bh_disable(); + rcu_read_lock(); + + for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { + unsigned long mask = dev->wcid_mask[i]; + + if (!mask) + continue; + + for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1) { + if (!(mask & 1)) + continue; + + wcid = rcu_dereference(dev->wcid[j]); + if (!wcid) + continue; + + spin_lock(&dev->rx_lock); + if (wcid->inactive_count++ < 5) + cur_rssi = ewma_signal_read(&wcid->rssi); + else + cur_rssi = 0; + spin_unlock(&dev->rx_lock); + + if (cur_rssi < min_rssi) + min_rssi = cur_rssi; + } + } + + rcu_read_unlock(); + local_bh_enable(); + + return min_rssi; +} +EXPORT_SYMBOL_GPL(mt76_get_min_avg_rssi); + MODULE_LICENSE("Dual BSD/GPL"); -- cgit v1.2.3 From 02e5a769c0a48e4e145b765329bc9d22a70261e7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 11 Jan 2019 14:17:30 +0100 Subject: mt76: fix rssi ewma tracking The generic EWMA code cannot deal with negative numbers, so convert signal to a positive number before adding it Fixes mt76x2 AGC tuning Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 4 +++- drivers/net/wireless/mediatek/mt76/util.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 226f98fff6ef..3b09d4560ae2 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -567,7 +567,9 @@ mt76_check_sta(struct mt76_dev *dev, struct sk_buff *skb) sta = container_of((void *) wcid, struct ieee80211_sta, drv_priv); - ewma_signal_add(&wcid->rssi, status->signal); + if (status->signal <= 0) + ewma_signal_add(&wcid->rssi, -status->signal); + wcid->inactive_count = 0; if (!test_bit(MT_WCID_FLAG_CHECK_PS, &wcid->flags)) diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 6242421c6011..69270c1a9091 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -100,7 +100,7 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev) spin_lock(&dev->rx_lock); if (wcid->inactive_count++ < 5) - cur_rssi = ewma_signal_read(&wcid->rssi); + cur_rssi = -ewma_signal_read(&wcid->rssi); else cur_rssi = 0; spin_unlock(&dev->rx_lock); -- cgit v1.2.3 From 9cf67ec7fd8077fdf7909449534e32b8438b5edc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 29 Dec 2018 13:01:31 +0100 Subject: mt76: fix signedness of rx status signal field It is usually negative, so it needs to be signed. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 2267163d2445..0435d623e9ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -497,7 +497,7 @@ struct mt76_rx_status { u8 rate_idx; u8 nss; u8 band; - u8 signal; + s8 signal; u8 chains; s8 chain_signal[IEEE80211_MAX_CHAINS]; }; -- cgit v1.2.3 From e7173858c78a981788bde18930d1e16fd5203151 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 15 Jan 2019 14:26:53 +0100 Subject: mt76: add channel switch announcement support Use the appropriate mac80211 callbacks after beacon transmission Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 39 +++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 5 +++ drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 13 ++++++-- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 ++ 4 files changed, 57 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 3b09d4560ae2..ee3b65a14870 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -734,3 +734,42 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return 0; } EXPORT_SYMBOL_GPL(mt76_get_txpower); + +static void +__mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + if (vif->csa_active && ieee80211_csa_is_complete(vif)) + ieee80211_csa_finish(vif); +} + +void mt76_csa_finish(struct mt76_dev *dev) +{ + if (!dev->csa_complete) + return; + + ieee80211_iterate_active_interfaces_atomic(dev->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + __mt76_csa_finish, dev); + + dev->csa_complete = 0; +} +EXPORT_SYMBOL_GPL(mt76_csa_finish); + +static void +__mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt76_dev *dev = priv; + + if (!vif->csa_active) + return; + + dev->csa_complete |= ieee80211_csa_is_complete(vif); +} + +void mt76_csa_check(struct mt76_dev *dev) +{ + ieee80211_iterate_active_interfaces_atomic(dev->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + __mt76_csa_check, dev); +} +EXPORT_SYMBOL_GPL(mt76_csa_check); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 0435d623e9ad..2bb9db4ed80a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -463,6 +463,8 @@ struct mt76_dev { bool led_al; u8 led_pin; + u8 csa_complete; + u32 rxfilter; union { @@ -691,6 +693,9 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev); int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm); +void mt76_csa_check(struct mt76_dev *dev); +void mt76_csa_finish(struct mt76_dev *dev); + /* internal */ void mt76_tx_free(struct mt76_dev *dev); struct mt76_txwi_cache *mt76_get_txwi(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 6236c6121c01..374bc9d91f12 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -116,6 +116,11 @@ static void mt76x02_pre_tbtt_tasklet(unsigned long arg) IEEE80211_IFACE_ITER_RESUME_ALL, mt76x02_update_beacon_iter, dev); + mt76_csa_check(&dev->mt76); + + if (dev->mt76.csa_complete) + return; + do { nframes = skb_queue_len(&data.q); ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), @@ -309,8 +314,12 @@ irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance) tasklet_schedule(&dev->pre_tbtt_tasklet); /* send buffered multicast frames now */ - if (intr & MT_INT_TBTT) - mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]); + if (intr & MT_INT_TBTT) { + if (dev->mt76.csa_complete) + mt76_csa_finish(&dev->mt76); + else + mt76_queue_kick(dev, &dev->mt76.q_tx[MT_TXQ_PSD]); + } if (intr & MT_INT_TX_STAT) { mt76x02_mac_poll_tx_status(dev, true); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 0bd23d64db24..062614ad0d51 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -160,6 +160,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev) #endif BIT(NL80211_IFTYPE_ADHOC); + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); /* init led callbacks */ -- cgit v1.2.3 From 905b464ad9008905db099f90ae20f373c7051804 Mon Sep 17 00:00:00 2001 From: Xue Chaojing Date: Tue, 15 Jan 2019 17:48:52 +0000 Subject: net-next/hinic: replace disable_irq_nosync/enable_irq In order to avoid frequent system interrupts when sending and receiving packets. we replace disable_irq_nosync/enable_irq with hinic_set_msix_state(), hinic_set_msix_state is used to access memory mapped hinic devices. Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller --- drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c | 13 +++++++++++ drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h | 3 +++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.c | 28 ++++++++++++++++++++++++ drivers/net/ethernet/huawei/hinic/hinic_hw_if.h | 14 ++++++++++++ drivers/net/ethernet/huawei/hinic/hinic_rx.c | 11 ++++++++-- drivers/net/ethernet/huawei/hinic/hinic_tx.c | 8 +++++-- 6 files changed, 73 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 6b19607a4caa..3875f39f43bb 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -1008,3 +1008,16 @@ int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq, &hw_ci, sizeof(hw_ci), NULL, NULL, HINIC_MGMT_MSG_SYNC); } + +/** + * hinic_hwdev_set_msix_state- set msix state + * @hwdev: the NIC HW device + * @msix_index: IRQ corresponding index number + * @flag: msix state + * + **/ +void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index, + enum hinic_msix_state flag) +{ + hinic_set_msix_state(hwdev->hwif, msix_index, flag); +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index d1a7d2522d82..c9e621e19dd0 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -240,4 +240,7 @@ int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index, int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq, u8 pending_limit, u8 coalesc_timer); +void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index, + enum hinic_msix_state flag); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c index 823a17061a97..9b160f076904 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c @@ -168,6 +168,22 @@ void hinic_db_state_set(struct hinic_hwif *hwif, hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4); } +void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx, + enum hinic_msix_state flag) +{ + u32 offset = msix_idx * HINIC_PCI_MSIX_ENTRY_SIZE + + HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL; + u32 mask_bits; + + mask_bits = readl(hwif->intr_regs_base + offset); + mask_bits &= ~HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT; + + if (flag) + mask_bits |= HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT; + + writel(mask_bits, hwif->intr_regs_base + offset); +} + /** * hwif_ready - test if the HW is ready for use * @hwif: the HW interface of a pci function device @@ -321,6 +337,13 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev) return -ENOMEM; } + hwif->intr_regs_base = pci_ioremap_bar(pdev, HINIC_PCI_INTR_REGS_BAR); + if (!hwif->intr_regs_base) { + dev_err(&pdev->dev, "Failed to map configuration regs\n"); + err = -ENOMEM; + goto err_map_intr_bar; + } + err = hwif_ready(hwif); if (err) { dev_err(&pdev->dev, "HW interface is not ready\n"); @@ -337,7 +360,11 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev) return 0; err_hwif_ready: + iounmap(hwif->intr_regs_base); + +err_map_intr_bar: iounmap(hwif->cfg_regs_bar); + return err; } @@ -347,5 +374,6 @@ err_hwif_ready: **/ void hinic_free_hwif(struct hinic_hwif *hwif) { + iounmap(hwif->intr_regs_base); iounmap(hwif->cfg_regs_bar); } diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h index 5b4760c0e9f5..22ec7f73e0a6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h @@ -152,6 +152,7 @@ #define HINIC_IS_PPF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PPF) #define HINIC_PCI_CFG_REGS_BAR 0 +#define HINIC_PCI_INTR_REGS_BAR 2 #define HINIC_PCI_DB_BAR 4 #define HINIC_PCIE_ST_DISABLE 0 @@ -164,6 +165,10 @@ #define HINIC_EQ_MSIX_LLI_CREDIT_LIMIT_DEFAULT 0 /* Disabled */ #define HINIC_EQ_MSIX_RESEND_TIMER_DEFAULT 7 /* max */ +#define HINIC_PCI_MSIX_ENTRY_SIZE 16 +#define HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL 12 +#define HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT 1 + enum hinic_pcie_nosnoop { HINIC_PCIE_SNOOP = 0, HINIC_PCIE_NO_SNOOP = 1, @@ -207,6 +212,11 @@ enum hinic_db_state { HINIC_DB_DISABLE = 1, }; +enum hinic_msix_state { + HINIC_MSIX_ENABLE, + HINIC_MSIX_DISABLE, +}; + struct hinic_func_attr { u16 func_idx; u8 pf_idx; @@ -226,6 +236,7 @@ struct hinic_func_attr { struct hinic_hwif { struct pci_dev *pdev; void __iomem *cfg_regs_bar; + void __iomem *intr_regs_base; struct hinic_func_attr attr; }; @@ -251,6 +262,9 @@ int hinic_msix_attr_get(struct hinic_hwif *hwif, u16 msix_index, u8 *lli_timer, u8 *lli_credit_limit, u8 *resend_timer); +void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx, + enum hinic_msix_state flag); + int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index); void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c index 0098b206e7e9..b6d218768ec1 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c @@ -381,6 +381,7 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget) static int rx_poll(struct napi_struct *napi, int budget) { struct hinic_rxq *rxq = container_of(napi, struct hinic_rxq, napi); + struct hinic_dev *nic_dev = netdev_priv(rxq->netdev); struct hinic_rq *rq = rxq->rq; int pkts; @@ -389,7 +390,10 @@ static int rx_poll(struct napi_struct *napi, int budget) return budget; napi_complete(napi); - enable_irq(rq->irq); + hinic_hwdev_set_msix_state(nic_dev->hwdev, + rq->msix_entry, + HINIC_MSIX_ENABLE); + return pkts; } @@ -414,7 +418,10 @@ static irqreturn_t rx_irq(int irq, void *data) struct hinic_dev *nic_dev; /* Disable the interrupt until napi will be completed */ - disable_irq_nosync(rq->irq); + nic_dev = netdev_priv(rxq->netdev); + hinic_hwdev_set_msix_state(nic_dev->hwdev, + rq->msix_entry, + HINIC_MSIX_DISABLE); nic_dev = netdev_priv(rxq->netdev); hinic_hwdev_msix_cnt_set(nic_dev->hwdev, rq->msix_entry); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c index 11e73e67358d..e17bf33eba0c 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c @@ -655,7 +655,9 @@ static int free_tx_poll(struct napi_struct *napi, int budget) if (pkts < budget) { napi_complete(napi); - enable_irq(sq->irq); + hinic_hwdev_set_msix_state(nic_dev->hwdev, + sq->msix_entry, + HINIC_MSIX_ENABLE); return pkts; } @@ -682,7 +684,9 @@ static irqreturn_t tx_irq(int irq, void *data) nic_dev = netdev_priv(txq->netdev); /* Disable the interrupt until napi will be completed */ - disable_irq_nosync(txq->sq->irq); + hinic_hwdev_set_msix_state(nic_dev->hwdev, + txq->sq->msix_entry, + HINIC_MSIX_DISABLE); hinic_hwdev_msix_cnt_set(nic_dev->hwdev, txq->sq->msix_entry); -- cgit v1.2.3 From 5db5ea995fc2fa89fdef61ef3a658cbb41a24222 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 15 Jan 2019 15:09:35 -0800 Subject: net: phy: Add helpers to determine if PHY driver is generic We are already checking in phy_detach() that the PHY driver is of generic kind (1G or 10G) and we are going to make use of that in the SFP layer as well for 1000BaseT SFP modules, so expose helper functions to return that information. Signed-off-by: Florian Fainelli Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 34 ++++++++++++++++++++++++++++++++-- include/linux/phy.h | 3 +++ 2 files changed, 35 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index bb1410821ce4..c02669270c41 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1277,6 +1277,36 @@ struct phy_device *phy_attach(struct net_device *dev, const char *bus_id, } EXPORT_SYMBOL(phy_attach); +static bool phy_driver_is_genphy_kind(struct phy_device *phydev, + struct device_driver *driver) +{ + struct device *d = &phydev->mdio.dev; + bool ret = false; + + if (!phydev->drv) + return ret; + + get_device(d); + ret = d->driver == driver; + put_device(d); + + return ret; +} + +bool phy_driver_is_genphy(struct phy_device *phydev) +{ + return phy_driver_is_genphy_kind(phydev, + &genphy_driver.mdiodrv.driver); +} +EXPORT_SYMBOL_GPL(phy_driver_is_genphy); + +bool phy_driver_is_genphy_10g(struct phy_device *phydev) +{ + return phy_driver_is_genphy_kind(phydev, + &genphy_10g_driver.mdiodrv.driver); +} +EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g); + /** * phy_detach - detach a PHY device from its network device * @phydev: target phy_device struct @@ -1308,8 +1338,8 @@ void phy_detach(struct phy_device *phydev) * from the generic driver so that there's a chance a * real driver could be loaded */ - if (phydev->mdio.dev.driver == &genphy_10g_driver.mdiodrv.driver || - phydev->mdio.dev.driver == &genphy_driver.mdiodrv.driver) + if (phy_driver_is_genphy(phydev) || + phy_driver_is_genphy_10g(phydev)) device_release_driver(&phydev->mdio.dev); /* diff --git a/include/linux/phy.h b/include/linux/phy.h index 3b051f761450..f1c19bf8c658 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1183,4 +1183,7 @@ module_exit(phy_module_exit) #define module_phy_driver(__phy_drivers) \ phy_module_driver(__phy_drivers, ARRAY_SIZE(__phy_drivers)) +bool phy_driver_is_genphy(struct phy_device *phydev); +bool phy_driver_is_genphy_10g(struct phy_device *phydev); + #endif /* __PHY_H */ -- cgit v1.2.3 From 4559dd248297cf8eb0318cff971d5f5c33660b6c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 15 Jan 2019 19:04:56 -0600 Subject: net: hns: Use struct_size() in devm_kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = devm_kzalloc(dev, sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = devm_kzalloc(dev, struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 5d64519b9b1d..6bf346c11b25 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -788,8 +788,9 @@ int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, int ring_num = hns_rcb_get_ring_num(dsaf_dev); rcb_common = - devm_kzalloc(dsaf_dev->dev, sizeof(*rcb_common) + - ring_num * sizeof(struct ring_pair_cb), GFP_KERNEL); + devm_kzalloc(dsaf_dev->dev, + struct_size(rcb_common, ring_pair_cb, ring_num), + GFP_KERNEL); if (!rcb_common) { dev_err(dsaf_dev->dev, "rcb common devm_kzalloc fail!\n"); return -ENOMEM; -- cgit v1.2.3 From 13d0ab6750b20957ac1466da4e44dc0af746ff28 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 16 Jan 2019 08:07:38 +0100 Subject: net: phy: check return code when requesting PHY driver module When requesting the PHY driver module fails we'll bind the genphy driver later. This isn't obvious to the user and may cause, depending on the PHY, different types of issues. Therefore check the return code of request_module(). Note that we only check for failures in loading the module, not whether a module exists for the respective PHY ID. v2: - add comment explaining what is checked and what is not - return error from phy_device_create() if loading module fails Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index c02669270c41..ddb12f420940 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -546,12 +546,31 @@ static const struct device_type mdio_bus_phy_type = { .pm = MDIO_BUS_PHY_PM_OPS, }; +static int phy_request_driver_module(struct phy_device *dev, int phy_id) +{ + int ret; + + ret = request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, + MDIO_ID_ARGS(phy_id)); + /* we only check for failures in executing the usermode binary, + * not whether a PHY driver module exists for the PHY ID + */ + if (IS_ENABLED(CONFIG_MODULES) && ret < 0) { + phydev_err(dev, "error %d loading PHY driver module for ID 0x%08x\n", + ret, phy_id); + return ret; + } + + return 0; +} + struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, bool is_c45, struct phy_c45_device_ids *c45_ids) { struct phy_device *dev; struct mdio_device *mdiodev; + int ret = 0; /* We allocate the device, and initialize the default values */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); @@ -608,15 +627,21 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, if (!(c45_ids->devices_in_package & (1 << i))) continue; - request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, - MDIO_ID_ARGS(c45_ids->device_ids[i])); + ret = phy_request_driver_module(dev, + c45_ids->device_ids[i]); + if (ret) + break; } } else { - request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, - MDIO_ID_ARGS(phy_id)); + ret = phy_request_driver_module(dev, phy_id); } - device_initialize(&mdiodev->dev); + if (!ret) { + device_initialize(&mdiodev->dev); + } else { + kfree(dev); + dev = ERR_PTR(ret); + } return dev; } -- cgit v1.2.3 From 5fb1beeceab857d57312e9351d836f168b513027 Mon Sep 17 00:00:00 2001 From: Bert Kenward Date: Wed, 16 Jan 2019 10:00:39 +0000 Subject: sfc: extend MTD support for newer hardware The X2 family of NICs (based on the SFC9250) have additional MTD partitions for firmware and configuration. This includes partitions that are read-only. The NICs also have extended versions of the NVRAM interface, allowing more detailed status information to be returned. Signed-off-by: Bert Kenward Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef10.c | 14 ++++++++--- drivers/net/ethernet/sfc/mcdi.c | 56 +++++++++++++++++++++++++++++++++++------ drivers/net/ethernet/sfc/mtd.c | 3 +++ 3 files changed, 63 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index b6a50058bb8d..ee42d4a887d7 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -6041,10 +6041,11 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = { { NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT3, 0, 3, "sfc_exp_rom_cfg" }, { NVRAM_PARTITION_TYPE_LICENSE, 0, 0, "sfc_license" }, { NVRAM_PARTITION_TYPE_PHY_MIN, 0xff, 0, "sfc_phy_fw" }, - /* MUM and SUC firmware share the same partition type */ { NVRAM_PARTITION_TYPE_MUM_FIRMWARE, 0, 0, "sfc_mumfw" }, { NVRAM_PARTITION_TYPE_EXPANSION_UEFI, 0, 0, "sfc_uefi" }, - { NVRAM_PARTITION_TYPE_STATUS, 0, 0, "sfc_status" } + { NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS, 0, 0, "sfc_dynamic_cfg_dflt" }, + { NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS, 0, 0, "sfc_exp_rom_cfg_dflt" }, + { NVRAM_PARTITION_TYPE_STATUS, 0, 0, "sfc_status" }, }; static int efx_ef10_mtd_probe_partition(struct efx_nic *efx, @@ -6071,8 +6072,15 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx, rc = efx_mcdi_nvram_info(efx, type, &size, &erase_size, &protected); if (rc) return rc; + if (protected && + (type != NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS && + type != NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS)) + /* Hide protected partitions that don't provide defaults. */ + return -ENODEV; + if (protected) - return -ENODEV; /* hide it */ + /* Protected partitions are read only. */ + erase_size = 0; part->nvram_type = type; diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index dfad93fca0a6..295ec1787b9f 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -2074,22 +2074,26 @@ fail: static int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type) { - MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN); + MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN); int rc; MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type); + MCDI_POPULATE_DWORD_1(inbuf, NVRAM_UPDATE_START_V2_IN_FLAGS, + NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, + 1); BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf), NULL, 0, NULL); + return rc; } static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type, loff_t offset, u8 *buffer, size_t length) { - MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN); + MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_V2_LEN); MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX)); size_t outlen; @@ -2098,6 +2102,8 @@ static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type, MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type); MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset); MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length); + MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_V2_MODE, + MC_CMD_NVRAM_READ_IN_V2_DEFAULT); rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); @@ -2147,15 +2153,51 @@ static int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type, static int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type) { - MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN); - int rc; + MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN); + MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN); + size_t outlen; + int rc, rc2; MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type); - - BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0); + /* Always set this flag. Old firmware ignores it */ + MCDI_POPULATE_DWORD_1(inbuf, NVRAM_UPDATE_FINISH_V2_IN_FLAGS, + NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, + 1); rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf), - NULL, 0, NULL); + outbuf, sizeof(outbuf), &outlen); + if (!rc && outlen >= MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) { + rc2 = MCDI_DWORD(outbuf, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE); + if (rc2 != MC_CMD_NVRAM_VERIFY_RC_SUCCESS) + netif_err(efx, drv, efx->net_dev, + "NVRAM update failed verification with code 0x%x\n", + rc2); + switch (rc2) { + case MC_CMD_NVRAM_VERIFY_RC_SUCCESS: + break; + case MC_CMD_NVRAM_VERIFY_RC_CMS_CHECK_FAILED: + case MC_CMD_NVRAM_VERIFY_RC_MESSAGE_DIGEST_CHECK_FAILED: + case MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHECK_FAILED: + case MC_CMD_NVRAM_VERIFY_RC_TRUSTED_APPROVERS_CHECK_FAILED: + case MC_CMD_NVRAM_VERIFY_RC_SIGNATURE_CHAIN_CHECK_FAILED: + rc = -EIO; + break; + case MC_CMD_NVRAM_VERIFY_RC_INVALID_CMS_FORMAT: + case MC_CMD_NVRAM_VERIFY_RC_BAD_MESSAGE_DIGEST: + rc = -EINVAL; + break; + case MC_CMD_NVRAM_VERIFY_RC_NO_VALID_SIGNATURES: + case MC_CMD_NVRAM_VERIFY_RC_NO_TRUSTED_APPROVERS: + case MC_CMD_NVRAM_VERIFY_RC_NO_SIGNATURE_MATCH: + rc = -EPERM; + break; + default: + netif_err(efx, drv, efx->net_dev, + "Unknown response to NVRAM_UPDATE_FINISH\n"); + rc = -EIO; + } + } + return rc; } diff --git a/drivers/net/ethernet/sfc/mtd.c b/drivers/net/ethernet/sfc/mtd.c index 4ac30b6e5dab..0d03e0577d85 100644 --- a/drivers/net/ethernet/sfc/mtd.c +++ b/drivers/net/ethernet/sfc/mtd.c @@ -66,6 +66,9 @@ int efx_mtd_add(struct efx_nic *efx, struct efx_mtd_partition *parts, part->mtd.writesize = 1; + if (!(part->mtd.flags & MTD_NO_ERASE)) + part->mtd.flags |= MTD_WRITEABLE; + part->mtd.owner = THIS_MODULE; part->mtd.priv = efx; part->mtd.name = part->name; -- cgit v1.2.3 From aed13f2e00ce278f039b76e7ac84d419aff48ef6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 16 Jan 2019 11:23:33 +0100 Subject: net: dsa: lantiq_gswip: fix use-after-free on failed probe Make sure to disable and deregister the switch on late probe errors to avoid use-after-free when the device-resource-managed switch is freed. Fixes: 14fceff4771e ("net: dsa: Add Lantiq / Intel DSA driver for vrx200") Cc: stable # 4.20 Cc: Hauke Mehrtens Signed-off-by: Johan Hovold Reviewed-by: Andrew Lunn Acked-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/dsa/lantiq_gswip.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 693a67f45bef..b06c41c98de9 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -1099,7 +1099,7 @@ static int gswip_probe(struct platform_device *pdev) dev_err(dev, "wrong CPU port defined, HW only supports port: %i", priv->hw_info->cpu_port); err = -EINVAL; - goto mdio_bus; + goto disable_switch; } platform_set_drvdata(pdev, priv); @@ -1109,6 +1109,9 @@ static int gswip_probe(struct platform_device *pdev) (version & GSWIP_VERSION_MOD_MASK) >> GSWIP_VERSION_MOD_SHIFT); return 0; +disable_switch: + gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); + dsa_unregister_switch(priv->ds); mdio_bus: if (mdio_np) mdiobus_unregister(priv->ds->slave_mii_bus); -- cgit v1.2.3 From c8cbcb0d8bd72d44fad1a5ddc348ac10e0fb1b37 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 16 Jan 2019 11:23:34 +0100 Subject: net: dsa: lantiq_gswip: fix OF child-node lookups Use the new of_get_compatible_child() helper to look up child nodes to avoid ever matching non-child nodes elsewhere in the tree. Also fix up the related struct device_node leaks. Fixes: 14fceff4771e ("net: dsa: Add Lantiq / Intel DSA driver for vrx200") Cc: stable # 4.20 Cc: Hauke Mehrtens Signed-off-by: Johan Hovold Reviewed-by: Andrew Lunn Acked-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/dsa/lantiq_gswip.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index b06c41c98de9..5792674dd4e4 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -1069,10 +1069,10 @@ static int gswip_probe(struct platform_device *pdev) version = gswip_switch_r(priv, GSWIP_VERSION); /* bring up the mdio bus */ - gphy_fw_np = of_find_compatible_node(pdev->dev.of_node, NULL, - "lantiq,gphy-fw"); + gphy_fw_np = of_get_compatible_child(dev->of_node, "lantiq,gphy-fw"); if (gphy_fw_np) { err = gswip_gphy_fw_list(priv, gphy_fw_np, version); + of_node_put(gphy_fw_np); if (err) { dev_err(dev, "gphy fw probe failed\n"); return err; @@ -1080,13 +1080,12 @@ static int gswip_probe(struct platform_device *pdev) } /* bring up the mdio bus */ - mdio_np = of_find_compatible_node(pdev->dev.of_node, NULL, - "lantiq,xrx200-mdio"); + mdio_np = of_get_compatible_child(dev->of_node, "lantiq,xrx200-mdio"); if (mdio_np) { err = gswip_mdio(priv, mdio_np); if (err) { dev_err(dev, "mdio probe failed\n"); - goto gphy_fw; + goto put_mdio_node; } } @@ -1115,7 +1114,8 @@ disable_switch: mdio_bus: if (mdio_np) mdiobus_unregister(priv->ds->slave_mii_bus); -gphy_fw: +put_mdio_node: + of_node_put(mdio_np); for (i = 0; i < priv->num_gphy_fw; i++) gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]); return err; @@ -1134,8 +1134,10 @@ static int gswip_remove(struct platform_device *pdev) dsa_unregister_switch(priv->ds); - if (priv->ds->slave_mii_bus) + if (priv->ds->slave_mii_bus) { mdiobus_unregister(priv->ds->slave_mii_bus); + of_node_put(priv->ds->slave_mii_bus->dev.of_node); + } for (i = 0; i < priv->num_gphy_fw; i++) gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]); -- cgit v1.2.3 From 8bb18f69c71f5fedaded2d0337dd8a0d15b51ea5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 16 Jan 2019 11:23:35 +0100 Subject: net: dsa: lantiq_gswip: drop bogus drvdata check The platform-device driver data is set on successful probe and will never be NULL on remove (or we have much bigger problems). Signed-off-by: Johan Hovold Reviewed-by: Andrew Lunn Acked-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/dsa/lantiq_gswip.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 5792674dd4e4..27d092cab40e 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -1126,9 +1126,6 @@ static int gswip_remove(struct platform_device *pdev) struct gswip_priv *priv = platform_get_drvdata(pdev); int i; - if (!priv) - return 0; - /* disable the switch */ gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB); -- cgit v1.2.3 From 43deda5408f913604bbca8c197f2cb25f22c4030 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Wed, 16 Jan 2019 20:49:25 +0100 Subject: davicom: Annotate implicit fall through in dm9000_set_io There is a plan to build the kernel with -Wimplicit-fallthrough and this place in the code produced a warning (W=1). This commit removes the following warning: include/linux/device.h:1480:5: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/ethernet/davicom/dm9000.c:397:3: note: in expansion of macro 'dev_dbg' drivers/net/ethernet/davicom/dm9000.c:398:2: note: here Signed-off-by: Mathieu Malaterre Signed-off-by: David S. Miller --- drivers/net/ethernet/davicom/dm9000.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 0a82fcf16d35..c2586f44c29d 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -395,6 +395,7 @@ static void dm9000_set_io(struct board_info *db, int byte_width) case 3: dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n"); + /* fall through */ case 2: db->dumpblk = dm9000_dumpblk_16bit; db->outblk = dm9000_outblk_16bit; -- cgit v1.2.3 From 9b420eff9fcf69a85034c1e657a861de575c96e1 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 16 Jan 2019 21:52:22 +0100 Subject: net: phy: micrel: use phy_read_mmd and phy_write_mmd This driver implements open-coded versions of phy_read_mmd() and phy_write_mmd() for KSZ9031. That's not needed, let's use the phylib functions directly. This is compile-tested only because I have no such hardware. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/micrel.c | 43 +++++++++++-------------------------------- 1 file changed, 11 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index c33384710d26..670698b7ef0e 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -426,9 +426,6 @@ static int ksz9021_config_init(struct phy_device *phydev) return 0; } -#define MII_KSZ9031RN_MMD_CTRL_REG 0x0d -#define MII_KSZ9031RN_MMD_REGDATA_REG 0x0e -#define OP_DATA 1 #define KSZ9031_PS_TO_REG 60 /* Extended registers */ @@ -446,24 +443,6 @@ static int ksz9021_config_init(struct phy_device *phydev) #define MII_KSZ9031RN_EDPD 0x23 #define MII_KSZ9031RN_EDPD_ENABLE BIT(0) -static int ksz9031_extended_write(struct phy_device *phydev, - u8 mode, u32 dev_addr, u32 regnum, u16 val) -{ - phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr); - phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum); - phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr); - return phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, val); -} - -static int ksz9031_extended_read(struct phy_device *phydev, - u8 mode, u32 dev_addr, u32 regnum) -{ - phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, dev_addr); - phy_write(phydev, MII_KSZ9031RN_MMD_REGDATA_REG, regnum); - phy_write(phydev, MII_KSZ9031RN_MMD_CTRL_REG, (mode << 14) | dev_addr); - return phy_read(phydev, MII_KSZ9031RN_MMD_REGDATA_REG); -} - static int ksz9031_of_load_skew_values(struct phy_device *phydev, const struct device_node *of_node, u16 reg, size_t field_sz, @@ -484,7 +463,7 @@ static int ksz9031_of_load_skew_values(struct phy_device *phydev, return 0; if (matches < numfields) - newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg); + newval = phy_read_mmd(phydev, 2, reg); else newval = 0; @@ -498,7 +477,7 @@ static int ksz9031_of_load_skew_values(struct phy_device *phydev, << (field_sz * i)); } - return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval); + return phy_write_mmd(phydev, 2, reg, newval); } /* Center KSZ9031RNX FLP timing at 16ms. */ @@ -506,13 +485,13 @@ static int ksz9031_center_flp_timing(struct phy_device *phydev) { int result; - result = ksz9031_extended_write(phydev, OP_DATA, 0, - MII_KSZ9031RN_FLP_BURST_TX_HI, 0x0006); + result = phy_write_mmd(phydev, 0, MII_KSZ9031RN_FLP_BURST_TX_HI, + 0x0006); if (result) return result; - result = ksz9031_extended_write(phydev, OP_DATA, 0, - MII_KSZ9031RN_FLP_BURST_TX_LO, 0x1A80); + result = phy_write_mmd(phydev, 0, MII_KSZ9031RN_FLP_BURST_TX_LO, + 0x1A80); if (result) return result; @@ -524,11 +503,11 @@ static int ksz9031_enable_edpd(struct phy_device *phydev) { int reg; - reg = ksz9031_extended_read(phydev, OP_DATA, 0x1C, MII_KSZ9031RN_EDPD); + reg = phy_read_mmd(phydev, 0x1C, MII_KSZ9031RN_EDPD); if (reg < 0) return reg; - return ksz9031_extended_write(phydev, OP_DATA, 0x1C, MII_KSZ9031RN_EDPD, - reg | MII_KSZ9031RN_EDPD_ENABLE); + return phy_write_mmd(phydev, 0x1C, MII_KSZ9031RN_EDPD, + reg | MII_KSZ9031RN_EDPD_ENABLE); } static int ksz9031_config_init(struct phy_device *phydev) @@ -654,7 +633,7 @@ static int ksz9131_of_load_skew_values(struct phy_device *phydev, return 0; if (matches < numfields) - newval = ksz9031_extended_read(phydev, OP_DATA, 2, reg); + newval = phy_read_mmd(phydev, 2, reg); else newval = 0; @@ -668,7 +647,7 @@ static int ksz9131_of_load_skew_values(struct phy_device *phydev, << (field_sz * i)); } - return ksz9031_extended_write(phydev, OP_DATA, 2, reg, newval); + return phy_write_mmd(phydev, 2, reg, newval); } static int ksz9131_config_init(struct phy_device *phydev) -- cgit v1.2.3 From c2b200e0bac0a0667f2de18e0806fcf71b745080 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:30 +0000 Subject: vxlan: Move up vxlan_fdb_free(), vxlan_fdb_destroy() These functions will be needed for rollbacks of vetoed FDB entries. Move them up so that they are visible at their intended point of use. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 59 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 5209ee9aac47..e4ace5e917a7 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -826,6 +826,35 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan, return 0; } +static void vxlan_fdb_free(struct rcu_head *head) +{ + struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); + struct vxlan_rdst *rd, *nd; + + list_for_each_entry_safe(rd, nd, &f->remotes, list) { + dst_cache_destroy(&rd->dst_cache); + kfree(rd); + } + kfree(f); +} + +static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, + bool do_notify, bool swdev_notify) +{ + struct vxlan_rdst *rd; + + netdev_dbg(vxlan->dev, "delete %pM\n", f->eth_addr); + + --vxlan->addrcnt; + if (do_notify) + list_for_each_entry(rd, &f->remotes, list) + vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH, + swdev_notify); + + hlist_del_rcu(&f->hlist); + call_rcu(&f->rcu, vxlan_fdb_free); +} + /* Add new entry to forwarding table -- assumes lock held */ static int vxlan_fdb_update(struct vxlan_dev *vxlan, const u8 *mac, union vxlan_addr *ip, @@ -912,36 +941,6 @@ static int vxlan_fdb_update(struct vxlan_dev *vxlan, return 0; } -static void vxlan_fdb_free(struct rcu_head *head) -{ - struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); - struct vxlan_rdst *rd, *nd; - - list_for_each_entry_safe(rd, nd, &f->remotes, list) { - dst_cache_destroy(&rd->dst_cache); - kfree(rd); - } - kfree(f); -} - -static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, - bool do_notify, bool swdev_notify) -{ - struct vxlan_rdst *rd; - - netdev_dbg(vxlan->dev, - "delete %pM\n", f->eth_addr); - - --vxlan->addrcnt; - if (do_notify) - list_for_each_entry(rd, &f->remotes, list) - vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH, - swdev_notify); - - hlist_del_rcu(&f->hlist); - call_rcu(&f->rcu, vxlan_fdb_free); -} - static void vxlan_dst_free(struct rcu_head *head) { struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu); -- cgit v1.2.3 From a76d1ca296a7eefba5d186014fc4cd14ee98c28b Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:32 +0000 Subject: vxlan: Split vxlan_fdb_update() in two In order to make it easier to implement rollbacks after FDB update vetoing, separate the FDB update code to two parts: one that deals with updates of existing FDB entries, and one that creates new entries. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 158 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index e4ace5e917a7..aeaa429229c7 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -855,92 +855,128 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, call_rcu(&f->rcu, vxlan_fdb_free); } -/* Add new entry to forwarding table -- assumes lock held */ -static int vxlan_fdb_update(struct vxlan_dev *vxlan, - const u8 *mac, union vxlan_addr *ip, - __u16 state, __u16 flags, - __be16 port, __be32 src_vni, __be32 vni, - __u32 ifindex, __u16 ndm_flags, - bool swdev_notify) +static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, + union vxlan_addr *ip, + __u16 state, __u16 flags, + __be16 port, __be32 vni, + __u32 ifindex, __u16 ndm_flags, + struct vxlan_fdb *f, + bool swdev_notify) { __u16 fdb_flags = (ndm_flags & ~NTF_USE); struct vxlan_rdst *rd = NULL; - struct vxlan_fdb *f; int notify = 0; int rc; - f = __vxlan_find_mac(vxlan, mac, src_vni); - if (f) { - if (flags & NLM_F_EXCL) { - netdev_dbg(vxlan->dev, - "lost race to create %pM\n", mac); - return -EEXIST; - } - - /* Do not allow an externally learned entry to take over an - * entry added by the user. - */ - if (!(fdb_flags & NTF_EXT_LEARNED) || - !(f->flags & NTF_VXLAN_ADDED_BY_USER)) { - if (f->state != state) { - f->state = state; - f->updated = jiffies; - notify = 1; - } - if (f->flags != fdb_flags) { - f->flags = fdb_flags; - f->updated = jiffies; - notify = 1; - } + /* Do not allow an externally learned entry to take over an entry added + * by the user. + */ + if (!(fdb_flags & NTF_EXT_LEARNED) || + !(f->flags & NTF_VXLAN_ADDED_BY_USER)) { + if (f->state != state) { + f->state = state; + f->updated = jiffies; + notify = 1; } - - if ((flags & NLM_F_REPLACE)) { - /* Only change unicasts */ - if (!(is_multicast_ether_addr(f->eth_addr) || - is_zero_ether_addr(f->eth_addr))) { - notify |= vxlan_fdb_replace(f, ip, port, vni, - ifindex); - } else - return -EOPNOTSUPP; + if (f->flags != fdb_flags) { + f->flags = fdb_flags; + f->updated = jiffies; + notify = 1; } - if ((flags & NLM_F_APPEND) && - (is_multicast_ether_addr(f->eth_addr) || - is_zero_ether_addr(f->eth_addr))) { - rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); + } - if (rc < 0) - return rc; + if ((flags & NLM_F_REPLACE)) { + /* Only change unicasts */ + if (!(is_multicast_ether_addr(f->eth_addr) || + is_zero_ether_addr(f->eth_addr))) { + rc = vxlan_fdb_replace(f, ip, port, vni, + ifindex); notify |= rc; - } - - if (ndm_flags & NTF_USE) - f->used = jiffies; - } else { - if (!(flags & NLM_F_CREATE)) - return -ENOENT; - - /* Disallow replace to add a multicast entry */ - if ((flags & NLM_F_REPLACE) && - (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac))) + } else { return -EOPNOTSUPP; + } + } + if ((flags & NLM_F_APPEND) && + (is_multicast_ether_addr(f->eth_addr) || + is_zero_ether_addr(f->eth_addr))) { + rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); - netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); - rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni, - vni, ifindex, fdb_flags, &f); if (rc < 0) return rc; - notify = 1; + notify |= rc; } + if (ndm_flags & NTF_USE) + f->used = jiffies; + if (notify) { if (rd == NULL) rd = first_remote_rtnl(f); + vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH, swdev_notify); } return 0; } +static int vxlan_fdb_update_create(struct vxlan_dev *vxlan, + const u8 *mac, union vxlan_addr *ip, + __u16 state, __u16 flags, + __be16 port, __be32 src_vni, __be32 vni, + __u32 ifindex, __u16 ndm_flags, + bool swdev_notify) +{ + __u16 fdb_flags = (ndm_flags & ~NTF_USE); + struct vxlan_fdb *f; + int rc; + + /* Disallow replace to add a multicast entry */ + if ((flags & NLM_F_REPLACE) && + (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac))) + return -EOPNOTSUPP; + + netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); + rc = vxlan_fdb_create(vxlan, mac, ip, state, port, src_vni, + vni, ifindex, fdb_flags, &f); + if (rc < 0) + return rc; + + vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH, + swdev_notify); + return 0; +} + +/* Add new entry to forwarding table -- assumes lock held */ +static int vxlan_fdb_update(struct vxlan_dev *vxlan, + const u8 *mac, union vxlan_addr *ip, + __u16 state, __u16 flags, + __be16 port, __be32 src_vni, __be32 vni, + __u32 ifindex, __u16 ndm_flags, + bool swdev_notify) +{ + struct vxlan_fdb *f; + + f = __vxlan_find_mac(vxlan, mac, src_vni); + if (f) { + if (flags & NLM_F_EXCL) { + netdev_dbg(vxlan->dev, + "lost race to create %pM\n", mac); + return -EEXIST; + } + + return vxlan_fdb_update_existing(vxlan, ip, state, flags, port, + vni, ifindex, ndm_flags, f, + swdev_notify); + } else { + if (!(flags & NLM_F_CREATE)) + return -ENOENT; + + return vxlan_fdb_update_create(vxlan, mac, ip, state, flags, + port, src_vni, vni, ifindex, + ndm_flags, swdev_notify); + } +} + static void vxlan_dst_free(struct rcu_head *head) { struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu); -- cgit v1.2.3 From ccdfd4f71d10937504cac8663cb1782063319e39 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:34 +0000 Subject: vxlan: Have vxlan_fdb_replace() save original rdst value To enable rollbacks after vetoed FDB updates, extend vxlan_fdb_replace() to take an additional argument where it should store the original values of a modified rdst. Update the sole caller. The following patch will make use of the saved value. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index aeaa429229c7..1c8d8c8e0961 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -625,7 +625,7 @@ EXPORT_SYMBOL_GPL(vxlan_fdb_clear_offload); /* Replace destination of unicast mac */ static int vxlan_fdb_replace(struct vxlan_fdb *f, union vxlan_addr *ip, __be16 port, __be32 vni, - __u32 ifindex) + __u32 ifindex, struct vxlan_rdst *oldrd) { struct vxlan_rdst *rd; @@ -637,6 +637,7 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f, if (!rd) return 0; + *oldrd = *rd; dst_cache_reset(&rd->dst_cache); rd->remote_ip = *ip; rd->remote_port = port; @@ -865,6 +866,7 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, { __u16 fdb_flags = (ndm_flags & ~NTF_USE); struct vxlan_rdst *rd = NULL; + struct vxlan_rdst oldrd; int notify = 0; int rc; @@ -890,7 +892,7 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, if (!(is_multicast_ether_addr(f->eth_addr) || is_zero_ether_addr(f->eth_addr))) { rc = vxlan_fdb_replace(f, ip, port, vni, - ifindex); + ifindex, &oldrd); notify |= rc; } else { return -EOPNOTSUPP; -- cgit v1.2.3 From 61f46fe8c646c1cc7810ee0963d7870b6d901a96 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:38 +0000 Subject: vxlan: Allow vetoing of FDB notifications Change vxlan_fdb_switchdev_call_notifiers() to return the result from calling switchdev notifiers. Propagate the error number up the stack. In vxlan_fdb_update_existing() and vxlan_fdb_update_create() add rollbacks to clean up the work that was done before the veto. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 64 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 1c8d8c8e0961..92904ee16053 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -375,32 +375,38 @@ static void vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev *vxlan, fdb_info->added_by_user = fdb->flags & NTF_VXLAN_ADDED_BY_USER; } -static void vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan, - struct vxlan_fdb *fdb, - struct vxlan_rdst *rd, - bool adding) +static int vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan, + struct vxlan_fdb *fdb, + struct vxlan_rdst *rd, + bool adding) { struct switchdev_notifier_vxlan_fdb_info info; enum switchdev_notifier_type notifier_type; + int ret; if (WARN_ON(!rd)) - return; + return 0; notifier_type = adding ? SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE : SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE; vxlan_fdb_switchdev_notifier_info(vxlan, fdb, rd, &info); - call_switchdev_notifiers(notifier_type, vxlan->dev, - &info.info); + ret = call_switchdev_notifiers(notifier_type, vxlan->dev, + &info.info); + return notifier_to_errno(ret); } -static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, - struct vxlan_rdst *rd, int type, bool swdev_notify) +static int vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, + struct vxlan_rdst *rd, int type, bool swdev_notify) { + int err; + if (swdev_notify) { switch (type) { case RTM_NEWNEIGH: - vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, - true); + err = vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, + true); + if (err) + return err; break; case RTM_DELNEIGH: vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, @@ -410,6 +416,7 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, } __vxlan_fdb_notify(vxlan, fdb, rd, type); + return 0; } static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa) @@ -868,7 +875,8 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, struct vxlan_rdst *rd = NULL; struct vxlan_rdst oldrd; int notify = 0; - int rc; + int rc = 0; + int err; /* Do not allow an externally learned entry to take over an entry added * by the user. @@ -915,10 +923,20 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, if (rd == NULL) rd = first_remote_rtnl(f); - vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH, swdev_notify); + err = vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH, + swdev_notify); + if (err) + goto err_notify; } return 0; + +err_notify: + if ((flags & NLM_F_REPLACE) && rc) + *rd = oldrd; + else if ((flags & NLM_F_APPEND) && rc) + list_del_rcu(&rd->list); + return err; } static int vxlan_fdb_update_create(struct vxlan_dev *vxlan, @@ -943,9 +961,16 @@ static int vxlan_fdb_update_create(struct vxlan_dev *vxlan, if (rc < 0) return rc; - vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH, - swdev_notify); + rc = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH, + swdev_notify); + if (rc) + goto err_notify; + return 0; + +err_notify: + vxlan_fdb_destroy(vxlan, f, false, false); + return rc; } /* Add new entry to forwarding table -- assumes lock held */ @@ -3515,9 +3540,12 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, goto errout; /* notify default fdb entry */ - if (f) - vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH, - true); + if (f) { + err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), + RTM_NEWNEIGH, true); + if (err) + goto errout; + } list_add(&vxlan->next, &vn->vxlan_list); return 0; -- cgit v1.2.3 From 8db9427d52b894276383091883b6a8bc5bb0c14d Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:39 +0000 Subject: vxlan: changelink: Inline vxlan_dev_configure() The changelink operation may cause change in remote address, and therefore an FDB update, which can be vetoed. To properly handle vetoing, vxlan_changelink() needs to be gradually updated. In this patch simply replace vxlan_dev_configure() with the two constituent calls. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 92904ee16053..f2f419c60dfe 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -3793,6 +3793,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *dst = &vxlan->default_dst; unsigned long old_age_interval; + struct net_device *lowerdev; struct vxlan_rdst old_dst; struct vxlan_config conf; int err; @@ -3805,10 +3806,13 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], old_age_interval = vxlan->cfg.age_interval; memcpy(&old_dst, dst, sizeof(struct vxlan_rdst)); - err = vxlan_dev_configure(vxlan->net, dev, &conf, true, extack); + err = vxlan_config_validate(vxlan->net, &conf, &lowerdev, + vxlan, extack); if (err) return err; + vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true); + if (old_age_interval != vxlan->cfg.age_interval) mod_timer(&vxlan->age_timer, jiffies); -- cgit v1.2.3 From 038a5a99e95214d0549401c74711152d9869ead3 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:41 +0000 Subject: vxlan: changelink: Postpone vxlan_config_apply() When an FDB entry is vetoed, it is necessary to unroll the changes that have already been done. To avoid having to unroll vxlan_config_apply(), postpone the call after the point where the vetoing takes place. Since the call can't fail, it doesn't necessitate any cleanups in the preceding FDB update logic. Correspondingly, move down the mod_timer() call as well. References to *dst need to be replaced with references to conf. Additionally, old_dst and old_age_interval are not necessary anymore, and therefore drop them. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f2f419c60dfe..51e10f47d4f1 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -3792,9 +3792,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *dst = &vxlan->default_dst; - unsigned long old_age_interval; struct net_device *lowerdev; - struct vxlan_rdst old_dst; struct vxlan_config conf; int err; @@ -3803,40 +3801,31 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], if (err) return err; - old_age_interval = vxlan->cfg.age_interval; - memcpy(&old_dst, dst, sizeof(struct vxlan_rdst)); - err = vxlan_config_validate(vxlan->net, &conf, &lowerdev, vxlan, extack); if (err) return err; - vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true); - - if (old_age_interval != vxlan->cfg.age_interval) - mod_timer(&vxlan->age_timer, jiffies); - /* handle default dst entry */ - if (!vxlan_addr_equal(&dst->remote_ip, &old_dst.remote_ip)) { + if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { spin_lock_bh(&vxlan->hash_lock); - if (!vxlan_addr_any(&old_dst.remote_ip)) + if (!vxlan_addr_any(&dst->remote_ip)) __vxlan_fdb_delete(vxlan, all_zeros_mac, - old_dst.remote_ip, + dst->remote_ip, vxlan->cfg.dst_port, - old_dst.remote_vni, - old_dst.remote_vni, - old_dst.remote_ifindex, + dst->remote_vni, + dst->remote_vni, + dst->remote_ifindex, true); - if (!vxlan_addr_any(&dst->remote_ip)) { + if (!vxlan_addr_any(&conf.remote_ip)) { err = vxlan_fdb_update(vxlan, all_zeros_mac, - &dst->remote_ip, + &conf.remote_ip, NUD_REACHABLE | NUD_PERMANENT, NLM_F_APPEND | NLM_F_CREATE, vxlan->cfg.dst_port, - dst->remote_vni, - dst->remote_vni, - dst->remote_ifindex, + conf.vni, conf.vni, + conf.remote_ifindex, NTF_SELF, true); if (err) { spin_unlock_bh(&vxlan->hash_lock); @@ -3846,6 +3835,10 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], spin_unlock_bh(&vxlan->hash_lock); } + if (conf.age_interval != vxlan->cfg.age_interval) + mod_timer(&vxlan->age_timer, jiffies); + + vxlan_config_apply(dev, &conf, lowerdev, vxlan->net, true); return 0; } -- cgit v1.2.3 From 1cdc98c2711e42d956c4a5ce525d3f8e90c58f9e Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:43 +0000 Subject: vxlan: changelink: Delete remote after update If a change in remote address prompts a change in a default FDB entry, that change might be vetoed. If that happens, it would then be necessary to reinstate the already-removed default FDB entry corresponding to the previous remote address. Instead, arrange to have the previous address removed only after the FDB is successfully vetted. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 51e10f47d4f1..83f65eb3085f 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -3809,15 +3809,6 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], /* handle default dst entry */ if (!vxlan_addr_equal(&conf.remote_ip, &dst->remote_ip)) { spin_lock_bh(&vxlan->hash_lock); - if (!vxlan_addr_any(&dst->remote_ip)) - __vxlan_fdb_delete(vxlan, all_zeros_mac, - dst->remote_ip, - vxlan->cfg.dst_port, - dst->remote_vni, - dst->remote_vni, - dst->remote_ifindex, - true); - if (!vxlan_addr_any(&conf.remote_ip)) { err = vxlan_fdb_update(vxlan, all_zeros_mac, &conf.remote_ip, @@ -3832,6 +3823,14 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], return err; } } + if (!vxlan_addr_any(&dst->remote_ip)) + __vxlan_fdb_delete(vxlan, all_zeros_mac, + dst->remote_ip, + vxlan->cfg.dst_port, + dst->remote_vni, + dst->remote_vni, + dst->remote_ifindex, + true); spin_unlock_bh(&vxlan->hash_lock); } -- cgit v1.2.3 From 87b0984ebfabafcfe959e52ca5cdab5eeb2d60c0 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:50 +0000 Subject: net: Add extack argument to ndo_fdb_add() Drivers may not be able to support certain FDB entries, and an error code is insufficient to give clear hints as to the reasons of rejection. In order to make it possible to communicate the rejection reason, extend ndo_fdb_add() with an extack argument. Adapt the existing implementations of ndo_fdb_add() to take the parameter (and ignore it). Pass the extack parameter when invoking ndo_fdb_add() from rtnl_fdb_add(). Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 ++- drivers/net/ethernet/intel/ice/ice_main.c | 3 ++- drivers/net/ethernet/intel/igb/igb_main.c | 3 ++- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 ++- drivers/net/ethernet/mscc/ocelot.c | 3 ++- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 3 ++- drivers/net/macvlan.c | 3 ++- drivers/net/vxlan.c | 3 ++- include/linux/netdevice.h | 6 ++++-- net/bridge/br_fdb.c | 3 ++- net/bridge/br_private.h | 3 ++- net/core/rtnetlink.c | 5 +++-- net/dsa/dsa_priv.h | 3 ++- net/dsa/slave.c | 3 ++- 14 files changed, 31 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f52e2c46e6a7..0ee641c41be4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -11644,7 +11644,8 @@ static int i40e_get_phys_port_id(struct net_device *netdev, static int i40e_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid, - u16 flags) + u16 flags, + struct netlink_ext_ack *extack) { struct i40e_netdev_priv *np = netdev_priv(dev); struct i40e_pf *pf = np->vsi->back; diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index f4bf6bda32a9..48f033928aa2 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2438,7 +2438,8 @@ static void ice_set_rx_mode(struct net_device *netdev) */ static int ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[], struct net_device *dev, const unsigned char *addr, - u16 vid, u16 flags) + u16 vid, u16 flags, + struct netlink_ext_ack *extack) { int err; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 87bdf1604ae2..3615e2e52399 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2486,7 +2486,8 @@ static int igb_set_features(struct net_device *netdev, static int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid, - u16 flags) + u16 flags, + struct netlink_ext_ack *extack) { /* guarantee we can provide a unique filter for the unicast address */ if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index daff8183534b..b53087a980ef 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -9910,7 +9910,8 @@ static void ixgbe_del_udp_tunnel_port(struct net_device *dev, static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid, - u16 flags) + u16 flags, + struct netlink_ext_ack *extack) { /* guarantee we can provide a unique filter for the unicast address */ if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) { diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 215a45374d7b..c6a575eb0ff5 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -721,7 +721,8 @@ static void ocelot_get_stats64(struct net_device *dev, static int ocelot_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, - u16 vid, u16 flags) + u16 vid, u16 flags, + struct netlink_ext_ack *extack) { struct ocelot_port *port = netdev_priv(dev); struct ocelot *ocelot = port->ocelot; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 16d0479f6891..7a873002e626 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -396,7 +396,8 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *netdev, - const unsigned char *addr, u16 vid, u16 flags) + const unsigned char *addr, u16 vid, u16 flags, + struct netlink_ext_ack *extack) { struct qlcnic_adapter *adapter = netdev_priv(netdev); int err = 0; diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index fc726ce4c164..084a1b3fbc80 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -963,7 +963,8 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev, static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid, - u16 flags) + u16 flags, + struct netlink_ext_ack *extack) { struct macvlan_dev *vlan = netdev_priv(dev); int err = -EINVAL; diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 83f65eb3085f..11f38fd71678 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1087,7 +1087,8 @@ static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan, /* Add static entry (via netlink) */ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, - const unsigned char *addr, u16 vid, u16 flags) + const unsigned char *addr, u16 vid, u16 flags, + struct netlink_ext_ack *extack) { struct vxlan_dev *vxlan = netdev_priv(dev); /* struct net *net = dev_net(vxlan->dev); */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1377d085ef99..a57b9a853aab 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1152,7 +1152,8 @@ struct dev_ifalias { * * int (*ndo_fdb_add)(struct ndmsg *ndm, struct nlattr *tb[], * struct net_device *dev, - * const unsigned char *addr, u16 vid, u16 flags) + * const unsigned char *addr, u16 vid, u16 flags, + * struct netlink_ext_ack *extack); * Adds an FDB entry to dev for addr. * int (*ndo_fdb_del)(struct ndmsg *ndm, struct nlattr *tb[], * struct net_device *dev, @@ -1376,7 +1377,8 @@ struct net_device_ops { struct net_device *dev, const unsigned char *addr, u16 vid, - u16 flags); + u16 flags, + struct netlink_ext_ack *extack); int (*ndo_fdb_del)(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index fe3c758791ca..6664cb8590f8 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -915,7 +915,8 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br, /* Add new permanent fdb entry with RTM_NEWNEIGH */ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, - const unsigned char *addr, u16 vid, u16 nlh_flags) + const unsigned char *addr, u16 vid, u16 nlh_flags, + struct netlink_ext_ack *extack) { struct net_bridge_vlan_group *vg; struct net_bridge_port *p = NULL; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index eabf8bf28a3f..00deef7fc1f3 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -573,7 +573,8 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid); int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, - const unsigned char *addr, u16 vid, u16 nlh_flags); + const unsigned char *addr, u16 vid, u16 nlh_flags, + struct netlink_ext_ack *extack); int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, struct net_device *fdev, int *idx); int br_fdb_get(struct sk_buff *skb, struct nlattr *tb[], struct net_device *dev, diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 5ea1bed08ede..b302df0cd5ae 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3639,7 +3639,7 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, const struct net_device_ops *ops = br_dev->netdev_ops; err = ops->ndo_fdb_add(ndm, tb, dev, addr, vid, - nlh->nlmsg_flags); + nlh->nlmsg_flags, extack); if (err) goto out; else @@ -3651,7 +3651,8 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, if (dev->netdev_ops->ndo_fdb_add) err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr, vid, - nlh->nlmsg_flags); + nlh->nlmsg_flags, + extack); else err = ndo_dflt_fdb_add(ndm, tb, dev, addr, vid, nlh->nlmsg_flags); diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 026a05774bf7..1f4972dab9f2 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -103,7 +103,8 @@ static inline void dsa_legacy_unregister(void) { } int dsa_legacy_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid, - u16 flags); + u16 flags, + struct netlink_ext_ack *extack); int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid); diff --git a/net/dsa/slave.c b/net/dsa/slave.c index a3fcc1d01615..d5680a98a7f0 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1009,7 +1009,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { int dsa_legacy_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid, - u16 flags) + u16 flags, + struct netlink_ext_ack *extack) { struct dsa_port *dp = dsa_slave_to_port(dev); -- cgit v1.2.3 From d907f58fa90f0fcba1268eab24b1e0997e0d1e22 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:52 +0000 Subject: mlxsw: Add extack to mlxsw_sp_nve_ops.fdb_replay A follow-up patch will extend vxlan_fdb_replay() with an extack argument. Extend the fdb_replay callback in mlxsw likewise so that the argument is ready for the vxlan conversion. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h | 3 ++- drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c index 9019548d731b..94e07767f18e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c @@ -841,7 +841,7 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid, nve->config = config; - err = ops->fdb_replay(params->dev, params->vni); + err = ops->fdb_replay(params->dev, params->vni, extack); if (err) { NL_SET_ERR_MSG_MOD(extack, "Failed to offload the FDB"); goto err_fdb_replay; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h index 02937ea95bc3..20d99b41611d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h @@ -41,7 +41,8 @@ struct mlxsw_sp_nve_ops { int (*init)(struct mlxsw_sp_nve *nve, const struct mlxsw_sp_nve_config *config); void (*fini)(struct mlxsw_sp_nve *nve); - int (*fdb_replay)(const struct net_device *nve_dev, __be32 vni); + int (*fdb_replay)(const struct net_device *nve_dev, __be32 vni, + struct netlink_ext_ack *extack); void (*fdb_clear_offload)(const struct net_device *nve_dev, __be32 vni); }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c index 74e564c4ac19..bc565f2aa121 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c @@ -212,7 +212,8 @@ static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve) } static int -mlxsw_sp_nve_vxlan_fdb_replay(const struct net_device *nve_dev, __be32 vni) +mlxsw_sp_nve_vxlan_fdb_replay(const struct net_device *nve_dev, __be32 vni, + struct netlink_ext_ack *extack) { if (WARN_ON(!netif_is_vxlan(nve_dev))) return -EINVAL; -- cgit v1.2.3 From 4c59b7d16096e5e2cfbc7f8cba972eb72f6b96c0 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:54 +0000 Subject: vxlan: Add extack to switchdev operations There are four sources of VXLAN switchdev notifier calls: - the changelink() link operation, which already supports extack, - ndo_fdb_add() which got extack support in a previous patch, - FDB updates due to packet forwarding, - and vxlan_fdb_replay(). Extend vxlan_fdb_switchdev_call_notifiers() to include extack in the switchdev message that it sends, and propagate the argument upwards to the callers. For the first two cases, pass in the extack gotten through the operation. For case #3, pass in NULL. To cover the last case, extend vxlan_fdb_replay() to take extack argument, which might come from whatever operation necessitated the FDB replay. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c | 3 +- drivers/net/vxlan.c | 68 +++++++++++++--------- include/net/vxlan.h | 6 +- 3 files changed, 46 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c index bc565f2aa121..9ba0b83bd949 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c @@ -217,7 +217,8 @@ mlxsw_sp_nve_vxlan_fdb_replay(const struct net_device *nve_dev, __be32 vni, { if (WARN_ON(!netif_is_vxlan(nve_dev))) return -EINVAL; - return vxlan_fdb_replay(nve_dev, vni, &mlxsw_sp_switchdev_notifier); + return vxlan_fdb_replay(nve_dev, vni, &mlxsw_sp_switchdev_notifier, + extack); } static void diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 11f38fd71678..a9e90159bb61 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -361,10 +361,11 @@ errout: static void vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev *vxlan, const struct vxlan_fdb *fdb, const struct vxlan_rdst *rd, + struct netlink_ext_ack *extack, struct switchdev_notifier_vxlan_fdb_info *fdb_info) { fdb_info->info.dev = vxlan->dev; - fdb_info->info.extack = NULL; + fdb_info->info.extack = extack; fdb_info->remote_ip = rd->remote_ip; fdb_info->remote_port = rd->remote_port; fdb_info->remote_vni = rd->remote_vni; @@ -378,7 +379,8 @@ static void vxlan_fdb_switchdev_notifier_info(const struct vxlan_dev *vxlan, static int vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, struct vxlan_rdst *rd, - bool adding) + bool adding, + struct netlink_ext_ack *extack) { struct switchdev_notifier_vxlan_fdb_info info; enum switchdev_notifier_type notifier_type; @@ -389,14 +391,15 @@ static int vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan, notifier_type = adding ? SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE : SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE; - vxlan_fdb_switchdev_notifier_info(vxlan, fdb, rd, &info); + vxlan_fdb_switchdev_notifier_info(vxlan, fdb, rd, NULL, &info); ret = call_switchdev_notifiers(notifier_type, vxlan->dev, &info.info); return notifier_to_errno(ret); } static int vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, - struct vxlan_rdst *rd, int type, bool swdev_notify) + struct vxlan_rdst *rd, int type, bool swdev_notify, + struct netlink_ext_ack *extack) { int err; @@ -404,13 +407,13 @@ static int vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, switch (type) { case RTM_NEWNEIGH: err = vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, - true); + true, extack); if (err) return err; break; case RTM_DELNEIGH: vxlan_fdb_switchdev_call_notifiers(vxlan, fdb, rd, - false); + false, extack); break; } } @@ -430,7 +433,7 @@ static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa) .remote_vni = cpu_to_be32(VXLAN_N_VID), }; - vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true); + vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true, NULL); } static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) @@ -442,7 +445,7 @@ static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) memcpy(f.eth_addr, eth_addr, ETH_ALEN); - vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true); + vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH, true, NULL); } /* Hash Ethernet address */ @@ -552,7 +555,7 @@ int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni, } rdst = first_remote_rcu(f); - vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, fdb_info); + vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, NULL, fdb_info); out: rcu_read_unlock(); @@ -563,19 +566,21 @@ EXPORT_SYMBOL_GPL(vxlan_fdb_find_uc); static int vxlan_fdb_notify_one(struct notifier_block *nb, const struct vxlan_dev *vxlan, const struct vxlan_fdb *f, - const struct vxlan_rdst *rdst) + const struct vxlan_rdst *rdst, + struct netlink_ext_ack *extack) { struct switchdev_notifier_vxlan_fdb_info fdb_info; int rc; - vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, &fdb_info); + vxlan_fdb_switchdev_notifier_info(vxlan, f, rdst, extack, &fdb_info); rc = nb->notifier_call(nb, SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE, &fdb_info); return notifier_to_errno(rc); } int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, - struct notifier_block *nb) + struct notifier_block *nb, + struct netlink_ext_ack *extack) { struct vxlan_dev *vxlan; struct vxlan_rdst *rdst; @@ -593,7 +598,8 @@ int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, if (f->vni == vni) { list_for_each_entry(rdst, &f->remotes, list) { rc = vxlan_fdb_notify_one(nb, vxlan, - f, rdst); + f, rdst, + extack); if (rc) goto out; } @@ -857,7 +863,7 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, if (do_notify) list_for_each_entry(rd, &f->remotes, list) vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH, - swdev_notify); + swdev_notify, NULL); hlist_del_rcu(&f->hlist); call_rcu(&f->rcu, vxlan_fdb_free); @@ -869,7 +875,8 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, __be16 port, __be32 vni, __u32 ifindex, __u16 ndm_flags, struct vxlan_fdb *f, - bool swdev_notify) + bool swdev_notify, + struct netlink_ext_ack *extack) { __u16 fdb_flags = (ndm_flags & ~NTF_USE); struct vxlan_rdst *rd = NULL; @@ -924,7 +931,7 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, rd = first_remote_rtnl(f); err = vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH, - swdev_notify); + swdev_notify, extack); if (err) goto err_notify; } @@ -944,7 +951,8 @@ static int vxlan_fdb_update_create(struct vxlan_dev *vxlan, __u16 state, __u16 flags, __be16 port, __be32 src_vni, __be32 vni, __u32 ifindex, __u16 ndm_flags, - bool swdev_notify) + bool swdev_notify, + struct netlink_ext_ack *extack) { __u16 fdb_flags = (ndm_flags & ~NTF_USE); struct vxlan_fdb *f; @@ -962,7 +970,7 @@ static int vxlan_fdb_update_create(struct vxlan_dev *vxlan, return rc; rc = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH, - swdev_notify); + swdev_notify, extack); if (rc) goto err_notify; @@ -979,7 +987,8 @@ static int vxlan_fdb_update(struct vxlan_dev *vxlan, __u16 state, __u16 flags, __be16 port, __be32 src_vni, __be32 vni, __u32 ifindex, __u16 ndm_flags, - bool swdev_notify) + bool swdev_notify, + struct netlink_ext_ack *extack) { struct vxlan_fdb *f; @@ -993,14 +1002,14 @@ static int vxlan_fdb_update(struct vxlan_dev *vxlan, return vxlan_fdb_update_existing(vxlan, ip, state, flags, port, vni, ifindex, ndm_flags, f, - swdev_notify); + swdev_notify, extack); } else { if (!(flags & NLM_F_CREATE)) return -ENOENT; return vxlan_fdb_update_create(vxlan, mac, ip, state, flags, port, src_vni, vni, ifindex, - ndm_flags, swdev_notify); + ndm_flags, swdev_notify, extack); } } @@ -1016,7 +1025,7 @@ static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, struct vxlan_rdst *rd, bool swdev_notify) { list_del_rcu(&rd->list); - vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH, swdev_notify); + vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH, swdev_notify, NULL); call_rcu(&rd->rcu, vxlan_dst_free); } @@ -1118,7 +1127,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], err = vxlan_fdb_update(vxlan, addr, &ip, ndm->ndm_state, flags, port, src_vni, vni, ifindex, ndm->ndm_flags | NTF_VXLAN_ADDED_BY_USER, - true); + true, extack); spin_unlock_bh(&vxlan->hash_lock); return err; @@ -1286,7 +1295,7 @@ static bool vxlan_snoop(struct net_device *dev, rdst->remote_ip = *src_ip; f->updated = jiffies; - vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true); + vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL); } else { /* learned new entry */ spin_lock(&vxlan->hash_lock); @@ -1299,7 +1308,7 @@ static bool vxlan_snoop(struct net_device *dev, vxlan->cfg.dst_port, vni, vxlan->default_dst.remote_vni, - ifindex, NTF_SELF, true); + ifindex, NTF_SELF, true, NULL); spin_unlock(&vxlan->hash_lock); } @@ -3543,7 +3552,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, /* notify default fdb entry */ if (f) { err = vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), - RTM_NEWNEIGH, true); + RTM_NEWNEIGH, true, extack); if (err) goto errout; } @@ -3818,7 +3827,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], vxlan->cfg.dst_port, conf.vni, conf.vni, conf.remote_ifindex, - NTF_SELF, true); + NTF_SELF, true, extack); if (err) { spin_unlock_bh(&vxlan->hash_lock); return err; @@ -4113,8 +4122,11 @@ vxlan_fdb_external_learn_add(struct net_device *dev, struct switchdev_notifier_vxlan_fdb_info *fdb_info) { struct vxlan_dev *vxlan = netdev_priv(dev); + struct netlink_ext_ack *extack; int err; + extack = switchdev_notifier_info_to_extack(&fdb_info->info); + spin_lock_bh(&vxlan->hash_lock); err = vxlan_fdb_update(vxlan, fdb_info->eth_addr, &fdb_info->remote_ip, NUD_REACHABLE, @@ -4124,7 +4136,7 @@ vxlan_fdb_external_learn_add(struct net_device *dev, fdb_info->remote_vni, fdb_info->remote_ifindex, NTF_USE | NTF_SELF | NTF_EXT_LEARNED, - false); + false, extack); spin_unlock_bh(&vxlan->hash_lock); return err; diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 236403eb5ba6..09767819c3d4 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -428,7 +428,8 @@ struct switchdev_notifier_vxlan_fdb_info { int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni, struct switchdev_notifier_vxlan_fdb_info *fdb_info); int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, - struct notifier_block *nb); + struct notifier_block *nb, + struct netlink_ext_ack *extack); void vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni); #else @@ -440,7 +441,8 @@ vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni, } static inline int vxlan_fdb_replay(const struct net_device *dev, __be32 vni, - struct notifier_block *nb) + struct notifier_block *nb, + struct netlink_ext_ack *extack) { return -EOPNOTSUPP; } -- cgit v1.2.3 From 6685987c29582afc79b7fa3998dfbf36b4295791 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:56 +0000 Subject: switchdev: Add extack argument to call_switchdev_notifiers() A follow-up patch will enable vetoing of FDB entries. Make it possible to communicate details of why an FDB entry is not acceptable back to the user. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- Documentation/networking/switchdev.txt | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 6 ++++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 12 ++++++------ drivers/net/ethernet/rocker/rocker_main.c | 2 +- drivers/net/ethernet/rocker/rocker_ofdpa.c | 4 ++-- drivers/net/vxlan.c | 2 +- include/net/switchdev.h | 6 ++++-- net/bridge/br_switchdev.c | 2 +- net/dsa/slave.c | 2 +- net/switchdev/switchdev.c | 5 +++-- 10 files changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index 82236a17b5e6..f3244d87512a 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -196,7 +196,7 @@ The switch device will learn/forget source MAC address/VLAN on ingress packets and notify the switch driver of the mac/vlan/port tuples. The switch driver, in turn, will notify the bridge driver using the switchdev notifier call: - err = call_switchdev_notifiers(val, dev, info); + err = call_switchdev_notifiers(val, dev, info, extack); Where val is SWITCHDEV_FDB_ADD when learning and SWITCHDEV_FDB_DEL when forgetting, and info points to a struct switchdev_notifier_fdb_info. On diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 98e5ffd71b91..042341c7f6b9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -7294,7 +7294,8 @@ static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) info.addr = mac; info.vid = vid; - call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info); + call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info, + NULL); } static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops = { @@ -7381,7 +7382,8 @@ static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) info.addr = mac; info.vid = 0; - call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info); + call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info, + NULL); } static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 0abbaa0fbf14..71aad9d4e160 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -2443,7 +2443,7 @@ static void mlxsw_sp_fdb_vxlan_call_notifiers(struct net_device *dev, ether_addr_copy(info.eth_addr, mac); info.vni = vni; info.offloaded = adding; - call_switchdev_notifiers(type, dev, &info.info); + call_switchdev_notifiers(type, dev, &info.info, NULL); } static void mlxsw_sp_fdb_nve_call_notifiers(struct net_device *dev, @@ -2468,7 +2468,7 @@ mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type, info.addr = mac; info.vid = vid; info.offloaded = offloaded; - call_switchdev_notifiers(type, dev, &info.info); + call_switchdev_notifiers(type, dev, &info.info, NULL); } static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp, @@ -2819,7 +2819,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp, return; vxlan_fdb_info.offloaded = true; call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, - &vxlan_fdb_info.info); + &vxlan_fdb_info.info, NULL); mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, vxlan_fdb_info.eth_addr, fdb_info->vid, dev, true); @@ -2832,7 +2832,7 @@ mlxsw_sp_switchdev_bridge_vxlan_fdb_event(struct mlxsw_sp *mlxsw_sp, false); vxlan_fdb_info.offloaded = false; call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, - &vxlan_fdb_info.info); + &vxlan_fdb_info.info, NULL); break; } } @@ -2977,7 +2977,7 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp, } vxlan_fdb_info->offloaded = true; call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, - &vxlan_fdb_info->info); + &vxlan_fdb_info->info, NULL); mlxsw_sp_fid_put(fid); return; } @@ -2998,7 +2998,7 @@ mlxsw_sp_switchdev_vxlan_fdb_add(struct mlxsw_sp *mlxsw_sp, goto err_fdb_tunnel_uc_op; vxlan_fdb_info->offloaded = true; call_switchdev_notifiers(SWITCHDEV_VXLAN_FDB_OFFLOADED, dev, - &vxlan_fdb_info->info); + &vxlan_fdb_info->info, NULL); mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, vxlan_fdb_info->eth_addr, vid, dev, true); diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 6213827e3956..62a205eba9f7 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2725,7 +2725,7 @@ rocker_fdb_offload_notify(struct rocker_port *rocker_port, info.vid = recv_info->vid; info.offloaded = true; call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, - rocker_port->dev, &info.info); + rocker_port->dev, &info.info, NULL); } static void rocker_switchdev_event_work(struct work_struct *work) diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c index 6473cc68c2d5..bea7895930f6 100644 --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c @@ -1833,10 +1833,10 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work) rtnl_lock(); if (learned && removing) call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, - lw->ofdpa_port->dev, &info.info); + lw->ofdpa_port->dev, &info.info, NULL); else if (learned && !removing) call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE, - lw->ofdpa_port->dev, &info.info); + lw->ofdpa_port->dev, &info.info, NULL); rtnl_unlock(); kfree(work); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a9e90159bb61..ef45c3c925be 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -393,7 +393,7 @@ static int vxlan_fdb_switchdev_call_notifiers(struct vxlan_dev *vxlan, : SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE; vxlan_fdb_switchdev_notifier_info(vxlan, fdb, rd, NULL, &info); ret = call_switchdev_notifiers(notifier_type, vxlan->dev, - &info.info); + &info.info, extack); return notifier_to_errno(ret); } diff --git a/include/net/switchdev.h b/include/net/switchdev.h index a7fdab5ee6c3..63843ae5dc81 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -195,7 +195,8 @@ int switchdev_port_obj_del(struct net_device *dev, int register_switchdev_notifier(struct notifier_block *nb); int unregister_switchdev_notifier(struct notifier_block *nb); int call_switchdev_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info); + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack); int register_switchdev_blocking_notifier(struct notifier_block *nb); int unregister_switchdev_blocking_notifier(struct notifier_block *nb); @@ -267,7 +268,8 @@ static inline int unregister_switchdev_notifier(struct notifier_block *nb) static inline int call_switchdev_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info) + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack) { return NOTIFY_DONE; } diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index 035ff59d9cbd..4d2b9eb7604a 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -113,7 +113,7 @@ br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac, info.added_by_user = added_by_user; info.offloaded = offloaded; notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE; - call_switchdev_notifiers(notifier_type, dev, &info.info); + call_switchdev_notifiers(notifier_type, dev, &info.info, NULL); } void diff --git a/net/dsa/slave.c b/net/dsa/slave.c index d5680a98a7f0..91de3a663226 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1451,7 +1451,7 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) } fdb_info->offloaded = true; call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, - &fdb_info->info); + &fdb_info->info, NULL); break; case SWITCHDEV_FDB_DEL_TO_DEVICE: diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 5df9d1138ac9..cd78253de31d 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -556,10 +556,11 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); * Call all network notifier blocks. */ int call_switchdev_notifiers(unsigned long val, struct net_device *dev, - struct switchdev_notifier_info *info) + struct switchdev_notifier_info *info, + struct netlink_ext_ack *extack) { info->dev = dev; - info->extack = NULL; + info->extack = extack; return atomic_notifier_call_chain(&switchdev_notif_chain, val, info); } EXPORT_SYMBOL_GPL(call_switchdev_notifiers); -- cgit v1.2.3 From a40313d956d3d3124f44b63ba752383c948c8587 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 16 Jan 2019 23:06:58 +0000 Subject: mlxsw: spectrum: Add extack messages to VXLAN FDB rejection Annotate the rejections in mlxsw_sp_switchdev_vxlan_work_prepare() with textual reasons. Because this code ends up being invoked for FDB replay as well, drop the default message from there, so that the more accurate error message is not overwritten. Signed-off-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c | 4 +--- .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 25 ++++++++++++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c index 94e07767f18e..1df164a4b06d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c @@ -842,10 +842,8 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid, nve->config = config; err = ops->fdb_replay(params->dev, params->vni, extack); - if (err) { - NL_SET_ERR_MSG_MOD(extack, "Failed to offload the FDB"); + if (err) goto err_fdb_replay; - } return 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 71aad9d4e160..8ab796e0c0d7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -3099,23 +3099,34 @@ mlxsw_sp_switchdev_vxlan_work_prepare(struct mlxsw_sp_switchdev_event_work * struct vxlan_dev *vxlan = netdev_priv(switchdev_work->dev); struct switchdev_notifier_vxlan_fdb_info *vxlan_fdb_info; struct vxlan_config *cfg = &vxlan->cfg; + struct netlink_ext_ack *extack; + extack = switchdev_notifier_info_to_extack(info); vxlan_fdb_info = container_of(info, struct switchdev_notifier_vxlan_fdb_info, info); - if (vxlan_fdb_info->remote_port != cfg->dst_port) - return -EOPNOTSUPP; - if (vxlan_fdb_info->remote_vni != cfg->vni) + if (vxlan_fdb_info->remote_port != cfg->dst_port) { + NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Non-default remote port is not supported"); return -EOPNOTSUPP; - if (vxlan_fdb_info->vni != cfg->vni) + } + if (vxlan_fdb_info->remote_vni != cfg->vni || + vxlan_fdb_info->vni != cfg->vni) { + NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Non-default VNI is not supported"); return -EOPNOTSUPP; - if (vxlan_fdb_info->remote_ifindex) + } + if (vxlan_fdb_info->remote_ifindex) { + NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Local interface is not supported"); return -EOPNOTSUPP; - if (is_multicast_ether_addr(vxlan_fdb_info->eth_addr)) + } + if (is_multicast_ether_addr(vxlan_fdb_info->eth_addr)) { + NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Multicast MAC addresses not supported"); return -EOPNOTSUPP; - if (vxlan_addr_multicast(&vxlan_fdb_info->remote_ip)) + } + if (vxlan_addr_multicast(&vxlan_fdb_info->remote_ip)) { + NL_SET_ERR_MSG_MOD(extack, "VxLAN: FDB: Multicast destination IP is not supported"); return -EOPNOTSUPP; + } switchdev_work->vxlan_fdb_info = *vxlan_fdb_info; -- cgit v1.2.3 From 5191673b693251d8cd80eae360390df4be4ba6b3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 16 Jan 2019 17:08:17 +0000 Subject: wan: dscc4: fix various indentation issues There are some lines that have indentation issues, fix these. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/wan/dscc4.c | 50 ++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index c0b0f525c87c..d5dc823f781e 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -456,16 +456,16 @@ static int state_check(u32 state, struct dscc4_dev_priv *dpriv, int ret = 0; if (debug > 1) { - if (SOURCE_ID(state) != dpriv->dev_id) { - printk(KERN_DEBUG "%s (%s): Source Id=%d, state=%08x\n", - dev->name, msg, SOURCE_ID(state), state ); + if (SOURCE_ID(state) != dpriv->dev_id) { + printk(KERN_DEBUG "%s (%s): Source Id=%d, state=%08x\n", + dev->name, msg, SOURCE_ID(state), state); ret = -1; - } - if (state & 0x0df80c00) { - printk(KERN_DEBUG "%s (%s): state=%08x (UFO alert)\n", - dev->name, msg, state); + } + if (state & 0x0df80c00) { + printk(KERN_DEBUG "%s (%s): state=%08x (UFO alert)\n", + dev->name, msg, state); ret = -1; - } + } } return ret; } @@ -1760,25 +1760,25 @@ try: } else { /* SccEvt */ if (debug > 1) { //FIXME: verifier la presence de tous les evenements - static struct { - u32 mask; - const char *irq_name; - } evts[] = { - { 0x00008000, "TIN"}, - { 0x00000020, "RSC"}, - { 0x00000010, "PCE"}, - { 0x00000008, "PLLA"}, - { 0, NULL} - }, *evt; - - for (evt = evts; evt->irq_name; evt++) { - if (state & evt->mask) { + static struct { + u32 mask; + const char *irq_name; + } evts[] = { + { 0x00008000, "TIN"}, + { 0x00000020, "RSC"}, + { 0x00000010, "PCE"}, + { 0x00000008, "PLLA"}, + { 0, NULL} + }, *evt; + + for (evt = evts; evt->irq_name; evt++) { + if (state & evt->mask) { printk(KERN_DEBUG "%s: %s\n", - dev->name, evt->irq_name); - if (!(state &= ~evt->mask)) - goto try; + dev->name, evt->irq_name); + if (!(state &= ~evt->mask)) + goto try; + } } - } } else { if (!(state &= ~0x0000c03c)) goto try; -- cgit v1.2.3 From 68d7431553a0cd05bce98d1c1d3fc56b3a1807c0 Mon Sep 17 00:00:00 2001 From: Ioana Ciocoi Radulescu Date: Wed, 16 Jan 2019 16:51:44 +0000 Subject: dpaa2-eth: Fix ndo_stop routine In the current implementation, on interface down we disabled NAPI and then manually drained any remaining ingress frames. This could lead to a situation when, under heavy traffic, the data availability notification for some of the channels would not get rearmed correctly. Change the implementation such that we let all remaining ingress frames be processed as usual and only disable NAPI once the hardware queues are empty. We also add a wait on the Tx side, to allow hardware time to process all in-flight Tx frames before issueing the disable command. Signed-off-by: Ioana Radulescu Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 68 ++++++++++++------------ 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 1ca9a18139ec..ecf92189b0a4 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -1243,34 +1243,36 @@ enable_err: return err; } -/* The DPIO store must be empty when we call this, - * at the end of every NAPI cycle. - */ -static u32 drain_channel(struct dpaa2_eth_channel *ch) +/* Total number of in-flight frames on ingress queues */ +static u32 ingress_fq_count(struct dpaa2_eth_priv *priv) { - u32 drained = 0, total = 0; + struct dpaa2_eth_fq *fq; + u32 fcnt = 0, bcnt = 0, total = 0; + int i, err; - do { - pull_channel(ch); - drained = consume_frames(ch, NULL); - total += drained; - } while (drained); + for (i = 0; i < priv->num_fqs; i++) { + fq = &priv->fq[i]; + err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt); + if (err) { + netdev_warn(priv->net_dev, "query_fq_count failed"); + break; + } + total += fcnt; + } return total; } -static u32 drain_ingress_frames(struct dpaa2_eth_priv *priv) +static void wait_for_fq_empty(struct dpaa2_eth_priv *priv) { - struct dpaa2_eth_channel *ch; - int i; - u32 drained = 0; - - for (i = 0; i < priv->num_channels; i++) { - ch = priv->channel[i]; - drained += drain_channel(ch); - } + int retries = 10; + u32 pending; - return drained; + do { + pending = ingress_fq_count(priv); + if (pending) + msleep(100); + } while (pending && --retries); } static int dpaa2_eth_stop(struct net_device *net_dev) @@ -1278,14 +1280,22 @@ static int dpaa2_eth_stop(struct net_device *net_dev) struct dpaa2_eth_priv *priv = netdev_priv(net_dev); int dpni_enabled = 0; int retries = 10; - u32 drained; netif_tx_stop_all_queues(net_dev); netif_carrier_off(net_dev); - /* Loop while dpni_disable() attempts to drain the egress FQs - * and confirm them back to us. + /* On dpni_disable(), the MC firmware will: + * - stop MAC Rx and wait for all Rx frames to be enqueued to software + * - cut off WRIOP dequeues from egress FQs and wait until transmission + * of all in flight Tx frames is finished (and corresponding Tx conf + * frames are enqueued back to software) + * + * Before calling dpni_disable(), we wait for all Tx frames to arrive + * on WRIOP. After it finishes, wait until all remaining frames on Rx + * and Tx conf queues are consumed on NAPI poll. */ + msleep(500); + do { dpni_disable(priv->mc_io, 0, priv->mc_token); dpni_is_enabled(priv->mc_io, 0, priv->mc_token, &dpni_enabled); @@ -1300,19 +1310,9 @@ static int dpaa2_eth_stop(struct net_device *net_dev) */ } - /* Wait for NAPI to complete on every core and disable it. - * In particular, this will also prevent NAPI from being rescheduled if - * a new CDAN is serviced, effectively discarding the CDAN. We therefore - * don't even need to disarm the channels, except perhaps for the case - * of a huge coalescing value. - */ + wait_for_fq_empty(priv); disable_ch_napi(priv); - /* Manually drain the Rx and TxConf queues */ - drained = drain_ingress_frames(priv); - if (drained) - netdev_dbg(net_dev, "Drained %d frames.\n", drained); - /* Empty the buffer pool */ drain_pool(priv); -- cgit v1.2.3 From 6394d98df6b47a4fe28715536bd6c8e003847071 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 17 Jan 2019 00:35:43 +0000 Subject: sb1000: fix a couple of indentation issues and remove assignment in if statements There is an if statement and a return statement that are incorrectly indented. Fix these. Also replace the assignment-in-if statements to assignment followed by an if to keep to the coding style. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/sb1000.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c index 7820fced33f6..941cfa8f1c2a 100644 --- a/drivers/net/sb1000.c +++ b/drivers/net/sb1000.c @@ -535,17 +535,20 @@ sb1000_activate(const int ioaddr[], const char* name) int status; ssleep(1); - if ((status = card_send_command(ioaddr, name, Command0, st))) + status = card_send_command(ioaddr, name, Command0, st); + if (status) return status; - if ((status = card_send_command(ioaddr, name, Command1, st))) + status = card_send_command(ioaddr, name, Command1, st); + if (status) return status; if (st[3] != 0xf1) { - if ((status = sb1000_start_get_set_command(ioaddr, name))) + status = sb1000_start_get_set_command(ioaddr, name); + if (status) return status; return -EIO; } udelay(1000); - return sb1000_start_get_set_command(ioaddr, name); + return sb1000_start_get_set_command(ioaddr, name); } /* get SB1000 firmware version */ -- cgit v1.2.3 From 5c423d71147422a2ba89a3cb4aaf83def2a4cec0 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 17 Jan 2019 20:59:19 +0800 Subject: net: ethernet: ti: cpsw-phy-sel: remove unneeded semicolon Remove unneeded semicolon. Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw-phy-sel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c index 396e1cd10667..fec275e2208d 100644 --- a/drivers/net/ethernet/ti/cpsw-phy-sel.c +++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c @@ -78,7 +78,7 @@ static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv, case PHY_INTERFACE_MODE_MII: mode = AM33XX_GMII_SEL_MODE_MII; break; - }; + } mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6); mask |= BIT(slave + 4); @@ -133,7 +133,7 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_phy_sel_priv *priv, case PHY_INTERFACE_MODE_MII: mode = AM33XX_GMII_SEL_MODE_MII; break; - }; + } switch (slave) { case 0: -- cgit v1.2.3 From bec03debe2e5ebc1c8bb811852b6106ce2129d71 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 17 Jan 2019 21:03:56 +0800 Subject: net/mlx4: remove unneeded semicolon Remove unneeded semicolon. Signed-off-by: YueHaibing Reviewed-by: Leon Romanovsky Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 2 +- drivers/net/ethernet/mellanox/mlx4/eq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index e65bc3c95630..c19e74e6ac94 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -3274,7 +3274,7 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat mlx4_warn(dev, "unknown value for link_state %02x on slave %d port %d\n", link_state, slave, port); return -EINVAL; - }; + } s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; s_info->link_state = link_state; diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 2df92dbd38e1..4953c852c247 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -820,7 +820,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? "HW" : "SW"); break; - }; + } ++eq->cons_index; eqes_found = 1; -- cgit v1.2.3 From e302c2a5fe0ca63b8fcc93389917625f486e0670 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 16 Jan 2019 19:47:57 +0100 Subject: net: phy: remove state PHY_CHANGELINK Since recent changes to the phylib state machine state PHY_CHANGELINK isn't used any longer. Therefore let's remove it. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 2 -- include/linux/phy.h | 6 ------ 2 files changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 241fb83ef4de..b0632e859564 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -47,7 +47,6 @@ static const char *phy_state_to_str(enum phy_state st) PHY_STATE_STR(RUNNING) PHY_STATE_STR(NOLINK) PHY_STATE_STR(FORCING) - PHY_STATE_STR(CHANGELINK) PHY_STATE_STR(HALTED) PHY_STATE_STR(RESUMING) } @@ -939,7 +938,6 @@ void phy_state_machine(struct work_struct *work) break; case PHY_NOLINK: case PHY_RUNNING: - case PHY_CHANGELINK: case PHY_RESUMING: err = phy_check_link_status(phydev); break; diff --git a/include/linux/phy.h b/include/linux/phy.h index f1c19bf8c658..232d93b9cea4 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -304,11 +304,6 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); * - irq or timer will set NOLINK if link goes down * - phy_stop moves to HALTED * - * CHANGELINK: PHY experienced a change in link state - * - timer moves to RUNNING if link - * - timer moves to NOLINK if the link is down - * - phy_stop moves to HALTED - * * HALTED: PHY is up, but no polling or interrupts are done. Or * PHY is in an error state. * @@ -327,7 +322,6 @@ enum phy_state { PHY_RUNNING, PHY_NOLINK, PHY_FORCING, - PHY_CHANGELINK, PHY_RESUMING }; -- cgit v1.2.3 From d8cce3a1bc539f7e928eb1d094a312089b146aa4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 16 Jan 2019 19:52:51 +0100 Subject: net: phy: improve get_phy_id Only caller of get_phy_id() is get_phy_device(). There a PHY ID of 0xffffffff is translated back to -ENODEV. So we can avoid some overhead by returning -ENODEV directly. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index ddb12f420940..3860dd85d097 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -773,15 +773,8 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id, /* Grab the bits from PHYIR1, and put them in the upper half */ phy_reg = mdiobus_read(bus, addr, MII_PHYSID1); if (phy_reg < 0) { - /* if there is no device, return without an error so scanning - * the bus works properly - */ - if (phy_reg == -EIO || phy_reg == -ENODEV) { - *phy_id = 0xffffffff; - return 0; - } - - return -EIO; + /* returning -ENODEV doesn't stop bus scanning */ + return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO; } *phy_id = (phy_reg & 0xffff) << 16; -- cgit v1.2.3 From c0028696cbb06dcff66fcad586a4a1be63f42fc2 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 16 Jan 2019 23:59:10 +0000 Subject: net: vxge: fix indentation issue There is a goto statement that indented too deeply, fix it. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/neterion/vxge/vxge-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 5ae3fa82909f..0da7393b2ef3 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -2553,7 +2553,7 @@ static int vxge_add_isr(struct vxgedev *vdev) vxge_debug_init(VXGE_ERR, "%s: Defaulting to INTA", vdev->ndev->name); - goto INTA_MODE; + goto INTA_MODE; } msix_idx = (vdev->vpaths[0].handle->vpath->vp_id * -- cgit v1.2.3 From fb70950eb4b1c14a3598321ef7305c941bc5e475 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 17 Jan 2019 00:03:26 +0000 Subject: net: jme: fix indentation issues There are two lines that have indentation issues, fix these. Also remove an empty line. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/jme.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index a5ab6f3403ae..763ee5281177 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -2034,10 +2034,9 @@ static void jme_drop_tx_map(struct jme_adapter *jme, int startidx, int count) ctxbi->len, PCI_DMA_TODEVICE); - ctxbi->mapping = 0; - ctxbi->len = 0; + ctxbi->mapping = 0; + ctxbi->len = 0; } - } static int -- cgit v1.2.3 From 472115d9834cd3a194a14269f28d8b146ad26c11 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 17 Jan 2019 20:07:54 +0100 Subject: net: phy: stop PHY if needed when entering phy_disconnect Stop PHY if needed when entering phy_disconnect. This allows drivers that don't need a separate call to phy_stop() to omit this call. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 3860dd85d097..616a5fe47f56 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -999,6 +999,9 @@ EXPORT_SYMBOL(phy_connect); */ void phy_disconnect(struct phy_device *phydev) { + if (phy_is_started(phydev)) + phy_stop(phydev); + if (phydev->irq > 0) phy_stop_interrupts(phydev); -- cgit v1.2.3 From cbfd12b3e8c3542e8142aa041714ed614d3f67b0 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 17 Jan 2019 20:08:39 +0100 Subject: net: phy: ensure phylib state machine is stopped after calling phy_stop The call to the phylib state machine in phy_stop() just ensures that the state machine isn't re-triggered, but a state machine call may be scheduled already. So lets's call phy_stop_machine(). This also allows to get rid of the call to phy_stop_machine() in phy_disconnect(). Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 1 + drivers/net/phy/phy_device.c | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index b0632e859564..37cf39fdcc91 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -858,6 +858,7 @@ void phy_stop(struct phy_device *phydev) mutex_unlock(&phydev->lock); phy_state_machine(&phydev->state_queue.work); + phy_stop_machine(phydev); /* Cannot call flush_scheduled_work() here as desired because * of rtnl_lock(), but PHY_HALTED shall guarantee irq handler diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 616a5fe47f56..e269a355012d 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1005,8 +1005,6 @@ void phy_disconnect(struct phy_device *phydev) if (phydev->irq > 0) phy_stop_interrupts(phydev); - phy_stop_machine(phydev); - phydev->adjust_link = NULL; phy_detach(phydev); -- cgit v1.2.3 From bb658ab7b8f2828b35c207a95cb0c05965721022 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 17 Jan 2019 20:09:21 +0100 Subject: net: phy: remove phy_stop_interrupts Interrupts have been disabled in phy_stop() already. So we can remove phy_stop_interrupts() and free the interrupt in phy_disconnect() directly. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 17 ----------------- drivers/net/phy/phy_device.c | 4 ++-- include/linux/phy.h | 1 - 3 files changed, 2 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 37cf39fdcc91..f7a92e7edff7 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -818,23 +818,6 @@ int phy_start_interrupts(struct phy_device *phydev) } EXPORT_SYMBOL(phy_start_interrupts); -/** - * phy_stop_interrupts - disable interrupts from a PHY device - * @phydev: target phy_device struct - */ -int phy_stop_interrupts(struct phy_device *phydev) -{ - int err = phy_disable_interrupts(phydev); - - if (err) - phy_error(phydev); - - free_irq(phydev->irq, phydev); - - return err; -} -EXPORT_SYMBOL(phy_stop_interrupts); - /** * phy_stop - Bring down the PHY link, and stop checking the status * @phydev: target phy_device struct diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e269a355012d..7b3164174251 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1002,8 +1002,8 @@ void phy_disconnect(struct phy_device *phydev) if (phy_is_started(phydev)) phy_stop(phydev); - if (phydev->irq > 0) - phy_stop_interrupts(phydev); + if (phy_interrupt_is_valid(phydev)) + free_irq(phydev->irq, phydev); phydev->adjust_link = NULL; diff --git a/include/linux/phy.h b/include/linux/phy.h index 232d93b9cea4..0990f913d649 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -951,7 +951,6 @@ int phy_aneg_done(struct phy_device *phydev); int phy_speed_down(struct phy_device *phydev, bool sync); int phy_speed_up(struct phy_device *phydev); -int phy_stop_interrupts(struct phy_device *phydev); int phy_restart_aneg(struct phy_device *phydev); int phy_reset_after_clk_enable(struct phy_device *phydev); -- cgit v1.2.3 From aba25279c10094c5c97d09c3491ca86d00b4ad5e Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 17 Jan 2019 23:59:18 +0200 Subject: net/mlx5e: Add TX reporter support Add mlx5e tx reporter to devlink health reporters. This reporter will be responsible for diagnosing, reporting and recovering of TX errors. This patch declares the TX reporter operations and allocate it using the devlink health API. Currently, this reporter supports reporting and recovering from send error CQE only. In addition, it adds diagnose information for the open SQs. For a local SQ recover (due to driver error report), in case of SQ recover failure, the recover operation will be considered as a failure. For a full TX recover, an attempt to close and open the channels will be done. If this one passed successfully, it will be considered as a successful recover. The SQ recover from error CQE flow is not a new feature in the driver, this patch re-organize the functions and adapt them for the devlink health API. For this purpose, move code from en_main.c to a new file named reporter_tx.c. Signed-off-by: Eran Ben Elisha Reviewed-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en.h | 18 +- .../net/ethernet/mellanox/mlx5/core/en/reporter.h | 14 + .../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 321 +++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 135 +-------- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +- 6 files changed, 367 insertions(+), 125 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 9de9abacf7f6..6bb2a860b15b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -22,7 +22,7 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \ # mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ en_tx.o en_rx.o en_dim.o en_txrx.o en/xdp.o en_stats.o \ - en_selftest.o en/port.o en/monitor_stats.o + en_selftest.o en/port.o en/monitor_stats.o en/reporter_tx.o # # Netdev extra diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 8fa8fdd30b85..27e276c9bf84 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -388,10 +388,7 @@ struct mlx5e_txqsq { struct mlx5e_channel *channel; int txq_ix; u32 rate_limit; - struct mlx5e_txqsq_recover { - struct work_struct recover_work; - u64 last_recover; - } recover; + struct work_struct recover_work; } ____cacheline_aligned_in_smp; struct mlx5e_dma_info { @@ -682,6 +679,13 @@ struct mlx5e_rss_params { u8 hfunc; }; +struct mlx5e_modify_sq_param { + int curr_state; + int next_state; + int rl_update; + int rl_index; +}; + struct mlx5e_priv { /* priv data path fields - start */ struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC]; @@ -737,6 +741,7 @@ struct mlx5e_priv { #ifdef CONFIG_MLX5_EN_TLS struct mlx5e_tls *tls; #endif + struct devlink_health_reporter *tx_reporter; }; struct mlx5e_profile { @@ -866,6 +871,11 @@ void mlx5e_set_rq_type(struct mlx5_core_dev *mdev, struct mlx5e_params *params); void mlx5e_init_rq_type_params(struct mlx5_core_dev *mdev, struct mlx5e_params *params); +int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, + struct mlx5e_modify_sq_param *p); +void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq); +void mlx5e_tx_disable_queue(struct netdev_queue *txq); + static inline bool mlx5e_tunnel_inner_ft_supported(struct mlx5_core_dev *mdev) { return (MLX5_CAP_ETH(mdev, tunnel_stateless_gre) && diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h new file mode 100644 index 000000000000..74083e120ab3 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2018 Mellanox Technologies. */ + +#ifndef __MLX5E_EN_REPORTER_H +#define __MLX5E_EN_REPORTER_H + +#include +#include "en.h" + +int mlx5e_tx_reporter_create(struct mlx5e_priv *priv); +void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv); +void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq); + +#endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c new file mode 100644 index 000000000000..9800df4909c2 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -0,0 +1,321 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2018 Mellanox Technologies. */ + +#include +#include "reporter.h" +#include "lib/eq.h" + +#define MLX5E_TX_REPORTER_PER_SQ_MAX_LEN 256 + +struct mlx5e_tx_err_ctx { + int (*recover)(struct mlx5e_txqsq *sq); + struct mlx5e_txqsq *sq; +}; + +static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) +{ + unsigned long exp_time = jiffies + msecs_to_jiffies(2000); + + while (time_before(jiffies, exp_time)) { + if (sq->cc == sq->pc) + return 0; + + msleep(20); + } + + netdev_err(sq->channel->netdev, + "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n", + sq->sqn, sq->cc, sq->pc); + + return -ETIMEDOUT; +} + +static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq) +{ + WARN_ONCE(sq->cc != sq->pc, + "SQ 0x%x: cc (0x%x) != pc (0x%x)\n", + sq->sqn, sq->cc, sq->pc); + sq->cc = 0; + sq->dma_fifo_cc = 0; + sq->pc = 0; +} + +static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state) +{ + struct mlx5_core_dev *mdev = sq->channel->mdev; + struct net_device *dev = sq->channel->netdev; + struct mlx5e_modify_sq_param msp = {0}; + int err; + + msp.curr_state = curr_state; + msp.next_state = MLX5_SQC_STATE_RST; + + err = mlx5e_modify_sq(mdev, sq->sqn, &msp); + if (err) { + netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn); + return err; + } + + memset(&msp, 0, sizeof(msp)); + msp.curr_state = MLX5_SQC_STATE_RST; + msp.next_state = MLX5_SQC_STATE_RDY; + + err = mlx5e_modify_sq(mdev, sq->sqn, &msp); + if (err) { + netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn); + return err; + } + + return 0; +} + +static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq) +{ + struct mlx5_core_dev *mdev = sq->channel->mdev; + struct net_device *dev = sq->channel->netdev; + u8 state; + int err; + + if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) + return 0; + + err = mlx5_core_query_sq_state(mdev, sq->sqn, &state); + if (err) { + netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n", + sq->sqn, err); + return err; + } + + if (state != MLX5_RQC_STATE_ERR) { + netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn); + return -EINVAL; + } + + mlx5e_tx_disable_queue(sq->txq); + + err = mlx5e_wait_for_sq_flush(sq); + if (err) + return err; + + /* At this point, no new packets will arrive from the stack as TXQ is + * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all + * pending WQEs. SQ can safely reset the SQ. + */ + + err = mlx5e_sq_to_ready(sq, state); + if (err) + return err; + + mlx5e_reset_txqsq_cc_pc(sq); + sq->stats->recover++; + mlx5e_activate_txqsq(sq); + + return 0; +} + +void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq) +{ + char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN]; + struct mlx5e_tx_err_ctx err_ctx = {0}; + + err_ctx.sq = sq; + err_ctx.recover = mlx5e_tx_reporter_err_cqe_recover; + sprintf(err_str, "ERR CQE on SQ: 0x%x", sq->sqn); + + devlink_health_report(sq->channel->priv->tx_reporter, err_str, + &err_ctx); +} + +/* state lock cannot be grabbed within this function. + * It can cause a dead lock or a read-after-free. + */ +int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_tx_err_ctx *err_ctx) +{ + return err_ctx->recover(err_ctx->sq); +} + +static int mlx5e_tx_reporter_recover_all(struct mlx5e_priv *priv) +{ + int err; + + mutex_lock(&priv->state_lock); + mlx5e_close_locked(priv->netdev); + err = mlx5e_open_locked(priv->netdev); + mutex_unlock(&priv->state_lock); + + return err; +} + +static int mlx5e_tx_reporter_recover(struct devlink_health_reporter *reporter, + void *context) +{ + struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); + struct mlx5e_tx_err_ctx *err_ctx = context; + + return err_ctx ? mlx5e_tx_reporter_recover_from_ctx(err_ctx) : + mlx5e_tx_reporter_recover_all(priv); +} + +static int +mlx5e_tx_reporter_build_diagnose_output(struct devlink_health_buffer *buffer, + u32 sqn, u8 state, u8 stopped) +{ + int err, i; + int nest = 0; + char name[20]; + + err = devlink_health_buffer_nest_start(buffer, + DEVLINK_ATTR_HEALTH_BUFFER_OBJECT); + if (err) + goto buffer_error; + nest++; + + err = devlink_health_buffer_nest_start(buffer, + DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR); + if (err) + goto buffer_error; + nest++; + + sprintf(name, "SQ 0x%x", sqn); + err = devlink_health_buffer_put_object_name(buffer, name); + if (err) + goto buffer_error; + + err = devlink_health_buffer_nest_start(buffer, + DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE); + if (err) + goto buffer_error; + nest++; + + err = devlink_health_buffer_nest_start(buffer, + DEVLINK_ATTR_HEALTH_BUFFER_OBJECT); + if (err) + goto buffer_error; + nest++; + + err = devlink_health_buffer_nest_start(buffer, + DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR); + if (err) + goto buffer_error; + nest++; + + err = devlink_health_buffer_put_object_name(buffer, "HW state"); + if (err) + goto buffer_error; + + err = devlink_health_buffer_nest_start(buffer, + DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE); + if (err) + goto buffer_error; + nest++; + + err = devlink_health_buffer_put_value_u8(buffer, state); + if (err) + goto buffer_error; + + devlink_health_buffer_nest_end(buffer); /* DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE */ + nest--; + + devlink_health_buffer_nest_end(buffer); /* DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR */ + nest--; + + err = devlink_health_buffer_nest_start(buffer, + DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR); + if (err) + goto buffer_error; + nest++; + + err = devlink_health_buffer_put_object_name(buffer, "stopped"); + if (err) + goto buffer_error; + + err = devlink_health_buffer_nest_start(buffer, + DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE); + if (err) + goto buffer_error; + nest++; + + err = devlink_health_buffer_put_value_u8(buffer, stopped); + if (err) + goto buffer_error; + + for (i = 0; i < nest; i++) + devlink_health_buffer_nest_end(buffer); + + return 0; + +buffer_error: + for (i = 0; i < nest; i++) + devlink_health_buffer_nest_cancel(buffer); + return err; +} + +static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter, + struct devlink_health_buffer **buffers_array, + unsigned int buffer_size, + unsigned int num_buffers) +{ + struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); + unsigned int buff = 0; + int i = 0, err = 0; + + if (buffer_size < MLX5E_TX_REPORTER_PER_SQ_MAX_LEN) + return -ENOMEM; + + mutex_lock(&priv->state_lock); + + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { + mutex_unlock(&priv->state_lock); + return 0; + } + + while (i < priv->channels.num * priv->channels.params.num_tc) { + struct mlx5e_txqsq *sq = priv->txq2sq[i]; + u8 state; + + err = mlx5_core_query_sq_state(priv->mdev, sq->sqn, &state); + if (err) + break; + + err = mlx5e_tx_reporter_build_diagnose_output(buffers_array[buff], + sq->sqn, state, + netif_xmit_stopped(sq->txq)); + if (err) { + if (++buff == num_buffers) + break; + } else { + i++; + } + } + + mutex_unlock(&priv->state_lock); + return err; +} + +static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = { + .name = "TX", + .recover = mlx5e_tx_reporter_recover, + .diagnose_size = MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC * + MLX5E_TX_REPORTER_PER_SQ_MAX_LEN, + .diagnose = mlx5e_tx_reporter_diagnose, + .dump_size = 0, + .dump = NULL, +}; + +#define MLX5_REPORTER_TX_GRACEFUL_PERIOD 500 +int mlx5e_tx_reporter_create(struct mlx5e_priv *priv) +{ + struct mlx5_core_dev *mdev = priv->mdev; + struct devlink *devlink = priv_to_devlink(mdev); + + priv->tx_reporter = + devlink_health_reporter_create(devlink, &mlx5_tx_reporter_ops, + MLX5_REPORTER_TX_GRACEFUL_PERIOD, + true, priv); + return PTR_ERR_OR_ZERO(priv->tx_reporter); +} + +void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv) +{ + devlink_health_reporter_destroy(priv->tx_reporter); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 8cfd2ec7c0a2..4c4507384fed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -51,6 +51,7 @@ #include "en/xdp.h" #include "lib/eq.h" #include "en/monitor_stats.h" +#include "en/reporter.h" struct mlx5e_rq_param { u32 rqc[MLX5_ST_SZ_DW(rqc)]; @@ -1160,7 +1161,7 @@ static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa) return 0; } -static void mlx5e_sq_recover(struct work_struct *work); +static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work); static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, int txq_ix, struct mlx5e_params *params, @@ -1182,7 +1183,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, sq->uar_map = mdev->mlx5e_res.bfreg.map; sq->min_inline_mode = params->tx_min_inline_mode; sq->stats = &c->priv->channel_stats[c->ix].sq[tc]; - INIT_WORK(&sq->recover.recover_work, mlx5e_sq_recover); + INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work); if (MLX5_IPSEC_DEV(c->priv->mdev)) set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state); if (mlx5_accel_is_tls_device(c->priv->mdev)) @@ -1270,15 +1271,8 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev, return err; } -struct mlx5e_modify_sq_param { - int curr_state; - int next_state; - bool rl_update; - int rl_index; -}; - -static int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, - struct mlx5e_modify_sq_param *p) +int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, + struct mlx5e_modify_sq_param *p) { void *in; void *sqc; @@ -1376,17 +1370,7 @@ err_free_txqsq: return err; } -static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq) -{ - WARN_ONCE(sq->cc != sq->pc, - "SQ 0x%x: cc (0x%x) != pc (0x%x)\n", - sq->sqn, sq->cc, sq->pc); - sq->cc = 0; - sq->dma_fifo_cc = 0; - sq->pc = 0; -} - -static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) +void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) { sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix); clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state); @@ -1395,7 +1379,7 @@ static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) netif_tx_start_queue(sq->txq); } -static inline void netif_tx_disable_queue(struct netdev_queue *txq) +void mlx5e_tx_disable_queue(struct netdev_queue *txq) { __netif_tx_lock_bh(txq); netif_tx_stop_queue(txq); @@ -1411,7 +1395,7 @@ static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq) /* prevent netif_tx_wake_queue */ napi_synchronize(&c->napi); - netif_tx_disable_queue(sq->txq); + mlx5e_tx_disable_queue(sq->txq); /* last doorbell out, godspeed .. */ if (mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1)) { @@ -1431,6 +1415,7 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq) struct mlx5_rate_limit rl = {0}; cancel_work_sync(&sq->dim.work); + cancel_work_sync(&sq->recover_work); mlx5e_destroy_sq(mdev, sq->sqn); if (sq->rate_limit) { rl.rate = sq->rate_limit; @@ -1440,105 +1425,15 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq) mlx5e_free_txqsq(sq); } -static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) +static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work) { - unsigned long exp_time = jiffies + msecs_to_jiffies(2000); - - while (time_before(jiffies, exp_time)) { - if (sq->cc == sq->pc) - return 0; - - msleep(20); - } - - netdev_err(sq->channel->netdev, - "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n", - sq->sqn, sq->cc, sq->pc); - - return -ETIMEDOUT; -} - -static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state) -{ - struct mlx5_core_dev *mdev = sq->channel->mdev; - struct net_device *dev = sq->channel->netdev; - struct mlx5e_modify_sq_param msp = {0}; - int err; - - msp.curr_state = curr_state; - msp.next_state = MLX5_SQC_STATE_RST; - - err = mlx5e_modify_sq(mdev, sq->sqn, &msp); - if (err) { - netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn); - return err; - } - - memset(&msp, 0, sizeof(msp)); - msp.curr_state = MLX5_SQC_STATE_RST; - msp.next_state = MLX5_SQC_STATE_RDY; + struct mlx5e_txqsq *sq = container_of(recover_work, struct mlx5e_txqsq, + recover_work); - err = mlx5e_modify_sq(mdev, sq->sqn, &msp); - if (err) { - netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn); - return err; - } - - return 0; -} - -static void mlx5e_sq_recover(struct work_struct *work) -{ - struct mlx5e_txqsq_recover *recover = - container_of(work, struct mlx5e_txqsq_recover, - recover_work); - struct mlx5e_txqsq *sq = container_of(recover, struct mlx5e_txqsq, - recover); - struct mlx5_core_dev *mdev = sq->channel->mdev; - struct net_device *dev = sq->channel->netdev; - u8 state; - int err; - - err = mlx5_core_query_sq_state(mdev, sq->sqn, &state); - if (err) { - netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n", - sq->sqn, err); - return; - } - - if (state != MLX5_RQC_STATE_ERR) { - netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn); - return; - } - - netif_tx_disable_queue(sq->txq); - - if (mlx5e_wait_for_sq_flush(sq)) - return; - - /* If the interval between two consecutive recovers per SQ is too - * short, don't recover to avoid infinite loop of ERR_CQE -> recover. - * If we reached this state, there is probably a bug that needs to be - * fixed. let's keep the queue close and let tx timeout cleanup. - */ - if (jiffies_to_msecs(jiffies - recover->last_recover) < - MLX5E_SQ_RECOVER_MIN_INTERVAL) { - netdev_err(dev, "Recover SQ 0x%x canceled, too many error CQEs\n", - sq->sqn); - return; - } - - /* At this point, no new packets will arrive from the stack as TXQ is - * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all - * pending WQEs. SQ can safely reset the SQ. - */ - if (mlx5e_sq_to_ready(sq, state)) + if (!sq->channel->priv->tx_reporter) return; - mlx5e_reset_txqsq_cc_pc(sq); - sq->stats->recover++; - recover->last_recover = jiffies; - mlx5e_activate_txqsq(sq); + mlx5e_tx_reporter_err_cqe(sq); } static int mlx5e_open_icosq(struct mlx5e_channel *c, @@ -3207,6 +3102,7 @@ static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv) { int tc; + mlx5e_tx_reporter_destroy(priv); for (tc = 0; tc < priv->profile->max_tc; tc++) mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]); } @@ -4908,6 +4804,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv) #ifdef CONFIG_MLX5_CORE_EN_DCB mlx5e_dcbnl_initialize(priv); #endif + mlx5e_tx_reporter_create(priv); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 598ad7e4d5c9..a8e052a5ce36 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -514,7 +514,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) mlx5e_dump_error_cqe(sq, (struct mlx5_err_cqe *)cqe); queue_work(cq->channel->priv->wq, - &sq->recover.recover_work); + &sq->recover_work); } stats->cqe_err++; } -- cgit v1.2.3 From ce019faa70f81555fa17ebc1d5a03651f2e7e15a Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 17 Jan 2019 23:59:19 +0200 Subject: net/mlx5e: Add TX timeout support for mlx5e TX reporter With this patch, ndo_tx_timeout callback will be redirected to the TX reporter in order to detect a TX timeout error and report it to the devlink health. (The watchdog detects TX timeouts, but the driver verify the issue still exists before launching any recover method). In addition, recover from TX timeout in case of lost interrupt was added to the TX reporter recover method. The TX timeout recover from lost interrupt is not a new feature in the driver, this patch re-organize the functionality and move it to the TX reporter recovery flow. TX timeout example: (with auto_recover set to false, if set to true, the manual recover and diagnose sections are irrelevant) $cat /sys/kernel/debug/tracing/trace ... devlink_health_report: bus_name=pci dev_name=0000:00:09.0 driver_name=mlx5_core reporter_name=TX: TX timeout on queue: 0, SQ: 0xd8a, CQ: 0x406, SQ Cons: 0x2 SQ Prod: 0x2, usecs since last trans: 13972000 $devlink health diagnose pci/0000:00:09 reporter TX SQ 0xd8a: HW state: 1, stopped: 1 SQ 0xe44: HW state: 1, stopped: 0 SQ 0xeb4: HW state: 1, stopped: 0 SQ 0xf1f: HW state: 1, stopped: 0 SQ 0xf80: HW state: 1, stopped: 0 SQ 0xfe5: HW state: 1, stopped: 0 $devlink health recover pci/0000:00:09 reporter TX $devlink health show pci/0000:00:09.0: name TX state healthy #err 1 #recover 1 last_dump_ts N/A dump_available false attributes: grace_period 500 auto_recover false Signed-off-by: Eran Ben Elisha Reviewed-by: Saeed Mahameed Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en/reporter.h | 1 + .../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 35 +++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 51 +++------------------- 3 files changed, 43 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h index 74083e120ab3..2335c5b48820 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h @@ -10,5 +10,6 @@ int mlx5e_tx_reporter_create(struct mlx5e_priv *priv); void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv); void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq); +void mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq); #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 9800df4909c2..d9675afbb924 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -126,6 +126,41 @@ void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq) &err_ctx); } +static int mlx5e_tx_reporter_timeout_recover(struct mlx5e_txqsq *sq) +{ + struct mlx5_eq_comp *eq = sq->cq.mcq.eq; + u32 eqe_count; + + netdev_err(sq->channel->netdev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n", + eq->core.eqn, eq->core.cons_index, eq->core.irqn); + + eqe_count = mlx5_eq_poll_irq_disabled(eq); + if (!eqe_count) { + clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); + return 1; + } + + netdev_err(sq->channel->netdev, "Recover %d eqes on EQ 0x%x\n", + eqe_count, eq->core.eqn); + sq->channel->stats->eq_rearm++; + return 0; +} + +void mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq) +{ + struct mlx5e_tx_err_ctx err_ctx; + char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN]; + + err_ctx.sq = sq; + err_ctx.recover = mlx5e_tx_reporter_timeout_recover; + sprintf(err_str, + "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n", + sq->channel->ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc, + jiffies_to_usecs(jiffies - sq->txq->trans_start)); + devlink_health_report(sq->channel->priv->tx_reporter, err_str, + &err_ctx); +} + /* state lock cannot be grabbed within this function. * It can cause a dead lock or a read-after-free. */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 4c4507384fed..dee0c8f3d4e9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4074,31 +4074,14 @@ netdev_features_t mlx5e_features_check(struct sk_buff *skb, return features; } -static bool mlx5e_tx_timeout_eq_recover(struct net_device *dev, - struct mlx5e_txqsq *sq) -{ - struct mlx5_eq_comp *eq = sq->cq.mcq.eq; - u32 eqe_count; - - netdev_err(dev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n", - eq->core.eqn, eq->core.cons_index, eq->core.irqn); - - eqe_count = mlx5_eq_poll_irq_disabled(eq); - if (!eqe_count) - return false; - - netdev_err(dev, "Recover %d eqes on EQ 0x%x\n", eqe_count, eq->core.eqn); - sq->channel->stats->eq_rearm++; - return true; -} - static void mlx5e_tx_timeout_work(struct work_struct *work) { struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv, tx_timeout_work); - struct net_device *dev = priv->netdev; - bool reopen_channels = false; - int i, err; + int i; + + if (!priv->tx_reporter) + return; rtnl_lock(); mutex_lock(&priv->state_lock); @@ -4107,36 +4090,16 @@ static void mlx5e_tx_timeout_work(struct work_struct *work) goto unlock; for (i = 0; i < priv->channels.num * priv->channels.params.num_tc; i++) { - struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, i); + struct netdev_queue *dev_queue = + netdev_get_tx_queue(priv->netdev, i); struct mlx5e_txqsq *sq = priv->txq2sq[i]; if (!netif_xmit_stopped(dev_queue)) continue; - netdev_err(dev, - "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n", - i, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc, - jiffies_to_usecs(jiffies - dev_queue->trans_start)); - - /* If we recover a lost interrupt, most likely TX timeout will - * be resolved, skip reopening channels - */ - if (!mlx5e_tx_timeout_eq_recover(dev, sq)) { - clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); - reopen_channels = true; - } + mlx5e_tx_reporter_timeout(sq); } - if (!reopen_channels) - goto unlock; - - mlx5e_close_locked(dev); - err = mlx5e_open_locked(dev); - if (err) - netdev_err(priv->netdev, - "mlx5e_open_locked failed recovering from a tx_timeout, err(%d).\n", - err); - unlock: mutex_unlock(&priv->state_lock); rtnl_unlock(); -- cgit v1.2.3 From 2c9dd668914bb9813b83bc62c28ebfe53e205525 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:03 +0800 Subject: net: hns3: modify enet reinitialization interface hns3_reset_notify_init_enet and hns3_reset_notify_uninit_enet are the reinitialization interface that will be called when the device reset, the number of TC changed, or the queue length changed. So these two function should call hns3_get_ring_config() and hns3_put_ring_config() to allocate and free memory for the ring with the correct number. Also this patch fixes a double free problem when hns3_reset_notify_uninit_enet calling hns3_nic_dealloc_vector_data Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 1bf7a5f116a0..e0621ef70984 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3185,6 +3185,9 @@ static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) for (i = 0; i < priv->vector_num; i++) { tqp_vector = &priv->tqp_vector[i]; + if (!tqp_vector->rx_group.ring && !tqp_vector->tx_group.ring) + continue; + ret = hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain); if (ret) @@ -3238,6 +3241,7 @@ static int hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, { struct hns3_nic_ring_data *ring_data = priv->ring_data; int queue_num = priv->ae_handle->kinfo.num_tqps; + int desc_num = priv->ae_handle->kinfo.num_desc; struct pci_dev *pdev = priv->ae_handle->pdev; struct hns3_enet_ring *ring; @@ -3263,7 +3267,7 @@ static int hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, ring->dev = priv->dev; ring->desc_dma_addr = 0; ring->buf_size = q->buf_size; - ring->desc_num = q->desc_num; + ring->desc_num = desc_num; ring->next_to_use = 0; ring->next_to_clean = 0; @@ -4045,10 +4049,14 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle) /* Carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); - ret = hns3_nic_alloc_vector_data(priv); + ret = hns3_get_ring_config(priv); if (ret) return ret; + ret = hns3_nic_alloc_vector_data(priv); + if (ret) + goto err_put_ring; + hns3_restore_coal(priv); ret = hns3_nic_init_vector_data(priv); @@ -4068,6 +4076,9 @@ err_uninit_vector: priv->ring_data = NULL; err_dealloc_vector: hns3_nic_dealloc_vector_data(priv); +err_put_ring: + hns3_put_ring_config(priv); + priv->ring_data = NULL; return ret; } @@ -4101,6 +4112,9 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle) if (ret) netdev_err(netdev, "uninit ring error\n"); + hns3_put_ring_config(priv); + priv->ring_data = NULL; + clear_bit(HNS3_NIC_STATE_INITED, &priv->state); return ret; -- cgit v1.2.3 From a81aca01a1152b8fafcb67f6d3122cf815e87a70 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:04 +0800 Subject: net: hns3: remove unused member in struct hns3_enet_ring The irq_init_flag field in struct hns3_enet_ring is unnecessary. This patch removes it. Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 1 - drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index e0621ef70984..c6f2d72a5e6f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3208,7 +3208,6 @@ static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) tqp_vector->irq_init_flag = HNS3_VECTOR_NOT_INITED; } - priv->ring_data[i].ring->irq_init_flag = HNS3_VECTOR_NOT_INITED; hns3_clear_ring_group(&tqp_vector->rx_group); hns3_clear_ring_group(&tqp_vector->tx_group); netif_napi_del(&priv->tqp_vector[i].napi); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index e55995e93bb0..f59ab7387b1f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -412,7 +412,6 @@ struct hns3_enet_ring { unsigned char *va; /* first buffer address for current packet */ u32 flag; /* ring attribute */ - int irq_init_flag; int numa_node; cpumask_t affinity_mask; -- cgit v1.2.3 From be5929b89002bb6b06b299f04bc35d90ab9d08fe Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:05 +0800 Subject: net: hns3: remove unnecessary hns3_adjust_tqps_num The parameter passed to hns3_set_channels() are already the number of queues per channel of the enabled TC, so it is not need to divide the number of enabled TCs. Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index c6f2d72a5e6f..c88714c667ba 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4183,11 +4183,6 @@ err_alloc_vector: return ret; } -static int hns3_adjust_tqps_num(u8 num_tc, u32 new_tqp_num) -{ - return (new_tqp_num / num_tc) * num_tc; -} - int hns3_set_channels(struct net_device *netdev, struct ethtool_channels *ch) { @@ -4211,7 +4206,6 @@ int hns3_set_channels(struct net_device *netdev, return -EINVAL; } - new_tqp_num = hns3_adjust_tqps_num(kinfo->num_tc, new_tqp_num); if (kinfo->num_tqps == new_tqp_num) return 0; -- cgit v1.2.3 From 65749f7375ae7a3cc14237c9972e5a3c14116c85 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:06 +0800 Subject: net: hns3: reuse reinitialization interface in the hns3_set_channels There is already common interface for network device reinitialization, so hns3_set_channels() should just call them. Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 75 ++++--------------------- 1 file changed, 12 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index c88714c667ba..0cd70d7667be 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4144,52 +4144,11 @@ static int hns3_reset_notify(struct hnae3_handle *handle, return ret; } -static int hns3_modify_tqp_num(struct net_device *netdev, u16 new_tqp_num) -{ - struct hns3_nic_priv *priv = netdev_priv(netdev); - struct hnae3_handle *h = hns3_get_handle(netdev); - int ret; - - ret = h->ae_algo->ops->set_channels(h, new_tqp_num); - if (ret) - return ret; - - ret = hns3_get_ring_config(priv); - if (ret) - return ret; - - ret = hns3_nic_alloc_vector_data(priv); - if (ret) - goto err_alloc_vector; - - hns3_restore_coal(priv); - - ret = hns3_nic_init_vector_data(priv); - if (ret) - goto err_uninit_vector; - - ret = hns3_init_all_ring(priv); - if (ret) - goto err_put_ring; - - return 0; - -err_put_ring: - hns3_put_ring_config(priv); -err_uninit_vector: - hns3_nic_uninit_vector_data(priv); -err_alloc_vector: - hns3_nic_dealloc_vector_data(priv); - return ret; -} - int hns3_set_channels(struct net_device *netdev, struct ethtool_channels *ch) { - struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = hns3_get_handle(netdev); struct hnae3_knic_private_info *kinfo = &h->kinfo; - bool if_running = netif_running(netdev); u32 new_tqp_num = ch->combined_count; u16 org_tqp_num; int ret; @@ -4209,27 +4168,18 @@ int hns3_set_channels(struct net_device *netdev, if (kinfo->num_tqps == new_tqp_num) return 0; - if (if_running) - hns3_nic_net_stop(netdev); - - ret = hns3_nic_uninit_vector_data(priv); - if (ret) { - dev_err(&netdev->dev, - "Unbind vector with tqp fail, nothing is changed"); - goto open_netdev; - } - - hns3_store_coal(priv); - - hns3_nic_dealloc_vector_data(priv); + ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT); + if (ret) + return ret; - hns3_uninit_all_ring(priv); - hns3_put_ring_config(priv); + ret = hns3_reset_notify(h, HNAE3_UNINIT_CLIENT); + if (ret) + return ret; org_tqp_num = h->kinfo.num_tqps; - ret = hns3_modify_tqp_num(netdev, new_tqp_num); + ret = h->ae_algo->ops->set_channels(h, new_tqp_num); if (ret) { - ret = hns3_modify_tqp_num(netdev, org_tqp_num); + ret = h->ae_algo->ops->set_channels(h, org_tqp_num); if (ret) { /* If revert to old tqp failed, fatal error occurred */ dev_err(&netdev->dev, @@ -4239,12 +4189,11 @@ int hns3_set_channels(struct net_device *netdev, dev_info(&netdev->dev, "Change tqp num fail, Revert to old tqp num"); } + ret = hns3_reset_notify(h, HNAE3_INIT_CLIENT); + if (ret) + return ret; -open_netdev: - if (if_running) - hns3_nic_net_open(netdev); - - return ret; + return hns3_reset_notify(h, HNAE3_UP_CLIENT); } static const struct hnae3_client_ops client_ops = { -- cgit v1.2.3 From 73fc9c4882439b3ea4f185264e1c6d969d61b067 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:07 +0800 Subject: net: hns3: add interface hclge_tm_bp_setup Provide a common interface to complete the back pressure settings of all enabled TCs. So other functions directly call this interface to complete the corresponding operation. Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 00458da67503..fda91e536a39 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1228,10 +1228,23 @@ static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev) return hclge_mac_pause_en_cfg(hdev, tx_en, rx_en); } +static int hclge_tm_bp_setup(struct hclge_dev *hdev) +{ + int ret = 0; + int i; + + for (i = 0; i < hdev->tm_info.num_tc; i++) { + ret = hclge_bp_setup_hw(hdev, i); + if (ret) + return ret; + } + + return ret; +} + int hclge_pause_setup_hw(struct hclge_dev *hdev) { int ret; - u8 i; ret = hclge_pause_param_setup_hw(hdev); if (ret) @@ -1250,13 +1263,7 @@ int hclge_pause_setup_hw(struct hclge_dev *hdev) if (ret) dev_warn(&hdev->pdev->dev, "set pfc pause failed:%d\n", ret); - for (i = 0; i < hdev->tm_info.num_tc; i++) { - ret = hclge_bp_setup_hw(hdev, i); - if (ret) - return ret; - } - - return 0; + return hclge_tm_bp_setup(hdev); } void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc) -- cgit v1.2.3 From c78b5b6cdc8fd8a305b26ba59fe5fad6a0acbe6e Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:08 +0800 Subject: net: hns3: modify parameter checks in the hns3_set_channels The number of queues for each enabled TC should range from 1 to the maximum available value, and return directly if the value is same as the current one. Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0cd70d7667be..0bda9bd8ecc1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4157,15 +4157,14 @@ int hns3_set_channels(struct net_device *netdev, return -EINVAL; if (new_tqp_num > hns3_get_max_available_channels(h) || - new_tqp_num < kinfo->num_tc) { + new_tqp_num < 1) { dev_err(&netdev->dev, - "Change tqps fail, the tqp range is from %d to %d", - kinfo->num_tc, + "Change tqps fail, the tqp range is from 1 to %d", hns3_get_max_available_channels(h)); return -EINVAL; } - if (kinfo->num_tqps == new_tqp_num) + if (kinfo->rss_size == new_tqp_num) return 0; ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT); -- cgit v1.2.3 From af95882728e30969d3ef911a0814bcd9ca56ee37 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:09 +0800 Subject: net: hns3: remove redundant codes in hclge_knic_setup The TC info will be updated in hclge_tm_vport_tc_info_update(), so hclge_knic_setup() no need to do it again. Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 17 +---------------- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 2 +- 2 files changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index f7637c08bb3a..17b1e33b0d4a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1096,7 +1096,7 @@ static int hclge_knic_setup(struct hclge_vport *vport, struct hnae3_handle *nic = &vport->nic; struct hnae3_knic_private_info *kinfo = &nic->kinfo; struct hclge_dev *hdev = vport->back; - int i, ret; + int ret; kinfo->num_desc = num_desc; kinfo->rx_buf_len = hdev->rx_buf_len; @@ -1105,21 +1105,6 @@ static int hclge_knic_setup(struct hclge_vport *vport, = min_t(u16, hdev->rss_size_max, num_tqps / kinfo->num_tc); kinfo->num_tqps = kinfo->rss_size * kinfo->num_tc; - for (i = 0; i < HNAE3_MAX_TC; i++) { - if (hdev->hw_tc_map & BIT(i)) { - kinfo->tc_info[i].enable = true; - kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size; - kinfo->tc_info[i].tqp_count = kinfo->rss_size; - kinfo->tc_info[i].tc = i; - } else { - /* Set to default queue if TC is disable */ - kinfo->tc_info[i].enable = false; - kinfo->tc_info[i].tqp_offset = 0; - kinfo->tc_info[i].tqp_count = 1; - kinfo->tc_info[i].tc = 0; - } - } - kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, sizeof(struct hnae3_queue *), GFP_KERNEL); if (!kinfo->tqp) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index fda91e536a39..8c5795013a60 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -529,7 +529,7 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) vport->dwrr = 100; /* 100 percent as init */ vport->alloc_rss_size = kinfo->rss_size; - for (i = 0; i < kinfo->num_tc; i++) { + for (i = 0; i < HNAE3_MAX_TC; i++) { if (hdev->hw_tc_map & BIT(i)) { kinfo->tc_info[i].enable = true; kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size; -- cgit v1.2.3 From 672ad0ede179b129ad1c9dbc080a8b808cce510c Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:10 +0800 Subject: net: hns3: fix user configuration loss for ethtool -L Ethtool -L option with the combined parameter is for changing the number of multi-purpose channels of the specified network device. Under the current scheme, the user configuration information will be lost after the reset or TC information changed. This patch fixes this issue. By default, this configuration is set to the minimum between the number of queues for each enabled TCs and the maximum number support available in the hardware. When there is a user configuration, regardless of the reset or TC information change, it should keep the user's configuration while it is under the hardware limits, otherwise set to the maximum number support available in the hardware. Fixes: 09f2af6405b8 ("net: hns3: add support to modify tqps number") Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 54 ++++------------------ .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 40 ++++++++++++++-- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 1 + 4 files changed, 47 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 36eab37d8a40..81d15854478d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -500,6 +500,7 @@ struct hnae3_tc_info { struct hnae3_knic_private_info { struct net_device *netdev; /* Set by KNIC client when init instance */ u16 rss_size; /* Allocated RSS queues */ + u16 req_rss_size; u16 rx_buf_len; u16 num_desc; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 17b1e33b0d4a..55a456f1dd38 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1068,14 +1068,14 @@ static int hclge_map_tqps_to_func(struct hclge_dev *hdev, u16 func_id, return ret; } -static int hclge_assign_tqp(struct hclge_vport *vport) +static int hclge_assign_tqp(struct hclge_vport *vport, u16 num_tqps) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hclge_dev *hdev = vport->back; int i, alloced; for (i = 0, alloced = 0; i < hdev->num_tqps && - alloced < kinfo->num_tqps; i++) { + alloced < num_tqps; i++) { if (!hdev->htqp[i].alloced) { hdev->htqp[i].q.handle = &vport->nic; hdev->htqp[i].q.tqp_index = alloced; @@ -1085,7 +1085,9 @@ static int hclge_assign_tqp(struct hclge_vport *vport) alloced++; } } - vport->alloc_tqps = kinfo->num_tqps; + vport->alloc_tqps = alloced; + kinfo->rss_size = min_t(u16, hdev->rss_size_max, + vport->alloc_tqps / hdev->tm_info.num_tc); return 0; } @@ -1100,17 +1102,13 @@ static int hclge_knic_setup(struct hclge_vport *vport, kinfo->num_desc = num_desc; kinfo->rx_buf_len = hdev->rx_buf_len; - kinfo->num_tc = min_t(u16, num_tqps, hdev->tm_info.num_tc); - kinfo->rss_size - = min_t(u16, hdev->rss_size_max, num_tqps / kinfo->num_tc); - kinfo->num_tqps = kinfo->rss_size * kinfo->num_tc; - kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps, + kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, num_tqps, sizeof(struct hnae3_queue *), GFP_KERNEL); if (!kinfo->tqp) return -ENOMEM; - ret = hclge_assign_tqp(vport); + ret = hclge_assign_tqp(vport, num_tqps); if (ret) dev_err(&hdev->pdev->dev, "fail to assign TQPs %d.\n", ret); @@ -7532,25 +7530,6 @@ static void hclge_get_tqps_and_rss_info(struct hnae3_handle *handle, *max_rss_size = hdev->rss_size_max; } -static void hclge_release_tqp(struct hclge_vport *vport) -{ - struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; - struct hclge_dev *hdev = vport->back; - int i; - - for (i = 0; i < kinfo->num_tqps; i++) { - struct hclge_tqp *tqp = - container_of(kinfo->tqp[i], struct hclge_tqp, q); - - tqp->q.handle = NULL; - tqp->q.tqp_index = 0; - tqp->alloced = false; - } - - devm_kfree(&hdev->pdev->dev, kinfo->tqp); - kinfo->tqp = NULL; -} - static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num) { struct hclge_vport *vport = hclge_get_vport(handle); @@ -7565,24 +7544,11 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num) u32 *rss_indir; int ret, i; - /* Free old tqps, and reallocate with new tqp number when nic setup */ - hclge_release_tqp(vport); - - ret = hclge_knic_setup(vport, new_tqps_num, kinfo->num_desc); - if (ret) { - dev_err(&hdev->pdev->dev, "setup nic fail, ret =%d\n", ret); - return ret; - } - - ret = hclge_map_tqp_to_vport(hdev, vport); - if (ret) { - dev_err(&hdev->pdev->dev, "map vport tqp fail, ret =%d\n", ret); - return ret; - } + kinfo->req_rss_size = new_tqps_num; - ret = hclge_tm_schd_init(hdev); + ret = hclge_tm_vport_map_update(hdev); if (ret) { - dev_err(&hdev->pdev->dev, "tm schd init fail, ret =%d\n", ret); + dev_err(&hdev->pdev->dev, "tm vport map fail, ret =%d\n", ret); return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 8c5795013a60..fb8596a3e5e4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -517,14 +517,27 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; struct hclge_dev *hdev = vport->back; + u16 max_rss_size; u8 i; vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit; - kinfo->num_tc = - min_t(u16, kinfo->num_tqps, hdev->tm_info.num_tc); - kinfo->rss_size - = min_t(u16, hdev->rss_size_max, - kinfo->num_tqps / kinfo->num_tc); + kinfo->num_tc = min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc); + max_rss_size = min_t(u16, hdev->rss_size_max, + vport->alloc_tqps / kinfo->num_tc); + + if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size && + kinfo->req_rss_size <= max_rss_size) { + dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n", + kinfo->rss_size, kinfo->req_rss_size); + kinfo->rss_size = kinfo->req_rss_size; + } else if (kinfo->rss_size > max_rss_size || + (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size)) { + dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n", + kinfo->rss_size, max_rss_size); + kinfo->rss_size = max_rss_size; + } + + kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size; vport->qs_offset = hdev->tm_info.num_tc * vport->vport_id; vport->dwrr = 100; /* 100 percent as init */ vport->alloc_rss_size = kinfo->rss_size; @@ -1334,3 +1347,20 @@ int hclge_tm_schd_init(struct hclge_dev *hdev) return hclge_tm_init_hw(hdev); } + +int hclge_tm_vport_map_update(struct hclge_dev *hdev) +{ + struct hclge_vport *vport = hdev->vport; + int ret; + + hclge_tm_vport_tc_info_update(vport); + + ret = hclge_vport_q_to_qs_map(hdev, vport); + if (ret) + return ret; + + if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) + return 0; + + return hclge_tm_bp_setup(hdev); +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index b6496a439304..898163c4d400 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -142,6 +142,7 @@ struct hclge_port_shapping_cmd { (HCLGE_TM_SHAP_##string##_LSH)) int hclge_tm_schd_init(struct hclge_dev *hdev); +int hclge_tm_vport_map_update(struct hclge_dev *hdev); int hclge_pause_setup_hw(struct hclge_dev *hdev); int hclge_tm_schd_mode_hw(struct hclge_dev *hdev); void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc); -- cgit v1.2.3 From 205a24ca2df10621a19081ad349920870759c0a6 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:11 +0800 Subject: net: hns3: adjust the use of alloc_tqps and num_tqps The alloc_tqps field of struct hclge_vport represents the total number of tqps allocated to the vport. The num_tqps of struct hnae3_knic_private_info indicates the total number of all enabled tqps, which needs to be distinguished during use. Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 55a456f1dd38..9506c5273010 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1123,7 +1123,7 @@ static int hclge_map_tqp_to_vport(struct hclge_dev *hdev, u16 i; kinfo = &nic->kinfo; - for (i = 0; i < kinfo->num_tqps; i++) { + for (i = 0; i < vport->alloc_tqps; i++) { struct hclge_tqp *q = container_of(kinfo->tqp[i], struct hclge_tqp, q); bool is_pf; @@ -5241,6 +5241,7 @@ static int hclge_set_loopback(struct hnae3_handle *handle, enum hnae3_loop loop_mode, bool en) { struct hclge_vport *vport = hclge_get_vport(handle); + struct hnae3_knic_private_info *kinfo; struct hclge_dev *hdev = vport->back; int i, ret; @@ -5259,7 +5260,8 @@ static int hclge_set_loopback(struct hnae3_handle *handle, break; } - for (i = 0; i < vport->alloc_tqps; i++) { + kinfo = &vport->nic.kinfo; + for (i = 0; i < kinfo->num_tqps; i++) { ret = hclge_tqp_enable(hdev, i, 0, en); if (ret) return ret; @@ -5271,11 +5273,13 @@ static int hclge_set_loopback(struct hnae3_handle *handle, static void hclge_reset_tqp_stats(struct hnae3_handle *handle) { struct hclge_vport *vport = hclge_get_vport(handle); + struct hnae3_knic_private_info *kinfo; struct hnae3_queue *queue; struct hclge_tqp *tqp; int i; - for (i = 0; i < vport->alloc_tqps; i++) { + kinfo = &vport->nic.kinfo; + for (i = 0; i < kinfo->num_tqps; i++) { queue = handle->kinfo.tqp[i]; tqp = container_of(queue, struct hclge_tqp, q); memset(&tqp->tqp_stats, 0, sizeof(tqp->tqp_stats)); -- cgit v1.2.3 From c3b9c50d1567aa12be4448fe85b09626eba2499c Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:12 +0800 Subject: net: hns3: fix wrong combined count returned by ethtool -l The current code returns the number of all queues that can be used and the number of queues that have been allocated, which is incorrect. What should be returned is the number of queues allocated for each enabled TC and the number of queues that can be allocated. This patch fixes it. Fixes: 482d2e9c1cc7 ("net: hns3: add support to query tqps number") Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 9506c5273010..450094cc4b28 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7510,18 +7510,17 @@ static u32 hclge_get_max_channels(struct hnae3_handle *handle) struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - return min_t(u32, hdev->rss_size_max * kinfo->num_tc, hdev->num_tqps); + return min_t(u32, hdev->rss_size_max, + vport->alloc_tqps / kinfo->num_tc); } static void hclge_get_channels(struct hnae3_handle *handle, struct ethtool_channels *ch) { - struct hclge_vport *vport = hclge_get_vport(handle); - ch->max_combined = hclge_get_max_channels(handle); ch->other_count = 1; ch->max_other = 1; - ch->combined_count = vport->alloc_tqps; + ch->combined_count = handle->kinfo.rss_size; } static void hclge_get_tqps_and_rss_info(struct hnae3_handle *handle, -- cgit v1.2.3 From af013903c5c5dc4a251e0ac49eaab9411293f9f9 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Fri, 18 Jan 2019 16:13:13 +0800 Subject: net: hns3: do reinitialization while ETS configuration changed When the ETS information is changed, the network device needs to be re-initialized, otherwise the information such as the receiving queue will be incorrect. Signed-off-by: Huazhong Tan Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 14 +------------- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 17 +++++++++++++++++ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 ++-- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 ++ 4 files changed, 22 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0bda9bd8ecc1..10cc86533885 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3728,7 +3728,6 @@ static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc) { struct hnae3_knic_private_info *kinfo = &handle->kinfo; struct net_device *ndev = kinfo->netdev; - bool if_running; int ret; if (tc > HNAE3_MAX_TC) @@ -3737,24 +3736,13 @@ static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc) if (!ndev) return -ENODEV; - if_running = netif_running(ndev); - - if (if_running) { - (void)hns3_nic_net_stop(ndev); - msleep(100); - } - ret = (kinfo->dcb_ops && kinfo->dcb_ops->map_update) ? kinfo->dcb_ops->map_update(handle) : -EOPNOTSUPP; if (ret) - goto err_out; + return ret; ret = hns3_nic_set_real_num_queue(ndev); -err_out: - if (if_running) - (void)hns3_nic_net_open(ndev); - return ret; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index f6323b2501dc..4ec0b9cd15ae 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -222,6 +222,16 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) if (ret) return ret; + if (map_changed) { + ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); + if (ret) + return ret; + + ret = hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT); + if (ret) + return ret; + } + hclge_tm_schd_info_update(hdev, num_tc); ret = hclge_ieee_ets_to_tm_info(hdev, ets); @@ -232,6 +242,13 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) ret = hclge_client_setup_tc(hdev); if (ret) return ret; + ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); + if (ret) + return ret; + + ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT); + if (ret) + return ret; } return hclge_tm_dwrr_cfg(hdev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 450094cc4b28..97683a75c95d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2401,8 +2401,8 @@ static void hclge_misc_irq_uninit(struct hclge_dev *hdev) hclge_free_vector(hdev, 0); } -static int hclge_notify_client(struct hclge_dev *hdev, - enum hnae3_reset_notify_type type) +int hclge_notify_client(struct hclge_dev *hdev, + enum hnae3_reset_notify_type type) { struct hnae3_client *client = hdev->nic_client; u16 i; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 6615b85a1c52..279ed2d83cb8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -878,4 +878,6 @@ void hclge_vport_stop(struct hclge_vport *vport); int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu); int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf); u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id); +int hclge_notify_client(struct hclge_dev *hdev, + enum hnae3_reset_notify_type type); #endif -- cgit v1.2.3 From 1f60949297ceb92f8dbf0571f5f502988bbb0273 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Fri, 18 Jan 2019 16:13:14 +0800 Subject: net: hns3: add HNAE3_RESTORE_CLIENT interface in enet module The HNAE3_INIT_CLIENT interface is also used when changing tc configuration, vlan/mac hardware table does not need to be restored when tc configuration changes. This patch adds a HNAE3_RESTORE_CLIENT interface to restore the vlan/mac hardware table when resetting. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 61 ++++++++++++---------- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 ++ .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 2 +- 4 files changed, 40 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 81d15854478d..d486748d5883 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -124,6 +124,7 @@ enum hnae3_reset_notify_type { HNAE3_DOWN_CLIENT, HNAE3_INIT_CLIENT, HNAE3_UNINIT_CLIENT, + HNAE3_RESTORE_CLIENT, }; enum hnae3_reset_type { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 10cc86533885..9dd8949381bc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4004,35 +4004,8 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle) { struct net_device *netdev = handle->kinfo.netdev; struct hns3_nic_priv *priv = netdev_priv(netdev); - bool vlan_filter_enable; int ret; - ret = hns3_init_mac_addr(netdev, false); - if (ret) - return ret; - - ret = hns3_recover_hw_addr(netdev); - if (ret) - return ret; - - ret = hns3_update_promisc_mode(netdev, handle->netdev_flags); - if (ret) - return ret; - - vlan_filter_enable = netdev->flags & IFF_PROMISC ? false : true; - hns3_enable_vlan_filter(netdev, vlan_filter_enable); - - /* Hardware table is only clear when pf resets */ - if (!(handle->flags & HNAE3_SUPPORT_VF)) { - ret = hns3_restore_vlan(netdev); - if (ret) - return ret; - } - - ret = hns3_restore_fd_rules(netdev); - if (ret) - return ret; - /* Carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); @@ -4070,6 +4043,37 @@ err_put_ring: return ret; } +static int hns3_reset_notify_restore_enet(struct hnae3_handle *handle) +{ + struct net_device *netdev = handle->kinfo.netdev; + bool vlan_filter_enable; + int ret; + + ret = hns3_init_mac_addr(netdev, false); + if (ret) + return ret; + + ret = hns3_recover_hw_addr(netdev); + if (ret) + return ret; + + ret = hns3_update_promisc_mode(netdev, handle->netdev_flags); + if (ret) + return ret; + + vlan_filter_enable = netdev->flags & IFF_PROMISC ? false : true; + hns3_enable_vlan_filter(netdev, vlan_filter_enable); + + /* Hardware table is only clear when pf resets */ + if (!(handle->flags & HNAE3_SUPPORT_VF)) { + ret = hns3_restore_vlan(netdev); + if (ret) + return ret; + } + + return hns3_restore_fd_rules(netdev); +} + static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle) { struct net_device *netdev = handle->kinfo.netdev; @@ -4125,6 +4129,9 @@ static int hns3_reset_notify(struct hnae3_handle *handle, case HNAE3_UNINIT_CLIENT: ret = hns3_reset_notify_uninit_enet(handle); break; + case HNAE3_RESTORE_CLIENT: + ret = hns3_reset_notify_restore_enet(handle); + break; default: break; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 97683a75c95d..00d7acb4d45a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2866,6 +2866,10 @@ static void hclge_reset(struct hclge_dev *hdev) if (ret) goto err_reset_lock; + ret = hclge_notify_client(hdev, HNAE3_RESTORE_CLIENT); + if (ret) + goto err_reset_lock; + hclge_clear_reset_cause(hdev); ret = hclge_reset_prepare_up(hdev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 82103d5fa815..bb9f45200ef5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1264,7 +1264,7 @@ static int hclgevf_reset_stack(struct hclgevf_dev *hdev) if (ret) return ret; - return 0; + return hclgevf_notify_client(hdev, HNAE3_RESTORE_CLIENT); } static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev) -- cgit v1.2.3 From 0c4335de196c23a28d9de8f5eb8b973673051ad9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 17 Jan 2019 03:13:12 +0000 Subject: virt_wifi: remove duplicated include from virt_wifi.c Remove duplicated include. Signed-off-by: YueHaibing Signed-off-by: Johannes Berg --- drivers/net/wireless/virt_wifi.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index 64b218699656..245d4d0af89b 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -14,11 +14,6 @@ #include #include -#include -#include -#include -#include - static struct wiphy *common_wiphy; struct virt_wifi_wiphy_priv { -- cgit v1.2.3 From e073f7caa26cc7f5423779b1a47f1689dd20bf17 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 17 Jan 2019 03:17:03 +0000 Subject: virt_wifi: remove set but not used variable 'w_priv' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/virt_wifi.c: In function 'virt_wifi_net_device_stop': drivers/net/wireless/virt_wifi.c:432:31: warning: variable 'w_priv' set but not used [-Wunused-but-set-variable] Signed-off-by: YueHaibing Signed-off-by: Johannes Berg --- drivers/net/wireless/virt_wifi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index 245d4d0af89b..9479b26b2d02 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -424,13 +424,11 @@ static int virt_wifi_net_device_open(struct net_device *dev) static int virt_wifi_net_device_stop(struct net_device *dev) { struct virt_wifi_netdev_priv *n_priv = netdev_priv(dev); - struct virt_wifi_wiphy_priv *w_priv; n_priv->is_up = false; if (!dev->ieee80211_ptr) return 0; - w_priv = wiphy_priv(dev->ieee80211_ptr->wiphy); virt_wifi_cancel_scan(dev->ieee80211_ptr->wiphy); virt_wifi_cancel_connect(dev); -- cgit v1.2.3 From 133bbb18ab1a2f5549435c5a3126413344ddbcb8 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Thu, 17 Jan 2019 20:08:53 -0500 Subject: virtio-net: per-queue RPS config On multiqueue network devices, RPS maps are configured independently for each receive queue through /sys/class/net/$DEV/queues/rx-*. On virtio-net currently all packets use the map from rx-0, because the real rx queue is not known at time of map lookup by get_rps_cpu. Call skb_record_rx_queue in the driver rx path to make lookup work. Recording the receive queue has ramifications beyond RPS, such as in sticky load balancing decisions for sockets (skb_tx_hash) and XPS. Reported-by: Mark Hlady Signed-off-by: Willem de Bruijn Acked-by: Jason Wang Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 023725086046..236ba5d5fb4b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1035,6 +1035,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, goto frame_err; } + skb_record_rx_queue(skb, vq2rxq(rq->vq)); skb->protocol = eth_type_trans(skb, dev); pr_debug("Receiving skb proto 0x%04x len %i type %i\n", ntohs(skb->protocol), skb->len, skb->pkt_type); -- cgit v1.2.3 From 186f21be865801f5381ee4ca4b906e0157fc9452 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Fri, 18 Jan 2019 16:15:59 +0000 Subject: dpaa2-eth: transform dpaa2_eth_queue_count into a macro Transform dpaa2_eth_queue_count into a macro to follow the the convention used by dpaa2_eth_fs_count and other functions. Signed-off-by: Ioana Ciornei Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h index 69c965de192b..308aae6bec48 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h @@ -405,6 +405,10 @@ static inline int dpaa2_eth_cmp_dpni_ver(struct dpaa2_eth_priv *priv, #define dpaa2_eth_fs_count(priv) \ ((priv)->dpni_attrs.fs_entries) +/* We have exactly one {Rx, Tx conf} queue per channel */ +#define dpaa2_eth_queue_count(priv) \ + ((priv)->num_channels) + enum dpaa2_eth_rx_dist { DPAA2_ETH_RX_DIST_HASH, DPAA2_ETH_RX_DIST_CLS @@ -447,12 +451,6 @@ static inline unsigned int dpaa2_eth_rx_head_room(struct dpaa2_eth_priv *priv) DPAA2_ETH_RX_HWA_SIZE; } -/* We have exactly one {Rx, Tx conf} queue per channel */ -static int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv) -{ - return priv->num_channels; -} - int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags); int dpaa2_eth_cls_key_size(void); int dpaa2_eth_cls_fld_off(int prot, int field); -- cgit v1.2.3 From 091a19ea6e34bf5ee52b46e265ad244b029d74d2 Mon Sep 17 00:00:00 2001 From: Ioana Radulescu Date: Fri, 18 Jan 2019 16:16:00 +0000 Subject: dpaa2-eth: add debugfs statistics Export detailed driver counters through debugfs. Statistics already available in ethtool are presented in a structured manner. Includes per-core, per-FQ and per-channel statistics. Also transition from module_fsl_mc_driver to explicit module_init/exit in order to create the debugfs directory besides registering the driver. Signed-off-by: Ioana Radulescu Signed-off-by: Ioana Ciornei Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/Makefile | 1 + .../ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c | 237 +++++++++++++++++++++ .../ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h | 31 +++ drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 30 ++- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 4 + 5 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c create mode 100644 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/Makefile b/drivers/net/ethernet/freescale/dpaa2/Makefile index 2f424e0a8225..d1e78cdd512f 100644 --- a/drivers/net/ethernet/freescale/dpaa2/Makefile +++ b/drivers/net/ethernet/freescale/dpaa2/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o obj-$(CONFIG_FSL_DPAA2_PTP_CLOCK) += fsl-dpaa2-ptp.o fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o +fsl-dpaa2-eth-${CONFIG_DEBUG_FS} += dpaa2-eth-debugfs.o fsl-dpaa2-ptp-objs := dpaa2-ptp.o dprtc.o # Needed by the tracing framework diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c new file mode 100644 index 000000000000..a027f4a9d0cc --- /dev/null +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2015 Freescale Semiconductor Inc. + * Copyright 2018-2019 NXP + */ +#include +#include +#include "dpaa2-eth.h" +#include "dpaa2-eth-debugfs.h" + +#define DPAA2_ETH_DBG_ROOT "dpaa2-eth" + +static struct dentry *dpaa2_dbg_root; + +static int dpaa2_dbg_cpu_show(struct seq_file *file, void *offset) +{ + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private; + struct rtnl_link_stats64 *stats; + struct dpaa2_eth_drv_stats *extras; + int i; + + seq_printf(file, "Per-CPU stats for %s\n", priv->net_dev->name); + seq_printf(file, "%s%16s%16s%16s%16s%16s%16s%16s%16s%16s\n", + "CPU", "Rx", "Rx Err", "Rx SG", "Tx", "Tx Err", "Tx conf", + "Tx SG", "Tx realloc", "Enq busy"); + + for_each_online_cpu(i) { + stats = per_cpu_ptr(priv->percpu_stats, i); + extras = per_cpu_ptr(priv->percpu_extras, i); + seq_printf(file, "%3d%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu\n", + i, + stats->rx_packets, + stats->rx_errors, + extras->rx_sg_frames, + stats->tx_packets, + stats->tx_errors, + extras->tx_conf_frames, + extras->tx_sg_frames, + extras->tx_reallocs, + extras->tx_portal_busy); + } + + return 0; +} + +static int dpaa2_dbg_cpu_open(struct inode *inode, struct file *file) +{ + int err; + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private; + + err = single_open(file, dpaa2_dbg_cpu_show, priv); + if (err < 0) + netdev_err(priv->net_dev, "single_open() failed\n"); + + return err; +} + +static const struct file_operations dpaa2_dbg_cpu_ops = { + .open = dpaa2_dbg_cpu_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static char *fq_type_to_str(struct dpaa2_eth_fq *fq) +{ + switch (fq->type) { + case DPAA2_RX_FQ: + return "Rx"; + case DPAA2_TX_CONF_FQ: + return "Tx conf"; + default: + return "N/A"; + } +} + +static int dpaa2_dbg_fqs_show(struct seq_file *file, void *offset) +{ + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private; + struct dpaa2_eth_fq *fq; + u32 fcnt, bcnt; + int i, err; + + seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name); + seq_printf(file, "%s%16s%16s%16s%16s\n", + "VFQID", "CPU", "Type", "Frames", "Pending frames"); + + for (i = 0; i < priv->num_fqs; i++) { + fq = &priv->fq[i]; + err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt); + if (err) + fcnt = 0; + + seq_printf(file, "%5d%16d%16s%16llu%16u\n", + fq->fqid, + fq->target_cpu, + fq_type_to_str(fq), + fq->stats.frames, + fcnt); + } + + return 0; +} + +static int dpaa2_dbg_fqs_open(struct inode *inode, struct file *file) +{ + int err; + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private; + + err = single_open(file, dpaa2_dbg_fqs_show, priv); + if (err < 0) + netdev_err(priv->net_dev, "single_open() failed\n"); + + return err; +} + +static const struct file_operations dpaa2_dbg_fq_ops = { + .open = dpaa2_dbg_fqs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int dpaa2_dbg_ch_show(struct seq_file *file, void *offset) +{ + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private; + struct dpaa2_eth_channel *ch; + int i; + + seq_printf(file, "Channel stats for %s:\n", priv->net_dev->name); + seq_printf(file, "%s%16s%16s%16s%16s\n", + "CHID", "CPU", "Deq busy", "CDANs", "Buf count"); + + for (i = 0; i < priv->num_channels; i++) { + ch = priv->channel[i]; + seq_printf(file, "%4d%16d%16llu%16llu%16d\n", + ch->ch_id, + ch->nctx.desired_cpu, + ch->stats.dequeue_portal_busy, + ch->stats.cdan, + ch->buf_count); + } + + return 0; +} + +static int dpaa2_dbg_ch_open(struct inode *inode, struct file *file) +{ + int err; + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private; + + err = single_open(file, dpaa2_dbg_ch_show, priv); + if (err < 0) + netdev_err(priv->net_dev, "single_open() failed\n"); + + return err; +} + +static const struct file_operations dpaa2_dbg_ch_ops = { + .open = dpaa2_dbg_ch_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void dpaa2_dbg_add(struct dpaa2_eth_priv *priv) +{ + if (!dpaa2_dbg_root) + return; + + /* Create a directory for the interface */ + priv->dbg.dir = debugfs_create_dir(priv->net_dev->name, + dpaa2_dbg_root); + if (!priv->dbg.dir) { + netdev_err(priv->net_dev, "debugfs_create_dir() failed\n"); + return; + } + + /* per-cpu stats file */ + priv->dbg.cpu_stats = debugfs_create_file("cpu_stats", 0444, + priv->dbg.dir, priv, + &dpaa2_dbg_cpu_ops); + if (!priv->dbg.cpu_stats) { + netdev_err(priv->net_dev, "debugfs_create_file() failed\n"); + goto err_cpu_stats; + } + + /* per-fq stats file */ + priv->dbg.fq_stats = debugfs_create_file("fq_stats", 0444, + priv->dbg.dir, priv, + &dpaa2_dbg_fq_ops); + if (!priv->dbg.fq_stats) { + netdev_err(priv->net_dev, "debugfs_create_file() failed\n"); + goto err_fq_stats; + } + + /* per-fq stats file */ + priv->dbg.ch_stats = debugfs_create_file("ch_stats", 0444, + priv->dbg.dir, priv, + &dpaa2_dbg_ch_ops); + if (!priv->dbg.fq_stats) { + netdev_err(priv->net_dev, "debugfs_create_file() failed\n"); + goto err_ch_stats; + } + + return; + +err_ch_stats: + debugfs_remove(priv->dbg.fq_stats); +err_fq_stats: + debugfs_remove(priv->dbg.cpu_stats); +err_cpu_stats: + debugfs_remove(priv->dbg.dir); +} + +void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv) +{ + debugfs_remove(priv->dbg.fq_stats); + debugfs_remove(priv->dbg.ch_stats); + debugfs_remove(priv->dbg.cpu_stats); + debugfs_remove(priv->dbg.dir); +} + +void dpaa2_eth_dbg_init(void) +{ + dpaa2_dbg_root = debugfs_create_dir(DPAA2_ETH_DBG_ROOT, NULL); + if (!dpaa2_dbg_root) { + pr_err("DPAA2-ETH: debugfs create failed\n"); + return; + } + + pr_debug("DPAA2-ETH: debugfs created\n"); +} + +void dpaa2_eth_dbg_exit(void) +{ + debugfs_remove(dpaa2_dbg_root); +} diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h new file mode 100644 index 000000000000..4f63de997a26 --- /dev/null +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* Copyright 2015 Freescale Semiconductor Inc. + * Copyright 2018-2019 NXP + */ +#ifndef DPAA2_ETH_DEBUGFS_H +#define DPAA2_ETH_DEBUGFS_H + +#include + +struct dpaa2_eth_priv; + +struct dpaa2_debugfs { + struct dentry *dir; + struct dentry *fq_stats; + struct dentry *ch_stats; + struct dentry *cpu_stats; +}; + +#ifdef CONFIG_DEBUG_FS +void dpaa2_eth_dbg_init(void); +void dpaa2_eth_dbg_exit(void); +void dpaa2_dbg_add(struct dpaa2_eth_priv *priv); +void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv); +#else +static inline void dpaa2_eth_dbg_init(void) {} +static inline void dpaa2_eth_dbg_exit(void) {} +static inline void dpaa2_dbg_add(struct dpaa2_eth_priv *priv) {} +static inline void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv) {} +#endif /* CONFIG_DEBUG_FS */ + +#endif /* DPAA2_ETH_DEBUGFS_H */ diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index ecf92189b0a4..04925c731f0b 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -3083,6 +3083,10 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) goto err_netdev_reg; } +#ifdef CONFIG_DEBUG_FS + dpaa2_dbg_add(priv); +#endif + dev_info(dev, "Probed interface %s\n", net_dev->name); return 0; @@ -3126,6 +3130,9 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) net_dev = dev_get_drvdata(dev); priv = netdev_priv(net_dev); +#ifdef CONFIG_DEBUG_FS + dpaa2_dbg_remove(priv); +#endif unregister_netdev(net_dev); if (priv->do_link_poll) @@ -3170,4 +3177,25 @@ static struct fsl_mc_driver dpaa2_eth_driver = { .match_id_table = dpaa2_eth_match_id_table }; -module_fsl_mc_driver(dpaa2_eth_driver); +static int __init dpaa2_eth_driver_init(void) +{ + int err; + + dpaa2_eth_dbg_init(); + err = fsl_mc_driver_register(&dpaa2_eth_driver); + if (err) { + dpaa2_eth_dbg_exit(); + return err; + } + + return 0; +} + +static void __exit dpaa2_eth_driver_exit(void) +{ + dpaa2_eth_dbg_exit(); + fsl_mc_driver_unregister(&dpaa2_eth_driver); +} + +module_init(dpaa2_eth_driver_init); +module_exit(dpaa2_eth_driver_exit); diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h index 308aae6bec48..31fe486ec25f 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h @@ -16,6 +16,7 @@ #include "dpni-cmd.h" #include "dpaa2-eth-trace.h" +#include "dpaa2-eth-debugfs.h" #define DPAA2_WRIOP_VERSION(x, y, z) ((x) << 10 | (y) << 5 | (z) << 0) @@ -365,6 +366,9 @@ struct dpaa2_eth_priv { struct dpaa2_eth_cls_rule *cls_rules; u8 rx_cls_enabled; struct bpf_prog *xdp_prog; +#ifdef CONFIG_DEBUG_FS + struct dpaa2_debugfs dbg; +#endif }; #define DPAA2_RXH_SUPPORTED (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO \ -- cgit v1.2.3 From fa1115c6a249cd3fac5b00aba1be38533e501005 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Fri, 18 Jan 2019 02:06:49 +0000 Subject: net: usb: rtl8150: remove set but not used variable 'rx_stat' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/usb/rtl8150.c: In function 'read_bulk_callback': drivers/net/usb/rtl8150.c:391:6: warning: variable 'rx_stat' set but not used [-Wunused-but-set-variable] Signed-off-by: Yue Haibing Signed-off-by: David S. Miller --- drivers/net/usb/rtl8150.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 80373a9171dd..3f145e4c6c08 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -388,7 +388,6 @@ static void read_bulk_callback(struct urb *urb) unsigned pkt_len, res; struct sk_buff *skb; struct net_device *netdev; - u16 rx_stat; int status = urb->status; int result; unsigned long flags; @@ -424,7 +423,6 @@ static void read_bulk_callback(struct urb *urb) goto goon; res = urb->actual_length; - rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4)); pkt_len = res - 4; skb_put(dev->rx_skb, pkt_len); -- cgit v1.2.3 From 65ea97d1760152e344e3e442fddcff822e3c750b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 18 Jan 2019 11:05:11 +0800 Subject: isdn: remove unneeded semicolon remove unneeded semicolon Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/isdn/hisax/netjet.c | 6 +++--- drivers/isdn/hisax/q931.c | 2 +- drivers/isdn/hisax/st5481.h | 2 +- drivers/isdn/isdnloop/isdnloop.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index e932a152c405..d7b011c8d692 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -332,7 +332,7 @@ static int make_raw_data_56k(struct BCState *bcs) { bitcnt = 0; } val >>= 1; - }; + } fcs = PPP_INITFCS; for (i = 0; i < bcs->tx_skb->len; i++) { val = bcs->tx_skb->data[i]; @@ -415,7 +415,7 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt) { else { // it's 56K mask = 0x7f; bits = 7; - }; + } for (i = 0; i < cnt; i++) { val = bcs->channel ? ((*p >> 8) & 0xff) : (*p & 0xff); p++; @@ -623,7 +623,7 @@ void netjet_fill_dma(struct BCState *bcs) else { // it's 56k if (make_raw_data_56k(bcs)) return; - }; + } if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "tiger fill_dma2: c%d %4lx", bcs->channel, bcs->Flag); diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c index 298c8dba0321..6b8c3fbe3965 100644 --- a/drivers/isdn/hisax/q931.c +++ b/drivers/isdn/hisax/q931.c @@ -598,7 +598,7 @@ prcalling(char *dest, u_char *p) dp += prbits(dp, *++p, 8, 8); *dp++ = '\n'; l--; - }; + } p++; dp += sprintf(dp, " number digits "); diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h index 8cd2d8277426..b421b86ca7da 100644 --- a/drivers/isdn/hisax/st5481.h +++ b/drivers/isdn/hisax/st5481.h @@ -512,7 +512,7 @@ static inline const char *ST5481_CMD_string(int evt) case ST5481_CMD_AR10: return "AR10"; case ST5481_CMD_ARL: return "ARL"; case ST5481_CMD_PDN: return "PDN"; - }; + } sprintf(s, "0x%x", evt); return s; diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index a4597e96c916..f4253d468ae1 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -72,7 +72,7 @@ isdnloop_bchan_send(isdnloop_card *card, int ch) printk(KERN_WARNING "isdnloop: no rcard, skb dropped\n"); dev_kfree_skb(skb); - }; + } cmd.command = ISDN_STAT_BSENT; cmd.parm.length = len; card->interface.statcallb(&cmd); -- cgit v1.2.3 From 3ff752c00288db8f214037ca6280c635d850bab4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 22:02:40 +0100 Subject: r8169: remove rtl_get_events This helper is used only once, so remove it. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index abb94c543aa2..b2e30e3025b6 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1278,11 +1278,6 @@ static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr) RTL_R32(tp, EFUSEAR) & EFUSEAR_DATA_MASK : ~0; } -static u16 rtl_get_events(struct rtl8169_private *tp) -{ - return RTL_R16(tp, IntrStatus); -} - static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) { RTL_W16(tp, IntrStatus, bits); @@ -6409,7 +6404,7 @@ release_descriptor: static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) { struct rtl8169_private *tp = dev_instance; - u16 status = rtl_get_events(tp); + u16 status = RTL_R16(tp, IntrStatus); u16 irq_mask = RTL_R16(tp, IntrMask); if (status == 0xffff || !(status & irq_mask)) -- cgit v1.2.3 From 445f1be2a59a9eb8991732035fbda6e7e5820241 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 22:03:13 +0100 Subject: r8169: remove unneeded call in pcierr rtl8169_hw_reset() is called as part of the reset routine which is scheduled in the line after. So we can remove the call to rtl8169_hw_reset() here. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index b2e30e3025b6..fd3c6a5487fd 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -6196,8 +6196,6 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) dev->features &= ~NETIF_F_HIGHDMA; } - rtl8169_hw_reset(tp); - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } -- cgit v1.2.3 From 5c41e78fe2a57e04e3080de75ec45d724d492622 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 22:03:49 +0100 Subject: r8169: initialize task workqueue only once It's sufficient to initialize the workqueue once, therefore remove the additional initialization whenever rtl_open() is called. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index fd3c6a5487fd..c4d53bc6a50d 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -6630,10 +6630,6 @@ static int rtl_open(struct net_device *dev) if (retval < 0) goto err_free_rx_1; - INIT_WORK(&tp->wk.work, rtl_task); - - smp_mb(); - rtl_request_firmware(tp); retval = pci_request_irq(pdev, 0, rtl8169_interrupt, NULL, tp, @@ -7293,6 +7289,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->saved_wolopts = __rtl8169_get_wol(tp); mutex_init(&tp->wk.mutex); + INIT_WORK(&tp->wk.work, rtl_task); u64_stats_init(&tp->rx_stats.syncp); u64_stats_init(&tp->tx_stats.syncp); -- cgit v1.2.3 From c259b7f491ee04d2ee12f8c82e1ae272884440c1 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 22:05:14 +0100 Subject: r8169: improve rtl_pcie_state_l2l3_enable All calls to this function have the enable parameter set to false. So we can replace the function with a disable-only version. v2: - fixed copy & paste error Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index c4d53bc6a50d..df3d2633fabb 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -4691,18 +4691,10 @@ static void rtl_enable_clock_request(struct rtl8169_private *tp) PCI_EXP_LNKCTL_CLKREQ_EN); } -static void rtl_pcie_state_l2l3_enable(struct rtl8169_private *tp, bool enable) +static void rtl_pcie_state_l2l3_disable(struct rtl8169_private *tp) { - u8 data; - - data = RTL_R8(tp, Config3); - - if (enable) - data |= Rdy_to_L23; - else - data &= ~Rdy_to_L23; - - RTL_W8(tp, Config3, data); + /* work around an issue when PCI reset occurs during L2/L3 state */ + RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Rdy_to_L23); } static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable) @@ -5023,7 +5015,7 @@ static void rtl_hw_start_8411(struct rtl8169_private *tp) }; rtl_hw_start_8168f(tp); - rtl_pcie_state_l2l3_enable(tp, false); + rtl_pcie_state_l2l3_disable(tp); rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); @@ -5057,7 +5049,7 @@ static void rtl_hw_start_8168g(struct rtl8169_private *tp) rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC); rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC); - rtl_pcie_state_l2l3_enable(tp, false); + rtl_pcie_state_l2l3_disable(tp); } static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) @@ -5163,7 +5155,7 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC); - rtl_pcie_state_l2l3_enable(tp, false); + rtl_pcie_state_l2l3_disable(tp); rtl_writephy(tp, 0x1f, 0x0c42); rg_saw_cnt = (rtl_readphy(tp, 0x13) & 0x3fff); @@ -5240,7 +5232,7 @@ static void rtl_hw_start_8168ep(struct rtl8169_private *tp) RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN); - rtl_pcie_state_l2l3_enable(tp, false); + rtl_pcie_state_l2l3_disable(tp); } static void rtl_hw_start_8168ep_1(struct rtl8169_private *tp) @@ -5511,7 +5503,7 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp) rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); - rtl_pcie_state_l2l3_enable(tp, false); + rtl_pcie_state_l2l3_disable(tp); } static void rtl_hw_start_8105e_2(struct rtl8169_private *tp) @@ -5546,7 +5538,7 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp) rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); rtl_w0w1_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC); - rtl_pcie_state_l2l3_enable(tp, false); + rtl_pcie_state_l2l3_disable(tp); } static void rtl_hw_start_8106(struct rtl8169_private *tp) @@ -5560,7 +5552,7 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp) RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET); RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN); - rtl_pcie_state_l2l3_enable(tp, false); + rtl_pcie_state_l2l3_disable(tp); rtl_hw_aspm_clkreq_enable(tp, true); } -- cgit v1.2.3 From df320ed7b3e46c93a57eb77c71228415bcd5b8b8 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 22:05:48 +0100 Subject: r8169: add helpers for locking / unlocking the config registers Add helpers for locking / unlocking the config registers. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index df3d2633fabb..a3df61d81adf 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -745,6 +745,16 @@ static void rtl_unlock_work(struct rtl8169_private *tp) mutex_unlock(&tp->wk.mutex); } +static void rtl_lock_config_regs(struct rtl8169_private *tp) +{ + RTL_W8(tp, Cfg9346, Cfg9346_Lock); +} + +static void rtl_unlock_config_regs(struct rtl8169_private *tp) +{ + RTL_W8(tp, Cfg9346, Cfg9346_Unlock); +} + static void rtl_tx_performance_tweak(struct rtl8169_private *tp, u16 force) { pcie_capability_clear_and_set_word(tp->pci_dev, PCI_EXP_DEVCTL, @@ -1426,7 +1436,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) }; u8 options; - RTL_W8(tp, Cfg9346, Cfg9346_Unlock); + rtl_unlock_config_regs(tp); switch (tp->mac_version) { case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38: @@ -1474,7 +1484,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) break; } - RTL_W8(tp, Cfg9346, Cfg9346_Lock); + rtl_lock_config_regs(tp); device_set_wakeup_enable(tp_to_dev(tp), wolopts); } @@ -4006,7 +4016,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) { rtl_lock_work(tp); - RTL_W8(tp, Cfg9346, Cfg9346_Unlock); + rtl_unlock_config_regs(tp); RTL_W32(tp, MAC4, addr[4] | addr[5] << 8); RTL_R32(tp, MAC4); @@ -4017,7 +4027,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) if (tp->mac_version == RTL_GIGA_MAC_VER_34) rtl_rar_exgmac_set(tp, addr); - RTL_W8(tp, Cfg9346, Cfg9346_Lock); + rtl_lock_config_regs(tp); rtl_unlock_work(tp); } @@ -4229,18 +4239,18 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) static void rtl_hw_jumbo_enable(struct rtl8169_private *tp) { if (tp->jumbo_ops.enable) { - RTL_W8(tp, Cfg9346, Cfg9346_Unlock); + rtl_unlock_config_regs(tp); tp->jumbo_ops.enable(tp); - RTL_W8(tp, Cfg9346, Cfg9346_Lock); + rtl_lock_config_regs(tp); } } static void rtl_hw_jumbo_disable(struct rtl8169_private *tp) { if (tp->jumbo_ops.disable) { - RTL_W8(tp, Cfg9346, Cfg9346_Unlock); + rtl_unlock_config_regs(tp); tp->jumbo_ops.disable(tp); - RTL_W8(tp, Cfg9346, Cfg9346_Lock); + rtl_lock_config_regs(tp); } } @@ -4561,13 +4571,13 @@ static void rtl_set_rx_mode(struct net_device *dev) static void rtl_hw_start(struct rtl8169_private *tp) { - RTL_W8(tp, Cfg9346, Cfg9346_Unlock); + rtl_unlock_config_regs(tp); tp->hw_start(tp); rtl_set_rx_max_size(tp); rtl_set_rx_tx_desc_registers(tp); - RTL_W8(tp, Cfg9346, Cfg9346_Lock); + rtl_lock_config_regs(tp); /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ RTL_R8(tp, IntrMask); @@ -6976,9 +6986,9 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) unsigned int flags; if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - RTL_W8(tp, Cfg9346, Cfg9346_Unlock); + rtl_unlock_config_regs(tp); RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable); - RTL_W8(tp, Cfg9346, Cfg9346_Lock); + rtl_lock_config_regs(tp); flags = PCI_IRQ_LEGACY; } else { flags = PCI_IRQ_ALL_TYPES; -- cgit v1.2.3 From 58ba566ccbae0ec629ab9e36006d1b79765fe252 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 22:06:25 +0100 Subject: r8169: reset chip synchronously in __rtl8169_resume Triggering an asynchronous reset is problematic for the following reasons, therefore reset the chip synchronously. - The reset routine resets registers and parameters behind our back what may collide with code executed after triggering the reset. - __rtl8169_resume() is called as part of pm_runtime_get_sync() and callers expect that the chip is fully resumed afterwards. In context of this driver triggering an asynchonous reset should be considered an emergency procedure. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index a3df61d81adf..c7a89d2a8bfe 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -6787,9 +6787,8 @@ static void __rtl8169_resume(struct net_device *dev) rtl_lock_work(tp); napi_enable(&tp->napi); set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); + rtl_reset_work(tp); rtl_unlock_work(tp); - - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } static int rtl8169_resume(struct device *device) -- cgit v1.2.3 From 703732f0058bd48842aa882217c26a3b3ed30216 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 22:07:05 +0100 Subject: r8169: replace mii_bus member with phy_device member in struct rtl8169_private Accessing the phy_device indirectly via the netdevice causes few issues: - Accessing the phy_device when it's not attached may cause a NPE. - If we have to access the phy_device when it's not attached we have to use mdiobus_get_phy() to get a reference to the phy_device. Therefore store a phy_device reference in struct rtl8169_private directly. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 56 ++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index c7a89d2a8bfe..07984f7e3e21 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -639,6 +639,7 @@ struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; struct net_device *dev; + struct phy_device *phydev; struct napi_struct napi; u32 msg_enable; u16 mac_version; @@ -679,7 +680,6 @@ struct rtl8169_private { } wk; unsigned supports_gmii:1; - struct mii_bus *mii_bus; dma_addr_t counters_phys_addr; struct rtl8169_counters *counters; struct rtl8169_tc_offsets tc_offset; @@ -1318,7 +1318,7 @@ static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) static void rtl_link_chg_patch(struct rtl8169_private *tp) { struct net_device *dev = tp->dev; - struct phy_device *phydev = dev->phydev; + struct phy_device *phydev = tp->phydev; if (!netif_running(dev)) return; @@ -3999,17 +3999,17 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) } /* We may have called phy_speed_down before */ - phy_speed_up(dev->phydev); + phy_speed_up(tp->phydev); - genphy_soft_reset(dev->phydev); + genphy_soft_reset(tp->phydev); /* It was reported that several chips end up with 10MBit/Half on a * 1GBit link after resuming from S3. For whatever reason the PHY on * these chips doesn't properly start a renegotiation when soft-reset. * Explicitly requesting a renegotiation fixes this. */ - if (dev->phydev->autoneg == AUTONEG_ENABLE) - phy_restart_aneg(dev->phydev); + if (tp->phydev->autoneg == AUTONEG_ENABLE) + phy_restart_aneg(tp->phydev); } static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) @@ -4054,10 +4054,12 @@ static int rtl_set_mac_address(struct net_device *dev, void *p) static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { + struct rtl8169_private *tp = netdev_priv(dev); + if (!netif_running(dev)) return -ENODEV; - return phy_mii_ioctl(dev->phydev, ifr, cmd); + return phy_mii_ioctl(tp->phydev, ifr, cmd); } static void rtl_init_mdio_ops(struct rtl8169_private *tp) @@ -4106,15 +4108,10 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) static bool rtl_wol_pll_power_down(struct rtl8169_private *tp) { - struct phy_device *phydev; - if (!__rtl8169_get_wol(tp)) return false; - /* phydev may not be attached to netdevice */ - phydev = mdiobus_get_phy(tp->mii_bus, 0); - - phy_speed_down(phydev, false); + phy_speed_down(tp->phydev, false); rtl_wol_suspend_quirk(tp); return true; @@ -4183,7 +4180,7 @@ static void r8168_pll_power_up(struct rtl8169_private *tp) break; } - phy_resume(tp->dev->phydev); + phy_resume(tp->phydev); /* give MAC/PHY some time to resume */ msleep(20); } @@ -6415,8 +6412,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) goto out; } - if (status & LinkChg && tp->dev->phydev) - phy_mac_interrupt(tp->dev->phydev); + if (status & LinkChg) + phy_mac_interrupt(tp->phydev); if (unlikely(status & RxFIFOOver && tp->mac_version == RTL_GIGA_MAC_VER_11)) { @@ -6507,12 +6504,12 @@ static void r8169_phylink_handler(struct net_device *ndev) } if (net_ratelimit()) - phy_print_status(ndev->phydev); + phy_print_status(tp->phydev); } static int r8169_phy_connect(struct rtl8169_private *tp) { - struct phy_device *phydev = mdiobus_get_phy(tp->mii_bus, 0); + struct phy_device *phydev = tp->phydev; phy_interface_t phy_mode; int ret; @@ -6539,7 +6536,7 @@ static void rtl8169_down(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); - phy_stop(dev->phydev); + phy_stop(tp->phydev); napi_disable(&tp->napi); netif_stop_queue(dev); @@ -6581,7 +6578,7 @@ static int rtl8169_close(struct net_device *dev) cancel_work_sync(&tp->wk.work); - phy_disconnect(dev->phydev); + phy_disconnect(tp->phydev); pci_free_irq(pdev, 0, tp); @@ -6658,7 +6655,7 @@ static int rtl_open(struct net_device *dev) if (!rtl8169_init_counter_offsets(tp)) netif_warn(tp, hw, dev, "counter reset/update failed\n"); - phy_start(dev->phydev); + phy_start(tp->phydev); netif_start_queue(dev); rtl_unlock_work(tp); @@ -6747,7 +6744,7 @@ static void rtl8169_net_suspend(struct net_device *dev) if (!netif_running(dev)) return; - phy_stop(dev->phydev); + phy_stop(tp->phydev); netif_device_detach(dev); rtl_lock_work(tp); @@ -6782,7 +6779,7 @@ static void __rtl8169_resume(struct net_device *dev) rtl_pll_power_up(tp); rtl8169_init_phy(dev, tp); - phy_start(tp->dev->phydev); + phy_start(tp->phydev); rtl_lock_work(tp); napi_enable(&tp->napi); @@ -6925,7 +6922,7 @@ static void rtl_remove_one(struct pci_dev *pdev) netif_napi_del(&tp->napi); unregister_netdev(dev); - mdiobus_unregister(tp->mii_bus); + mdiobus_unregister(tp->phydev->mdio.bus); rtl_release_firmware(tp); @@ -7032,7 +7029,6 @@ static int r8169_mdio_write_reg(struct mii_bus *mii_bus, int phyaddr, static int r8169_mdio_register(struct rtl8169_private *tp) { struct pci_dev *pdev = tp->pci_dev; - struct phy_device *phydev; struct mii_bus *new_bus; int ret; @@ -7054,16 +7050,14 @@ static int r8169_mdio_register(struct rtl8169_private *tp) if (ret) return ret; - phydev = mdiobus_get_phy(new_bus, 0); - if (!phydev) { + tp->phydev = mdiobus_get_phy(new_bus, 0); + if (!tp->phydev) { mdiobus_unregister(new_bus); return -ENODEV; } /* PHY will be woken up in rtl_open() */ - phy_suspend(phydev); - - tp->mii_bus = new_bus; + phy_suspend(tp->phydev); return 0; } @@ -7397,7 +7391,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; err_mdio_unregister: - mdiobus_unregister(tp->mii_bus); + mdiobus_unregister(tp->phydev->mdio.bus); return rc; } -- cgit v1.2.3 From b779daea4aee27d3838a9052e2c3364e28ebaa87 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 22:07:34 +0100 Subject: r8169: factor out getting ether_clk rtl_init_one() is complex enough, so we better factor out getting the ether_clk. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 53 ++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 07984f7e3e21..e790a4116f1e 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -7155,6 +7155,32 @@ static void rtl_disable_clk(void *data) clk_disable_unprepare(data); } +static int rtl_get_ether_clk(struct rtl8169_private *tp) +{ + struct device *d = tp_to_dev(tp); + struct clk *clk; + int rc; + + clk = devm_clk_get(d, "ether_clk"); + if (IS_ERR(clk)) { + rc = PTR_ERR(clk); + if (rc == -ENOENT) + /* clk-core allows NULL (for suspend / resume) */ + rc = 0; + else if (rc != -EPROBE_DEFER) + dev_err(d, "failed to get clk: %d\n", rc); + } else { + tp->clk = clk; + rc = clk_prepare_enable(clk); + if (rc) + dev_err(d, "failed to enable clk: %d\n", rc); + else + rc = devm_add_action_or_reset(d, rtl_disable_clk, clk); + } + + return rc; +} + static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; @@ -7176,30 +7202,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->supports_gmii = cfg->has_gmii; /* Get the *optional* external "ether_clk" used on some boards */ - tp->clk = devm_clk_get(&pdev->dev, "ether_clk"); - if (IS_ERR(tp->clk)) { - rc = PTR_ERR(tp->clk); - if (rc == -ENOENT) { - /* clk-core allows NULL (for suspend / resume) */ - tp->clk = NULL; - } else if (rc == -EPROBE_DEFER) { - return rc; - } else { - dev_err(&pdev->dev, "failed to get clk: %d\n", rc); - return rc; - } - } else { - rc = clk_prepare_enable(tp->clk); - if (rc) { - dev_err(&pdev->dev, "failed to enable clk: %d\n", rc); - return rc; - } - - rc = devm_add_action_or_reset(&pdev->dev, rtl_disable_clk, - tp->clk); - if (rc) - return rc; - } + rc = rtl_get_ether_clk(tp); + if (rc) + return rc; /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pcim_enable_device(pdev); -- cgit v1.2.3 From afba3e10822a0bf08ca9cabf81c761a7d46ea70f Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:39 +0000 Subject: mlxsw: reg: Add fields to RITR - Router Interface Table Register Add fields relevant for Spectrum-2 Loopback IPinIP router interface creation. Add additional Loopback RIF protocol value - Generic, used for creation of an explicit underlay RIF, and also add a field named underlay_rif used for specifying the underlay RIF of a tunnel. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 16 +++++++++++++--- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 9b48dffc9f63..fb75d7ad0716 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -5666,6 +5666,8 @@ enum mlxsw_reg_ritr_loopback_protocol { MLXSW_REG_RITR_LOOPBACK_PROTOCOL_IPIP_IPV4, /* IPinIP IPv6 underlay Unicast */ MLXSW_REG_RITR_LOOPBACK_PROTOCOL_IPIP_IPV6, + /* IPinIP generic - used for Spectrum-2 underlay RIF */ + MLXSW_REG_RITR_LOOPBACK_GENERIC, }; /* reg_ritr_loopback_protocol @@ -5706,6 +5708,13 @@ MLXSW_ITEM32(reg, ritr, loopback_ipip_options, 0x10, 20, 4); */ MLXSW_ITEM32(reg, ritr, loopback_ipip_uvr, 0x10, 0, 16); +/* reg_ritr_loopback_ipip_underlay_rif + * Underlay ingress router interface. + * Reserved for Spectrum. + * Access: RW + */ +MLXSW_ITEM32(reg, ritr, loopback_ipip_underlay_rif, 0x14, 0, 16); + /* reg_ritr_loopback_ipip_usip* * Encapsulation Underlay source IP. * Access: RW @@ -5821,11 +5830,12 @@ static inline void mlxsw_reg_ritr_loopback_ipip_common_pack(char *payload, enum mlxsw_reg_ritr_loopback_ipip_type ipip_type, enum mlxsw_reg_ritr_loopback_ipip_options options, - u16 uvr_id, u32 gre_key) + u16 uvr_id, u16 underlay_rif, u32 gre_key) { mlxsw_reg_ritr_loopback_ipip_type_set(payload, ipip_type); mlxsw_reg_ritr_loopback_ipip_options_set(payload, options); mlxsw_reg_ritr_loopback_ipip_uvr_set(payload, uvr_id); + mlxsw_reg_ritr_loopback_ipip_underlay_rif_set(payload, underlay_rif); mlxsw_reg_ritr_loopback_ipip_gre_key_set(payload, gre_key); } @@ -5833,12 +5843,12 @@ static inline void mlxsw_reg_ritr_loopback_ipip4_pack(char *payload, enum mlxsw_reg_ritr_loopback_ipip_type ipip_type, enum mlxsw_reg_ritr_loopback_ipip_options options, - u16 uvr_id, u32 usip, u32 gre_key) + u16 uvr_id, u16 underlay_rif, u32 usip, u32 gre_key) { mlxsw_reg_ritr_loopback_protocol_set(payload, MLXSW_REG_RITR_LOOPBACK_PROTOCOL_IPIP_IPV4); mlxsw_reg_ritr_loopback_ipip_common_pack(payload, ipip_type, options, - uvr_id, gre_key); + uvr_id, underlay_rif, gre_key); mlxsw_reg_ritr_loopback_ipip_usip4_set(payload, usip); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 042341c7f6b9..727d35947cbe 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -1453,7 +1453,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, rif->rif_index, rif->vr_id, rif->dev->mtu); mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt, MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET, - ul_vr->id, saddr4, lb_cf.okey); + ul_vr->id, 0, saddr4, lb_cf.okey); break; case MLXSW_SP_L3_PROTO_IPV6: -- cgit v1.2.3 From c9417498a6fe7090f9b93834bc3296154bed98bf Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 20 Jan 2019 06:50:39 +0000 Subject: mlxsw: reg: Add underlay egress RIF field in RTDP register In Spectrum-2 we need to specify the underlay egress router interface when performing IP-in-IP and NVE packet decapsulation in the underlay router. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index fb75d7ad0716..5f8066ab7d40 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -7210,6 +7210,13 @@ MLXSW_ITEM32(reg, rtdp, type, 0x00, 28, 4); */ MLXSW_ITEM32(reg, rtdp, tunnel_index, 0x00, 0, 24); +/* reg_rtdp_egress_router_interface + * Underlay egress router interface. + * Valid range is from 0 to cap_max_router_interfaces - 1 + * Access: RW + */ +MLXSW_ITEM32(reg, rtdp, egress_router_interface, 0x40, 0, 16); + /* IPinIP */ /* reg_rtdp_ipip_irif -- cgit v1.2.3 From 99974468b9b608bc0fbac8db8b0e1859aa62b256 Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:40 +0000 Subject: mlxsw: spectrum_router: Split RIF ops array for Spectrum-2 support Split RIF ops array for Spectrum-1 and Spectrum-2 callbacks in order to support different sets of operations for loopback RIF handling, as underlying implementation differs between the ASICs. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 41 +++++++++++++++++----- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 727d35947cbe..094037539300 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -7424,7 +7424,7 @@ mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif, } static int -mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) +mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) { struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); @@ -7449,7 +7449,7 @@ err_loopback_op: return err; } -static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif) +static void mlxsw_sp1_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif) { struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; @@ -7462,19 +7462,44 @@ static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif) mlxsw_sp_vr_put(mlxsw_sp, ul_vr); } -static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops = { +static const struct mlxsw_sp_rif_ops mlxsw_sp1_rif_ipip_lb_ops = { .type = MLXSW_SP_RIF_TYPE_IPIP_LB, .rif_size = sizeof(struct mlxsw_sp_rif_ipip_lb), .setup = mlxsw_sp_rif_ipip_lb_setup, - .configure = mlxsw_sp_rif_ipip_lb_configure, - .deconfigure = mlxsw_sp_rif_ipip_lb_deconfigure, + .configure = mlxsw_sp1_rif_ipip_lb_configure, + .deconfigure = mlxsw_sp1_rif_ipip_lb_deconfigure, }; -static const struct mlxsw_sp_rif_ops *mlxsw_sp_rif_ops_arr[] = { +const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[] = { [MLXSW_SP_RIF_TYPE_SUBPORT] = &mlxsw_sp_rif_subport_ops, [MLXSW_SP_RIF_TYPE_VLAN] = &mlxsw_sp_rif_vlan_emu_ops, [MLXSW_SP_RIF_TYPE_FID] = &mlxsw_sp_rif_fid_ops, - [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp_rif_ipip_lb_ops, + [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp1_rif_ipip_lb_ops, +}; + +static int +mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) +{ + return 0; +} + +static void mlxsw_sp2_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif) +{ +} + +static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_ipip_lb_ops = { + .type = MLXSW_SP_RIF_TYPE_IPIP_LB, + .rif_size = sizeof(struct mlxsw_sp_rif_ipip_lb), + .setup = mlxsw_sp_rif_ipip_lb_setup, + .configure = mlxsw_sp2_rif_ipip_lb_configure, + .deconfigure = mlxsw_sp2_rif_ipip_lb_deconfigure, +}; + +const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[] = { + [MLXSW_SP_RIF_TYPE_SUBPORT] = &mlxsw_sp_rif_subport_ops, + [MLXSW_SP_RIF_TYPE_VLAN] = &mlxsw_sp_rif_vlan_emu_ops, + [MLXSW_SP_RIF_TYPE_FID] = &mlxsw_sp_rif_fid_ops, + [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp2_rif_ipip_lb_ops, }; static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp) @@ -7487,7 +7512,7 @@ static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp) if (!mlxsw_sp->router->rifs) return -ENOMEM; - mlxsw_sp->router->rif_ops_arr = mlxsw_sp_rif_ops_arr; + mlxsw_sp->router->rif_ops_arr = mlxsw_sp1_rif_ops_arr; return 0; } -- cgit v1.2.3 From 1f5b23033937f5a4f232b0373ff4a4c5302a6f0c Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:41 +0000 Subject: mlxsw: spectrum: Set RIF ops per ASIC type Set RIF ops array as member of mlxsw_sp in order to control which RIF operations callbacks are called per ASIC type. This is needed to control per ASIC handling of loopback RIF configurations. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 6 ++++++ drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 4 +--- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 32519c93df17..a88169738b4a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4094,6 +4094,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->acl_tcam_ops = &mlxsw_sp1_acl_tcam_ops; mlxsw_sp->nve_ops_arr = mlxsw_sp1_nve_ops_arr; mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask; + mlxsw_sp->rif_ops_arr = mlxsw_sp1_rif_ops_arr; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info); } @@ -4110,6 +4111,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops; mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr; mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask; + mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index a1c32a81b011..1fa5c81b209f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -75,6 +75,11 @@ enum mlxsw_sp_rif_type { MLXSW_SP_RIF_TYPE_MAX, }; +struct mlxsw_sp_rif_ops; + +extern const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[]; +extern const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[]; + enum mlxsw_sp_fid_type { MLXSW_SP_FID_TYPE_8021Q, MLXSW_SP_FID_TYPE_8021D, @@ -161,6 +166,7 @@ struct mlxsw_sp { const struct mlxsw_sp_mr_tcam_ops *mr_tcam_ops; const struct mlxsw_sp_acl_tcam_ops *acl_tcam_ops; const struct mlxsw_sp_nve_ops **nve_ops_arr; + const struct mlxsw_sp_rif_ops **rif_ops_arr; }; static inline struct mlxsw_sp_upper * diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 094037539300..139767769ace 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -6284,7 +6284,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, int i, err; type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev); - ops = mlxsw_sp->router->rif_ops_arr[type]; + ops = mlxsw_sp->rif_ops_arr[type]; vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN, extack); if (IS_ERR(vr)) @@ -7512,8 +7512,6 @@ static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp) if (!mlxsw_sp->router->rifs) return -ENOMEM; - mlxsw_sp->router->rif_ops_arr = mlxsw_sp1_rif_ops_arr; - return 0; } -- cgit v1.2.3 From 3c747500daedb037a9c9ccec61270c3aaf5d678e Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:42 +0000 Subject: mlxsw: spectrum_router: Adjust loopback RIF configuration In Spectrum-2, the underlay routing table is pointed by an underlay router interface in contrary to Spectrum where only an underlay virtual router should be set. That makes the underlay virtual router field in RITR reserved for Spectrum-2. Change loopback RIF creation function to support the new underlay RIF field, however leave this field reserved for Spectrum-1 updates. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 139767769ace..c55bd5af0341 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -1437,8 +1437,8 @@ mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp *mlxsw_sp, } static int -mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, - struct mlxsw_sp_vr *ul_vr, bool enable) +mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id, + u16 ul_rif_id, bool enable) { struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config; struct mlxsw_sp_rif *rif = &lb_rif->common; @@ -1453,7 +1453,7 @@ mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, rif->rif_index, rif->vr_id, rif->dev->mtu); mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt, MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET, - ul_vr->id, 0, saddr4, lb_cf.okey); + ul_vr_id, ul_rif_id, saddr4, lb_cf.okey); break; case MLXSW_SP_L3_PROTO_IPV6: @@ -1475,7 +1475,7 @@ static int mlxsw_sp_netdevice_ipip_ol_update_mtu(struct mlxsw_sp *mlxsw_sp, if (ipip_entry) { lb_rif = ipip_entry->ol_lb; ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id]; - err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true); + err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, true); if (err) goto out; lb_rif->common.mtu = ol_dev->mtu; @@ -7436,7 +7436,7 @@ mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) if (IS_ERR(ul_vr)) return PTR_ERR(ul_vr); - err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true); + err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, true); if (err) goto err_loopback_op; @@ -7456,7 +7456,7 @@ static void mlxsw_sp1_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif) struct mlxsw_sp_vr *ul_vr; ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id]; - mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, false); + mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, false); --ul_vr->rif_count; mlxsw_sp_vr_put(mlxsw_sp, ul_vr); -- cgit v1.2.3 From a04563e4892c585d63870f33e4650a98e09b243f Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:46 +0000 Subject: mlxsw: spectrum_router: Mark RIF index as taken before creation The presence of an allocated RIF in mlxsw_sp->router->rifs[rif_index] marks that rif_index as taken. Set the marking of a taken RIF to happen before calling ops->create in order to allow creation of a GRE underlay RIF, which may be allocated and created as part of an overlay RIF creation. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index c55bd5af0341..1cac38365503 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -6303,6 +6303,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, goto err_rif_alloc; } dev_hold(rif->dev); + mlxsw_sp->router->rifs[rif_index] = rif; rif->mlxsw_sp = mlxsw_sp; rif->ops = ops; @@ -6329,7 +6330,6 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, } mlxsw_sp_rif_counters_alloc(rif); - mlxsw_sp->router->rifs[rif_index] = rif; return rif; @@ -6341,6 +6341,7 @@ err_configure: if (fid) mlxsw_sp_fid_put(fid); err_fid_get: + mlxsw_sp->router->rifs[rif_index] = NULL; dev_put(rif->dev); kfree(rif); err_rif_alloc: @@ -6361,7 +6362,6 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif); vr = &mlxsw_sp->router->vrs[rif->vr_id]; - mlxsw_sp->router->rifs[rif->rif_index] = NULL; mlxsw_sp_rif_counters_free(rif); for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++) mlxsw_sp_mr_rif_del(vr->mr_table[i], rif); @@ -6369,6 +6369,7 @@ static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) if (fid) /* Loopback RIFs are not associated with a FID. */ mlxsw_sp_fid_put(fid); + mlxsw_sp->router->rifs[rif->rif_index] = NULL; dev_put(rif->dev); kfree(rif); vr->rif_count--; -- cgit v1.2.3 From 25f844ddd2b49da4e0e792de8e804359b05b90cc Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:47 +0000 Subject: mlxsw: spectrum_router: Add underlay RIF ID support Spectrum-2 GRE tunnels underlay should be given not only the virtual router information for an encapsulated packet lookup, but also an underlay RIF object which belongs to a virtual router. Therefore add ul_rif_id field in struct mlxsw_sp_rif_ipip_lb, to be used later in Spectrum-2 underlay RIF implementation. This field complements ul_vr_id field, already present and defined as reserved for Spectrum-2. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 1cac38365503..c9dbef5ed6e3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -120,6 +120,7 @@ struct mlxsw_sp_rif_ipip_lb { struct mlxsw_sp_rif common; struct mlxsw_sp_rif_ipip_lb_config lb_config; u16 ul_vr_id; /* Reserved for Spectrum-2. */ + u16 ul_rif_id; /* Reserved for Spectrum. */ }; struct mlxsw_sp_rif_params_ipip_lb { @@ -1468,14 +1469,13 @@ static int mlxsw_sp_netdevice_ipip_ol_update_mtu(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_ipip_entry *ipip_entry; struct mlxsw_sp_rif_ipip_lb *lb_rif; - struct mlxsw_sp_vr *ul_vr; int err = 0; ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev); if (ipip_entry) { lb_rif = ipip_entry->ol_lb; - ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id]; - err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, true); + err = mlxsw_sp_rif_ipip_lb_op(lb_rif, lb_rif->ul_vr_id, + lb_rif->ul_rif_id, true); if (err) goto out; lb_rif->common.mtu = ol_dev->mtu; @@ -7442,6 +7442,7 @@ mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) goto err_loopback_op; lb_rif->ul_vr_id = ul_vr->id; + lb_rif->ul_rif_id = 0; ++ul_vr->rif_count; return 0; -- cgit v1.2.3 From 33c04afe4d985d58d16c4af727bceb91715d03da Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:48 +0000 Subject: mlxsw: spectrum_router: Change mlxsw_sp_ipip_lb_ul_vr_id() For the sake of Spectrum-2 GRE support, as ul_vr_id field is reserved for Spectrum-2, Change mlxsw_sp_ipip_lb_ul_vr_id() implementation not to use the reserved field. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index c9dbef5ed6e3..2cfbba810527 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -6251,7 +6251,14 @@ u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif) u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif) { - return lb_rif->ul_vr_id; + u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(lb_rif->common.dev); + struct mlxsw_sp_vr *ul_vr; + + ul_vr = mlxsw_sp_vr_get(lb_rif->common.mlxsw_sp, ul_tb_id, NULL); + if (WARN_ON(IS_ERR(ul_vr))) + return 0; + + return ul_vr->id; } int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif) -- cgit v1.2.3 From 73b8f493c8863711989174193cbd67b34ac1a350 Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:49 +0000 Subject: mlxsw: spectrum_router: Support RIF without device Spectrum-2 underlay RIF is merely an auxiliary RIF that points to the virtual router used for encapsulated packets lookup. It exists only when its overlay RIF exists but may be shared with other overlay RIFs. Hence it is undesired to mark any device as related to it. Therefore allow usage of NULL device when allocating RIF. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c index 41e607a14846..49933818c6f5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c @@ -220,7 +220,7 @@ start_again: for (; i < rif_count; i++) { struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i); - if (!rif) + if (!rif || !mlxsw_sp_rif_dev(rif)) continue; err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif, counters_enabled); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 2cfbba810527..4316afc2c043 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -80,7 +80,7 @@ struct mlxsw_sp_router { struct mlxsw_sp_rif { struct list_head nexthop_list; struct list_head neigh_list; - struct net_device *dev; + struct net_device *dev; /* NULL for underlay RIF */ struct mlxsw_sp_fid *fid; unsigned char addr[ETH_ALEN]; int mtu; @@ -6224,10 +6224,12 @@ static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index, INIT_LIST_HEAD(&rif->nexthop_list); INIT_LIST_HEAD(&rif->neigh_list); - ether_addr_copy(rif->addr, l3_dev->dev_addr); - rif->mtu = l3_dev->mtu; + if (l3_dev) { + ether_addr_copy(rif->addr, l3_dev->dev_addr); + rif->mtu = l3_dev->mtu; + rif->dev = l3_dev; + } rif->vr_id = vr_id; - rif->dev = l3_dev; rif->rif_index = rif_index; return rif; @@ -6758,7 +6760,7 @@ static int mlxsw_sp_router_port_check_rif_addr(struct mlxsw_sp *mlxsw_sp, for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) { rif = mlxsw_sp->router->rifs[i]; - if (rif && rif->dev != dev && + if (rif && rif->dev && rif->dev != dev && !ether_addr_equal_masked(rif->dev->dev_addr, dev_addr, mlxsw_sp->mac_mask)) { NL_SET_ERR_MSG_MOD(extack, "All router interface MAC addresses must have the same prefix"); -- cgit v1.2.3 From 311596f554b739546fc390dac5e4cd0916d9fcc6 Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:50 +0000 Subject: mlxsw: spectrum_router: Update tunnel decap properties Spectrum-2 requires to specify the egress RIF when setting tunnel decap properties. Add a method for accessing the underlay RIF index and then use it when setting decap properties. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c | 2 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 5 +++++ drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h | 1 + 3 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c index 00db26c96bf5..6400cd644b7a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c @@ -145,6 +145,7 @@ mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_ipip_entry *ipip_entry) { u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); + u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb); char rtdp_pl[MLXSW_REG_RTDP_LEN]; struct ip_tunnel_parm parms; unsigned int type_check; @@ -157,6 +158,7 @@ mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp, ikey = mlxsw_sp_ipip_parms4_ikey(parms); mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_IPIP, tunnel_index); + mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_id); type_check = has_ikey ? MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE_KEY : diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 4316afc2c043..bee9aeb0a07e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -6263,6 +6263,11 @@ u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif) return ul_vr->id; } +u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif) +{ + return lb_rif->ul_rif_id; +} + int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif) { return rif->dev->ifindex; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 3dbafdeaab2b..cc1de91e8217 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -29,6 +29,7 @@ struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp, u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif); u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *rif); u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *rif); +u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif); u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev); int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif); const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif); -- cgit v1.2.3 From a5040a9059ed6b9ecb77514092eb62726708412c Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Sun, 20 Jan 2019 06:50:51 +0000 Subject: mlxsw: spectrum_router: Add GRE tunnel support for Spectrum-2 Spectrum-2 GRE tunnel implementation requires a specific underlay RIF that points to the virtual router used for forwarding the encapsulated packet. Add Spectrum-2 specific loopback router interface creation methods which may create or reuse the dedicated underlay RIF. Signed-off-by: Nir Dotan Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index bee9aeb0a07e..0949404a28e5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -441,6 +441,8 @@ struct mlxsw_sp_vr { struct mlxsw_sp_fib *fib4; struct mlxsw_sp_fib *fib6; struct mlxsw_sp_mr_table *mr_table[MLXSW_SP_L3_PROTO_MAX]; + struct mlxsw_sp_rif *ul_rif; + refcount_t ul_rif_refcnt; }; static const struct rhashtable_params mlxsw_sp_fib_ht_params; @@ -7493,14 +7495,142 @@ const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[] = { [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp1_rif_ipip_lb_ops, }; +static int +mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable) +{ + struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp; + char ritr_pl[MLXSW_REG_RITR_LEN]; + + mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF, + ul_rif->rif_index, ul_rif->vr_id, IP_MAX_MTU); + mlxsw_reg_ritr_loopback_protocol_set(ritr_pl, + MLXSW_REG_RITR_LOOPBACK_GENERIC); + + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); +} + +static struct mlxsw_sp_rif * +mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_rif *ul_rif; + u16 rif_index; + int err; + + err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces"); + return ERR_PTR(err); + } + + ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL); + if (!ul_rif) + return ERR_PTR(-ENOMEM); + + mlxsw_sp->router->rifs[rif_index] = ul_rif; + ul_rif->mlxsw_sp = mlxsw_sp; + err = mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, true); + if (err) + goto ul_rif_op_err; + + return ul_rif; + +ul_rif_op_err: + mlxsw_sp->router->rifs[rif_index] = NULL; + kfree(ul_rif); + return ERR_PTR(err); +} + +static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif) +{ + struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp; + + mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false); + mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL; + kfree(ul_rif); +} + +static struct mlxsw_sp_rif * +mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, + struct netlink_ext_ack *extack) +{ + struct mlxsw_sp_vr *vr; + int err; + + vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, extack); + if (IS_ERR(vr)) + return ERR_CAST(vr); + + if (refcount_inc_not_zero(&vr->ul_rif_refcnt)) + return vr->ul_rif; + + vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack); + if (IS_ERR(vr->ul_rif)) { + err = PTR_ERR(vr->ul_rif); + goto err_ul_rif_create; + } + + vr->rif_count++; + refcount_set(&vr->ul_rif_refcnt, 1); + + return vr->ul_rif; + +err_ul_rif_create: + mlxsw_sp_vr_put(mlxsw_sp, vr); + return ERR_PTR(err); +} + +static void mlxsw_sp_ul_rif_put(struct mlxsw_sp_rif *ul_rif) +{ + struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp; + struct mlxsw_sp_vr *vr; + + vr = &mlxsw_sp->router->vrs[ul_rif->vr_id]; + + if (!refcount_dec_and_test(&vr->ul_rif_refcnt)) + return; + + vr->rif_count--; + mlxsw_sp_ul_rif_destroy(ul_rif); + mlxsw_sp_vr_put(mlxsw_sp, vr); +} + static int mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) { + struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); + u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev); + struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; + struct mlxsw_sp_rif *ul_rif; + int err; + + ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL); + if (IS_ERR(ul_rif)) + return PTR_ERR(ul_rif); + + err = mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, ul_rif->rif_index, true); + if (err) + goto err_loopback_op; + + lb_rif->ul_vr_id = 0; + lb_rif->ul_rif_id = ul_rif->rif_index; + return 0; + +err_loopback_op: + mlxsw_sp_ul_rif_put(ul_rif); + return err; } static void mlxsw_sp2_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif) { + struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif); + struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; + struct mlxsw_sp_rif *ul_rif; + + ul_rif = mlxsw_sp_rif_by_index(mlxsw_sp, lb_rif->ul_rif_id); + mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, lb_rif->ul_rif_id, false); + mlxsw_sp_ul_rif_put(ul_rif); } static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_ipip_lb_ops = { -- cgit v1.2.3 From f832898dff55f243081697b6e5773f7318c8a344 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 19 Jan 2019 16:00:26 +0100 Subject: mt76: do not report out-of-range rx nss Take into account device rx stream in mt76x02_mac_process_rate in order to not report wrong number of rx spatial stream to mac80211. The issue has been reported on mt76x0 device which is 1x1:1 however the hw sometimes reports rx nss equal to 2 Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 68d01e136fa0..ce9bb702045f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -476,7 +476,9 @@ out: } static int -mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate) +mt76x02_mac_process_rate(struct mt76x02_dev *dev, + struct mt76_rx_status *status, + u16 rate) { u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate); @@ -508,11 +510,15 @@ mt76x02_mac_process_rate(struct mt76_rx_status *status, u16 rate) status->encoding = RX_ENC_HT; status->rate_idx = idx; break; - case MT_PHY_TYPE_VHT: + case MT_PHY_TYPE_VHT: { + u8 n_rxstream = dev->mt76.chainmask & 0xf; + status->encoding = RX_ENC_VHT; status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx); - status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1; + status->nss = min_t(u8, n_rxstream, + FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1); break; + } default: return -EINVAL; } @@ -656,7 +662,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, status->tid = FIELD_GET(MT_RXWI_TID, tid_sn); status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn); - return mt76x02_mac_process_rate(status, rate); + return mt76x02_mac_process_rate(dev, status, rate); } void mt76x02_mac_poll_tx_status(struct mt76x02_dev *dev, bool irq) -- cgit v1.2.3 From 5c0a1001c8beecc29c2364171f3a1080e864a672 Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Wed, 16 Jan 2019 18:01:15 +0530 Subject: Bluetooth: hci_qca: Add helper to set device address This patch add qca_set_bdaddr() to set the device address for latest Qualcomm Bluetooth chipset wcn3990 and above. Signed-off-by: Balakrishna Godavarthi Reviewed-by: Matthias Kaehlcke Tested-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqca.c | 19 +++++++++++++++++++ drivers/bluetooth/btqca.h | 8 +++++++- drivers/bluetooth/hci_qca.c | 5 ++++- 3 files changed, 30 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index ec9e03a6b778..612268574fc7 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -391,6 +391,25 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, } EXPORT_SYMBOL_GPL(qca_uart_setup); +int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) +{ + struct sk_buff *skb; + int err; + + skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6, bdaddr, + HCI_EV_VENDOR, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "QCA Change address cmd failed (%d)", err); + return err; + } + + kfree_skb(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(qca_set_bdaddr); + MODULE_AUTHOR("Ben Young Tae Kim "); MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 0c01f375fe83..c72c56ea7480 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h @@ -20,6 +20,7 @@ #define EDL_PATCH_CMD_OPCODE (0xFC00) #define EDL_NVM_ACCESS_OPCODE (0xFC0B) +#define EDL_WRITE_BD_ADDR_OPCODE (0xFC14) #define EDL_PATCH_CMD_LEN (1) #define EDL_PATCH_VER_REQ_CMD (0x19) #define EDL_PATCH_TLV_REQ_CMD (0x1E) @@ -140,7 +141,7 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr); int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, enum qca_btsoc_type soc_type, u32 soc_ver); int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version); - +int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); #else static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) @@ -159,4 +160,9 @@ static inline int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) return -EOPNOTSUPP; } +static inline int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) +{ + return -EOPNOTSUPP; +} + #endif diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index f036c8f98ea3..53ac5ade532b 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1241,7 +1241,10 @@ static int qca_setup(struct hci_uart *hu) } /* Setup bdaddr */ - hu->hdev->set_bdaddr = qca_set_bdaddr_rome; + if (qcadev->btsoc_type == QCA_WCN3990) + hu->hdev->set_bdaddr = qca_set_bdaddr; + else + hu->hdev->set_bdaddr = qca_set_bdaddr_rome; return ret; } -- cgit v1.2.3 From 10004f813152646deeeb1e61a521b7ca026aa837 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 11 Jan 2019 21:56:56 +0100 Subject: Bluetooth: btmrvl: improve printk messages Use dev_* variants to print messages in drivers. Signed-off-by: Stefan Agner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_sdio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index fb3d03928460..6f9a1735039d 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -62,13 +62,14 @@ static const struct of_device_id btmrvl_sdio_of_match_table[] = { static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv) { struct btmrvl_sdio_card *card = priv; + struct device *dev = &card->func->dev; struct btmrvl_plt_wake_cfg *cfg = card->plt_wake_cfg; - pr_info("%s: wake by bt\n", __func__); + dev_info(dev, "wake by bt\n"); cfg->wake_by_bt = true; disable_irq_nosync(irq); - pm_wakeup_event(&card->func->dev, 0); + pm_wakeup_event(dev, 0); pm_system_wakeup(); return IRQ_HANDLED; @@ -87,7 +88,7 @@ static int btmrvl_sdio_probe_of(struct device *dev, if (!dev->of_node || !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) { - pr_err("sdio platform data not available\n"); + dev_err(dev, "sdio platform data not available\n"); return -1; } -- cgit v1.2.3 From 37c589ec289bbf5c3a506c9da259986bd63c40e9 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 11 Jan 2019 21:56:57 +0100 Subject: Bluetooth: btmrvl: lower log level of informational message The platform specific wake-up interrupt is optional. Don't print an error message in case it is missing, merely inform the user in this case. Signed-off-by: Stefan Agner Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 6f9a1735039d..8ff4c31e0e48 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -88,7 +88,7 @@ static int btmrvl_sdio_probe_of(struct device *dev, if (!dev->of_node || !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) { - dev_err(dev, "sdio platform data not available\n"); + dev_info(dev, "sdio device tree data not available\n"); return -1; } -- cgit v1.2.3 From 1dc2d785156cbdc80806c32e8d2c7c735d0b4721 Mon Sep 17 00:00:00 2001 From: Myungho Jung Date: Tue, 22 Jan 2019 00:33:26 -0800 Subject: Bluetooth: hci_uart: Check if socket buffer is ERR_PTR in h4_recv_buf() h4_recv_buf() callers store the return value to socket buffer and recursively pass the buffer to h4_recv_buf() without protection. So, ERR_PTR returned from h4_recv_buf() can be dereferenced, if called again before setting the socket buffer to NULL from previous error. Check if skb is ERR_PTR in h4_recv_buf(). Reported-by: syzbot+017a32f149406df32703@syzkaller.appspotmail.com Signed-off-by: Myungho Jung Signed-off-by: Marcel Holtmann --- drivers/bluetooth/h4_recv.h | 4 ++++ drivers/bluetooth/hci_h4.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/h4_recv.h b/drivers/bluetooth/h4_recv.h index b432651f8236..307d82166f48 100644 --- a/drivers/bluetooth/h4_recv.h +++ b/drivers/bluetooth/h4_recv.h @@ -60,6 +60,10 @@ static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev, const struct h4_recv_pkt *pkts, int pkts_count) { + /* Check for error from previous call */ + if (IS_ERR(skb)) + skb = NULL; + while (count) { int i, len; diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c index fb97a3bf069b..5d97d77627c1 100644 --- a/drivers/bluetooth/hci_h4.c +++ b/drivers/bluetooth/hci_h4.c @@ -174,6 +174,10 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb, struct hci_uart *hu = hci_get_drvdata(hdev); u8 alignment = hu->alignment ? hu->alignment : 1; + /* Check for error from previous call */ + if (IS_ERR(skb)) + skb = NULL; + while (count) { int i, len; -- cgit v1.2.3 From 8c57983bf7a7987f957830614b1645bd6943f5af Mon Sep 17 00:00:00 2001 From: Hemantkumar Suthar Date: Wed, 9 Jan 2019 15:03:57 +0000 Subject: Bluetooth: btmrvl: add support for sd8977 chipset This patch adds support for 8977 chipset to mwifiex with SDIO interface. Register offsets and supported feature flags are updated. Firmware image used will be mrvl/sd8977_uapsta.bin. Signed-off-by: Hemantkumar Suthar Signed-off-by: Rakesh Parmar Signed-off-by: Cathy Luo Signed-off-by: Ganapathi Bhat Signed-off-by: Marcel Holtmann --- drivers/bluetooth/Kconfig | 4 ++-- drivers/bluetooth/btmrvl_sdio.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 845b0314ce3a..7b2e76e7f22f 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -336,7 +336,7 @@ config BT_MRVL The core driver to support Marvell Bluetooth devices. This driver is required if you want to support - Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8997. + Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897/8977/8997. Say Y here to compile Marvell Bluetooth driver into the kernel or say M to compile it as module. @@ -350,7 +350,7 @@ config BT_MRVL_SDIO The driver for Marvell Bluetooth chipsets with SDIO interface. This driver is required if you want to use Marvell Bluetooth - devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8997 + devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897/SD8977/SD8997 chipsets are supported. Say Y here to compile support for Marvell BT-over-SDIO driver diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 8ff4c31e0e48..047b75ce1deb 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -212,6 +212,29 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = { .fw_dump_end = 0xea, }; +static const struct btmrvl_sdio_card_reg btmrvl_reg_8977 = { + .cfg = 0x00, + .host_int_mask = 0x08, + .host_intstatus = 0x0c, + .card_status = 0x5c, + .sq_read_base_addr_a0 = 0xf8, + .sq_read_base_addr_a1 = 0xf9, + .card_revision = 0xc8, + .card_fw_status0 = 0xe8, + .card_fw_status1 = 0xe9, + .card_rx_len = 0xea, + .card_rx_unit = 0xeb, + .io_port_0 = 0xe4, + .io_port_1 = 0xe5, + .io_port_2 = 0xe6, + .int_read_to_clear = true, + .host_int_rsr = 0x04, + .card_misc_cfg = 0xD8, + .fw_dump_ctrl = 0xf0, + .fw_dump_start = 0xf1, + .fw_dump_end = 0xf8, +}; + static const struct btmrvl_sdio_card_reg btmrvl_reg_8997 = { .cfg = 0x00, .host_int_mask = 0x08, @@ -280,6 +303,15 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { .supports_fw_dump = true, }; +static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = { + .helper = NULL, + .firmware = "mrvl/sd8977_uapsta.bin", + .reg = &btmrvl_reg_8977, + .support_pscan_win_report = true, + .sd_blksz_fw_dl = 256, + .supports_fw_dump = true, +}; + static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = { .helper = NULL, .firmware = "mrvl/sd8997_uapsta.bin", @@ -308,6 +340,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { /* Marvell SD8897 Bluetooth device */ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E), .driver_data = (unsigned long)&btmrvl_sdio_sd8897 }, + /* Marvell SD8977 Bluetooth device */ + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9146), + .driver_data = (unsigned long)&btmrvl_sdio_sd8977 }, /* Marvell SD8997 Bluetooth device */ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9142), .driver_data = (unsigned long)&btmrvl_sdio_sd8997 }, @@ -1761,4 +1796,5 @@ MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); +MODULE_FIRMWARE("mrvl/sd8977_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin"); -- cgit v1.2.3 From 099791da67691eb8f1c29f70deb7403503d9403b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 3 Jan 2019 13:32:27 +0100 Subject: Bluetooth: btmrvl: Drop unused GPIO includes I can't see that these drivers use the old GPIO inlcudes in any way, drop and . Signed-off-by: Linus Walleij Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_drv.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index f0454541e5fd..fb7729779166 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -24,11 +24,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include -- cgit v1.2.3 From f3fef2b6e1cc802fdf3e2dd543447a8ce15568a7 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Tue, 18 Dec 2018 13:45:14 +0000 Subject: i40e: Remove umem from VSI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As current implementation of netdev already contains and provides umems for us, we no longer have the need to contain these structures in i40e_vsi. Refactor the code to operate on netdev-provided umems. Signed-off-by: Jan Sokolowski Acked-by: Björn Töpel Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 10 +-- drivers/net/ethernet/intel/i40e/i40e_xsk.c | 110 +++++------------------------ 2 files changed, 21 insertions(+), 99 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 8de9085bba9e..7f41fd422ee1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "i40e_type.h" #include "i40e_prototype.h" #include "i40e_client.h" @@ -787,11 +788,6 @@ struct i40e_vsi { /* VSI specific handlers */ irqreturn_t (*irq_handler)(int irq, void *data); - - /* AF_XDP zero-copy */ - struct xdp_umem **xsk_umems; - u16 num_xsk_umems_used; - u16 num_xsk_umems; } ____cacheline_internodealigned_in_smp; struct i40e_netdev_priv { @@ -1104,10 +1100,10 @@ static inline struct xdp_umem *i40e_xsk_umem(struct i40e_ring *ring) if (ring_is_xdp(ring)) qid -= ring->vsi->alloc_queue_pairs; - if (!ring->vsi->xsk_umems || !ring->vsi->xsk_umems[qid] || !xdp_on) + if (!xdp_on) return NULL; - return ring->vsi->xsk_umems[qid]; + return xdp_get_umem_from_qid(ring->vsi->netdev, qid); } int i40e_create_queue_channel(struct i40e_vsi *vsi, struct i40e_channel *ch); diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index 870cf654e436..96d849460d9b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -9,69 +9,6 @@ #include "i40e_txrx_common.h" #include "i40e_xsk.h" -/** - * i40e_alloc_xsk_umems - Allocate an array to store per ring UMEMs - * @vsi: Current VSI - * - * Returns 0 on success, <0 on failure - **/ -static int i40e_alloc_xsk_umems(struct i40e_vsi *vsi) -{ - if (vsi->xsk_umems) - return 0; - - vsi->num_xsk_umems_used = 0; - vsi->num_xsk_umems = vsi->alloc_queue_pairs; - vsi->xsk_umems = kcalloc(vsi->num_xsk_umems, sizeof(*vsi->xsk_umems), - GFP_KERNEL); - if (!vsi->xsk_umems) { - vsi->num_xsk_umems = 0; - return -ENOMEM; - } - - return 0; -} - -/** - * i40e_add_xsk_umem - Store a UMEM for a certain ring/qid - * @vsi: Current VSI - * @umem: UMEM to store - * @qid: Ring/qid to associate with the UMEM - * - * Returns 0 on success, <0 on failure - **/ -static int i40e_add_xsk_umem(struct i40e_vsi *vsi, struct xdp_umem *umem, - u16 qid) -{ - int err; - - err = i40e_alloc_xsk_umems(vsi); - if (err) - return err; - - vsi->xsk_umems[qid] = umem; - vsi->num_xsk_umems_used++; - - return 0; -} - -/** - * i40e_remove_xsk_umem - Remove a UMEM for a certain ring/qid - * @vsi: Current VSI - * @qid: Ring/qid associated with the UMEM - **/ -static void i40e_remove_xsk_umem(struct i40e_vsi *vsi, u16 qid) -{ - vsi->xsk_umems[qid] = NULL; - vsi->num_xsk_umems_used--; - - if (vsi->num_xsk_umems == 0) { - kfree(vsi->xsk_umems); - vsi->xsk_umems = NULL; - vsi->num_xsk_umems = 0; - } -} - /** * i40e_xsk_umem_dma_map - DMA maps all UMEM memory for the netdev * @vsi: Current VSI @@ -140,6 +77,7 @@ static void i40e_xsk_umem_dma_unmap(struct i40e_vsi *vsi, struct xdp_umem *umem) static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem, u16 qid) { + struct net_device *netdev = vsi->netdev; struct xdp_umem_fq_reuse *reuseq; bool if_running; int err; @@ -150,12 +88,9 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem, if (qid >= vsi->num_queue_pairs) return -EINVAL; - if (vsi->xsk_umems) { - if (qid >= vsi->num_xsk_umems) - return -EINVAL; - if (vsi->xsk_umems[qid]) - return -EBUSY; - } + if (qid >= netdev->real_num_rx_queues || + qid >= netdev->real_num_tx_queues) + return -EINVAL; reuseq = xsk_reuseq_prepare(vsi->rx_rings[0]->count); if (!reuseq) @@ -173,13 +108,7 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem, err = i40e_queue_pair_disable(vsi, qid); if (err) return err; - } - - err = i40e_add_xsk_umem(vsi, umem, qid); - if (err) - return err; - if (if_running) { err = i40e_queue_pair_enable(vsi, qid); if (err) return err; @@ -197,11 +126,13 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem, **/ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid) { + struct net_device *netdev = vsi->netdev; + struct xdp_umem *umem; bool if_running; int err; - if (!vsi->xsk_umems || qid >= vsi->num_xsk_umems || - !vsi->xsk_umems[qid]) + umem = xdp_get_umem_from_qid(netdev, qid); + if (!umem) return -EINVAL; if_running = netif_running(vsi->netdev) && i40e_enabled_xdp_vsi(vsi); @@ -212,8 +143,7 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid) return err; } - i40e_xsk_umem_dma_unmap(vsi, vsi->xsk_umems[qid]); - i40e_remove_xsk_umem(vsi, qid); + i40e_xsk_umem_dma_unmap(vsi, umem); if (if_running) { err = i40e_queue_pair_enable(vsi, qid); @@ -237,20 +167,18 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid) int i40e_xsk_umem_query(struct i40e_vsi *vsi, struct xdp_umem **umem, u16 qid) { + struct net_device *netdev = vsi->netdev; + struct xdp_umem *queried_umem; + if (vsi->type != I40E_VSI_MAIN) return -EINVAL; - if (qid >= vsi->num_queue_pairs) - return -EINVAL; + queried_umem = xdp_get_umem_from_qid(netdev, qid); - if (vsi->xsk_umems) { - if (qid >= vsi->num_xsk_umems) - return -EINVAL; - *umem = vsi->xsk_umems[qid]; - return 0; - } + if (!queried_umem) + return -EINVAL; - *umem = NULL; + *umem = queried_umem; return 0; } @@ -945,13 +873,11 @@ void i40e_xsk_clean_tx_ring(struct i40e_ring *tx_ring) **/ bool i40e_xsk_any_rx_ring_enabled(struct i40e_vsi *vsi) { + struct net_device *netdev = vsi->netdev; int i; - if (!vsi->xsk_umems) - return false; - for (i = 0; i < vsi->num_queue_pairs; i++) { - if (vsi->xsk_umems[i]) + if (xdp_get_umem_from_qid(netdev, i)) return true; } -- cgit v1.2.3 From 3647cd6eaf83d7f6145a3ccac73f5286496490d2 Mon Sep 17 00:00:00 2001 From: Aleksandr Loktionov Date: Wed, 19 Dec 2018 06:45:37 -0800 Subject: i40e: Limiting RSS queues to CPUs Limiting RSS queues number to online CPUs number in order to avoid issues with creating misconfigured RSS queues. Signed-off-by: Aleksandr Loktionov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 0ee641c41be4..b5311846573e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -11042,6 +11042,7 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count) if (!(pf->flags & I40E_FLAG_RSS_ENABLED)) return 0; + queue_count = min_t(int, queue_count, num_online_cpus()); new_rss_size = min_t(int, queue_count, pf->rss_size_max); if (queue_count != vsi->num_queue_pairs) { -- cgit v1.2.3 From 68f7030f2d5f9592fcae405296376073eff69cbd Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 22 Jan 2019 16:33:53 +0100 Subject: mt76: fix per-chain signal strength reporting Fix an off-by-one error that resulted in not reporting the signal strength for the first chain Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index ce9bb702045f..63fa27d2c404 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -648,7 +648,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, status->chains = BIT(0); signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0); - for (i = 1; i < nstreams; i++) { + for (i = 0; i < nstreams; i++) { status->chains |= BIT(i); status->chain_signal[i] = mt76x02_mac_get_rssi(dev, rxwi->rssi[i], -- cgit v1.2.3 From d225581df3147060bc99e931b11f7cf2dcb1b2ca Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 21 Jan 2019 17:33:38 +0100 Subject: mt76: avoid scheduling tx queues for powersave stations In case a tx queue wake call arrives after a client has transitioned to powersave, make sure that the queue is not kept active until the client has left powersave mode Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/tx.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 1ea08ce62713..ef38e8626da9 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -396,6 +396,11 @@ mt76_txq_send_burst(struct mt76_dev *dev, struct mt76_queue *hwq, bool probe; int idx; + if (test_bit(MT_WCID_FLAG_PS, &wcid->flags)) { + *empty = true; + return 0; + } + skb = mt76_txq_dequeue(dev, mtxq, false); if (!skb) { *empty = true; -- cgit v1.2.3 From 1d96340196f1ee9e60eb39c828ba1186dfabe08a Mon Sep 17 00:00:00 2001 From: Damian Dybek Date: Wed, 19 Dec 2018 06:45:38 -0800 Subject: i40e: Add support FEC configuration for Fortville 25G This patch adds support for setting/getting FEC configuration using ethtool options: set/show-priv-flags rs-fec/base-r-fec set/show-fec off/rs/baser/auto for kernels version >= 4.14 Signed-off-by: Damian Dybek Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 4 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 228 ++++++++++++++++++++++++- drivers/net/ethernet/intel/i40e/i40e_main.c | 26 +++ 3 files changed, 256 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 7f41fd422ee1..d684998ba2b0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -524,6 +524,8 @@ struct i40e_pf { #define I40E_FLAG_FD_SB_INACTIVE BIT(22) #define I40E_FLAG_FD_SB_TO_CLOUD_FILTER BIT(23) #define I40E_FLAG_DISABLE_FW_LLDP BIT(24) +#define I40E_FLAG_RS_FEC BIT(25) +#define I40E_FLAG_BASE_R_FEC BIT(26) struct i40e_client_instance *cinst; bool stat_offsets_loaded; @@ -1087,6 +1089,8 @@ i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf); i40e_status i40e_commit_partition_bw_setting(struct i40e_pf *pf); void i40e_print_link_message(struct i40e_vsi *vsi, bool isup); +void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags); + static inline bool i40e_enabled_xdp_vsi(struct i40e_vsi *vsi) { return !!vsi->xdp_prog; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index a6bc7847346b..a861816b81b0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -438,6 +438,8 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = { I40E_PRIV_FLAG("disable-source-pruning", I40E_FLAG_SOURCE_PRUNING_DISABLED, 0), I40E_PRIV_FLAG("disable-fw-lldp", I40E_FLAG_DISABLE_FW_LLDP, 0), + I40E_PRIV_FLAG("rs-fec", I40E_FLAG_RS_FEC, 0), + I40E_PRIV_FLAG("base-r-fec", I40E_FLAG_BASE_R_FEC, 0), }; #define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gstrings_priv_flags) @@ -606,6 +608,24 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseCR_Full); } + if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_AOC || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_ACC) { + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB) { + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_BASER); + } + } /* need to add new 10G PHY types */ if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 || phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU) { @@ -721,6 +741,13 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 25000baseSR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseSR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_BASER); ethtool_link_ksettings_add_link_mode(ks, supported, 10000baseSR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, @@ -825,6 +852,9 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 40000baseKR4_Full); ethtool_link_ksettings_add_link_mode(ks, supported, 25000baseKR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); ethtool_link_ksettings_add_link_mode(ks, supported, 20000baseKR2_Full); ethtool_link_ksettings_add_link_mode(ks, supported, @@ -838,6 +868,10 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 40000baseKR4_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseKR_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_BASER); ethtool_link_ksettings_add_link_mode(ks, advertising, 20000baseKR2_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, @@ -855,6 +889,13 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, 25000baseCR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseCR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_BASER); break; case I40E_PHY_TYPE_25GBASE_AOC: case I40E_PHY_TYPE_25GBASE_ACC: @@ -862,9 +903,15 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); ethtool_link_ksettings_add_link_mode(ks, supported, 25000baseCR_Full); - ethtool_link_ksettings_add_link_mode(ks, advertising, 25000baseCR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); + ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); + ethtool_link_ksettings_add_link_mode(ks, advertising, + FEC_BASER); ethtool_link_ksettings_add_link_mode(ks, supported, 10000baseCR_Full); ethtool_link_ksettings_add_link_mode(ks, advertising, @@ -1261,6 +1308,154 @@ done: return err; } +static int i40e_set_fec_cfg(struct net_device *netdev, u8 fec_cfg) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_aq_get_phy_abilities_resp abilities; + struct i40e_pf *pf = np->vsi->back; + struct i40e_hw *hw = &pf->hw; + i40e_status status = 0; + u32 flags = 0; + int err = 0; + + flags = READ_ONCE(pf->flags); + i40e_set_fec_in_flags(fec_cfg, &flags); + + /* Get the current phy config */ + memset(&abilities, 0, sizeof(abilities)); + status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, + NULL); + if (status) { + err = -EAGAIN; + goto done; + } + + if (abilities.fec_cfg_curr_mod_ext_info != fec_cfg) { + struct i40e_aq_set_phy_config config; + + memset(&config, 0, sizeof(config)); + config.phy_type = abilities.phy_type; + config.abilities = abilities.abilities; + config.phy_type_ext = abilities.phy_type_ext; + config.link_speed = abilities.link_speed; + config.eee_capability = abilities.eee_capability; + config.eeer = abilities.eeer_val; + config.low_power_ctrl = abilities.d3_lpan; + config.fec_config = fec_cfg & I40E_AQ_PHY_FEC_CONFIG_MASK; + status = i40e_aq_set_phy_config(hw, &config, NULL); + if (status) { + netdev_info(netdev, + "Set phy config failed, err %s aq_err %s\n", + i40e_stat_str(hw, status), + i40e_aq_str(hw, hw->aq.asq_last_status)); + err = -EAGAIN; + goto done; + } + pf->flags = flags; + status = i40e_update_link_info(hw); + if (status) + /* debug level message only due to relation to the link + * itself rather than to the FEC settings + * (e.g. no physical connection etc.) + */ + netdev_dbg(netdev, + "Updating link info failed with err %s aq_err %s\n", + i40e_stat_str(hw, status), + i40e_aq_str(hw, hw->aq.asq_last_status)); + } + +done: + return err; +} + +static int i40e_get_fec_param(struct net_device *netdev, + struct ethtool_fecparam *fecparam) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_aq_get_phy_abilities_resp abilities; + struct i40e_pf *pf = np->vsi->back; + struct i40e_hw *hw = &pf->hw; + i40e_status status = 0; + int err = 0; + + /* Get the current phy config */ + memset(&abilities, 0, sizeof(abilities)); + status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, + NULL); + if (status) { + err = -EAGAIN; + goto done; + } + + fecparam->fec = 0; + if (abilities.fec_cfg_curr_mod_ext_info & I40E_AQ_SET_FEC_AUTO) + fecparam->fec |= ETHTOOL_FEC_AUTO; + if ((abilities.fec_cfg_curr_mod_ext_info & + I40E_AQ_SET_FEC_REQUEST_RS) || + (abilities.fec_cfg_curr_mod_ext_info & + I40E_AQ_SET_FEC_ABILITY_RS)) + fecparam->fec |= ETHTOOL_FEC_RS; + if ((abilities.fec_cfg_curr_mod_ext_info & + I40E_AQ_SET_FEC_REQUEST_KR) || + (abilities.fec_cfg_curr_mod_ext_info & I40E_AQ_SET_FEC_ABILITY_KR)) + fecparam->fec |= ETHTOOL_FEC_BASER; + if (abilities.fec_cfg_curr_mod_ext_info == 0) + fecparam->fec |= ETHTOOL_FEC_OFF; + + if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_KR_ENA) + fecparam->active_fec = ETHTOOL_FEC_BASER; + else if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_RS_ENA) + fecparam->active_fec = ETHTOOL_FEC_RS; + else + fecparam->active_fec = ETHTOOL_FEC_OFF; +done: + return err; +} + +static int i40e_set_fec_param(struct net_device *netdev, + struct ethtool_fecparam *fecparam) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_pf *pf = np->vsi->back; + struct i40e_hw *hw = &pf->hw; + u8 fec_cfg = 0; + int err = 0; + + if (hw->device_id != I40E_DEV_ID_25G_SFP28 && + hw->device_id != I40E_DEV_ID_25G_B) { + err = -EPERM; + goto done; + } + + switch (fecparam->fec) { + case ETHTOOL_FEC_AUTO: + fec_cfg = I40E_AQ_SET_FEC_AUTO; + break; + case ETHTOOL_FEC_RS: + fec_cfg = (I40E_AQ_SET_FEC_REQUEST_RS | + I40E_AQ_SET_FEC_ABILITY_RS); + break; + case ETHTOOL_FEC_BASER: + fec_cfg = (I40E_AQ_SET_FEC_REQUEST_KR | + I40E_AQ_SET_FEC_ABILITY_KR); + break; + case ETHTOOL_FEC_OFF: + case ETHTOOL_FEC_NONE: + fec_cfg = 0; + break; + default: + dev_warn(&pf->pdev->dev, "Unsupported FEC mode: %d", + fecparam->fec); + err = -EINVAL; + goto done; + } + + err = i40e_set_fec_cfg(netdev, fec_cfg); + +done: + return err; +} + static int i40e_nway_reset(struct net_device *netdev) { /* restart autonegotiation */ @@ -1376,7 +1571,7 @@ static int i40e_set_pauseparam(struct net_device *netdev, else if (!pause->rx_pause && !pause->tx_pause) hw->fc.requested_mode = I40E_FC_NONE; else - return -EINVAL; + return -EINVAL; /* Tell the OS link is going down, the link will go back up when fw * says it is ready asynchronously @@ -4676,6 +4871,15 @@ flags_complete: } } + if (((changed_flags & I40E_FLAG_RS_FEC) || + (changed_flags & I40E_FLAG_BASE_R_FEC)) && + pf->hw.device_id != I40E_DEV_ID_25G_SFP28 && + pf->hw.device_id != I40E_DEV_ID_25G_B) { + dev_warn(&pf->pdev->dev, + "Device does not support changing FEC configuration\n"); + return -EOPNOTSUPP; + } + /* Now that we've checked to ensure that the new flags are valid, load * them into place. Since we only modify flags either (a) during * initialization or (b) while holding the RTNL lock, we don't need @@ -4714,6 +4918,24 @@ flags_complete: } } + if ((changed_flags & I40E_FLAG_RS_FEC) || + (changed_flags & I40E_FLAG_BASE_R_FEC)) { + u8 fec_cfg = 0; + + if (pf->flags & I40E_FLAG_RS_FEC && + pf->flags & I40E_FLAG_BASE_R_FEC) { + fec_cfg = I40E_AQ_SET_FEC_AUTO; + } else if (pf->flags & I40E_FLAG_RS_FEC) { + fec_cfg = (I40E_AQ_SET_FEC_REQUEST_RS | + I40E_AQ_SET_FEC_ABILITY_RS); + } else if (pf->flags & I40E_FLAG_BASE_R_FEC) { + fec_cfg = (I40E_AQ_SET_FEC_REQUEST_KR | + I40E_AQ_SET_FEC_ABILITY_KR); + } + if (i40e_set_fec_cfg(dev, fec_cfg)) + dev_warn(&pf->pdev->dev, "Cannot change FEC config\n"); + } + if ((changed_flags & pf->flags & I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED) && (pf->flags & I40E_FLAG_MFP_ENABLED)) @@ -4948,6 +5170,8 @@ static const struct ethtool_ops i40e_ethtool_ops = { .set_per_queue_coalesce = i40e_set_per_queue_coalesce, .get_link_ksettings = i40e_get_link_ksettings, .set_link_ksettings = i40e_set_link_ksettings, + .get_fecparam = i40e_get_fec_param, + .set_fecparam = i40e_set_fec_param, }; void i40e_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b5311846573e..94122dff77d3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -13860,6 +13860,29 @@ static void i40e_get_platform_mac_addr(struct pci_dev *pdev, struct i40e_pf *pf) i40e_get_mac_addr(&pf->hw, pf->hw.mac.addr); } +/** + * i40e_set_fec_in_flags - helper function for setting FEC options in flags + * @fec_cfg: FEC option to set in flags + * @flags: ptr to flags in which we set FEC option + **/ +void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags) +{ + if (fec_cfg & I40E_AQ_SET_FEC_AUTO) + *flags |= I40E_FLAG_RS_FEC | I40E_FLAG_BASE_R_FEC; + if ((fec_cfg & I40E_AQ_SET_FEC_REQUEST_RS) || + (fec_cfg & I40E_AQ_SET_FEC_ABILITY_RS)) { + *flags |= I40E_FLAG_RS_FEC; + *flags &= ~I40E_FLAG_BASE_R_FEC; + } + if ((fec_cfg & I40E_AQ_SET_FEC_REQUEST_KR) || + (fec_cfg & I40E_AQ_SET_FEC_ABILITY_KR)) { + *flags |= I40E_FLAG_BASE_R_FEC; + *flags &= ~I40E_FLAG_RS_FEC; + } + if (fec_cfg == 0) + *flags &= ~(I40E_FLAG_RS_FEC | I40E_FLAG_BASE_R_FEC); +} + /** * i40e_probe - Device initialization routine * @pdev: PCI device information struct @@ -14351,6 +14374,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); pf->hw.phy.link_info.requested_speeds = abilities.link_speed; + /* set the FEC config due to the board capabilities */ + i40e_set_fec_in_flags(abilities.fec_cfg_curr_mod_ext_info, &pf->flags); + /* get the supported phy types from the fw */ err = i40e_aq_get_phy_capabilities(hw, false, true, &abilities, NULL); if (err) -- cgit v1.2.3 From 9b0732d9ed6f80d712119fa32ff25ae9b09d481e Mon Sep 17 00:00:00 2001 From: Grzegorz Siwik Date: Wed, 19 Dec 2018 06:45:39 -0800 Subject: i40e: Change unmatched function types Change of function declaration from int to u64 due to return type mismatch (u64). Signed-off-by: Grzegorz Siwik Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index a861816b81b0..31f14765719b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2370,7 +2370,7 @@ static int i40e_get_ts_info(struct net_device *dev, return 0; } -static int i40e_link_test(struct net_device *netdev, u64 *data) +static u64 i40e_link_test(struct net_device *netdev, u64 *data) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; @@ -2393,7 +2393,7 @@ static int i40e_link_test(struct net_device *netdev, u64 *data) return *data; } -static int i40e_reg_test(struct net_device *netdev, u64 *data) +static u64 i40e_reg_test(struct net_device *netdev, u64 *data) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; @@ -2404,7 +2404,7 @@ static int i40e_reg_test(struct net_device *netdev, u64 *data) return *data; } -static int i40e_eeprom_test(struct net_device *netdev, u64 *data) +static u64 i40e_eeprom_test(struct net_device *netdev, u64 *data) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; @@ -2418,7 +2418,7 @@ static int i40e_eeprom_test(struct net_device *netdev, u64 *data) return *data; } -static int i40e_intr_test(struct net_device *netdev, u64 *data) +static u64 i40e_intr_test(struct net_device *netdev, u64 *data) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; -- cgit v1.2.3 From 3f8af41262697a4d6742f030fbe0ceb9e1a048a6 Mon Sep 17 00:00:00 2001 From: Sergey Nemov Date: Wed, 19 Dec 2018 06:45:40 -0800 Subject: i40e: check queue pairs num in config queues handler Check if num_queue_pairs number requested by VF is less than maximum possible value in VIRTCHNL_OP_CONFIG_VSI_QUEUES handler. Also check if local_vf_id >= 0 in common handler since it is of int type and can potentially be negative. Signed-off-by: Sergey Nemov Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 2ac23ebfbf31..f62937045c5d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2069,6 +2069,11 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) goto error_param; } + if (qci->num_queue_pairs > I40E_MAX_VF_QUEUES) { + aq_ret = I40E_ERR_PARAM; + goto error_param; + } + for (i = 0; i < qci->num_queue_pairs; i++) { qpi = &qci->qpair[i]; @@ -3656,7 +3661,7 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode, int ret; pf->vf_aq_requests++; - if (local_vf_id >= pf->num_alloc_vfs) + if (local_vf_id < 0 || local_vf_id >= pf->num_alloc_vfs) return -EINVAL; vf = &(pf->vf[local_vf_id]); -- cgit v1.2.3 From ce0a5f1ae68d136b7d8d518555f9ff743f855c30 Mon Sep 17 00:00:00 2001 From: Lihong Yang Date: Wed, 19 Dec 2018 06:45:41 -0800 Subject: i40e: remove debugfs tx_timeout support The tx_timeout command from debugfs was originally intended to support early silicon validation efforts. It is no longer needed. Thus remove it to avoid misuse of triggering tx_timeout through debugfs. Signed-off-by: Lihong Yang Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index a20d1cf058ad..c67d485d6f99 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1642,30 +1642,7 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp, count = buf_tmp - i40e_dbg_netdev_ops_buf + 1; } - if (strncmp(i40e_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) { - cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i", &vsi_seid); - if (cnt != 1) { - dev_info(&pf->pdev->dev, "tx_timeout \n"); - goto netdev_ops_write_done; - } - vsi = i40e_dbg_find_vsi(pf, vsi_seid); - if (!vsi) { - dev_info(&pf->pdev->dev, - "tx_timeout: VSI %d not found\n", vsi_seid); - } else if (!vsi->netdev) { - dev_info(&pf->pdev->dev, "tx_timeout: no netdev for VSI %d\n", - vsi_seid); - } else if (test_bit(__I40E_VSI_DOWN, vsi->state)) { - dev_info(&pf->pdev->dev, "tx_timeout: VSI %d not UP\n", - vsi_seid); - } else if (rtnl_trylock()) { - vsi->netdev->netdev_ops->ndo_tx_timeout(vsi->netdev); - rtnl_unlock(); - dev_info(&pf->pdev->dev, "tx_timeout called\n"); - } else { - dev_info(&pf->pdev->dev, "Could not acquire RTNL - please try again\n"); - } - } else if (strncmp(i40e_dbg_netdev_ops_buf, "change_mtu", 10) == 0) { + if (strncmp(i40e_dbg_netdev_ops_buf, "change_mtu", 10) == 0) { int mtu; cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i %i", @@ -1733,7 +1710,6 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp, dev_info(&pf->pdev->dev, "unknown command '%s'\n", i40e_dbg_netdev_ops_buf); dev_info(&pf->pdev->dev, "available commands\n"); - dev_info(&pf->pdev->dev, " tx_timeout \n"); dev_info(&pf->pdev->dev, " change_mtu \n"); dev_info(&pf->pdev->dev, " set_rx_mode \n"); dev_info(&pf->pdev->dev, " napi \n"); -- cgit v1.2.3 From 9f250f1564b6f34363c304a9fb79c7c44b9bf42d Mon Sep 17 00:00:00 2001 From: Alice Michael Date: Wed, 19 Dec 2018 06:45:42 -0800 Subject: i40e: update version number Signed-off-by: Alice Michael Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 94122dff77d3..430c984edd4f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -26,8 +26,8 @@ static const char i40e_driver_string[] = #define DRV_KERN "-k" #define DRV_VERSION_MAJOR 2 -#define DRV_VERSION_MINOR 7 -#define DRV_VERSION_BUILD 6 +#define DRV_VERSION_MINOR 8 +#define DRV_VERSION_BUILD 10 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN -- cgit v1.2.3 From 1d67ad3905d2cdd98b4f909af8ee9937b12f3154 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 30 Dec 2018 16:53:10 +0100 Subject: i40e: increase indentation Convert spaces to tabs to get correct alignment. Found with the help of Coccinelle. Signed-off-by: Julia Lawall Acked-by: Jeff Kirsher Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 430c984edd4f..5d616916a0d6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3610,7 +3610,7 @@ static void i40e_configure_msi_and_legacy(struct i40e_vsi *vsi) (I40E_QUEUE_TYPE_TX << I40E_QINT_TQCTL_NEXTQ_TYPE_SHIFT); - wr32(hw, I40E_QINT_TQCTL(nextqp), val); + wr32(hw, I40E_QINT_TQCTL(nextqp), val); } val = I40E_QINT_TQCTL_CAUSE_ENA_MASK | -- cgit v1.2.3 From d1b3fa861c62e21bb4dc598f0aee73b6ccf5d051 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 7 Jan 2019 22:59:28 +0000 Subject: i40e: clean up several indentation issues There are several statements that have incorrect levels of indentation, fix these. Signed-off-by: Colin Ian King Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 8 ++++---- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 31f14765719b..4c885801fa26 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2635,10 +2635,10 @@ static int i40e_set_phys_id(struct net_device *netdev, default: break; } - if (ret) - return -ENOENT; - else - return 0; + if (ret) + return -ENOENT; + else + return 0; } /* NOTE: i40e hardware uses a conversion factor of 2 for Interrupt diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5d616916a0d6..5c6731b97059 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8131,8 +8131,8 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, i40e_service_event_schedule(pf); } else { i40e_pf_unquiesce_all_vsi(pf); - set_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state); - set_bit(__I40E_CLIENT_L2_CHANGE, pf->state); + set_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state); + set_bit(__I40E_CLIENT_L2_CHANGE, pf->state); } exit: diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index f62937045c5d..831d52bc3c9a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -3389,8 +3389,8 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) dev_info(&pf->pdev->dev, "VF %d: Invalid input/s, can't apply cloud filter\n", vf->vf_id); - aq_ret = I40E_ERR_PARAM; - goto err; + aq_ret = I40E_ERR_PARAM; + goto err; } cfilter = kzalloc(sizeof(*cfilter), GFP_KERNEL); -- cgit v1.2.3 From 76f7164d02d4c596b396fc2e868276d1db3c5e1e Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Thu, 17 Jan 2019 20:56:21 -0800 Subject: net/tls: free ctx in sock destruct free tls context in sock destruct. close may not be the last call to free sock but force releasing the ctx in close will result in GPF when ctx referred again in tcp_done [ 515.330477] general protection fault: 0000 [#1] SMP PTI [ 515.330539] CPU: 5 PID: 0 Comm: swapper/5 Not tainted 4.20.0-rc7+ #10 [ 515.330657] Hardware name: Supermicro X8ST3/X8ST3, BIOS 2.0b 11/07/2013 [ 515.330844] RIP: 0010:tls_hw_unhash+0xbf/0xd0 [ [ 515.332220] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 515.332340] CR2: 00007fab32c55000 CR3: 000000009261e000 CR4: 00000000000006e0 [ 515.332519] Call Trace: [ 515.332632] [ 515.332793] tcp_set_state+0x5a/0x190 [ 515.332907] ? tcp_update_metrics+0xe3/0x350 [ 515.333023] tcp_done+0x31/0xd0 [ 515.333130] tcp_rcv_state_process+0xc27/0x111a [ 515.333242] ? __lock_is_held+0x4f/0x90 [ 515.333350] ? tcp_v4_do_rcv+0xaf/0x1e0 [ 515.333456] tcp_v4_do_rcv+0xaf/0x1e0 Signed-off-by: Atul Gupta Signed-off-by: David S. Miller --- drivers/crypto/chelsio/chtls/chtls_cm.c | 4 ++++ net/tls/tls_main.c | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c index 59b75299fcbc..2e11b0d6a9bb 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.c +++ b/drivers/crypto/chelsio/chtls/chtls_cm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "chtls.h" #include "chtls_cm.h" @@ -1015,6 +1016,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk, { struct inet_sock *newinet; const struct iphdr *iph; + struct tls_context *ctx; struct net_device *ndev; struct chtls_sock *csk; struct dst_entry *dst; @@ -1063,6 +1065,8 @@ static struct sock *chtls_recv_sock(struct sock *lsk, oreq->ts_recent = PASS_OPEN_TID_G(ntohl(req->tos_stid)); sk_setup_caps(newsk, dst); + ctx = tls_get_ctx(lsk); + newsk->sk_destruct = ctx->sk_destruct; csk->sk = newsk; csk->passive_reap_next = oreq; csk->tx_chan = cxgb4_port_chan(ndev); diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index fc97a105ebc2..d36d095cbcf0 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c @@ -266,8 +266,10 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) lock_sock(sk); sk_proto_close = ctx->sk_proto_close; - if ((ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD) || - (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE)) { + if (ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD) + goto skip_tx_cleanup; + + if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) { free_ctx = true; goto skip_tx_cleanup; } @@ -579,6 +581,17 @@ static void tls_build_proto(struct sock *sk) } } +static void tls_hw_sk_destruct(struct sock *sk) +{ + struct tls_context *ctx = tls_get_ctx(sk); + struct inet_connection_sock *icsk = inet_csk(sk); + + ctx->sk_destruct(sk); + /* Free ctx */ + kfree(ctx); + icsk->icsk_ulp_data = NULL; +} + static int tls_hw_prot(struct sock *sk) { struct tls_context *ctx; @@ -597,6 +610,8 @@ static int tls_hw_prot(struct sock *sk) ctx->hash = sk->sk_prot->hash; ctx->unhash = sk->sk_prot->unhash; ctx->sk_proto_close = sk->sk_prot->close; + ctx->sk_destruct = sk->sk_destruct; + sk->sk_destruct = tls_hw_sk_destruct; ctx->rx_conf = TLS_HW_RECORD; ctx->tx_conf = TLS_HW_RECORD; update_sk_prot(sk, ctx); -- cgit v1.2.3 From 1435d997037899924187c704ac672257d9576f3e Mon Sep 17 00:00:00 2001 From: Atul Gupta Date: Thu, 17 Jan 2019 20:56:39 -0800 Subject: cxgb4: TLS record offload enable Enable Inline TLS record by default Signed-off-by: Atul Gupta Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 6ba9099ca7fe..73fc2479b4f4 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -5653,7 +5653,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) NETIF_F_GSO_UDP_TUNNEL | NETIF_F_TSO | NETIF_F_TSO6; - netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; + netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_HW_TLS_RECORD; } if (highdma) -- cgit v1.2.3 From 3d021715d994766b59ce724843c6add030d9de6a Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 18 Jan 2019 14:30:20 +0200 Subject: bonding: adjust style of bond_3ad_rx_indication No functional changes, adjust the style of bond_3ad_rx_indication to prepare it for the stats changes: - reduce indentation by returning early on wrong length - remove extra new lines between switch cases - add marker local variable and use it to reduce line length - rearrange local variables in reverse xmas tree - separate final return Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 85 ++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 7c46d9f4fefd..cdc43eebef9d 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2357,57 +2357,54 @@ re_arm: static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length) { - struct port *port; int ret = RX_HANDLER_ANOTHER; + struct bond_marker *marker; + struct port *port; - if (length >= sizeof(struct lacpdu)) { - - port = &(SLAVE_AD_INFO(slave)->port); + if (length < sizeof(struct lacpdu)) + return ret; - if (!port->slave) { - net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", - slave->dev->name, slave->bond->dev->name); - return ret; - } + port = &(SLAVE_AD_INFO(slave)->port); + if (!port->slave) { + net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", + slave->dev->name, slave->bond->dev->name); + return ret; + } - switch (lacpdu->subtype) { - case AD_TYPE_LACPDU: - ret = RX_HANDLER_CONSUMED; - netdev_dbg(slave->bond->dev, - "Received LACPDU on port %d slave %s\n", - port->actor_port_number, - slave->dev->name); - /* Protect against concurrent state machines */ - spin_lock(&slave->bond->mode_lock); - ad_rx_machine(lacpdu, port); - spin_unlock(&slave->bond->mode_lock); + switch (lacpdu->subtype) { + case AD_TYPE_LACPDU: + ret = RX_HANDLER_CONSUMED; + netdev_dbg(slave->bond->dev, + "Received LACPDU on port %d slave %s\n", + port->actor_port_number, slave->dev->name); + /* Protect against concurrent state machines */ + spin_lock(&slave->bond->mode_lock); + ad_rx_machine(lacpdu, port); + spin_unlock(&slave->bond->mode_lock); + break; + case AD_TYPE_MARKER: + ret = RX_HANDLER_CONSUMED; + /* No need to convert fields to Little Endian since we + * don't use the marker's fields. + */ + marker = (struct bond_marker *)lacpdu; + switch (marker->tlv_type) { + case AD_MARKER_INFORMATION_SUBTYPE: + netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n", + port->actor_port_number); + ad_marker_info_received(marker, port); break; - - case AD_TYPE_MARKER: - ret = RX_HANDLER_CONSUMED; - /* No need to convert fields to Little Endian since we - * don't use the marker's fields. - */ - - switch (((struct bond_marker *)lacpdu)->tlv_type) { - case AD_MARKER_INFORMATION_SUBTYPE: - netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n", - port->actor_port_number); - ad_marker_info_received((struct bond_marker *)lacpdu, port); - break; - - case AD_MARKER_RESPONSE_SUBTYPE: - netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n", - port->actor_port_number); - ad_marker_response_received((struct bond_marker *)lacpdu, port); - break; - - default: - netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n", - port->actor_port_number); - } + case AD_MARKER_RESPONSE_SUBTYPE: + netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n", + port->actor_port_number); + ad_marker_response_received(marker, port); + break; + default: + netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n", + port->actor_port_number); } } + return ret; } -- cgit v1.2.3 From dadeb61dcc9acf6a6cafde3ff4931ef88d2e6677 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 18 Jan 2019 14:30:21 +0200 Subject: bonding: 3ad: remove bond_3ad_rx_indication's length argument Since the received lacpdu is accessed via skb_header_pointer() in bond_3ad_lacpdu_recv() we no longer need to check for skb->len's length. If the returned lacpdu pointer is not null that should be enough. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index cdc43eebef9d..d8ef2350c68d 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2348,22 +2348,17 @@ re_arm: * bond_3ad_rx_indication - handle a received frame * @lacpdu: received lacpdu * @slave: slave struct to work on - * @length: length of the data received * * It is assumed that frames that were sent on this NIC don't returned as new * received frames (loopback). Since only the payload is given to this * function, it check for loopback. */ -static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, - u16 length) +static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave) { int ret = RX_HANDLER_ANOTHER; struct bond_marker *marker; struct port *port; - if (length < sizeof(struct lacpdu)) - return ret; - port = &(SLAVE_AD_INFO(slave)->port); if (!port->slave) { net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", @@ -2643,7 +2638,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, if (!lacpdu) return RX_HANDLER_ANOTHER; - return bond_3ad_rx_indication(lacpdu, slave, skb->len); + return bond_3ad_rx_indication(lacpdu, slave); } /** -- cgit v1.2.3 From 267c095aa2d9126059c1f5a65c660d5a71833e3f Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 18 Jan 2019 14:30:22 +0200 Subject: bonding: add 3ad stats Count the following types of 3ad packets per slave: - rx/tx lacpdu - rx/tx marker - rx/tx marker response - rx illegal lacpdus (right now counted on wrong length) - rx unknown lacpdu type - rx unknown marker type The counters are using atomic64 since this is not fast path. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 28 +++++++++++++++++++++++++++- include/net/bond_3ad.h | 14 ++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index d8ef2350c68d..d1d8cb6b8cdc 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -851,6 +851,8 @@ static int ad_lacpdu_send(struct port *port) if (!skb) return -ENOMEM; + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_tx); + skb->dev = slave->dev; skb_reset_mac_header(skb); skb->network_header = skb->mac_header + ETH_HLEN; @@ -892,6 +894,15 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker) if (!skb) return -ENOMEM; + switch (marker->tlv_type) { + case AD_MARKER_INFORMATION_SUBTYPE: + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_tx); + break; + case AD_MARKER_RESPONSE_SUBTYPE: + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_resp_tx); + break; + } + skb_reserve(skb, 16); skb->dev = slave->dev; @@ -1086,6 +1097,9 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) */ last_state = port->sm_rx_state; + if (lacpdu) + atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.lacpdu_rx); + /* check if state machine should change state */ /* first, check if port was reinitialized */ @@ -1922,6 +1936,8 @@ static void ad_marker_info_received(struct bond_marker *marker_info, { struct bond_marker marker; + atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_rx); + /* copy the received marker data to the response marker */ memcpy(&marker, marker_info, sizeof(struct bond_marker)); /* change the marker subtype to marker response */ @@ -1946,6 +1962,8 @@ static void ad_marker_info_received(struct bond_marker *marker_info, static void ad_marker_response_received(struct bond_marker *marker, struct port *port) { + atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_resp_rx); + /* DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW */ } @@ -2358,6 +2376,7 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave) int ret = RX_HANDLER_ANOTHER; struct bond_marker *marker; struct port *port; + atomic64_t *stat; port = &(SLAVE_AD_INFO(slave)->port); if (!port->slave) { @@ -2397,7 +2416,12 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave) default: netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n", port->actor_port_number); + stat = &SLAVE_AD_INFO(slave)->stats.marker_unknown_rx; + atomic64_inc(stat); } + break; + default: + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_unknown_rx); } return ret; @@ -2635,8 +2659,10 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, return RX_HANDLER_ANOTHER; lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu); - if (!lacpdu) + if (!lacpdu) { + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_illegal_rx); return RX_HANDLER_ANOTHER; + } return bond_3ad_rx_indication(lacpdu, slave); } diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h index fc3111515f5c..30e60dba1b2d 100644 --- a/include/net/bond_3ad.h +++ b/include/net/bond_3ad.h @@ -180,6 +180,19 @@ struct port; #pragma pack(8) #endif +struct bond_3ad_stats { + atomic64_t lacpdu_rx; + atomic64_t lacpdu_tx; + atomic64_t lacpdu_unknown_rx; + atomic64_t lacpdu_illegal_rx; + + atomic64_t marker_rx; + atomic64_t marker_tx; + atomic64_t marker_resp_rx; + atomic64_t marker_resp_tx; + atomic64_t marker_unknown_rx; +}; + /* aggregator structure(43.4.5 in the 802.3ad standard) */ typedef struct aggregator { struct mac_addr aggregator_mac_address; @@ -272,6 +285,7 @@ struct ad_bond_info { struct ad_slave_info { struct aggregator aggregator; /* 802.3ad aggregator structure */ struct port port; /* 802.3ad port structure */ + struct bond_3ad_stats stats; u16 id; }; -- cgit v1.2.3 From a258aeacd7f0dc10bb45caa7e92a3ea3ca1a76e9 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Fri, 18 Jan 2019 14:30:23 +0200 Subject: bonding: add support for xstats and export 3ad stats This patch adds support for extended statistics (xstats) call to the bonding. The first user would be the 3ad code which counts the following events: - LACPDU Rx/Tx - LACPDU unknown type Rx - LACPDU illegal Rx - Marker Rx/Tx - Marker response Rx/Tx - Marker unknown type Rx All of these are exported via netlink as separate attributes to be easily extensible as we plan to add more in the future. Similar to how the bridge and other xstats exports, the structure inside is: [ IFLA_STATS_LINK_XSTATS ] -> [ LINK_XSTATS_TYPE_BOND ] -> [ BOND_XSTATS_3AD ] -> [ 3ad stats attributes ] With this structure it's easy to add more stat types later. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 83 ++++++++++++++++++++++++++++++++++++++ drivers/net/bonding/bond_netlink.c | 71 ++++++++++++++++++++++++++++++++ include/net/bond_3ad.h | 3 ++ include/uapi/linux/if_bonding.h | 24 +++++++++++ include/uapi/linux/if_link.h | 1 + 5 files changed, 182 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index d1d8cb6b8cdc..d30c21b34858 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -31,6 +31,7 @@ #include #include #include +#include /* General definitions */ #define AD_SHORT_TIMEOUT 1 @@ -2696,3 +2697,85 @@ void bond_3ad_update_lacp_rate(struct bonding *bond) } spin_unlock_bh(&bond->mode_lock); } + +void bond_3ad_stats_add(struct slave *slave, struct bond_3ad_stats *stats) +{ + struct bond_3ad_stats *rstats = &SLAVE_AD_INFO(slave)->stats; + u64 stat; + + atomic64_add(atomic64_read(&rstats->lacpdu_rx), &stats->lacpdu_rx); + atomic64_add(atomic64_read(&rstats->lacpdu_tx), &stats->lacpdu_tx); + + stat = atomic64_read(&rstats->lacpdu_unknown_rx); + atomic64_add(stat, &stats->lacpdu_unknown_rx); + stat = atomic64_read(&rstats->lacpdu_illegal_rx); + atomic64_add(stat, &stats->lacpdu_illegal_rx); + + atomic64_add(atomic64_read(&rstats->marker_rx), &stats->marker_rx); + atomic64_add(atomic64_read(&rstats->marker_tx), &stats->marker_tx); + + stat = atomic64_read(&rstats->marker_resp_rx); + atomic64_add(stat, &stats->marker_resp_rx); + stat = atomic64_read(&rstats->marker_resp_tx); + atomic64_add(stat, &stats->marker_resp_tx); + stat = atomic64_read(&rstats->marker_unknown_rx); + atomic64_add(stat, &stats->marker_unknown_rx); +} + +size_t bond_3ad_stats_size(void) +{ + return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_TX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_UNKNOWN_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_ILLEGAL_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_TX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RESP_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RESP_TX */ + nla_total_size_64bit(sizeof(u64)); /* BOND_3AD_STAT_MARKER_UNKNOWN_RX */ +} + +int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats) +{ + u64 val; + + val = atomic64_read(&stats->lacpdu_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->lacpdu_tx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_TX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->lacpdu_unknown_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_UNKNOWN_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->lacpdu_illegal_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_ILLEGAL_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + + val = atomic64_read(&stats->marker_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->marker_tx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_TX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->marker_resp_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RESP_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->marker_resp_tx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RESP_TX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->marker_unknown_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_UNKNOWN_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + + return 0; +} diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index 6b9ad8673218..d1338fbe1830 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -675,6 +675,75 @@ nla_put_failure: return -EMSGSIZE; } +static size_t bond_get_linkxstats_size(const struct net_device *dev, int attr) +{ + switch (attr) { + case IFLA_STATS_LINK_XSTATS: + case IFLA_STATS_LINK_XSTATS_SLAVE: + break; + default: + return 0; + } + + return bond_3ad_stats_size() + nla_total_size(0); +} + +static int bond_fill_linkxstats(struct sk_buff *skb, + const struct net_device *dev, + int *prividx, int attr) +{ + struct nlattr *nla __maybe_unused; + struct slave *slave = NULL; + struct nlattr *nest, *nest2; + struct bonding *bond; + + switch (attr) { + case IFLA_STATS_LINK_XSTATS: + bond = netdev_priv(dev); + break; + case IFLA_STATS_LINK_XSTATS_SLAVE: + slave = bond_slave_get_rtnl(dev); + if (!slave) + return 0; + bond = slave->bond; + break; + default: + return -EINVAL; + } + + nest = nla_nest_start(skb, LINK_XSTATS_TYPE_BOND); + if (!nest) + return -EMSGSIZE; + if (BOND_MODE(bond) == BOND_MODE_8023AD) { + struct bond_3ad_stats stats; + struct list_head *iter; + + memset(&stats, 0, sizeof(stats)); + if (slave) { + bond_3ad_stats_add(slave, &stats); + } else { + bond_for_each_slave(bond, slave, iter) + bond_3ad_stats_add(slave, &stats); + } + + nest2 = nla_nest_start(skb, BOND_XSTATS_3AD); + if (!nest2) { + nla_nest_end(skb, nest); + return -EMSGSIZE; + } + + if (bond_3ad_stats_fill(skb, &stats)) { + nla_nest_cancel(skb, nest2); + nla_nest_end(skb, nest); + return -EMSGSIZE; + } + nla_nest_end(skb, nest2); + } + nla_nest_end(skb, nest); + + return 0; +} + struct rtnl_link_ops bond_link_ops __read_mostly = { .kind = "bond", .priv_size = sizeof(struct bonding), @@ -689,6 +758,8 @@ struct rtnl_link_ops bond_link_ops __read_mostly = { .get_num_tx_queues = bond_get_num_tx_queues, .get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number as for TX queues */ + .fill_linkxstats = bond_fill_linkxstats, + .get_linkxstats_size = bond_get_linkxstats_size, .slave_maxtype = IFLA_BOND_SLAVE_MAX, .slave_policy = bond_slave_policy, .slave_changelink = bond_slave_changelink, diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h index 30e60dba1b2d..25aaf49d19be 100644 --- a/include/net/bond_3ad.h +++ b/include/net/bond_3ad.h @@ -321,5 +321,8 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, int bond_3ad_set_carrier(struct bonding *bond); void bond_3ad_update_lacp_rate(struct bonding *bond); void bond_3ad_update_ad_actor_settings(struct bonding *bond); +void bond_3ad_stats_add(struct slave *slave, struct bond_3ad_stats *stats); +int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats); +size_t bond_3ad_stats_size(void); #endif /* _NET_BOND_3AD_H */ diff --git a/include/uapi/linux/if_bonding.h b/include/uapi/linux/if_bonding.h index 61a1bf6e865e..790585f0e61b 100644 --- a/include/uapi/linux/if_bonding.h +++ b/include/uapi/linux/if_bonding.h @@ -117,6 +117,30 @@ struct ad_info { __u8 partner_system[ETH_ALEN]; }; +/* Embedded inside LINK_XSTATS_TYPE_BOND */ +enum { + BOND_XSTATS_UNSPEC, + BOND_XSTATS_3AD, + __BOND_XSTATS_MAX +}; +#define BOND_XSTATS_MAX (__BOND_XSTATS_MAX - 1) + +/* Embedded inside BOND_XSTATS_3AD */ +enum { + BOND_3AD_STAT_LACPDU_RX, + BOND_3AD_STAT_LACPDU_TX, + BOND_3AD_STAT_LACPDU_UNKNOWN_RX, + BOND_3AD_STAT_LACPDU_ILLEGAL_RX, + BOND_3AD_STAT_MARKER_RX, + BOND_3AD_STAT_MARKER_TX, + BOND_3AD_STAT_MARKER_RESP_RX, + BOND_3AD_STAT_MARKER_RESP_TX, + BOND_3AD_STAT_MARKER_UNKNOWN_RX, + BOND_3AD_STAT_PAD, + __BOND_3AD_STAT_MAX +}; +#define BOND_3AD_STAT_MAX (__BOND_3AD_STAT_MAX - 1) + #endif /* _LINUX_IF_BONDING_H */ /* diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index d6533828123a..5b225ff63b48 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -925,6 +925,7 @@ enum { enum { LINK_XSTATS_TYPE_UNSPEC, LINK_XSTATS_TYPE_BRIDGE, + LINK_XSTATS_TYPE_BOND, __LINK_XSTATS_TYPE_MAX }; #define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1) -- cgit v1.2.3 From 21e194425abd65b525fa38cbddd08ef169d5269d Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 10:30:21 +0100 Subject: net: phy: fix issue with loading PHY driver w/o initramfs It was reported that on a system with nfsboot and w/o initramfs network fails because trying to load the PHY driver returns -ENOENT. Reason was that due to missing initramfs the modprobe binary isn't available. So we have to ignore error code -ENOENT. Fixes: 13d0ab6750b2 ("net: phy: check return code when requesting PHY driver module") Reported-by: Krzysztof Kozlowski Signed-off-by: Heiner Kallweit Tested-by: Krzysztof Kozlowski Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index b61db0a5ba3a..d35038b23370 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -564,10 +564,12 @@ static int phy_request_driver_module(struct phy_device *dev, int phy_id) ret = request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id)); - /* we only check for failures in executing the usermode binary, - * not whether a PHY driver module exists for the PHY ID + /* We only check for failures in executing the usermode binary, + * not whether a PHY driver module exists for the PHY ID. + * Accept -ENOENT because this may occur in case no initramfs exists, + * then modprobe isn't available. */ - if (IS_ENABLED(CONFIG_MODULES) && ret < 0) { + if (IS_ENABLED(CONFIG_MODULES) && ret < 0 && ret != -ENOENT) { phydev_err(dev, "error %d loading PHY driver module for ID 0x%08x\n", ret, phy_id); return ret; -- cgit v1.2.3 From a5996989d5911f416f8a31cf2b3d415911febbf6 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 19 Jan 2019 10:43:07 +0100 Subject: net: phy: improve phy_init_hw Currently the soft reset (if defined) is done only if the driver also implements the config_init callback. I think this dependency is a mistake, so let's remove it. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index d35038b23370..6ccc2c7cc9f6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1072,7 +1072,7 @@ int phy_init_hw(struct phy_device *phydev) /* Deassert the reset signal */ phy_device_reset(phydev, 0); - if (!phydev->drv || !phydev->drv->config_init) + if (!phydev->drv) return 0; if (phydev->drv->soft_reset) @@ -1085,7 +1085,10 @@ int phy_init_hw(struct phy_device *phydev) if (ret < 0) return ret; - return phydev->drv->config_init(phydev); + if (phydev->drv->config_init) + ret = phydev->drv->config_init(phydev); + + return ret; } EXPORT_SYMBOL(phy_init_hw); -- cgit v1.2.3 From 6dc8b74bf5c5a958136613ff773f6c770fbde2f2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 20 Jan 2019 11:12:01 +0100 Subject: r8169: improve rx buffer allocation 8 years ago, as part of 6f0333b8fde4 ("r8169: use 50% less ram for RX ring"), the alignment requirement for rx buffers was silently changed from 8 bytes to 16 bytes. I found nothing explaining this, also the chip specs I have only mention an 8 byte requirement. AFAICS kmalloc_node() guarantees allocated memory to be at least "long long" aligned, what is 8 bytes on a 32 bit machine. So we can take this memory as-is and avoid some overhead by changing the alignment requirement back to 8 bytes. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e790a4116f1e..970c82694d4d 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -5659,11 +5659,6 @@ static inline void rtl8169_mark_to_asic(struct RxDesc *desc) desc->opts1 = cpu_to_le32(DescOwn | eor | R8169_RX_BUF_SIZE); } -static inline void *rtl8169_align(void *data) -{ - return (void *)ALIGN((long)data, 16); -} - static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, struct RxDesc *desc) { @@ -5676,15 +5671,13 @@ static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, if (!data) return NULL; - if (rtl8169_align(data) != data) { - kfree(data); - data = kmalloc_node(R8169_RX_BUF_SIZE + 15, GFP_KERNEL, node); - if (!data) - return NULL; + /* Memory should be properly aligned, but better check. */ + if (!IS_ALIGNED((unsigned long)data, 8)) { + netdev_err_once(tp->dev, "RX buffer not 8-byte-aligned\n"); + goto err_out; } - mapping = dma_map_single(d, rtl8169_align(data), R8169_RX_BUF_SIZE, - DMA_FROM_DEVICE); + mapping = dma_map_single(d, data, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(d, mapping))) { if (net_ratelimit()) netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); @@ -6290,7 +6283,6 @@ static struct sk_buff *rtl8169_try_rx_copy(void *data, struct sk_buff *skb; struct device *d = tp_to_dev(tp); - data = rtl8169_align(data); dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); prefetch(data); skb = napi_alloc_skb(&tp->napi, pkt_size); -- cgit v1.2.3 From 10b63e8543145d03de68735a3a2b6f3784dd4a33 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 20 Jan 2019 11:45:20 +0100 Subject: r8169: remove PCI DAC support The old non-PCIe chip versions support PCI DAC, however this feature seems to be fragile, see comment in the PCI error handler. Therefore it's disabled per default. I think meanwhile it's time remove support for this legacy feature. This helps to reduce complexity of the driver. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 970c82694d4d..5480073e0026 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -229,7 +229,6 @@ static const struct pci_device_id rtl8169_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); -static int use_dac = -1; static struct { u32 msg_enable; } debug = { -1 }; @@ -704,8 +703,6 @@ struct rtl8169_private { MODULE_AUTHOR("Realtek and the Linux r8169 crew "); MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); module_param_named(debug, debug.msg_enable, int, 0); MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); MODULE_SOFTDEP("pre: realtek"); @@ -6180,14 +6177,6 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->cur_rx) { - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } @@ -7241,13 +7230,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->cp_cmd = RTL_R16(tp, CPlusCmd); - if (sizeof(dma_addr_t) > 4 && (use_dac == 1 || (use_dac == -1 && - tp->mac_version >= RTL_GIGA_MAC_VER_18)) && + if (sizeof(dma_addr_t) > 4 && tp->mac_version >= RTL_GIGA_MAC_VER_18 && !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) { - - /* CPlusCmd Dual Access Cycle is only needed for non-PCIe */ - if (!pci_is_pcie(pdev)) - tp->cp_cmd |= PCIDAC; dev->features |= NETIF_F_HIGHDMA; } else { rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); -- cgit v1.2.3 From 6679cf099b81994884246612538bd4c7fb935b30 Mon Sep 17 00:00:00 2001 From: Xue Chaojing Date: Sun, 20 Jan 2019 22:15:46 +0000 Subject: hinic: Add pci device ids This patch adds PCI device IDs to support following cards: 1. Add device id 0x0205 for HINIC 100GE dual port mezz card. 2. Add device id 0x0210 for HINIC 25GE quad port mezz card. 3. Delete device id 0x0201 for HINIC 100GE dual port card, because this is used by other product. 4. Macro of device id 0x200 is modified for HINIC 100GE dual port card. Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller --- drivers/net/ethernet/huawei/hinic/hinic_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index da323b9e1f62..e64bc664f687 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -51,9 +51,10 @@ static unsigned int rx_weight = 64; module_param(rx_weight, uint, 0644); MODULE_PARM_DESC(rx_weight, "Number Rx packets for NAPI budget (default=64)"); -#define HINIC_DEV_ID_QUAD_PORT_25GE 0x1822 -#define HINIC_DEV_ID_DUAL_PORT_25GE 0x0200 -#define HINIC_DEV_ID_DUAL_PORT_100GE 0x0201 +#define HINIC_DEV_ID_QUAD_PORT_25GE 0x1822 +#define HINIC_DEV_ID_DUAL_PORT_100GE 0x0200 +#define HINIC_DEV_ID_DUAL_PORT_100GE_MEZZ 0x0205 +#define HINIC_DEV_ID_QUAD_PORT_25GE_MEZZ 0x0210 #define HINIC_WQ_NAME "hinic_dev" @@ -1113,8 +1114,9 @@ static void hinic_shutdown(struct pci_dev *pdev) static const struct pci_device_id hinic_pci_table[] = { { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE), 0}, - { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_25GE), 0}, { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_100GE), 0}, + { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_100GE_MEZZ), 0}, + { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE_MEZZ), 0}, { 0, 0} }; MODULE_DEVICE_TABLE(pci, hinic_pci_table); -- cgit v1.2.3 From d6228b7cdd6e790e6c21a844b9b3ab35d01a1974 Mon Sep 17 00:00:00 2001 From: Artem Panfilov Date: Sun, 20 Jan 2019 19:05:15 +0300 Subject: net: stmmac: implement the SIOCGHWTSTAMP ioctl This patch adds support for the SIOCGHWTSTAMP ioctl which enables user processes to read the current hwtstamp_config settings non-destructively. Signed-off-by: Artem Panfilov Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 36 +++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 63e1064b27a2..f9b42b0c20f4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -28,6 +28,7 @@ #include #include "common.h" #include +#include #include struct stmmac_resources { @@ -174,6 +175,7 @@ struct stmmac_priv { unsigned int mode; unsigned int chain_mode; int extend_desc; + struct hwtstamp_config tstamp_config; struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_ops; unsigned int default_addend; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 5afba69981cf..517555bcfa44 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -534,7 +534,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, } /** - * stmmac_hwtstamp_ioctl - control hardware timestamping. + * stmmac_hwtstamp_set - control hardware timestamping. * @dev: device pointer. * @ifr: An IOCTL specific structure, that can contain a pointer to * a proprietary structure used to pass information to the driver. @@ -544,7 +544,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, * Return Value: * 0 on success and an appropriate -ve integer on failure. */ -static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) +static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) { struct stmmac_priv *priv = netdev_priv(dev); struct hwtstamp_config config; @@ -573,7 +573,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) } if (copy_from_user(&config, ifr->ifr_data, - sizeof(struct hwtstamp_config))) + sizeof(config))) return -EFAULT; netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", @@ -765,8 +765,31 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) (u32)now.tv_sec, now.tv_nsec); } + memcpy(&priv->tstamp_config, &config, sizeof(config)); + return copy_to_user(ifr->ifr_data, &config, - sizeof(struct hwtstamp_config)) ? -EFAULT : 0; + sizeof(config)) ? -EFAULT : 0; +} + +/** + * stmmac_hwtstamp_get - read hardware timestamping. + * @dev: device pointer. + * @ifr: An IOCTL specific structure, that can contain a pointer to + * a proprietary structure used to pass information to the driver. + * Description: + * This function obtain the current hardware timestamping settings + as requested. + */ +static int stmmac_hwtstamp_get(struct net_device *dev, struct ifreq *ifr) +{ + struct stmmac_priv *priv = netdev_priv(dev); + struct hwtstamp_config *config = &priv->tstamp_config; + + if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) + return -EOPNOTSUPP; + + return copy_to_user(ifr->ifr_data, config, + sizeof(*config)) ? -EFAULT : 0; } /** @@ -3767,7 +3790,10 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ret = phy_mii_ioctl(dev->phydev, rq, cmd); break; case SIOCSHWTSTAMP: - ret = stmmac_hwtstamp_ioctl(dev, rq); + ret = stmmac_hwtstamp_set(dev, rq); + break; + case SIOCGHWTSTAMP: + ret = stmmac_hwtstamp_get(dev, rq); break; default: break; -- cgit v1.2.3 From a7c30e62d4b89580c16023a4daba466f9fed35ae Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 21 Jan 2019 14:43:15 +0530 Subject: net: stmmac: Add driver for Qualcomm ethqos Add glue driver to support Qualcomm ETHQOS using stmmac driver. This is based on downstream driver written by Siddarth Gupta, Sunil Kumar Paidimarri, Rahul Ankushrao Kawadgave, Nisha Menon, Jagadeesh Babu Challagundla, Chaitanya Pratapa, Lakshit Tyagi, Suraj Jaiswal, Sneh Shah and Ventrapragada Ravi Kanth Co-developed-by: Niklas Cassel Signed-off-by: Niklas Cassel Signed-off-by: Vinod Koul Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/Kconfig | 10 + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 545 +++++++++++++++++++++ 3 files changed, 556 insertions(+) create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 6209cc1fb305..f194235153f9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -105,6 +105,16 @@ config DWMAC_OXNAS This selects the Oxford Semiconductor OXNASSoC glue layer support for the stmmac device driver. This driver is used for OX820. +config DWMAC_QCOM_ETHQOS + tristate "Qualcomm ETHQOS support" + default ARCH_QCOM + depends on OF && (ARCH_QCOM || COMPILE_TEST) + help + Support for the Qualcomm ETHQOS core. + + This selects the Qualcomm ETHQOS glue layer support for the + stmmac device driver. + config DWMAC_ROCKCHIP tristate "Rockchip dwmac support" default ARCH_ROCKCHIP diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index bf09701d2623..c529c21e9bdd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o +obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c new file mode 100644 index 000000000000..30724bd330f4 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018-19, Linaro Limited + +#include +#include +#include +#include +#include +#include "stmmac.h" +#include "stmmac_platform.h" + +#define RGMII_IO_MACRO_CONFIG 0x0 +#define SDCC_HC_REG_DLL_CONFIG 0x4 +#define SDCC_HC_REG_DDR_CONFIG 0xC +#define SDCC_HC_REG_DLL_CONFIG2 0x10 +#define SDC4_STATUS 0x14 +#define SDCC_USR_CTL 0x18 +#define RGMII_IO_MACRO_CONFIG2 0x1C +#define RGMII_IO_MACRO_DEBUG1 0x20 +#define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28 + +/* RGMII_IO_MACRO_CONFIG fields */ +#define RGMII_CONFIG_FUNC_CLK_EN BIT(30) +#define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23) +#define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20) +#define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17) +#define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8) +#define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6) +#define RGMII_CONFIG_INTF_SEL GENMASK(5, 4) +#define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3) +#define RGMII_CONFIG_LOOPBACK_EN BIT(2) +#define RGMII_CONFIG_PROG_SWAP BIT(1) +#define RGMII_CONFIG_DDR_MODE BIT(0) + +/* SDCC_HC_REG_DLL_CONFIG fields */ +#define SDCC_DLL_CONFIG_DLL_RST BIT(30) +#define SDCC_DLL_CONFIG_PDN BIT(29) +#define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24) +#define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20) +#define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19) +#define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18) +#define SDCC_DLL_CONFIG_CDR_EN BIT(17) +#define SDCC_DLL_CONFIG_DLL_EN BIT(16) +#define SDCC_DLL_MCLK_GATING_EN BIT(5) +#define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2) + +/* SDCC_HC_REG_DDR_CONFIG fields */ +#define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31) +#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21) +#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27) +#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30) +#define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0) + +/* SDCC_HC_REG_DLL_CONFIG2 fields */ +#define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21) +#define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10) +#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2) +#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1) +#define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0) + +/* SDC4_STATUS bits */ +#define SDC4_STATUS_DLL_LOCK BIT(7) + +/* RGMII_IO_MACRO_CONFIG2 fields */ +#define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17) +#define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16) +#define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13) +#define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12) +#define RGMII_CONFIG2_RX_PROG_SWAP BIT(7) +#define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6) +#define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) + +struct ethqos_emac_por { + unsigned int offset; + unsigned int value; +}; + +struct qcom_ethqos { + struct platform_device *pdev; + void __iomem *rgmii_base; + + unsigned int rgmii_clk_rate; + struct clk *rgmii_clk; + unsigned int speed; + + const struct ethqos_emac_por *por; + unsigned int num_por; +}; + +static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) +{ + return readl(ethqos->rgmii_base + offset); +} + +static void rgmii_writel(struct qcom_ethqos *ethqos, + int value, unsigned int offset) +{ + writel(value, ethqos->rgmii_base + offset); +} + +static void rgmii_updatel(struct qcom_ethqos *ethqos, + int mask, int val, unsigned int offset) +{ + unsigned int temp; + + temp = rgmii_readl(ethqos, offset); + temp = (temp & ~(mask)) | val; + rgmii_writel(ethqos, temp, offset); +} + +static void rgmii_dump(struct qcom_ethqos *ethqos) +{ + dev_dbg(ðqos->pdev->dev, "Rgmii register dump\n"); + dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n", + rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG)); + dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n", + rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG)); + dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n", + rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG)); + dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n", + rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2)); + dev_dbg(ðqos->pdev->dev, "SDC4_STATUS: %x\n", + rgmii_readl(ethqos, SDC4_STATUS)); + dev_dbg(ðqos->pdev->dev, "SDCC_USR_CTL: %x\n", + rgmii_readl(ethqos, SDCC_USR_CTL)); + dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n", + rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2)); + dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n", + rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1)); + dev_dbg(ðqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n", + rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG)); +} + +/* Clock rates */ +#define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL) +#define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL) +#define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL) + +static void +ethqos_update_rgmii_clk(struct qcom_ethqos *ethqos, unsigned int speed) +{ + switch (speed) { + case SPEED_1000: + ethqos->rgmii_clk_rate = RGMII_1000_NOM_CLK_FREQ; + break; + + case SPEED_100: + ethqos->rgmii_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ; + break; + + case SPEED_10: + ethqos->rgmii_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ; + break; + } + + clk_set_rate(ethqos->rgmii_clk, ethqos->rgmii_clk_rate); +} + +static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) +{ + rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN, + RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); +} + +static const struct ethqos_emac_por emac_v2_3_0_por[] = { + { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, + { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, + { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 }, + { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, + { .offset = SDCC_USR_CTL, .value = 0x00010800 }, + { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, +}; + +static int ethqos_dll_configure(struct qcom_ethqos *ethqos) +{ + unsigned int val; + int retry = 1000; + + /* Set CDR_EN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN, + SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG); + + /* Set CDR_EXT_EN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EXT_EN, + SDCC_DLL_CONFIG_CDR_EXT_EN, SDCC_HC_REG_DLL_CONFIG); + + /* Clear CK_OUT_EN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, + 0, SDCC_HC_REG_DLL_CONFIG); + + /* Set DLL_EN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, + SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); + + rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN, + 0, SDCC_HC_REG_DLL_CONFIG); + + rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE, + 0, SDCC_HC_REG_DLL_CONFIG); + + /* Wait for CK_OUT_EN clear */ + do { + val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); + val &= SDCC_DLL_CONFIG_CK_OUT_EN; + if (!val) + break; + mdelay(1); + retry--; + } while (retry > 0); + if (!retry) + dev_err(ðqos->pdev->dev, "Clear CK_OUT_EN timedout\n"); + + /* Set CK_OUT_EN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, + SDCC_DLL_CONFIG_CK_OUT_EN, SDCC_HC_REG_DLL_CONFIG); + + /* Wait for CK_OUT_EN set */ + retry = 1000; + do { + val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); + val &= SDCC_DLL_CONFIG_CK_OUT_EN; + if (val) + break; + mdelay(1); + retry--; + } while (retry > 0); + if (!retry) + dev_err(ðqos->pdev->dev, "Set CK_OUT_EN timedout\n"); + + /* Set DDR_CAL_EN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN, + SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2); + + rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS, + 0, SDCC_HC_REG_DLL_CONFIG2); + + rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, + 0x1A << 10, SDCC_HC_REG_DLL_CONFIG2); + + rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, + BIT(2), SDCC_HC_REG_DLL_CONFIG2); + + rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, + SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, + SDCC_HC_REG_DLL_CONFIG2); + + return 0; +} + +static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) +{ + /* Disable loopback mode */ + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, + 0, RGMII_IO_MACRO_CONFIG2); + + /* Select RGMII, write 0 to interface select */ + rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL, + 0, RGMII_IO_MACRO_CONFIG); + + switch (ethqos->speed) { + case SPEED_1000: + rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, + RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, + RGMII_CONFIG_POS_NEG_DATA_SEL, + RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, + RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_IO_MACRO_CONFIG2); + + /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */ + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, + 57, SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, + SDCC_DDR_CONFIG_PRG_DLY_EN, + SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); + break; + + case SPEED_100: + rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, + RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, + BIT(6), RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + 0, RGMII_IO_MACRO_CONFIG2); + /* Write 0x5 to PRG_RCLK_DLY_CODE */ + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, + (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, + SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, + SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); + break; + + case SPEED_10: + rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, + RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, + BIT(12) | GENMASK(9, 8), + RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + 0, RGMII_IO_MACRO_CONFIG2); + /* Write 0x5 to PRG_RCLK_DLY_CODE */ + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, + (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, + SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, + SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); + break; + default: + dev_err(ðqos->pdev->dev, + "Invalid speed %d\n", ethqos->speed); + return -EINVAL; + } + + return 0; +} + +static int ethqos_configure(struct qcom_ethqos *ethqos) +{ + volatile unsigned int dll_lock; + unsigned int i, retry = 1000; + + /* Reset to POR values and enable clk */ + for (i = 0; i < ethqos->num_por; i++) + rgmii_writel(ethqos, ethqos->por[i].value, + ethqos->por[i].offset); + ethqos_set_func_clk_en(ethqos); + + /* Initialize the DLL first */ + + /* Set DLL_RST */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, + SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG); + + /* Set PDN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, + SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); + + /* Clear DLL_RST */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, 0, + SDCC_HC_REG_DLL_CONFIG); + + /* Clear PDN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, 0, + SDCC_HC_REG_DLL_CONFIG); + + if (ethqos->speed != SPEED_100 && ethqos->speed != SPEED_10) { + /* Set DLL_EN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, + SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); + + /* Set CK_OUT_EN */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, + SDCC_DLL_CONFIG_CK_OUT_EN, + SDCC_HC_REG_DLL_CONFIG); + + /* Set USR_CTL bit 26 with mask of 3 bits */ + rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26), SDCC_USR_CTL); + + /* wait for DLL LOCK */ + do { + mdelay(1); + dll_lock = rgmii_readl(ethqos, SDC4_STATUS); + if (dll_lock & SDC4_STATUS_DLL_LOCK) + break; + } while (retry > 0); + if (!retry) + dev_err(ðqos->pdev->dev, + "Timeout while waiting for DLL lock\n"); + } + + if (ethqos->speed == SPEED_1000) + ethqos_dll_configure(ethqos); + + ethqos_rgmii_macro_init(ethqos); + + return 0; +} + +static void ethqos_fix_mac_speed(void *priv, unsigned int speed) +{ + struct qcom_ethqos *ethqos = priv; + + ethqos->speed = speed; + ethqos_update_rgmii_clk(ethqos, speed); + ethqos_configure(ethqos); +} + +static int qcom_ethqos_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; + struct qcom_ethqos *ethqos; + struct resource *res; + int ret; + + ret = stmmac_get_platform_resources(pdev, &stmmac_res); + if (ret) + return ret; + + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); + if (IS_ERR(plat_dat)) { + dev_err(&pdev->dev, "dt configuration failed\n"); + return PTR_ERR(plat_dat); + } + + ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL); + if (!ethqos) { + ret = -ENOMEM; + goto err_mem; + } + + ethqos->pdev = pdev; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rgmii"); + ethqos->rgmii_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ethqos->rgmii_base)) { + dev_err(&pdev->dev, "Can't get rgmii base\n"); + ret = PTR_ERR(ethqos->rgmii_base); + goto err_mem; + } + + ethqos->por = of_device_get_match_data(&pdev->dev); + + ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii"); + if (!ethqos->rgmii_clk) { + ret = -ENOMEM; + goto err_mem; + } + + ret = clk_prepare_enable(ethqos->rgmii_clk); + if (ret) + goto err_mem; + + ethqos->speed = SPEED_1000; + ethqos_update_rgmii_clk(ethqos, SPEED_1000); + ethqos_set_func_clk_en(ethqos); + + plat_dat->bsp_priv = ethqos; + plat_dat->fix_mac_speed = ethqos_fix_mac_speed; + plat_dat->has_gmac4 = 1; + plat_dat->pmt = 1; + plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); + + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + goto err_clk; + + rgmii_dump(ethqos); + + return ret; + +err_clk: + clk_disable_unprepare(ethqos->rgmii_clk); + +err_mem: + stmmac_remove_config_dt(pdev, plat_dat); + + return ret; +} + +static int qcom_ethqos_remove(struct platform_device *pdev) +{ + struct qcom_ethqos *ethqos; + int ret; + + ethqos = get_stmmac_bsp_priv(&pdev->dev); + if (!ethqos) + return -ENODEV; + + ret = stmmac_pltfr_remove(pdev); + clk_disable_unprepare(ethqos->rgmii_clk); + + return ret; +} + +static const struct of_device_id qcom_ethqos_match[] = { + { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_por}, + { } +}; +MODULE_DEVICE_TABLE(of, qcom_ethqos_match); + +static struct platform_driver qcom_ethqos_driver = { + .probe = qcom_ethqos_probe, + .remove = qcom_ethqos_remove, + .driver = { + .name = "qcom-ethqos", + .pm = &stmmac_pltfr_pm_ops, + .of_match_table = of_match_ptr(qcom_ethqos_match), + }, +}; +module_platform_driver(qcom_ethqos_driver); + +MODULE_DESCRIPTION("Qualcomm ETHQOS driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From cd28d1d6e52e740130745429b3ff0af7cbba7b2c Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 21 Jan 2019 14:43:17 +0530 Subject: net: phy: at803x: Disable phy delay for RGMII mode For RGMII mode, phy delay should be disabled. Add this case along with disable delay routines. Signed-off-by: Vinod Koul Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index f9432d053a22..8ff12938ab47 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -110,16 +110,16 @@ static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, return phy_write(phydev, AT803X_DEBUG_DATA, val); } -static inline int at803x_enable_rx_delay(struct phy_device *phydev) +static inline int at803x_disable_rx_delay(struct phy_device *phydev) { - return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0, - AT803X_DEBUG_RX_CLK_DLY_EN); + return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, + AT803X_DEBUG_RX_CLK_DLY_EN, 0); } -static inline int at803x_enable_tx_delay(struct phy_device *phydev) +static inline int at803x_disable_tx_delay(struct phy_device *phydev) { - return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0, - AT803X_DEBUG_TX_CLK_DLY_EN); + return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, + AT803X_DEBUG_TX_CLK_DLY_EN, 0); } /* save relevant PHY registers to private copy */ @@ -256,15 +256,17 @@ static int at803x_config_init(struct phy_device *phydev) return ret; if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { - ret = at803x_enable_rx_delay(phydev); + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII) { + ret = at803x_disable_rx_delay(phydev); if (ret < 0) return ret; } if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { - ret = at803x_enable_tx_delay(phydev); + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII) { + ret = at803x_disable_tx_delay(phydev); if (ret < 0) return ret; } -- cgit v1.2.3 From 5ecdd77c61c8fe1d75ded538701e5e854963c890 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Mon, 21 Jan 2019 14:43:18 +0530 Subject: net: dsa: qca8k: disable delay for RGMII mode In RGMII mode we should not have any delay in port MAC, so disable the delay. Signed-off-by: Vinod Koul Signed-off-by: David S. Miller --- drivers/net/dsa/qca8k.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index 7e97e620bd44..a4b6cda38016 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -420,7 +420,7 @@ qca8k_mib_init(struct qca8k_priv *priv) static int qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode) { - u32 reg; + u32 reg, val; switch (port) { case 0: @@ -439,17 +439,9 @@ qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode) */ switch (mode) { case PHY_INTERFACE_MODE_RGMII: - qca8k_write(priv, reg, - QCA8K_PORT_PAD_RGMII_EN | - QCA8K_PORT_PAD_RGMII_TX_DELAY(3) | - QCA8K_PORT_PAD_RGMII_RX_DELAY(3)); - - /* According to the datasheet, RGMII delay is enabled through - * PORT5_PAD_CTRL for all ports, rather than individual port - * registers - */ - qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, - QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); + /* RGMII mode means no delay so don't enable the delay */ + val = QCA8K_PORT_PAD_RGMII_EN; + qca8k_write(priv, reg, val); break; case PHY_INTERFACE_MODE_SGMII: qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); -- cgit v1.2.3 From b0bc10cc8887214c997bfe4f47217b04db4733a2 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Mon, 21 Jan 2019 18:41:38 +0800 Subject: ptp_qoriq: fix interrupt enabling and handling The tmr_tevent register would update event bits no matter tmr_temask bits were set or not. So we should get interrupts by tmr_tevent & tmr_temask, and clean up interrupts in tmr_tevent before enabling them. Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/ptp/ptp_qoriq.c | 62 ++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index fdd49c26bbcc..274321471d50 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -98,11 +98,18 @@ static irqreturn_t isr(int irq, void *priv) struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; struct ptp_clock_event event; u64 ns; - u32 ack = 0, lo, hi, mask, val; + u32 ack = 0, lo, hi, mask, val, irqs; + + spin_lock(&qoriq_ptp->lock); val = qoriq_read(®s->ctrl_regs->tmr_tevent); + mask = qoriq_read(®s->ctrl_regs->tmr_temask); + + spin_unlock(&qoriq_ptp->lock); + + irqs = val & mask; - if (val & ETS1) { + if (irqs & ETS1) { ack |= ETS1; hi = qoriq_read(®s->etts_regs->tmr_etts1_h); lo = qoriq_read(®s->etts_regs->tmr_etts1_l); @@ -113,7 +120,7 @@ static irqreturn_t isr(int irq, void *priv) ptp_clock_event(qoriq_ptp->clock, &event); } - if (val & ETS2) { + if (irqs & ETS2) { ack |= ETS2; hi = qoriq_read(®s->etts_regs->tmr_etts2_h); lo = qoriq_read(®s->etts_regs->tmr_etts2_l); @@ -124,7 +131,7 @@ static irqreturn_t isr(int irq, void *priv) ptp_clock_event(qoriq_ptp->clock, &event); } - if (val & ALM2) { + if (irqs & ALM2) { ack |= ALM2; if (qoriq_ptp->alarm_value) { event.type = PTP_CLOCK_ALARM; @@ -136,13 +143,10 @@ static irqreturn_t isr(int irq, void *priv) ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval; hi = ns >> 32; lo = ns & 0xffffffff; - spin_lock(&qoriq_ptp->lock); qoriq_write(®s->alarm_regs->tmr_alarm2_l, lo); qoriq_write(®s->alarm_regs->tmr_alarm2_h, hi); - spin_unlock(&qoriq_ptp->lock); qoriq_ptp->alarm_value = ns; } else { - qoriq_write(®s->ctrl_regs->tmr_tevent, ALM2); spin_lock(&qoriq_ptp->lock); mask = qoriq_read(®s->ctrl_regs->tmr_temask); mask &= ~ALM2EN; @@ -153,7 +157,7 @@ static irqreturn_t isr(int irq, void *priv) } } - if (val & PP1) { + if (irqs & PP1) { ack |= PP1; event.type = PTP_CLOCK_PPS; ptp_clock_event(qoriq_ptp->clock, &event); @@ -260,7 +264,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; unsigned long flags; - u32 bit, mask; + u32 bit, mask = 0; switch (rq->type) { case PTP_CLK_REQ_EXTTS: @@ -274,32 +278,28 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, default: return -EINVAL; } - spin_lock_irqsave(&qoriq_ptp->lock, flags); - mask = qoriq_read(®s->ctrl_regs->tmr_temask); - if (on) - mask |= bit; - else - mask &= ~bit; - qoriq_write(®s->ctrl_regs->tmr_temask, mask); - spin_unlock_irqrestore(&qoriq_ptp->lock, flags); - return 0; - + break; case PTP_CLK_REQ_PPS: - spin_lock_irqsave(&qoriq_ptp->lock, flags); - mask = qoriq_read(®s->ctrl_regs->tmr_temask); - if (on) - mask |= PP1EN; - else - mask &= ~PP1EN; - qoriq_write(®s->ctrl_regs->tmr_temask, mask); - spin_unlock_irqrestore(&qoriq_ptp->lock, flags); - return 0; - - default: + bit = PP1EN; break; + default: + return -EOPNOTSUPP; } - return -EOPNOTSUPP; + spin_lock_irqsave(&qoriq_ptp->lock, flags); + + mask = qoriq_read(®s->ctrl_regs->tmr_temask); + if (on) { + mask |= bit; + qoriq_write(®s->ctrl_regs->tmr_tevent, bit); + } else { + mask &= ~bit; + } + + qoriq_write(®s->ctrl_regs->tmr_temask, mask); + + spin_unlock_irqrestore(&qoriq_ptp->lock, flags); + return 0; } static const struct ptp_clock_info ptp_qoriq_caps = { -- cgit v1.2.3 From 6815d8b09282c1df8e016bd2fabf25ada6d4462b Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Mon, 21 Jan 2019 18:41:39 +0800 Subject: ptp_qoriq: support external trigger stamp FIFO The external trigger stamp FIFO was introduced as a new feature for QorIQ 1588 timer IP block. This patch is to support it by adding a new dts property "fsl,extts-fifo". Any QorIQ 1588 timer supporting this feature is required to add this property in its dts node. In addition, the FIFO should be cleaned up before enabling external trigger interrupts. Otherwise, there will be interrupts immediately just after enabling external trigger interrupts. Signed-off-by: Yangbo Lu Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/ptp/ptp_qoriq.c | 68 ++++++++++++++++++++++++++++++++++--------- include/linux/fsl/ptp_qoriq.h | 3 ++ 2 files changed, 57 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index 274321471d50..a2e7702db3a4 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -88,6 +88,49 @@ static void set_fipers(struct qoriq_ptp *qoriq_ptp) qoriq_write(®s->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2); } +static int extts_clean_up(struct qoriq_ptp *qoriq_ptp, int index, + bool update_event) +{ + struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_clock_event event; + void __iomem *reg_etts_l; + void __iomem *reg_etts_h; + u32 valid, stat, lo, hi; + + switch (index) { + case 0: + valid = ETS1_VLD; + reg_etts_l = ®s->etts_regs->tmr_etts1_l; + reg_etts_h = ®s->etts_regs->tmr_etts1_h; + break; + case 1: + valid = ETS2_VLD; + reg_etts_l = ®s->etts_regs->tmr_etts2_l; + reg_etts_h = ®s->etts_regs->tmr_etts2_h; + break; + default: + return -EINVAL; + } + + event.type = PTP_CLOCK_EXTTS; + event.index = index; + + do { + lo = qoriq_read(reg_etts_l); + hi = qoriq_read(reg_etts_h); + + if (update_event) { + event.timestamp = ((u64) hi) << 32; + event.timestamp |= lo; + ptp_clock_event(qoriq_ptp->clock, &event); + } + + stat = qoriq_read(®s->ctrl_regs->tmr_stat); + } while (qoriq_ptp->extts_fifo_support && (stat & valid)); + + return 0; +} + /* * Interrupt service routine */ @@ -111,24 +154,12 @@ static irqreturn_t isr(int irq, void *priv) if (irqs & ETS1) { ack |= ETS1; - hi = qoriq_read(®s->etts_regs->tmr_etts1_h); - lo = qoriq_read(®s->etts_regs->tmr_etts1_l); - event.type = PTP_CLOCK_EXTTS; - event.index = 0; - event.timestamp = ((u64) hi) << 32; - event.timestamp |= lo; - ptp_clock_event(qoriq_ptp->clock, &event); + extts_clean_up(qoriq_ptp, 0, true); } if (irqs & ETS2) { ack |= ETS2; - hi = qoriq_read(®s->etts_regs->tmr_etts2_h); - lo = qoriq_read(®s->etts_regs->tmr_etts2_l); - event.type = PTP_CLOCK_EXTTS; - event.index = 1; - event.timestamp = ((u64) hi) << 32; - event.timestamp |= lo; - ptp_clock_event(qoriq_ptp->clock, &event); + extts_clean_up(qoriq_ptp, 1, true); } if (irqs & ALM2) { @@ -278,6 +309,10 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, default: return -EINVAL; } + + if (on) + extts_clean_up(qoriq_ptp, rq->extts.index, false); + break; case PTP_CLK_REQ_PPS: bit = PP1EN; @@ -441,6 +476,11 @@ static int qoriq_ptp_probe(struct platform_device *dev) if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel)) qoriq_ptp->cksel = DEFAULT_CKSEL; + if (of_property_read_bool(node, "fsl,extts-fifo")) + qoriq_ptp->extts_fifo_support = true; + else + qoriq_ptp->extts_fifo_support = false; + if (of_property_read_u32(node, "fsl,tclk-period", &qoriq_ptp->tclk_period) || of_property_read_u32(node, diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index c1f003aadcce..43b4b442f6a4 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -120,6 +120,8 @@ struct qoriq_ptp_registers { /* Bit definitions for the TMR_STAT register */ #define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */ #define STAT_VEC_MASK (0x3f) +#define ETS1_VLD (1<<24) +#define ETS2_VLD (1<<25) /* Bit definitions for the TMR_PRSC register */ #define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */ @@ -141,6 +143,7 @@ struct qoriq_ptp { struct ptp_clock *clock; struct ptp_clock_info caps; struct resource *rsrc; + bool extts_fifo_support; int irq; int phc_index; u64 alarm_interval; /* for periodic alarm */ -- cgit v1.2.3 From 19df7510d5cf077c2e88a7690fb7617e6d341beb Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Mon, 21 Jan 2019 18:41:42 +0800 Subject: ptp: add debugfs support for ptp_qoriq This patch is to add debugfs support for ptp_qoriq. Current debugfs supports to control fiper1/fiper2 loopback mode. If the loopback mode is enabled, the fiper1/fiper2 pulse is looped back into trigger1/ trigger2 input. This is very useful for validating hardware and driver without external hardware. Below is an example to enable fiper1 loopback. echo 1 > /sys/kernel/debug/2d10e00.ptp_clock/fiper1-loopback Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/ptp/Kconfig | 2 +- drivers/ptp/Makefile | 4 +- drivers/ptp/ptp_qoriq.c | 3 ++ drivers/ptp/ptp_qoriq_debugfs.c | 101 ++++++++++++++++++++++++++++++++++++++++ include/linux/fsl/ptp_qoriq.h | 12 +++++ 5 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 drivers/ptp/ptp_qoriq_debugfs.c (limited to 'drivers') diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index d137c480db46..aeb4a8b2e0af 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -53,7 +53,7 @@ config PTP_1588_CLOCK_QORIQ packets using the SO_TIMESTAMPING API. To compile this driver as a module, choose M here: the module - will be called ptp_qoriq. + will be called ptp-qoriq. config PTP_1588_CLOCK_IXP46X tristate "Intel IXP46x as PTP clock" diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile index 19efa9cfa950..677d1d178a3e 100644 --- a/drivers/ptp/Makefile +++ b/drivers/ptp/Makefile @@ -9,4 +9,6 @@ obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_dte.o obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o obj-$(CONFIG_PTP_1588_CLOCK_PCH) += ptp_pch.o obj-$(CONFIG_PTP_1588_CLOCK_KVM) += ptp_kvm.o -obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp_qoriq.o +obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp-qoriq.o +ptp-qoriq-y += ptp_qoriq.o +ptp-qoriq-$(CONFIG_DEBUG_FS) += ptp_qoriq_debugfs.o diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index a2e7702db3a4..43416b2e8a13 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -471,6 +471,7 @@ static int qoriq_ptp_probe(struct platform_device *dev) err = -EINVAL; + qoriq_ptp->dev = &dev->dev; qoriq_ptp->caps = ptp_qoriq_caps; if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel)) @@ -572,6 +573,7 @@ static int qoriq_ptp_probe(struct platform_device *dev) } qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock); + ptp_qoriq_create_debugfs(qoriq_ptp); platform_set_drvdata(dev, qoriq_ptp); return 0; @@ -597,6 +599,7 @@ static int qoriq_ptp_remove(struct platform_device *dev) qoriq_write(®s->ctrl_regs->tmr_temask, 0); qoriq_write(®s->ctrl_regs->tmr_ctrl, 0); + ptp_qoriq_remove_debugfs(qoriq_ptp); ptp_clock_unregister(qoriq_ptp->clock); iounmap(qoriq_ptp->base); release_resource(qoriq_ptp->rsrc); diff --git a/drivers/ptp/ptp_qoriq_debugfs.c b/drivers/ptp/ptp_qoriq_debugfs.c new file mode 100644 index 000000000000..d904332b240d --- /dev/null +++ b/drivers/ptp/ptp_qoriq_debugfs.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright 2019 NXP + */ +#include +#include +#include + +static int ptp_qoriq_fiper1_lpbk_get(void *data, u64 *val) +{ + struct qoriq_ptp *qoriq_ptp = data; + struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + u32 ctrl; + + ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); + *val = ctrl & PP1L ? 1 : 0; + + return 0; +} + +static int ptp_qoriq_fiper1_lpbk_set(void *data, u64 val) +{ + struct qoriq_ptp *qoriq_ptp = data; + struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + u32 ctrl; + + ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); + if (val == 0) + ctrl &= ~PP1L; + else + ctrl |= PP1L; + + qoriq_write(®s->ctrl_regs->tmr_ctrl, ctrl); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(ptp_qoriq_fiper1_fops, ptp_qoriq_fiper1_lpbk_get, + ptp_qoriq_fiper1_lpbk_set, "%llu\n"); + +static int ptp_qoriq_fiper2_lpbk_get(void *data, u64 *val) +{ + struct qoriq_ptp *qoriq_ptp = data; + struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + u32 ctrl; + + ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); + *val = ctrl & PP2L ? 1 : 0; + + return 0; +} + +static int ptp_qoriq_fiper2_lpbk_set(void *data, u64 val) +{ + struct qoriq_ptp *qoriq_ptp = data; + struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + u32 ctrl; + + ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); + if (val == 0) + ctrl &= ~PP2L; + else + ctrl |= PP2L; + + qoriq_write(®s->ctrl_regs->tmr_ctrl, ctrl); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(ptp_qoriq_fiper2_fops, ptp_qoriq_fiper2_lpbk_get, + ptp_qoriq_fiper2_lpbk_set, "%llu\n"); + +void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp) +{ + struct dentry *root; + + root = debugfs_create_dir(dev_name(qoriq_ptp->dev), NULL); + if (IS_ERR(root)) + return; + if (!root) + goto err_root; + + qoriq_ptp->debugfs_root = root; + + if (!debugfs_create_file("fiper1-loopback", 0600, root, qoriq_ptp, + &ptp_qoriq_fiper1_fops)) + goto err_node; + if (!debugfs_create_file("fiper2-loopback", 0600, root, qoriq_ptp, + &ptp_qoriq_fiper2_fops)) + goto err_node; + return; + +err_node: + debugfs_remove_recursive(root); + qoriq_ptp->debugfs_root = NULL; +err_root: + dev_err(qoriq_ptp->dev, "failed to initialize debugfs\n"); +} + +void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp) +{ + debugfs_remove_recursive(qoriq_ptp->debugfs_root); + qoriq_ptp->debugfs_root = NULL; +} diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index 43b4b442f6a4..94e9797e434c 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -143,6 +143,8 @@ struct qoriq_ptp { struct ptp_clock *clock; struct ptp_clock_info caps; struct resource *rsrc; + struct dentry *debugfs_root; + struct device *dev; bool extts_fifo_support; int irq; int phc_index; @@ -169,4 +171,14 @@ static inline void qoriq_write(unsigned __iomem *addr, u32 val) iowrite32be(val, addr); } +#ifdef CONFIG_DEBUG_FS +void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp); +void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp); +#else +static inline void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp) +{ } +static inline void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp) +{ } +#endif + #endif -- cgit v1.2.3 From 95eb7882dfdde9642362586a858734c233335a95 Mon Sep 17 00:00:00 2001 From: Vishal Kulkarni Date: Mon, 21 Jan 2019 17:12:11 +0530 Subject: cxgb4/cxgb4vf: Link management changes 1) Speed should be supported by Physical Port Capabilities. 2) report Forward Error Correction mode which are available. 3) Added few comments. Signed-off-by: Casey Leedom Signed-off-by: Vishal Kulkarni Signed-off-by: Arjun Vynipadath Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 24 ++++++----- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 47 ++++++++++++++++++++-- drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c | 6 ++- 3 files changed, 63 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index d07230c892a5..796043544fc3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -446,8 +446,10 @@ static void fw_caps_to_lmm(enum fw_port_type port_type, unsigned long *link_mode_mask) { #define SET_LMM(__lmm_name) \ - __set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \ - link_mode_mask) + do { \ + __set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \ + link_mode_mask); \ + } while (0) #define FW_CAPS_TO_LMM(__fw_name, __lmm_name) \ do { \ @@ -541,7 +543,7 @@ static void fw_caps_to_lmm(enum fw_port_type port_type, case FW_PORT_TYPE_CR4_QSFP: SET_LMM(FIBRE); FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full); - FW_CAPS_TO_LMM(SPEED_10G, 10000baseSR_Full); + FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full); FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full); FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full); FW_CAPS_TO_LMM(SPEED_50G, 50000baseCR2_Full); @@ -552,6 +554,13 @@ static void fw_caps_to_lmm(enum fw_port_type port_type, break; } + if (fw_caps & FW_PORT_CAP32_FEC_V(FW_PORT_CAP32_FEC_M)) { + FW_CAPS_TO_LMM(FEC_RS, FEC_RS); + FW_CAPS_TO_LMM(FEC_BASER_RS, FEC_BASER); + } else { + SET_LMM(FEC_NONE); + } + FW_CAPS_TO_LMM(ANEG, Autoneg); FW_CAPS_TO_LMM(802_3_PAUSE, Pause); FW_CAPS_TO_LMM(802_3_ASM_DIR, Asym_Pause); @@ -679,18 +688,15 @@ static int set_link_ksettings(struct net_device *dev, base->autoneg == AUTONEG_DISABLE) { fw_caps = speed_to_fw_caps(base->speed); - /* Must only specify a single speed which must be supported - * as part of the Physical Port Capabilities. - */ - if ((fw_caps & (fw_caps - 1)) != 0 || - !(lc->pcaps & fw_caps)) + /* Speed must be supported by Physical Port Capabilities. */ + if (!(lc->pcaps & fw_caps)) return -EINVAL; lc->speed_caps = fw_caps; lc->acaps = fw_caps; } else { fw_caps = - lmm_to_fw_caps(link_ksettings->link_modes.advertising); + lmm_to_fw_caps(link_ksettings->link_modes.advertising); if (!(lc->pcaps & fw_caps)) return -EINVAL; lc->speed_caps = 0; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 2b03f6187a24..c5e5466ee38b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -4105,6 +4105,9 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec) * @mbox: the Firmware Mailbox to use * @port: the Port ID * @lc: the Port's Link Configuration + * @sleep_ok: if true we may sleep while awaiting command completion + * @timeout: time to wait for command to finish before timing out + * (negative implies @sleep_ok=false) * * Set up a port's MAC and PHY according to a desired link configuration. * - If the PHY can auto-negotiate first decide what to advertise, then @@ -4124,6 +4127,7 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox, int ret; fw_mdi = (FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO) & lc->pcaps); + /* Convert driver coding of Pause Frame Flow Control settings into the * Firmware's API. */ @@ -4143,8 +4147,13 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox, fw_fec = cc_to_fwcap_fec(cc_fec); /* Figure out what our Requested Port Capabilities are going to be. + * Note parallel structure in t4_handle_get_port_info() and + * init_link_config(). */ if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) { + if (lc->autoneg == AUTONEG_ENABLE) + return -EINVAL; + rcap = lc->acaps | fw_fc | fw_fec; lc->fc = lc->requested_fc & ~PAUSE_AUTONEG; lc->fec = cc_fec; @@ -4156,7 +4165,11 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox, rcap = lc->acaps | fw_fc | fw_fec | fw_mdi; } - /* Note that older Firmware doesn't have FW_PORT_CAP32_FORCE_PAUSE, so + /* Some Requested Port Capabilities are trivially wrong if they exceed + * the Physical Port Capabilities. We can check that here and provide + * moderately useful feedback in the system log. + * + * Note that older Firmware doesn't have FW_PORT_CAP32_FORCE_PAUSE, so * we need to exclude this from this check in order to maintain * compatibility ... */ @@ -4185,6 +4198,13 @@ int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox, ret = t4_wr_mbox_meat_timeout(adapter, mbox, &cmd, sizeof(cmd), NULL, sleep_ok, timeout); + + /* Unfortunately, even if the Requested Port Capabilities "fit" within + * the Physical Port Capabilities, some combinations of features may + * still not be leagal. For example, 40Gb/s and Reed-Solomon Forward + * Error Correction. So if the Firmware rejects the L1 Configure + * request, flag that here. + */ if (ret) { dev_err(adapter->pdev_dev, "Requested Port Capabilities %#x rejected, error %d\n", @@ -8461,6 +8481,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) fc = fwcap_to_cc_pause(linkattr); speed = fwcap_to_speed(linkattr); + /* Reset state for communicating new Transceiver Module status and + * whether the OS-dependent layer wants us to redo the current + * "sticky" L1 Configure Link Parameters. + */ lc->new_module = false; lc->redo_l1cfg = false; @@ -8497,9 +8521,15 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) */ pi->port_type = port_type; + /* Record new Module Type information. + */ pi->mod_type = mod_type; + /* Let the OS-dependent layer know if we have a new + * Transceiver Module inserted. + */ lc->new_module = t4_is_inserted_mod_type(mod_type); + t4_os_portmod_changed(adapter, pi->port_id); } @@ -8507,8 +8537,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) fc != lc->fc || fec != lc->fec) { /* something changed */ if (!link_ok && lc->link_ok) { lc->link_down_rc = linkdnrc; - dev_warn(adapter->pdev_dev, "Port %d link down, reason: %s\n", - pi->tx_chan, t4_link_down_rc_str(linkdnrc)); + dev_warn_ratelimited(adapter->pdev_dev, + "Port %d link down, reason: %s\n", + pi->tx_chan, + t4_link_down_rc_str(linkdnrc)); } lc->link_ok = link_ok; lc->speed = speed; @@ -8518,6 +8550,11 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) lc->lpacaps = lpacaps; lc->acaps = acaps & ADVERT_MASK; + /* If we're not physically capable of Auto-Negotiation, note + * this as Auto-Negotiation disabled. Otherwise, we track + * what Auto-Negotiation settings we have. Note parallel + * structure in t4_link_l1cfg_core() and init_link_config(). + */ if (!(lc->acaps & FW_PORT_CAP32_ANEG)) { lc->autoneg = AUTONEG_DISABLE; } else if (lc->acaps & FW_PORT_CAP32_ANEG) { @@ -8535,6 +8572,10 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) t4_os_link_changed(adapter, pi->port_id, link_ok); } + /* If we have a new Transceiver Module and the OS-dependent code has + * told us that it wants us to redo whatever "sticky" L1 Configuration + * Link Parameters are set, do that now. + */ if (lc->new_module && lc->redo_l1cfg) { struct link_config old_lc; int ret; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c index 5b8c08cf523f..84dff74ca9cd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c @@ -2005,8 +2005,10 @@ static void t4vf_handle_get_port_info(struct port_info *pi, fc != lc->fc || fec != lc->fec) { /* something changed */ if (!link_ok && lc->link_ok) { lc->link_down_rc = linkdnrc; - dev_warn(adapter->pdev_dev, "Port %d link down, reason: %s\n", - pi->port_id, t4vf_link_down_rc_str(linkdnrc)); + dev_warn_ratelimited(adapter->pdev_dev, + "Port %d link down, reason: %s\n", + pi->port_id, + t4vf_link_down_rc_str(linkdnrc)); } lc->link_ok = link_ok; lc->speed = speed; -- cgit v1.2.3 From a2443fd1a54d6ae787157794a2920dd61f50f7f1 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Mon, 21 Jan 2019 19:05:50 +0100 Subject: net: phy: Convert some PHY and MDIO driver files to SPDX headers Where the license text and the MODULE_LICENSE() value agree, convert to using an SPDX header, removing the license text. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/amd.c | 7 +------ drivers/net/phy/aquantia.c | 5 +---- drivers/net/phy/at803x.c | 6 +----- drivers/net/phy/bcm-cygnus.c | 10 +--------- drivers/net/phy/bcm-phy-lib.c | 5 +---- drivers/net/phy/bcm-phy-lib.h | 10 +--------- drivers/net/phy/bcm63xx.c | 6 +----- drivers/net/phy/bcm7xxx.c | 6 +----- drivers/net/phy/broadcom.c | 6 +----- drivers/net/phy/cicada.c | 7 +------ drivers/net/phy/cortina.c | 11 +---------- drivers/net/phy/davicom.c | 7 +------ drivers/net/phy/dp83640.c | 15 +-------------- drivers/net/phy/et1011c.c | 7 +------ drivers/net/phy/fixed_phy.c | 6 +----- drivers/net/phy/icplus.c | 7 +------ drivers/net/phy/intel-xway.c | 11 +---------- drivers/net/phy/lxt.c | 7 +------ drivers/net/phy/marvell.c | 7 +------ drivers/net/phy/marvell10g.c | 1 + drivers/net/phy/mdio-bcm-iproc.c | 1 + drivers/net/phy/mdio-bcm-unimac.c | 6 +----- drivers/net/phy/mdio-boardinfo.c | 6 +----- drivers/net/phy/mdio-i2c.c | 5 +---- drivers/net/phy/mdio-i2c.h | 5 +---- drivers/net/phy/mdio-mux-bcm-iproc.c | 13 +------------ drivers/net/phy/mdio-mux-mmioreg.c | 5 +---- drivers/net/phy/mdio-xgene.c | 14 +------------- drivers/net/phy/mdio-xgene.h | 14 +------------- drivers/net/phy/mdio_bus.c | 7 +------ drivers/net/phy/mdio_device.c | 7 +------ drivers/net/phy/meson-gxl.c | 12 +----------- drivers/net/phy/micrel.c | 6 +----- drivers/net/phy/microchip.c | 14 +------------- drivers/net/phy/mscc.c | 1 + drivers/net/phy/national.c | 7 +------ drivers/net/phy/phy-core.c | 6 +----- drivers/net/phy/phy.c | 7 +------ drivers/net/phy/phy_device.c | 7 +------ drivers/net/phy/phy_led_triggers.c | 14 ++------------ drivers/net/phy/qsemi.c | 7 +------ drivers/net/phy/realtek.c | 7 +------ drivers/net/phy/sfp.c | 1 + drivers/net/phy/smsc.c | 6 +----- drivers/net/phy/spi_ks8995.c | 5 +---- drivers/net/phy/ste10Xp.c | 7 +------ drivers/net/phy/swphy.c | 6 +----- drivers/net/phy/teranetics.c | 5 +---- drivers/net/phy/uPD60620.c | 7 +------ drivers/net/phy/vitesse.c | 9 +-------- drivers/net/phy/xilinx_gmii2rgmii.c | 11 +---------- 51 files changed, 52 insertions(+), 323 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/amd.c b/drivers/net/phy/amd.c index 9d0504f3e3b2..65b4b0960b1e 100644 --- a/drivers/net/phy/amd.c +++ b/drivers/net/phy/amd.c @@ -1,15 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for AMD am79c PHYs * * Author: Heiko Schocher * * Copyright (c) 2011 DENX Software Engineering GmbH - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index beb3309bb0f0..0578fe75d3b6 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for Aquantia PHY * * Author: Shaohui Xie * * Copyright 2015 Freescale Semiconductor, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. */ #include diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 8ff12938ab47..512562084283 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/at803x.c * * Driver for Atheros 803x PHY * * Author: Matus Ujhelyi - * - * 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; either version 2 of the License, or (at your - * option) any later version. */ #include diff --git a/drivers/net/phy/bcm-cygnus.c b/drivers/net/phy/bcm-cygnus.c index e757b09f1889..ab8e12922bf9 100644 --- a/drivers/net/phy/bcm-cygnus.c +++ b/drivers/net/phy/bcm-cygnus.c @@ -1,14 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2015 Broadcom Corporation - * - * 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. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ /* Broadcom Cygnus SoC internal transceivers support. */ diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index e10e7b54ec4b..d6d1efc5907a 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -1,10 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2015-2017 Broadcom * - * 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. - * * This program is distributed "as is" WITHOUT ANY WARRANTY of any * kind, whether express or implied; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h index 81cceaa412fe..17faaefcfd60 100644 --- a/drivers/net/phy/bcm-phy-lib.h +++ b/drivers/net/phy/bcm-phy-lib.h @@ -1,14 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2015 Broadcom Corporation - * - * 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. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #ifndef _LINUX_BCM_PHY_LIB_H diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c index a88dd14a25c0..44e6cff419a0 100644 --- a/drivers/net/phy/bcm63xx.c +++ b/drivers/net/phy/bcm63xx.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Broadcom 63xx SOCs integrated PHYs - * - * 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; either version - * 2 of the License, or (at your option) any later version. */ #include "bcm-phy-lib.h" #include diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index 712224cc442d..b8415f8fae14 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Broadcom BCM7xxx internal transceivers support. * * Copyright (C) 2014-2017 Broadcom - * - * 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; either version - * 2 of the License, or (at your option) any later version. */ #include diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index aa73c5cc5f86..9605d4fe540b 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/broadcom.c * @@ -7,11 +8,6 @@ * Copyright (c) 2006 Maciej W. Rozycki * * Inspired by code written by Amy Fong. - * - * 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; either version - * 2 of the License, or (at your option) any later version. */ #include "bcm-phy-lib.h" diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c index fea61c81bda9..108ed24f8489 100644 --- a/drivers/net/phy/cicada.c +++ b/drivers/net/phy/cicada.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/cicada.c * @@ -6,12 +7,6 @@ * Author: Andy Fleming * * Copyright (c) 2004 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c index 1a4d04afb7f0..c291dc014769 100644 --- a/drivers/net/phy/cortina.c +++ b/drivers/net/phy/cortina.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2017 NXP * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * * CORTINA is a registered trademark of Cortina Systems, Inc. * */ diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c index 97162008f42b..bf39baa7f2c8 100644 --- a/drivers/net/phy/davicom.c +++ b/drivers/net/phy/davicom.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/davicom.c * @@ -6,12 +7,6 @@ * Author: Andy Fleming * * Copyright (c) 2004 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 18b41bc345ab..25ef483bcc24 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for the National Semiconductor DP83640 PHYTER * * Copyright (C) 2010 OMICRON electronics GmbH - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c index 565e49e7f76f..2aa367c04a8e 100644 --- a/drivers/net/phy/et1011c.c +++ b/drivers/net/phy/et1011c.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/et1011c.c * @@ -6,12 +7,6 @@ * Author: Chaithrika U S * * Copyright (c) 2008 Texas Instruments - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index 72d43c88e6ff..47a8cb574c45 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Fixed MDIO bus (MDIO bus emulation with fixed PHYs) * @@ -5,11 +6,6 @@ * Anton Vorontsov * * Copyright (c) 2006-2007 MontaVista Software, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. */ #include diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index 7d5938b87660..ebef8354bc81 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c @@ -1,13 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for ICPlus PHYs * * Copyright (c) 2007 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/intel-xway.c b/drivers/net/phy/intel-xway.c index fc0f5024a29e..02d9713318b6 100644 --- a/drivers/net/phy/intel-xway.c +++ b/drivers/net/phy/intel-xway.c @@ -1,16 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2012 Daniel Schwierzeck * Copyright (C) 2016 Hauke Mehrtens - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c index c8bb29ae1a2a..a93d673baf35 100644 --- a/drivers/net/phy/lxt.c +++ b/drivers/net/phy/lxt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/lxt.c * @@ -6,12 +7,6 @@ * Author: Andy Fleming * * Copyright (c) 2004 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 2e12f982534f..90f44ba8aca7 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/marvell.c * @@ -8,12 +9,6 @@ * Copyright (c) 2004 Freescale Semiconductor, Inc. * * Copyright (c) 2013 Michael Stapelberg - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 82ab6ed3b74e..38cfc923a88a 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Marvell 10G 88x3310 PHY driver * diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c index 46fe1ae919a3..af9b7eae7ce3 100644 --- a/drivers/net/phy/mdio-bcm-iproc.c +++ b/drivers/net/phy/mdio-bcm-iproc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2015 Broadcom Corporation * diff --git a/drivers/net/phy/mdio-bcm-unimac.c b/drivers/net/phy/mdio-bcm-unimac.c index df75efa96a7d..8295bc7c8c20 100644 --- a/drivers/net/phy/mdio-bcm-unimac.c +++ b/drivers/net/phy/mdio-bcm-unimac.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Broadcom UniMAC MDIO bus controller driver * * Copyright (C) 2014-2017 Broadcom - * - * 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; either version 2 of the License, or - * (at your option) any later version. */ #include diff --git a/drivers/net/phy/mdio-boardinfo.c b/drivers/net/phy/mdio-boardinfo.c index 863496fa5d13..d9b54c67ef9f 100644 --- a/drivers/net/phy/mdio-boardinfo.c +++ b/drivers/net/phy/mdio-boardinfo.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * mdio-boardinfo - Collect pre-declarations for MDIO devices - * - * 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; either version 2 of the License, or (at your - * option) any later version. */ #include diff --git a/drivers/net/phy/mdio-i2c.c b/drivers/net/phy/mdio-i2c.c index 6d24fd13ca86..0dce67672548 100644 --- a/drivers/net/phy/mdio-i2c.c +++ b/drivers/net/phy/mdio-i2c.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * MDIO I2C bridge * * Copyright (C) 2015-2016 Russell King * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * * Network PHYs can appear on I2C buses when they are part of SFP module. * This driver exposes these PHYs to the networking PHY code, allowing * our PHY drivers access to these PHYs, and so allowing configuration diff --git a/drivers/net/phy/mdio-i2c.h b/drivers/net/phy/mdio-i2c.h index 889ab57d7f3e..751dab281f57 100644 --- a/drivers/net/phy/mdio-i2c.h +++ b/drivers/net/phy/mdio-i2c.h @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * MDIO I2C bridge * * Copyright (C) 2015 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef MDIO_I2C_H #define MDIO_I2C_H diff --git a/drivers/net/phy/mdio-mux-bcm-iproc.c b/drivers/net/phy/mdio-mux-bcm-iproc.c index 696bdf1e4576..88d409e48c1f 100644 --- a/drivers/net/phy/mdio-mux-bcm-iproc.c +++ b/drivers/net/phy/mdio-mux-bcm-iproc.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright 2016 Broadcom - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2, as - * published by the Free Software Foundation (the "GPL"). - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 (GPLv2) for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 (GPLv2) along with this source code. */ #include #include diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c index 70f6115530af..d1a8780e24d8 100644 --- a/drivers/net/phy/mdio-mux-mmioreg.c +++ b/drivers/net/phy/mdio-mux-mmioreg.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Simple memory-mapped device MDIO MUX driver * * Author: Timur Tabi * * Copyright 2012 Freescale Semiconductor, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. */ #include diff --git a/drivers/net/phy/mdio-xgene.c b/drivers/net/phy/mdio-xgene.c index 07c6048200c6..717cc2a056e8 100644 --- a/drivers/net/phy/mdio-xgene.c +++ b/drivers/net/phy/mdio-xgene.c @@ -1,20 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* Applied Micro X-Gene SoC MDIO Driver * * Copyright (c) 2016, Applied Micro Circuits Corporation * Author: Iyappan Subramanian - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ #include diff --git a/drivers/net/phy/mdio-xgene.h b/drivers/net/phy/mdio-xgene.h index 3c85f3e30baa..b1f5ccb4ad9c 100644 --- a/drivers/net/phy/mdio-xgene.h +++ b/drivers/net/phy/mdio-xgene.h @@ -1,20 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* Applied Micro X-Gene SoC MDIO Driver * * Copyright (c) 2016, Applied Micro Circuits Corporation * Author: Iyappan Subramanian - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . */ #ifndef __MDIO_XGENE_H__ diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 2e53ba3fa2e7..3d313585c9c1 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -1,14 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* MDIO Bus interface * * Author: Andy Fleming * * Copyright (c) 2004 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c index c924700cf37b..887076292e50 100644 --- a/drivers/net/phy/mdio_device.c +++ b/drivers/net/phy/mdio_device.c @@ -1,12 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* Framework for MDIO devices, other than PHYs. * * Copyright (c) 2016 Andrew Lunn - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c index 3ddaf9595697..a238388eb1a5 100644 --- a/drivers/net/phy/meson-gxl.c +++ b/drivers/net/phy/meson-gxl.c @@ -1,20 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Amlogic Meson GXL Internal PHY Driver * * Copyright (C) 2015 Amlogic, Inc. All rights reserved. * Copyright (C) 2016 BayLibre, SAS. All rights reserved. * Author: Neil Armstrong - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * */ #include #include diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 0d62b548ab39..38d5bd877346 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/micrel.c * @@ -8,11 +9,6 @@ * Copyright (c) 2010-2013 Micrel, Inc. * Copyright (c) 2014 Johan Hovold * - * 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; either version 2 of the License, or (at your - * option) any later version. - * * Support : Micrel Phys: * Giga phys: ksz9021, ksz9031, ksz9131 * 100/10 Phys : ksz8001, ksz8721, ksz8737, ksz8041 diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c index 7557bebd5d7f..c6cbb3aa8ae0 100644 --- a/drivers/net/phy/microchip.c +++ b/drivers/net/phy/microchip.c @@ -1,18 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2015 Microchip Technology - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . */ #include #include diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index 3949fe299b18..db50efb30df5 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) /* * Driver for Microsemi VSC85xx PHYs * diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c index 139bed2c8ab4..42282a86b680 100644 --- a/drivers/net/phy/national.c +++ b/drivers/net/phy/national.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/national.c * @@ -7,12 +8,6 @@ * Maintainer: Giuseppe Cavallaro * * Copyright (c) 2008 STMicroelectronics Limited - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index 20fbd5eb56fd..909b3344babf 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Core PHY library, taken from phy.c - * - * 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; either version 2 of the License, or (at your - * option) any later version. */ #include #include diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 745a705a505a..631ed33fe9d9 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* Framework for configuring and reading PHY devices * Based on code in sungem_phy.c and gianfar_phy.c * @@ -5,12 +6,6 @@ * * Copyright (c) 2004 Freescale Semiconductor, Inc. * Copyright (c) 2006, 2007 Maciej W. Rozycki - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 6ccc2c7cc9f6..509d9402fa9a 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1,15 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* Framework for finding and configuring PHYs. * Also contains generic PHY driver * * Author: Andy Fleming * * Copyright (c) 2004 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c index 263385b75bba..b86a4b2116f8 100644 --- a/drivers/net/phy/phy_led_triggers.c +++ b/drivers/net/phy/phy_led_triggers.c @@ -1,15 +1,5 @@ -/* Copyright (C) 2016 National Instruments Corp. - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (C) 2016 National Instruments Corp. */ #include #include #include diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c index cfe2313dbefd..5486f6fb2ab2 100644 --- a/drivers/net/phy/qsemi.c +++ b/drivers/net/phy/qsemi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/qsemi.c * @@ -6,12 +7,6 @@ * Author: Andy Fleming * * Copyright (c) 2004 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index c6010fb1aa0f..75543f9370f3 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/realtek.c * @@ -6,12 +7,6 @@ * Author: Johnson Leung * * Copyright (c) 2004 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include #include diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index fd8bb998ae52..298ab7546929 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include #include #include diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index f9477ff55545..c94d3bfbc772 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/smsc.c * @@ -7,11 +8,6 @@ * * Copyright (c) 2006 Herbert Valerio Riedel * - * 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; either version 2 of the License, or (at your - * option) any later version. - * * Support added for SMSC LAN8187 and LAN8700 by steve.glendinning@shawell.net * */ diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index f17b3441779b..92b64e254b44 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SPI driver for Micrel/Kendin KS8995M and KSZ8864RMN ethernet switches * @@ -5,10 +6,6 @@ * * This file was based on: drivers/spi/at25.c * Copyright (C) 2006 David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/drivers/net/phy/ste10Xp.c b/drivers/net/phy/ste10Xp.c index 33d733684f5b..5b6acf431f98 100644 --- a/drivers/net/phy/ste10Xp.c +++ b/drivers/net/phy/ste10Xp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * drivers/net/phy/ste10Xp.c * @@ -6,12 +7,6 @@ * Author: Giuseppe Cavallaro * * Copyright (c) 2008 STMicroelectronics Limited - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include diff --git a/drivers/net/phy/swphy.c b/drivers/net/phy/swphy.c index 34f58f2349e9..b9743569e431 100644 --- a/drivers/net/phy/swphy.c +++ b/drivers/net/phy/swphy.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Software PHY emulation * @@ -7,11 +8,6 @@ * Anton Vorontsov * * Copyright (c) 2006-2007 MontaVista Software, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. */ #include #include diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index 91247182bc52..145c328b00fa 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for Teranetics PHY * * Author: Shaohui Xie * * Copyright 2015 Freescale Semiconductor, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. */ #include diff --git a/drivers/net/phy/uPD60620.c b/drivers/net/phy/uPD60620.c index 1e4fc42e4629..219fc7cdc2b3 100644 --- a/drivers/net/phy/uPD60620.c +++ b/drivers/net/phy/uPD60620.c @@ -1,13 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for the Renesas PHY uPD60620. * * Copyright (C) 2015 Softing Industrial Automation GmbH - * - * 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; either version 2 of the License, or - * (at your option) any later version. - * */ #include diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 0646af458f6a..dc0dd87a6694 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -1,15 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Vitesse PHYs * * Author: Kriston Carson - * - * Copyright (c) 2005, 2009, 2011 Freescale Semiconductor, Inc. - * - * 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; either version 2 of the License, or (at your - * option) any later version. - * */ #include diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c index 74a8782313cf..ebf419dc7307 100644 --- a/drivers/net/phy/xilinx_gmii2rgmii.c +++ b/drivers/net/phy/xilinx_gmii2rgmii.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* Xilinx GMII2RGMII Converter driver * * Copyright (C) 2016 Xilinx, Inc. @@ -8,16 +9,6 @@ * * Description: * This driver is developed for Xilinx GMII2RGMII Converter - * - * 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, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include #include -- cgit v1.2.3 From 84bfe20980b819baa731f6020172e923891ff449 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Mon, 21 Jan 2019 19:05:51 +0100 Subject: net: phy: Remove redundent License text when SPDX header is present The SPDX header makes any license text redundent. Remove it. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/bcm-phy-lib.c | 5 ----- drivers/net/phy/mdio-bcm-iproc.c | 9 --------- 2 files changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index d6d1efc5907a..a75642051b8b 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -1,11 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2015-2017 Broadcom - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include "bcm-phy-lib.h" diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c index af9b7eae7ce3..7d0f388d8db8 100644 --- a/drivers/net/phy/mdio-bcm-iproc.c +++ b/drivers/net/phy/mdio-bcm-iproc.c @@ -1,15 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2015 Broadcom Corporation - * - * 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. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include -- cgit v1.2.3 From 5f85757572e17f11b956e77405289babf1f234e3 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Mon, 21 Jan 2019 19:10:19 +0100 Subject: net: phy: Fixup GPLv2 SPDX tags based on license text A few PHY drivers have the GPLv2 license text. They then either have a MODULE_LICENSE() of GPLv2+, or an SPDX tag of GPLv2+. Since the license text is much easier to understand than either the SPDX tag or the MODULE_LICENSE, use it as the definitive source of the licence, and fixup with others when there are contradictions. Cc: Russell King Cc: Jonas Jensen Cc: Laurent Pinchart Cc: Paulius Zaleckas Cc: Scott Wood Acked-by: Maxime Ripard Acked-by: Andrew F. Davis Acked-by: Dan Murphy Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/dp83822.c | 12 ++---------- drivers/net/phy/dp83848.c | 12 ++---------- drivers/net/phy/dp83867.c | 12 ++---------- drivers/net/phy/mdio-bitbang.c | 7 ++----- drivers/net/phy/mdio-gpio.c | 7 ++----- drivers/net/phy/mdio-moxart.c | 7 ++----- drivers/net/phy/mdio-sun4i.c | 7 ++----- drivers/net/phy/phylink.c | 7 ++----- 8 files changed, 16 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c index 24c7f149f3e6..bbd8c22067f3 100644 --- a/drivers/net/phy/dp83822.c +++ b/drivers/net/phy/dp83822.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for the Texas Instruments DP83822 PHY * * Copyright (C) 2017 Texas Instruments Inc. - * - * 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; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include @@ -338,4 +330,4 @@ MODULE_DEVICE_TABLE(mdio, dp83822_tbl); MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver"); MODULE_AUTHOR("Dan Murphy @@ -133,4 +125,4 @@ module_phy_driver(dp83848_driver); MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver"); MODULE_AUTHOR("Andrew F. Davis "); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index da6a67d47ce9..8a8d9f606b3e 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for the Texas Instruments DP83867 PHY * * Copyright (C) 2015 Texas Instruments Inc. - * - * 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; either version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include @@ -357,4 +349,4 @@ MODULE_DEVICE_TABLE(mdio, dp83867_tbl); MODULE_DESCRIPTION("Texas Instruments DP83867 PHY driver"); MODULE_AUTHOR("Dan Murphy - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. */ #include @@ -232,4 +229,4 @@ void free_mdio_bitbang(struct mii_bus *bus) } EXPORT_SYMBOL(free_mdio_bitbang); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index ea9a0e339778..1b00235d7dc5 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * GPIO based MDIO bitbang driver. * Supports OpenFirmware. @@ -14,10 +15,6 @@ * * 2005 (c) MontaVista Software, Inc. * Vitaly Bordug - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. */ #include @@ -216,5 +213,5 @@ module_platform_driver(mdio_gpio_driver); MODULE_ALIAS("platform:mdio-gpio"); MODULE_AUTHOR("Laurent Pinchart, Paulius Zaleckas"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Generic driver for MDIO bus emulation using GPIO"); diff --git a/drivers/net/phy/mdio-moxart.c b/drivers/net/phy/mdio-moxart.c index 5bb56d126693..af3910fe8ec7 100644 --- a/drivers/net/phy/mdio-moxart.c +++ b/drivers/net/phy/mdio-moxart.c @@ -1,10 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* MOXA ART Ethernet (RTL8201CP) MDIO interface driver * * Copyright (C) 2013 Jonas Jensen - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. */ #include @@ -190,4 +187,4 @@ module_platform_driver(moxart_mdio_driver); MODULE_DESCRIPTION("MOXA ART MDIO interface driver"); MODULE_AUTHOR("Jonas Jensen "); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-sun4i.c b/drivers/net/phy/mdio-sun4i.c index 6425ce04d3f9..20ffd8fb79ce 100644 --- a/drivers/net/phy/mdio-sun4i.c +++ b/drivers/net/phy/mdio-sun4i.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Allwinner EMAC MDIO interface driver * @@ -6,10 +7,6 @@ * * Based on the Linux driver provided by Allwinner: * Copyright (C) 1997 Sten Wang - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. */ #include @@ -179,4 +176,4 @@ module_platform_driver(sun4i_mdio_driver); MODULE_DESCRIPTION("Allwinner EMAC MDIO interface driver"); MODULE_AUTHOR("Maxime Ripard "); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index e7becc7379d7..7d9910da5018 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * phylink models the MAC to optional PHY connection, supporting * technologies such as SFP cages where the PHY is hot-pluggable. * * Copyright (C) 2015 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include #include @@ -1697,4 +1694,4 @@ void phylink_helper_basex_speed(struct phylink_link_state *state) } EXPORT_SYMBOL_GPL(phylink_helper_basex_speed); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 8bbe833a65209632f96931415070bc3a490f2dc9 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Mon, 21 Jan 2019 19:34:53 +0100 Subject: net: phy: Add SDPX tag based on COPYING file Some of the PHY and MDIO drivers refer to the COPYING file in the main directory of this archive. This is the main license for Linux, thus GPLv2 plus syscall extension. Fixup the MODULE_LICENSE() where needed and add an SDPX header for GPLv2. Cc: David Daney Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/bcm87xx.c | 7 ++----- drivers/net/phy/mdio-cavium.c | 7 ++----- drivers/net/phy/mdio-cavium.h | 5 +---- drivers/net/phy/mdio-mux-gpio.c | 7 ++----- drivers/net/phy/mdio-mux.c | 7 ++----- drivers/net/phy/mdio-octeon.c | 7 ++----- drivers/net/phy/mdio-thunder.c | 7 ++----- 7 files changed, 13 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c index a271239748f2..f0c0eefe2202 100644 --- a/drivers/net/phy/bcm87xx.c +++ b/drivers/net/phy/bcm87xx.c @@ -1,8 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * * Copyright (C) 2011 - 2012 Cavium, Inc. */ @@ -221,4 +218,4 @@ static struct phy_driver bcm87xx_driver[] = { module_phy_driver(bcm87xx_driver); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-cavium.c b/drivers/net/phy/mdio-cavium.c index 6df2fa755bb4..1afd6fc1a351 100644 --- a/drivers/net/phy/mdio-cavium.c +++ b/drivers/net/phy/mdio-cavium.c @@ -1,8 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * * Copyright (C) 2009-2016 Cavium, Inc. */ @@ -150,4 +147,4 @@ EXPORT_SYMBOL(cavium_mdiobus_write); MODULE_DESCRIPTION("Common code for OCTEON and Thunder MDIO bus drivers"); MODULE_AUTHOR("David Daney"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-cavium.h b/drivers/net/phy/mdio-cavium.h index 4bccd45d24e2..ed5f9bb5448d 100644 --- a/drivers/net/phy/mdio-cavium.h +++ b/drivers/net/phy/mdio-cavium.h @@ -1,8 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * * Copyright (C) 2009-2016 Cavium, Inc. */ diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c index fe34576262bd..6c8960df43b0 100644 --- a/drivers/net/phy/mdio-mux-gpio.c +++ b/drivers/net/phy/mdio-mux-gpio.c @@ -1,8 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * * Copyright (C) 2011, 2012 Cavium, Inc. */ @@ -103,4 +100,4 @@ module_platform_driver(mdio_mux_gpio_driver); MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR("David Daney"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 0a86f1e4c02f..6a1d3540210b 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -1,8 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * * Copyright (C) 2011, 2012 Cavium, Inc. */ @@ -210,4 +207,4 @@ EXPORT_SYMBOL_GPL(mdio_mux_uninit); MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_AUTHOR("David Daney"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c index ab6914f8bd50..8327382aa568 100644 --- a/drivers/net/phy/mdio-octeon.c +++ b/drivers/net/phy/mdio-octeon.c @@ -1,8 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * * Copyright (C) 2009-2015 Cavium, Inc. */ @@ -122,4 +119,4 @@ module_platform_driver(octeon_mdiobus_driver); MODULE_DESCRIPTION("Cavium OCTEON MDIO bus driver"); MODULE_AUTHOR("David Daney"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/mdio-thunder.c b/drivers/net/phy/mdio-thunder.c index 1546f6398831..b6128ae7f14f 100644 --- a/drivers/net/phy/mdio-thunder.c +++ b/drivers/net/phy/mdio-thunder.c @@ -1,8 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * * Copyright (C) 2009-2016 Cavium, Inc. */ @@ -151,4 +148,4 @@ static struct pci_driver thunder_mdiobus_driver = { module_pci_driver(thunder_mdiobus_driver); MODULE_DESCRIPTION("Cavium ThunderX MDIO bus driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From f116465385344294edda66970734a26f5dd59a93 Mon Sep 17 00:00:00 2001 From: Sudarsana Reddy Kalluru Date: Tue, 22 Jan 2019 03:05:20 -0800 Subject: bnx2x: Bump up driver version to 1.713.36 Recently, there were bunch of fixes to bnx2x driver, the code is now aligned to out-of-box driver version 1.713.36. This patch updates bnx2x driver version to 1.713.36. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 03d131f777bc..6026b53137aa 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -32,7 +32,7 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.712.30-0" +#define DRV_MODULE_VERSION "1.713.36-0" #define DRV_MODULE_RELDATE "2014/02/10" #define BNX2X_BC_VER 0x040200 -- cgit v1.2.3 From d422a286e181a36ce97fc8beb087e45ce1cff382 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 23 Jan 2019 01:29:55 -0600 Subject: net: 3c509: mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/net/ethernet/3com/3c509.c:1265:8: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/ethernet/3com/3c509.c:1271:8: warning: this statement may fall through [-Wimplicit-fallthrough=] Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c509.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index b223769d6a5e..3da97996bdf3 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -1266,12 +1266,14 @@ el3_up(struct net_device *dev) pr_cont("Forcing 3c5x9b full-duplex mode"); break; } + /* fall through */ case 8: /* set full-duplex mode based on eeprom config setting */ if ((sw_info & 0x000f) && (sw_info & 0x8000)) { pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)"); break; } + /* fall through */ default: /* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */ pr_cont("Setting 3c5x9/3c5x9B half-duplex mode"); -- cgit v1.2.3 From 015496c43f399675589132d3dd48a55d8c5fc5ba Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 23 Jan 2019 01:41:19 -0600 Subject: broadcom: Mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c:6336:6: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c:2231:6: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/ethernet/broadcom/tg3.c:722:6: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/ethernet/broadcom/tg3.c:783:6: warning: this statement may fall through [-Wimplicit-fallthrough=] Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Gustavo A. R. Silva Acked-by: Sudarsana Kalluru Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 2 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 2 +- drivers/net/ethernet/broadcom/tg3.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 29738dfa878c..d581d0ae6584 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -6335,7 +6335,7 @@ int bnx2x_set_led(struct link_params *params, */ if (!vars->link_up) break; - /* else: fall through */ + /* fall through */ case LED_MODE_ON: if (((params->phy[EXT_PHY1].type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) || diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index c835f6c7ecd0..c97b642e6537 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -2230,7 +2230,7 @@ int bnx2x_vf_free(struct bnx2x *bp, struct bnx2x_virtf *vf) rc = bnx2x_vf_close(bp, vf); if (rc) goto op_err; - /* Fallthrough to release resources */ + /* Fall through - to release resources */ case VF_ACQUIRED: DP(BNX2X_MSG_IOV, "about to free resources\n"); bnx2x_vf_free_resc(bp, vf); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index b1627dd5f2fd..328373e0578f 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -721,7 +721,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) case TG3_APE_LOCK_GPIO: if (tg3_asic_rev(tp) == ASIC_REV_5761) return 0; - /* else: fall through */ + /* fall through */ case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: if (!tp->pci_fn) @@ -782,7 +782,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) case TG3_APE_LOCK_GPIO: if (tg3_asic_rev(tp) == ASIC_REV_5761) return; - /* else: fall through */ + /* fall through */ case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: if (!tp->pci_fn) -- cgit v1.2.3 From 9536d6ed156feda000a2c1660f98b01b7704d6dc Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 23 Jan 2019 01:53:28 -0600 Subject: bna: Mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/net/ethernet/brocade/bna/bfa_ioc.c:790:3: warning: this statement may fall through [-Wimplicit-fallthrough=] drivers/net/ethernet/brocade/bna/bfa_ioc.c:860:3: warning: this statement may fall through [-Wimplicit-fallthrough=] Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough Signed-off-by: Gustavo A. R. Silva Signed-off-by: Gustavo A. R. Silva Acked-by: Sudarsana Kalluru Signed-off-by: David S. Miller --- drivers/net/ethernet/brocade/bna/bfa_ioc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index a36e38676640..cbc9175d74c5 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -788,9 +788,8 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event) case IOCPF_E_INITFAIL: del_timer(&ioc->iocpf_timer); - /* - * !!! fall through !!! - */ + /* fall through */ + case IOCPF_E_TIMEOUT: bfa_nw_ioc_hw_sem_release(ioc); if (event == IOCPF_E_TIMEOUT) @@ -858,9 +857,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event) case IOCPF_E_FAIL: del_timer(&ioc->iocpf_timer); - /* - * !!! fall through !!! - */ + /* fall through*/ case IOCPF_E_TIMEOUT: bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); -- cgit v1.2.3 From ed35da4fce1d203d7dc56b371069d53b17063d70 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 23 Jan 2019 01:59:12 -0600 Subject: qed: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/net/ethernet/qlogic/qed/qed_cxt.c:2126:4: warning: this statement may fall through [-Wimplicit-fallthrough=] Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_cxt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index c2ad405b2f50..35c9f484eb9f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -2129,6 +2129,7 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn, u32 rdma_tasks) rdma_tasks); /* no need for break since RoCE coexist with Ethernet */ } + /* fall through */ case QED_PCI_ETH: { struct qed_eth_pf_params *p_params = -- cgit v1.2.3 From 482dcf7df7e9be692b57159da414491389f93d03 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 23 Jan 2019 02:05:11 -0600 Subject: net/mlx4: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/net/ethernet/mellanox/mlx4/eq.c: In function ‘mlx4_eq_int’: drivers/net/ethernet/mellanox/mlx4/mlx4.h:219:5: warning: this statement may fall through [-Wimplicit-fallthrough=] if (mlx4_debug_level) \ ^ drivers/net/ethernet/mellanox/mlx4/eq.c:558:4: note: in expansion of macro ‘mlx4_dbg’ mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n", ^~~~~~~~ drivers/net/ethernet/mellanox/mlx4/eq.c:561:3: note: here case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/eq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 4953c852c247..2f4201023836 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -558,6 +558,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n", __func__, be32_to_cpu(eqe->event.srq.srqn), eq->eqn); + /* fall through */ case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: if (mlx4_is_master(dev)) { /* forward only to slave owning the SRQ */ -- cgit v1.2.3 From eff42aa9986ec2c4ca7d778f2f04556f5b9e722b Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 23 Jan 2019 14:32:55 +0000 Subject: mlxsw: spectrum: Expose functions to create and destroy underlay RIF In Spectrum-2, instead of providing the ID of the virtual router (VR) where NVE underlay lookups will occur as in Spectrum-1, the ID of a router interface (RIF) in this VR is required. Expose functions to create and destroy such a RIF. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 3 +++ .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 28 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 1fa5c81b209f..9384b108c8c2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -507,6 +507,9 @@ void mlxsw_sp_router_nve_demote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id, const union mlxsw_sp_l3addr *ul_sip); int mlxsw_sp_router_tb_id_vr_id(struct mlxsw_sp *mlxsw_sp, u32 tb_id, u16 *vr_id); +int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id, + u16 *ul_rif_index); +void mlxsw_sp_router_ul_rif_put(struct mlxsw_sp *mlxsw_sp, u16 ul_rif_index); /* spectrum_kvdl.c */ enum mlxsw_sp_kvdl_entry_type { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 0949404a28e5..230e1f6e192b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -7595,6 +7595,34 @@ static void mlxsw_sp_ul_rif_put(struct mlxsw_sp_rif *ul_rif) mlxsw_sp_vr_put(mlxsw_sp, vr); } +int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id, + u16 *ul_rif_index) +{ + struct mlxsw_sp_rif *ul_rif; + + ASSERT_RTNL(); + + ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL); + if (IS_ERR(ul_rif)) + return PTR_ERR(ul_rif); + *ul_rif_index = ul_rif->rif_index; + + return 0; +} + +void mlxsw_sp_router_ul_rif_put(struct mlxsw_sp *mlxsw_sp, u16 ul_rif_index) +{ + struct mlxsw_sp_rif *ul_rif; + + ASSERT_RTNL(); + + ul_rif = mlxsw_sp->router->rifs[ul_rif_index]; + if (WARN_ON(!ul_rif)) + return; + + mlxsw_sp_ul_rif_put(ul_rif); +} + static int mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif) { -- cgit v1.2.3 From 3179a56f6ed9341c3f7ca451039b9d2f99c48ab4 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 23 Jan 2019 14:32:56 +0000 Subject: mlxsw: spectrum_nve: Breakout common code to a common function The configuration of a VXLAN tunnel in Spectrum-1 and Spectrum-2 is largely the same. To avoid code duplication, breakout the common parts to a common function that can be invoked from the ASIC-specific code. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c | 30 ++++++++++++++-------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c index 9ba0b83bd949..60f88e5642e1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c @@ -112,13 +112,30 @@ static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl); } +static void +mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl, + const struct mlxsw_sp_nve_config *config) +{ + u8 udp_sport; + + mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, true, + config->ttl); + /* VxLAN driver's default UDP source port range is 32768 (0x8000) + * to 60999 (0xee47). Set the upper 8 bits of the UDP source port + * to a random number between 0x80 and 0xee + */ + get_random_bytes(&udp_sport, sizeof(udp_sport)); + udp_sport = (udp_sport % (0xee - 0x80 + 1)) + 0x80; + mlxsw_reg_tngcr_nve_udp_sport_prefix_set(tngcr_pl, udp_sport); + mlxsw_reg_tngcr_usipv4_set(tngcr_pl, be32_to_cpu(config->ul_sip.addr4)); +} + static int mlxsw_sp1_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_nve_config *config) { char tngcr_pl[MLXSW_REG_TNGCR_LEN]; u16 ul_vr_id; - u8 udp_sport; int err; err = mlxsw_sp_router_tb_id_vr_id(mlxsw_sp, config->ul_tb_id, @@ -126,18 +143,9 @@ mlxsw_sp1_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp, if (err) return err; - mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, true, - config->ttl); - /* VxLAN driver's default UDP source port range is 32768 (0x8000) - * to 60999 (0xee47). Set the upper 8 bits of the UDP source port - * to a random number between 0x80 and 0xee - */ - get_random_bytes(&udp_sport, sizeof(udp_sport)); - udp_sport = (udp_sport % (0xee - 0x80 + 1)) + 0x80; - mlxsw_reg_tngcr_nve_udp_sport_prefix_set(tngcr_pl, udp_sport); + mlxsw_sp_nve_vxlan_config_prepare(tngcr_pl, config); mlxsw_reg_tngcr_learn_enable_set(tngcr_pl, config->learning_en); mlxsw_reg_tngcr_underlay_virtual_router_set(tngcr_pl, ul_vr_id); - mlxsw_reg_tngcr_usipv4_set(tngcr_pl, be32_to_cpu(config->ul_sip.addr4)); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); } -- cgit v1.2.3 From 4ee70efab68d2e99cfe9f32c9acc30b5a404d490 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 23 Jan 2019 14:32:57 +0000 Subject: mlxsw: spectrum_nve: Add support for VXLAN on Spectrum-2 Spectrum-1 and Spectrum-2 are largely backward compatible with regards to VXLAN. One difference - as explained in previous patch - is that an underlay RIF needs to be specified instead of an underlay VR during NVE initialization. This is accomplished by calling the relevant function that returns the index of such a RIF based on the table ID (RT_TABLE_MAIN) where underlay look up occurs. The second difference is that VXLAN learning (snooping) is controlled via a different register (TNPC). Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h | 1 + .../ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c | 110 ++++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h index 20d99b41611d..0035640156a1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h @@ -28,6 +28,7 @@ struct mlxsw_sp_nve { unsigned int num_nve_tunnels; /* Protected by RTNL */ unsigned int num_max_mc_entries[MLXSW_SP_L3_PROTO_MAX]; u32 tunnel_index; + u16 ul_rif_index; /* Reserved for Spectrum */ }; struct mlxsw_sp_nve_ops { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c index 60f88e5642e1..91b3c71bf031 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c @@ -7,6 +7,7 @@ #include #include "reg.h" +#include "spectrum.h" #include "spectrum_nve.h" /* Eth (18B) | IPv6 (40B) | UDP (8B) | VxLAN (8B) | Eth (14B) | IPv6 (40B) @@ -254,14 +255,121 @@ static bool mlxsw_sp2_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, return false; } +static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp, + bool learning_en) +{ + char tnpc_pl[MLXSW_REG_TNPC_LEN]; + + mlxsw_reg_tnpc_pack(tnpc_pl, MLXSW_REG_TNPC_TUNNEL_PORT_NVE, + learning_en); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tnpc), tnpc_pl); +} + +static int +mlxsw_sp2_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_nve_config *config) +{ + char tngcr_pl[MLXSW_REG_TNGCR_LEN]; + u16 ul_rif_index; + int err; + + err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, config->ul_tb_id, + &ul_rif_index); + if (err) + return err; + mlxsw_sp->nve->ul_rif_index = ul_rif_index; + + err = mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, config->learning_en); + if (err) + goto err_vxlan_learning_set; + + mlxsw_sp_nve_vxlan_config_prepare(tngcr_pl, config); + mlxsw_reg_tngcr_underlay_rif_set(tngcr_pl, ul_rif_index); + + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); + if (err) + goto err_tngcr_write; + + return 0; + +err_tngcr_write: + mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, false); +err_vxlan_learning_set: + mlxsw_sp_router_ul_rif_put(mlxsw_sp, ul_rif_index); + return err; +} + +static void mlxsw_sp2_nve_vxlan_config_clear(struct mlxsw_sp *mlxsw_sp) +{ + char tngcr_pl[MLXSW_REG_TNGCR_LEN]; + + mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, false, 0); + mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); + mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, false); + mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->nve->ul_rif_index); +} + +static int mlxsw_sp2_nve_vxlan_rtdp_set(struct mlxsw_sp *mlxsw_sp, + unsigned int tunnel_index, + u16 ul_rif_index) +{ + char rtdp_pl[MLXSW_REG_RTDP_LEN]; + + mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_NVE, tunnel_index); + mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_index); + + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); +} + static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve, const struct mlxsw_sp_nve_config *config) { - return -EOPNOTSUPP; + struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp; + int err; + + err = mlxsw_sp_nve_parsing_set(mlxsw_sp, + MLXSW_SP_NVE_VXLAN_PARSING_DEPTH, + config->udp_dport); + if (err) + return err; + + err = mlxsw_sp2_nve_vxlan_config_set(mlxsw_sp, config); + if (err) + goto err_config_set; + + err = mlxsw_sp2_nve_vxlan_rtdp_set(mlxsw_sp, nve->tunnel_index, + nve->ul_rif_index); + if (err) + goto err_rtdp_set; + + err = mlxsw_sp_router_nve_promote_decap(mlxsw_sp, config->ul_tb_id, + config->ul_proto, + &config->ul_sip, + nve->tunnel_index); + if (err) + goto err_promote_decap; + + return 0; + +err_promote_decap: +err_rtdp_set: + mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp); +err_config_set: + mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH, + config->udp_dport); + return err; } static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve) { + struct mlxsw_sp_nve_config *config = &nve->config; + struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp; + + mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id, + config->ul_proto, &config->ul_sip); + mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp); + mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH, + config->udp_dport); } const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = { -- cgit v1.2.3 From 02d21b59d5cc4b4b395bbc2a29319b8a529ebeff Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 23 Jan 2019 14:32:59 +0000 Subject: mlxsw: spectrum_nve: Enable VXLAN on Spectrum-2 Enable VXLAN on Spectrum-2 as previous patches added the required functionality. Note that for now Spectrum-1 and Spectrum-2 use the same function to determine whether the VXLAN configuration is valid or not. In the future, when the driver will be extended to support features not present in Spectrum-1, two different functions will be needed. Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c index 91b3c71bf031..93ccd9fc2266 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c @@ -21,9 +21,9 @@ #define MLXSW_SP_NVE_VXLAN_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \ VXLAN_F_LEARN) -static bool mlxsw_sp1_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, - const struct net_device *dev, - struct netlink_ext_ack *extack) +static bool mlxsw_sp_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, + const struct net_device *dev, + struct netlink_ext_ack *extack) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_config *cfg = &vxlan->cfg; @@ -240,7 +240,7 @@ mlxsw_sp_nve_vxlan_clear_offload(const struct net_device *nve_dev, __be32 vni) const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = { .type = MLXSW_SP_NVE_TYPE_VXLAN, - .can_offload = mlxsw_sp1_nve_vxlan_can_offload, + .can_offload = mlxsw_sp_nve_vxlan_can_offload, .nve_config = mlxsw_sp_nve_vxlan_config, .init = mlxsw_sp1_nve_vxlan_init, .fini = mlxsw_sp1_nve_vxlan_fini, @@ -248,13 +248,6 @@ const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = { .fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload, }; -static bool mlxsw_sp2_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, - const struct net_device *dev, - struct netlink_ext_ack *extack) -{ - return false; -} - static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp, bool learning_en) { @@ -374,7 +367,7 @@ static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve) const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = { .type = MLXSW_SP_NVE_TYPE_VXLAN, - .can_offload = mlxsw_sp2_nve_vxlan_can_offload, + .can_offload = mlxsw_sp_nve_vxlan_can_offload, .nve_config = mlxsw_sp_nve_vxlan_config, .init = mlxsw_sp2_nve_vxlan_init, .fini = mlxsw_sp2_nve_vxlan_fini, -- cgit v1.2.3 From 45e92b7e4e27a427de7e87d5c4d63d4ce7ba02ab Mon Sep 17 00:00:00 2001 From: Peng Li Date: Wed, 23 Jan 2019 07:39:27 +0800 Subject: net: hns3: add calling roce callback function when link status change This patch adds calling roce callback function when link status change. Signed-off-by: Wei Hu (Xavier) Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 6 ++++++ drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 5 +++++ 2 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 00d7acb4d45a..35fb0c54b986 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2105,7 +2105,9 @@ static int hclge_get_mac_phy_link(struct hclge_dev *hdev) static void hclge_update_link_status(struct hclge_dev *hdev) { + struct hnae3_client *rclient = hdev->roce_client; struct hnae3_client *client = hdev->nic_client; + struct hnae3_handle *rhandle; struct hnae3_handle *handle; int state; int i; @@ -2117,6 +2119,10 @@ static void hclge_update_link_status(struct hclge_dev *hdev) for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { handle = &hdev->vport[i].nic; client->ops->link_status_change(handle, state); + rhandle = &hdev->vport[i].roce; + if (rclient && rclient->ops->link_status_change) + rclient->ops->link_status_change(rhandle, + state); } hdev->hw.mac.link = state; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index bb9f45200ef5..989f08377d58 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -349,16 +349,21 @@ static void hclgevf_request_link_info(struct hclgevf_dev *hdev) void hclgevf_update_link_status(struct hclgevf_dev *hdev, int link_state) { + struct hnae3_handle *rhandle = &hdev->roce; struct hnae3_handle *handle = &hdev->nic; + struct hnae3_client *rclient; struct hnae3_client *client; client = handle->client; + rclient = hdev->roce_client; link_state = test_bit(HCLGEVF_STATE_DOWN, &hdev->state) ? 0 : link_state; if (link_state != hdev->hw.mac.link) { client->ops->link_status_change(handle, !!link_state); + if (rclient && rclient->ops->link_status_change) + rclient->ops->link_status_change(rhandle, !!link_state); hdev->hw.mac.link = link_state; } } -- cgit v1.2.3 From c376fa1aae6328beb5551e92fa84f4441fdde399 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Wed, 23 Jan 2019 07:39:28 +0800 Subject: net: hns3: add rx multicast packets statistic This patch adds rx multicast packets statistic for each ring. Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 6 ++++++ drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 8 ++++++++ drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 1 + 3 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 9dd8949381bc..2ec3759961f1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2572,6 +2572,7 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, struct sk_buff **out_skb) { struct net_device *netdev = ring->tqp->handle->kinfo.netdev; + enum hns3_pkt_l2t_type l2_frame_type; struct sk_buff *skb = ring->skb; struct hns3_desc_cb *desc_cb; struct hns3_desc *desc; @@ -2680,7 +2681,12 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, return -EFAULT; } + l2_frame_type = hnae3_get_field(l234info, HNS3_RXD_DMAC_M, + HNS3_RXD_DMAC_S); u64_stats_update_begin(&ring->syncp); + if (l2_frame_type == HNS3_L2_TYPE_MULTICAST) + ring->stats.rx_multicast++; + ring->stats.rx_pkts++; ring->stats.rx_bytes += skb->len; u64_stats_update_end(&ring->syncp); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index f59ab7387b1f..f3d248626ab3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -202,6 +202,13 @@ enum hns3_nic_state { #define HNS3_RING_EN_B 0 +enum hns3_pkt_l2t_type { + HNS3_L2_TYPE_UNICAST, + HNS3_L2_TYPE_MULTICAST, + HNS3_L2_TYPE_BROADCAST, + HNS3_L2_TYPE_INVALID, +}; + enum hns3_pkt_l3t_type { HNS3_L3T_NONE, HNS3_L3T_IPV6, @@ -376,6 +383,7 @@ struct ring_stats { u64 err_bd_num; u64 l2_err; u64 l3l4_csum_err; + u64 rx_multicast; }; }; }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index e678b6939da3..abb78696d7ce 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -47,6 +47,7 @@ static const struct hns3_stats hns3_rxq_stats[] = { HNS3_TQP_STAT("err_bd_num", err_bd_num), HNS3_TQP_STAT("l2_err", l2_err), HNS3_TQP_STAT("l3l4_csum_err", l3l4_csum_err), + HNS3_TQP_STAT("multicast", rx_multicast), }; #define HNS3_RXQ_STATS_COUNT ARRAY_SIZE(hns3_rxq_stats) -- cgit v1.2.3 From d3ec4ef669379bf69891415b4f1397a26a81932c Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Wed, 23 Jan 2019 07:39:29 +0800 Subject: net: hns3: refactor the statistics updating for netdev In origin codes, there are some statistics item are got from mac, which also include the packets statistics of VF. It is unreasonable. This patch fixes it by counting them in the rx/tx processing flow. Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 27 ++++++++++++++++------ .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 25 -------------------- 2 files changed, 20 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 2ec3759961f1..1f15864fb8db 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1399,7 +1399,12 @@ static void hns3_nic_get_stats64(struct net_device *netdev, int queue_num = priv->ae_handle->kinfo.num_tqps; struct hnae3_handle *handle = priv->ae_handle; struct hns3_enet_ring *ring; + u64 rx_length_errors = 0; + u64 rx_crc_errors = 0; + u64 rx_multicast = 0; unsigned int start; + u64 tx_errors = 0; + u64 rx_errors = 0; unsigned int idx; u64 tx_bytes = 0; u64 rx_bytes = 0; @@ -1422,6 +1427,8 @@ static void hns3_nic_get_stats64(struct net_device *netdev, tx_pkts += ring->stats.tx_pkts; tx_drop += ring->stats.tx_busy; tx_drop += ring->stats.sw_err_cnt; + tx_errors += ring->stats.tx_busy; + tx_errors += ring->stats.sw_err_cnt; } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); /* fetch the rx stats */ @@ -1433,6 +1440,12 @@ static void hns3_nic_get_stats64(struct net_device *netdev, rx_drop += ring->stats.non_vld_descs; rx_drop += ring->stats.err_pkt_len; rx_drop += ring->stats.l2_err; + rx_errors += ring->stats.non_vld_descs; + rx_errors += ring->stats.l2_err; + rx_crc_errors += ring->stats.l2_err; + rx_crc_errors += ring->stats.l3l4_csum_err; + rx_multicast += ring->stats.rx_multicast; + rx_length_errors += ring->stats.err_pkt_len; } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); } @@ -1441,15 +1454,15 @@ static void hns3_nic_get_stats64(struct net_device *netdev, stats->rx_bytes = rx_bytes; stats->rx_packets = rx_pkts; - stats->rx_errors = netdev->stats.rx_errors; - stats->multicast = netdev->stats.multicast; - stats->rx_length_errors = netdev->stats.rx_length_errors; - stats->rx_crc_errors = netdev->stats.rx_crc_errors; + stats->rx_errors = rx_errors; + stats->multicast = rx_multicast; + stats->rx_length_errors = rx_length_errors; + stats->rx_crc_errors = rx_crc_errors; stats->rx_missed_errors = netdev->stats.rx_missed_errors; - stats->tx_errors = netdev->stats.tx_errors; - stats->rx_dropped = rx_drop + netdev->stats.rx_dropped; - stats->tx_dropped = tx_drop + netdev->stats.tx_dropped; + stats->tx_errors = tx_errors; + stats->rx_dropped = rx_drop; + stats->tx_dropped = tx_drop; stats->collisions = netdev->stats.collisions; stats->rx_over_errors = netdev->stats.rx_over_errors; stats->rx_frame_errors = netdev->stats.rx_frame_errors; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 35fb0c54b986..bf0931c6764f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -461,26 +461,6 @@ static u8 *hclge_comm_get_strings(u32 stringset, return (u8 *)buff; } -static void hclge_update_netstat(struct hclge_hw_stats *hw_stats, - struct net_device_stats *net_stats) -{ - net_stats->tx_dropped = 0; - net_stats->rx_errors = hw_stats->mac_stats.mac_rx_oversize_pkt_num; - net_stats->rx_errors += hw_stats->mac_stats.mac_rx_undersize_pkt_num; - net_stats->rx_errors += hw_stats->mac_stats.mac_rx_fcs_err_pkt_num; - - net_stats->multicast = hw_stats->mac_stats.mac_tx_multi_pkt_num; - net_stats->multicast += hw_stats->mac_stats.mac_rx_multi_pkt_num; - - net_stats->rx_crc_errors = hw_stats->mac_stats.mac_rx_fcs_err_pkt_num; - net_stats->rx_length_errors = - hw_stats->mac_stats.mac_rx_undersize_pkt_num; - net_stats->rx_length_errors += - hw_stats->mac_stats.mac_rx_oversize_pkt_num; - net_stats->rx_over_errors = - hw_stats->mac_stats.mac_rx_oversize_pkt_num; -} - static void hclge_update_stats_for_all(struct hclge_dev *hdev) { struct hnae3_handle *handle; @@ -500,8 +480,6 @@ static void hclge_update_stats_for_all(struct hclge_dev *hdev) if (status) dev_err(&hdev->pdev->dev, "Update MAC stats fail, status = %d.\n", status); - - hclge_update_netstat(&hdev->hw_stats, &handle->kinfo.netdev->stats); } static void hclge_update_stats(struct hnae3_handle *handle, @@ -509,7 +487,6 @@ static void hclge_update_stats(struct hnae3_handle *handle, { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - struct hclge_hw_stats *hw_stats = &hdev->hw_stats; int status; if (test_and_set_bit(HCLGE_STATE_STATISTICS_UPDATING, &hdev->state)) @@ -527,8 +504,6 @@ static void hclge_update_stats(struct hnae3_handle *handle, "Update TQPS stats fail, status = %d.\n", status); - hclge_update_netstat(hw_stats, net_stats); - clear_bit(HCLGE_STATE_STATISTICS_UPDATING, &hdev->state); } -- cgit v1.2.3 From 90c68a41db7d02ac031e612c0c97147a58e20515 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Wed, 23 Jan 2019 07:39:30 +0800 Subject: net: hns3: fix rss configuration lost problem when setting channel Currently rss configuration set by user will be lost when setting channel. This patch fixes it by not setting rss configuration to default if user has configured the rss. Fixes: 09f2af6405b8 ("net: hns3: add support to modify tqps number") Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 3 ++- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 6 ++++-- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 8 +++++++- 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index d486748d5883..dc3db45361d3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -433,7 +433,8 @@ struct hnae3_ae_ops { struct ethtool_channels *ch); void (*get_tqps_and_rss_info)(struct hnae3_handle *h, u16 *alloc_tqps, u16 *max_rss_size); - int (*set_channels)(struct hnae3_handle *handle, u32 new_tqps_num); + int (*set_channels)(struct hnae3_handle *handle, u32 new_tqps_num, + bool rxfh_configured); void (*get_flowctrl_adv)(struct hnae3_handle *handle, u32 *flowctrl_adv); int (*set_led_id)(struct hnae3_handle *handle, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 1f15864fb8db..544f0d2f1e12 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4163,6 +4163,7 @@ int hns3_set_channels(struct net_device *netdev, { struct hnae3_handle *h = hns3_get_handle(netdev); struct hnae3_knic_private_info *kinfo = &h->kinfo; + bool rxfh_configured = netif_is_rxfh_configured(netdev); u32 new_tqp_num = ch->combined_count; u16 org_tqp_num; int ret; @@ -4190,9 +4191,10 @@ int hns3_set_channels(struct net_device *netdev, return ret; org_tqp_num = h->kinfo.num_tqps; - ret = h->ae_algo->ops->set_channels(h, new_tqp_num); + ret = h->ae_algo->ops->set_channels(h, new_tqp_num, rxfh_configured); if (ret) { - ret = h->ae_algo->ops->set_channels(h, org_tqp_num); + ret = h->ae_algo->ops->set_channels(h, org_tqp_num, + rxfh_configured); if (ret) { /* If revert to old tqp failed, fatal error occurred */ dev_err(&netdev->dev, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index bf0931c6764f..3ba8de93bc3d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7518,7 +7518,8 @@ static void hclge_get_tqps_and_rss_info(struct hnae3_handle *handle, *max_rss_size = hdev->rss_size_max; } -static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num) +static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, + bool rxfh_configured) { struct hclge_vport *vport = hclge_get_vport(handle); struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; @@ -7557,6 +7558,10 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num) if (ret) return ret; + /* RSS indirection table has been configuared by user */ + if (rxfh_configured) + goto out; + /* Reinitializes the rss indirect table according to the new RSS size */ rss_indir = kcalloc(HCLGE_RSS_IND_TBL_SIZE, sizeof(u32), GFP_KERNEL); if (!rss_indir) @@ -7572,6 +7577,7 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num) kfree(rss_indir); +out: if (!ret) dev_info(&hdev->pdev->dev, "Channels changed, rss_size from %d to %d, tqps from %d to %d", -- cgit v1.2.3 From 9e5157ba440f2bf87071c017545d6c4ba627e501 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Wed, 23 Jan 2019 07:39:31 +0800 Subject: net: hns3: fix for shaper not setting when TC num changes Shaper setting does not change currently, when TC num changes, which may cause shaper parameter not setting problem. This patch fixes it by setting the shaper parameter when TC num changes. Fixes: cacde272dd00 ("net: hns3: Add hclge_dcb module for the support of DCB feature") Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 6 +----- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 6 +++--- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 4ec0b9cd15ae..5f7ac63707b8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -162,11 +162,7 @@ static int hclge_map_update(struct hnae3_handle *h) struct hclge_dev *hdev = vport->back; int ret; - ret = hclge_tm_map_cfg(hdev); - if (ret) - return ret; - - ret = hclge_tm_schd_mode_hw(hdev); + ret = hclge_tm_schd_setup_hw(hdev); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index fb8596a3e5e4..d057c9f03175 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1005,7 +1005,7 @@ static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev) return 0; } -int hclge_tm_map_cfg(struct hclge_dev *hdev) +static int hclge_tm_map_cfg(struct hclge_dev *hdev) { int ret; @@ -1120,7 +1120,7 @@ static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev) return 0; } -int hclge_tm_schd_mode_hw(struct hclge_dev *hdev) +static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev) { int ret; @@ -1131,7 +1131,7 @@ int hclge_tm_schd_mode_hw(struct hclge_dev *hdev) return hclge_tm_lvl34_schd_mode_cfg(hdev); } -static int hclge_tm_schd_setup_hw(struct hclge_dev *hdev) +int hclge_tm_schd_setup_hw(struct hclge_dev *hdev) { int ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index 898163c4d400..ef3f93b70c22 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -144,11 +144,10 @@ struct hclge_port_shapping_cmd { int hclge_tm_schd_init(struct hclge_dev *hdev); int hclge_tm_vport_map_update(struct hclge_dev *hdev); int hclge_pause_setup_hw(struct hclge_dev *hdev); -int hclge_tm_schd_mode_hw(struct hclge_dev *hdev); +int hclge_tm_schd_setup_hw(struct hclge_dev *hdev); void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc); void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc); int hclge_tm_dwrr_cfg(struct hclge_dev *hdev); -int hclge_tm_map_cfg(struct hclge_dev *hdev); int hclge_tm_init_hw(struct hclge_dev *hdev); int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx); int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr); -- cgit v1.2.3 From 8be7362186bd5ccb5f6f72be49751ad2778e2636 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Wed, 23 Jan 2019 07:39:32 +0800 Subject: net: hns3: fix bug of ethtool_ops.get_channels for VF The current code returns the number of all queues that can be used and the number of queues that have been allocated, which is incorrect. What should be returned is the number of queues allocated for each enabled TC and the number of queues that can be allocated. This patch fixes it. Fixes: 849e46077689 ("net: hns3: add ethtool_ops.get_channels support for VF") Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 989f08377d58..24b54083b5f9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2466,7 +2466,8 @@ static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev) struct hnae3_handle *nic = &hdev->nic; struct hnae3_knic_private_info *kinfo = &nic->kinfo; - return min_t(u32, hdev->rss_size_max * kinfo->num_tc, hdev->num_tqps); + return min_t(u32, hdev->rss_size_max, + hdev->num_tqps / kinfo->num_tc); } /** @@ -2487,7 +2488,7 @@ static void hclgevf_get_channels(struct hnae3_handle *handle, ch->max_combined = hclgevf_get_max_channels(hdev); ch->other_count = 0; ch->max_other = 0; - ch->combined_count = hdev->num_tqps; + ch->combined_count = handle->kinfo.rss_size; } static void hclgevf_get_tqps_and_rss_info(struct hnae3_handle *handle, -- cgit v1.2.3 From ac574b80a1ba834be01932d8cd4976acda775a36 Mon Sep 17 00:00:00 2001 From: Peng Li Date: Wed, 23 Jan 2019 07:39:33 +0800 Subject: net: hns3: clear param in ring when free ring Param pending_buf and skb may be not NULL when free ring. This patch clears them when free ring. Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 544f0d2f1e12..327dde2765ab 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3397,6 +3397,11 @@ static void hns3_fini_ring(struct hns3_enet_ring *ring) ring->desc_cb = NULL; ring->next_to_clean = 0; ring->next_to_use = 0; + ring->pending_buf = 0; + if (ring->skb) { + dev_kfree_skb_any(ring->skb); + ring->skb = NULL; + } } static int hns3_buf_size2type(u32 buf_size) -- cgit v1.2.3 From 4a402f47cfce904051cd8b31bef4fe2910d9dce9 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Wed, 23 Jan 2019 07:39:34 +0800 Subject: net: hns3: Change fw error code NOT_EXEC to NOT_SUPPORTED According to firmware error code definition, the error code of 2 means NOT_SUPPORTED, this patch changes it to NOT_SUPPORTED. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 2 ++ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index e483a6e730e6..b0ee070884eb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -259,6 +259,8 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num) if (desc_ret == HCLGE_CMD_EXEC_SUCCESS) retval = 0; + else if (desc_ret == HCLGE_CMD_NOT_SUPPORTED) + retval = -EOPNOTSUPP; else retval = -EIO; hw->cmq.last_status = desc_ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index f23042b24c09..9f07279513b7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -39,7 +39,7 @@ struct hclge_cmq_ring { enum hclge_cmd_return_status { HCLGE_CMD_EXEC_SUCCESS = 0, HCLGE_CMD_NO_AUTH = 1, - HCLGE_CMD_NOT_EXEC = 2, + HCLGE_CMD_NOT_SUPPORTED = 2, HCLGE_CMD_QUEUE_FULL = 3, }; -- cgit v1.2.3 From 44e59e375bf7785660a250f61e802996894d148a Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Wed, 23 Jan 2019 07:39:35 +0800 Subject: net: hns3: do not return GE PFC setting err when initializing GE MAC does not support PFC, when driver is initializing and MAC is in GE Mode, ignore the fw not supported error, otherwise initialization will fail. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 6 +++--- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 19 ++++++++++++------- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 4 ++-- 4 files changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 5f7ac63707b8..7db491086fea 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -166,7 +166,7 @@ static int hclge_map_update(struct hnae3_handle *h) if (ret) return ret; - ret = hclge_pause_setup_hw(hdev); + ret = hclge_pause_setup_hw(hdev, false); if (ret) return ret; @@ -313,7 +313,7 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) hdev->tm_info.hw_pfc_map = pfc_map; - return hclge_pause_setup_hw(hdev); + return hclge_pause_setup_hw(hdev, false); } /* DCBX configuration */ @@ -361,7 +361,7 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) hclge_tm_schd_info_update(hdev, tc); hclge_tm_prio_tc_info_update(hdev, prio_tc); - ret = hclge_tm_init_hw(hdev); + ret = hclge_tm_init_hw(hdev, false); if (ret) return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 3ba8de93bc3d..6fb3144eb79d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7428,7 +7428,7 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev) return ret; } - ret = hclge_tm_init_hw(hdev); + ret = hclge_tm_init_hw(hdev, true); if (ret) { dev_err(&pdev->dev, "tm init hw fail, ret =%d\n", ret); return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index d057c9f03175..44316602c2fc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1255,7 +1255,7 @@ static int hclge_tm_bp_setup(struct hclge_dev *hdev) return ret; } -int hclge_pause_setup_hw(struct hclge_dev *hdev) +int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init) { int ret; @@ -1271,10 +1271,15 @@ int hclge_pause_setup_hw(struct hclge_dev *hdev) if (!hnae3_dev_dcb_supported(hdev)) return 0; - /* When MAC is GE Mode, hdev does not support pfc setting */ + /* GE MAC does not support PFC, when driver is initializing and MAC + * is in GE Mode, ignore the error here, otherwise initialization + * will fail. + */ ret = hclge_pfc_setup_hw(hdev); - if (ret) - dev_warn(&hdev->pdev->dev, "set pfc pause failed:%d\n", ret); + if (init && ret == -EOPNOTSUPP) + dev_warn(&hdev->pdev->dev, "GE MAC does not support pfc\n"); + else + return ret; return hclge_tm_bp_setup(hdev); } @@ -1314,7 +1319,7 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc) hclge_tm_schd_info_init(hdev); } -int hclge_tm_init_hw(struct hclge_dev *hdev) +int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) { int ret; @@ -1326,7 +1331,7 @@ int hclge_tm_init_hw(struct hclge_dev *hdev) if (ret) return ret; - ret = hclge_pause_setup_hw(hdev); + ret = hclge_pause_setup_hw(hdev, init); if (ret) return ret; @@ -1345,7 +1350,7 @@ int hclge_tm_schd_init(struct hclge_dev *hdev) if (ret) return ret; - return hclge_tm_init_hw(hdev); + return hclge_tm_init_hw(hdev, true); } int hclge_tm_vport_map_update(struct hclge_dev *hdev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h index ef3f93b70c22..f60e540c7a62 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h @@ -143,12 +143,12 @@ struct hclge_port_shapping_cmd { int hclge_tm_schd_init(struct hclge_dev *hdev); int hclge_tm_vport_map_update(struct hclge_dev *hdev); -int hclge_pause_setup_hw(struct hclge_dev *hdev); +int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init); int hclge_tm_schd_setup_hw(struct hclge_dev *hdev); void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc); void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc); int hclge_tm_dwrr_cfg(struct hclge_dev *hdev); -int hclge_tm_init_hw(struct hclge_dev *hdev); +int hclge_tm_init_hw(struct hclge_dev *hdev, bool init); int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx); int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr); int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); -- cgit v1.2.3 From 330baff5423b143fba698f2acc9eff3cfb1a0776 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Wed, 23 Jan 2019 07:39:36 +0800 Subject: net: hns3: add ETS TC weight setting in SSU module This patch sets the TC weight in SSU module according to info in tm_info. Also, zero weight of TC weight in SSU ETS module means enabling strict priority, so do not allow zero weight when in ETS mode. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 44316602c2fc..bad975ebe137 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -947,6 +947,36 @@ static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) return 0; } +static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev) +{ +#define DEFAULT_TC_WEIGHT 1 +#define DEFAULT_TC_OFFSET 14 + + struct hclge_ets_tc_weight_cmd *ets_weight; + struct hclge_desc desc; + int i; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, false); + ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data; + + for (i = 0; i < HNAE3_MAX_TC; i++) { + struct hclge_pg_info *pg_info; + + ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT; + + if (!(hdev->hw_tc_map & BIT(i))) + continue; + + pg_info = + &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; + ets_weight->tc_weight[i] = pg_info->tc_dwrr[i]; + } + + ets_weight->weight_offset = DEFAULT_TC_OFFSET; + + return hclge_cmd_send(&hdev->hw, &desc, 1); +} + static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport) { struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; @@ -996,6 +1026,19 @@ static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev) ret = hclge_tm_pri_tc_base_dwrr_cfg(hdev); if (ret) return ret; + + if (!hnae3_dev_dcb_supported(hdev)) + return 0; + + ret = hclge_tm_ets_tc_dwrr_cfg(hdev); + if (ret == -EOPNOTSUPP) { + dev_warn(&hdev->pdev->dev, + "fw %08x does't support ets tc weight cmd\n", + hdev->fw_version); + ret = 0; + } + + return ret; } else { ret = hclge_tm_pri_vnet_base_dwrr_cfg(hdev); if (ret) -- cgit v1.2.3 From d174ea75c96a12287354af53dc17cb24f328f90a Mon Sep 17 00:00:00 2001 From: liuzhongzhu Date: Wed, 23 Jan 2019 07:39:37 +0800 Subject: net: hns3: add statistics for PFC frames and MAC control frames In the old firmware version, statistics acquisition of PFC frames and MAC control frames is not supported. Add command retrieves statistics for PFC frames and MAC control frames from the firmware. Signed-off-by: liuzhongzhu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 10 ++- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 97 ++++++++++++++++++++-- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 7 ++ 4 files changed, 109 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index b0ee070884eb..81dbe1b6abb0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -170,8 +170,12 @@ static bool hclge_is_special_opcode(u16 opcode) /* these commands have several descriptors, * and use the first one to save opcode and return value */ - u16 spec_opcode[3] = {HCLGE_OPC_STATS_64_BIT, - HCLGE_OPC_STATS_32_BIT, HCLGE_OPC_STATS_MAC}; + u16 spec_opcode[] = {HCLGE_OPC_STATS_64_BIT, + HCLGE_OPC_STATS_32_BIT, + HCLGE_OPC_STATS_MAC, + HCLGE_OPC_STATS_MAC_ALL, + HCLGE_OPC_QUERY_32_BIT_REG, + HCLGE_OPC_QUERY_64_BIT_REG}; int i; for (i = 0; i < ARRAY_SIZE(spec_opcode); i++) { @@ -259,6 +263,8 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num) if (desc_ret == HCLGE_CMD_EXEC_SUCCESS) retval = 0; + else if (desc_ret == HCLGE_CMD_NO_AUTH) + retval = -EPERM; else if (desc_ret == HCLGE_CMD_NOT_SUPPORTED) retval = -EOPNOTSUPP; else diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index 9f07279513b7..e26a25128693 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -82,6 +82,8 @@ enum hclge_opcode_type { HCLGE_OPC_STATS_64_BIT = 0x0030, HCLGE_OPC_STATS_32_BIT = 0x0031, HCLGE_OPC_STATS_MAC = 0x0032, + HCLGE_OPC_QUERY_MAC_REG_NUM = 0x0033, + HCLGE_OPC_STATS_MAC_ALL = 0x0034, HCLGE_OPC_QUERY_REG_NUM = 0x0040, HCLGE_OPC_QUERY_32_BIT_REG = 0x0041, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 6fb3144eb79d..64b1589e549f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -118,6 +118,12 @@ static const struct hclge_comm_stats_str g_mac_stats_string[] = { HCLGE_MAC_STATS_FIELD_OFF(mac_tx_mac_pause_num)}, {"mac_rx_mac_pause_num", HCLGE_MAC_STATS_FIELD_OFF(mac_rx_mac_pause_num)}, + {"mac_tx_control_pkt_num", + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_ctrl_pkt_num)}, + {"mac_rx_control_pkt_num", + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_ctrl_pkt_num)}, + {"mac_tx_pfc_pkt_num", + HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pause_pkt_num)}, {"mac_tx_pfc_pri0_pkt_num", HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri0_pkt_num)}, {"mac_tx_pfc_pri1_pkt_num", @@ -134,6 +140,8 @@ static const struct hclge_comm_stats_str g_mac_stats_string[] = { HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri6_pkt_num)}, {"mac_tx_pfc_pri7_pkt_num", HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri7_pkt_num)}, + {"mac_rx_pfc_pkt_num", + HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pause_pkt_num)}, {"mac_rx_pfc_pri0_pkt_num", HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri0_pkt_num)}, {"mac_rx_pfc_pri1_pkt_num", @@ -287,10 +295,9 @@ static const struct hclge_mac_mgr_tbl_entry_cmd hclge_mgr_table[] = { }, }; -static int hclge_mac_update_stats(struct hclge_dev *hdev) +static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) { #define HCLGE_MAC_CMD_NUM 21 -#define HCLGE_RTN_DATA_NUM 4 u64 *data = (u64 *)(&hdev->hw_stats.mac_stats); struct hclge_desc desc[HCLGE_MAC_CMD_NUM]; @@ -308,22 +315,102 @@ static int hclge_mac_update_stats(struct hclge_dev *hdev) } for (i = 0; i < HCLGE_MAC_CMD_NUM; i++) { + /* for special opcode 0032, only the first desc has the head */ if (unlikely(i == 0)) { desc_data = (__le64 *)(&desc[i].data[0]); - n = HCLGE_RTN_DATA_NUM - 2; + n = HCLGE_RD_FIRST_STATS_NUM; } else { desc_data = (__le64 *)(&desc[i]); - n = HCLGE_RTN_DATA_NUM; + n = HCLGE_RD_OTHER_STATS_NUM; } + + for (k = 0; k < n; k++) { + *data += le64_to_cpu(*desc_data); + data++; + desc_data++; + } + } + + return 0; +} + +static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num) +{ + u64 *data = (u64 *)(&hdev->hw_stats.mac_stats); + struct hclge_desc *desc; + __le64 *desc_data; + u16 i, k, n; + int ret; + + desc = kcalloc(desc_num, sizeof(struct hclge_desc), GFP_KERNEL); + hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_STATS_MAC_ALL, true); + ret = hclge_cmd_send(&hdev->hw, desc, desc_num); + if (ret) { + kfree(desc); + return ret; + } + + for (i = 0; i < desc_num; i++) { + /* for special opcode 0034, only the first desc has the head */ + if (i == 0) { + desc_data = (__le64 *)(&desc[i].data[0]); + n = HCLGE_RD_FIRST_STATS_NUM; + } else { + desc_data = (__le64 *)(&desc[i]); + n = HCLGE_RD_OTHER_STATS_NUM; + } + for (k = 0; k < n; k++) { - *data++ += le64_to_cpu(*desc_data); + *data += le64_to_cpu(*desc_data); + data++; desc_data++; } } + kfree(desc); + return 0; } +static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *desc_num) +{ + struct hclge_desc desc; + __le32 *desc_data; + u32 reg_num; + int ret; + + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_MAC_REG_NUM, true); + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + return ret; + + desc_data = (__le32 *)(&desc.data[0]); + reg_num = le32_to_cpu(*desc_data); + + *desc_num = 1 + ((reg_num - 3) >> 2) + + (u32)(((reg_num - 3) & 0x3) ? 1 : 0); + + return 0; +} + +static int hclge_mac_update_stats(struct hclge_dev *hdev) +{ + u32 desc_num; + int ret; + + ret = hclge_mac_query_reg_num(hdev, &desc_num); + + /* The firmware supports the new statistics acquisition method */ + if (!ret) + ret = hclge_mac_update_stats_complete(hdev, desc_num); + else if (ret == -EOPNOTSUPP) + ret = hclge_mac_update_stats_defective(hdev); + else + dev_err(&hdev->pdev->dev, "query mac reg num fail!\n"); + + return ret; +} + static int hclge_tqps_update_stats(struct hnae3_handle *handle) { struct hnae3_knic_private_info *kinfo = &handle->kinfo; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 279ed2d83cb8..b5a38fc1af91 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -16,6 +16,9 @@ #define HCLGE_MAX_PF_NUM 8 +#define HCLGE_RD_FIRST_STATS_NUM 2 +#define HCLGE_RD_OTHER_STATS_NUM 4 + #define HCLGE_INVALID_VPORT 0xffff #define HCLGE_PF_CFG_BLOCK_SIZE 32 @@ -415,6 +418,10 @@ struct hclge_mac_stats { u64 mac_rx_fcs_err_pkt_num; u64 mac_rx_send_app_good_pkt_num; u64 mac_rx_send_app_bad_pkt_num; + u64 mac_tx_pfc_pause_pkt_num; + u64 mac_rx_pfc_pause_pkt_num; + u64 mac_tx_ctrl_pkt_num; + u64 mac_rx_ctrl_pkt_num; }; #define HCLGE_STATS_TIMER_INTERVAL (60 * 5) -- cgit v1.2.3 From d3ad430ac531e65f29c9737f86744c425c9173ef Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Wed, 23 Jan 2019 07:39:38 +0800 Subject: net: hns3: fix PFC not setting problem for DCB module The PFC enabling is based on user priority, currently it is based on TC, which may cause PFC not setting correctly when pri to TC mapping is not one to one relation. This patch adds pfc_en in tm_info to fix it. Fixes: cacde272dd00 ("net: hns3: Add hclge_dcb module for the support of DCB feature") Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 7 ++++--- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 1 + drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 7db491086fea..3a4a54ee5204 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -296,6 +296,9 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE) return -EINVAL; + if (pfc->pfc_en == hdev->tm_info.pfc_en) + return 0; + prio_tc = hdev->tm_info.prio_tc; pfc_map = 0; @@ -308,10 +311,8 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) } } - if (pfc_map == hdev->tm_info.hw_pfc_map) - return 0; - hdev->tm_info.hw_pfc_map = pfc_map; + hdev->tm_info.pfc_en = pfc->pfc_en; return hclge_pause_setup_hw(hdev, false); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index b5a38fc1af91..2c413c63c6c9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -325,6 +325,7 @@ struct hclge_tm_info { struct hclge_tc_info tc_info[HNAE3_MAX_TC]; enum hclge_fc_mode fc_mode; u8 hw_pfc_map; /* Allow for packet drop or not on this TC */ + u8 pfc_en; /* PFC enabled or not for user priority */ }; struct hclge_comm_stats_str { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index bad975ebe137..9f4069fb786b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1215,7 +1215,7 @@ static int hclge_pfc_setup_hw(struct hclge_dev *hdev) HCLGE_RX_MAC_PAUSE_EN_MSK; return hclge_pfc_pause_en_cfg(hdev, enable_bitmap, - hdev->tm_info.hw_pfc_map); + hdev->tm_info.pfc_en); } /* Each Tc has a 1024 queue sets to backpress, it divides to -- cgit v1.2.3 From 254764e55652d47fe81a54d7c226f3ba230180fe Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 22 Jan 2019 22:23:41 +0100 Subject: r8169: improve firmware handling So far member rtl_fw has three states: - IS_ERR(rtl_fw): firmware not loaded - !rtl_fw: no firmware available - other: firmware loaded This can be made simpler and clearer by adding the firmware name as member fw_name to struct rtl8169_private. Then: - !fw_name: no firmware available - !rtl_fw: firmware not loaded - rtl_fw: firmware loaded This change also allows to easily merge rtl_request_uncached_firmware into rtl_request_firmware. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 47 ++++++++++++------------------------ 1 file changed, 15 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 5480073e0026..f574b6b557f9 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -684,6 +684,7 @@ struct rtl8169_private { struct rtl8169_tc_offsets tc_offset; u32 saved_wolopts; + const char *fw_name; struct rtl_fw { const struct firmware *fw; @@ -696,7 +697,6 @@ struct rtl8169_private { size_t size; } phy_action; } *rtl_fw; -#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN) u32 ocp_base; }; @@ -1510,11 +1510,6 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) return 0; } -static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp) -{ - return rtl_chip_infos[tp->mac_version].fw_name; -} - static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -1524,7 +1519,7 @@ static void rtl8169_get_drvinfo(struct net_device *dev, strlcpy(info->driver, MODULENAME, sizeof(info->driver)); strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info)); BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); - if (!IS_ERR_OR_NULL(rtl_fw)) + if (rtl_fw) strlcpy(info->fw_version, rtl_fw->version, sizeof(info->fw_version)); } @@ -2201,7 +2196,7 @@ static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) if (fw->size % FW_OPCODE_SIZE) goto out; - strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE); + strlcpy(version, tp->fw_name, RTL_VER_SIZE); pa->code = (__le32 *)fw->data; pa->size = fw->size / FW_OPCODE_SIZE; @@ -2376,20 +2371,18 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) static void rtl_release_firmware(struct rtl8169_private *tp) { - if (!IS_ERR_OR_NULL(tp->rtl_fw)) { + if (tp->rtl_fw) { release_firmware(tp->rtl_fw->fw); kfree(tp->rtl_fw); + tp->rtl_fw = NULL; } - tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; } static void rtl_apply_firmware(struct rtl8169_private *tp) { - struct rtl_fw *rtl_fw = tp->rtl_fw; - /* TODO: release firmware once rtl_phy_write_fw signals failures. */ - if (!IS_ERR_OR_NULL(rtl_fw)) - rtl_phy_write_fw(tp, rtl_fw); + if (tp->rtl_fw) + rtl_phy_write_fw(tp, tp->rtl_fw); } static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) @@ -4377,21 +4370,20 @@ static void rtl_hw_reset(struct rtl8169_private *tp) rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); } -static void rtl_request_uncached_firmware(struct rtl8169_private *tp) +static void rtl_request_firmware(struct rtl8169_private *tp) { struct rtl_fw *rtl_fw; - const char *name; int rc = -ENOMEM; - name = rtl_lookup_firmware_name(tp); - if (!name) - goto out_no_firmware; + /* firmware loaded already or no firmware available */ + if (tp->rtl_fw || !tp->fw_name) + return; rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); if (!rtl_fw) goto err_warn; - rc = request_firmware(&rtl_fw->fw, name, tp_to_dev(tp)); + rc = request_firmware(&rtl_fw->fw, tp->fw_name, tp_to_dev(tp)); if (rc < 0) goto err_free; @@ -4400,7 +4392,7 @@ static void rtl_request_uncached_firmware(struct rtl8169_private *tp) goto err_release_firmware; tp->rtl_fw = rtl_fw; -out: + return; err_release_firmware: @@ -4409,16 +4401,7 @@ err_free: kfree(rtl_fw); err_warn: netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n", - name, rc); -out_no_firmware: - tp->rtl_fw = NULL; - goto out; -} - -static void rtl_request_firmware(struct rtl8169_private *tp) -{ - if (IS_ERR(tp->rtl_fw)) - rtl_request_uncached_firmware(tp); + tp->fw_name, rc); } static void rtl_rx_close(struct rtl8169_private *tp) @@ -7331,7 +7314,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->irq_mask = RTL_EVENT_NAPI | cfg->irq_mask; tp->coalesce_info = cfg->coalesce_info; - tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; + tp->fw_name = rtl_chip_infos[chipset].fw_name; tp->counters = dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters), &tp->counters_phys_addr, -- cgit v1.2.3 From e90287f3aaf666c9e18e60f889f82ecfb0ee3c5d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 22 Jan 2019 22:45:25 -0800 Subject: nfp: bpf: don't use instruction number for jump target Instruction number is meaningless at code gen phase. The target of the instruction is overwritten by nfp_fixup_branches(). The convention is to put the raw offset in target address as a place holder. See cmp_* functions. Signed-off-by: Jakub Kicinski Reviewed-by: Quentin Monnet Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/netronome/nfp/bpf/jit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index e23ca90289f7..323587dee498 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c @@ -3182,7 +3182,7 @@ bpf_to_bpf_call(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) wrp_immed_relo(nfp_prog, imm_b(nfp_prog), 0, RELO_IMMED_REL); } else { ret_tgt = nfp_prog_current_offset(nfp_prog) + 2; - emit_br(nfp_prog, BR_UNC, meta->n + 1 + meta->insn.imm, 1); + emit_br(nfp_prog, BR_UNC, meta->insn.imm, 1); offset_br = nfp_prog_current_offset(nfp_prog); } wrp_immed_relo(nfp_prog, ret_reg(nfp_prog), ret_tgt, RELO_IMMED_REL); -- cgit v1.2.3 From 91a87a5823f798f1c7b26783e0d2c6d22a1dc28c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 22 Jan 2019 22:45:26 -0800 Subject: nfp: bpf: split up the skip flag We fail program loading if jump lands on a skipped instruction. This is for historical reasons, it used to be that we only skipped instructions optimized out based on prior context, and therefore the optimization would be buggy if we jumped directly to such instruction (because the context would be skipped by the jump). There are cases where instructions can be skipped without any context, for example there is no point in generating code for: r0 |= 0 We will also soon support dropping dead code, so make the skip logic differentiate between "optimized with preceding context" vs other skip types. Signed-off-by: Jakub Kicinski Reviewed-by: Quentin Monnet Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/netronome/nfp/bpf/jit.c | 36 ++++++++++++++------------- drivers/net/ethernet/netronome/nfp/bpf/main.h | 9 +++++-- 2 files changed, 26 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index 323587dee498..054382b9cbe6 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c @@ -1266,7 +1266,7 @@ wrp_alu64_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, u64 imm = insn->imm; /* sign extend */ if (skip) { - meta->skip = true; + meta->flags |= FLAG_INSN_SKIP_NOOP; return 0; } @@ -1296,7 +1296,7 @@ wrp_alu32_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, const struct bpf_insn *insn = &meta->insn; if (skip) { - meta->skip = true; + meta->flags |= FLAG_INSN_SKIP_NOOP; return 0; } @@ -3395,7 +3395,7 @@ static int nfp_fixup_branches(struct nfp_prog *nfp_prog) int err; list_for_each_entry(meta, &nfp_prog->insns, l) { - if (meta->skip) + if (meta->flags & FLAG_INSN_SKIP_MASK) continue; if (BPF_CLASS(meta->insn.code) != BPF_JMP) continue; @@ -3439,7 +3439,7 @@ static int nfp_fixup_branches(struct nfp_prog *nfp_prog) jmp_dst = meta->jmp_dst; - if (jmp_dst->skip) { + if (jmp_dst->flags & FLAG_INSN_SKIP_PREC_DEPENDENT) { pr_err("Branch landing on removed instruction!!\n"); return -ELOOP; } @@ -3689,7 +3689,7 @@ static int nfp_translate(struct nfp_prog *nfp_prog) return nfp_prog->error; } - if (meta->skip) { + if (meta->flags & FLAG_INSN_SKIP_MASK) { nfp_prog->n_translated++; continue; } @@ -3737,10 +3737,10 @@ static void nfp_bpf_opt_reg_init(struct nfp_prog *nfp_prog) /* Programs start with R6 = R1 but we ignore the skb pointer */ if (insn.code == (BPF_ALU64 | BPF_MOV | BPF_X) && insn.src_reg == 1 && insn.dst_reg == 6) - meta->skip = true; + meta->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT; /* Return as soon as something doesn't match */ - if (!meta->skip) + if (!(meta->flags & FLAG_INSN_SKIP_MASK)) return; } } @@ -3755,7 +3755,7 @@ static void nfp_bpf_opt_neg_add_sub(struct nfp_prog *nfp_prog) list_for_each_entry(meta, &nfp_prog->insns, l) { struct bpf_insn insn = meta->insn; - if (meta->skip) + if (meta->flags & FLAG_INSN_SKIP_MASK) continue; if (BPF_CLASS(insn.code) != BPF_ALU && @@ -3829,7 +3829,7 @@ static void nfp_bpf_opt_ld_mask(struct nfp_prog *nfp_prog) if (meta2->flags & FLAG_INSN_IS_JUMP_DST) continue; - meta2->skip = true; + meta2->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT; } } @@ -3869,8 +3869,8 @@ static void nfp_bpf_opt_ld_shift(struct nfp_prog *nfp_prog) meta3->flags & FLAG_INSN_IS_JUMP_DST) continue; - meta2->skip = true; - meta3->skip = true; + meta2->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT; + meta3->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT; } } @@ -4065,7 +4065,8 @@ static void nfp_bpf_opt_ldst_gather(struct nfp_prog *nfp_prog) } head_ld_meta->paired_st = &head_st_meta->insn; - head_st_meta->skip = true; + head_st_meta->flags |= + FLAG_INSN_SKIP_PREC_DEPENDENT; } else { head_ld_meta->ldst_gather_len = 0; } @@ -4098,8 +4099,8 @@ static void nfp_bpf_opt_ldst_gather(struct nfp_prog *nfp_prog) head_ld_meta = meta1; head_st_meta = meta2; } else { - meta1->skip = true; - meta2->skip = true; + meta1->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT; + meta2->flags |= FLAG_INSN_SKIP_PREC_DEPENDENT; } head_ld_meta->ldst_gather_len += BPF_LDST_BYTES(ld); @@ -4124,7 +4125,7 @@ static void nfp_bpf_opt_pkt_cache(struct nfp_prog *nfp_prog) if (meta->flags & FLAG_INSN_IS_JUMP_DST) cache_avail = false; - if (meta->skip) + if (meta->flags & FLAG_INSN_SKIP_MASK) continue; insn = &meta->insn; @@ -4210,7 +4211,7 @@ start_new: } list_for_each_entry(meta, &nfp_prog->insns, l) { - if (meta->skip) + if (meta->flags & FLAG_INSN_SKIP_MASK) continue; if (is_mbpf_load_pkt(meta) && !meta->ldst_gather_len) { @@ -4246,7 +4247,8 @@ static int nfp_bpf_replace_map_ptrs(struct nfp_prog *nfp_prog) u32 id; nfp_for_each_insn_walk2(nfp_prog, meta1, meta2) { - if (meta1->skip || meta2->skip) + if (meta1->flags & FLAG_INSN_SKIP_MASK || + meta2->flags & FLAG_INSN_SKIP_MASK) continue; if (meta1->insn.code != (BPF_LD | BPF_IMM | BPF_DW) || diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h index 941277936475..40291aedd895 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.h +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h @@ -243,6 +243,13 @@ struct nfp_bpf_reg_state { #define FLAG_INSN_IS_JUMP_DST BIT(0) #define FLAG_INSN_IS_SUBPROG_START BIT(1) #define FLAG_INSN_PTR_CALLER_STACK_FRAME BIT(2) +/* Instruction is pointless, noop even on its own */ +#define FLAG_INSN_SKIP_NOOP BIT(3) +/* Instruction is optimized out based on preceding instructions */ +#define FLAG_INSN_SKIP_PREC_DEPENDENT BIT(4) + +#define FLAG_INSN_SKIP_MASK (FLAG_INSN_SKIP_NOOP | \ + FLAG_INSN_SKIP_PREC_DEPENDENT) /** * struct nfp_insn_meta - BPF instruction wrapper @@ -271,7 +278,6 @@ struct nfp_bpf_reg_state { * @n: eBPF instruction number * @flags: eBPF instruction extra optimization flags * @subprog_idx: index of subprogram to which the instruction belongs - * @skip: skip this instruction (optimized out) * @double_cb: callback for second part of the instruction * @l: link on nfp_prog->insns list */ @@ -319,7 +325,6 @@ struct nfp_insn_meta { unsigned short n; unsigned short flags; unsigned short subprog_idx; - bool skip; instr_cb_t double_cb; struct list_head l; -- cgit v1.2.3 From e2fc61146aa6dea81f3231530c130be72af05c5a Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 22 Jan 2019 22:45:27 -0800 Subject: nfp: bpf: save original program length Instead of passing env->prog->len around, and trying to adjust for optimized out instructions just save the initial number of instructions in struct nfp_prog. Signed-off-by: Jakub Kicinski Reviewed-by: Quentin Monnet Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/netronome/nfp/bpf/jit.c | 4 ++-- drivers/net/ethernet/netronome/nfp/bpf/main.h | 6 ++++-- drivers/net/ethernet/netronome/nfp/bpf/offload.c | 3 ++- drivers/net/ethernet/netronome/nfp/bpf/verifier.c | 16 +++++++--------- 4 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index 054382b9cbe6..3308fd92c017 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c @@ -4327,7 +4327,7 @@ int nfp_bpf_jit(struct nfp_prog *nfp_prog) return ret; } -void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog, unsigned int cnt) +void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog) { struct nfp_insn_meta *meta; @@ -4355,7 +4355,7 @@ void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog, unsigned int cnt) else dst_idx = meta->n + 1 + meta->insn.off; - dst_meta = nfp_bpf_goto_meta(nfp_prog, meta, dst_idx, cnt); + dst_meta = nfp_bpf_goto_meta(nfp_prog, meta, dst_idx); if (pseudo_call) dst_meta->flags |= FLAG_INSN_IS_SUBPROG_START; diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h index 40291aedd895..07879eee3d46 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.h +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h @@ -462,6 +462,7 @@ struct nfp_bpf_subprog_info { * @subprog_cnt: number of sub-programs, including main function * @map_records: the map record pointers from bpf->maps_neutral * @subprog: pointer to an array of objects holding info about sub-programs + * @n_insns: number of instructions on @insns list * @insns: list of BPF instruction wrappers (struct nfp_insn_meta) */ struct nfp_prog { @@ -494,6 +495,7 @@ struct nfp_prog { struct nfp_bpf_neutral_map **map_records; struct nfp_bpf_subprog_info *subprog; + unsigned int n_insns; struct list_head insns; }; @@ -510,7 +512,7 @@ struct nfp_bpf_vnic { }; bool nfp_is_subprog_start(struct nfp_insn_meta *meta); -void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog, unsigned int cnt); +void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog); int nfp_bpf_jit(struct nfp_prog *prog); bool nfp_bpf_supported_opcode(u8 code); @@ -531,7 +533,7 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog, struct nfp_insn_meta * nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, - unsigned int insn_idx, unsigned int n_insns); + unsigned int insn_idx); void *nfp_bpf_relo_for_vnic(struct nfp_prog *nfp_prog, struct nfp_bpf_vnic *bv); diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c index f0283854fade..c10aab392cf6 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c @@ -163,8 +163,9 @@ nfp_prog_prepare(struct nfp_prog *nfp_prog, const struct bpf_insn *prog, list_add_tail(&meta->l, &nfp_prog->insns); } + nfp_prog->n_insns = cnt; - nfp_bpf_jit_prepare(nfp_prog, cnt); + nfp_bpf_jit_prepare(nfp_prog); return 0; } diff --git a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c index 337bb862ec1d..2712ab17d57c 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c @@ -18,15 +18,15 @@ struct nfp_insn_meta * nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, - unsigned int insn_idx, unsigned int n_insns) + unsigned int insn_idx) { unsigned int forward, backward, i; backward = meta->n - insn_idx; forward = insn_idx - meta->n; - if (min(forward, backward) > n_insns - insn_idx - 1) { - backward = n_insns - insn_idx - 1; + if (min(forward, backward) > nfp_prog->n_insns - insn_idx - 1) { + backward = nfp_prog->n_insns - insn_idx - 1; meta = nfp_prog_last_meta(nfp_prog); } if (min(forward, backward) > insn_idx && backward > insn_idx) { @@ -629,7 +629,7 @@ int nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx, struct nfp_prog *nfp_prog = env->prog->aux->offload->dev_priv; struct nfp_insn_meta *meta = nfp_prog->verifier_meta; - meta = nfp_bpf_goto_meta(nfp_prog, meta, insn_idx, env->prog->len); + meta = nfp_bpf_goto_meta(nfp_prog, meta, insn_idx); nfp_prog->verifier_meta = meta; if (!nfp_bpf_supported_opcode(meta->insn.code)) { @@ -690,8 +690,7 @@ nfp_assign_subprog_idx_and_regs(struct bpf_verifier_env *env, return 0; } -static unsigned int -nfp_bpf_get_stack_usage(struct nfp_prog *nfp_prog, unsigned int cnt) +static unsigned int nfp_bpf_get_stack_usage(struct nfp_prog *nfp_prog) { struct nfp_insn_meta *meta = nfp_prog_first_meta(nfp_prog); unsigned int max_depth = 0, depth = 0, frame = 0; @@ -726,7 +725,7 @@ continue_subprog: /* Find the callee and start processing it. */ meta = nfp_bpf_goto_meta(nfp_prog, meta, - meta->n + 1 + meta->insn.imm, cnt); + meta->n + 1 + meta->insn.imm); idx = meta->subprog_idx; frame++; goto process_subprog; @@ -778,8 +777,7 @@ int nfp_bpf_finalize(struct bpf_verifier_env *env) nn = netdev_priv(env->prog->aux->offload->netdev); max_stack = nn_readb(nn, NFP_NET_CFG_BPF_STACK_SZ) * 64; - nfp_prog->stack_size = nfp_bpf_get_stack_usage(nfp_prog, - env->prog->len); + nfp_prog->stack_size = nfp_bpf_get_stack_usage(nfp_prog); if (nfp_prog->stack_size > max_stack) { pr_vlog(env, "stack too large: program %dB > FW stack %dB\n", nfp_prog->stack_size, max_stack); -- cgit v1.2.3 From a32014b351662fd67c7e0f807855f527d0834d00 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 22 Jan 2019 22:45:28 -0800 Subject: nfp: bpf: support optimizing dead branches Verifier will now optimize out branches to dead code, implement the replace_insn callback to take advantage of that optimization. Signed-off-by: Jakub Kicinski Reviewed-by: Quentin Monnet Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/netronome/nfp/bpf/main.h | 14 ++++++++++ drivers/net/ethernet/netronome/nfp/bpf/offload.c | 1 + drivers/net/ethernet/netronome/nfp/bpf/verifier.c | 34 +++++++++++++++++++++++ 3 files changed, 49 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h index 07879eee3d46..a33aa7df1979 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.h +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h @@ -412,6 +412,17 @@ static inline bool is_mbpf_div(const struct nfp_insn_meta *meta) return is_mbpf_alu(meta) && mbpf_op(meta) == BPF_DIV; } +static inline bool is_mbpf_cond_jump(const struct nfp_insn_meta *meta) +{ + u8 op; + + if (BPF_CLASS(meta->insn.code) != BPF_JMP) + return false; + + op = BPF_OP(meta->insn.code); + return op != BPF_JA && op != BPF_EXIT && op != BPF_CALL; +} + static inline bool is_mbpf_helper_call(const struct nfp_insn_meta *meta) { struct bpf_insn insn = meta->insn; @@ -520,6 +531,9 @@ int nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx, int prev_insn_idx); int nfp_bpf_finalize(struct bpf_verifier_env *env); +int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off, + struct bpf_insn *insn); + extern const struct bpf_prog_offload_ops nfp_bpf_dev_ops; struct netdev_bpf; diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c index c10aab392cf6..877c1b8f95e2 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c @@ -592,6 +592,7 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog, const struct bpf_prog_offload_ops nfp_bpf_dev_ops = { .insn_hook = nfp_verify_insn, .finalize = nfp_bpf_finalize, + .replace_insn = nfp_bpf_opt_replace_insn, .prepare = nfp_bpf_verifier_prep, .translate = nfp_bpf_translate, .destroy = nfp_bpf_destroy, diff --git a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c index 2712ab17d57c..32468e1b1b73 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c @@ -786,3 +786,37 @@ int nfp_bpf_finalize(struct bpf_verifier_env *env) return 0; } + +int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off, + struct bpf_insn *insn) +{ + struct nfp_prog *nfp_prog = env->prog->aux->offload->dev_priv; + struct bpf_insn_aux_data *aux_data = env->insn_aux_data; + struct nfp_insn_meta *meta = nfp_prog->verifier_meta; + + meta = nfp_bpf_goto_meta(nfp_prog, meta, aux_data[off].orig_idx); + nfp_prog->verifier_meta = meta; + + /* conditional jump to jump conversion */ + if (is_mbpf_cond_jump(meta) && + insn->code == (BPF_JMP | BPF_JA | BPF_K)) { + unsigned int tgt_off; + + tgt_off = off + insn->off + 1; + + if (!insn->off) { + meta->jmp_dst = list_next_entry(meta, l); + meta->jump_neg_op = false; + } else if (meta->jmp_dst->n != aux_data[tgt_off].orig_idx) { + pr_vlog(env, "branch hard wire at %d changes target %d -> %d\n", + off, meta->jmp_dst->n, + aux_data[tgt_off].orig_idx); + return -EINVAL; + } + return 0; + } + + pr_vlog(env, "unsupported instruction replacement %hhx -> %hhx\n", + meta->insn.code, insn->code); + return -EINVAL; +} -- cgit v1.2.3 From 9a06927e778bc4e805acc8fa03573bbf7e597cc5 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 22 Jan 2019 22:45:29 -0800 Subject: nfp: bpf: support removing dead code Add a verifier callback to the nfp JIT to remove the instructions the verifier deemed to be dead. Signed-off-by: Jakub Kicinski Reviewed-by: Quentin Monnet Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/netronome/nfp/bpf/main.h | 6 +++++- drivers/net/ethernet/netronome/nfp/bpf/offload.c | 5 +++++ drivers/net/ethernet/netronome/nfp/bpf/verifier.c | 24 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h index a33aa7df1979..5813c3e13ebe 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.h +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h @@ -247,9 +247,12 @@ struct nfp_bpf_reg_state { #define FLAG_INSN_SKIP_NOOP BIT(3) /* Instruction is optimized out based on preceding instructions */ #define FLAG_INSN_SKIP_PREC_DEPENDENT BIT(4) +/* Instruction is optimized by the verifier */ +#define FLAG_INSN_SKIP_VERIFIER_OPT BIT(5) #define FLAG_INSN_SKIP_MASK (FLAG_INSN_SKIP_NOOP | \ - FLAG_INSN_SKIP_PREC_DEPENDENT) + FLAG_INSN_SKIP_PREC_DEPENDENT | \ + FLAG_INSN_SKIP_VERIFIER_OPT) /** * struct nfp_insn_meta - BPF instruction wrapper @@ -533,6 +536,7 @@ int nfp_bpf_finalize(struct bpf_verifier_env *env); int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off, struct bpf_insn *insn); +int nfp_bpf_opt_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt); extern const struct bpf_prog_offload_ops nfp_bpf_dev_ops; diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c index 877c1b8f95e2..55c7dbf8b421 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c @@ -220,6 +220,10 @@ static int nfp_bpf_translate(struct bpf_prog *prog) unsigned int max_instr; int err; + /* We depend on dead code elimination succeeding */ + if (prog->aux->offload->opt_failed) + return -EINVAL; + max_instr = nn_readw(nn, NFP_NET_CFG_BPF_MAX_LEN); nfp_prog->__prog_alloc_len = max_instr * sizeof(u64); @@ -593,6 +597,7 @@ const struct bpf_prog_offload_ops nfp_bpf_dev_ops = { .insn_hook = nfp_verify_insn, .finalize = nfp_bpf_finalize, .replace_insn = nfp_bpf_opt_replace_insn, + .remove_insns = nfp_bpf_opt_remove_insns, .prepare = nfp_bpf_verifier_prep, .translate = nfp_bpf_translate, .destroy = nfp_bpf_destroy, diff --git a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c index 32468e1b1b73..36f56eb4cbe2 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/verifier.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/verifier.c @@ -820,3 +820,27 @@ int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off, meta->insn.code, insn->code); return -EINVAL; } + +int nfp_bpf_opt_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt) +{ + struct nfp_prog *nfp_prog = env->prog->aux->offload->dev_priv; + struct bpf_insn_aux_data *aux_data = env->insn_aux_data; + struct nfp_insn_meta *meta = nfp_prog->verifier_meta; + unsigned int i; + + meta = nfp_bpf_goto_meta(nfp_prog, meta, aux_data[off].orig_idx); + + for (i = 0; i < cnt; i++) { + if (WARN_ON_ONCE(&meta->l == &nfp_prog->insns)) + return -EINVAL; + + /* doesn't count if it already has the flag */ + if (meta->flags & FLAG_INSN_SKIP_VERIFIER_OPT) + i--; + + meta->flags |= FLAG_INSN_SKIP_VERIFIER_OPT; + meta = list_next_entry(meta, l); + } + + return 0; +} -- cgit v1.2.3 From e355477ed9e4f401e3931043df97325d38552d54 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Fri, 18 Jan 2019 16:33:10 -0800 Subject: net/mlx5: Make mlx5_cmd_exec_cb() a safe API APIs that have deferred callbacks should have some kind of cleanup function that callers can use to fence the callbacks. Otherwise things like module unloading can lead to dangling function pointers, or worse. The IB MR code is the only place that calls this function and had a really poor attempt at creating this fence. Provide a good version in the core code as future patches will add more places that need this fence. Signed-off-by: Jason Gunthorpe Signed-off-by: Yishai Hadas Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/mlx5/mlx5_ib.h | 2 + drivers/infiniband/hw/mlx5/mr.c | 39 ++++--------------- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 55 ++++++++++++++++++++++++--- drivers/net/ethernet/mellanox/mlx5/core/mr.c | 11 +++--- include/linux/mlx5/driver.h | 32 +++++++++++++--- 5 files changed, 91 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index efe383c0ac86..eedba0d2ec4b 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -587,6 +587,7 @@ struct mlx5_ib_mr { struct mlx5_ib_mr *parent; atomic_t num_leaf_free; wait_queue_head_t q_leaf_free; + struct mlx5_async_work cb_work; }; struct mlx5_ib_mw { @@ -944,6 +945,7 @@ struct mlx5_ib_dev { struct mlx5_memic memic; u16 devx_whitelist_uid; struct mlx5_srq_table srq_table; + struct mlx5_async_ctx async_ctx; }; static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq) diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c index fd6ea1f75085..bf2b6ea23851 100644 --- a/drivers/infiniband/hw/mlx5/mr.c +++ b/drivers/infiniband/hw/mlx5/mr.c @@ -123,9 +123,10 @@ static void update_odp_mr(struct mlx5_ib_mr *mr) } #endif -static void reg_mr_callback(int status, void *context) +static void reg_mr_callback(int status, struct mlx5_async_work *context) { - struct mlx5_ib_mr *mr = context; + struct mlx5_ib_mr *mr = + container_of(context, struct mlx5_ib_mr, cb_work); struct mlx5_ib_dev *dev = mr->dev; struct mlx5_mr_cache *cache = &dev->cache; int c = order2idx(dev, mr->order); @@ -216,9 +217,9 @@ static int add_keys(struct mlx5_ib_dev *dev, int c, int num) ent->pending++; spin_unlock_irq(&ent->lock); err = mlx5_core_create_mkey_cb(dev->mdev, &mr->mmkey, - in, inlen, + &dev->async_ctx, in, inlen, mr->out, sizeof(mr->out), - reg_mr_callback, mr); + reg_mr_callback, &mr->cb_work); if (err) { spin_lock_irq(&ent->lock); ent->pending--; @@ -679,6 +680,7 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev) return -ENOMEM; } + mlx5_cmd_init_async_ctx(dev->mdev, &dev->async_ctx); timer_setup(&dev->delay_timer, delay_time_func, 0); for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) { ent = &cache->ent[i]; @@ -725,33 +727,6 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev) return 0; } -static void wait_for_async_commands(struct mlx5_ib_dev *dev) -{ - struct mlx5_mr_cache *cache = &dev->cache; - struct mlx5_cache_ent *ent; - int total = 0; - int i; - int j; - - for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) { - ent = &cache->ent[i]; - for (j = 0 ; j < 1000; j++) { - if (!ent->pending) - break; - msleep(50); - } - } - for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) { - ent = &cache->ent[i]; - total += ent->pending; - } - - if (total) - mlx5_ib_warn(dev, "aborted while there are %d pending mr requests\n", total); - else - mlx5_ib_warn(dev, "done with all pending requests\n"); -} - int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev) { int i; @@ -763,12 +738,12 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev) flush_workqueue(dev->cache.wq); mlx5_mr_cache_debugfs_cleanup(dev); + mlx5_cmd_cleanup_async_ctx(&dev->async_ctx); for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) clean_keys(dev, i); destroy_workqueue(dev->cache.wq); - wait_for_async_commands(dev); del_timer_sync(&dev->delay_timer); return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 3e0fa8a8077b..a25a8c6f938e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1711,12 +1711,57 @@ int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, } EXPORT_SYMBOL(mlx5_cmd_exec); -int mlx5_cmd_exec_cb(struct mlx5_core_dev *dev, void *in, int in_size, - void *out, int out_size, mlx5_cmd_cbk_t callback, - void *context) +void mlx5_cmd_init_async_ctx(struct mlx5_core_dev *dev, + struct mlx5_async_ctx *ctx) { - return cmd_exec(dev, in, in_size, out, out_size, callback, context, - false); + ctx->dev = dev; + /* Starts at 1 to avoid doing wake_up if we are not cleaning up */ + atomic_set(&ctx->num_inflight, 1); + init_waitqueue_head(&ctx->wait); +} +EXPORT_SYMBOL(mlx5_cmd_init_async_ctx); + +/** + * mlx5_cmd_cleanup_async_ctx - Clean up an async_ctx + * @ctx: The ctx to clean + * + * Upon return all callbacks given to mlx5_cmd_exec_cb() have been called. The + * caller must ensure that mlx5_cmd_exec_cb() is not called during or after + * the call mlx5_cleanup_async_ctx(). + */ +void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx) +{ + atomic_dec(&ctx->num_inflight); + wait_event(ctx->wait, atomic_read(&ctx->num_inflight) == 0); +} +EXPORT_SYMBOL(mlx5_cmd_cleanup_async_ctx); + +static void mlx5_cmd_exec_cb_handler(int status, void *_work) +{ + struct mlx5_async_work *work = _work; + struct mlx5_async_ctx *ctx = work->ctx; + + work->user_callback(status, work); + if (atomic_dec_and_test(&ctx->num_inflight)) + wake_up(&ctx->wait); +} + +int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, + void *out, int out_size, mlx5_async_cbk_t callback, + struct mlx5_async_work *work) +{ + int ret; + + work->ctx = ctx; + work->user_callback = callback; + if (WARN_ON(!atomic_inc_not_zero(&ctx->num_inflight))) + return -EIO; + ret = cmd_exec(ctx->dev, in, in_size, out, out_size, + mlx5_cmd_exec_cb_handler, work, false); + if (ret && atomic_dec_and_test(&ctx->num_inflight)) + wake_up(&ctx->wait); + + return ret; } EXPORT_SYMBOL(mlx5_cmd_exec_cb); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mr.c b/drivers/net/ethernet/mellanox/mlx5/core/mr.c index 0670165afd5f..ea744d8466ea 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mr.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/mr.c @@ -51,9 +51,10 @@ void mlx5_cleanup_mkey_table(struct mlx5_core_dev *dev) int mlx5_core_create_mkey_cb(struct mlx5_core_dev *dev, struct mlx5_core_mkey *mkey, - u32 *in, int inlen, - u32 *out, int outlen, - mlx5_cmd_cbk_t callback, void *context) + struct mlx5_async_ctx *async_ctx, u32 *in, + int inlen, u32 *out, int outlen, + mlx5_async_cbk_t callback, + struct mlx5_async_work *context) { struct mlx5_mkey_table *table = &dev->priv.mkey_table; u32 lout[MLX5_ST_SZ_DW(create_mkey_out)] = {0}; @@ -71,7 +72,7 @@ int mlx5_core_create_mkey_cb(struct mlx5_core_dev *dev, MLX5_SET(mkc, mkc, mkey_7_0, key); if (callback) - return mlx5_cmd_exec_cb(dev, in, inlen, out, outlen, + return mlx5_cmd_exec_cb(async_ctx, in, inlen, out, outlen, callback, context); err = mlx5_cmd_exec(dev, in, inlen, lout, sizeof(lout)); @@ -105,7 +106,7 @@ int mlx5_core_create_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mkey *mkey, u32 *in, int inlen) { - return mlx5_core_create_mkey_cb(dev, mkey, in, inlen, + return mlx5_core_create_mkey_cb(dev, mkey, NULL, in, inlen, NULL, 0, NULL, NULL); } EXPORT_SYMBOL(mlx5_core_create_mkey); diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 4e444863054a..039c9398614c 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -850,11 +850,30 @@ void mlx5_cmd_cleanup(struct mlx5_core_dev *dev); void mlx5_cmd_use_events(struct mlx5_core_dev *dev); void mlx5_cmd_use_polling(struct mlx5_core_dev *dev); +struct mlx5_async_ctx { + struct mlx5_core_dev *dev; + atomic_t num_inflight; + struct wait_queue_head wait; +}; + +struct mlx5_async_work; + +typedef void (*mlx5_async_cbk_t)(int status, struct mlx5_async_work *context); + +struct mlx5_async_work { + struct mlx5_async_ctx *ctx; + mlx5_async_cbk_t user_callback; +}; + +void mlx5_cmd_init_async_ctx(struct mlx5_core_dev *dev, + struct mlx5_async_ctx *ctx); +void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx); +int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, + void *out, int out_size, mlx5_async_cbk_t callback, + struct mlx5_async_work *work); + int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int out_size); -int mlx5_cmd_exec_cb(struct mlx5_core_dev *dev, void *in, int in_size, - void *out, int out_size, mlx5_cmd_cbk_t callback, - void *context); int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int out_size); void mlx5_cmd_mbox_status(void *out, u8 *status, u32 *syndrome); @@ -885,9 +904,10 @@ void mlx5_init_mkey_table(struct mlx5_core_dev *dev); void mlx5_cleanup_mkey_table(struct mlx5_core_dev *dev); int mlx5_core_create_mkey_cb(struct mlx5_core_dev *dev, struct mlx5_core_mkey *mkey, - u32 *in, int inlen, - u32 *out, int outlen, - mlx5_cmd_cbk_t callback, void *context); + struct mlx5_async_ctx *async_ctx, u32 *in, + int inlen, u32 *out, int outlen, + mlx5_async_cbk_t callback, + struct mlx5_async_work *context); int mlx5_core_create_mkey(struct mlx5_core_dev *dev, struct mlx5_core_mkey *mkey, u32 *in, int inlen); -- cgit v1.2.3 From ce4eee5340a966f633fee1e8603aafd223ca394a Mon Sep 17 00:00:00 2001 From: Michael Guralnik Date: Fri, 18 Jan 2019 16:33:11 -0800 Subject: net/mlx5: Add pci AtomicOps request Calling pci_enable_atomic_ops_to_root enables AtomicOp requests to pci root port. AtomicOp requests will be enabled only if the completer and all intermediate pci bridges support PCI atomic operations. This, together with appropriate settings in the NVCONFIG should enable PCI atomic operations on the device. PCI atomic operations were first introduced in PCI Express Base Specification 2.1. The Supported operations are Swap (Unconditional Swap), CAS (Compare and Swap) and FetchAdd (Fetch and Add). Unlike other atomic operation modes PCI atomic operations gives the user the option to do atomic operations on local memory, without involving verbs api, without it compromising the operation's atomicity. Signed-off-by: Michael Guralnik Reviewed-by: Majd Dibbiny Signed-off-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index be81b319b0dc..085e1133b8d5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -693,6 +693,11 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv) goto err_clr_master; } + if (pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP32) && + pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP64) && + pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP128)) + mlx5_core_dbg(dev, "Enabling pci atomics failed\n"); + dev->iseg_base = pci_resource_start(dev->pdev, 0); dev->iseg = ioremap(dev->iseg_base, sizeof(*dev->iseg)); if (!dev->iseg) { -- cgit v1.2.3 From 5e5b9f6272f2c537c43bc80607079cdf8fdb50aa Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Tue, 22 Jan 2019 15:25:50 +0200 Subject: net/mlx4_core: A write memory barrier is sufficient in EQ ci update Soften the memory barrier call of mb() by a sufficient wmb() in the consumer index update of the event queues. Suggested-by: Eric Dumazet Signed-off-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/eq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 2f4201023836..a5be27772b8e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -100,7 +100,7 @@ static void eq_set_ci(struct mlx4_eq *eq, int req_not) req_not << 31), eq->doorbell); /* We still want ordering, just not swabbing, so add a barrier */ - mb(); + wmb(); } static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry, u8 eqe_factor, -- cgit v1.2.3 From d4fd0404c1c95b17880f254ebfee3485693fa8ba Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 22 Jan 2019 15:29:54 +0200 Subject: enetc: Introduce basic PF and VF ENETC ethernet drivers ENETC is a multi-port virtualized Ethernet controller supporting GbE designs and Time-Sensitive Networking (TSN) functionality. ENETC is operating as an SR-IOV multi-PF capable Root Complex Integrated Endpoint (RCIE). As such, it contains multiple physical (PF) and virtual (VF) PCIe functions, discoverable by standard PCI Express. Introduce basic PF and VF ENETC ethernet drivers. The PF has access to the ENETC Port registers and resources and makes the required privileged configurations for the underlying VF devices. Common functionality is controlled through so called System Interface (SI) register blocks, PFs and VFs own a SI each. Though SI register blocks are almost identical, there are a few privileged SI level controls that are accessible only to PFs, and so the distinction is made between PF SIs (PSI) and VF SIs (VSI). As such, the bulk of the code, including datapath processing, basic h/w offload support and generic pci related configuration, is shared between the 2 drivers and is factored out in common source files (i.e. enetc.c). Major functionalities included (for both drivers): MSI-X support for Rx and Tx processing, assignment of Rx/Tx BD ring pairs to MSI-X entries, multi-queue support, Rx S/G (Rx frame fragmentation) and jumbo frame (up to 9600B) support, Rx paged allocation and reuse, Tx S/G support (NETIF_F_SG), Rx and Tx checksum offload, PF MAC filtering and initial control ring support, VLAN extraction/ insertion, PF Rx VLAN CTAG filtering, VF mac address config support, VF VLAN isolation support, etc. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- MAINTAINERS | 6 + drivers/net/ethernet/freescale/Kconfig | 1 + drivers/net/ethernet/freescale/Makefile | 3 + drivers/net/ethernet/freescale/enetc/Kconfig | 19 + drivers/net/ethernet/freescale/enetc/Makefile | 14 + drivers/net/ethernet/freescale/enetc/enetc.c | 1526 ++++++++++++++++++++ drivers/net/ethernet/freescale/enetc/enetc.h | 200 +++ drivers/net/ethernet/freescale/enetc/enetc_cbdr.c | 110 ++ .../net/ethernet/freescale/enetc/enetc_ethtool.c | 137 ++ drivers/net/ethernet/freescale/enetc/enetc_hw.h | 351 +++++ drivers/net/ethernet/freescale/enetc/enetc_pf.c | 831 +++++++++++ drivers/net/ethernet/freescale/enetc/enetc_pf.h | 32 + drivers/net/ethernet/freescale/enetc/enetc_vf.c | 160 ++ 13 files changed, 3390 insertions(+) create mode 100644 drivers/net/ethernet/freescale/enetc/Kconfig create mode 100644 drivers/net/ethernet/freescale/enetc/Makefile create mode 100644 drivers/net/ethernet/freescale/enetc/enetc.c create mode 100644 drivers/net/ethernet/freescale/enetc/enetc.h create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_cbdr.c create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_ethtool.c create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_hw.h create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_pf.c create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_pf.h create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_vf.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index d5d36cedf0b9..a0245fd1b09a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6023,6 +6023,12 @@ L: linuxppc-dev@lists.ozlabs.org S: Maintained F: drivers/dma/fsldma.* +FREESCALE ENETC ETHERNET DRIVERS +M: Claudiu Manoil +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/ethernet/freescale/enetc/ + FREESCALE eTSEC ETHERNET DRIVER (GIANFAR) M: Claudiu Manoil L: netdev@vger.kernel.org diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig index d3a62bc1f1c6..71793e03c3c8 100644 --- a/drivers/net/ethernet/freescale/Kconfig +++ b/drivers/net/ethernet/freescale/Kconfig @@ -97,5 +97,6 @@ config GIANFAR source "drivers/net/ethernet/freescale/dpaa/Kconfig" source "drivers/net/ethernet/freescale/dpaa2/Kconfig" +source "drivers/net/ethernet/freescale/enetc/Kconfig" endif # NET_VENDOR_FREESCALE diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile index 3b4ff08e3841..6a93293d31e0 100644 --- a/drivers/net/ethernet/freescale/Makefile +++ b/drivers/net/ethernet/freescale/Makefile @@ -23,3 +23,6 @@ obj-$(CONFIG_FSL_FMAN) += fman/ obj-$(CONFIG_FSL_DPAA_ETH) += dpaa/ obj-$(CONFIG_FSL_DPAA2_ETH) += dpaa2/ + +obj-$(CONFIG_FSL_ENETC) += enetc/ +obj-$(CONFIG_FSL_ENETC_VF) += enetc/ diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig new file mode 100644 index 000000000000..f9dd26fbfc83 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +config FSL_ENETC + tristate "ENETC PF driver" + depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST) + help + This driver supports NXP ENETC gigabit ethernet controller PCIe + physical function (PF) devices, managing ENETC Ports at a privileged + level. + + If compiled as module (M), the module name is fsl-enetc. + +config FSL_ENETC_VF + tristate "ENETC VF driver" + depends on PCI && PCI_MSI && (ARCH_LAYERSCAPE || COMPILE_TEST) + help + This driver supports NXP ENETC gigabit ethernet controller PCIe + virtual function (VF) devices enabled by the ENETC PF driver. + + If compiled as module (M), the module name is fsl-enetc-vf. diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile new file mode 100644 index 000000000000..a85ef2b475fe --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o +fsl-enetc-$(CONFIG_FSL_ENETC) += enetc.o enetc_cbdr.o enetc_ethtool.o +fsl-enetc-objs := enetc_pf.o $(fsl-enetc-y) + +obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o + +ifeq ($(CONFIG_FSL_ENETC)$(CONFIG_FSL_ENETC_VF), yy) +fsl-enetc-vf-objs := enetc_vf.o +else +fsl-enetc-vf-$(CONFIG_FSL_ENETC_VF) += enetc.o enetc_cbdr.o \ + enetc_ethtool.o +fsl-enetc-vf-objs := enetc_vf.o $(fsl-enetc-vf-y) +endif diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c new file mode 100644 index 000000000000..f63be02cffae --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -0,0 +1,1526 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2017-2019 NXP */ + +#include "enetc.h" +#include +#include +#include + +/* ENETC overhead: optional extension BD + 1 BD gap */ +#define ENETC_TXBDS_NEEDED(val) ((val) + 2) +/* max # of chained Tx BDs is 15, including head and extension BD */ +#define ENETC_MAX_SKB_FRAGS 13 +#define ENETC_TXBDS_MAX_NEEDED ENETC_TXBDS_NEEDED(ENETC_MAX_SKB_FRAGS + 1) + +static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb); + +netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_bdr *tx_ring; + int count; + + tx_ring = priv->tx_ring[skb->queue_mapping]; + + if (unlikely(skb_shinfo(skb)->nr_frags > ENETC_MAX_SKB_FRAGS)) + if (unlikely(skb_linearize(skb))) + goto drop_packet_err; + + count = skb_shinfo(skb)->nr_frags + 1; /* fragments + head */ + if (enetc_bd_unused(tx_ring) < ENETC_TXBDS_NEEDED(count)) { + netif_stop_subqueue(ndev, tx_ring->index); + return NETDEV_TX_BUSY; + } + + count = enetc_map_tx_buffs(tx_ring, skb); + if (unlikely(!count)) + goto drop_packet_err; + + if (enetc_bd_unused(tx_ring) < ENETC_TXBDS_MAX_NEEDED) + netif_stop_subqueue(ndev, tx_ring->index); + + return NETDEV_TX_OK; + +drop_packet_err: + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +static bool enetc_tx_csum(struct sk_buff *skb, union enetc_tx_bd *txbd) +{ + int l3_start, l3_hsize; + u16 l3_flags, l4_flags; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return false; + + switch (skb->csum_offset) { + case offsetof(struct tcphdr, check): + l4_flags = ENETC_TXBD_L4_TCP; + break; + case offsetof(struct udphdr, check): + l4_flags = ENETC_TXBD_L4_UDP; + break; + default: + skb_checksum_help(skb); + return false; + } + + l3_start = skb_network_offset(skb); + l3_hsize = skb_network_header_len(skb); + + l3_flags = 0; + if (skb->protocol == htons(ETH_P_IPV6)) + l3_flags = ENETC_TXBD_L3_IPV6; + + /* write BD fields */ + txbd->l3_csoff = enetc_txbd_l3_csoff(l3_start, l3_hsize, l3_flags); + txbd->l4_csoff = l4_flags; + + return true; +} + +static void enetc_unmap_tx_buff(struct enetc_bdr *tx_ring, + struct enetc_tx_swbd *tx_swbd) +{ + if (tx_swbd->is_dma_page) + dma_unmap_page(tx_ring->dev, tx_swbd->dma, + tx_swbd->len, DMA_TO_DEVICE); + else + dma_unmap_single(tx_ring->dev, tx_swbd->dma, + tx_swbd->len, DMA_TO_DEVICE); + tx_swbd->dma = 0; +} + +static void enetc_free_tx_skb(struct enetc_bdr *tx_ring, + struct enetc_tx_swbd *tx_swbd) +{ + if (tx_swbd->dma) + enetc_unmap_tx_buff(tx_ring, tx_swbd); + + if (tx_swbd->skb) { + dev_kfree_skb_any(tx_swbd->skb); + tx_swbd->skb = NULL; + } +} + +static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb) +{ + struct enetc_tx_swbd *tx_swbd; + struct skb_frag_struct *frag; + int len = skb_headlen(skb); + union enetc_tx_bd temp_bd; + union enetc_tx_bd *txbd; + bool do_vlan, do_tstamp; + int i, count = 0; + unsigned int f; + dma_addr_t dma; + u8 flags = 0; + + i = tx_ring->next_to_use; + txbd = ENETC_TXBD(*tx_ring, i); + prefetchw(txbd); + + dma = dma_map_single(tx_ring->dev, skb->data, len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(tx_ring->dev, dma))) + goto dma_err; + + temp_bd.addr = cpu_to_le64(dma); + temp_bd.buf_len = cpu_to_le16(len); + temp_bd.lstatus = 0; + + tx_swbd = &tx_ring->tx_swbd[i]; + tx_swbd->dma = dma; + tx_swbd->len = len; + tx_swbd->is_dma_page = 0; + count++; + + do_vlan = skb_vlan_tag_present(skb); + do_tstamp = skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP; + + if (do_vlan || do_tstamp) + flags |= ENETC_TXBD_FLAGS_EX; + + if (enetc_tx_csum(skb, &temp_bd)) + flags |= ENETC_TXBD_FLAGS_CSUM | ENETC_TXBD_FLAGS_L4CS; + + /* first BD needs frm_len and offload flags set */ + temp_bd.frm_len = cpu_to_le16(skb->len); + temp_bd.flags = flags; + + if (flags & ENETC_TXBD_FLAGS_EX) { + u8 e_flags = 0; + *txbd = temp_bd; + enetc_clear_tx_bd(&temp_bd); + + /* add extension BD for VLAN and/or timestamping */ + flags = 0; + tx_swbd++; + txbd++; + i++; + if (unlikely(i == tx_ring->bd_count)) { + i = 0; + tx_swbd = tx_ring->tx_swbd; + txbd = ENETC_TXBD(*tx_ring, 0); + } + prefetchw(txbd); + + if (do_vlan) { + temp_bd.ext.vid = cpu_to_le16(skb_vlan_tag_get(skb)); + temp_bd.ext.tpid = 0; /* < C-TAG */ + e_flags |= ENETC_TXBD_E_FLAGS_VLAN_INS; + } + + if (do_tstamp) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + e_flags |= ENETC_TXBD_E_FLAGS_TWO_STEP_PTP; + } + + temp_bd.ext.e_flags = e_flags; + count++; + } + + frag = &skb_shinfo(skb)->frags[0]; + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++, frag++) { + len = skb_frag_size(frag); + dma = skb_frag_dma_map(tx_ring->dev, frag, 0, len, + DMA_TO_DEVICE); + if (dma_mapping_error(tx_ring->dev, dma)) + goto dma_err; + + *txbd = temp_bd; + enetc_clear_tx_bd(&temp_bd); + + flags = 0; + tx_swbd++; + txbd++; + i++; + if (unlikely(i == tx_ring->bd_count)) { + i = 0; + tx_swbd = tx_ring->tx_swbd; + txbd = ENETC_TXBD(*tx_ring, 0); + } + prefetchw(txbd); + + temp_bd.addr = cpu_to_le64(dma); + temp_bd.buf_len = cpu_to_le16(len); + + tx_swbd->dma = dma; + tx_swbd->len = len; + tx_swbd->is_dma_page = 1; + count++; + } + + /* last BD needs 'F' bit set */ + flags |= ENETC_TXBD_FLAGS_F; + temp_bd.flags = flags; + *txbd = temp_bd; + + tx_ring->tx_swbd[i].skb = skb; + + enetc_bdr_idx_inc(tx_ring, &i); + tx_ring->next_to_use = i; + + /* let H/W know BD ring has been updated */ + enetc_wr_reg(tx_ring->tpir, i); /* includes wmb() */ + + return count; + +dma_err: + dev_err(tx_ring->dev, "DMA map error"); + + do { + tx_swbd = &tx_ring->tx_swbd[i]; + enetc_free_tx_skb(tx_ring, tx_swbd); + if (i == 0) + i = tx_ring->bd_count; + i--; + } while (count--); + + return 0; +} + +static irqreturn_t enetc_msix(int irq, void *data) +{ + struct enetc_int_vector *v = data; + int i; + + /* disable interrupts */ + enetc_wr_reg(v->rbier, 0); + + for_each_set_bit(i, &v->tx_rings_map, v->count_tx_rings) + enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i), 0); + + napi_schedule_irqoff(&v->napi); + + return IRQ_HANDLED; +} + +static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget); +static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, + struct napi_struct *napi, int work_limit); + +static int enetc_poll(struct napi_struct *napi, int budget) +{ + struct enetc_int_vector + *v = container_of(napi, struct enetc_int_vector, napi); + bool complete = true; + int work_done; + int i; + + for (i = 0; i < v->count_tx_rings; i++) + if (!enetc_clean_tx_ring(&v->tx_ring[i], budget)) + complete = false; + + work_done = enetc_clean_rx_ring(&v->rx_ring, napi, budget); + if (work_done == budget) + complete = false; + + if (!complete) + return budget; + + napi_complete_done(napi, work_done); + + /* enable interrupts */ + enetc_wr_reg(v->rbier, ENETC_RBIER_RXTIE); + + for_each_set_bit(i, &v->tx_rings_map, v->count_tx_rings) + enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i), + ENETC_TBIER_TXTIE); + + return work_done; +} + +static int enetc_bd_ready_count(struct enetc_bdr *tx_ring, int ci) +{ + int pi = enetc_rd_reg(tx_ring->tcir) & ENETC_TBCIR_IDX_MASK; + + return pi >= ci ? pi - ci : tx_ring->bd_count - ci + pi; +} + +static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget) +{ + struct net_device *ndev = tx_ring->ndev; + int tx_frm_cnt = 0, tx_byte_cnt = 0; + struct enetc_tx_swbd *tx_swbd; + int i, bds_to_clean; + + i = tx_ring->next_to_clean; + tx_swbd = &tx_ring->tx_swbd[i]; + bds_to_clean = enetc_bd_ready_count(tx_ring, i); + + while (bds_to_clean && tx_frm_cnt < ENETC_DEFAULT_TX_WORK) { + bool is_eof = !!tx_swbd->skb; + + enetc_unmap_tx_buff(tx_ring, tx_swbd); + if (is_eof) { + napi_consume_skb(tx_swbd->skb, napi_budget); + tx_swbd->skb = NULL; + } + + tx_byte_cnt += tx_swbd->len; + + bds_to_clean--; + tx_swbd++; + i++; + if (unlikely(i == tx_ring->bd_count)) { + i = 0; + tx_swbd = tx_ring->tx_swbd; + } + + /* BD iteration loop end */ + if (is_eof) { + tx_frm_cnt++; + /* re-arm interrupt source */ + enetc_wr_reg(tx_ring->idr, BIT(tx_ring->index) | + BIT(16 + tx_ring->index)); + } + + if (unlikely(!bds_to_clean)) + bds_to_clean = enetc_bd_ready_count(tx_ring, i); + } + + tx_ring->next_to_clean = i; + tx_ring->stats.packets += tx_frm_cnt; + tx_ring->stats.bytes += tx_byte_cnt; + + if (unlikely(tx_frm_cnt && netif_carrier_ok(ndev) && + __netif_subqueue_stopped(ndev, tx_ring->index) && + (enetc_bd_unused(tx_ring) >= ENETC_TXBDS_MAX_NEEDED))) { + netif_wake_subqueue(ndev, tx_ring->index); + } + + return tx_frm_cnt != ENETC_DEFAULT_TX_WORK; +} + +static bool enetc_new_page(struct enetc_bdr *rx_ring, + struct enetc_rx_swbd *rx_swbd) +{ + struct page *page; + dma_addr_t addr; + + page = dev_alloc_page(); + if (unlikely(!page)) + return false; + + addr = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(rx_ring->dev, addr))) { + __free_page(page); + + return false; + } + + rx_swbd->dma = addr; + rx_swbd->page = page; + rx_swbd->page_offset = ENETC_RXB_PAD; + + return true; +} + +static int enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt) +{ + struct enetc_rx_swbd *rx_swbd; + union enetc_rx_bd *rxbd; + int i, j; + + i = rx_ring->next_to_use; + rx_swbd = &rx_ring->rx_swbd[i]; + rxbd = ENETC_RXBD(*rx_ring, i); + + for (j = 0; j < buff_cnt; j++) { + /* try reuse page */ + if (unlikely(!rx_swbd->page)) { + if (unlikely(!enetc_new_page(rx_ring, rx_swbd))) { + rx_ring->stats.rx_alloc_errs++; + break; + } + } + + /* update RxBD */ + rxbd->w.addr = cpu_to_le64(rx_swbd->dma + + rx_swbd->page_offset); + /* clear 'R" as well */ + rxbd->r.lstatus = 0; + + rx_swbd++; + rxbd++; + i++; + if (unlikely(i == rx_ring->bd_count)) { + i = 0; + rx_swbd = rx_ring->rx_swbd; + rxbd = ENETC_RXBD(*rx_ring, 0); + } + } + + if (likely(j)) { + rx_ring->next_to_alloc = i; /* keep track from page reuse */ + rx_ring->next_to_use = i; + /* update ENETC's consumer index */ + enetc_wr_reg(rx_ring->rcir, i); + } + + return j; +} + +static void enetc_get_offloads(struct enetc_bdr *rx_ring, + union enetc_rx_bd *rxbd, struct sk_buff *skb) +{ + /* TODO: add tstamp, hashing */ + if (rx_ring->ndev->features & NETIF_F_RXCSUM) { + u16 inet_csum = le16_to_cpu(rxbd->r.inet_csum); + + skb->csum = csum_unfold((__force __sum16)~htons(inet_csum)); + skb->ip_summed = CHECKSUM_COMPLETE; + } + + /* copy VLAN to skb, if one is extracted, for now we assume it's a + * standard TPID, but HW also supports custom values + */ + if (le16_to_cpu(rxbd->r.flags) & ENETC_RXBD_FLAG_VLAN) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + le16_to_cpu(rxbd->r.vlan_opt)); +} + +static void enetc_process_skb(struct enetc_bdr *rx_ring, + struct sk_buff *skb) +{ + skb_record_rx_queue(skb, rx_ring->index); + skb->protocol = eth_type_trans(skb, rx_ring->ndev); +} + +static bool enetc_page_reusable(struct page *page) +{ + return (!page_is_pfmemalloc(page) && page_ref_count(page) == 1); +} + +static void enetc_reuse_page(struct enetc_bdr *rx_ring, + struct enetc_rx_swbd *old) +{ + struct enetc_rx_swbd *new; + + new = &rx_ring->rx_swbd[rx_ring->next_to_alloc]; + + /* next buf that may reuse a page */ + enetc_bdr_idx_inc(rx_ring, &rx_ring->next_to_alloc); + + /* copy page reference */ + *new = *old; +} + +static struct enetc_rx_swbd *enetc_get_rx_buff(struct enetc_bdr *rx_ring, + int i, u16 size) +{ + struct enetc_rx_swbd *rx_swbd = &rx_ring->rx_swbd[i]; + + dma_sync_single_range_for_cpu(rx_ring->dev, rx_swbd->dma, + rx_swbd->page_offset, + size, DMA_FROM_DEVICE); + return rx_swbd; +} + +static void enetc_put_rx_buff(struct enetc_bdr *rx_ring, + struct enetc_rx_swbd *rx_swbd) +{ + if (likely(enetc_page_reusable(rx_swbd->page))) { + rx_swbd->page_offset ^= ENETC_RXB_TRUESIZE; + page_ref_inc(rx_swbd->page); + + enetc_reuse_page(rx_ring, rx_swbd); + + /* sync for use by the device */ + dma_sync_single_range_for_device(rx_ring->dev, rx_swbd->dma, + rx_swbd->page_offset, + ENETC_RXB_DMA_SIZE, + DMA_FROM_DEVICE); + } else { + dma_unmap_page(rx_ring->dev, rx_swbd->dma, + PAGE_SIZE, DMA_FROM_DEVICE); + } + + rx_swbd->page = NULL; +} + +static struct sk_buff *enetc_map_rx_buff_to_skb(struct enetc_bdr *rx_ring, + int i, u16 size) +{ + struct enetc_rx_swbd *rx_swbd = enetc_get_rx_buff(rx_ring, i, size); + struct sk_buff *skb; + void *ba; + + ba = page_address(rx_swbd->page) + rx_swbd->page_offset; + skb = build_skb(ba - ENETC_RXB_PAD, ENETC_RXB_TRUESIZE); + if (unlikely(!skb)) { + rx_ring->stats.rx_alloc_errs++; + return NULL; + } + + skb_reserve(skb, ENETC_RXB_PAD); + __skb_put(skb, size); + + enetc_put_rx_buff(rx_ring, rx_swbd); + + return skb; +} + +static void enetc_add_rx_buff_to_skb(struct enetc_bdr *rx_ring, int i, + u16 size, struct sk_buff *skb) +{ + struct enetc_rx_swbd *rx_swbd = enetc_get_rx_buff(rx_ring, i, size); + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_swbd->page, + rx_swbd->page_offset, size, ENETC_RXB_TRUESIZE); + + enetc_put_rx_buff(rx_ring, rx_swbd); +} + +#define ENETC_RXBD_BUNDLE 16 /* # of BDs to update at once */ + +static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, + struct napi_struct *napi, int work_limit) +{ + int rx_frm_cnt = 0, rx_byte_cnt = 0; + int cleaned_cnt, i; + + cleaned_cnt = enetc_bd_unused(rx_ring); + /* next descriptor to process */ + i = rx_ring->next_to_clean; + + while (likely(rx_frm_cnt < work_limit)) { + union enetc_rx_bd *rxbd; + struct sk_buff *skb; + u32 bd_status; + u16 size; + + if (cleaned_cnt >= ENETC_RXBD_BUNDLE) { + int count = enetc_refill_rx_ring(rx_ring, cleaned_cnt); + + cleaned_cnt -= count; + } + + rxbd = ENETC_RXBD(*rx_ring, i); + bd_status = le32_to_cpu(rxbd->r.lstatus); + if (!bd_status) + break; + + enetc_wr_reg(rx_ring->idr, BIT(rx_ring->index)); + dma_rmb(); /* for reading other rxbd fields */ + size = le16_to_cpu(rxbd->r.buf_len); + skb = enetc_map_rx_buff_to_skb(rx_ring, i, size); + if (!skb) + break; + + enetc_get_offloads(rx_ring, rxbd, skb); + + cleaned_cnt++; + rxbd++; + i++; + if (unlikely(i == rx_ring->bd_count)) { + i = 0; + rxbd = ENETC_RXBD(*rx_ring, 0); + } + + if (unlikely(bd_status & + ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK))) { + dev_kfree_skb(skb); + while (!(bd_status & ENETC_RXBD_LSTATUS_F)) { + dma_rmb(); + bd_status = le32_to_cpu(rxbd->r.lstatus); + rxbd++; + i++; + if (unlikely(i == rx_ring->bd_count)) { + i = 0; + rxbd = ENETC_RXBD(*rx_ring, 0); + } + } + + rx_ring->ndev->stats.rx_dropped++; + rx_ring->ndev->stats.rx_errors++; + + break; + } + + /* not last BD in frame? */ + while (!(bd_status & ENETC_RXBD_LSTATUS_F)) { + bd_status = le32_to_cpu(rxbd->r.lstatus); + size = ENETC_RXB_DMA_SIZE; + + if (bd_status & ENETC_RXBD_LSTATUS_F) { + dma_rmb(); + size = le16_to_cpu(rxbd->r.buf_len); + } + + enetc_add_rx_buff_to_skb(rx_ring, i, size, skb); + + cleaned_cnt++; + rxbd++; + i++; + if (unlikely(i == rx_ring->bd_count)) { + i = 0; + rxbd = ENETC_RXBD(*rx_ring, 0); + } + } + + rx_byte_cnt += skb->len; + + enetc_process_skb(rx_ring, skb); + + napi_gro_receive(napi, skb); + + rx_frm_cnt++; + } + + rx_ring->next_to_clean = i; + + rx_ring->stats.packets += rx_frm_cnt; + rx_ring->stats.bytes += rx_byte_cnt; + + return rx_frm_cnt; +} + +/* Probing and Init */ +void enetc_get_si_caps(struct enetc_si *si) +{ + struct enetc_hw *hw = &si->hw; + u32 val; + + /* find out how many of various resources we have to work with */ + val = enetc_rd(hw, ENETC_SICAPR0); + si->num_rx_rings = (val >> 16) & 0xff; + si->num_tx_rings = val & 0xff; +} + +static int enetc_dma_alloc_bdr(struct enetc_bdr *r, size_t bd_size) +{ + r->bd_base = dma_alloc_coherent(r->dev, r->bd_count * bd_size, + &r->bd_dma_base, GFP_KERNEL); + if (!r->bd_base) + return -ENOMEM; + + /* h/w requires 128B alignment */ + if (!IS_ALIGNED(r->bd_dma_base, 128)) { + dma_free_coherent(r->dev, r->bd_count * bd_size, r->bd_base, + r->bd_dma_base); + return -EINVAL; + } + + return 0; +} + +static int enetc_alloc_txbdr(struct enetc_bdr *txr) +{ + int err; + + txr->tx_swbd = vzalloc(txr->bd_count * sizeof(struct enetc_tx_swbd)); + if (!txr->tx_swbd) + return -ENOMEM; + + err = enetc_dma_alloc_bdr(txr, sizeof(union enetc_tx_bd)); + if (err) { + vfree(txr->tx_swbd); + return err; + } + + txr->next_to_clean = 0; + txr->next_to_use = 0; + + return 0; +} + +static void enetc_free_txbdr(struct enetc_bdr *txr) +{ + int size, i; + + for (i = 0; i < txr->bd_count; i++) + enetc_free_tx_skb(txr, &txr->tx_swbd[i]); + + size = txr->bd_count * sizeof(union enetc_tx_bd); + + dma_free_coherent(txr->dev, size, txr->bd_base, txr->bd_dma_base); + txr->bd_base = NULL; + + vfree(txr->tx_swbd); + txr->tx_swbd = NULL; +} + +static int enetc_alloc_tx_resources(struct enetc_ndev_priv *priv) +{ + int i, err; + + for (i = 0; i < priv->num_tx_rings; i++) { + err = enetc_alloc_txbdr(priv->tx_ring[i]); + + if (err) + goto fail; + } + + return 0; + +fail: + while (i-- > 0) + enetc_free_txbdr(priv->tx_ring[i]); + + return err; +} + +static void enetc_free_tx_resources(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_rings; i++) + enetc_free_txbdr(priv->tx_ring[i]); +} + +static int enetc_alloc_rxbdr(struct enetc_bdr *rxr) +{ + int err; + + rxr->rx_swbd = vzalloc(rxr->bd_count * sizeof(struct enetc_rx_swbd)); + if (!rxr->rx_swbd) + return -ENOMEM; + + err = enetc_dma_alloc_bdr(rxr, sizeof(union enetc_rx_bd)); + if (err) { + vfree(rxr->rx_swbd); + return err; + } + + rxr->next_to_clean = 0; + rxr->next_to_use = 0; + rxr->next_to_alloc = 0; + + return 0; +} + +static void enetc_free_rxbdr(struct enetc_bdr *rxr) +{ + int size; + + size = rxr->bd_count * sizeof(union enetc_rx_bd); + + dma_free_coherent(rxr->dev, size, rxr->bd_base, rxr->bd_dma_base); + rxr->bd_base = NULL; + + vfree(rxr->rx_swbd); + rxr->rx_swbd = NULL; +} + +static int enetc_alloc_rx_resources(struct enetc_ndev_priv *priv) +{ + int i, err; + + for (i = 0; i < priv->num_rx_rings; i++) { + err = enetc_alloc_rxbdr(priv->rx_ring[i]); + + if (err) + goto fail; + } + + return 0; + +fail: + while (i-- > 0) + enetc_free_rxbdr(priv->rx_ring[i]); + + return err; +} + +static void enetc_free_rx_resources(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_rx_rings; i++) + enetc_free_rxbdr(priv->rx_ring[i]); +} + +static void enetc_free_tx_ring(struct enetc_bdr *tx_ring) +{ + int i; + + if (!tx_ring->tx_swbd) + return; + + for (i = 0; i < tx_ring->bd_count; i++) { + struct enetc_tx_swbd *tx_swbd = &tx_ring->tx_swbd[i]; + + enetc_free_tx_skb(tx_ring, tx_swbd); + } + + tx_ring->next_to_clean = 0; + tx_ring->next_to_use = 0; +} + +static void enetc_free_rx_ring(struct enetc_bdr *rx_ring) +{ + int i; + + if (!rx_ring->rx_swbd) + return; + + for (i = 0; i < rx_ring->bd_count; i++) { + struct enetc_rx_swbd *rx_swbd = &rx_ring->rx_swbd[i]; + + if (!rx_swbd->page) + continue; + + dma_unmap_page(rx_ring->dev, rx_swbd->dma, + PAGE_SIZE, DMA_FROM_DEVICE); + __free_page(rx_swbd->page); + rx_swbd->page = NULL; + } + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + rx_ring->next_to_alloc = 0; +} + +static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_rx_rings; i++) + enetc_free_rx_ring(priv->rx_ring[i]); + + for (i = 0; i < priv->num_tx_rings; i++) + enetc_free_tx_ring(priv->tx_ring[i]); +} + +static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr) +{ + int size = cbdr->bd_count * sizeof(struct enetc_cbd); + + cbdr->bd_base = dma_alloc_coherent(dev, size, &cbdr->bd_dma_base, + GFP_KERNEL); + if (!cbdr->bd_base) + return -ENOMEM; + + /* h/w requires 128B alignment */ + if (!IS_ALIGNED(cbdr->bd_dma_base, 128)) { + dma_free_coherent(dev, size, cbdr->bd_base, cbdr->bd_dma_base); + return -EINVAL; + } + + cbdr->next_to_clean = 0; + cbdr->next_to_use = 0; + + return 0; +} + +static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr) +{ + int size = cbdr->bd_count * sizeof(struct enetc_cbd); + + dma_free_coherent(dev, size, cbdr->bd_base, cbdr->bd_dma_base); + cbdr->bd_base = NULL; +} + +static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr) +{ + /* set CBDR cache attributes */ + enetc_wr(hw, ENETC_SICAR2, + ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT); + + enetc_wr(hw, ENETC_SICBDRBAR0, lower_32_bits(cbdr->bd_dma_base)); + enetc_wr(hw, ENETC_SICBDRBAR1, upper_32_bits(cbdr->bd_dma_base)); + enetc_wr(hw, ENETC_SICBDRLENR, ENETC_RTBLENR_LEN(cbdr->bd_count)); + + enetc_wr(hw, ENETC_SICBDRPIR, 0); + enetc_wr(hw, ENETC_SICBDRCIR, 0); + + /* enable ring */ + enetc_wr(hw, ENETC_SICBDRMR, BIT(31)); + + cbdr->pir = hw->reg + ENETC_SICBDRPIR; + cbdr->cir = hw->reg + ENETC_SICBDRCIR; +} + +static void enetc_clear_cbdr(struct enetc_hw *hw) +{ + enetc_wr(hw, ENETC_SICBDRMR, 0); +} + +static int enetc_configure_si(struct enetc_ndev_priv *priv) +{ + struct enetc_si *si = priv->si; + struct enetc_hw *hw = &si->hw; + + enetc_setup_cbdr(hw, &si->cbd_ring); + /* set SI cache attributes */ + enetc_wr(hw, ENETC_SICAR0, + ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT); + enetc_wr(hw, ENETC_SICAR1, ENETC_SICAR_MSI); + /* enable SI */ + enetc_wr(hw, ENETC_SIMR, ENETC_SIMR_EN); + + return 0; +} + +void enetc_init_si_rings_params(struct enetc_ndev_priv *priv) +{ + struct enetc_si *si = priv->si; + int cpus = num_online_cpus(); + + priv->tx_bd_count = ENETC_BDR_DEFAULT_SIZE; + priv->rx_bd_count = ENETC_BDR_DEFAULT_SIZE; + + /* Enable all available TX rings in order to configure as many + * priorities as possible, when needed. + * TODO: Make # of TX rings run-time configurable + */ + priv->num_rx_rings = min_t(int, cpus, si->num_rx_rings); + priv->num_tx_rings = si->num_tx_rings; + priv->bdr_int_num = cpus; + + /* SI specific */ + si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE; +} + +int enetc_alloc_si_resources(struct enetc_ndev_priv *priv) +{ + struct enetc_si *si = priv->si; + int err; + + err = enetc_alloc_cbdr(priv->dev, &si->cbd_ring); + if (err) + return err; + + err = enetc_configure_si(priv); + if (err) + goto err_config_si; + + return 0; + +err_config_si: + enetc_clear_cbdr(&si->hw); + enetc_free_cbdr(priv->dev, &si->cbd_ring); + + return err; +} + +void enetc_free_si_resources(struct enetc_ndev_priv *priv) +{ + struct enetc_si *si = priv->si; + + enetc_clear_cbdr(&si->hw); + enetc_free_cbdr(priv->dev, &si->cbd_ring); +} + +static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) +{ + int idx = tx_ring->index; + u32 tbmr; + + enetc_txbdr_wr(hw, idx, ENETC_TBBAR0, + lower_32_bits(tx_ring->bd_dma_base)); + + enetc_txbdr_wr(hw, idx, ENETC_TBBAR1, + upper_32_bits(tx_ring->bd_dma_base)); + + WARN_ON(!IS_ALIGNED(tx_ring->bd_count, 64)); /* multiple of 64 */ + enetc_txbdr_wr(hw, idx, ENETC_TBLENR, + ENETC_RTBLENR_LEN(tx_ring->bd_count)); + + /* clearing PI/CI registers for Tx not supported, adjust sw indexes */ + tx_ring->next_to_use = enetc_txbdr_rd(hw, idx, ENETC_TBPIR); + tx_ring->next_to_clean = enetc_txbdr_rd(hw, idx, ENETC_TBCIR); + + /* enable Tx ints by setting pkt thr to 1 */ + enetc_txbdr_wr(hw, idx, ENETC_TBICIR0, ENETC_TBICIR0_ICEN | 0x1); + + tbmr = ENETC_TBMR_EN; + if (tx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_TX) + tbmr |= ENETC_TBMR_VIH; + + /* enable ring */ + enetc_txbdr_wr(hw, idx, ENETC_TBMR, tbmr); + + tx_ring->tpir = hw->reg + ENETC_BDR(TX, idx, ENETC_TBPIR); + tx_ring->tcir = hw->reg + ENETC_BDR(TX, idx, ENETC_TBCIR); + tx_ring->idr = hw->reg + ENETC_SITXIDR; +} + +static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) +{ + int idx = rx_ring->index; + u32 rbmr; + + enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0, + lower_32_bits(rx_ring->bd_dma_base)); + + enetc_rxbdr_wr(hw, idx, ENETC_RBBAR1, + upper_32_bits(rx_ring->bd_dma_base)); + + WARN_ON(!IS_ALIGNED(rx_ring->bd_count, 64)); /* multiple of 64 */ + enetc_rxbdr_wr(hw, idx, ENETC_RBLENR, + ENETC_RTBLENR_LEN(rx_ring->bd_count)); + + enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, ENETC_RXB_DMA_SIZE); + + enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0); + + /* enable Rx ints by setting pkt thr to 1 */ + enetc_rxbdr_wr(hw, idx, ENETC_RBICIR0, ENETC_RBICIR0_ICEN | 0x1); + + rbmr = ENETC_RBMR_EN; + if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX) + rbmr |= ENETC_RBMR_VTE; + + rx_ring->rcir = hw->reg + ENETC_BDR(RX, idx, ENETC_RBCIR); + rx_ring->idr = hw->reg + ENETC_SIRXIDR; + + enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring)); + + /* enable ring */ + enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr); +} + +static void enetc_setup_bdrs(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_rings; i++) + enetc_setup_txbdr(&priv->si->hw, priv->tx_ring[i]); + + for (i = 0; i < priv->num_rx_rings; i++) + enetc_setup_rxbdr(&priv->si->hw, priv->rx_ring[i]); +} + +static void enetc_clear_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) +{ + int idx = rx_ring->index; + + /* disable EN bit on ring */ + enetc_rxbdr_wr(hw, idx, ENETC_RBMR, 0); +} + +static void enetc_clear_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) +{ + int delay = 8, timeout = 100; + int idx = tx_ring->index; + + /* disable EN bit on ring */ + enetc_txbdr_wr(hw, idx, ENETC_TBMR, 0); + + /* wait for busy to clear */ + while (delay < timeout && + enetc_txbdr_rd(hw, idx, ENETC_TBSR) & ENETC_TBSR_BUSY) { + msleep(delay); + delay *= 2; + } + + if (delay >= timeout) + netdev_warn(tx_ring->ndev, "timeout for tx ring #%d clear\n", + idx); +} + +static void enetc_clear_bdrs(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_rings; i++) + enetc_clear_txbdr(&priv->si->hw, priv->tx_ring[i]); + + for (i = 0; i < priv->num_rx_rings; i++) + enetc_clear_rxbdr(&priv->si->hw, priv->rx_ring[i]); + + udelay(1); +} + +static int enetc_setup_irqs(struct enetc_ndev_priv *priv) +{ + struct pci_dev *pdev = priv->si->pdev; + cpumask_t cpu_mask; + int i, j, err; + + for (i = 0; i < priv->bdr_int_num; i++) { + int irq = pci_irq_vector(pdev, ENETC_BDR_INT_BASE_IDX + i); + struct enetc_int_vector *v = priv->int_vector[i]; + int entry = ENETC_BDR_INT_BASE_IDX + i; + struct enetc_hw *hw = &priv->si->hw; + + snprintf(v->name, sizeof(v->name), "%s-rxtx%d", + priv->ndev->name, i); + err = request_irq(irq, enetc_msix, 0, v->name, v); + if (err) { + dev_err(priv->dev, "request_irq() failed!\n"); + goto irq_err; + } + + v->tbier_base = hw->reg + ENETC_BDR(TX, 0, ENETC_TBIER); + v->rbier = hw->reg + ENETC_BDR(RX, i, ENETC_RBIER); + + enetc_wr(hw, ENETC_SIMSIRRV(i), entry); + + for (j = 0; j < v->count_tx_rings; j++) { + int idx = v->tx_ring[j].index; + + enetc_wr(hw, ENETC_SIMSITRV(idx), entry); + } + cpumask_clear(&cpu_mask); + cpumask_set_cpu(i % num_online_cpus(), &cpu_mask); + irq_set_affinity_hint(irq, &cpu_mask); + } + + return 0; + +irq_err: + while (i--) { + int irq = pci_irq_vector(pdev, ENETC_BDR_INT_BASE_IDX + i); + + irq_set_affinity_hint(irq, NULL); + free_irq(irq, priv->int_vector[i]); + } + + return err; +} + +static void enetc_free_irqs(struct enetc_ndev_priv *priv) +{ + struct pci_dev *pdev = priv->si->pdev; + int i; + + for (i = 0; i < priv->bdr_int_num; i++) { + int irq = pci_irq_vector(pdev, ENETC_BDR_INT_BASE_IDX + i); + + irq_set_affinity_hint(irq, NULL); + free_irq(irq, priv->int_vector[i]); + } +} + +static void enetc_enable_interrupts(struct enetc_ndev_priv *priv) +{ + int i; + + /* enable Tx & Rx event indication */ + for (i = 0; i < priv->num_rx_rings; i++) { + enetc_rxbdr_wr(&priv->si->hw, i, + ENETC_RBIER, ENETC_RBIER_RXTIE); + } + + for (i = 0; i < priv->num_tx_rings; i++) { + enetc_txbdr_wr(&priv->si->hw, i, + ENETC_TBIER, ENETC_TBIER_TXTIE); + } +} + +static void enetc_disable_interrupts(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_rings; i++) + enetc_txbdr_wr(&priv->si->hw, i, ENETC_TBIER, 0); + + for (i = 0; i < priv->num_rx_rings; i++) + enetc_rxbdr_wr(&priv->si->hw, i, ENETC_RBIER, 0); +} + +static void adjust_link(struct net_device *ndev) +{ + struct phy_device *phydev = ndev->phydev; + + phy_print_status(phydev); +} + +static int enetc_phy_connect(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct phy_device *phydev; + + if (!priv->phy_node) + return 0; /* phy-less mode */ + + phydev = of_phy_connect(ndev, priv->phy_node, &adjust_link, + 0, priv->if_mode); + if (!phydev) { + dev_err(&ndev->dev, "could not attach to PHY\n"); + return -ENODEV; + } + + phy_attached_info(phydev); + + return 0; +} + +int enetc_open(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + int i, err; + + err = enetc_setup_irqs(priv); + if (err) + return err; + + err = enetc_phy_connect(ndev); + if (err) + goto err_phy_connect; + + err = enetc_alloc_tx_resources(priv); + if (err) + goto err_alloc_tx; + + err = enetc_alloc_rx_resources(priv); + if (err) + goto err_alloc_rx; + + enetc_setup_bdrs(priv); + + err = netif_set_real_num_tx_queues(ndev, priv->num_tx_rings); + if (err) + goto err_set_queues; + + err = netif_set_real_num_rx_queues(ndev, priv->num_rx_rings); + if (err) + goto err_set_queues; + + for (i = 0; i < priv->bdr_int_num; i++) + napi_enable(&priv->int_vector[i]->napi); + + enetc_enable_interrupts(priv); + + if (ndev->phydev) + phy_start(ndev->phydev); + else + netif_carrier_on(ndev); + + netif_tx_start_all_queues(ndev); + + return 0; + +err_set_queues: + enetc_free_rx_resources(priv); +err_alloc_rx: + enetc_free_tx_resources(priv); +err_alloc_tx: + if (ndev->phydev) + phy_disconnect(ndev->phydev); +err_phy_connect: + enetc_free_irqs(priv); + + return err; +} + +int enetc_close(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + int i; + + netif_tx_stop_all_queues(ndev); + + if (ndev->phydev) { + phy_stop(ndev->phydev); + phy_disconnect(ndev->phydev); + } else { + netif_carrier_off(ndev); + } + + for (i = 0; i < priv->bdr_int_num; i++) { + napi_synchronize(&priv->int_vector[i]->napi); + napi_disable(&priv->int_vector[i]->napi); + } + + enetc_disable_interrupts(priv); + enetc_clear_bdrs(priv); + + enetc_free_rxtx_rings(priv); + enetc_free_rx_resources(priv); + enetc_free_tx_resources(priv); + enetc_free_irqs(priv); + + return 0; +} + +struct net_device_stats *enetc_get_stats(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &ndev->stats; + unsigned long packets = 0, bytes = 0; + int i; + + for (i = 0; i < priv->num_rx_rings; i++) { + packets += priv->rx_ring[i]->stats.packets; + bytes += priv->rx_ring[i]->stats.bytes; + } + + stats->rx_packets = packets; + stats->rx_bytes = bytes; + bytes = 0; + packets = 0; + + for (i = 0; i < priv->num_tx_rings; i++) { + packets += priv->tx_ring[i]->stats.packets; + bytes += priv->tx_ring[i]->stats.bytes; + } + + stats->tx_packets = packets; + stats->tx_bytes = bytes; + + return stats; +} + +int enetc_alloc_msix(struct enetc_ndev_priv *priv) +{ + struct pci_dev *pdev = priv->si->pdev; + int size, v_tx_rings; + int i, n, err, nvec; + + nvec = ENETC_BDR_INT_BASE_IDX + priv->bdr_int_num; + /* allocate MSIX for both messaging and Rx/Tx interrupts */ + n = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_MSIX); + + if (n < 0) + return n; + + if (n != nvec) + return -EPERM; + + /* # of tx rings per int vector */ + v_tx_rings = priv->num_tx_rings / priv->bdr_int_num; + size = sizeof(struct enetc_int_vector) + + sizeof(struct enetc_bdr) * v_tx_rings; + + for (i = 0; i < priv->bdr_int_num; i++) { + struct enetc_int_vector *v; + struct enetc_bdr *bdr; + int j; + + v = kzalloc(size, GFP_KERNEL); + if (!v) { + err = -ENOMEM; + goto fail; + } + + priv->int_vector[i] = v; + + netif_napi_add(priv->ndev, &v->napi, enetc_poll, + NAPI_POLL_WEIGHT); + v->count_tx_rings = v_tx_rings; + + for (j = 0; j < v_tx_rings; j++) { + int idx; + + /* default tx ring mapping policy */ + if (priv->bdr_int_num == ENETC_MAX_BDR_INT) + idx = 2 * j + i; /* 2 CPUs */ + else + idx = j + i * v_tx_rings; /* default */ + + __set_bit(idx, &v->tx_rings_map); + bdr = &v->tx_ring[j]; + bdr->index = idx; + bdr->ndev = priv->ndev; + bdr->dev = priv->dev; + bdr->bd_count = priv->tx_bd_count; + priv->tx_ring[idx] = bdr; + } + + bdr = &v->rx_ring; + bdr->index = i; + bdr->ndev = priv->ndev; + bdr->dev = priv->dev; + bdr->bd_count = priv->rx_bd_count; + priv->rx_ring[i] = bdr; + } + + return 0; + +fail: + while (i--) { + netif_napi_del(&priv->int_vector[i]->napi); + kfree(priv->int_vector[i]); + } + + pci_free_irq_vectors(pdev); + + return err; +} + +void enetc_free_msix(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->bdr_int_num; i++) { + struct enetc_int_vector *v = priv->int_vector[i]; + + netif_napi_del(&v->napi); + } + + for (i = 0; i < priv->num_rx_rings; i++) + priv->rx_ring[i] = NULL; + + for (i = 0; i < priv->num_tx_rings; i++) + priv->tx_ring[i] = NULL; + + for (i = 0; i < priv->bdr_int_num; i++) { + kfree(priv->int_vector[i]); + priv->int_vector[i] = NULL; + } + + /* disable all MSIX for this device */ + pci_free_irq_vectors(priv->si->pdev); +} + +static void enetc_kfree_si(struct enetc_si *si) +{ + char *p = (char *)si - si->pad; + + kfree(p); +} + +static void enetc_detect_errata(struct enetc_si *si) +{ + if (si->pdev->revision == ENETC_REV1) + si->errata = ENETC_ERR_TXCSUM | ENETC_ERR_VLAN_ISOL | + ENETC_ERR_UCMCSWP; +} + +int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv) +{ + struct enetc_si *si, *p; + struct enetc_hw *hw; + size_t alloc_size; + int err, len; + + pcie_flr(pdev); + err = pci_enable_device_mem(pdev); + if (err) { + dev_err(&pdev->dev, "device enable failed\n"); + return err; + } + + /* set up for high or low dma */ + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (err) { + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, + "DMA configuration failed: 0x%x\n", err); + goto err_dma; + } + } + + err = pci_request_mem_regions(pdev, name); + if (err) { + dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err); + goto err_pci_mem_reg; + } + + pci_set_master(pdev); + + alloc_size = sizeof(struct enetc_si); + if (sizeof_priv) { + /* align priv to 32B */ + alloc_size = ALIGN(alloc_size, ENETC_SI_ALIGN); + alloc_size += sizeof_priv; + } + /* force 32B alignment for enetc_si */ + alloc_size += ENETC_SI_ALIGN - 1; + + p = kzalloc(alloc_size, GFP_KERNEL); + if (!p) { + err = -ENOMEM; + goto err_alloc_si; + } + + si = PTR_ALIGN(p, ENETC_SI_ALIGN); + si->pad = (char *)si - (char *)p; + + pci_set_drvdata(pdev, si); + si->pdev = pdev; + hw = &si->hw; + + len = pci_resource_len(pdev, ENETC_BAR_REGS); + hw->reg = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), len); + if (!hw->reg) { + err = -ENXIO; + dev_err(&pdev->dev, "ioremap() failed\n"); + goto err_ioremap; + } + if (len > ENETC_PORT_BASE) + hw->port = hw->reg + ENETC_PORT_BASE; + if (len > ENETC_GLOBAL_BASE) + hw->global = hw->reg + ENETC_GLOBAL_BASE; + + enetc_detect_errata(si); + + return 0; + +err_ioremap: + enetc_kfree_si(si); +err_alloc_si: + pci_release_mem_regions(pdev); +err_pci_mem_reg: +err_dma: + pci_disable_device(pdev); + + return err; +} + +void enetc_pci_remove(struct pci_dev *pdev) +{ + struct enetc_si *si = pci_get_drvdata(pdev); + struct enetc_hw *hw = &si->hw; + + iounmap(hw->reg); + enetc_kfree_si(si); + pci_release_mem_regions(pdev); + pci_disable_device(pdev); +} diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h new file mode 100644 index 000000000000..d19bb434bca3 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* Copyright 2017-2019 NXP */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "enetc_hw.h" + +#define ENETC_MAC_MAXFRM_SIZE 9600 +#define ENETC_MAX_MTU (ENETC_MAC_MAXFRM_SIZE - \ + (ETH_FCS_LEN + ETH_HLEN + VLAN_HLEN)) + +struct enetc_tx_swbd { + struct sk_buff *skb; + dma_addr_t dma; + u16 len; + u16 is_dma_page; +}; + +#define ENETC_RX_MAXFRM_SIZE ENETC_MAC_MAXFRM_SIZE +#define ENETC_RXB_TRUESIZE 2048 /* PAGE_SIZE >> 1 */ +#define ENETC_RXB_PAD NET_SKB_PAD /* add extra space if needed */ +#define ENETC_RXB_DMA_SIZE \ + (SKB_WITH_OVERHEAD(ENETC_RXB_TRUESIZE) - ENETC_RXB_PAD) + +struct enetc_rx_swbd { + dma_addr_t dma; + struct page *page; + u16 page_offset; +}; + +struct enetc_ring_stats { + unsigned int packets; + unsigned int bytes; + unsigned int rx_alloc_errs; +}; + +#define ENETC_BDR_DEFAULT_SIZE 1024 +#define ENETC_DEFAULT_TX_WORK 256 + +struct enetc_bdr { + struct device *dev; /* for DMA mapping */ + struct net_device *ndev; + void *bd_base; /* points to Rx or Tx BD ring */ + union { + void __iomem *tpir; + void __iomem *rcir; + }; + u16 index; + int bd_count; /* # of BDs */ + int next_to_use; + int next_to_clean; + union { + struct enetc_tx_swbd *tx_swbd; + struct enetc_rx_swbd *rx_swbd; + }; + union { + void __iomem *tcir; /* Tx */ + int next_to_alloc; /* Rx */ + }; + void __iomem *idr; /* Interrupt Detect Register pointer */ + + struct enetc_ring_stats stats; + + dma_addr_t bd_dma_base; +} ____cacheline_aligned_in_smp; + +static inline void enetc_bdr_idx_inc(struct enetc_bdr *bdr, int *i) +{ + if (unlikely(++*i == bdr->bd_count)) + *i = 0; +} + +static inline int enetc_bd_unused(struct enetc_bdr *bdr) +{ + if (bdr->next_to_clean > bdr->next_to_use) + return bdr->next_to_clean - bdr->next_to_use - 1; + + return bdr->bd_count + bdr->next_to_clean - bdr->next_to_use - 1; +} + +/* Control BD ring */ +#define ENETC_CBDR_DEFAULT_SIZE 64 +struct enetc_cbdr { + void *bd_base; /* points to Rx or Tx BD ring */ + void __iomem *pir; + void __iomem *cir; + + int bd_count; /* # of BDs */ + int next_to_use; + int next_to_clean; + + dma_addr_t bd_dma_base; +}; + +#define ENETC_TXBD(BDR, i) (&(((union enetc_tx_bd *)((BDR).bd_base))[i])) +#define ENETC_RXBD(BDR, i) (&(((union enetc_rx_bd *)((BDR).bd_base))[i])) + +#define ENETC_REV1 0x1 +enum enetc_errata { + ENETC_ERR_TXCSUM = BIT(0), + ENETC_ERR_VLAN_ISOL = BIT(1), + ENETC_ERR_UCMCSWP = BIT(2), +}; + +/* PCI IEP device data */ +struct enetc_si { + struct pci_dev *pdev; + struct enetc_hw hw; + enum enetc_errata errata; + + struct net_device *ndev; /* back ref. */ + + struct enetc_cbdr cbd_ring; + + int num_rx_rings; /* how many rings are available in the SI */ + int num_tx_rings; + unsigned short pad; +}; + +#define ENETC_SI_ALIGN 32 + +static inline void *enetc_si_priv(const struct enetc_si *si) +{ + return (char *)si + ALIGN(sizeof(struct enetc_si), ENETC_SI_ALIGN); +} + +static inline bool enetc_si_is_pf(struct enetc_si *si) +{ + return !!(si->hw.port); +} + +#define ENETC_MAX_NUM_TXQS 8 +#define ENETC_INT_NAME_MAX (IFNAMSIZ + 8) + +struct enetc_int_vector { + void __iomem *rbier; + void __iomem *tbier_base; + unsigned long tx_rings_map; + int count_tx_rings; + struct napi_struct napi; + char name[ENETC_INT_NAME_MAX]; + + struct enetc_bdr rx_ring ____cacheline_aligned_in_smp; + struct enetc_bdr tx_ring[0]; +}; + +#define ENETC_MAX_BDR_INT 2 /* fixed to max # of available cpus */ + +struct enetc_ndev_priv { + struct net_device *ndev; + struct device *dev; /* dma-mapping device */ + struct enetc_si *si; + + int bdr_int_num; /* number of Rx/Tx ring interrupts */ + struct enetc_int_vector *int_vector[ENETC_MAX_BDR_INT]; + u16 num_rx_rings, num_tx_rings; + u16 rx_bd_count, tx_bd_count; + + u16 msg_enable; + + struct enetc_bdr *tx_ring[16]; + struct enetc_bdr *rx_ring[16]; + + struct device_node *phy_node; + phy_interface_t if_mode; +}; + +#define ENETC_CBD(R, i) (&(((struct enetc_cbd *)((R).bd_base))[i])) + +#define ENETC_CBDR_TIMEOUT 1000 /* usecs */ + +/* SI common */ +int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv); +void enetc_pci_remove(struct pci_dev *pdev); +int enetc_alloc_msix(struct enetc_ndev_priv *priv); +void enetc_free_msix(struct enetc_ndev_priv *priv); +void enetc_get_si_caps(struct enetc_si *si); +void enetc_init_si_rings_params(struct enetc_ndev_priv *priv); +int enetc_alloc_si_resources(struct enetc_ndev_priv *priv); +void enetc_free_si_resources(struct enetc_ndev_priv *priv); + +int enetc_open(struct net_device *ndev); +int enetc_close(struct net_device *ndev); +netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev); +struct net_device_stats *enetc_get_stats(struct net_device *ndev); +/* ethtool */ +void enetc_set_ethtool_ops(struct net_device *ndev); + +/* control buffer descriptor ring (CBDR) */ +int enetc_set_mac_flt_entry(struct enetc_si *si, int index, + char *mac_addr, int si_map); +int enetc_clear_mac_flt_entry(struct enetc_si *si, int index); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c new file mode 100644 index 000000000000..2ec0f2f316be --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2017-2019 NXP */ + +#include "enetc.h" + +static void enetc_clean_cbdr(struct enetc_si *si) +{ + struct enetc_cbdr *ring = &si->cbd_ring; + struct enetc_cbd *dest_cbd; + int i, status; + + i = ring->next_to_clean; + + while (enetc_rd_reg(ring->cir) != i) { + dest_cbd = ENETC_CBD(*ring, i); + status = dest_cbd->status_flags & ENETC_CBD_STATUS_MASK; + if (status) + dev_warn(&si->pdev->dev, "CMD err %04x for cmd %04x\n", + status, dest_cbd->cmd); + + memset(dest_cbd, 0, sizeof(*dest_cbd)); + + i = (i + 1) % ring->bd_count; + } + + ring->next_to_clean = i; +} + +static int enetc_cbd_unused(struct enetc_cbdr *r) +{ + return (r->next_to_clean - r->next_to_use - 1 + r->bd_count) % + r->bd_count; +} + +static int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd) +{ + struct enetc_cbdr *ring = &si->cbd_ring; + int timeout = ENETC_CBDR_TIMEOUT; + struct enetc_cbd *dest_cbd; + int i; + + if (unlikely(!ring->bd_base)) + return -EIO; + + if (unlikely(!enetc_cbd_unused(ring))) + enetc_clean_cbdr(si); + + i = ring->next_to_use; + dest_cbd = ENETC_CBD(*ring, i); + + /* copy command to the ring */ + *dest_cbd = *cbd; + i = (i + 1) % ring->bd_count; + + ring->next_to_use = i; + /* let H/W know BD ring has been updated */ + enetc_wr_reg(ring->pir, i); + + do { + if (enetc_rd_reg(ring->cir) == i) + break; + udelay(10); /* cannot sleep, rtnl_lock() */ + timeout -= 10; + } while (timeout); + + if (!timeout) + return -EBUSY; + + enetc_clean_cbdr(si); + + return 0; +} + +int enetc_clear_mac_flt_entry(struct enetc_si *si, int index) +{ + struct enetc_cbd cbd; + + memset(&cbd, 0, sizeof(cbd)); + + cbd.cls = 1; + cbd.status_flags = ENETC_CBD_FLAGS_SF; + cbd.index = cpu_to_le16(index); + + return enetc_send_cmd(si, &cbd); +} + +int enetc_set_mac_flt_entry(struct enetc_si *si, int index, + char *mac_addr, int si_map) +{ + struct enetc_cbd cbd; + u32 upper; + u16 lower; + + memset(&cbd, 0, sizeof(cbd)); + + /* fill up the "set" descriptor */ + cbd.cls = 1; + cbd.status_flags = ENETC_CBD_FLAGS_SF; + cbd.index = cpu_to_le16(index); + cbd.opt[3] = cpu_to_le32(si_map); + /* enable entry */ + cbd.opt[0] = cpu_to_le32(BIT(31)); + + upper = *(const u32 *)mac_addr; + lower = *(const u16 *)(mac_addr + 4); + cbd.addr[0] = cpu_to_le32(upper); + cbd.addr[1] = cpu_to_le32(lower); + + return enetc_send_cmd(si, &cbd); +} diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c new file mode 100644 index 000000000000..41771edada97 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2017-2019 NXP */ + +#include +#include +#include "enetc.h" + +static const u32 enetc_si_regs[] = { + ENETC_SIMR, ENETC_SIPMAR0, ENETC_SIPMAR1, ENETC_SICBDRMR, + ENETC_SICBDRSR, ENETC_SICBDRBAR0, ENETC_SICBDRBAR1, ENETC_SICBDRPIR, + ENETC_SICBDRCIR, ENETC_SICBDRLENR, ENETC_SICAPR0, ENETC_SICAPR1, + ENETC_SIUEFDCR +}; + +static const u32 enetc_txbdr_regs[] = { + ENETC_TBMR, ENETC_TBSR, ENETC_TBBAR0, ENETC_TBBAR1, + ENETC_TBPIR, ENETC_TBCIR, ENETC_TBLENR, ENETC_TBIER +}; + +static const u32 enetc_rxbdr_regs[] = { + ENETC_RBMR, ENETC_RBSR, ENETC_RBBSR, ENETC_RBCIR, ENETC_RBBAR0, + ENETC_RBBAR1, ENETC_RBPIR, ENETC_RBLENR, ENETC_RBICIR0, ENETC_RBIER +}; + +static const u32 enetc_port_regs[] = { + ENETC_PMR, ENETC_PSR, ENETC_PSIPMR, ENETC_PSIPMAR0(0), + ENETC_PSIPMAR1(0), ENETC_PTXMBAR, ENETC_PCAPR0, ENETC_PCAPR1, + ENETC_PSICFGR0(0), ENETC_PTCMSDUR(0), ENETC_PM0_CMD_CFG, + ENETC_PM0_MAXFRM, ENETC_PM0_IF_MODE +}; + +static int enetc_get_reglen(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_hw *hw = &priv->si->hw; + int len; + + len = ARRAY_SIZE(enetc_si_regs); + len += ARRAY_SIZE(enetc_txbdr_regs) * priv->num_tx_rings; + len += ARRAY_SIZE(enetc_rxbdr_regs) * priv->num_rx_rings; + + if (hw->port) + len += ARRAY_SIZE(enetc_port_regs); + + len *= sizeof(u32) * 2; /* store 2 entries per reg: addr and value */ + + return len; +} + +static void enetc_get_regs(struct net_device *ndev, struct ethtool_regs *regs, + void *regbuf) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_hw *hw = &priv->si->hw; + u32 *buf = (u32 *)regbuf; + int i, j; + u32 addr; + + for (i = 0; i < ARRAY_SIZE(enetc_si_regs); i++) { + *buf++ = enetc_si_regs[i]; + *buf++ = enetc_rd(hw, enetc_si_regs[i]); + } + + for (i = 0; i < priv->num_tx_rings; i++) { + for (j = 0; j < ARRAY_SIZE(enetc_txbdr_regs); j++) { + addr = ENETC_BDR(TX, i, enetc_txbdr_regs[j]); + + *buf++ = addr; + *buf++ = enetc_rd(hw, addr); + } + } + + for (i = 0; i < priv->num_rx_rings; i++) { + for (j = 0; j < ARRAY_SIZE(enetc_rxbdr_regs); j++) { + addr = ENETC_BDR(RX, i, enetc_rxbdr_regs[j]); + + *buf++ = addr; + *buf++ = enetc_rd(hw, addr); + } + } + + if (!hw->port) + return; + + for (i = 0; i < ARRAY_SIZE(enetc_port_regs); i++) { + addr = ENETC_PORT_BASE + enetc_port_regs[i]; + *buf++ = addr; + *buf++ = enetc_rd(hw, addr); + } +} + +static void enetc_get_ringparam(struct net_device *ndev, + struct ethtool_ringparam *ring) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + ring->rx_pending = priv->rx_bd_count; + ring->tx_pending = priv->tx_bd_count; + + /* do some h/w sanity checks for BDR length */ + if (netif_running(ndev)) { + struct enetc_hw *hw = &priv->si->hw; + u32 val = enetc_rxbdr_rd(hw, 0, ENETC_RBLENR); + + if (val != priv->rx_bd_count) + netif_err(priv, hw, ndev, "RxBDR[RBLENR] = %d!\n", val); + + val = enetc_txbdr_rd(hw, 0, ENETC_TBLENR); + + if (val != priv->tx_bd_count) + netif_err(priv, hw, ndev, "TxBDR[TBLENR] = %d!\n", val); + } +} + +static const struct ethtool_ops enetc_pf_ethtool_ops = { + .get_regs_len = enetc_get_reglen, + .get_regs = enetc_get_regs, + .get_ringparam = enetc_get_ringparam, + .get_link_ksettings = phy_ethtool_get_link_ksettings, + .set_link_ksettings = phy_ethtool_set_link_ksettings, +}; + +static const struct ethtool_ops enetc_vf_ethtool_ops = { + .get_regs_len = enetc_get_reglen, + .get_regs = enetc_get_regs, + .get_ringparam = enetc_get_ringparam, +}; + +void enetc_set_ethtool_ops(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + if (enetc_si_is_pf(priv->si)) + ndev->ethtool_ops = &enetc_pf_ethtool_ops; + else + ndev->ethtool_ops = &enetc_vf_ethtool_ops; +} diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h new file mode 100644 index 000000000000..351af09f7cab --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h @@ -0,0 +1,351 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* Copyright 2017-2019 NXP */ + +#include + +/* ENETC device IDs */ +#define ENETC_DEV_ID_PF 0xe100 +#define ENETC_DEV_ID_VF 0xef00 + +/* ENETC register block BAR */ +#define ENETC_BAR_REGS 0 + +/** SI regs, offset: 0h */ +#define ENETC_SIMR 0 +#define ENETC_SIMR_EN BIT(31) +#define ENETC_SICTR0 0x18 +#define ENETC_SICTR1 0x1c +#define ENETC_SIPCAPR0 0x20 +#define ENETC_SIPCAPR1 0x24 +#define ENETC_SITGTGR 0x30 +#define ENETC_SIRBGCR 0x38 +/* cache attribute registers for transactions initiated by ENETC */ +#define ENETC_SICAR0 0x40 +#define ENETC_SICAR1 0x44 +#define ENETC_SICAR2 0x48 +/* rd snoop, no alloc + * wr snoop, no alloc, partial cache line update for BDs and full cache line + * update for data + */ +#define ENETC_SICAR_RD_COHERENT 0x2b2b0000 +#define ENETC_SICAR_WR_COHERENT 0x00006727 +#define ENETC_SICAR_MSI 0x00300030 /* rd/wr device, no snoop, no alloc */ + +#define ENETC_SIPMAR0 0x80 +#define ENETC_SIPMAR1 0x84 + +/* Control BDR regs */ +#define ENETC_SICBDRMR 0x800 +#define ENETC_SICBDRSR 0x804 /* RO */ +#define ENETC_SICBDRBAR0 0x810 +#define ENETC_SICBDRBAR1 0x814 +#define ENETC_SICBDRPIR 0x818 +#define ENETC_SICBDRCIR 0x81c +#define ENETC_SICBDRLENR 0x820 + +#define ENETC_SICAPR0 0x900 +#define ENETC_SICAPR1 0x904 + +#define ENETC_PSIIER 0xa00 +#define ENETC_PSIIER_MR_MASK GENMASK(2, 1) +#define ENETC_PSIIDR 0xa08 +#define ENETC_SITXIDR 0xa18 +#define ENETC_SIRXIDR 0xa28 +#define ENETC_SIMSIVR 0xa30 + +#define ENETC_SIMSITRV(n) (0xB00 + (n) * 0x4) +#define ENETC_SIMSIRRV(n) (0xB80 + (n) * 0x4) + +#define ENETC_SIUEFDCR 0xe28 + +/** SI BDR sub-blocks, n = 0..7 */ +enum enetc_bdr_type {TX, RX}; +#define ENETC_BDR_OFF(i) ((i) * 0x200) +#define ENETC_BDR(t, i, r) (0x8000 + (t) * 0x100 + ENETC_BDR_OFF(i) + (r)) +/* RX BDR reg offsets */ +#define ENETC_RBMR 0 +#define ENETC_RBMR_BDS BIT(2) +#define ENETC_RBMR_VTE BIT(5) +#define ENETC_RBMR_EN BIT(31) +#define ENETC_RBSR 0x4 +#define ENETC_RBBSR 0x8 +#define ENETC_RBCIR 0xc +#define ENETC_RBBAR0 0x10 +#define ENETC_RBBAR1 0x14 +#define ENETC_RBPIR 0x18 +#define ENETC_RBLENR 0x20 +#define ENETC_RBIER 0xa0 +#define ENETC_RBIER_RXTIE BIT(0) +#define ENETC_RBIDR 0xa4 +#define ENETC_RBICIR0 0xa8 +#define ENETC_RBICIR0_ICEN BIT(31) + +/* TX BDR reg offsets */ +#define ENETC_TBMR 0 +#define ENETC_TBSR_BUSY BIT(0) +#define ENETC_TBMR_VIH BIT(9) +#define ENETC_TBMR_PRIO_MASK GENMASK(2, 0) +#define ENETC_TBMR_PRIO_SET(val) val +#define ENETC_TBMR_EN BIT(31) +#define ENETC_TBSR 0x4 +#define ENETC_TBBAR0 0x10 +#define ENETC_TBBAR1 0x14 +#define ENETC_TBPIR 0x18 +#define ENETC_TBCIR 0x1c +#define ENETC_TBCIR_IDX_MASK 0xffff +#define ENETC_TBLENR 0x20 +#define ENETC_TBIER 0xa0 +#define ENETC_TBIER_TXTIE BIT(0) +#define ENETC_TBIDR 0xa4 +#define ENETC_TBICIR0 0xa8 +#define ENETC_TBICIR0_ICEN BIT(31) + +#define ENETC_RTBLENR_LEN(n) ((n) & ~0x7) + +/* Port regs, offset: 1_0000h */ +#define ENETC_PORT_BASE 0x10000 +#define ENETC_PMR 0x0000 +#define ENETC_PMR_EN GENMASK(18, 16) +#define ENETC_PSR 0x0004 /* RO */ +#define ENETC_PSIPMR 0x0018 +#define ENETC_PSIPMR_SET_UP(n) BIT(n) /* n = SI index */ +#define ENETC_PSIPMR_SET_MP(n) BIT((n) + 16) +#define ENETC_PSIPVMR 0x001c +#define ENETC_VLAN_PROMISC_MAP_ALL 0x7 +#define ENETC_PSIPVMR_SET_VP(simap) ((simap) & 0x7) +#define ENETC_PSIPVMR_SET_VUTA(simap) (((simap) & 0x7) << 16) +#define ENETC_PSIPMAR0(n) (0x0100 + (n) * 0x8) /* n = SI index */ +#define ENETC_PSIPMAR1(n) (0x0104 + (n) * 0x8) +#define ENETC_PVCLCTR 0x0208 +#define ENETC_VLAN_TYPE_C BIT(0) +#define ENETC_VLAN_TYPE_S BIT(1) +#define ENETC_PVCLCTR_OVTPIDL(bmp) ((bmp) & 0xff) /* VLAN_TYPE */ +#define ENETC_PSIVLANR(n) (0x0240 + (n) * 4) /* n = SI index */ +#define ENETC_PSIVLAN_EN BIT(31) +#define ENETC_PSIVLAN_SET_QOS(val) ((u32)(val) << 12) +#define ENETC_PTXMBAR 0x0608 +#define ENETC_PCAPR0 0x0900 +#define ENETC_PCAPR0_RXBDR(val) ((val) >> 24) +#define ENETC_PCAPR0_TXBDR(val) (((val) >> 16) & 0xff) +#define ENETC_PCAPR1 0x0904 +#define ENETC_PSICFGR0(n) (0x0940 + (n) * 0xc) /* n = SI index */ +#define ENETC_PSICFGR0_SET_TXBDR(val) ((val) & 0xff) +#define ENETC_PSICFGR0_SET_RXBDR(val) (((val) & 0xff) << 16) +#define ENETC_PSICFGR0_VTE BIT(12) +#define ENETC_PSICFGR0_SIVIE BIT(14) +#define ENETC_PSICFGR0_ASE BIT(15) +#define ENETC_PSICFGR0_SIVC(bmp) (((bmp) & 0xff) << 24) /* VLAN_TYPE */ + +#define ENETC_PTCCBSR0(n) (0x1110 + (n) * 8) /* n = 0 to 7*/ +#define ENETC_PTCCBSR1(n) (0x1114 + (n) * 8) /* n = 0 to 7*/ +#define ENETC_PSIVLANFMR 0x1700 +#define ENETC_PSIVLANFMR_VS BIT(0) +#define ENETC_PFPMR 0x1900 +#define ENETC_PFPMR_PMACE BIT(1) +#define ENETC_PFPMR_MWLM BIT(0) +#define ENETC_PSIUMHFR0(n, err) (((err) ? 0x1d08 : 0x1d00) + (n) * 0x10) +#define ENETC_PSIUMHFR1(n) (0x1d04 + (n) * 0x10) +#define ENETC_PSIMMHFR0(n, err) (((err) ? 0x1d00 : 0x1d08) + (n) * 0x10) +#define ENETC_PSIMMHFR1(n) (0x1d0c + (n) * 0x10) +#define ENETC_PSIVHFR0(n) (0x1e00 + (n) * 8) /* n = SI index */ +#define ENETC_PSIVHFR1(n) (0x1e04 + (n) * 8) /* n = SI index */ +#define ENETC_MMCSR 0x1f00 +#define ENETC_MMCSR_ME BIT(16) +#define ENETC_PTCMSDUR(n) (0x2020 + (n) * 4) /* n = TC index [0..7] */ + +#define ENETC_PM0_CMD_CFG 0x8008 +#define ENETC_PM1_CMD_CFG 0x9008 +#define ENETC_PM0_TX_EN BIT(0) +#define ENETC_PM0_RX_EN BIT(1) +#define ENETC_PM0_PROMISC BIT(4) +#define ENETC_PM0_CMD_XGLP BIT(10) +#define ENETC_PM0_CMD_TXP BIT(11) +#define ENETC_PM0_CMD_PHY_TX_EN BIT(15) +#define ENETC_PM0_CMD_SFD BIT(21) +#define ENETC_PM0_MAXFRM 0x8014 +#define ENETC_SET_TX_MTU(val) ((val) << 16) +#define ENETC_SET_MAXFRM(val) ((val) & 0xffff) +#define ENETC_PM0_IF_MODE 0x8300 +#define ENETC_PMO_IFM_RG BIT(2) +#define ENETC_PM0_IFM_RLP (BIT(5) | BIT(11)) +#define ENETC_PM0_IFM_RGAUTO (BIT(15) | ENETC_PMO_IFM_RG | BIT(1)) +#define ENETC_PM0_IFM_XGMII BIT(12) + +/** Global regs, offset: 2_0000h */ +#define ENETC_GLOBAL_BASE 0x20000 +#define ENETC_G_EIPBRR0 0x0bf8 +#define ENETC_G_EIPBRR1 0x0bfc +#define ENETC_G_EPFBLPR(n) (0xd00 + 4 * (n)) +#define ENETC_G_EPFBLPR1_XGMII 0x80000000 + +/* PCI device info */ +struct enetc_hw { + /* SI registers, used by all PCI functions */ + void __iomem *reg; + /* Port registers, PF only */ + void __iomem *port; + /* IP global registers, PF only */ + void __iomem *global; +}; + +/* general register accessors */ +#define enetc_rd_reg(reg) ioread32((reg)) +#define enetc_wr_reg(reg, val) iowrite32((val), (reg)) + +#define enetc_rd(hw, off) enetc_rd_reg((hw)->reg + (off)) +#define enetc_wr(hw, off, val) enetc_wr_reg((hw)->reg + (off), val) +/* port register accessors - PF only */ +#define enetc_port_rd(hw, off) enetc_rd_reg((hw)->port + (off)) +#define enetc_port_wr(hw, off, val) enetc_wr_reg((hw)->port + (off), val) +/* global register accessors - PF only */ +#define enetc_global_rd(hw, off) enetc_rd_reg((hw)->global + (off)) +#define enetc_global_wr(hw, off, val) enetc_wr_reg((hw)->global + (off), val) +/* BDR register accessors, see ENETC_BDR() */ +#define enetc_bdr_rd(hw, t, n, off) \ + enetc_rd(hw, ENETC_BDR(t, n, off)) +#define enetc_bdr_wr(hw, t, n, off, val) \ + enetc_wr(hw, ENETC_BDR(t, n, off), val) +#define enetc_txbdr_rd(hw, n, off) enetc_bdr_rd(hw, TX, n, off) +#define enetc_rxbdr_rd(hw, n, off) enetc_bdr_rd(hw, RX, n, off) +#define enetc_txbdr_wr(hw, n, off, val) \ + enetc_bdr_wr(hw, TX, n, off, val) +#define enetc_rxbdr_wr(hw, n, off, val) \ + enetc_bdr_wr(hw, RX, n, off, val) + +/* Buffer Descriptors (BD) */ +union enetc_tx_bd { + struct { + __le64 addr; + __le16 buf_len; + __le16 frm_len; + union { + struct { + __le16 l3_csoff; + u8 l4_csoff; + u8 flags; + }; /* default layout */ + __le32 lstatus; + }; + }; + struct { + __le32 tstamp; + __le16 tpid; + __le16 vid; + u8 reserved[6]; + u8 e_flags; + u8 flags; + } ext; /* Tx BD extension */ +}; + +#define ENETC_TXBD_FLAGS_L4CS BIT(0) +#define ENETC_TXBD_FLAGS_W BIT(2) +#define ENETC_TXBD_FLAGS_CSUM BIT(3) +#define ENETC_TXBD_FLAGS_EX BIT(6) +#define ENETC_TXBD_FLAGS_F BIT(7) + +static inline void enetc_clear_tx_bd(union enetc_tx_bd *txbd) +{ + memset(txbd, 0, sizeof(*txbd)); +} + +/* L3 csum flags */ +#define ENETC_TXBD_L3_IPCS BIT(7) +#define ENETC_TXBD_L3_IPV6 BIT(15) + +#define ENETC_TXBD_L3_START_MASK GENMASK(6, 0) +#define ENETC_TXBD_L3_SET_HSIZE(val) ((((val) >> 2) & 0x7f) << 8) + +/* Extension flags */ +#define ENETC_TXBD_E_FLAGS_VLAN_INS BIT(0) +#define ENETC_TXBD_E_FLAGS_TWO_STEP_PTP BIT(2) + +static inline __le16 enetc_txbd_l3_csoff(int start, int hdr_sz, u16 l3_flags) +{ + return cpu_to_le16(l3_flags | ENETC_TXBD_L3_SET_HSIZE(hdr_sz) | + (start & ENETC_TXBD_L3_START_MASK)); +} + +/* L4 csum flags */ +#define ENETC_TXBD_L4_UDP BIT(5) +#define ENETC_TXBD_L4_TCP BIT(6) + +union enetc_rx_bd { + struct { + __le64 addr; + u8 reserved[8]; + } w; + struct { + __le16 inet_csum; + __le16 parse_summary; + __le32 rss_hash; + __le16 buf_len; + __le16 vlan_opt; + union { + struct { + __le16 flags; + __le16 error; + }; + __le32 lstatus; + }; + } r; +}; + +#define ENETC_RXBD_LSTATUS_R BIT(30) +#define ENETC_RXBD_LSTATUS_F BIT(31) +#define ENETC_RXBD_ERR_MASK 0xff +#define ENETC_RXBD_LSTATUS(flags) ((flags) << 16) +#define ENETC_RXBD_FLAG_VLAN BIT(9) +#define ENETC_RXBD_FLAG_TSTMP BIT(10) + +#define ENETC_MAC_ADDR_FILT_CNT 8 /* # of supported entries per port */ +#define EMETC_MAC_ADDR_FILT_RES 3 /* # of reserved entries at the beginning */ +#define ENETC_MAX_NUM_VFS 2 + +struct enetc_cbd { + union { + struct { + __le32 addr[2]; + __le32 opt[4]; + }; + __le32 data[6]; + }; + __le16 index; + __le16 length; + u8 cmd; + u8 cls; + u8 _res; + u8 status_flags; +}; + +#define ENETC_CBD_FLAGS_SF BIT(7) /* short format */ +#define ENETC_CBD_STATUS_MASK 0xf + +static inline void enetc_get_primary_mac_addr(struct enetc_hw *hw, u8 *addr) +{ + *(u32 *)addr = __raw_readl(hw->reg + ENETC_SIPMAR0); + *(u16 *)(addr + 4) = __raw_readw(hw->reg + ENETC_SIPMAR1); +} + +#define ENETC_SI_INT_IDX 0 +/* base index for Rx/Tx interrupts */ +#define ENETC_BDR_INT_BASE_IDX 1 + +/* Common H/W utility functions */ + +static inline void enetc_enable_rxvlan(struct enetc_hw *hw, int si_idx, + bool en) +{ + u32 val = enetc_rxbdr_rd(hw, si_idx, ENETC_RBMR); + + val = (val & ~ENETC_RBMR_VTE) | (en ? ENETC_RBMR_VTE : 0); + enetc_rxbdr_wr(hw, si_idx, ENETC_RBMR, val); +} + +static inline void enetc_enable_txvlan(struct enetc_hw *hw, int si_idx, + bool en) +{ + u32 val = enetc_txbdr_rd(hw, si_idx, ENETC_TBMR); + + val = (val & ~ENETC_TBMR_VIH) | (en ? ENETC_TBMR_VIH : 0); + enetc_txbdr_wr(hw, si_idx, ENETC_TBMR, val); +} diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c new file mode 100644 index 000000000000..596e0a35339a --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -0,0 +1,831 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2017-2019 NXP */ + +#include +#include +#include +#include "enetc_pf.h" + +#define ENETC_DRV_VER_MAJ 1 +#define ENETC_DRV_VER_MIN 0 + +#define ENETC_DRV_VER_STR __stringify(ENETC_DRV_VER_MAJ) "." \ + __stringify(ENETC_DRV_VER_MIN) +static const char enetc_drv_ver[] = ENETC_DRV_VER_STR; +#define ENETC_DRV_NAME_STR "ENETC PF driver" +static const char enetc_drv_name[] = ENETC_DRV_NAME_STR; + +static void enetc_pf_get_primary_mac_addr(struct enetc_hw *hw, int si, u8 *addr) +{ + u32 upper = __raw_readl(hw->port + ENETC_PSIPMAR0(si)); + u16 lower = __raw_readw(hw->port + ENETC_PSIPMAR1(si)); + + *(u32 *)addr = upper; + *(u16 *)(addr + 4) = lower; +} + +static void enetc_pf_set_primary_mac_addr(struct enetc_hw *hw, int si, + const u8 *addr) +{ + u32 upper = *(const u32 *)addr; + u16 lower = *(const u16 *)(addr + 4); + + __raw_writel(upper, hw->port + ENETC_PSIPMAR0(si)); + __raw_writew(lower, hw->port + ENETC_PSIPMAR1(si)); +} + +static int enetc_pf_set_mac_addr(struct net_device *ndev, void *addr) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct sockaddr *saddr = addr; + + if (!is_valid_ether_addr(saddr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(ndev->dev_addr, saddr->sa_data, ndev->addr_len); + enetc_pf_set_primary_mac_addr(&priv->si->hw, 0, saddr->sa_data); + + return 0; +} + +static void enetc_set_vlan_promisc(struct enetc_hw *hw, char si_map) +{ + u32 val = enetc_port_rd(hw, ENETC_PSIPVMR); + + val &= ~ENETC_PSIPVMR_SET_VP(ENETC_VLAN_PROMISC_MAP_ALL); + enetc_port_wr(hw, ENETC_PSIPVMR, ENETC_PSIPVMR_SET_VP(si_map) | val); +} + +static bool enetc_si_vlan_promisc_is_on(struct enetc_pf *pf, int si_idx) +{ + return pf->vlan_promisc_simap & BIT(si_idx); +} + +static bool enetc_vlan_filter_is_on(struct enetc_pf *pf) +{ + int i; + + for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) + return true; + + return false; +} + +static void enetc_enable_si_vlan_promisc(struct enetc_pf *pf, int si_idx) +{ + pf->vlan_promisc_simap |= BIT(si_idx); + enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap); +} + +static void enetc_disable_si_vlan_promisc(struct enetc_pf *pf, int si_idx) +{ + pf->vlan_promisc_simap &= ~BIT(si_idx); + enetc_set_vlan_promisc(&pf->si->hw, pf->vlan_promisc_simap); +} + +static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, u16 vlan, u8 qos) +{ + u32 val = 0; + + if (vlan) + val = ENETC_PSIVLAN_EN | ENETC_PSIVLAN_SET_QOS(qos) | vlan; + + enetc_port_wr(hw, ENETC_PSIVLANR(si), val); +} + +static int enetc_mac_addr_hash_idx(const u8 *addr) +{ + u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16; + u64 mask = 0; + int res = 0; + int i; + + for (i = 0; i < 8; i++) + mask |= BIT_ULL(i * 6); + + for (i = 0; i < 6; i++) + res |= (hweight64(fold & (mask << i)) & 0x1) << i; + + return res; +} + +static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter) +{ + filter->mac_addr_cnt = 0; + + bitmap_zero(filter->mac_hash_table, + ENETC_MADDR_HASH_TBL_SZ); +} + +static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter, + const unsigned char *addr) +{ + /* add exact match addr */ + ether_addr_copy(filter->mac_addr, addr); + filter->mac_addr_cnt++; +} + +static void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter, + const unsigned char *addr) +{ + int idx = enetc_mac_addr_hash_idx(addr); + + /* add hash table entry */ + __set_bit(idx, filter->mac_hash_table); + filter->mac_addr_cnt++; +} + +static void enetc_clear_mac_ht_flt(struct enetc_si *si, int si_idx, int type) +{ + bool err = si->errata & ENETC_ERR_UCMCSWP; + + if (type == UC) { + enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), 0); + enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), 0); + } else { /* MC */ + enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), 0); + enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), 0); + } +} + +static void enetc_set_mac_ht_flt(struct enetc_si *si, int si_idx, int type, + u32 *hash) +{ + bool err = si->errata & ENETC_ERR_UCMCSWP; + + if (type == UC) { + enetc_port_wr(&si->hw, ENETC_PSIUMHFR0(si_idx, err), *hash); + enetc_port_wr(&si->hw, ENETC_PSIUMHFR1(si_idx), *(hash + 1)); + } else { /* MC */ + enetc_port_wr(&si->hw, ENETC_PSIMMHFR0(si_idx, err), *hash); + enetc_port_wr(&si->hw, ENETC_PSIMMHFR1(si_idx), *(hash + 1)); + } +} + +static void enetc_sync_mac_filters(struct enetc_pf *pf) +{ + struct enetc_mac_filter *f = pf->mac_filter; + struct enetc_si *si = pf->si; + int i, pos; + + pos = EMETC_MAC_ADDR_FILT_RES; + + for (i = 0; i < MADDR_TYPE; i++, f++) { + bool em = (f->mac_addr_cnt == 1) && (i == UC); + bool clear = !f->mac_addr_cnt; + + if (clear) { + if (i == UC) + enetc_clear_mac_flt_entry(si, pos); + + enetc_clear_mac_ht_flt(si, 0, i); + continue; + } + + /* exact match filter */ + if (em) { + int err; + + enetc_clear_mac_ht_flt(si, 0, UC); + + err = enetc_set_mac_flt_entry(si, pos, f->mac_addr, + BIT(0)); + if (!err) + continue; + + /* fallback to HT filtering */ + dev_warn(&si->pdev->dev, "fallback to HT filt (%d)\n", + err); + } + + /* hash table filter, clear EM filter for UC entries */ + if (i == UC) + enetc_clear_mac_flt_entry(si, pos); + + enetc_set_mac_ht_flt(si, 0, i, (u32 *)f->mac_hash_table); + } +} + +static void enetc_pf_set_rx_mode(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_pf *pf = enetc_si_priv(priv->si); + struct enetc_hw *hw = &priv->si->hw; + bool uprom = false, mprom = false; + struct enetc_mac_filter *filter; + struct netdev_hw_addr *ha; + u32 psipmr = 0; + bool em; + + if (ndev->flags & IFF_PROMISC) { + /* enable promisc mode for SI0 (PF) */ + psipmr = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0); + uprom = true; + mprom = true; + /* enable VLAN promisc mode for SI0 */ + if (!enetc_si_vlan_promisc_is_on(pf, 0)) + enetc_enable_si_vlan_promisc(pf, 0); + + } else if (ndev->flags & IFF_ALLMULTI) { + /* enable multi cast promisc mode for SI0 (PF) */ + psipmr = ENETC_PSIPMR_SET_MP(0); + mprom = true; + } + + /* first 2 filter entries belong to PF */ + if (!uprom) { + /* Update unicast filters */ + filter = &pf->mac_filter[UC]; + enetc_reset_mac_addr_filter(filter); + + em = (netdev_uc_count(ndev) == 1); + netdev_for_each_uc_addr(ha, ndev) { + if (em) { + enetc_add_mac_addr_em_filter(filter, ha->addr); + break; + } + + enetc_add_mac_addr_ht_filter(filter, ha->addr); + } + } + + if (!mprom) { + /* Update multicast filters */ + filter = &pf->mac_filter[MC]; + enetc_reset_mac_addr_filter(filter); + + netdev_for_each_mc_addr(ha, ndev) { + if (!is_multicast_ether_addr(ha->addr)) + continue; + + enetc_add_mac_addr_ht_filter(filter, ha->addr); + } + } + + if (!uprom || !mprom) + /* update PF entries */ + enetc_sync_mac_filters(pf); + + psipmr |= enetc_port_rd(hw, ENETC_PSIPMR) & + ~(ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0)); + enetc_port_wr(hw, ENETC_PSIPMR, psipmr); +} + +static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx, + u32 *hash) +{ + enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), *hash); + enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), *(hash + 1)); +} + +static int enetc_vid_hash_idx(unsigned int vid) +{ + int res = 0; + int i; + + for (i = 0; i < 6; i++) + res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i; + + return res; +} + +static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash) +{ + int i; + + if (rehash) { + bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE); + + for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) { + int hidx = enetc_vid_hash_idx(i); + + __set_bit(hidx, pf->vlan_ht_filter); + } + } + + enetc_set_vlan_ht_filter(&pf->si->hw, 0, (u32 *)pf->vlan_ht_filter); +} + +static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_pf *pf = enetc_si_priv(priv->si); + int idx; + + if (enetc_si_vlan_promisc_is_on(pf, 0)) + enetc_disable_si_vlan_promisc(pf, 0); + + __set_bit(vid, pf->active_vlans); + + idx = enetc_vid_hash_idx(vid); + if (!__test_and_set_bit(idx, pf->vlan_ht_filter)) + enetc_sync_vlan_ht_filter(pf, false); + + return 0; +} + +static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_pf *pf = enetc_si_priv(priv->si); + + __clear_bit(vid, pf->active_vlans); + enetc_sync_vlan_ht_filter(pf, true); + + if (!enetc_vlan_filter_is_on(pf)) + enetc_enable_si_vlan_promisc(pf, 0); + + return 0; +} + +static void enetc_set_loopback(struct net_device *ndev, bool en) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_hw *hw = &priv->si->hw; + u32 reg; + + reg = enetc_port_rd(hw, ENETC_PM0_IF_MODE); + if (reg & ENETC_PMO_IFM_RG) { + /* RGMII mode */ + reg = (reg & ~ENETC_PM0_IFM_RLP) | + (en ? ENETC_PM0_IFM_RLP : 0); + enetc_port_wr(hw, ENETC_PM0_IF_MODE, reg); + } else { + /* assume SGMII mode */ + reg = enetc_port_rd(hw, ENETC_PM0_CMD_CFG); + reg = (reg & ~ENETC_PM0_CMD_XGLP) | + (en ? ENETC_PM0_CMD_XGLP : 0); + reg = (reg & ~ENETC_PM0_CMD_PHY_TX_EN) | + (en ? ENETC_PM0_CMD_PHY_TX_EN : 0); + enetc_port_wr(hw, ENETC_PM0_CMD_CFG, reg); + enetc_port_wr(hw, ENETC_PM1_CMD_CFG, reg); + } +} + +static int enetc_pf_set_vf_mac(struct net_device *ndev, int vf, u8 *mac) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_pf *pf = enetc_si_priv(priv->si); + + if (vf >= pf->total_vfs) + return -EINVAL; + + if (!is_valid_ether_addr(mac)) + return -EADDRNOTAVAIL; + + enetc_pf_set_primary_mac_addr(&priv->si->hw, vf + 1, mac); + return 0; +} + +static int enetc_pf_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, + u8 qos, __be16 proto) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_pf *pf = enetc_si_priv(priv->si); + + if (priv->si->errata & ENETC_ERR_VLAN_ISOL) + return -EOPNOTSUPP; + + if (vf >= pf->total_vfs) + return -EINVAL; + + if (proto != htons(ETH_P_8021Q)) + /* only C-tags supported for now */ + return -EPROTONOSUPPORT; + + enetc_set_isol_vlan(&priv->si->hw, vf + 1, vlan, qos); + return 0; +} + +static int enetc_pf_set_vf_spoofchk(struct net_device *ndev, int vf, bool en) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_pf *pf = enetc_si_priv(priv->si); + u32 cfgr; + + if (vf >= pf->total_vfs) + return -EINVAL; + + cfgr = enetc_port_rd(&priv->si->hw, ENETC_PSICFGR0(vf + 1)); + cfgr = (cfgr & ~ENETC_PSICFGR0_ASE) | (en ? ENETC_PSICFGR0_ASE : 0); + enetc_port_wr(&priv->si->hw, ENETC_PSICFGR0(vf + 1), cfgr); + + return 0; +} + +static void enetc_port_setup_primary_mac_address(struct enetc_si *si) +{ + unsigned char mac_addr[MAX_ADDR_LEN]; + struct enetc_pf *pf = enetc_si_priv(si); + struct enetc_hw *hw = &si->hw; + int i; + + /* check MAC addresses for PF and all VFs, if any is 0 set it ro rand */ + for (i = 0; i < pf->total_vfs + 1; i++) { + enetc_pf_get_primary_mac_addr(hw, i, mac_addr); + if (!is_zero_ether_addr(mac_addr)) + continue; + eth_random_addr(mac_addr); + dev_info(&si->pdev->dev, "no MAC address specified for SI%d, using %pM\n", + i, mac_addr); + enetc_pf_set_primary_mac_addr(hw, i, mac_addr); + } +} + +static void enetc_port_si_configure(struct enetc_si *si) +{ + struct enetc_pf *pf = enetc_si_priv(si); + struct enetc_hw *hw = &si->hw; + int num_rings, i; + u32 val; + + val = enetc_port_rd(hw, ENETC_PCAPR0); + num_rings = min(ENETC_PCAPR0_RXBDR(val), ENETC_PCAPR0_TXBDR(val)); + + val = ENETC_PSICFGR0_SET_TXBDR(ENETC_PF_NUM_RINGS); + val |= ENETC_PSICFGR0_SET_RXBDR(ENETC_PF_NUM_RINGS); + + if (unlikely(num_rings < ENETC_PF_NUM_RINGS)) { + val = ENETC_PSICFGR0_SET_TXBDR(num_rings); + val |= ENETC_PSICFGR0_SET_RXBDR(num_rings); + + dev_warn(&si->pdev->dev, "Found %d rings, expected %d!\n", + num_rings, ENETC_PF_NUM_RINGS); + + num_rings = 0; + } + + /* Add default one-time settings for SI0 (PF) */ + val |= ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S); + + enetc_port_wr(hw, ENETC_PSICFGR0(0), val); + + if (num_rings) + num_rings -= ENETC_PF_NUM_RINGS; + + /* Configure the SIs for each available VF */ + val = ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S); + val |= ENETC_PSICFGR0_VTE | ENETC_PSICFGR0_SIVIE; + + if (num_rings) { + num_rings /= pf->total_vfs; + val |= ENETC_PSICFGR0_SET_TXBDR(num_rings); + val |= ENETC_PSICFGR0_SET_RXBDR(num_rings); + } + + for (i = 0; i < pf->total_vfs; i++) + enetc_port_wr(hw, ENETC_PSICFGR0(i + 1), val); + + /* Port level VLAN settings */ + val = ENETC_PVCLCTR_OVTPIDL(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S); + enetc_port_wr(hw, ENETC_PVCLCTR, val); + /* use outer tag for VLAN filtering */ + enetc_port_wr(hw, ENETC_PSIVLANFMR, ENETC_PSIVLANFMR_VS); +} + +static void enetc_configure_port_mac(struct enetc_hw *hw) +{ + enetc_port_wr(hw, ENETC_PM0_MAXFRM, + ENETC_SET_MAXFRM(ENETC_RX_MAXFRM_SIZE)); + + enetc_port_wr(hw, ENETC_PTCMSDUR(0), ENETC_MAC_MAXFRM_SIZE); + enetc_port_wr(hw, ENETC_PTXMBAR, 2 * ENETC_MAC_MAXFRM_SIZE); + + enetc_port_wr(hw, ENETC_PM0_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN | + ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC | + ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); + + enetc_port_wr(hw, ENETC_PM1_CMD_CFG, ENETC_PM0_CMD_PHY_TX_EN | + ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC | + ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); + /* set auto-speed for RGMII */ + if (enetc_port_rd(hw, ENETC_PM0_IF_MODE) & ENETC_PMO_IFM_RG) + enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_RGAUTO); + if (enetc_global_rd(hw, ENETC_G_EPFBLPR(1)) == ENETC_G_EPFBLPR1_XGMII) + enetc_port_wr(hw, ENETC_PM0_IF_MODE, ENETC_PM0_IFM_XGMII); +} + +static void enetc_configure_port_pmac(struct enetc_hw *hw) +{ + u32 temp; + + /* Set pMAC step lock */ + temp = enetc_port_rd(hw, ENETC_PFPMR); + enetc_port_wr(hw, ENETC_PFPMR, + temp | ENETC_PFPMR_PMACE | ENETC_PFPMR_MWLM); + + temp = enetc_port_rd(hw, ENETC_MMCSR); + enetc_port_wr(hw, ENETC_MMCSR, temp | ENETC_MMCSR_ME); +} + +static void enetc_configure_port(struct enetc_pf *pf) +{ + struct enetc_hw *hw = &pf->si->hw; + + enetc_configure_port_pmac(hw); + + enetc_configure_port_mac(hw); + + enetc_port_si_configure(pf->si); + + /* fix-up primary MAC addresses, if not set already */ + enetc_port_setup_primary_mac_address(pf->si); + + /* enforce VLAN promisc mode for all SIs */ + pf->vlan_promisc_simap = ENETC_VLAN_PROMISC_MAP_ALL; + enetc_set_vlan_promisc(hw, pf->vlan_promisc_simap); + + enetc_port_wr(hw, ENETC_PSIPMR, 0); + + /* enable port */ + enetc_port_wr(hw, ENETC_PMR, ENETC_PMR_EN); +} + +#ifdef CONFIG_PCI_IOV +static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs) +{ + struct enetc_si *si = pci_get_drvdata(pdev); + struct enetc_pf *pf = enetc_si_priv(si); + int err; + + if (!num_vfs) { + pf->num_vfs = 0; + pci_disable_sriov(pdev); + } else { + pf->num_vfs = num_vfs; + + err = pci_enable_sriov(pdev, num_vfs); + if (err) { + dev_err(&pdev->dev, "pci_enable_sriov err %d\n", err); + goto err_en_sriov; + } + } + + return num_vfs; + +err_en_sriov: + pf->num_vfs = 0; + + return err; +} +#else +#define enetc_sriov_configure(pdev, num_vfs) (void)0 +#endif + +static int enetc_pf_set_features(struct net_device *ndev, + netdev_features_t features) +{ + netdev_features_t changed = ndev->features ^ features; + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + if (changed & NETIF_F_HW_VLAN_CTAG_RX) + enetc_enable_rxvlan(&priv->si->hw, 0, + !!(features & NETIF_F_HW_VLAN_CTAG_RX)); + + if (changed & NETIF_F_HW_VLAN_CTAG_TX) + enetc_enable_txvlan(&priv->si->hw, 0, + !!(features & NETIF_F_HW_VLAN_CTAG_TX)); + + if (changed & NETIF_F_LOOPBACK) + enetc_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK)); + + return 0; +} + +static const struct net_device_ops enetc_ndev_ops = { + .ndo_open = enetc_open, + .ndo_stop = enetc_close, + .ndo_start_xmit = enetc_xmit, + .ndo_get_stats = enetc_get_stats, + .ndo_set_mac_address = enetc_pf_set_mac_addr, + .ndo_set_rx_mode = enetc_pf_set_rx_mode, + .ndo_vlan_rx_add_vid = enetc_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = enetc_vlan_rx_del_vid, + .ndo_set_vf_mac = enetc_pf_set_vf_mac, + .ndo_set_vf_vlan = enetc_pf_set_vf_vlan, + .ndo_set_vf_spoofchk = enetc_pf_set_vf_spoofchk, + .ndo_set_features = enetc_pf_set_features, +}; + +static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, + const struct net_device_ops *ndev_ops) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + SET_NETDEV_DEV(ndev, &si->pdev->dev); + priv->ndev = ndev; + priv->si = si; + priv->dev = &si->pdev->dev; + si->ndev = ndev; + + priv->msg_enable = (NETIF_MSG_WOL << 1) - 1; + ndev->netdev_ops = ndev_ops; + enetc_set_ethtool_ops(ndev); + ndev->watchdog_timeo = 5 * HZ; + ndev->max_mtu = ENETC_MAX_MTU; + + ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_LOOPBACK; + ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | + NETIF_F_RXCSUM | NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_FILTER; + + if (si->errata & ENETC_ERR_TXCSUM) { + ndev->hw_features &= ~NETIF_F_HW_CSUM; + ndev->features &= ~NETIF_F_HW_CSUM; + } + + ndev->priv_flags |= IFF_UNICAST_FLT; + + /* pick up primary MAC address from SI */ + enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr); +} + +static int enetc_of_get_phy(struct enetc_ndev_priv *priv) +{ + struct device_node *np = priv->dev->of_node; + int err; + + if (!np) { + dev_err(priv->dev, "missing ENETC port node\n"); + return -ENODEV; + } + + priv->phy_node = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy_node) { + if (!of_phy_is_fixed_link(np)) { + dev_err(priv->dev, "PHY not specified\n"); + return -ENODEV; + } + + err = of_phy_register_fixed_link(np); + if (err < 0) { + dev_err(priv->dev, "fixed link registration failed\n"); + return err; + } + + priv->phy_node = of_node_get(np); + } + + priv->if_mode = of_get_phy_mode(np); + if (priv->if_mode < 0) { + dev_err(priv->dev, "missing phy type\n"); + of_node_put(priv->phy_node); + if (of_phy_is_fixed_link(np)) + of_phy_deregister_fixed_link(np); + + return -EINVAL; + } + + return 0; +} + +static void enetc_of_put_phy(struct enetc_ndev_priv *priv) +{ + struct device_node *np = priv->dev->of_node; + + if (np && of_phy_is_fixed_link(np)) + of_phy_deregister_fixed_link(np); + if (priv->phy_node) + of_node_put(priv->phy_node); +} + +static int enetc_pf_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct enetc_ndev_priv *priv; + struct net_device *ndev; + struct enetc_si *si; + struct enetc_pf *pf; + int err; + + if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) { + dev_info(&pdev->dev, "device is disabled, skipping\n"); + return -ENODEV; + } + + err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf)); + if (err) { + dev_err(&pdev->dev, "PCI probing failed\n"); + return err; + } + + si = pci_get_drvdata(pdev); + if (!si->hw.port || !si->hw.global) { + err = -ENODEV; + dev_err(&pdev->dev, "could not map PF space, probing a VF?\n"); + goto err_map_pf_space; + } + + pf = enetc_si_priv(si); + pf->si = si; + pf->total_vfs = pci_sriov_get_totalvfs(pdev); + + enetc_configure_port(pf); + + enetc_get_si_caps(si); + + ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS); + if (!ndev) { + err = -ENOMEM; + dev_err(&pdev->dev, "netdev creation failed\n"); + goto err_alloc_netdev; + } + + enetc_pf_netdev_setup(si, ndev, &enetc_ndev_ops); + + priv = netdev_priv(ndev); + + enetc_init_si_rings_params(priv); + + err = enetc_alloc_si_resources(priv); + if (err) { + dev_err(&pdev->dev, "SI resource alloc failed\n"); + goto err_alloc_si_res; + } + + err = enetc_alloc_msix(priv); + if (err) { + dev_err(&pdev->dev, "MSIX alloc failed\n"); + goto err_alloc_msix; + } + + err = enetc_of_get_phy(priv); + if (err) + dev_warn(&pdev->dev, "Fallback to PHY-less operation\n"); + + err = register_netdev(ndev); + if (err) + goto err_reg_netdev; + + netif_carrier_off(ndev); + + netif_info(priv, probe, ndev, "%s v%s\n", + enetc_drv_name, enetc_drv_ver); + + return 0; + +err_reg_netdev: + enetc_of_put_phy(priv); + enetc_free_msix(priv); +err_alloc_msix: + enetc_free_si_resources(priv); +err_alloc_si_res: + si->ndev = NULL; + free_netdev(ndev); +err_alloc_netdev: +err_map_pf_space: + enetc_pci_remove(pdev); + + return err; +} + +static void enetc_pf_remove(struct pci_dev *pdev) +{ + struct enetc_si *si = pci_get_drvdata(pdev); + struct enetc_pf *pf = enetc_si_priv(si); + struct enetc_ndev_priv *priv; + + if (pf->num_vfs) + enetc_sriov_configure(pdev, 0); + + priv = netdev_priv(si->ndev); + netif_info(priv, drv, si->ndev, "%s v%s remove\n", + enetc_drv_name, enetc_drv_ver); + + unregister_netdev(si->ndev); + + enetc_of_put_phy(priv); + + enetc_free_msix(priv); + + enetc_free_si_resources(priv); + + free_netdev(si->ndev); + + enetc_pci_remove(pdev); +} + +static const struct pci_device_id enetc_pf_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) }, + { 0, } /* End of table. */ +}; +MODULE_DEVICE_TABLE(pci, enetc_pf_id_table); + +static struct pci_driver enetc_pf_driver = { + .name = KBUILD_MODNAME, + .id_table = enetc_pf_id_table, + .probe = enetc_pf_probe, + .remove = enetc_pf_remove, +#ifdef CONFIG_PCI_IOV + .sriov_configure = enetc_sriov_configure, +#endif +}; +module_pci_driver(enetc_pf_driver); + +MODULE_DESCRIPTION(ENETC_DRV_NAME_STR); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(ENETC_DRV_VER_STR); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h new file mode 100644 index 000000000000..a990eb6a85f7 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* Copyright 2017-2019 NXP */ + +#include "enetc.h" + +#define ENETC_PF_NUM_RINGS 8 + +enum enetc_mac_addr_type {UC, MC, MADDR_TYPE}; +#define ENETC_MAX_NUM_MAC_FLT ((ENETC_MAX_NUM_VFS + 1) * MADDR_TYPE) + +#define ENETC_MADDR_HASH_TBL_SZ 64 +struct enetc_mac_filter { + union { + char mac_addr[ETH_ALEN]; + DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ); + }; + int mac_addr_cnt; +}; + +#define ENETC_VLAN_HT_SIZE 64 + +struct enetc_pf { + struct enetc_si *si; + int num_vfs; /* number of active VFs, after sriov_init */ + int total_vfs; /* max number of VFs, set for PF at probe */ + + struct enetc_mac_filter mac_filter[ENETC_MAX_NUM_MAC_FLT]; + + char vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */ + DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE); + DECLARE_BITMAP(active_vlans, VLAN_N_VID); +}; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c new file mode 100644 index 000000000000..5f5103fa7891 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2017-2019 NXP */ + +#include +#include "enetc.h" + +#define ENETC_DRV_VER_MAJ 1 +#define ENETC_DRV_VER_MIN 0 + +#define ENETC_DRV_VER_STR __stringify(ENETC_DRV_VER_MAJ) "." \ + __stringify(ENETC_DRV_VER_MIN) +static const char enetc_drv_ver[] = ENETC_DRV_VER_STR; +#define ENETC_DRV_NAME_STR "ENETC VF driver" +static const char enetc_drv_name[] = ENETC_DRV_NAME_STR; + +/* Probing/ Init */ +static const struct net_device_ops enetc_ndev_ops = { + .ndo_open = enetc_open, + .ndo_stop = enetc_close, + .ndo_start_xmit = enetc_xmit, + .ndo_get_stats = enetc_get_stats, +}; + +static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev, + const struct net_device_ops *ndev_ops) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + SET_NETDEV_DEV(ndev, &si->pdev->dev); + priv->ndev = ndev; + priv->si = si; + priv->dev = &si->pdev->dev; + si->ndev = ndev; + + priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1; + ndev->netdev_ops = ndev_ops; + enetc_set_ethtool_ops(ndev); + ndev->watchdog_timeo = 5 * HZ; + ndev->max_mtu = ENETC_MAX_MTU; + + ndev->hw_features = NETIF_F_RXCSUM | NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; + ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | + NETIF_F_RXCSUM | NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; + + if (si->errata & ENETC_ERR_TXCSUM) { + ndev->hw_features &= ~NETIF_F_HW_CSUM; + ndev->features &= ~NETIF_F_HW_CSUM; + } + + /* pick up primary MAC address from SI */ + enetc_get_primary_mac_addr(&si->hw, ndev->dev_addr); +} + +static int enetc_vf_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct enetc_ndev_priv *priv; + struct net_device *ndev; + struct enetc_si *si; + int err; + + err = enetc_pci_probe(pdev, KBUILD_MODNAME, 0); + if (err) { + dev_err(&pdev->dev, "PCI probing failed\n"); + return err; + } + + si = pci_get_drvdata(pdev); + + enetc_get_si_caps(si); + + ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS); + if (!ndev) { + err = -ENOMEM; + dev_err(&pdev->dev, "netdev creation failed\n"); + goto err_alloc_netdev; + } + + enetc_vf_netdev_setup(si, ndev, &enetc_ndev_ops); + + priv = netdev_priv(ndev); + + enetc_init_si_rings_params(priv); + + err = enetc_alloc_si_resources(priv); + if (err) { + dev_err(&pdev->dev, "SI resource alloc failed\n"); + goto err_alloc_si_res; + } + + err = enetc_alloc_msix(priv); + if (err) { + dev_err(&pdev->dev, "MSIX alloc failed\n"); + goto err_alloc_msix; + } + + err = register_netdev(ndev); + if (err) + goto err_reg_netdev; + + netif_carrier_off(ndev); + + netif_info(priv, probe, ndev, "%s v%s\n", + enetc_drv_name, enetc_drv_ver); + + return 0; + +err_reg_netdev: + enetc_free_msix(priv); +err_alloc_msix: + enetc_free_si_resources(priv); +err_alloc_si_res: + si->ndev = NULL; + free_netdev(ndev); +err_alloc_netdev: + enetc_pci_remove(pdev); + + return err; +} + +static void enetc_vf_remove(struct pci_dev *pdev) +{ + struct enetc_si *si = pci_get_drvdata(pdev); + struct enetc_ndev_priv *priv; + + priv = netdev_priv(si->ndev); + netif_info(priv, drv, si->ndev, "%s v%s remove\n", + enetc_drv_name, enetc_drv_ver); + unregister_netdev(si->ndev); + + enetc_free_msix(priv); + + enetc_free_si_resources(priv); + + free_netdev(si->ndev); + + enetc_pci_remove(pdev); +} + +static const struct pci_device_id enetc_vf_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) }, + { 0, } /* End of table. */ +}; +MODULE_DEVICE_TABLE(pci, enetc_vf_id_table); + +static struct pci_driver enetc_vf_driver = { + .name = KBUILD_MODNAME, + .id_table = enetc_vf_id_table, + .probe = enetc_vf_probe, + .remove = enetc_vf_remove, +}; +module_pci_driver(enetc_vf_driver); + +MODULE_DESCRIPTION(ENETC_DRV_NAME_STR); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(ENETC_DRV_VER_STR); -- cgit v1.2.3 From 16eb4c85c96417c0ef75a7a2ef50eecb198ac8a6 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 22 Jan 2019 15:29:55 +0200 Subject: enetc: Add ethtool statistics This adds most h/w statistics counters: non-privileged SI conters, as well as privileged Port and MAC counters available only to the PF. Per ring software stats are also included. Signed-off-by: Alex Marginean Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- .../net/ethernet/freescale/enetc/enetc_ethtool.c | 187 +++++++++++++++++++++ drivers/net/ethernet/freescale/enetc/enetc_hw.h | 88 ++++++++++ 2 files changed, 275 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c index 41771edada97..e79d80e37d50 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c @@ -89,6 +89,187 @@ static void enetc_get_regs(struct net_device *ndev, struct ethtool_regs *regs, } } +static const struct { + int reg; + char name[ETH_GSTRING_LEN]; +} enetc_si_counters[] = { + { ENETC_SIROCT, "SI rx octets" }, + { ENETC_SIRFRM, "SI rx frames" }, + { ENETC_SIRUCA, "SI rx u-cast frames" }, + { ENETC_SIRMCA, "SI rx m-cast frames" }, + { ENETC_SITOCT, "SI tx octets" }, + { ENETC_SITFRM, "SI tx frames" }, + { ENETC_SITUCA, "SI tx u-cast frames" }, + { ENETC_SITMCA, "SI tx m-cast frames" }, + { ENETC_RBDCR(0), "Rx ring 0 discarded frames" }, + { ENETC_RBDCR(1), "Rx ring 1 discarded frames" }, + { ENETC_RBDCR(2), "Rx ring 2 discarded frames" }, + { ENETC_RBDCR(3), "Rx ring 3 discarded frames" }, + { ENETC_RBDCR(4), "Rx ring 4 discarded frames" }, + { ENETC_RBDCR(5), "Rx ring 5 discarded frames" }, + { ENETC_RBDCR(6), "Rx ring 6 discarded frames" }, + { ENETC_RBDCR(7), "Rx ring 7 discarded frames" }, + { ENETC_RBDCR(8), "Rx ring 8 discarded frames" }, + { ENETC_RBDCR(9), "Rx ring 9 discarded frames" }, + { ENETC_RBDCR(10), "Rx ring 10 discarded frames" }, + { ENETC_RBDCR(11), "Rx ring 11 discarded frames" }, + { ENETC_RBDCR(12), "Rx ring 12 discarded frames" }, + { ENETC_RBDCR(13), "Rx ring 13 discarded frames" }, + { ENETC_RBDCR(14), "Rx ring 14 discarded frames" }, + { ENETC_RBDCR(15), "Rx ring 15 discarded frames" }, +}; + +static const struct { + int reg; + char name[ETH_GSTRING_LEN]; +} enetc_port_counters[] = { + { ENETC_PM0_REOCT, "MAC rx ethernet octets" }, + { ENETC_PM0_RALN, "MAC rx alignment errors" }, + { ENETC_PM0_RXPF, "MAC rx valid pause frames" }, + { ENETC_PM0_RFRM, "MAC rx valid frames" }, + { ENETC_PM0_RFCS, "MAC rx fcs errors" }, + { ENETC_PM0_RVLAN, "MAC rx VLAN frames" }, + { ENETC_PM0_RERR, "MAC rx frame errors" }, + { ENETC_PM0_RUCA, "MAC rx unicast frames" }, + { ENETC_PM0_RMCA, "MAC rx multicast frames" }, + { ENETC_PM0_RBCA, "MAC rx broadcast frames" }, + { ENETC_PM0_RDRP, "MAC rx dropped packets" }, + { ENETC_PM0_RPKT, "MAC rx packets" }, + { ENETC_PM0_RUND, "MAC rx undersized packets" }, + { ENETC_PM0_R64, "MAC rx 64 byte packets" }, + { ENETC_PM0_R127, "MAC rx 65-127 byte packets" }, + { ENETC_PM0_R255, "MAC rx 128-255 byte packets" }, + { ENETC_PM0_R511, "MAC rx 256-511 byte packets" }, + { ENETC_PM0_R1023, "MAC rx 512-1023 byte packets" }, + { ENETC_PM0_R1518, "MAC rx 1024-1518 byte packets" }, + { ENETC_PM0_R1519X, "MAC rx 1519 to max-octet packets" }, + { ENETC_PM0_ROVR, "MAC rx oversized packets" }, + { ENETC_PM0_RJBR, "MAC rx jabber packets" }, + { ENETC_PM0_RFRG, "MAC rx fragment packets" }, + { ENETC_PM0_RCNP, "MAC rx control packets" }, + { ENETC_PM0_RDRNTP, "MAC rx fifo drop" }, + { ENETC_PM0_TEOCT, "MAC tx ethernet octets" }, + { ENETC_PM0_TOCT, "MAC tx octets" }, + { ENETC_PM0_TCRSE, "MAC tx carrier sense errors" }, + { ENETC_PM0_TXPF, "MAC tx valid pause frames" }, + { ENETC_PM0_TFRM, "MAC tx frames" }, + { ENETC_PM0_TFCS, "MAC tx fcs errors" }, + { ENETC_PM0_TVLAN, "MAC tx VLAN frames" }, + { ENETC_PM0_TERR, "MAC tx frames" }, + { ENETC_PM0_TUCA, "MAC tx unicast frames" }, + { ENETC_PM0_TMCA, "MAC tx multicast frames" }, + { ENETC_PM0_TBCA, "MAC tx broadcast frames" }, + { ENETC_PM0_TPKT, "MAC tx packets" }, + { ENETC_PM0_TUND, "MAC tx undersized packets" }, + { ENETC_PM0_T127, "MAC tx 65-127 byte packets" }, + { ENETC_PM0_T1023, "MAC tx 512-1023 byte packets" }, + { ENETC_PM0_T1518, "MAC tx 1024-1518 byte packets" }, + { ENETC_PM0_TCNP, "MAC tx control packets" }, + { ENETC_PM0_TDFR, "MAC tx deferred packets" }, + { ENETC_PM0_TMCOL, "MAC tx multiple collisions" }, + { ENETC_PM0_TSCOL, "MAC tx single collisions" }, + { ENETC_PM0_TLCOL, "MAC tx late collisions" }, + { ENETC_PM0_TECOL, "MAC tx excessive collisions" }, + { ENETC_UFDMF, "SI MAC nomatch u-cast discards" }, + { ENETC_MFDMF, "SI MAC nomatch m-cast discards" }, + { ENETC_PBFDSIR, "SI MAC nomatch b-cast discards" }, + { ENETC_PUFDVFR, "SI VLAN nomatch u-cast discards" }, + { ENETC_PMFDVFR, "SI VLAN nomatch m-cast discards" }, + { ENETC_PBFDVFR, "SI VLAN nomatch b-cast discards" }, + { ENETC_PFDMSAPR, "SI pruning discarded frames" }, + { ENETC_PICDR(0), "ICM DR0 discarded frames" }, + { ENETC_PICDR(1), "ICM DR1 discarded frames" }, + { ENETC_PICDR(2), "ICM DR2 discarded frames" }, + { ENETC_PICDR(3), "ICM DR3 discarded frames" }, +}; + +static const char rx_ring_stats[][ETH_GSTRING_LEN] = { + "Rx ring %2d frames", + "Rx ring %2d alloc errors", +}; + +static const char tx_ring_stats[][ETH_GSTRING_LEN] = { + "Tx ring %2d frames", +}; + +static int enetc_get_sset_count(struct net_device *ndev, int sset) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + if (sset == ETH_SS_STATS) + return ARRAY_SIZE(enetc_si_counters) + + ARRAY_SIZE(tx_ring_stats) * priv->num_tx_rings + + ARRAY_SIZE(rx_ring_stats) * priv->num_rx_rings + + (enetc_si_is_pf(priv->si) ? + ARRAY_SIZE(enetc_port_counters) : 0); + + return -EOPNOTSUPP; +} + +static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + u8 *p = data; + int i, j; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++) { + strlcpy(p, enetc_si_counters[i].name, ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + for (i = 0; i < priv->num_tx_rings; i++) { + for (j = 0; j < ARRAY_SIZE(tx_ring_stats); j++) { + snprintf(p, ETH_GSTRING_LEN, tx_ring_stats[j], + i); + p += ETH_GSTRING_LEN; + } + } + for (i = 0; i < priv->num_rx_rings; i++) { + for (j = 0; j < ARRAY_SIZE(rx_ring_stats); j++) { + snprintf(p, ETH_GSTRING_LEN, rx_ring_stats[j], + i); + p += ETH_GSTRING_LEN; + } + } + + if (!enetc_si_is_pf(priv->si)) + break; + + for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) { + strlcpy(p, enetc_port_counters[i].name, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + break; + } +} + +static void enetc_get_ethtool_stats(struct net_device *ndev, + struct ethtool_stats *stats, u64 *data) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_hw *hw = &priv->si->hw; + int i, o = 0; + + for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++) + data[o++] = enetc_rd64(hw, enetc_si_counters[i].reg); + + for (i = 0; i < priv->num_tx_rings; i++) + data[o++] = priv->tx_ring[i]->stats.packets; + + for (i = 0; i < priv->num_rx_rings; i++) { + data[o++] = priv->rx_ring[i]->stats.packets; + data[o++] = priv->rx_ring[i]->stats.rx_alloc_errs; + } + + if (!enetc_si_is_pf(priv->si)) + return; + + for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) + data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg); +} + static void enetc_get_ringparam(struct net_device *ndev, struct ethtool_ringparam *ring) { @@ -115,6 +296,9 @@ static void enetc_get_ringparam(struct net_device *ndev, static const struct ethtool_ops enetc_pf_ethtool_ops = { .get_regs_len = enetc_get_reglen, .get_regs = enetc_get_regs, + .get_sset_count = enetc_get_sset_count, + .get_strings = enetc_get_strings, + .get_ethtool_stats = enetc_get_ethtool_stats, .get_ringparam = enetc_get_ringparam, .get_link_ksettings = phy_ethtool_get_link_ksettings, .set_link_ksettings = phy_ethtool_set_link_ksettings, @@ -123,6 +307,9 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = { static const struct ethtool_ops enetc_vf_ethtool_ops = { .get_regs_len = enetc_get_reglen, .get_regs = enetc_get_regs, + .get_sset_count = enetc_get_sset_count, + .get_strings = enetc_get_strings, + .get_ethtool_stats = enetc_get_ethtool_stats, .get_ringparam = enetc_get_ringparam, }; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h index 351af09f7cab..68d3b2b5dfb9 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h @@ -34,6 +34,17 @@ #define ENETC_SIPMAR0 0x80 #define ENETC_SIPMAR1 0x84 +/* SI statistics */ +#define ENETC_SIROCT 0x300 +#define ENETC_SIRFRM 0x308 +#define ENETC_SIRUCA 0x310 +#define ENETC_SIRMCA 0x318 +#define ENETC_SITOCT 0x320 +#define ENETC_SITFRM 0x328 +#define ENETC_SITUCA 0x330 +#define ENETC_SITMCA 0x338 +#define ENETC_RBDCR(n) (0x8180 + (n) * 0x200) + /* Control BDR regs */ #define ENETC_SICBDRMR 0x800 #define ENETC_SICBDRSR 0x804 /* RO */ @@ -171,6 +182,65 @@ enum enetc_bdr_type {TX, RX}; #define ENETC_PM0_IFM_RGAUTO (BIT(15) | ENETC_PMO_IFM_RG | BIT(1)) #define ENETC_PM0_IFM_XGMII BIT(12) +/* MAC counters */ +#define ENETC_PM0_REOCT 0x8100 +#define ENETC_PM0_RALN 0x8110 +#define ENETC_PM0_RXPF 0x8118 +#define ENETC_PM0_RFRM 0x8120 +#define ENETC_PM0_RFCS 0x8128 +#define ENETC_PM0_RVLAN 0x8130 +#define ENETC_PM0_RERR 0x8138 +#define ENETC_PM0_RUCA 0x8140 +#define ENETC_PM0_RMCA 0x8148 +#define ENETC_PM0_RBCA 0x8150 +#define ENETC_PM0_RDRP 0x8158 +#define ENETC_PM0_RPKT 0x8160 +#define ENETC_PM0_RUND 0x8168 +#define ENETC_PM0_R64 0x8170 +#define ENETC_PM0_R127 0x8178 +#define ENETC_PM0_R255 0x8180 +#define ENETC_PM0_R511 0x8188 +#define ENETC_PM0_R1023 0x8190 +#define ENETC_PM0_R1518 0x8198 +#define ENETC_PM0_R1519X 0x81A0 +#define ENETC_PM0_ROVR 0x81A8 +#define ENETC_PM0_RJBR 0x81B0 +#define ENETC_PM0_RFRG 0x81B8 +#define ENETC_PM0_RCNP 0x81C0 +#define ENETC_PM0_RDRNTP 0x81C8 +#define ENETC_PM0_TEOCT 0x8200 +#define ENETC_PM0_TOCT 0x8208 +#define ENETC_PM0_TCRSE 0x8210 +#define ENETC_PM0_TXPF 0x8218 +#define ENETC_PM0_TFRM 0x8220 +#define ENETC_PM0_TFCS 0x8228 +#define ENETC_PM0_TVLAN 0x8230 +#define ENETC_PM0_TERR 0x8238 +#define ENETC_PM0_TUCA 0x8240 +#define ENETC_PM0_TMCA 0x8248 +#define ENETC_PM0_TBCA 0x8250 +#define ENETC_PM0_TPKT 0x8260 +#define ENETC_PM0_TUND 0x8268 +#define ENETC_PM0_T127 0x8278 +#define ENETC_PM0_T1023 0x8290 +#define ENETC_PM0_T1518 0x8298 +#define ENETC_PM0_TCNP 0x82C0 +#define ENETC_PM0_TDFR 0x82D0 +#define ENETC_PM0_TMCOL 0x82D8 +#define ENETC_PM0_TSCOL 0x82E0 +#define ENETC_PM0_TLCOL 0x82E8 +#define ENETC_PM0_TECOL 0x82F0 + +/* Port counters */ +#define ENETC_PICDR(n) (0x0700 + (n) * 8) /* n = [0..3] */ +#define ENETC_PBFDSIR 0x0810 +#define ENETC_PFDMSAPR 0x0814 +#define ENETC_UFDMF 0x1680 +#define ENETC_MFDMF 0x1684 +#define ENETC_PUFDVFR 0x1780 +#define ENETC_PMFDVFR 0x1784 +#define ENETC_PBFDVFR 0x1788 + /** Global regs, offset: 2_0000h */ #define ENETC_GLOBAL_BASE 0x20000 #define ENETC_G_EIPBRR0 0x0bf8 @@ -191,9 +261,27 @@ struct enetc_hw { /* general register accessors */ #define enetc_rd_reg(reg) ioread32((reg)) #define enetc_wr_reg(reg, val) iowrite32((val), (reg)) +#ifdef ioread64 +#define enetc_rd_reg64(reg) ioread64((reg)) +#else +/* using this to read out stats on 32b systems */ +static inline u64 enetc_rd_reg64(void __iomem *reg) +{ + u32 low, high, tmp; + + do { + high = ioread32(reg + 4); + low = ioread32(reg); + tmp = ioread32(reg + 4); + } while (high != tmp); + + return le64_to_cpu((__le64)high << 32 | low); +} +#endif #define enetc_rd(hw, off) enetc_rd_reg((hw)->reg + (off)) #define enetc_wr(hw, off, val) enetc_wr_reg((hw)->reg + (off), val) +#define enetc_rd64(hw, off) enetc_rd_reg64((hw)->reg + (off)) /* port register accessors - PF only */ #define enetc_port_rd(hw, off) enetc_rd_reg((hw)->port + (off)) #define enetc_port_wr(hw, off, val) enetc_wr_reg((hw)->port + (off), val) -- cgit v1.2.3 From beb74ac878c8defeb5c862f432a524a032ef2609 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 22 Jan 2019 15:29:56 +0200 Subject: enetc: Add vf to pf messaging support VSIs (VFs) may send a message to the PSI (PF) for general notification or to gain access to hardware resources which requires host inspection. These messages may vary in size and are handled as a partition copy between two memory regions owned by the respective participants. The PSI will respond with fail or success and a 16-bit message code. The patch implements the vf to pf messaging mechanism above and, as the first application making use of this support, it enables the VF to configure its own primary MAC address. Signed-off-by: Catalin Horghidan Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/Makefile | 1 + drivers/net/ethernet/freescale/enetc/enetc.h | 14 ++ drivers/net/ethernet/freescale/enetc/enetc_hw.h | 50 +++++++ drivers/net/ethernet/freescale/enetc/enetc_msg.c | 164 +++++++++++++++++++++++ drivers/net/ethernet/freescale/enetc/enetc_pf.c | 68 ++++++++++ drivers/net/ethernet/freescale/enetc/enetc_pf.h | 17 +++ drivers/net/ethernet/freescale/enetc/enetc_vf.c | 85 ++++++++++++ 7 files changed, 399 insertions(+) create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_msg.c (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile index a85ef2b475fe..9529b01872ca 100644 --- a/drivers/net/ethernet/freescale/enetc/Makefile +++ b/drivers/net/ethernet/freescale/enetc/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o fsl-enetc-$(CONFIG_FSL_ENETC) += enetc.o enetc_cbdr.o enetc_ethtool.o +fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o fsl-enetc-objs := enetc_pf.o $(fsl-enetc-y) obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index d19bb434bca3..c44e6be24038 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -103,6 +103,12 @@ struct enetc_cbdr { #define ENETC_TXBD(BDR, i) (&(((union enetc_tx_bd *)((BDR).bd_base))[i])) #define ENETC_RXBD(BDR, i) (&(((union enetc_rx_bd *)((BDR).bd_base))[i])) +struct enetc_msg_swbd { + void *vaddr; + dma_addr_t dma; + int size; +}; + #define ENETC_REV1 0x1 enum enetc_errata { ENETC_ERR_TXCSUM = BIT(0), @@ -173,6 +179,14 @@ struct enetc_ndev_priv { phy_interface_t if_mode; }; +/* Messaging */ + +/* VF-PF set primary MAC address message format */ +struct enetc_msg_cmd_set_primary_mac { + struct enetc_msg_cmd_header header; + struct sockaddr mac; +}; + #define ENETC_CBD(R, i) (&(((struct enetc_cbd *)((R).bd_base))[i])) #define ENETC_CBDR_TIMEOUT 1000 /* usecs */ diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h index 68d3b2b5dfb9..25edb46a4451 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h @@ -34,6 +34,29 @@ #define ENETC_SIPMAR0 0x80 #define ENETC_SIPMAR1 0x84 +/* VF-PF Message passing */ +#define ENETC_DEFAULT_MSG_SIZE 1024 /* and max size */ +/* msg size encoding: default and max msg value of 1024B encoded as 0 */ +static inline u32 enetc_vsi_set_msize(u32 size) +{ + return size < ENETC_DEFAULT_MSG_SIZE ? size >> 5 : 0; +} + +#define ENETC_PSIMSGRR 0x204 +#define ENETC_PSIMSGRR_MR_MASK GENMASK(2, 1) +#define ENETC_PSIMSGRR_MR(n) BIT((n) + 1) /* n = VSI index */ +#define ENETC_PSIVMSGRCVAR0(n) (0x210 + (n) * 0x8) /* n = VSI index */ +#define ENETC_PSIVMSGRCVAR1(n) (0x214 + (n) * 0x8) + +#define ENETC_VSIMSGSR 0x204 /* RO */ +#define ENETC_VSIMSGSR_MB BIT(0) +#define ENETC_VSIMSGSR_MS BIT(1) +#define ENETC_VSIMSGSNDAR0 0x210 +#define ENETC_VSIMSGSNDAR1 0x214 + +#define ENETC_SIMSGSR_SET_MC(val) ((val) << 16) +#define ENETC_SIMSGSR_GET_MC(val) ((val) >> 16) + /* SI statistics */ #define ENETC_SIROCT 0x300 #define ENETC_SIRFRM 0x308 @@ -418,6 +441,33 @@ static inline void enetc_get_primary_mac_addr(struct enetc_hw *hw, u8 *addr) /* base index for Rx/Tx interrupts */ #define ENETC_BDR_INT_BASE_IDX 1 +/* Messaging */ + +/* Command completion status */ +enum enetc_msg_cmd_status { + ENETC_MSG_CMD_STATUS_OK, + ENETC_MSG_CMD_STATUS_FAIL +}; + +/* VSI-PSI command message types */ +enum enetc_msg_cmd_type { + ENETC_MSG_CMD_MNG_MAC = 1, /* manage MAC address */ + ENETC_MSG_CMD_MNG_RX_MAC_FILTER,/* manage RX MAC table */ + ENETC_MSG_CMD_MNG_RX_VLAN_FILTER /* manage RX VLAN table */ +}; + +/* VSI-PSI command action types */ +enum enetc_msg_cmd_action_type { + ENETC_MSG_CMD_MNG_ADD = 1, + ENETC_MSG_CMD_MNG_REMOVE +}; + +/* PSI-VSI command header format */ +struct enetc_msg_cmd_header { + u16 type; /* command class type */ + u16 id; /* denotes the specific required action */ +}; + /* Common H/W utility functions */ static inline void enetc_enable_rxvlan(struct enetc_hw *hw, int si_idx, diff --git a/drivers/net/ethernet/freescale/enetc/enetc_msg.c b/drivers/net/ethernet/freescale/enetc/enetc_msg.c new file mode 100644 index 000000000000..40d22ebe9224 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_msg.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2017-2019 NXP */ + +#include "enetc_pf.h" + +static void enetc_msg_disable_mr_int(struct enetc_hw *hw) +{ + u32 psiier = enetc_rd(hw, ENETC_PSIIER); + /* disable MR int source(s) */ + enetc_wr(hw, ENETC_PSIIER, psiier & ~ENETC_PSIIER_MR_MASK); +} + +static void enetc_msg_enable_mr_int(struct enetc_hw *hw) +{ + u32 psiier = enetc_rd(hw, ENETC_PSIIER); + + enetc_wr(hw, ENETC_PSIIER, psiier | ENETC_PSIIER_MR_MASK); +} + +static irqreturn_t enetc_msg_psi_msix(int irq, void *data) +{ + struct enetc_si *si = (struct enetc_si *)data; + struct enetc_pf *pf = enetc_si_priv(si); + + enetc_msg_disable_mr_int(&si->hw); + schedule_work(&pf->msg_task); + + return IRQ_HANDLED; +} + +static void enetc_msg_task(struct work_struct *work) +{ + struct enetc_pf *pf = container_of(work, struct enetc_pf, msg_task); + struct enetc_hw *hw = &pf->si->hw; + unsigned long mr_mask; + int i; + + for (;;) { + mr_mask = enetc_rd(hw, ENETC_PSIMSGRR) & ENETC_PSIMSGRR_MR_MASK; + if (!mr_mask) { + /* re-arm MR interrupts, w1c the IDR reg */ + enetc_wr(hw, ENETC_PSIIDR, ENETC_PSIIER_MR_MASK); + enetc_msg_enable_mr_int(hw); + return; + } + + for (i = 0; i < pf->num_vfs; i++) { + u32 psimsgrr; + u16 msg_code; + + if (!(ENETC_PSIMSGRR_MR(i) & mr_mask)) + continue; + + enetc_msg_handle_rxmsg(pf, i, &msg_code); + + psimsgrr = ENETC_SIMSGSR_SET_MC(msg_code); + psimsgrr |= ENETC_PSIMSGRR_MR(i); /* w1c */ + enetc_wr(hw, ENETC_PSIMSGRR, psimsgrr); + } + } +} + +/* Init */ +static int enetc_msg_alloc_mbx(struct enetc_si *si, int idx) +{ + struct enetc_pf *pf = enetc_si_priv(si); + struct device *dev = &si->pdev->dev; + struct enetc_hw *hw = &si->hw; + struct enetc_msg_swbd *msg; + u32 val; + + msg = &pf->rxmsg[idx]; + /* allocate and set receive buffer */ + msg->size = ENETC_DEFAULT_MSG_SIZE; + + msg->vaddr = dma_alloc_coherent(dev, msg->size, &msg->dma, + GFP_KERNEL); + if (!msg->vaddr) { + dev_err(dev, "msg: fail to alloc dma buffer of size: %d\n", + msg->size); + return -ENOMEM; + } + + /* set multiple of 32 bytes */ + val = lower_32_bits(msg->dma); + enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), val); + val = upper_32_bits(msg->dma); + enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), val); + + return 0; +} + +static void enetc_msg_free_mbx(struct enetc_si *si, int idx) +{ + struct enetc_pf *pf = enetc_si_priv(si); + struct enetc_hw *hw = &si->hw; + struct enetc_msg_swbd *msg; + + msg = &pf->rxmsg[idx]; + dma_free_coherent(&si->pdev->dev, msg->size, msg->vaddr, msg->dma); + memset(msg, 0, sizeof(*msg)); + + enetc_wr(hw, ENETC_PSIVMSGRCVAR0(idx), 0); + enetc_wr(hw, ENETC_PSIVMSGRCVAR1(idx), 0); +} + +int enetc_msg_psi_init(struct enetc_pf *pf) +{ + struct enetc_si *si = pf->si; + int vector, i, err; + + /* register message passing interrupt handler */ + snprintf(pf->msg_int_name, sizeof(pf->msg_int_name), "%s-vfmsg", + si->ndev->name); + vector = pci_irq_vector(si->pdev, ENETC_SI_INT_IDX); + err = request_irq(vector, enetc_msg_psi_msix, 0, pf->msg_int_name, si); + if (err) { + dev_err(&si->pdev->dev, + "PSI messaging: request_irq() failed!\n"); + return err; + } + + /* set one IRQ entry for PSI message receive notification (SI int) */ + enetc_wr(&si->hw, ENETC_SIMSIVR, ENETC_SI_INT_IDX); + + /* initialize PSI mailbox */ + INIT_WORK(&pf->msg_task, enetc_msg_task); + + for (i = 0; i < pf->num_vfs; i++) { + err = enetc_msg_alloc_mbx(si, i); + if (err) + goto err_init_mbx; + } + + /* enable MR interrupts */ + enetc_msg_enable_mr_int(&si->hw); + + return 0; + +err_init_mbx: + for (i--; i >= 0; i--) + enetc_msg_free_mbx(si, i); + + free_irq(vector, si); + + return err; +} + +void enetc_msg_psi_free(struct enetc_pf *pf) +{ + struct enetc_si *si = pf->si; + int i; + + cancel_work_sync(&pf->msg_task); + + /* disable MR interrupts */ + enetc_msg_disable_mr_int(&si->hw); + + for (i = 0; i < pf->num_vfs; i++) + enetc_msg_free_mbx(si, i); + + /* de-register message passing interrupt handler */ + free_irq(pci_irq_vector(si->pdev, ENETC_SI_INT_IDX), si); +} diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 596e0a35339a..35cad5df71ef 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -366,6 +366,7 @@ static int enetc_pf_set_vf_mac(struct net_device *ndev, int vf, u8 *mac) { struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_pf *pf = enetc_si_priv(priv->si); + struct enetc_vf_state *vf_state; if (vf >= pf->total_vfs) return -EINVAL; @@ -373,6 +374,8 @@ static int enetc_pf_set_vf_mac(struct net_device *ndev, int vf, u8 *mac) if (!is_valid_ether_addr(mac)) return -EADDRNOTAVAIL; + vf_state = &pf->vf_state[vf]; + vf_state->flags |= ENETC_VF_FLAG_PF_SET_MAC; enetc_pf_set_primary_mac_addr(&priv->si->hw, vf + 1, mac); return 0; } @@ -541,6 +544,53 @@ static void enetc_configure_port(struct enetc_pf *pf) enetc_port_wr(hw, ENETC_PMR, ENETC_PMR_EN); } +/* Messaging */ +static u16 enetc_msg_pf_set_vf_primary_mac_addr(struct enetc_pf *pf, + int vf_id) +{ + struct enetc_vf_state *vf_state = &pf->vf_state[vf_id]; + struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id]; + struct enetc_msg_cmd_set_primary_mac *cmd; + struct device *dev = &pf->si->pdev->dev; + u16 cmd_id; + char *addr; + + cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr; + cmd_id = cmd->header.id; + if (cmd_id != ENETC_MSG_CMD_MNG_ADD) + return ENETC_MSG_CMD_STATUS_FAIL; + + addr = cmd->mac.sa_data; + if (vf_state->flags & ENETC_VF_FLAG_PF_SET_MAC) + dev_warn(dev, "Attempt to override PF set mac addr for VF%d\n", + vf_id); + else + enetc_pf_set_primary_mac_addr(&pf->si->hw, vf_id + 1, addr); + + return ENETC_MSG_CMD_STATUS_OK; +} + +void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int vf_id, u16 *status) +{ + struct enetc_msg_swbd *msg = &pf->rxmsg[vf_id]; + struct device *dev = &pf->si->pdev->dev; + struct enetc_msg_cmd_header *cmd_hdr; + u16 cmd_type; + + *status = ENETC_MSG_CMD_STATUS_OK; + cmd_hdr = (struct enetc_msg_cmd_header *)msg->vaddr; + cmd_type = cmd_hdr->type; + + switch (cmd_type) { + case ENETC_MSG_CMD_MNG_MAC: + *status = enetc_msg_pf_set_vf_primary_mac_addr(pf, vf_id); + break; + default: + dev_err(dev, "command not supported (cmd_type: 0x%x)\n", + cmd_type); + } +} + #ifdef CONFIG_PCI_IOV static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs) { @@ -549,11 +599,26 @@ static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs) int err; if (!num_vfs) { + enetc_msg_psi_free(pf); + kfree(pf->vf_state); pf->num_vfs = 0; pci_disable_sriov(pdev); } else { pf->num_vfs = num_vfs; + pf->vf_state = kcalloc(num_vfs, sizeof(struct enetc_vf_state), + GFP_KERNEL); + if (!pf->vf_state) { + pf->num_vfs = 0; + return -ENOMEM; + } + + err = enetc_msg_psi_init(pf); + if (err) { + dev_err(&pdev->dev, "enetc_msg_psi_init (%d)\n", err); + goto err_msg_psi; + } + err = pci_enable_sriov(pdev, num_vfs); if (err) { dev_err(&pdev->dev, "pci_enable_sriov err %d\n", err); @@ -564,6 +629,9 @@ static int enetc_sriov_configure(struct pci_dev *pdev, int num_vfs) return num_vfs; err_en_sriov: + enetc_msg_psi_free(pf); +err_msg_psi: + kfree(pf->vf_state); pf->num_vfs = 0; return err; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h index a990eb6a85f7..2061ae5ccba0 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h @@ -19,14 +19,31 @@ struct enetc_mac_filter { #define ENETC_VLAN_HT_SIZE 64 +enum enetc_vf_flags { + ENETC_VF_FLAG_PF_SET_MAC = BIT(0), +}; + +struct enetc_vf_state { + enum enetc_vf_flags flags; +}; + struct enetc_pf { struct enetc_si *si; int num_vfs; /* number of active VFs, after sriov_init */ int total_vfs; /* max number of VFs, set for PF at probe */ + struct enetc_vf_state *vf_state; struct enetc_mac_filter mac_filter[ENETC_MAX_NUM_MAC_FLT]; + struct enetc_msg_swbd rxmsg[ENETC_MAX_NUM_VFS]; + struct work_struct msg_task; + char msg_int_name[ENETC_INT_NAME_MAX]; + char vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */ DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE); DECLARE_BITMAP(active_vlans, VLAN_N_VID); }; + +int enetc_msg_psi_init(struct enetc_pf *pf); +void enetc_msg_psi_free(struct enetc_pf *pf); +void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int mbox_id, u16 *status); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c index 5f5103fa7891..e8695a99aec3 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c @@ -13,12 +13,97 @@ static const char enetc_drv_ver[] = ENETC_DRV_VER_STR; #define ENETC_DRV_NAME_STR "ENETC VF driver" static const char enetc_drv_name[] = ENETC_DRV_NAME_STR; +/* Messaging */ +static void enetc_msg_vsi_write_msg(struct enetc_hw *hw, + struct enetc_msg_swbd *msg) +{ + u32 val; + + val = enetc_vsi_set_msize(msg->size) | lower_32_bits(msg->dma); + enetc_wr(hw, ENETC_VSIMSGSNDAR1, upper_32_bits(msg->dma)); + enetc_wr(hw, ENETC_VSIMSGSNDAR0, val); +} + +static int enetc_msg_vsi_send(struct enetc_si *si, struct enetc_msg_swbd *msg) +{ + int timeout = 100; + u32 vsimsgsr; + + enetc_msg_vsi_write_msg(&si->hw, msg); + + do { + vsimsgsr = enetc_rd(&si->hw, ENETC_VSIMSGSR); + if (!(vsimsgsr & ENETC_VSIMSGSR_MB)) + break; + + usleep_range(1000, 2000); + } while (--timeout); + + if (!timeout) + return -ETIMEDOUT; + + /* check for message delivery error */ + if (vsimsgsr & ENETC_VSIMSGSR_MS) { + dev_err(&si->pdev->dev, "VSI command execute error: %d\n", + ENETC_SIMSGSR_GET_MC(vsimsgsr)); + return -EIO; + } + + return 0; +} + +static int enetc_msg_vsi_set_primary_mac_addr(struct enetc_ndev_priv *priv, + struct sockaddr *saddr) +{ + struct enetc_msg_cmd_set_primary_mac *cmd; + struct enetc_msg_swbd msg; + int err; + + msg.size = ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac), 64); + msg.vaddr = dma_alloc_coherent(priv->dev, msg.size, &msg.dma, + GFP_KERNEL); + if (!msg.vaddr) { + dev_err(priv->dev, "Failed to alloc Tx msg (size: %d)\n", + msg.size); + return -ENOMEM; + } + + cmd = (struct enetc_msg_cmd_set_primary_mac *)msg.vaddr; + cmd->header.type = ENETC_MSG_CMD_MNG_MAC; + cmd->header.id = ENETC_MSG_CMD_MNG_ADD; + memcpy(&cmd->mac, saddr, sizeof(struct sockaddr)); + + /* send the command and wait */ + err = enetc_msg_vsi_send(priv->si, &msg); + + dma_free_coherent(priv->dev, msg.size, msg.vaddr, msg.dma); + + return err; +} + +static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct sockaddr *saddr = addr; + int err; + + if (!is_valid_ether_addr(saddr->sa_data)) + return -EADDRNOTAVAIL; + + err = enetc_msg_vsi_set_primary_mac_addr(priv, saddr); + if (err) + return err; + + return 0; +} + /* Probing/ Init */ static const struct net_device_ops enetc_ndev_ops = { .ndo_open = enetc_open, .ndo_stop = enetc_close, .ndo_start_xmit = enetc_xmit, .ndo_get_stats = enetc_get_stats, + .ndo_set_mac_address = enetc_vf_set_mac_addr, }; static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev, -- cgit v1.2.3 From d382563f541b01f6a38fb1edd762a4cfcd2ca52a Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 22 Jan 2019 15:29:57 +0200 Subject: enetc: Add RFS and RSS support A ternary match table is used for RFS. If multiple entries in the table match, the entry with the lowest numerical values index is chosen as the matching entry. Entries in the table are identified using an index which takes a value from 0 to PRFSCAPR[NUM_RFS]-1 when accessed by the PSI (PF). Portions of the RFS table can be assigned to each SI by the PSI (PF) driver in PSIaRFSCFGR. Assignments are cumulative, the entries assigned to SIn start after those assigned to SIn-1. The total assignments to all SIs must be equal to or less than the number available to the port as found in PRFSCAPR. For RSS, the Toeplitz hash function used requires two inputs, a 40B random secret key that is supplied through the PRSSKR0-9 registers as well as the relevant pieces of the packet header (n-tuple). The 6 LSB bits of the hash function result will then be used as a pointer to obtain the tag referenced in the 64 entry indirection table. The result will provide a winning group which will be used to help route the received packet. Signed-off-by: Alex Marginean Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/enetc.c | 77 ++++++ drivers/net/ethernet/freescale/enetc/enetc.h | 16 ++ drivers/net/ethernet/freescale/enetc/enetc_cbdr.c | 100 ++++++++ .../net/ethernet/freescale/enetc/enetc_ethtool.c | 277 ++++++++++++++++++++- drivers/net/ethernet/freescale/enetc/enetc_hw.h | 43 ++++ drivers/net/ethernet/freescale/enetc/enetc_pf.c | 34 ++- drivers/net/ethernet/freescale/enetc/enetc_vf.c | 10 + 7 files changed, 554 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index f63be02cffae..37b587c541ee 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -638,6 +638,7 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, } /* Probing and Init */ +#define ENETC_MAX_RFS_SIZE 64 void enetc_get_si_caps(struct enetc_si *si) { struct enetc_hw *hw = &si->hw; @@ -647,6 +648,17 @@ void enetc_get_si_caps(struct enetc_si *si) val = enetc_rd(hw, ENETC_SICAPR0); si->num_rx_rings = (val >> 16) & 0xff; si->num_tx_rings = val & 0xff; + + val = enetc_rd(hw, ENETC_SIRFSCAPR); + si->num_fs_entries = ENETC_SIRFSCAPR_GET_NUM_RFS(val); + si->num_fs_entries = min(si->num_fs_entries, ENETC_MAX_RFS_SIZE); + + si->num_rss = 0; + val = enetc_rd(hw, ENETC_SIPCAPR0); + if (val & ENETC_SIPCAPR0_RSS) { + val = enetc_rd(hw, ENETC_SIRSSCAPR); + si->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(val); + } } static int enetc_dma_alloc_bdr(struct enetc_bdr *r, size_t bd_size) @@ -898,10 +910,31 @@ static void enetc_clear_cbdr(struct enetc_hw *hw) enetc_wr(hw, ENETC_SICBDRMR, 0); } +static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups) +{ + int *rss_table; + int i; + + rss_table = kmalloc_array(si->num_rss, sizeof(*rss_table), GFP_KERNEL); + if (!rss_table) + return -ENOMEM; + + /* Set up RSS table defaults */ + for (i = 0; i < si->num_rss; i++) + rss_table[i] = i % num_groups; + + enetc_set_rss_table(si, rss_table, si->num_rss); + + kfree(rss_table); + + return 0; +} + static int enetc_configure_si(struct enetc_ndev_priv *priv) { struct enetc_si *si = priv->si; struct enetc_hw *hw = &si->hw; + int err; enetc_setup_cbdr(hw, &si->cbd_ring); /* set SI cache attributes */ @@ -911,6 +944,12 @@ static int enetc_configure_si(struct enetc_ndev_priv *priv) /* enable SI */ enetc_wr(hw, ENETC_SIMR, ENETC_SIMR_EN); + if (si->num_rss) { + err = enetc_setup_default_rss_table(si, priv->num_rx_rings); + if (err) + return err; + } + return 0; } @@ -943,6 +982,13 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv) if (err) return err; + priv->cls_rules = kcalloc(si->num_fs_entries, sizeof(*priv->cls_rules), + GFP_KERNEL); + if (!priv->cls_rules) { + err = -ENOMEM; + goto err_alloc_cls; + } + err = enetc_configure_si(priv); if (err) goto err_config_si; @@ -950,6 +996,8 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv) return 0; err_config_si: + kfree(priv->cls_rules); +err_alloc_cls: enetc_clear_cbdr(&si->hw); enetc_free_cbdr(priv->dev, &si->cbd_ring); @@ -962,6 +1010,8 @@ void enetc_free_si_resources(struct enetc_ndev_priv *priv) enetc_clear_cbdr(&si->hw); enetc_free_cbdr(priv->dev, &si->cbd_ring); + + kfree(priv->cls_rules); } static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) @@ -1316,6 +1366,33 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev) return stats; } +static int enetc_set_rss(struct net_device *ndev, int en) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_hw *hw = &priv->si->hw; + u32 reg; + + enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings); + + reg = enetc_rd(hw, ENETC_SIMR); + reg &= ~ENETC_SIMR_RSSE; + reg |= (en) ? ENETC_SIMR_RSSE : 0; + enetc_wr(hw, ENETC_SIMR, reg); + + return 0; +} + +int enetc_set_features(struct net_device *ndev, + netdev_features_t features) +{ + netdev_features_t changed = ndev->features ^ features; + + if (changed & NETIF_F_RXHASH) + enetc_set_rss(ndev, !!(features & NETIF_F_RXHASH)); + + return 0; +} + int enetc_alloc_msix(struct enetc_ndev_priv *priv) { struct pci_dev *pdev = priv->si->pdev; diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index c44e6be24038..b274135c5103 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -128,6 +128,8 @@ struct enetc_si { int num_rx_rings; /* how many rings are available in the SI */ int num_tx_rings; + int num_fs_entries; + int num_rss; /* number of RSS buckets */ unsigned short pad; }; @@ -158,6 +160,11 @@ struct enetc_int_vector { struct enetc_bdr tx_ring[0]; }; +struct enetc_cls_rule { + struct ethtool_rx_flow_spec fs; + int used; +}; + #define ENETC_MAX_BDR_INT 2 /* fixed to max # of available cpus */ struct enetc_ndev_priv { @@ -175,6 +182,8 @@ struct enetc_ndev_priv { struct enetc_bdr *tx_ring[16]; struct enetc_bdr *rx_ring[16]; + struct enetc_cls_rule *cls_rules; + struct device_node *phy_node; phy_interface_t if_mode; }; @@ -205,6 +214,8 @@ int enetc_open(struct net_device *ndev); int enetc_close(struct net_device *ndev); netdev_tx_t enetc_xmit(struct sk_buff *skb, struct net_device *ndev); struct net_device_stats *enetc_get_stats(struct net_device *ndev); +int enetc_set_features(struct net_device *ndev, + netdev_features_t features); /* ethtool */ void enetc_set_ethtool_ops(struct net_device *ndev); @@ -212,3 +223,8 @@ void enetc_set_ethtool_ops(struct net_device *ndev); int enetc_set_mac_flt_entry(struct enetc_si *si, int index, char *mac_addr, int si_map); int enetc_clear_mac_flt_entry(struct enetc_si *si, int index); +int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse, + int index); +void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes); +int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count); +int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c index 2ec0f2f316be..de466b71bf8f 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c @@ -108,3 +108,103 @@ int enetc_set_mac_flt_entry(struct enetc_si *si, int index, return enetc_send_cmd(si, &cbd); } + +#define RFSE_ALIGN 64 +/* Set entry in RFS table */ +int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse, + int index) +{ + struct enetc_cbd cbd = {.cmd = 0}; + dma_addr_t dma, dma_align; + void *tmp, *tmp_align; + int err; + + /* fill up the "set" descriptor */ + cbd.cmd = 0; + cbd.cls = 4; + cbd.index = cpu_to_le16(index); + cbd.length = cpu_to_le16(sizeof(*rfse)); + cbd.opt[3] = cpu_to_le32(0); /* SI */ + + tmp = dma_alloc_coherent(&si->pdev->dev, sizeof(*rfse) + RFSE_ALIGN, + &dma, GFP_KERNEL); + if (!tmp) { + dev_err(&si->pdev->dev, "DMA mapping of RFS entry failed!\n"); + return -ENOMEM; + } + + dma_align = ALIGN(dma, RFSE_ALIGN); + tmp_align = PTR_ALIGN(tmp, RFSE_ALIGN); + memcpy(tmp_align, rfse, sizeof(*rfse)); + + cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align)); + cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align)); + + err = enetc_send_cmd(si, &cbd); + if (err) + dev_err(&si->pdev->dev, "FS entry add failed (%d)!", err); + + dma_free_coherent(&si->pdev->dev, sizeof(*rfse) + RFSE_ALIGN, + tmp, dma); + + return err; +} + +#define RSSE_ALIGN 64 +static int enetc_cmd_rss_table(struct enetc_si *si, u32 *table, int count, + bool read) +{ + struct enetc_cbd cbd = {.cmd = 0}; + dma_addr_t dma, dma_align; + u8 *tmp, *tmp_align; + int err, i; + + if (count < RSSE_ALIGN) + /* HW only takes in a full 64 entry table */ + return -EINVAL; + + tmp = dma_alloc_coherent(&si->pdev->dev, count + RSSE_ALIGN, + &dma, GFP_KERNEL); + if (!tmp) { + dev_err(&si->pdev->dev, "DMA mapping of RSS table failed!\n"); + return -ENOMEM; + } + dma_align = ALIGN(dma, RSSE_ALIGN); + tmp_align = PTR_ALIGN(tmp, RSSE_ALIGN); + + if (!read) + for (i = 0; i < count; i++) + tmp_align[i] = (u8)(table[i]); + + /* fill up the descriptor */ + cbd.cmd = read ? 2 : 1; + cbd.cls = 3; + cbd.length = cpu_to_le16(count); + + cbd.addr[0] = cpu_to_le32(lower_32_bits(dma_align)); + cbd.addr[1] = cpu_to_le32(upper_32_bits(dma_align)); + + err = enetc_send_cmd(si, &cbd); + if (err) + dev_err(&si->pdev->dev, "RSS cmd failed (%d)!", err); + + if (read) + for (i = 0; i < count; i++) + table[i] = tmp_align[i]; + + dma_free_coherent(&si->pdev->dev, count + RSSE_ALIGN, tmp, dma); + + return err; +} + +/* Get RSS table */ +int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count) +{ + return enetc_cmd_rss_table(si, table, count, true); +} + +/* Set RSS table */ +int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count) +{ + return enetc_cmd_rss_table(si, (u32 *)table, count, false); +} diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c index e79d80e37d50..1ecad9ffabae 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c @@ -25,8 +25,8 @@ static const u32 enetc_rxbdr_regs[] = { static const u32 enetc_port_regs[] = { ENETC_PMR, ENETC_PSR, ENETC_PSIPMR, ENETC_PSIPMAR0(0), ENETC_PSIPMAR1(0), ENETC_PTXMBAR, ENETC_PCAPR0, ENETC_PCAPR1, - ENETC_PSICFGR0(0), ENETC_PTCMSDUR(0), ENETC_PM0_CMD_CFG, - ENETC_PM0_MAXFRM, ENETC_PM0_IF_MODE + ENETC_PSICFGR0(0), ENETC_PRFSCAPR, ENETC_PTCMSDUR(0), + ENETC_PM0_CMD_CFG, ENETC_PM0_MAXFRM, ENETC_PM0_IF_MODE }; static int enetc_get_reglen(struct net_device *ndev) @@ -270,6 +270,268 @@ static void enetc_get_ethtool_stats(struct net_device *ndev, data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg); } +#define ENETC_RSSHASH_L3 (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO | RXH_IP_SRC | \ + RXH_IP_DST) +#define ENETC_RSSHASH_L4 (ENETC_RSSHASH_L3 | RXH_L4_B_0_1 | RXH_L4_B_2_3) +static int enetc_get_rsshash(struct ethtool_rxnfc *rxnfc) +{ + static const u32 rsshash[] = { + [TCP_V4_FLOW] = ENETC_RSSHASH_L4, + [UDP_V4_FLOW] = ENETC_RSSHASH_L4, + [SCTP_V4_FLOW] = ENETC_RSSHASH_L4, + [AH_ESP_V4_FLOW] = ENETC_RSSHASH_L3, + [IPV4_FLOW] = ENETC_RSSHASH_L3, + [TCP_V6_FLOW] = ENETC_RSSHASH_L4, + [UDP_V6_FLOW] = ENETC_RSSHASH_L4, + [SCTP_V6_FLOW] = ENETC_RSSHASH_L4, + [AH_ESP_V6_FLOW] = ENETC_RSSHASH_L3, + [IPV6_FLOW] = ENETC_RSSHASH_L3, + [ETHER_FLOW] = 0, + }; + + if (rxnfc->flow_type >= ARRAY_SIZE(rsshash)) + return -EINVAL; + + rxnfc->data = rsshash[rxnfc->flow_type]; + + return 0; +} + +/* current HW spec does byte reversal on everything including MAC addresses */ +static void ether_addr_copy_swap(u8 *dst, const u8 *src) +{ + int i; + + for (i = 0; i < ETH_ALEN; i++) + dst[i] = src[ETH_ALEN - i - 1]; +} + +static int enetc_set_cls_entry(struct enetc_si *si, + struct ethtool_rx_flow_spec *fs, bool en) +{ + struct ethtool_tcpip4_spec *l4ip4_h, *l4ip4_m; + struct ethtool_usrip4_spec *l3ip4_h, *l3ip4_m; + struct ethhdr *eth_h, *eth_m; + struct enetc_cmd_rfse rfse = { {0} }; + + if (!en) + goto done; + + switch (fs->flow_type & 0xff) { + case TCP_V4_FLOW: + l4ip4_h = &fs->h_u.tcp_ip4_spec; + l4ip4_m = &fs->m_u.tcp_ip4_spec; + goto l4ip4; + case UDP_V4_FLOW: + l4ip4_h = &fs->h_u.udp_ip4_spec; + l4ip4_m = &fs->m_u.udp_ip4_spec; + goto l4ip4; + case SCTP_V4_FLOW: + l4ip4_h = &fs->h_u.sctp_ip4_spec; + l4ip4_m = &fs->m_u.sctp_ip4_spec; +l4ip4: + rfse.sip_h[0] = l4ip4_h->ip4src; + rfse.sip_m[0] = l4ip4_m->ip4src; + rfse.dip_h[0] = l4ip4_h->ip4dst; + rfse.dip_m[0] = l4ip4_m->ip4dst; + rfse.sport_h = ntohs(l4ip4_h->psrc); + rfse.sport_m = ntohs(l4ip4_m->psrc); + rfse.dport_h = ntohs(l4ip4_h->pdst); + rfse.dport_m = ntohs(l4ip4_m->pdst); + if (l4ip4_m->tos) + netdev_warn(si->ndev, "ToS field is not supported and was ignored\n"); + rfse.ethtype_h = ETH_P_IP; /* IPv4 */ + rfse.ethtype_m = 0xffff; + break; + case IP_USER_FLOW: + l3ip4_h = &fs->h_u.usr_ip4_spec; + l3ip4_m = &fs->m_u.usr_ip4_spec; + + rfse.sip_h[0] = l3ip4_h->ip4src; + rfse.sip_m[0] = l3ip4_m->ip4src; + rfse.dip_h[0] = l3ip4_h->ip4dst; + rfse.dip_m[0] = l3ip4_m->ip4dst; + if (l3ip4_m->tos) + netdev_warn(si->ndev, "ToS field is not supported and was ignored\n"); + rfse.ethtype_h = ETH_P_IP; /* IPv4 */ + rfse.ethtype_m = 0xffff; + break; + case ETHER_FLOW: + eth_h = &fs->h_u.ether_spec; + eth_m = &fs->m_u.ether_spec; + + ether_addr_copy_swap(rfse.smac_h, eth_h->h_source); + ether_addr_copy_swap(rfse.smac_m, eth_m->h_source); + ether_addr_copy_swap(rfse.dmac_h, eth_h->h_dest); + ether_addr_copy_swap(rfse.dmac_m, eth_m->h_dest); + rfse.ethtype_h = ntohs(eth_h->h_proto); + rfse.ethtype_m = ntohs(eth_m->h_proto); + break; + default: + return -EOPNOTSUPP; + } + + rfse.mode |= ENETC_RFSE_EN; + if (fs->ring_cookie != RX_CLS_FLOW_DISC) { + rfse.mode |= ENETC_RFSE_MODE_BD; + rfse.result = fs->ring_cookie; + } +done: + return enetc_set_fs_entry(si, &rfse, fs->location); +} + +static int enetc_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc, + u32 *rule_locs) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + int i, j; + + switch (rxnfc->cmd) { + case ETHTOOL_GRXRINGS: + rxnfc->data = priv->num_rx_rings; + break; + case ETHTOOL_GRXFH: + /* get RSS hash config */ + return enetc_get_rsshash(rxnfc); + case ETHTOOL_GRXCLSRLCNT: + /* total number of entries */ + rxnfc->data = priv->si->num_fs_entries; + /* number of entries in use */ + rxnfc->rule_cnt = 0; + for (i = 0; i < priv->si->num_fs_entries; i++) + if (priv->cls_rules[i].used) + rxnfc->rule_cnt++; + break; + case ETHTOOL_GRXCLSRULE: + if (rxnfc->fs.location >= priv->si->num_fs_entries) + return -EINVAL; + + /* get entry x */ + rxnfc->fs = priv->cls_rules[rxnfc->fs.location].fs; + break; + case ETHTOOL_GRXCLSRLALL: + /* total number of entries */ + rxnfc->data = priv->si->num_fs_entries; + /* array of indexes of used entries */ + j = 0; + for (i = 0; i < priv->si->num_fs_entries; i++) { + if (!priv->cls_rules[i].used) + continue; + if (j == rxnfc->rule_cnt) + return -EMSGSIZE; + rule_locs[j++] = i; + } + /* number of entries in use */ + rxnfc->rule_cnt = j; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int enetc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *rxnfc) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + int err; + + switch (rxnfc->cmd) { + case ETHTOOL_SRXCLSRLINS: + if (rxnfc->fs.location >= priv->si->num_fs_entries) + return -EINVAL; + + if (rxnfc->fs.ring_cookie >= priv->num_rx_rings && + rxnfc->fs.ring_cookie != RX_CLS_FLOW_DISC) + return -EINVAL; + + err = enetc_set_cls_entry(priv->si, &rxnfc->fs, true); + if (err) + return err; + priv->cls_rules[rxnfc->fs.location].fs = rxnfc->fs; + priv->cls_rules[rxnfc->fs.location].used = 1; + break; + case ETHTOOL_SRXCLSRLDEL: + if (rxnfc->fs.location >= priv->si->num_fs_entries) + return -EINVAL; + + err = enetc_set_cls_entry(priv->si, &rxnfc->fs, false); + if (err) + return err; + priv->cls_rules[rxnfc->fs.location].used = 0; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static u32 enetc_get_rxfh_key_size(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + /* return the size of the RX flow hash key. PF only */ + return (priv->si->hw.port) ? ENETC_RSSHASH_KEY_SIZE : 0; +} + +static u32 enetc_get_rxfh_indir_size(struct net_device *ndev) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + + /* return the size of the RX flow hash indirection table */ + return priv->si->num_rss; +} + +static int enetc_get_rxfh(struct net_device *ndev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_hw *hw = &priv->si->hw; + int err = 0, i; + + /* return hash function */ + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + + /* return hash key */ + if (key && hw->port) + for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++) + ((u32 *)key)[i] = enetc_port_rd(hw, ENETC_PRSSK(i)); + + /* return RSS table */ + if (indir) + err = enetc_get_rss_table(priv->si, indir, priv->si->num_rss); + + return err; +} + +void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes) +{ + int i; + + for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++) + enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]); +} + +static int enetc_set_rxfh(struct net_device *ndev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_hw *hw = &priv->si->hw; + int err = 0; + + /* set hash key, if PF */ + if (key && hw->port) + enetc_set_rss_key(hw, key); + + /* set RSS table */ + if (indir) + err = enetc_set_rss_table(priv->si, indir, priv->si->num_rss); + + return err; +} + static void enetc_get_ringparam(struct net_device *ndev, struct ethtool_ringparam *ring) { @@ -299,6 +561,12 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = { .get_sset_count = enetc_get_sset_count, .get_strings = enetc_get_strings, .get_ethtool_stats = enetc_get_ethtool_stats, + .get_rxnfc = enetc_get_rxnfc, + .set_rxnfc = enetc_set_rxnfc, + .get_rxfh_key_size = enetc_get_rxfh_key_size, + .get_rxfh_indir_size = enetc_get_rxfh_indir_size, + .get_rxfh = enetc_get_rxfh, + .set_rxfh = enetc_set_rxfh, .get_ringparam = enetc_get_ringparam, .get_link_ksettings = phy_ethtool_get_link_ksettings, .set_link_ksettings = phy_ethtool_set_link_ksettings, @@ -310,6 +578,11 @@ static const struct ethtool_ops enetc_vf_ethtool_ops = { .get_sset_count = enetc_get_sset_count, .get_strings = enetc_get_strings, .get_ethtool_stats = enetc_get_ethtool_stats, + .get_rxnfc = enetc_get_rxnfc, + .set_rxnfc = enetc_set_rxnfc, + .get_rxfh_indir_size = enetc_get_rxfh_indir_size, + .get_rxfh = enetc_get_rxfh, + .set_rxfh = enetc_set_rxfh, .get_ringparam = enetc_get_ringparam, }; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h index 25edb46a4451..efa0b1a5ef4f 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h @@ -13,9 +13,11 @@ /** SI regs, offset: 0h */ #define ENETC_SIMR 0 #define ENETC_SIMR_EN BIT(31) +#define ENETC_SIMR_RSSE BIT(0) #define ENETC_SICTR0 0x18 #define ENETC_SICTR1 0x1c #define ENETC_SIPCAPR0 0x20 +#define ENETC_SIPCAPR0_RSS BIT(8) #define ENETC_SIPCAPR1 0x24 #define ENETC_SITGTGR 0x30 #define ENETC_SIRBGCR 0x38 @@ -92,6 +94,11 @@ static inline u32 enetc_vsi_set_msize(u32 size) #define ENETC_SIUEFDCR 0xe28 +#define ENETC_SIRFSCAPR 0x1200 +#define ENETC_SIRFSCAPR_GET_NUM_RFS(val) ((val) & 0x7f) +#define ENETC_SIRSSCAPR 0x1600 +#define ENETC_SIRSSCAPR_GET_NUM_RSS(val) (BIT((val) & 0xf) * 32) + /** SI BDR sub-blocks, n = 0..7 */ enum enetc_bdr_type {TX, RX}; #define ENETC_BDR_OFF(i) ((i) * 0x200) @@ -172,8 +179,15 @@ enum enetc_bdr_type {TX, RX}; #define ENETC_PTCCBSR0(n) (0x1110 + (n) * 8) /* n = 0 to 7*/ #define ENETC_PTCCBSR1(n) (0x1114 + (n) * 8) /* n = 0 to 7*/ +#define ENETC_RSSHASH_KEY_SIZE 40 +#define ENETC_PRSSK(n) (0x1410 + (n) * 4) /* n = [0..9] */ #define ENETC_PSIVLANFMR 0x1700 #define ENETC_PSIVLANFMR_VS BIT(0) +#define ENETC_PRFSMR 0x1800 +#define ENETC_PRFSMR_RFSE BIT(31) +#define ENETC_PRFSCAPR 0x1804 +#define ENETC_PRFSCAPR_GET_NUM_RFS(val) ((((val) & 0xf) + 1) * 16) +#define ENETC_PSIRFSCFGR(n) (0x1814 + (n) * 4) /* n = SI index */ #define ENETC_PFPMR 0x1900 #define ENETC_PFPMR_PMACE BIT(1) #define ENETC_PFPMR_MWLM BIT(0) @@ -431,6 +445,35 @@ struct enetc_cbd { #define ENETC_CBD_FLAGS_SF BIT(7) /* short format */ #define ENETC_CBD_STATUS_MASK 0xf +struct enetc_cmd_rfse { + u8 smac_h[6]; + u8 smac_m[6]; + u8 dmac_h[6]; + u8 dmac_m[6]; + u32 sip_h[4]; + u32 sip_m[4]; + u32 dip_h[4]; + u32 dip_m[4]; + u16 ethtype_h; + u16 ethtype_m; + u16 ethtype4_h; + u16 ethtype4_m; + u16 sport_h; + u16 sport_m; + u16 dport_h; + u16 dport_m; + u16 vlan_h; + u16 vlan_m; + u8 proto_h; + u8 proto_m; + u16 flags; + u16 result; + u16 mode; +}; + +#define ENETC_RFSE_EN BIT(15) +#define ENETC_RFSE_MODE_BD 2 + static inline void enetc_get_primary_mac_addr(struct enetc_hw *hw, u8 *addr) { *(u32 *)addr = __raw_readl(hw->reg + ENETC_SIPMAR0); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 35cad5df71ef..7d28f5e9b46b 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -435,6 +435,27 @@ static void enetc_port_setup_primary_mac_address(struct enetc_si *si) } } +static void enetc_port_assign_rfs_entries(struct enetc_si *si) +{ + struct enetc_pf *pf = enetc_si_priv(si); + struct enetc_hw *hw = &si->hw; + int num_entries, vf_entries, i; + u32 val; + + /* split RFS entries between functions */ + val = enetc_port_rd(hw, ENETC_PRFSCAPR); + num_entries = ENETC_PRFSCAPR_GET_NUM_RFS(val); + vf_entries = num_entries / (pf->total_vfs + 1); + + for (i = 0; i < pf->total_vfs; i++) + enetc_port_wr(hw, ENETC_PSIRFSCFGR(i + 1), vf_entries); + enetc_port_wr(hw, ENETC_PSIRFSCFGR(0), + num_entries - vf_entries * pf->total_vfs); + + /* enable RFS on port */ + enetc_port_wr(hw, ENETC_PRFSMR, ENETC_PRFSMR_RFSE); +} + static void enetc_port_si_configure(struct enetc_si *si) { struct enetc_pf *pf = enetc_si_priv(si); @@ -523,6 +544,7 @@ static void enetc_configure_port_pmac(struct enetc_hw *hw) static void enetc_configure_port(struct enetc_pf *pf) { + u8 hash_key[ENETC_RSSHASH_KEY_SIZE]; struct enetc_hw *hw = &pf->si->hw; enetc_configure_port_pmac(hw); @@ -531,6 +553,13 @@ static void enetc_configure_port(struct enetc_pf *pf) enetc_port_si_configure(pf->si); + /* set up hash key */ + get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE); + enetc_set_rss_key(hw, hash_key); + + /* split up RFS entries */ + enetc_port_assign_rfs_entries(pf->si); + /* fix-up primary MAC addresses, if not set already */ enetc_port_setup_primary_mac_address(pf->si); @@ -657,7 +686,7 @@ static int enetc_pf_set_features(struct net_device *ndev, if (changed & NETIF_F_LOOPBACK) enetc_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK)); - return 0; + return enetc_set_features(ndev, features); } static const struct net_device_ops enetc_ndev_ops = { @@ -701,6 +730,9 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; + if (si->num_rss) + ndev->hw_features |= NETIF_F_RXHASH; + if (si->errata & ENETC_ERR_TXCSUM) { ndev->hw_features &= ~NETIF_F_HW_CSUM; ndev->features &= ~NETIF_F_HW_CSUM; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c index e8695a99aec3..64bebee9f52a 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c @@ -97,6 +97,12 @@ static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr) return 0; } +static int enetc_vf_set_features(struct net_device *ndev, + netdev_features_t features) +{ + return enetc_set_features(ndev, features); +} + /* Probing/ Init */ static const struct net_device_ops enetc_ndev_ops = { .ndo_open = enetc_open, @@ -104,6 +110,7 @@ static const struct net_device_ops enetc_ndev_ops = { .ndo_start_xmit = enetc_xmit, .ndo_get_stats = enetc_get_stats, .ndo_set_mac_address = enetc_vf_set_mac_addr, + .ndo_set_features = enetc_vf_set_features, }; static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev, @@ -131,6 +138,9 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev, NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; + if (si->num_rss) + ndev->hw_features |= NETIF_F_RXHASH; + if (si->errata & ENETC_ERR_TXCSUM) { ndev->hw_features &= ~NETIF_F_HW_CSUM; ndev->features &= ~NETIF_F_HW_CSUM; -- cgit v1.2.3 From 843ef94e3374b8c2afdff3a68270d4b09964e165 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 22 Jan 2019 14:37:55 +0000 Subject: net: amd8111e: clean up two minor indentation issues Two statements are incorrecly indented, fix these by removing a space. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/amd8111e.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index a90080f12e67..b9632928496e 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -435,7 +435,7 @@ static int amd8111e_restart(struct net_device *dev) int i,reg_val; /* stop the chip */ - writel(RUN, mmio + CMD0); + writel(RUN, mmio + CMD0); if(amd8111e_init_ring(dev)) return -ENOMEM; @@ -1720,7 +1720,7 @@ static void amd8111e_config_ipg(struct timer_list *t) writew((u32)tmp_ipg, mmio + IPG); writew((u32)(tmp_ipg - IFS1_DELTA), mmio + IFS1); } - mod_timer(&lp->ipg_data.ipg_timer, jiffies + IPG_CONVERGE_JIFFIES); + mod_timer(&lp->ipg_data.ipg_timer, jiffies + IPG_CONVERGE_JIFFIES); return; } -- cgit v1.2.3 From 8f4ebaaa8d97dc531a3f947a8d30a5a70fe38743 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 23 Jan 2019 06:19:18 +0000 Subject: net: stmmac: Fix return value check in qcom_ethqos_probe() In case of error, the function devm_clk_get() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Fixes: a7c30e62d4b8 ("net: stmmac: Add driver for Qualcomm ethqos") Signed-off-by: Wei Yongjun Acked-by: Vinod Koul Acked-by: Niklas Cassel Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 30724bd330f4..7ec895407d23 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -473,8 +473,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->por = of_device_get_match_data(&pdev->dev); ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii"); - if (!ethqos->rgmii_clk) { - ret = -ENOMEM; + if (IS_ERR(ethqos->rgmii_clk)) { + ret = PTR_ERR(ethqos->rgmii_clk); goto err_mem; } -- cgit v1.2.3 From a016becd3a56cdb260013c8fe1d4aefc6edc4989 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 23 Jan 2019 07:27:21 +0100 Subject: net: phy: start state machine in phy_start only The state machine is a no-op before phy_start() has been called. Therefore let's enable it in phy_start() only. In phy_start() let's call phy_start_machine() instead of phy_trigger_machine(). phy_start_machine is an alias for phy_trigger_machine but it makes clearer that we start the state machine here instead of just triggering a run. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 2 +- drivers/net/phy/phy_device.c | 1 - drivers/net/phy/phylink.c | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 631ed33fe9d9..a7fca15888b6 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -878,7 +878,7 @@ void phy_start(struct phy_device *phydev) } mutex_unlock(&phydev->lock); - phy_trigger_machine(phydev); + phy_start_machine(phydev); } EXPORT_SYMBOL(phy_start); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 509d9402fa9a..64c25a0684ac 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -951,7 +951,6 @@ int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, return rc; phy_prepare_link(phydev, handler); - phy_start_machine(phydev); if (phydev->irq > 0) phy_start_interrupts(phydev); diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 7d9910da5018..c1b6e05ba60c 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -676,7 +676,6 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) __ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported, __ETHTOOL_LINK_MODE_MASK_NBITS, phy->advertising); - phy_start_machine(phy); if (phy->irq > 0) phy_start_interrupts(phy); -- cgit v1.2.3 From 217962615662f1ab7a60978a194444023039f0a4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 23 Jan 2019 07:30:38 +0100 Subject: net: phy: warn if phy_start is called from invalid state phy_start() should be called from states PHY_READY or PHY_HALTED only. Check for this to detect misbehaving drivers. Also the state machine should be started only when being called from one of the valid states. Some more background: For all invalid states phy_start() basically was a no-op. All it did was triggering a state machine run, but for all "running" states the poll loop was active anyway. And if called from PHY_DOWN, the state machine does nothing. v3: - extended commit message Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index a7fca15888b6..dedd57b86c80 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -856,9 +856,16 @@ void phy_start(struct phy_device *phydev) mutex_lock(&phydev->lock); + if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) { + WARN(1, "called from state %s\n", + phy_state_to_str(phydev->state)); + goto out; + } + switch (phydev->state) { case PHY_READY: phydev->state = PHY_UP; + phy_start_machine(phydev); break; case PHY_HALTED: /* if phy was suspended, bring the physical link up again */ @@ -872,13 +879,13 @@ void phy_start(struct phy_device *phydev) } phydev->state = PHY_RESUMING; + phy_start_machine(phydev); break; default: break; } +out: mutex_unlock(&phydev->lock); - - phy_start_machine(phydev); } EXPORT_SYMBOL(phy_start); -- cgit v1.2.3 From 9e573cfc35c6ffac45e385ed4f14f5187c09090a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 23 Jan 2019 07:31:23 +0100 Subject: net: phy: start interrupts in phy_start Interrupts don't have to be enabled before calling phy_start(). Therefore let's enable them in phy_start(). In a subsequent step we'll remove enabling interrupts from phy_connect_direct(). Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index dedd57b86c80..079b6a617fc8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -852,7 +852,7 @@ EXPORT_SYMBOL(phy_stop); */ void phy_start(struct phy_device *phydev) { - int err = 0; + int err; mutex_lock(&phydev->lock); @@ -862,28 +862,22 @@ void phy_start(struct phy_device *phydev) goto out; } - switch (phydev->state) { - case PHY_READY: - phydev->state = PHY_UP; - phy_start_machine(phydev); - break; - case PHY_HALTED: - /* if phy was suspended, bring the physical link up again */ - __phy_resume(phydev); + /* if phy was suspended, bring the physical link up again */ + __phy_resume(phydev); - /* make sure interrupts are re-enabled for the PHY */ - if (phy_interrupt_is_valid(phydev)) { - err = phy_enable_interrupts(phydev); - if (err < 0) - break; - } + /* make sure interrupts are enabled for the PHY */ + if (phy_interrupt_is_valid(phydev)) { + err = phy_enable_interrupts(phydev); + if (err < 0) + goto out; + } + if (phydev->state == PHY_READY) + phydev->state = PHY_UP; + else phydev->state = PHY_RESUMING; - phy_start_machine(phydev); - break; - default: - break; - } + + phy_start_machine(phydev); out: mutex_unlock(&phydev->lock); } -- cgit v1.2.3 From 434a4315b9617bf1742bc64712bf44a208502f7f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 23 Jan 2019 07:31:58 +0100 Subject: net: phy: change phy_start_interrupts to phy_request_interrupt Now that we enable the interrupts in phy_start() we don't have to do it before. Therefore remove enabling interrupts from phy_start_interrupts() and rename this function to reflect the changed functionality. v2: - improve warning to clearly state that we fall back to polling Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 23 +++++++++++------------ drivers/net/phy/phy_device.c | 4 ++-- drivers/net/phy/phylink.c | 4 ++-- include/linux/phy.h | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 079b6a617fc8..d12aa512b7f5 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -785,28 +785,27 @@ static int phy_enable_interrupts(struct phy_device *phydev) } /** - * phy_start_interrupts - request and enable interrupts for a PHY device + * phy_request_interrupt - request interrupt for a PHY device * @phydev: target phy_device struct * * Description: Request the interrupt for the given PHY. * If this fails, then we set irq to PHY_POLL. - * Otherwise, we enable the interrupts in the PHY. * This should only be called with a valid IRQ number. - * Returns 0 on success or < 0 on error. */ -int phy_start_interrupts(struct phy_device *phydev) +void phy_request_interrupt(struct phy_device *phydev) { - if (request_threaded_irq(phydev->irq, NULL, phy_interrupt, - IRQF_ONESHOT | IRQF_SHARED, - phydev_name(phydev), phydev) < 0) { - phydev_warn(phydev, "Can't get IRQ %d\n", phydev->irq); + int err; + + err = request_threaded_irq(phydev->irq, NULL, phy_interrupt, + IRQF_ONESHOT | IRQF_SHARED, + phydev_name(phydev), phydev); + if (err) { + phydev_warn(phydev, "Error %d requesting IRQ %d, falling back to polling\n", + err, phydev->irq); phydev->irq = PHY_POLL; - return 0; } - - return phy_enable_interrupts(phydev); } -EXPORT_SYMBOL(phy_start_interrupts); +EXPORT_SYMBOL(phy_request_interrupt); /** * phy_stop - Bring down the PHY link, and stop checking the status diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 64c25a0684ac..891e0178b97f 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -951,8 +951,8 @@ int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, return rc; phy_prepare_link(phydev, handler); - if (phydev->irq > 0) - phy_start_interrupts(phydev); + if (phy_interrupt_is_valid(phydev)) + phy_request_interrupt(phydev); return 0; } diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index c1b6e05ba60c..2e21ce42e388 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -676,8 +676,8 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) __ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported, __ETHTOOL_LINK_MODE_MASK_NBITS, phy->advertising); - if (phy->irq > 0) - phy_start_interrupts(phy); + if (phy_interrupt_is_valid(phy)) + phy_request_interrupt(phy); return 0; } diff --git a/include/linux/phy.h b/include/linux/phy.h index 1f3873a2ff29..70f83d0d7469 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1047,7 +1047,7 @@ void phy_ethtool_ksettings_get(struct phy_device *phydev, int phy_ethtool_ksettings_set(struct phy_device *phydev, const struct ethtool_link_ksettings *cmd); int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd); -int phy_start_interrupts(struct phy_device *phydev); +void phy_request_interrupt(struct phy_device *phydev); void phy_print_status(struct phy_device *phydev); int phy_set_max_speed(struct phy_device *phydev, u32 max_speed); void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode); -- cgit v1.2.3 From 949e7cea0cbccd7e2afc4b374e2be998b8fcef78 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 23 Jan 2019 19:14:50 +0200 Subject: bonding: count master 3ad stats separately I made a dumb mistake when I summed up the slave stats, obviously slaves can come and go which would make the master stats unreliable. Count and export the master stats separately. Fixes: a258aeacd7f0 ("bonding: add support for xstats and export 3ad stats") Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 39 +++++++++++++------------------------- drivers/net/bonding/bond_netlink.c | 18 +++++++----------- include/net/bond_3ad.h | 2 +- 3 files changed, 21 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index d30c21b34858..9274dcc6e9b0 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -853,6 +853,7 @@ static int ad_lacpdu_send(struct port *port) return -ENOMEM; atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_tx); + atomic64_inc(&BOND_AD_INFO(slave->bond).stats.lacpdu_tx); skb->dev = slave->dev; skb_reset_mac_header(skb); @@ -898,9 +899,11 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker) switch (marker->tlv_type) { case AD_MARKER_INFORMATION_SUBTYPE: atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_tx); + atomic64_inc(&BOND_AD_INFO(slave->bond).stats.marker_tx); break; case AD_MARKER_RESPONSE_SUBTYPE: atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_resp_tx); + atomic64_inc(&BOND_AD_INFO(slave->bond).stats.marker_resp_tx); break; } @@ -1098,9 +1101,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) */ last_state = port->sm_rx_state; - if (lacpdu) + if (lacpdu) { atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.lacpdu_rx); - + atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.lacpdu_rx); + } /* check if state machine should change state */ /* first, check if port was reinitialized */ @@ -1938,6 +1942,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info, struct bond_marker marker; atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_rx); + atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.marker_rx); /* copy the received marker data to the response marker */ memcpy(&marker, marker_info, sizeof(struct bond_marker)); @@ -1964,6 +1969,7 @@ static void ad_marker_response_received(struct bond_marker *marker, struct port *port) { atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_resp_rx); + atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.marker_resp_rx); /* DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW */ } @@ -2374,6 +2380,7 @@ re_arm: */ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave) { + struct bonding *bond = slave->bond; int ret = RX_HANDLER_ANOTHER; struct bond_marker *marker; struct port *port; @@ -2419,10 +2426,13 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave) port->actor_port_number); stat = &SLAVE_AD_INFO(slave)->stats.marker_unknown_rx; atomic64_inc(stat); + stat = &BOND_AD_INFO(bond).stats.marker_unknown_rx; + atomic64_inc(stat); } break; default: atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_unknown_rx); + atomic64_inc(&BOND_AD_INFO(bond).stats.lacpdu_unknown_rx); } return ret; @@ -2662,6 +2672,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu); if (!lacpdu) { atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_illegal_rx); + atomic64_inc(&BOND_AD_INFO(bond).stats.lacpdu_illegal_rx); return RX_HANDLER_ANOTHER; } @@ -2698,30 +2709,6 @@ void bond_3ad_update_lacp_rate(struct bonding *bond) spin_unlock_bh(&bond->mode_lock); } -void bond_3ad_stats_add(struct slave *slave, struct bond_3ad_stats *stats) -{ - struct bond_3ad_stats *rstats = &SLAVE_AD_INFO(slave)->stats; - u64 stat; - - atomic64_add(atomic64_read(&rstats->lacpdu_rx), &stats->lacpdu_rx); - atomic64_add(atomic64_read(&rstats->lacpdu_tx), &stats->lacpdu_tx); - - stat = atomic64_read(&rstats->lacpdu_unknown_rx); - atomic64_add(stat, &stats->lacpdu_unknown_rx); - stat = atomic64_read(&rstats->lacpdu_illegal_rx); - atomic64_add(stat, &stats->lacpdu_illegal_rx); - - atomic64_add(atomic64_read(&rstats->marker_rx), &stats->marker_rx); - atomic64_add(atomic64_read(&rstats->marker_tx), &stats->marker_tx); - - stat = atomic64_read(&rstats->marker_resp_rx); - atomic64_add(stat, &stats->marker_resp_rx); - stat = atomic64_read(&rstats->marker_resp_tx); - atomic64_add(stat, &stats->marker_resp_tx); - stat = atomic64_read(&rstats->marker_unknown_rx); - atomic64_add(stat, &stats->marker_unknown_rx); -} - size_t bond_3ad_stats_size(void) { return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */ diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index d1338fbe1830..b286f591242e 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -715,16 +715,12 @@ static int bond_fill_linkxstats(struct sk_buff *skb, if (!nest) return -EMSGSIZE; if (BOND_MODE(bond) == BOND_MODE_8023AD) { - struct bond_3ad_stats stats; - struct list_head *iter; - - memset(&stats, 0, sizeof(stats)); - if (slave) { - bond_3ad_stats_add(slave, &stats); - } else { - bond_for_each_slave(bond, slave, iter) - bond_3ad_stats_add(slave, &stats); - } + struct bond_3ad_stats *stats; + + if (slave) + stats = &SLAVE_AD_INFO(slave)->stats; + else + stats = &BOND_AD_INFO(bond).stats; nest2 = nla_nest_start(skb, BOND_XSTATS_3AD); if (!nest2) { @@ -732,7 +728,7 @@ static int bond_fill_linkxstats(struct sk_buff *skb, return -EMSGSIZE; } - if (bond_3ad_stats_fill(skb, &stats)) { + if (bond_3ad_stats_fill(skb, stats)) { nla_nest_cancel(skb, nest2); nla_nest_end(skb, nest); return -EMSGSIZE; diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h index 25aaf49d19be..c781e1afd683 100644 --- a/include/net/bond_3ad.h +++ b/include/net/bond_3ad.h @@ -278,6 +278,7 @@ struct ad_system { struct ad_bond_info { struct ad_system system; /* 802.3ad system structure */ + struct bond_3ad_stats stats; u32 agg_select_timer; /* Timer to select aggregator after all adapter's hand shakes */ u16 aggregator_identifier; }; @@ -321,7 +322,6 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, int bond_3ad_set_carrier(struct bonding *bond); void bond_3ad_update_lacp_rate(struct bonding *bond); void bond_3ad_update_ad_actor_settings(struct bonding *bond); -void bond_3ad_stats_add(struct slave *slave, struct bond_3ad_stats *stats); int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats); size_t bond_3ad_stats_size(void); #endif /* _NET_BOND_3AD_H */ -- cgit v1.2.3 From c46863ab8356f0eb4a27dd65a2dc368e41198ad3 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 23 Jan 2019 20:39:09 +0100 Subject: r8169: factor out disabling ALDPS Chip versions from RTL8168g onward use the same sequence to disable ALDPS (Advanced Link-Down Power Saving). So let's factor this out. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index f574b6b557f9..74d093cfeabb 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3366,6 +3366,12 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); } +static void rtl8168g_disable_aldps(struct rtl8169_private *tp) +{ + phy_write(tp->phydev, 0x1f, 0x0a43); + phy_clear_bits(tp->phydev, 0x10, BIT(2)); +} + static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) { rtl_apply_firmware(tp); @@ -3424,10 +3430,7 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x14, 0x9065); rtl_writephy(tp, 0x14, 0x1065); - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); + rtl8168g_disable_aldps(tp); rtl_writephy(tp, 0x1f, 0x0000); } @@ -3539,10 +3542,7 @@ static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp) rtl_w0w1_phy(tp, 0x11, 0x0000, 0x0080); rtl_writephy(tp, 0x1f, 0x0000); - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); + rtl8168g_disable_aldps(tp); rtl_writephy(tp, 0x1f, 0x0000); } @@ -3612,10 +3612,7 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp) rtl_w0w1_phy(tp, 0x11, 0x0000, 0x0080); rtl_writephy(tp, 0x1f, 0x0000); - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); + rtl8168g_disable_aldps(tp); rtl_writephy(tp, 0x1f, 0x0000); } @@ -3654,10 +3651,7 @@ static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp) rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000); rtl_writephy(tp, 0x1f, 0x0000); - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); + rtl8168g_disable_aldps(tp); rtl_writephy(tp, 0x1f, 0x0000); } @@ -3745,10 +3739,7 @@ static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x14, 0x1065); rtl_writephy(tp, 0x1f, 0x0000); - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); + rtl8168g_disable_aldps(tp); rtl_writephy(tp, 0x1f, 0x0000); } -- cgit v1.2.3 From a1ead2ec3c098d2f94b8de8bb3f1929d27e9e7d5 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 23 Jan 2019 20:47:30 +0100 Subject: r8169: factor out PHY init sequence adjusting 10M and ALDPS Few chip versions use the same sequence to adjust 10M and ALDPS, so let's factor it out. This patch also fixes a (most likely) typo in rtl8168g_1_hw_phy_config. There bit 8 in reg 0x14 on page 0x0bcc was set and not cleared. According to the vendor driver this bit needs to be cleared in all cases. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 49 ++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 74d093cfeabb..83c4663e6cd3 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3372,6 +3372,24 @@ static void rtl8168g_disable_aldps(struct rtl8169_private *tp) phy_clear_bits(tp->phydev, 0x10, BIT(2)); } +static void rtl8168g_phy_adjust_10m_aldps(struct rtl8169_private *tp) +{ + struct phy_device *phydev = tp->phydev; + + phy_write(phydev, 0x1f, 0x0bcc); + phy_clear_bits(phydev, 0x14, BIT(8)); + + phy_write(phydev, 0x1f, 0x0a44); + phy_set_bits(phydev, 0x11, BIT(7) | BIT(6)); + + phy_write(phydev, 0x1f, 0x0a43); + phy_write(phydev, 0x13, 0x8084); + phy_clear_bits(phydev, 0x14, BIT(14) | BIT(13)); + phy_set_bits(phydev, 0x10, BIT(12) | BIT(1) | BIT(0)); + + phy_write(phydev, 0x1f, 0x0000); +} + static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) { rtl_apply_firmware(tp); @@ -3398,14 +3416,7 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0a44); rtl_w0w1_phy(tp, 0x11, 0x000c, 0x0000); - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w0w1_phy(tp, 0x14, 0x0100, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8084); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000); - rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000); + rtl8168g_phy_adjust_10m_aldps(tp); /* EEE auto-fallback function */ rtl_writephy(tp, 0x1f, 0x0a4b); @@ -3624,16 +3635,7 @@ static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp) rtl_w0w1_phy(tp, 0x11, 0x000c, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); - /* patch 10M & ALDPS */ - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8084); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000); - rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); + rtl8168g_phy_adjust_10m_aldps(tp); /* Enable EEE auto-fallback function */ rtl_writephy(tp, 0x1f, 0x0a4b); @@ -3658,16 +3660,7 @@ static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp) static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp) { - /* patch 10M & ALDPS */ - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8084); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000); - rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); + rtl8168g_phy_adjust_10m_aldps(tp); /* Enable UC LPF tune function */ rtl_writephy(tp, 0x1f, 0x0a43); -- cgit v1.2.3 From 2bb3e10394834f81e89df63d870274ad56d6dbe3 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Thu, 24 Jan 2019 07:33:05 +0000 Subject: mlxfw: Replace license text with SPDX identifiers and adjust copyrights Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxfw/mlxfw.h | 35 ++------------------- drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c | 35 ++------------------- drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c | 35 ++------------------- drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h | 35 ++------------------- .../net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h | 35 ++------------------- .../ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h | 36 ++-------------------- .../net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h | 35 ++------------------- .../ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c | 35 ++------------------- .../ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h | 36 ++-------------------- 9 files changed, 20 insertions(+), 297 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h index 7a712b6b09ec..14c0c62f8e73 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw.h @@ -1,36 +1,5 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw.h - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ #ifndef _MLXFW_H #define _MLXFW_H diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c index 2cf89126fb23..240c027e5f07 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c @@ -1,36 +1,5 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw.c - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ #define pr_fmt(fmt) "mlxfw: " fmt diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c index 993cb5ba934e..544344ac4894 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c @@ -1,36 +1,5 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ #define pr_fmt(fmt) "mlxfw_mfa2: " fmt diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h index 20472aa139cd..5bba6ad79d34 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h @@ -1,36 +1,5 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.h - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ #ifndef _MLXFW_MFA2_H #define _MLXFW_MFA2_H diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h index f667942b1ea3..874c0a2474ae 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h @@ -1,36 +1,5 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_file.h - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ #ifndef _MLXFW_MFA2_FILE_H #define _MLXFW_MFA2_FILE_H diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h index dd66737c033d..b001e5258091 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h @@ -1,36 +1,6 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_format.h - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ + #ifndef _MLXFW_MFA2_FORMAT_H #define _MLXFW_MFA2_FORMAT_H diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h index cc013e77b326..33c971190bba 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h @@ -1,36 +1,5 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv.h - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ #ifndef _MLXFW_MFA2_TLV_H #define _MLXFW_MFA2_TLV_H diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c index 0094b92a233b..017d68f1e123 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c @@ -1,36 +1,5 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ #define pr_fmt(fmt) "MFA2: " fmt diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h index 2c667894f3a2..633284eeded7 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h @@ -1,36 +1,6 @@ -/* - * drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.h - * Copyright (c) 2017 Mellanox Technologies. All rights reserved. - * Copyright (c) 2017 Yotam Gigi - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ +/* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */ + #ifndef _MLXFW_MFA2_TLV_MULTI_H #define _MLXFW_MFA2_TLV_MULTI_H -- cgit v1.2.3 From bcfcd409d4dbb886d78c61423ce3034c94324c32 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Jan 2019 15:28:11 -0800 Subject: usb: split code locating ACPI companion into port and device In preparation for handling embedded USB devices let's split usb_acpi_find_companion() into usb_acpi_find_companion_for_device() and usb_acpi_find_companion_for_port(). Signed-off-by: Dmitry Torokhov Signed-off-by: Rajat Jain Acked-by: Greg Kroah-Hartman Tested-by: Sukumar Ghorai Signed-off-by: Marcel Holtmann --- drivers/usb/core/usb-acpi.c | 133 ++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index e221861b3187..8ff73c83e8e8 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -139,12 +139,79 @@ static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent, return acpi_find_child_device(parent, raw, false); } -static struct acpi_device *usb_acpi_find_companion(struct device *dev) +static struct acpi_device * +usb_acpi_get_companion_for_port(struct usb_port *port_dev) { struct usb_device *udev; struct acpi_device *adev; acpi_handle *parent_handle; + int port1; + + /* Get the struct usb_device point of port's hub */ + udev = to_usb_device(port_dev->dev.parent->parent); + + /* + * The root hub ports' parent is the root hub. The non-root-hub + * ports' parent is the parent hub port which the hub is + * connected to. + */ + if (!udev->parent) { + adev = ACPI_COMPANION(&udev->dev); + port1 = usb_hcd_find_raw_port_number(bus_to_hcd(udev->bus), + port_dev->portnum); + } else { + parent_handle = usb_get_hub_port_acpi_handle(udev->parent, + udev->portnum); + if (!parent_handle) + return NULL; + + acpi_bus_get_device(parent_handle, &adev); + port1 = port_dev->portnum; + } + + return usb_acpi_find_port(adev, port1); +} + +static struct acpi_device * +usb_acpi_find_companion_for_port(struct usb_port *port_dev) +{ + struct acpi_device *adev; + struct acpi_pld_info *pld; + acpi_handle *handle; + acpi_status status; + + adev = usb_acpi_get_companion_for_port(port_dev); + if (!adev) + return NULL; + + handle = adev->handle; + status = acpi_get_physical_device_location(handle, &pld); + if (!ACPI_FAILURE(status) && pld) { + port_dev->location = USB_ACPI_LOCATION_VALID + | pld->group_token << 8 | pld->group_position; + port_dev->connect_type = usb_acpi_get_connect_type(handle, pld); + ACPI_FREE(pld); + } + return adev; +} + +static struct acpi_device * +usb_acpi_find_companion_for_device(struct usb_device *udev) +{ + struct acpi_device *adev; + + if (!udev->parent) + return NULL; + + /* root hub is only child (_ADR=0) under its parent, the HC */ + adev = ACPI_COMPANION(udev->dev.parent); + return acpi_find_child_device(adev, 0, false); +} + + +static struct acpi_device *usb_acpi_find_companion(struct device *dev) +{ /* * In the ACPI DSDT table, only usb root hub and usb ports are * acpi device nodes. The hierarchy like following. @@ -158,66 +225,10 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev) * So all binding process is divided into two parts. binding * root hub and usb ports. */ - if (is_usb_device(dev)) { - udev = to_usb_device(dev); - if (udev->parent) - return NULL; - - /* root hub is only child (_ADR=0) under its parent, the HC */ - adev = ACPI_COMPANION(dev->parent); - return acpi_find_child_device(adev, 0, false); - } else if (is_usb_port(dev)) { - struct usb_port *port_dev = to_usb_port(dev); - int port1 = port_dev->portnum; - struct acpi_pld_info *pld; - acpi_handle *handle; - acpi_status status; - - /* Get the struct usb_device point of port's hub */ - udev = to_usb_device(dev->parent->parent); - - /* - * The root hub ports' parent is the root hub. The non-root-hub - * ports' parent is the parent hub port which the hub is - * connected to. - */ - if (!udev->parent) { - struct usb_hcd *hcd = bus_to_hcd(udev->bus); - int raw; - - raw = usb_hcd_find_raw_port_number(hcd, port1); - - adev = usb_acpi_find_port(ACPI_COMPANION(&udev->dev), - raw); - - if (!adev) - return NULL; - } else { - parent_handle = - usb_get_hub_port_acpi_handle(udev->parent, - udev->portnum); - if (!parent_handle) - return NULL; - - acpi_bus_get_device(parent_handle, &adev); - - adev = usb_acpi_find_port(adev, port1); - - if (!adev) - return NULL; - } - handle = adev->handle; - status = acpi_get_physical_device_location(handle, &pld); - if (ACPI_FAILURE(status) || !pld) - return adev; - - port_dev->location = USB_ACPI_LOCATION_VALID - | pld->group_token << 8 | pld->group_position; - port_dev->connect_type = usb_acpi_get_connect_type(handle, pld); - ACPI_FREE(pld); - - return adev; - } + if (is_usb_device(dev)) + return usb_acpi_find_companion_for_device(to_usb_device(dev)); + else if (is_usb_port(dev)) + return usb_acpi_find_companion_for_port(to_usb_port(dev)); return NULL; } -- cgit v1.2.3 From b4dfbbd1803d81b51bf2c47b182a7029b476d8e2 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Jan 2019 15:28:12 -0800 Subject: usb: assign ACPI companions for embedded USB devices USB devices permanently connected to USB ports may be described in ACPI tables and share ACPI devices with ports they are connected to. See [1] for details. This will allow us to describe sideband resources for devices, such as, for example, hard reset line for BT USB controllers. [1] https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/other-acpi-namespace-objects#acpi-namespace-hierarchy-and-adr-for-embedded-usb-devices Signed-off-by: Dmitry Torokhov Signed-off-by: Rajat Jain (changed how we get the usb_port) Acked-by: Greg Kroah-Hartman Tested-by: Sukumar Ghorai Signed-off-by: Marcel Holtmann --- drivers/usb/core/usb-acpi.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 8ff73c83e8e8..9043d7242d67 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -200,30 +200,56 @@ static struct acpi_device * usb_acpi_find_companion_for_device(struct usb_device *udev) { struct acpi_device *adev; + struct usb_port *port_dev; + struct usb_hub *hub; + + if (!udev->parent) { + /* root hub is only child (_ADR=0) under its parent, the HC */ + adev = ACPI_COMPANION(udev->dev.parent); + return acpi_find_child_device(adev, 0, false); + } - if (!udev->parent) + hub = usb_hub_to_struct_hub(udev->parent); + if (!hub) return NULL; - /* root hub is only child (_ADR=0) under its parent, the HC */ - adev = ACPI_COMPANION(udev->dev.parent); - return acpi_find_child_device(adev, 0, false); + /* + * This is an embedded USB device connected to a port and such + * devices share port's ACPI companion. + */ + port_dev = hub->ports[udev->portnum - 1]; + return usb_acpi_get_companion_for_port(port_dev); } - static struct acpi_device *usb_acpi_find_companion(struct device *dev) { /* - * In the ACPI DSDT table, only usb root hub and usb ports are - * acpi device nodes. The hierarchy like following. + * The USB hierarchy like following: + * * Device (EHC1) * Device (HUBN) * Device (PR01) * Device (PR11) * Device (PR12) + * Device (FN12) + * Device (FN13) * Device (PR13) * ... - * So all binding process is divided into two parts. binding - * root hub and usb ports. + * where HUBN is root hub, and PRNN are USB ports and devices + * connected to them, and FNNN are individualk functions for + * connected composite USB devices. PRNN and FNNN may contain + * _CRS and other methods describing sideband resources for + * the connected device. + * + * On the kernel side both root hub and embedded USB devices are + * represented as instances of usb_device structure, and ports + * are represented as usb_port structures, so the whole process + * is split into 2 parts: finding companions for devices and + * finding companions for ports. + * + * Note that we do not handle individual functions of composite + * devices yet, for that we would need to assign companions to + * devices corresponding to USB interfaces. */ if (is_usb_device(dev)) return usb_acpi_find_companion_for_device(to_usb_device(dev)); -- cgit v1.2.3 From dc786b2c2c1bc0730ab88e403c33de0989da7f48 Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Thu, 24 Jan 2019 15:28:14 -0800 Subject: Bluetooth: btusb: Use the cmd_timeout method to reset the Intel BT chip If the platform provides it, use the reset gpio to reset the Intel BT chip, as part of cmd_timeout handling. This has been found helpful on Intel bluetooth controllers where the firmware gets stuck and the only way out is a hard reset pin provided by the platform. Signed-off-by: Rajat Jain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4761499db9ee..5de0c2e59b97 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -439,6 +440,7 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = { #define BTUSB_BOOTING 9 #define BTUSB_DIAG_RUNNING 10 #define BTUSB_OOB_WAKE_ENABLED 11 +#define BTUSB_HW_RESET_ACTIVE 12 struct btusb_data { struct hci_dev *hdev; @@ -476,6 +478,8 @@ struct btusb_data { struct usb_endpoint_descriptor *diag_tx_ep; struct usb_endpoint_descriptor *diag_rx_ep; + struct gpio_desc *reset_gpio; + __u8 cmdreq_type; __u8 cmdreq; @@ -489,8 +493,41 @@ struct btusb_data { int (*setup_on_usb)(struct hci_dev *hdev); int oob_wake_irq; /* irq for out-of-band wake-on-bt */ + unsigned cmd_timeout_cnt; }; + +static void btusb_intel_cmd_timeout(struct hci_dev *hdev) +{ + struct btusb_data *data = hci_get_drvdata(hdev); + struct gpio_desc *reset_gpio = data->reset_gpio; + + if (++data->cmd_timeout_cnt < 5) + return; + + if (!reset_gpio) { + bt_dev_err(hdev, "No way to reset. Ignoring and continuing"); + return; + } + + /* + * Toggle the hard reset line if the platform provides one. The reset + * is going to yank the device off the USB and then replug. So doing + * once is enough. The cleanup is handled correctly on the way out + * (standard USB disconnect), and the new device is detected cleanly + * and bound to the driver again like it should be. + */ + if (test_and_set_bit(BTUSB_HW_RESET_ACTIVE, &data->flags)) { + bt_dev_err(hdev, "last reset failed? Not resetting again"); + return; + } + + bt_dev_err(hdev, "Initiating HW reset via gpio"); + gpiod_set_value(reset_gpio, 1); + mdelay(100); + gpiod_set_value(reset_gpio, 0); +} + static inline void btusb_free_frags(struct btusb_data *data) { unsigned long flags; @@ -2915,6 +2952,7 @@ static int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_endpoint_descriptor *ep_desc; + struct gpio_desc *reset_gpio; struct btusb_data *data; struct hci_dev *hdev; unsigned ifnum_base; @@ -3028,6 +3066,15 @@ static int btusb_probe(struct usb_interface *intf, SET_HCIDEV_DEV(hdev, &intf->dev); + reset_gpio = gpiod_get_optional(&data->udev->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(reset_gpio)) { + err = PTR_ERR(reset_gpio); + goto out_free_dev; + } else if (reset_gpio) { + data->reset_gpio = reset_gpio; + } + hdev->open = btusb_open; hdev->close = btusb_close; hdev->flush = btusb_flush; @@ -3082,6 +3129,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->shutdown = btusb_shutdown_intel; hdev->set_diag = btintel_set_diag_mfg; hdev->set_bdaddr = btintel_set_bdaddr; + hdev->cmd_timeout = btusb_intel_cmd_timeout; set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); @@ -3094,6 +3142,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->hw_error = btintel_hw_error; hdev->set_diag = btintel_set_diag; hdev->set_bdaddr = btintel_set_bdaddr; + hdev->cmd_timeout = btusb_intel_cmd_timeout; set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); @@ -3226,6 +3275,8 @@ static int btusb_probe(struct usb_interface *intf, return 0; out_free_dev: + if (data->reset_gpio) + gpiod_put(data->reset_gpio); hci_free_dev(hdev); return err; } @@ -3269,6 +3320,9 @@ static void btusb_disconnect(struct usb_interface *intf) if (data->oob_wake_irq) device_init_wakeup(&data->udev->dev, false); + if (data->reset_gpio) + gpiod_put(data->reset_gpio); + hci_free_dev(hdev); } -- cgit v1.2.3 From 30e5c2c6bf285d93dee4c45f23da95d7d50b125a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 25 Jan 2019 10:53:23 -0800 Subject: net: Revert devlink health changes. This reverts the devlink health changes from 9/17/2019, Jiri wants things to be designed differently and it was agreed that the easiest way to do this is start from the beginning again. Commits reverted: cb5ccfbe73b389470e1dc11061bb185ef4bc9aec 880ee82f0313453ec5a6cb122866ac057263066b c7af343b4e33578b7de91786a3f639c8cfa0d97b ff253fedab961b22117a73ab808fcfa9e6852b50 6f9d56132eb6d2603d4273cfc65bed914ec47acb fcd852c69d776c0f46c8f79e8e431e5cc6ddc7b7 8a66704a13d9713593342e29b4f0c19762f5746b 12bd0dcefe88782ac1c9fff632958dd1b71d27e5 aba25279c10094c5c97d09c3491ca86d00b4ad5e ce019faa70f81555fa17ebc1d5a03651f2e7e15a b8c45a033acc607201588f7665ba84207e5149e0 And the follow-on build fix: o33a0efa4baecd689da9474ce0e8b673eb6931c60 Signed-off-by: David S. Miller --- Documentation/networking/devlink-health.txt | 86 -- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en.h | 18 +- .../net/ethernet/mellanox/mlx5/core/en/reporter.h | 15 - .../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 356 ------- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 186 +++- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +- include/net/devlink.h | 144 --- include/trace/events/devlink.h | 62 -- include/uapi/linux/devlink.h | 25 - net/core/devlink.c | 1058 -------------------- 11 files changed, 169 insertions(+), 1785 deletions(-) delete mode 100644 Documentation/networking/devlink-health.txt delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c (limited to 'drivers') diff --git a/Documentation/networking/devlink-health.txt b/Documentation/networking/devlink-health.txt deleted file mode 100644 index 1db3fbea0831..000000000000 --- a/Documentation/networking/devlink-health.txt +++ /dev/null @@ -1,86 +0,0 @@ -The health mechanism is targeted for Real Time Alerting, in order to know when -something bad had happened to a PCI device -- Provide alert debug information -- Self healing -- If problem needs vendor support, provide a way to gather all needed debugging - information. - -The main idea is to unify and centralize driver health reports in the -generic devlink instance and allow the user to set different -attributes of the health reporting and recovery procedures. - -The devlink health reporter: -Device driver creates a "health reporter" per each error/health type. -Error/Health type can be a known/generic (eg pci error, fw error, rx/tx error) -or unknown (driver specific). -For each registered health reporter a driver can issue error/health reports -asynchronously. All health reports handling is done by devlink. -Device driver can provide specific callbacks for each "health reporter", e.g. - - Recovery procedures - - Diagnostics and object dump procedures - - OOB initial parameters -Different parts of the driver can register different types of health reporters -with different handlers. - -Once an error is reported, devlink health will do the following actions: - * A log is being send to the kernel trace events buffer - * Health status and statistics are being updated for the reporter instance - * Object dump is being taken and saved at the reporter instance (as long as - there is no other dump which is already stored) - * Auto recovery attempt is being done. Depends on: - - Auto-recovery configuration - - Grace period vs. time passed since last recover - -The user interface: -User can access/change each reporter's parameters and driver specific callbacks -via devlink, e.g per error type (per health reporter) - - Configure reporter's generic parameters (like: disable/enable auto recovery) - - Invoke recovery procedure - - Run diagnostics - - Object dump - -The devlink health interface (via netlink): -DEVLINK_CMD_HEALTH_REPORTER_GET - Retrieves status and configuration info per DEV and reporter. -DEVLINK_CMD_HEALTH_REPORTER_SET - Allows reporter-related configuration setting. -DEVLINK_CMD_HEALTH_REPORTER_RECOVER - Triggers a reporter's recovery procedure. -DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE - Retrieves diagnostics data from a reporter on a device. -DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET - Retrieves the last stored dump. Devlink health - saves a single dump. If an dump is not already stored by the devlink - for this reporter, devlink generates a new dump. - dump output is defined by the reporter. -DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR - Clears the last saved dump file for the specified reporter. - - - netlink - +--------------------------+ - | | - | + | - | | | - +--------------------------+ - |request for ops - |(diagnose, - mlx5_core devlink |recover, - |dump) -+--------+ +--------------------------+ -| | | reporter| | -| | | +---------v----------+ | -| | ops execution | | | | -| <----------------------------------+ | | -| | | | | | -| | | + ^------------------+ | -| | | | request for ops | -| | | | (recover, dump) | -| | | | | -| | | +-+------------------+ | -| | health report | | health handler | | -| +-------------------------------> | | -| | | +--------------------+ | -| | health reporter create | | -| +----------------------------> | -+--------+ +--------------------------+ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 6bb2a860b15b..9de9abacf7f6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -22,7 +22,7 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \ # mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ en_tx.o en_rx.o en_dim.o en_txrx.o en/xdp.o en_stats.o \ - en_selftest.o en/port.o en/monitor_stats.o en/reporter_tx.o + en_selftest.o en/port.o en/monitor_stats.o # # Netdev extra diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 27e276c9bf84..8fa8fdd30b85 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -388,7 +388,10 @@ struct mlx5e_txqsq { struct mlx5e_channel *channel; int txq_ix; u32 rate_limit; - struct work_struct recover_work; + struct mlx5e_txqsq_recover { + struct work_struct recover_work; + u64 last_recover; + } recover; } ____cacheline_aligned_in_smp; struct mlx5e_dma_info { @@ -679,13 +682,6 @@ struct mlx5e_rss_params { u8 hfunc; }; -struct mlx5e_modify_sq_param { - int curr_state; - int next_state; - int rl_update; - int rl_index; -}; - struct mlx5e_priv { /* priv data path fields - start */ struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC]; @@ -741,7 +737,6 @@ struct mlx5e_priv { #ifdef CONFIG_MLX5_EN_TLS struct mlx5e_tls *tls; #endif - struct devlink_health_reporter *tx_reporter; }; struct mlx5e_profile { @@ -871,11 +866,6 @@ void mlx5e_set_rq_type(struct mlx5_core_dev *mdev, struct mlx5e_params *params); void mlx5e_init_rq_type_params(struct mlx5_core_dev *mdev, struct mlx5e_params *params); -int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, - struct mlx5e_modify_sq_param *p); -void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq); -void mlx5e_tx_disable_queue(struct netdev_queue *txq); - static inline bool mlx5e_tunnel_inner_ft_supported(struct mlx5_core_dev *mdev) { return (MLX5_CAP_ETH(mdev, tunnel_stateless_gre) && diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h deleted file mode 100644 index 2335c5b48820..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ -/* Copyright (c) 2018 Mellanox Technologies. */ - -#ifndef __MLX5E_EN_REPORTER_H -#define __MLX5E_EN_REPORTER_H - -#include -#include "en.h" - -int mlx5e_tx_reporter_create(struct mlx5e_priv *priv); -void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv); -void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq); -void mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq); - -#endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c deleted file mode 100644 index d9675afbb924..000000000000 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ /dev/null @@ -1,356 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ -/* Copyright (c) 2018 Mellanox Technologies. */ - -#include -#include "reporter.h" -#include "lib/eq.h" - -#define MLX5E_TX_REPORTER_PER_SQ_MAX_LEN 256 - -struct mlx5e_tx_err_ctx { - int (*recover)(struct mlx5e_txqsq *sq); - struct mlx5e_txqsq *sq; -}; - -static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) -{ - unsigned long exp_time = jiffies + msecs_to_jiffies(2000); - - while (time_before(jiffies, exp_time)) { - if (sq->cc == sq->pc) - return 0; - - msleep(20); - } - - netdev_err(sq->channel->netdev, - "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n", - sq->sqn, sq->cc, sq->pc); - - return -ETIMEDOUT; -} - -static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq) -{ - WARN_ONCE(sq->cc != sq->pc, - "SQ 0x%x: cc (0x%x) != pc (0x%x)\n", - sq->sqn, sq->cc, sq->pc); - sq->cc = 0; - sq->dma_fifo_cc = 0; - sq->pc = 0; -} - -static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state) -{ - struct mlx5_core_dev *mdev = sq->channel->mdev; - struct net_device *dev = sq->channel->netdev; - struct mlx5e_modify_sq_param msp = {0}; - int err; - - msp.curr_state = curr_state; - msp.next_state = MLX5_SQC_STATE_RST; - - err = mlx5e_modify_sq(mdev, sq->sqn, &msp); - if (err) { - netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn); - return err; - } - - memset(&msp, 0, sizeof(msp)); - msp.curr_state = MLX5_SQC_STATE_RST; - msp.next_state = MLX5_SQC_STATE_RDY; - - err = mlx5e_modify_sq(mdev, sq->sqn, &msp); - if (err) { - netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn); - return err; - } - - return 0; -} - -static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq) -{ - struct mlx5_core_dev *mdev = sq->channel->mdev; - struct net_device *dev = sq->channel->netdev; - u8 state; - int err; - - if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) - return 0; - - err = mlx5_core_query_sq_state(mdev, sq->sqn, &state); - if (err) { - netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n", - sq->sqn, err); - return err; - } - - if (state != MLX5_RQC_STATE_ERR) { - netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn); - return -EINVAL; - } - - mlx5e_tx_disable_queue(sq->txq); - - err = mlx5e_wait_for_sq_flush(sq); - if (err) - return err; - - /* At this point, no new packets will arrive from the stack as TXQ is - * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all - * pending WQEs. SQ can safely reset the SQ. - */ - - err = mlx5e_sq_to_ready(sq, state); - if (err) - return err; - - mlx5e_reset_txqsq_cc_pc(sq); - sq->stats->recover++; - mlx5e_activate_txqsq(sq); - - return 0; -} - -void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq) -{ - char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN]; - struct mlx5e_tx_err_ctx err_ctx = {0}; - - err_ctx.sq = sq; - err_ctx.recover = mlx5e_tx_reporter_err_cqe_recover; - sprintf(err_str, "ERR CQE on SQ: 0x%x", sq->sqn); - - devlink_health_report(sq->channel->priv->tx_reporter, err_str, - &err_ctx); -} - -static int mlx5e_tx_reporter_timeout_recover(struct mlx5e_txqsq *sq) -{ - struct mlx5_eq_comp *eq = sq->cq.mcq.eq; - u32 eqe_count; - - netdev_err(sq->channel->netdev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n", - eq->core.eqn, eq->core.cons_index, eq->core.irqn); - - eqe_count = mlx5_eq_poll_irq_disabled(eq); - if (!eqe_count) { - clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); - return 1; - } - - netdev_err(sq->channel->netdev, "Recover %d eqes on EQ 0x%x\n", - eqe_count, eq->core.eqn); - sq->channel->stats->eq_rearm++; - return 0; -} - -void mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq) -{ - struct mlx5e_tx_err_ctx err_ctx; - char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN]; - - err_ctx.sq = sq; - err_ctx.recover = mlx5e_tx_reporter_timeout_recover; - sprintf(err_str, - "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n", - sq->channel->ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc, - jiffies_to_usecs(jiffies - sq->txq->trans_start)); - devlink_health_report(sq->channel->priv->tx_reporter, err_str, - &err_ctx); -} - -/* state lock cannot be grabbed within this function. - * It can cause a dead lock or a read-after-free. - */ -int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_tx_err_ctx *err_ctx) -{ - return err_ctx->recover(err_ctx->sq); -} - -static int mlx5e_tx_reporter_recover_all(struct mlx5e_priv *priv) -{ - int err; - - mutex_lock(&priv->state_lock); - mlx5e_close_locked(priv->netdev); - err = mlx5e_open_locked(priv->netdev); - mutex_unlock(&priv->state_lock); - - return err; -} - -static int mlx5e_tx_reporter_recover(struct devlink_health_reporter *reporter, - void *context) -{ - struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); - struct mlx5e_tx_err_ctx *err_ctx = context; - - return err_ctx ? mlx5e_tx_reporter_recover_from_ctx(err_ctx) : - mlx5e_tx_reporter_recover_all(priv); -} - -static int -mlx5e_tx_reporter_build_diagnose_output(struct devlink_health_buffer *buffer, - u32 sqn, u8 state, u8 stopped) -{ - int err, i; - int nest = 0; - char name[20]; - - err = devlink_health_buffer_nest_start(buffer, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT); - if (err) - goto buffer_error; - nest++; - - err = devlink_health_buffer_nest_start(buffer, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR); - if (err) - goto buffer_error; - nest++; - - sprintf(name, "SQ 0x%x", sqn); - err = devlink_health_buffer_put_object_name(buffer, name); - if (err) - goto buffer_error; - - err = devlink_health_buffer_nest_start(buffer, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE); - if (err) - goto buffer_error; - nest++; - - err = devlink_health_buffer_nest_start(buffer, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT); - if (err) - goto buffer_error; - nest++; - - err = devlink_health_buffer_nest_start(buffer, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR); - if (err) - goto buffer_error; - nest++; - - err = devlink_health_buffer_put_object_name(buffer, "HW state"); - if (err) - goto buffer_error; - - err = devlink_health_buffer_nest_start(buffer, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE); - if (err) - goto buffer_error; - nest++; - - err = devlink_health_buffer_put_value_u8(buffer, state); - if (err) - goto buffer_error; - - devlink_health_buffer_nest_end(buffer); /* DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE */ - nest--; - - devlink_health_buffer_nest_end(buffer); /* DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR */ - nest--; - - err = devlink_health_buffer_nest_start(buffer, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR); - if (err) - goto buffer_error; - nest++; - - err = devlink_health_buffer_put_object_name(buffer, "stopped"); - if (err) - goto buffer_error; - - err = devlink_health_buffer_nest_start(buffer, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE); - if (err) - goto buffer_error; - nest++; - - err = devlink_health_buffer_put_value_u8(buffer, stopped); - if (err) - goto buffer_error; - - for (i = 0; i < nest; i++) - devlink_health_buffer_nest_end(buffer); - - return 0; - -buffer_error: - for (i = 0; i < nest; i++) - devlink_health_buffer_nest_cancel(buffer); - return err; -} - -static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter, - struct devlink_health_buffer **buffers_array, - unsigned int buffer_size, - unsigned int num_buffers) -{ - struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); - unsigned int buff = 0; - int i = 0, err = 0; - - if (buffer_size < MLX5E_TX_REPORTER_PER_SQ_MAX_LEN) - return -ENOMEM; - - mutex_lock(&priv->state_lock); - - if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { - mutex_unlock(&priv->state_lock); - return 0; - } - - while (i < priv->channels.num * priv->channels.params.num_tc) { - struct mlx5e_txqsq *sq = priv->txq2sq[i]; - u8 state; - - err = mlx5_core_query_sq_state(priv->mdev, sq->sqn, &state); - if (err) - break; - - err = mlx5e_tx_reporter_build_diagnose_output(buffers_array[buff], - sq->sqn, state, - netif_xmit_stopped(sq->txq)); - if (err) { - if (++buff == num_buffers) - break; - } else { - i++; - } - } - - mutex_unlock(&priv->state_lock); - return err; -} - -static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = { - .name = "TX", - .recover = mlx5e_tx_reporter_recover, - .diagnose_size = MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC * - MLX5E_TX_REPORTER_PER_SQ_MAX_LEN, - .diagnose = mlx5e_tx_reporter_diagnose, - .dump_size = 0, - .dump = NULL, -}; - -#define MLX5_REPORTER_TX_GRACEFUL_PERIOD 500 -int mlx5e_tx_reporter_create(struct mlx5e_priv *priv) -{ - struct mlx5_core_dev *mdev = priv->mdev; - struct devlink *devlink = priv_to_devlink(mdev); - - priv->tx_reporter = - devlink_health_reporter_create(devlink, &mlx5_tx_reporter_ops, - MLX5_REPORTER_TX_GRACEFUL_PERIOD, - true, priv); - return PTR_ERR_OR_ZERO(priv->tx_reporter); -} - -void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv) -{ - devlink_health_reporter_destroy(priv->tx_reporter); -} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index dee0c8f3d4e9..8cfd2ec7c0a2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -51,7 +51,6 @@ #include "en/xdp.h" #include "lib/eq.h" #include "en/monitor_stats.h" -#include "en/reporter.h" struct mlx5e_rq_param { u32 rqc[MLX5_ST_SZ_DW(rqc)]; @@ -1161,7 +1160,7 @@ static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa) return 0; } -static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work); +static void mlx5e_sq_recover(struct work_struct *work); static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, int txq_ix, struct mlx5e_params *params, @@ -1183,7 +1182,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, sq->uar_map = mdev->mlx5e_res.bfreg.map; sq->min_inline_mode = params->tx_min_inline_mode; sq->stats = &c->priv->channel_stats[c->ix].sq[tc]; - INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work); + INIT_WORK(&sq->recover.recover_work, mlx5e_sq_recover); if (MLX5_IPSEC_DEV(c->priv->mdev)) set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state); if (mlx5_accel_is_tls_device(c->priv->mdev)) @@ -1271,8 +1270,15 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev, return err; } -int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, - struct mlx5e_modify_sq_param *p) +struct mlx5e_modify_sq_param { + int curr_state; + int next_state; + bool rl_update; + int rl_index; +}; + +static int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, + struct mlx5e_modify_sq_param *p) { void *in; void *sqc; @@ -1370,7 +1376,17 @@ err_free_txqsq: return err; } -void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) +static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq) +{ + WARN_ONCE(sq->cc != sq->pc, + "SQ 0x%x: cc (0x%x) != pc (0x%x)\n", + sq->sqn, sq->cc, sq->pc); + sq->cc = 0; + sq->dma_fifo_cc = 0; + sq->pc = 0; +} + +static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) { sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix); clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state); @@ -1379,7 +1395,7 @@ void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) netif_tx_start_queue(sq->txq); } -void mlx5e_tx_disable_queue(struct netdev_queue *txq) +static inline void netif_tx_disable_queue(struct netdev_queue *txq) { __netif_tx_lock_bh(txq); netif_tx_stop_queue(txq); @@ -1395,7 +1411,7 @@ static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq) /* prevent netif_tx_wake_queue */ napi_synchronize(&c->napi); - mlx5e_tx_disable_queue(sq->txq); + netif_tx_disable_queue(sq->txq); /* last doorbell out, godspeed .. */ if (mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1)) { @@ -1415,7 +1431,6 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq) struct mlx5_rate_limit rl = {0}; cancel_work_sync(&sq->dim.work); - cancel_work_sync(&sq->recover_work); mlx5e_destroy_sq(mdev, sq->sqn); if (sq->rate_limit) { rl.rate = sq->rate_limit; @@ -1425,15 +1440,105 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq) mlx5e_free_txqsq(sq); } -static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work) +static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) +{ + unsigned long exp_time = jiffies + msecs_to_jiffies(2000); + + while (time_before(jiffies, exp_time)) { + if (sq->cc == sq->pc) + return 0; + + msleep(20); + } + + netdev_err(sq->channel->netdev, + "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n", + sq->sqn, sq->cc, sq->pc); + + return -ETIMEDOUT; +} + +static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state) { - struct mlx5e_txqsq *sq = container_of(recover_work, struct mlx5e_txqsq, - recover_work); + struct mlx5_core_dev *mdev = sq->channel->mdev; + struct net_device *dev = sq->channel->netdev; + struct mlx5e_modify_sq_param msp = {0}; + int err; - if (!sq->channel->priv->tx_reporter) + msp.curr_state = curr_state; + msp.next_state = MLX5_SQC_STATE_RST; + + err = mlx5e_modify_sq(mdev, sq->sqn, &msp); + if (err) { + netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn); + return err; + } + + memset(&msp, 0, sizeof(msp)); + msp.curr_state = MLX5_SQC_STATE_RST; + msp.next_state = MLX5_SQC_STATE_RDY; + + err = mlx5e_modify_sq(mdev, sq->sqn, &msp); + if (err) { + netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn); + return err; + } + + return 0; +} + +static void mlx5e_sq_recover(struct work_struct *work) +{ + struct mlx5e_txqsq_recover *recover = + container_of(work, struct mlx5e_txqsq_recover, + recover_work); + struct mlx5e_txqsq *sq = container_of(recover, struct mlx5e_txqsq, + recover); + struct mlx5_core_dev *mdev = sq->channel->mdev; + struct net_device *dev = sq->channel->netdev; + u8 state; + int err; + + err = mlx5_core_query_sq_state(mdev, sq->sqn, &state); + if (err) { + netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n", + sq->sqn, err); + return; + } + + if (state != MLX5_RQC_STATE_ERR) { + netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn); + return; + } + + netif_tx_disable_queue(sq->txq); + + if (mlx5e_wait_for_sq_flush(sq)) return; - mlx5e_tx_reporter_err_cqe(sq); + /* If the interval between two consecutive recovers per SQ is too + * short, don't recover to avoid infinite loop of ERR_CQE -> recover. + * If we reached this state, there is probably a bug that needs to be + * fixed. let's keep the queue close and let tx timeout cleanup. + */ + if (jiffies_to_msecs(jiffies - recover->last_recover) < + MLX5E_SQ_RECOVER_MIN_INTERVAL) { + netdev_err(dev, "Recover SQ 0x%x canceled, too many error CQEs\n", + sq->sqn); + return; + } + + /* At this point, no new packets will arrive from the stack as TXQ is + * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all + * pending WQEs. SQ can safely reset the SQ. + */ + if (mlx5e_sq_to_ready(sq, state)) + return; + + mlx5e_reset_txqsq_cc_pc(sq); + sq->stats->recover++; + recover->last_recover = jiffies; + mlx5e_activate_txqsq(sq); } static int mlx5e_open_icosq(struct mlx5e_channel *c, @@ -3102,7 +3207,6 @@ static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv) { int tc; - mlx5e_tx_reporter_destroy(priv); for (tc = 0; tc < priv->profile->max_tc; tc++) mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]); } @@ -4074,14 +4178,31 @@ netdev_features_t mlx5e_features_check(struct sk_buff *skb, return features; } +static bool mlx5e_tx_timeout_eq_recover(struct net_device *dev, + struct mlx5e_txqsq *sq) +{ + struct mlx5_eq_comp *eq = sq->cq.mcq.eq; + u32 eqe_count; + + netdev_err(dev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n", + eq->core.eqn, eq->core.cons_index, eq->core.irqn); + + eqe_count = mlx5_eq_poll_irq_disabled(eq); + if (!eqe_count) + return false; + + netdev_err(dev, "Recover %d eqes on EQ 0x%x\n", eqe_count, eq->core.eqn); + sq->channel->stats->eq_rearm++; + return true; +} + static void mlx5e_tx_timeout_work(struct work_struct *work) { struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv, tx_timeout_work); - int i; - - if (!priv->tx_reporter) - return; + struct net_device *dev = priv->netdev; + bool reopen_channels = false; + int i, err; rtnl_lock(); mutex_lock(&priv->state_lock); @@ -4090,16 +4211,36 @@ static void mlx5e_tx_timeout_work(struct work_struct *work) goto unlock; for (i = 0; i < priv->channels.num * priv->channels.params.num_tc; i++) { - struct netdev_queue *dev_queue = - netdev_get_tx_queue(priv->netdev, i); + struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, i); struct mlx5e_txqsq *sq = priv->txq2sq[i]; if (!netif_xmit_stopped(dev_queue)) continue; - mlx5e_tx_reporter_timeout(sq); + netdev_err(dev, + "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n", + i, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc, + jiffies_to_usecs(jiffies - dev_queue->trans_start)); + + /* If we recover a lost interrupt, most likely TX timeout will + * be resolved, skip reopening channels + */ + if (!mlx5e_tx_timeout_eq_recover(dev, sq)) { + clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); + reopen_channels = true; + } } + if (!reopen_channels) + goto unlock; + + mlx5e_close_locked(dev); + err = mlx5e_open_locked(dev); + if (err) + netdev_err(priv->netdev, + "mlx5e_open_locked failed recovering from a tx_timeout, err(%d).\n", + err); + unlock: mutex_unlock(&priv->state_lock); rtnl_unlock(); @@ -4767,7 +4908,6 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv) #ifdef CONFIG_MLX5_CORE_EN_DCB mlx5e_dcbnl_initialize(priv); #endif - mlx5e_tx_reporter_create(priv); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index a8e052a5ce36..598ad7e4d5c9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -514,7 +514,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) mlx5e_dump_error_cqe(sq, (struct mlx5_err_cqe *)cqe); queue_work(cq->channel->priv->wq, - &sq->recover_work); + &sq->recover.recover_work); } stats->cqe_err++; } diff --git a/include/net/devlink.h b/include/net/devlink.h index a81a1b7a67d7..67f4293bc970 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -30,7 +30,6 @@ struct devlink { struct list_head param_list; struct list_head region_list; u32 snapshot_id; - struct list_head reporter_list; struct devlink_dpipe_headers *dpipe_headers; const struct devlink_ops *ops; struct device *dev; @@ -424,36 +423,6 @@ struct devlink_region; typedef void devlink_snapshot_data_dest_t(const void *data); -struct devlink_health_buffer; -struct devlink_health_reporter; - -/** - * struct devlink_health_reporter_ops - Reporter operations - * @name: reporter name - * dump_size: dump buffer size allocated by the devlink - * diagnose_size: diagnose buffer size allocated by the devlink - * recover: callback to recover from reported error - * if priv_ctx is NULL, run a full recover - * dump: callback to dump an object - * if priv_ctx is NULL, run a full dump - * diagnose: callback to diagnose the current status - */ - -struct devlink_health_reporter_ops { - char *name; - unsigned int dump_size; - unsigned int diagnose_size; - int (*recover)(struct devlink_health_reporter *reporter, - void *priv_ctx); - int (*dump)(struct devlink_health_reporter *reporter, - struct devlink_health_buffer **buffers_array, - unsigned int buffer_size, unsigned int num_buffers, - void *priv_ctx); - int (*diagnose)(struct devlink_health_reporter *reporter, - struct devlink_health_buffer **buffers_array, - unsigned int buffer_size, unsigned int num_buffers); -}; - struct devlink_ops { int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack); int (*port_type_set)(struct devlink_port *devlink_port, @@ -615,34 +584,6 @@ int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, u8 *data, u32 snapshot_id, devlink_snapshot_data_dest_t *data_destructor); -int devlink_health_buffer_nest_start(struct devlink_health_buffer *buffer, - int attrtype); -void devlink_health_buffer_nest_end(struct devlink_health_buffer *buffer); -void devlink_health_buffer_nest_cancel(struct devlink_health_buffer *buffer); -int devlink_health_buffer_put_object_name(struct devlink_health_buffer *buffer, - char *name); -int devlink_health_buffer_put_value_u8(struct devlink_health_buffer *buffer, - u8 value); -int devlink_health_buffer_put_value_u32(struct devlink_health_buffer *buffer, - u32 value); -int devlink_health_buffer_put_value_u64(struct devlink_health_buffer *buffer, - u64 value); -int devlink_health_buffer_put_value_string(struct devlink_health_buffer *buffer, - char *name); -int devlink_health_buffer_put_value_data(struct devlink_health_buffer *buffer, - void *data, int len); -struct devlink_health_reporter * -devlink_health_reporter_create(struct devlink *devlink, - const struct devlink_health_reporter_ops *ops, - u64 graceful_period, bool auto_recover, - void *priv); -void -devlink_health_reporter_destroy(struct devlink_health_reporter *reporter); - -void * -devlink_health_reporter_priv(struct devlink_health_reporter *reporter); -int devlink_health_report(struct devlink_health_reporter *reporter, - const char *msg, void *priv_ctx); #else static inline struct devlink *devlink_alloc(const struct devlink_ops *ops, @@ -903,91 +844,6 @@ devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, return 0; } -static inline int -devlink_health_buffer_nest_start(struct devlink_health_buffer *buffer, - int attrtype) -{ - return 0; -} - -static inline void -devlink_health_buffer_nest_end(struct devlink_health_buffer *buffer) -{ -} - -static inline void -devlink_health_buffer_nest_cancel(struct devlink_health_buffer *buffer) -{ -} - -static inline int -devlink_health_buffer_put_object_name(struct devlink_health_buffer *buffer, - char *name) -{ - return 0; -} - -static inline int -devlink_health_buffer_put_value_u8(struct devlink_health_buffer *buffer, - u8 value) -{ - return 0; -} - -static inline int -devlink_health_buffer_put_value_u32(struct devlink_health_buffer *buffer, - u32 value) -{ - return 0; -} - -static inline int -devlink_health_buffer_put_value_u64(struct devlink_health_buffer *buffer, - u64 value) -{ - return 0; -} - -static inline int -devlink_health_buffer_put_value_string(struct devlink_health_buffer *buffer, - char *name) -{ - return 0; -} - -static inline int -devlink_health_buffer_put_value_data(struct devlink_health_buffer *buffer, - void *data, int len) -{ - return 0; -} - -static inline struct devlink_health_reporter * -devlink_health_reporter_create(struct devlink *devlink, - const struct devlink_health_reporter_ops *ops, - u64 graceful_period, bool auto_recover, - void *priv) -{ - return NULL; -} - -static inline void -devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) -{ -} - -static inline void * -devlink_health_reporter_priv(struct devlink_health_reporter *reporter) -{ - return NULL; -} - -static inline int -devlink_health_report(struct devlink_health_reporter *reporter, - const char *msg, void *priv_ctx) -{ - return 0; -} #endif #endif /* _NET_DEVLINK_H_ */ diff --git a/include/trace/events/devlink.h b/include/trace/events/devlink.h index 7e39d2fc7c75..44acfbca1266 100644 --- a/include/trace/events/devlink.h +++ b/include/trace/events/devlink.h @@ -46,65 +46,6 @@ TRACE_EVENT(devlink_hwmsg, (int) __entry->len, __get_dynamic_array(buf), __entry->len) ); -TRACE_EVENT(devlink_health_report, - TP_PROTO(const struct devlink *devlink, const char *reporter_name, - const char *msg), - - TP_ARGS(devlink, reporter_name, msg), - - TP_STRUCT__entry( - __string(bus_name, devlink->dev->bus->name) - __string(dev_name, dev_name(devlink->dev)) - __string(driver_name, devlink->dev->driver->name) - __string(reporter_name, msg) - __string(msg, msg) - ), - - TP_fast_assign( - __assign_str(bus_name, devlink->dev->bus->name); - __assign_str(dev_name, dev_name(devlink->dev)); - __assign_str(driver_name, devlink->dev->driver->name); - __assign_str(reporter_name, reporter_name); - __assign_str(msg, msg); - ), - - TP_printk("bus_name=%s dev_name=%s driver_name=%s reporter_name=%s: %s", - __get_str(bus_name), __get_str(dev_name), - __get_str(driver_name), __get_str(reporter_name), - __get_str(msg)) -); - -TRACE_EVENT(devlink_health_recover_aborted, - TP_PROTO(const struct devlink *devlink, const char *reporter_name, - bool health_state, u64 time_since_last_recover), - - TP_ARGS(devlink, reporter_name, health_state, time_since_last_recover), - - TP_STRUCT__entry( - __string(bus_name, devlink->dev->bus->name) - __string(dev_name, dev_name(devlink->dev)) - __string(driver_name, devlink->dev->driver->name) - __string(reporter_name, reporter_name) - __field(bool, health_state) - __field(u64, time_since_last_recover) - ), - - TP_fast_assign( - __assign_str(bus_name, devlink->dev->bus->name); - __assign_str(dev_name, dev_name(devlink->dev)); - __assign_str(driver_name, devlink->dev->driver->name); - __assign_str(reporter_name, reporter_name); - __entry->health_state = health_state; - __entry->time_since_last_recover = time_since_last_recover; - ), - - TP_printk("bus_name=%s dev_name=%s driver_name=%s reporter_name=%s: health_state=%d time_since_last_recover = %llu recover aborted", - __get_str(bus_name), __get_str(dev_name), - __get_str(driver_name), __get_str(reporter_name), - __entry->health_state, - __entry->time_since_last_recover) -); - #endif /* _TRACE_DEVLINK_H */ /* This part must be outside protection */ @@ -123,9 +64,6 @@ static inline void trace_devlink_hwmsg(const struct devlink *devlink, { } -static inline void trace_devlink_health(const char *msg) -{ -} #endif /* _TRACE_DEVLINK_H */ #endif diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index 6b26bb2ce4dc..6e52d3660654 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -89,13 +89,6 @@ enum devlink_command { DEVLINK_CMD_REGION_DEL, DEVLINK_CMD_REGION_READ, - DEVLINK_CMD_HEALTH_REPORTER_GET, - DEVLINK_CMD_HEALTH_REPORTER_SET, - DEVLINK_CMD_HEALTH_REPORTER_RECOVER, - DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, - DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, - DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, - /* add new commands above here */ __DEVLINK_CMD_MAX, DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 @@ -292,24 +285,6 @@ enum devlink_attr { DEVLINK_ATTR_REGION_CHUNK_ADDR, /* u64 */ DEVLINK_ATTR_REGION_CHUNK_LEN, /* u64 */ - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT, /* nested */ - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR, /* nested */ - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_NAME, /* string */ - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE, /* nested */ - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_ARRAY, /* nested */ - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE, /* u8 */ - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA, /* dynamic */ - - DEVLINK_ATTR_HEALTH_REPORTER, /* nested */ - DEVLINK_ATTR_HEALTH_REPORTER_NAME, /* string */ - DEVLINK_ATTR_HEALTH_REPORTER_STATE, /* u8 */ - DEVLINK_ATTR_HEALTH_REPORTER_ERR, /* u64 */ - DEVLINK_ATTR_HEALTH_REPORTER_RECOVER, /* u64 */ - DEVLINK_ATTR_HEALTH_REPORTER_DUMP_AVAIL, /* u8 */ - DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS, /* u64 */ - DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD, /* u64 */ - DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER, /* u8 */ - /* add new attributes above here, update the policy in devlink.c */ __DEVLINK_ATTR_MAX, diff --git a/net/core/devlink.c b/net/core/devlink.c index 24f266468ca5..abb0da9d7b4b 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -3597,1015 +3597,6 @@ out: return 0; } -#define DEVLINK_HEALTH_BUFFER_SIZE (4096 - GENL_HDRLEN) -#define DEVLINK_HEALTH_BUFFER_DATA_SIZE (DEVLINK_HEALTH_BUFFER_SIZE / 2) -#define DEVLINK_HEALTH_SIZE_TO_BUFFERS(size) DIV_ROUND_UP_ULL(size, DEVLINK_HEALTH_BUFFER_DATA_SIZE) -#define DEVLINK_HEALTH_BUFFER_MAX_CHUNK 1024 - -struct devlink_health_buffer { - void *data; - u64 offset; - u64 bytes_left; - u64 bytes_left_metadata; - u64 max_nested_depth; - u64 curr_nest; -}; - -struct devlink_health_buffer_desc { - int attrtype; - u16 len; - u8 nla_type; - u8 nest_end; - int value[0]; -}; - -static void -devlink_health_buffers_reset(struct devlink_health_buffer **buffers_list, - u64 num_of_buffers) -{ - u64 i; - - for (i = 0; i < num_of_buffers; i++) { - memset(buffers_list[i]->data, 0, DEVLINK_HEALTH_BUFFER_SIZE); - buffers_list[i]->offset = 0; - buffers_list[i]->bytes_left = DEVLINK_HEALTH_BUFFER_DATA_SIZE; - buffers_list[i]->bytes_left_metadata = - DEVLINK_HEALTH_BUFFER_DATA_SIZE; - buffers_list[i]->max_nested_depth = 0; - buffers_list[i]->curr_nest = 0; - } -} - -static void -devlink_health_buffers_destroy(struct devlink_health_buffer **buffers_list, - u64 size); - -static struct devlink_health_buffer ** -devlink_health_buffers_create(u64 size) -{ - struct devlink_health_buffer **buffers_list; - u64 num_of_buffers = DEVLINK_HEALTH_SIZE_TO_BUFFERS(size); - u64 i; - - buffers_list = kcalloc(num_of_buffers, - sizeof(struct devlink_health_buffer *), - GFP_KERNEL); - if (!buffers_list) - return NULL; - - for (i = 0; i < num_of_buffers; i++) { - struct devlink_health_buffer *buffer; - void *data; - - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); - data = kzalloc(DEVLINK_HEALTH_BUFFER_SIZE, GFP_KERNEL); - if (!buffer || !data) { - kfree(buffer); - kfree(data); - goto buffers_cleanup; - } - buffers_list[i] = buffer; - buffer->data = data; - } - devlink_health_buffers_reset(buffers_list, num_of_buffers); - - return buffers_list; - -buffers_cleanup: - devlink_health_buffers_destroy(buffers_list, --i); - kfree(buffers_list); - return NULL; -} - -static void -devlink_health_buffers_destroy(struct devlink_health_buffer **buffers_list, - u64 num_of_buffers) -{ - u64 i; - - for (i = 0; i < num_of_buffers; i++) { - kfree(buffers_list[i]->data); - kfree(buffers_list[i]); - } -} - -void -devlink_health_buffer_offset_inc(struct devlink_health_buffer *buffer, - int len) -{ - buffer->offset += len; -} - -/* In order to store a nest, need two descriptors, for start and end */ -#define DEVLINK_HEALTH_BUFFER_NEST_SIZE (sizeof(struct devlink_health_buffer_desc) * 2) - -int devlink_health_buffer_verify_len(struct devlink_health_buffer *buffer, - int len, int metadata_len) -{ - if (len > DEVLINK_HEALTH_BUFFER_DATA_SIZE) - return -EINVAL; - - if (buffer->bytes_left < len || - buffer->bytes_left_metadata < metadata_len) - return -ENOMEM; - - return 0; -} - -static struct devlink_health_buffer_desc * -devlink_health_buffer_get_desc_from_offset(struct devlink_health_buffer *buffer) -{ - return buffer->data + buffer->offset; -} - -int -devlink_health_buffer_nest_start(struct devlink_health_buffer *buffer, - int attrtype) -{ - struct devlink_health_buffer_desc *desc; - int err; - - err = devlink_health_buffer_verify_len(buffer, 0, - DEVLINK_HEALTH_BUFFER_NEST_SIZE); - if (err) - return err; - - if (attrtype != DEVLINK_ATTR_HEALTH_BUFFER_OBJECT && - attrtype != DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR && - attrtype != DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE && - attrtype != DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_ARRAY) - return -EINVAL; - - desc = devlink_health_buffer_get_desc_from_offset(buffer); - - desc->attrtype = attrtype; - buffer->bytes_left_metadata -= DEVLINK_HEALTH_BUFFER_NEST_SIZE; - devlink_health_buffer_offset_inc(buffer, sizeof(*desc)); - - buffer->curr_nest++; - buffer->max_nested_depth = max(buffer->max_nested_depth, - buffer->curr_nest); - - return 0; -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_nest_start); - -enum devlink_health_buffer_nest_end_cancel { - DEVLINK_HEALTH_BUFFER_NEST_END = 1, - DEVLINK_HEALTH_BUFFER_NEST_CANCEL, -}; - -static void -devlink_health_buffer_nest_end_cancel(struct devlink_health_buffer *buffer, - enum devlink_health_buffer_nest_end_cancel nest) -{ - struct devlink_health_buffer_desc *desc; - - WARN_ON(!buffer->curr_nest); - buffer->curr_nest--; - - desc = devlink_health_buffer_get_desc_from_offset(buffer); - desc->nest_end = nest; - devlink_health_buffer_offset_inc(buffer, sizeof(*desc)); -} - -void devlink_health_buffer_nest_end(struct devlink_health_buffer *buffer) -{ - devlink_health_buffer_nest_end_cancel(buffer, - DEVLINK_HEALTH_BUFFER_NEST_END); -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_nest_end); - -void devlink_health_buffer_nest_cancel(struct devlink_health_buffer *buffer) -{ - devlink_health_buffer_nest_end_cancel(buffer, - DEVLINK_HEALTH_BUFFER_NEST_CANCEL); -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_nest_cancel); - -int -devlink_health_buffer_put_object_name(struct devlink_health_buffer *buffer, - char *name) -{ - struct devlink_health_buffer_desc *desc; - int err; - - err = devlink_health_buffer_verify_len(buffer, strlen(name) + 1, - sizeof(*desc)); - if (err) - return err; - - desc = devlink_health_buffer_get_desc_from_offset(buffer); - desc->attrtype = DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_NAME; - desc->nla_type = NLA_NUL_STRING; - desc->len = strlen(name) + 1; - memcpy(&desc->value, name, desc->len); - devlink_health_buffer_offset_inc(buffer, sizeof(*desc) + desc->len); - - buffer->bytes_left_metadata -= sizeof(*desc); - buffer->bytes_left -= (strlen(name) + 1); - - return 0; -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_put_object_name); - -static int -devlink_health_buffer_put_value(struct devlink_health_buffer *buffer, - u8 nla_type, void *value, int len) -{ - struct devlink_health_buffer_desc *desc; - int err; - - err = devlink_health_buffer_verify_len(buffer, len, sizeof(*desc)); - if (err) - return err; - - desc = devlink_health_buffer_get_desc_from_offset(buffer); - desc->attrtype = DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA; - desc->nla_type = nla_type; - desc->len = len; - memcpy(&desc->value, value, len); - devlink_health_buffer_offset_inc(buffer, sizeof(*desc) + desc->len); - - buffer->bytes_left_metadata -= sizeof(*desc); - buffer->bytes_left -= len; - - return 0; -} - -int -devlink_health_buffer_put_value_u8(struct devlink_health_buffer *buffer, - u8 value) -{ - int err; - - err = devlink_health_buffer_put_value(buffer, NLA_U8, &value, - sizeof(value)); - if (err) - return err; - - return 0; -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_u8); - -int -devlink_health_buffer_put_value_u32(struct devlink_health_buffer *buffer, - u32 value) -{ - int err; - - err = devlink_health_buffer_put_value(buffer, NLA_U32, &value, - sizeof(value)); - if (err) - return err; - - return 0; -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_u32); - -int -devlink_health_buffer_put_value_u64(struct devlink_health_buffer *buffer, - u64 value) -{ - int err; - - err = devlink_health_buffer_put_value(buffer, NLA_U64, &value, - sizeof(value)); - if (err) - return err; - - return 0; -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_u64); - -int -devlink_health_buffer_put_value_string(struct devlink_health_buffer *buffer, - char *name) -{ - int err; - - if (strlen(name) + 1 > DEVLINK_HEALTH_BUFFER_MAX_CHUNK) - return -EINVAL; - - err = devlink_health_buffer_put_value(buffer, NLA_NUL_STRING, name, - strlen(name) + 1); - if (err) - return err; - - return 0; -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_string); - -int -devlink_health_buffer_put_value_data(struct devlink_health_buffer *buffer, - void *data, int len) -{ - int err; - - if (len > DEVLINK_HEALTH_BUFFER_MAX_CHUNK) - return -EINVAL; - - err = devlink_health_buffer_put_value(buffer, NLA_BINARY, data, len); - if (err) - return err; - - return 0; -} -EXPORT_SYMBOL_GPL(devlink_health_buffer_put_value_data); - -static int -devlink_health_buffer_fill_data(struct sk_buff *skb, - struct devlink_health_buffer_desc *desc) -{ - int err = -EINVAL; - - switch (desc->nla_type) { - case NLA_U8: - err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA, - *(u8 *)desc->value); - break; - case NLA_U32: - err = nla_put_u32(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA, - *(u32 *)desc->value); - break; - case NLA_U64: - err = nla_put_u64_64bit(skb, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA, - *(u64 *)desc->value, DEVLINK_ATTR_PAD); - break; - case NLA_NUL_STRING: - err = nla_put_string(skb, - DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA, - (char *)&desc->value); - break; - case NLA_BINARY: - err = nla_put(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA, - desc->len, (void *)&desc->value); - break; - } - - return err; -} - -static int -devlink_health_buffer_fill_type(struct sk_buff *skb, - struct devlink_health_buffer_desc *desc) -{ - int err = -EINVAL; - - switch (desc->nla_type) { - case NLA_U8: - err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE, - NLA_U8); - break; - case NLA_U32: - err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE, - NLA_U32); - break; - case NLA_U64: - err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE, - NLA_U64); - break; - case NLA_NUL_STRING: - err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE, - NLA_NUL_STRING); - break; - case NLA_BINARY: - err = nla_put_u8(skb, DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE, - NLA_BINARY); - break; - } - - return err; -} - -static inline struct devlink_health_buffer_desc * -devlink_health_buffer_get_next_desc(struct devlink_health_buffer_desc *desc) -{ - return (void *)&desc->value + desc->len; -} - -static int -devlink_health_buffer_prepare_skb(struct sk_buff *skb, - struct devlink_health_buffer *buffer) -{ - struct devlink_health_buffer_desc *last_desc, *desc; - struct nlattr **buffer_nlattr; - int err; - int i = 0; - - buffer_nlattr = kcalloc(buffer->max_nested_depth, - sizeof(*buffer_nlattr), GFP_KERNEL); - if (!buffer_nlattr) - return -EINVAL; - - last_desc = devlink_health_buffer_get_desc_from_offset(buffer); - desc = buffer->data; - while (desc != last_desc) { - switch (desc->attrtype) { - case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT: - case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_PAIR: - case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE: - case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_ARRAY: - buffer_nlattr[i] = nla_nest_start(skb, desc->attrtype); - if (!buffer_nlattr[i]) - goto nla_put_failure; - i++; - break; - case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA: - err = devlink_health_buffer_fill_data(skb, desc); - if (err) - goto nla_put_failure; - err = devlink_health_buffer_fill_type(skb, desc); - if (err) - goto nla_put_failure; - break; - case DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_NAME: - err = nla_put_string(skb, desc->attrtype, - (char *)&desc->value); - if (err) - goto nla_put_failure; - break; - default: - WARN_ON(!desc->nest_end); - WARN_ON(i <= 0); - if (desc->nest_end == DEVLINK_HEALTH_BUFFER_NEST_END) - nla_nest_end(skb, buffer_nlattr[--i]); - else - nla_nest_cancel(skb, buffer_nlattr[--i]); - break; - } - desc = devlink_health_buffer_get_next_desc(desc); - } - - return 0; - -nla_put_failure: - kfree(buffer_nlattr); - return err; -} - -static int -devlink_health_buffer_snd(struct genl_info *info, - enum devlink_command cmd, int flags, - struct devlink_health_buffer **buffers_array, - u64 num_of_buffers) -{ - struct sk_buff *skb; - struct nlmsghdr *nlh; - void *hdr; - int err; - u64 i; - - for (i = 0; i < num_of_buffers; i++) { - /* Skip buffer if driver did not fill it up with any data */ - if (!buffers_array[i]->offset) - continue; - - skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!skb) - return -ENOMEM; - - hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, - &devlink_nl_family, NLM_F_MULTI, cmd); - if (!hdr) - goto nla_put_failure; - - err = devlink_health_buffer_prepare_skb(skb, buffers_array[i]); - if (err) - goto nla_put_failure; - - genlmsg_end(skb, hdr); - err = genlmsg_reply(skb, info); - if (err) - return err; - } - - skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!skb) - return -ENOMEM; - nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, - NLMSG_DONE, 0, flags | NLM_F_MULTI); - if (!nlh) - goto nla_put_failure; - - err = genlmsg_reply(skb, info); - if (err) - return err; - - return 0; - -nla_put_failure: - err = -EIO; - nlmsg_free(skb); - return err; -} - -struct devlink_health_reporter { - struct list_head list; - struct devlink_health_buffer **dump_buffers_array; - struct mutex dump_lock; /* lock parallel read/write from dump buffers */ - struct devlink_health_buffer **diagnose_buffers_array; - struct mutex diagnose_lock; /* lock parallel read/write from diagnose buffers */ - void *priv; - const struct devlink_health_reporter_ops *ops; - struct devlink *devlink; - u64 graceful_period; - bool auto_recover; - u8 health_state; - u8 dump_avail; - u64 dump_ts; - u64 error_count; - u64 recovery_count; - u64 last_recovery_ts; -}; - -enum devlink_health_reporter_state { - DEVLINK_HEALTH_REPORTER_STATE_HEALTHY, - DEVLINK_HEALTH_REPORTER_STATE_ERROR, -}; - -void * -devlink_health_reporter_priv(struct devlink_health_reporter *reporter) -{ - return reporter->priv; -} -EXPORT_SYMBOL_GPL(devlink_health_reporter_priv); - -static struct devlink_health_reporter * -devlink_health_reporter_find_by_name(struct devlink *devlink, - const char *reporter_name) -{ - struct devlink_health_reporter *reporter; - - list_for_each_entry(reporter, &devlink->reporter_list, list) - if (!strcmp(reporter->ops->name, reporter_name)) - return reporter; - return NULL; -} - -/** - * devlink_health_reporter_create - create devlink health reporter - * - * @devlink: devlink - * @ops: ops - * @graceful_period: to avoid recovery loops, in msecs - * @auto_recover: auto recover when error occurs - * @priv: priv - */ -struct devlink_health_reporter * -devlink_health_reporter_create(struct devlink *devlink, - const struct devlink_health_reporter_ops *ops, - u64 graceful_period, bool auto_recover, - void *priv) -{ - struct devlink_health_reporter *reporter; - - mutex_lock(&devlink->lock); - if (devlink_health_reporter_find_by_name(devlink, ops->name)) { - reporter = ERR_PTR(-EEXIST); - goto unlock; - } - - if (WARN_ON(ops->dump && !ops->dump_size) || - WARN_ON(ops->diagnose && !ops->diagnose_size) || - WARN_ON(auto_recover && !ops->recover) || - WARN_ON(graceful_period && !ops->recover)) { - reporter = ERR_PTR(-EINVAL); - goto unlock; - } - - reporter = kzalloc(sizeof(*reporter), GFP_KERNEL); - if (!reporter) { - reporter = ERR_PTR(-ENOMEM); - goto unlock; - } - - if (ops->dump) { - reporter->dump_buffers_array = - devlink_health_buffers_create(ops->dump_size); - if (!reporter->dump_buffers_array) { - kfree(reporter); - reporter = ERR_PTR(-ENOMEM); - goto unlock; - } - } - - if (ops->diagnose) { - reporter->diagnose_buffers_array = - devlink_health_buffers_create(ops->diagnose_size); - if (!reporter->diagnose_buffers_array) { - devlink_health_buffers_destroy(reporter->dump_buffers_array, - DEVLINK_HEALTH_SIZE_TO_BUFFERS(ops->dump_size)); - kfree(reporter); - reporter = ERR_PTR(-ENOMEM); - goto unlock; - } - } - - list_add_tail(&reporter->list, &devlink->reporter_list); - mutex_init(&reporter->dump_lock); - mutex_init(&reporter->diagnose_lock); - - reporter->priv = priv; - reporter->ops = ops; - reporter->devlink = devlink; - reporter->graceful_period = graceful_period; - reporter->auto_recover = auto_recover; -unlock: - mutex_unlock(&devlink->lock); - return reporter; -} -EXPORT_SYMBOL_GPL(devlink_health_reporter_create); - -/** - * devlink_health_reporter_destroy - destroy devlink health reporter - * - * @reporter: devlink health reporter to destroy - */ -void -devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) -{ - mutex_lock(&reporter->devlink->lock); - list_del(&reporter->list); - devlink_health_buffers_destroy(reporter->dump_buffers_array, - DEVLINK_HEALTH_SIZE_TO_BUFFERS(reporter->ops->dump_size)); - devlink_health_buffers_destroy(reporter->diagnose_buffers_array, - DEVLINK_HEALTH_SIZE_TO_BUFFERS(reporter->ops->diagnose_size)); - kfree(reporter); - mutex_unlock(&reporter->devlink->lock); -} -EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy); - -static int -devlink_health_reporter_recover(struct devlink_health_reporter *reporter, - void *priv_ctx) -{ - int err; - - if (!reporter->ops->recover) - return -EOPNOTSUPP; - - err = reporter->ops->recover(reporter, priv_ctx); - if (err) - return err; - - reporter->recovery_count++; - reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY; - reporter->last_recovery_ts = jiffies; - - return 0; -} - -static int devlink_health_do_dump(struct devlink_health_reporter *reporter, - void *priv_ctx) -{ - int err; - - if (!reporter->ops->dump) - return 0; - - if (reporter->dump_avail) - return 0; - - devlink_health_buffers_reset(reporter->dump_buffers_array, - DEVLINK_HEALTH_SIZE_TO_BUFFERS(reporter->ops->dump_size)); - err = reporter->ops->dump(reporter, reporter->dump_buffers_array, - DEVLINK_HEALTH_BUFFER_SIZE, - DEVLINK_HEALTH_SIZE_TO_BUFFERS(reporter->ops->dump_size), - priv_ctx); - if (!err) { - reporter->dump_avail = true; - reporter->dump_ts = jiffies; - } - - return err; -} - -int devlink_health_report(struct devlink_health_reporter *reporter, - const char *msg, void *priv_ctx) -{ - struct devlink *devlink = reporter->devlink; - int err = 0; - - /* write a log message of the current error */ - WARN_ON(!msg); - trace_devlink_health_report(devlink, reporter->ops->name, msg); - reporter->error_count++; - - /* abort if the previous error wasn't recovered */ - if (reporter->auto_recover && - (reporter->health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY || - jiffies - reporter->last_recovery_ts < - msecs_to_jiffies(reporter->graceful_period))) { - trace_devlink_health_recover_aborted(devlink, - reporter->ops->name, - reporter->health_state, - jiffies - - reporter->last_recovery_ts); - return -ECANCELED; - } - - reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR; - - mutex_lock(&reporter->dump_lock); - /* store current dump of current error, for later analysis */ - devlink_health_do_dump(reporter, priv_ctx); - mutex_unlock(&reporter->dump_lock); - - if (reporter->auto_recover) - err = devlink_health_reporter_recover(reporter, priv_ctx); - - return err; -} -EXPORT_SYMBOL_GPL(devlink_health_report); - -static struct devlink_health_reporter * -devlink_health_reporter_get_from_info(struct devlink *devlink, - struct genl_info *info) -{ - char *reporter_name; - - if (!info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]) - return NULL; - - reporter_name = - nla_data(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]); - return devlink_health_reporter_find_by_name(devlink, reporter_name); -} - -static int -devlink_nl_health_reporter_fill(struct sk_buff *msg, - struct devlink *devlink, - struct devlink_health_reporter *reporter, - enum devlink_command cmd, u32 portid, - u32 seq, int flags) -{ - struct nlattr *reporter_attr; - void *hdr; - - hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); - if (!hdr) - return -EMSGSIZE; - - if (devlink_nl_put_handle(msg, devlink)) - goto genlmsg_cancel; - - reporter_attr = nla_nest_start(msg, DEVLINK_ATTR_HEALTH_REPORTER); - if (!reporter_attr) - goto genlmsg_cancel; - if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME, - reporter->ops->name)) - goto reporter_nest_cancel; - if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE, - reporter->health_state)) - goto reporter_nest_cancel; - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR, - reporter->error_count, DEVLINK_ATTR_PAD)) - goto reporter_nest_cancel; - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER, - reporter->recovery_count, DEVLINK_ATTR_PAD)) - goto reporter_nest_cancel; - if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD, - reporter->graceful_period, - DEVLINK_ATTR_PAD)) - goto reporter_nest_cancel; - if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER, - reporter->auto_recover)) - goto reporter_nest_cancel; - if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_AVAIL, - reporter->dump_avail)) - goto reporter_nest_cancel; - if (reporter->dump_avail && - nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS, - jiffies_to_msecs(reporter->dump_ts), - DEVLINK_ATTR_PAD)) - goto reporter_nest_cancel; - - nla_nest_end(msg, reporter_attr); - genlmsg_end(msg, hdr); - return 0; - -reporter_nest_cancel: - nla_nest_end(msg, reporter_attr); -genlmsg_cancel: - genlmsg_cancel(msg, hdr); - return -EMSGSIZE; -} - -static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb, - struct genl_info *info) -{ - struct devlink *devlink = info->user_ptr[0]; - struct devlink_health_reporter *reporter; - struct sk_buff *msg; - int err; - - reporter = devlink_health_reporter_get_from_info(devlink, info); - if (!reporter) - return -EINVAL; - - msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - err = devlink_nl_health_reporter_fill(msg, devlink, reporter, - DEVLINK_CMD_HEALTH_REPORTER_GET, - info->snd_portid, info->snd_seq, - 0); - if (err) { - nlmsg_free(msg); - return err; - } - - return genlmsg_reply(msg, info); -} - -static int -devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg, - struct netlink_callback *cb) -{ - struct devlink_health_reporter *reporter; - struct devlink *devlink; - int start = cb->args[0]; - int idx = 0; - int err; - - mutex_lock(&devlink_mutex); - list_for_each_entry(devlink, &devlink_list, list) { - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) - continue; - mutex_lock(&devlink->lock); - list_for_each_entry(reporter, &devlink->reporter_list, - list) { - if (idx < start) { - idx++; - continue; - } - err = devlink_nl_health_reporter_fill(msg, devlink, - reporter, - DEVLINK_CMD_HEALTH_REPORTER_GET, - NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, - NLM_F_MULTI); - if (err) { - mutex_unlock(&devlink->lock); - goto out; - } - idx++; - } - mutex_unlock(&devlink->lock); - } -out: - mutex_unlock(&devlink_mutex); - - cb->args[0] = idx; - return msg->len; -} - -static int -devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb, - struct genl_info *info) -{ - struct devlink *devlink = info->user_ptr[0]; - struct devlink_health_reporter *reporter; - - reporter = devlink_health_reporter_get_from_info(devlink, info); - if (!reporter) - return -EINVAL; - - if (!reporter->ops->recover && - (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] || - info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) - return -EINVAL; - - if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]) - reporter->graceful_period = - nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]); - - if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]) - reporter->auto_recover = - nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]); - - return 0; -} - -static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb, - struct genl_info *info) -{ - struct devlink *devlink = info->user_ptr[0]; - struct devlink_health_reporter *reporter; - - reporter = devlink_health_reporter_get_from_info(devlink, info); - if (!reporter) - return -EINVAL; - - return devlink_health_reporter_recover(reporter, NULL); -} - -static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb, - struct genl_info *info) -{ - struct devlink *devlink = info->user_ptr[0]; - struct devlink_health_reporter *reporter; - u64 num_of_buffers; - int err; - - reporter = devlink_health_reporter_get_from_info(devlink, info); - if (!reporter) - return -EINVAL; - - if (!reporter->ops->diagnose) - return -EOPNOTSUPP; - - num_of_buffers = - DEVLINK_HEALTH_SIZE_TO_BUFFERS(reporter->ops->diagnose_size); - - mutex_lock(&reporter->diagnose_lock); - devlink_health_buffers_reset(reporter->diagnose_buffers_array, - num_of_buffers); - - err = reporter->ops->diagnose(reporter, - reporter->diagnose_buffers_array, - DEVLINK_HEALTH_BUFFER_SIZE, - num_of_buffers); - if (err) - goto out; - - err = devlink_health_buffer_snd(info, - DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, - 0, reporter->diagnose_buffers_array, - num_of_buffers); - if (err) - goto out; - - mutex_unlock(&reporter->diagnose_lock); - return 0; - -out: - mutex_unlock(&reporter->diagnose_lock); - return err; -} - -static void -devlink_health_dump_clear(struct devlink_health_reporter *reporter) -{ - reporter->dump_avail = false; - reporter->dump_ts = 0; - devlink_health_buffers_reset(reporter->dump_buffers_array, - DEVLINK_HEALTH_SIZE_TO_BUFFERS(reporter->ops->dump_size)); -} - -static int devlink_nl_cmd_health_reporter_dump_get_doit(struct sk_buff *skb, - struct genl_info *info) -{ - struct devlink *devlink = info->user_ptr[0]; - struct devlink_health_reporter *reporter; - u64 num_of_buffers; - int err; - - reporter = devlink_health_reporter_get_from_info(devlink, info); - if (!reporter) - return -EINVAL; - - if (!reporter->ops->dump) - return -EOPNOTSUPP; - - num_of_buffers = - DEVLINK_HEALTH_SIZE_TO_BUFFERS(reporter->ops->dump_size); - - mutex_lock(&reporter->dump_lock); - err = devlink_health_do_dump(reporter, NULL); - if (err) - goto out; - - err = devlink_health_buffer_snd(info, - DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, - 0, reporter->dump_buffers_array, - num_of_buffers); - -out: - mutex_unlock(&reporter->dump_lock); - return err; -} - -static int -devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb, - struct genl_info *info) -{ - struct devlink *devlink = info->user_ptr[0]; - struct devlink_health_reporter *reporter; - - reporter = devlink_health_reporter_get_from_info(devlink, info); - if (!reporter) - return -EINVAL; - - mutex_lock(&reporter->dump_lock); - devlink_health_dump_clear(reporter); - mutex_unlock(&reporter->dump_lock); - return 0; -} - static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, @@ -4631,9 +3622,6 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, - [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING }, - [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 }, - [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 }, }; static const struct genl_ops devlink_nl_ops[] = { @@ -4854,51 +3842,6 @@ static const struct genl_ops devlink_nl_ops[] = { .flags = GENL_ADMIN_PERM, .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, }, - { - .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET, - .doit = devlink_nl_cmd_health_reporter_get_doit, - .dumpit = devlink_nl_cmd_health_reporter_get_dumpit, - .policy = devlink_nl_policy, - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, - /* can be retrieved by unprivileged users */ - }, - { - .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET, - .doit = devlink_nl_cmd_health_reporter_set_doit, - .policy = devlink_nl_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, - }, - { - .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER, - .doit = devlink_nl_cmd_health_reporter_recover_doit, - .policy = devlink_nl_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, - }, - { - .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, - .doit = devlink_nl_cmd_health_reporter_diagnose_doit, - .policy = devlink_nl_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, - }, - { - .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, - .doit = devlink_nl_cmd_health_reporter_dump_get_doit, - .policy = devlink_nl_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | - DEVLINK_NL_FLAG_NO_LOCK, - }, - { - .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, - .doit = devlink_nl_cmd_health_reporter_dump_clear_doit, - .policy = devlink_nl_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | - DEVLINK_NL_FLAG_NO_LOCK, - }, }; static struct genl_family devlink_nl_family __ro_after_init = { @@ -4939,7 +3882,6 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) INIT_LIST_HEAD(&devlink->resource_list); INIT_LIST_HEAD(&devlink->param_list); INIT_LIST_HEAD(&devlink->region_list); - INIT_LIST_HEAD(&devlink->reporter_list); mutex_init(&devlink->lock); return devlink; } -- cgit v1.2.3 From aba1e632c2e810bd685a2c954ebc726e5ca30b2b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 21 Aug 2018 11:21:09 +0100 Subject: iwlwifi: pcie: make array 'prop' static, shrinks object size Don't populate the array prop on the stack but instead make it static. Makes the object code smaller by 30 bytes: Before: text data bss dec hex filename 80138 15382 576 96096 17760 drivers/net/wireless/intel/iwlwifi/pcie/trans.o After: text data bss dec hex filename 79948 15542 576 96066 17742 drivers/net/wireless/intel/iwlwifi/pcie/trans.o (gcc version 8.2.0 x86_64) Signed-off-by: Colin Ian King Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index f97aea5ffc44..dbe62bc3ece4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1968,7 +1968,7 @@ static void iwl_trans_pcie_removal_wk(struct work_struct *wk) struct iwl_trans_pcie_removal *removal = container_of(wk, struct iwl_trans_pcie_removal, work); struct pci_dev *pdev = removal->pdev; - char *prop[] = {"EVENT=INACCESSIBLE", NULL}; + static char *prop[] = {"EVENT=INACCESSIBLE", NULL}; dev_err(&pdev->dev, "Device gone - attempting removal\n"); kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, prop); -- cgit v1.2.3 From d3561e0ecd75a595cb4a477fa4c65fdb51535364 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 13 Sep 2018 14:52:59 +0300 Subject: iwlwifi: wrt: add to dump number of lmacs, lmac1 and umac error id Add to the dump the number of lmacs, the error id of the umac and the error id of lmac1, if supported. In case the reason for the dump trigger is not an assert the error id is zero. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 8 +++++++- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 5 ++++- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 11 +++++++++-- drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 3 ++- drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 13 ++++++++----- 5 files changed, 30 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 2a19b178c5e8..d4d6544f8833 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -828,7 +828,13 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, sizeof(dump_info->dev_human_readable) - 1); strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name, sizeof(dump_info->bus_human_readable) - 1); - dump_info->rt_status = cpu_to_le32(fwrt->dump.rt_status); + dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs; + dump_info->lmac_err_id[0] = + cpu_to_le32(fwrt->dump.lmac_err_id[0]); + if (fwrt->smem_cfg.num_lmacs > 1) + dump_info->lmac_err_id[1] = + cpu_to_le32(fwrt->dump.lmac_err_id[1]); + dump_info->umac_err_id = cpu_to_le32(fwrt->dump.umac_err_id); dump_data = iwl_fw_error_next_data(dump_data); } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 6aabbdd72326..40dcc3deb257 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -102,7 +102,10 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt) if (fwrt->dump.desc != &iwl_dump_desc_assert) kfree(fwrt->dump.desc); fwrt->dump.desc = NULL; - fwrt->dump.rt_status = 0; + fwrt->dump.lmac_err_id[0] = 0; + if (fwrt->smem_cfg.num_lmacs > 1) + fwrt->dump.lmac_err_id[1] = 0; + fwrt->dump.umac_err_id = 0; } void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 65faecf552cd..c02425a1e64f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -180,6 +180,8 @@ enum iwl_fw_error_dump_family { IWL_FW_ERROR_DUMP_FAMILY_8 = 8, }; +#define MAX_NUM_LMAC 2 + /** * struct iwl_fw_error_dump_info - info on the device / firmware * @device_family: the family of the device (7 / 8) @@ -187,7 +189,10 @@ enum iwl_fw_error_dump_family { * @fw_human_readable: human readable FW version * @dev_human_readable: name of the device * @bus_human_readable: name of the bus used - * @rt_status: the error_id/rt_status that that triggered the latest dump + * @num_of_lmacs: the number of lmacs + * @lmac_err_id: the lmac 0/1 error_id/rt_status that triggered the latest dump + * if the dump collection was not initiated by an assert, the value is 0 + * @umac_err_id: the umac error_id/rt_status that triggered the latest dump * if the dump collection was not initiated by an assert, the value is 0 */ struct iwl_fw_error_dump_info { @@ -196,7 +201,9 @@ struct iwl_fw_error_dump_info { u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ]; u8 dev_human_readable[64]; u8 bus_human_readable[8]; - __le32 rt_status; + u8 num_of_lmacs; + __le32 umac_err_id; + __le32 lmac_err_id[MAX_NUM_LMAC]; } __packed; /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 4f7090f88cb0..a0fcbb28114b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -142,7 +142,8 @@ struct iwl_fw_runtime { u32 *d3_debug_data; struct iwl_fw_ini_active_regs active_regs[IWL_FW_INI_MAX_REGION_ID]; struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM]; - u32 rt_status; + u32 lmac_err_id[MAX_NUM_LMAC]; + u32 umac_err_id; } dump; #ifdef CONFIG_IWLWIFI_DEBUGFS struct { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index d116c6ae18ff..e8659bf50890 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -463,6 +463,9 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) iwl_trans_read_mem_bytes(trans, mvm->umac_error_event_table, &table, sizeof(table)); + if (table.valid) + mvm->fwrt.dump.umac_err_id = table.error_id; + if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { IWL_ERR(trans, "Start IWL Error Log Dump:\n"); IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", @@ -486,11 +489,11 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) IWL_ERR(mvm, "0x%08X | isr status reg\n", table.nic_isr_pref); } -static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base) +static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num) { struct iwl_trans *trans = mvm->trans; struct iwl_error_event_table table; - u32 val; + u32 val, base = mvm->error_event_table[lmac_num]; if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) { if (!base) @@ -541,7 +544,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u32 base) iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); if (table.valid) - mvm->fwrt.dump.rt_status = table.error_id; + mvm->fwrt.dump.lmac_err_id[lmac_num] = table.error_id; if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { IWL_ERR(trans, "Start IWL Error Log Dump:\n"); @@ -598,10 +601,10 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) return; } - iwl_mvm_dump_lmac_error_log(mvm, mvm->error_event_table[0]); + iwl_mvm_dump_lmac_error_log(mvm, 0); if (mvm->error_event_table[1]) - iwl_mvm_dump_lmac_error_log(mvm, mvm->error_event_table[1]); + iwl_mvm_dump_lmac_error_log(mvm, 1); iwl_mvm_dump_umac_error_log(mvm); } -- cgit v1.2.3 From 7360f99e0b99e325ae945eb39a3407215403d4d2 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 12 Sep 2018 14:10:56 +0300 Subject: iwlwifi: mvm: advertise support for TWT in the Extended Capability IE We want to advertise support for TWT in the Extended Capability IE. Since we don't want to set the bits for all the interface types, define an interface specific configuration. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 3 +-- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index d9afedc3d1d9..173ade96f119 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -569,8 +569,7 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { .has_he = true, .he_cap_elem = { .mac_cap_info[0] = - IEEE80211_HE_MAC_CAP0_HTC_HE | - IEEE80211_HE_MAC_CAP0_TWT_RES, + IEEE80211_HE_MAC_CAP0_HTC_HE, .mac_cap_info[1] = IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US | IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 97dc464379d2..310a36dd33cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -395,6 +395,21 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm) return ret; } +const static u8 he_if_types_ext_capa_sta[] = { + [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, + [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT, +}; + +const static struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = { + { + .iftype = NL80211_IFTYPE_STATION, + .extended_capabilities = he_if_types_ext_capa_sta, + .extended_capabilities_mask = he_if_types_ext_capa_sta, + .extended_capabilities_len = sizeof(he_if_types_ext_capa_sta), + }, +}; + int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) { struct ieee80211_hw *hw = mvm->hw; @@ -673,6 +688,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE); } + if (mvm->nvm_data->sku_cap_11ax_enable && + !iwlwifi_mod_params.disable_11ax) { + hw->wiphy->iftype_ext_capab = he_iftypes_ext_capa; + hw->wiphy->num_iftype_ext_capab = + ARRAY_SIZE(he_iftypes_ext_capa); + } + mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; #ifdef CONFIG_PM_SLEEP -- cgit v1.2.3 From 866a6a85d4680403a79b347b9e81a35d85f57471 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 12 Sep 2018 16:25:27 +0300 Subject: iwlwifi: mvm: rely on mac80211 to configure TWT support Mac80211 will check both the HE Capability IE and the Extended Capability IE, so set the TWT support bit when mac80211 tells us to. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 7779951a9533..eb66269ddf73 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -778,27 +778,9 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, if (vif->bss_conf.assoc && vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) { - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - u8 sta_id = mvmvif->ap_sta_id; - cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); - if (sta_id != IWL_MVM_INVALID_STA) { - struct ieee80211_sta *sta; - - sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], - lockdep_is_held(&mvm->mutex)); - - /* - * TODO: we should check the ext cap IE but it is - * unclear why the spec requires two bits (one in HE - * cap IE, and one in the ext cap IE). In the meantime - * rely on the HE cap IE only. - */ - if (sta && (sta->he_cap.he_cap_elem.mac_cap_info[0] & - IEEE80211_HE_MAC_CAP0_TWT_RES)) - ctxt_sta->data_policy |= - cpu_to_le32(TWT_SUPPORTED); - } + if (vif->bss_conf.twt_requester) + ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED); } -- cgit v1.2.3 From 8093bb6d4feee04aefaf6abef4179193b54f4b8a Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 25 Sep 2018 11:21:50 +0300 Subject: iwlwifi: add PCI IDs for the 22260 device series Add new structs and PCI IDs for 22260 devices. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 40 +++++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-config.h | 3 ++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 10 +++++++ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 3 +- 4 files changed, 55 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 7e65073834b7..588433da5ab1 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -83,6 +83,7 @@ #define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-" #define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-" #define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-" +#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-" #define IWL_22000_HR_MODULE_FIRMWARE(api) \ IWL_22000_HR_FW_PRE __stringify(api) ".ucode" @@ -104,6 +105,8 @@ IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode" #define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" +#define IWL_CC_A_MODULE_FIRMWARE(api) \ + IWL_CC_A_FW_PRE __stringify(api) ".ucode" static const struct iwl_base_params iwl_22000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, @@ -207,6 +210,42 @@ const struct iwl_cfg iwl22000_2ax_cfg_hr = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, }; +const struct iwl_cfg iwl22260_2ax_cfg = { + .name = "Intel(R) Wireless-AX 22260", + .fw_name_pre = IWL_CC_A_FW_PRE, + IWL_DEVICE_22500, + /* + * This device doesn't support receiving BlockAck with a large bitmap + * so we need to restrict the size of transmitted aggregation to the + * HT size; mac80211 would otherwise pick the HE max (256) by default. + */ + .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, +}; + +const struct iwl_cfg killer1650x_2ax_cfg = { + .name = "Killer(R) Wireless-AX 1650x Wireless Network Adapter (22260NGW)", + .fw_name_pre = IWL_CC_A_FW_PRE, + IWL_DEVICE_22500, + /* + * This device doesn't support receiving BlockAck with a large bitmap + * so we need to restrict the size of transmitted aggregation to the + * HT size; mac80211 would otherwise pick the HE max (256) by default. + */ + .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, +}; + +const struct iwl_cfg killer1650w_2ax_cfg = { + .name = "Killer(R) Wireless-AX 1650w Wireless Network Adapter (22260D2W)", + .fw_name_pre = IWL_CC_A_FW_PRE, + IWL_DEVICE_22500, + /* + * This device doesn't support receiving BlockAck with a large bitmap + * so we need to restrict the size of transmitted aggregation to the + * HT size; mac80211 would otherwise pick the HE max (256) by default. + */ + .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, +}; + /* * All JF radio modules are part of the 9000 series, but the MAC part * looks more like 22000. That's why this device is here, but called @@ -324,3 +363,4 @@ MODULE_FIRMWARE(IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 91861a9cbe57..1261a29f3b40 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -571,6 +571,9 @@ extern const struct iwl_cfg iwl22000_2ac_cfg_hr; extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; extern const struct iwl_cfg iwl22000_2ac_cfg_jf; extern const struct iwl_cfg iwl22000_2ax_cfg_hr; +extern const struct iwl_cfg iwl22260_2ax_cfg; +extern const struct iwl_cfg killer1650x_2ax_cfg; +extern const struct iwl_cfg killer1650w_2ax_cfg; extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0; extern const struct iwl_cfg iwl9462_2ac_cfg_qu_b0_jf_b0; extern const struct iwl_cfg iwl9560_2ac_cfg_qu_b0_jf_b0; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 353581ccc01e..4462133c12ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -898,6 +898,16 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl22000_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x0088, iwl22260_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x008C, iwl22260_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x4080, iwl22260_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x4088, iwl22260_2ax_cfg)}, + + {IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)}, + {IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)}, + #endif /* CONFIG_IWLMVM */ {0} diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index dbe62bc3ece4..fc2f98f2d516 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3602,7 +3602,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, goto out_no_pci; } } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == - CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && + trans->cfg != &iwl22260_2ax_cfg) { u32 hw_status; hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS); -- cgit v1.2.3 From 99be6166a4a0179b3a7e7986ea022136b812f95a Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 2 Oct 2018 11:42:28 +0300 Subject: iwlwifi: pcie: recognize NICs with hw_rev 0x364 correctly Some devices with PCI ID 0x2723, which is supposed to be 22260, are actually not. So we need to differentiate them by checking the hw_rev and change the cfg accordingly. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index caa5806acd81..42af421bbc3c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -325,6 +325,7 @@ enum { #define CSR_HW_REV_TYPE_7265D (0x0000210) #define CSR_HW_REV_TYPE_NONE (0x00001F0) #define CSR_HW_REV_TYPE_QNJ (0x0000360) +#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364) #define CSR_HW_REV_TYPE_HR_CDB (0x0000340) /* RF_ID value */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index fc2f98f2d516..633444d2f930 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3569,6 +3569,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, } } + IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", trans->hw_rev); + /* * 9000-series integrated A-step has a problem with suspend/resume * and sometimes even causes the whole platform to get stuck. This @@ -3603,7 +3605,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, } } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && - trans->cfg != &iwl22260_2ax_cfg) { + (trans->cfg != &iwl22260_2ax_cfg || + trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) { u32 hw_status; hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS); -- cgit v1.2.3 From 7703238ef7e56b96eb0d23e629245b1d56241224 Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Sun, 16 Sep 2018 09:58:15 +0300 Subject: iwlwifi: mvm: fix wrong DCM TLC config When configuring TLC DCM flag: 1. check the peer's RX DCM capabilities (since we TX) 2. do not set DCM_NSS_2 since we do not support it Signed-off-by: Shaul Triebitz Fixes: 423584dd8060 ("iwlwifi: rs-fw: support dcm") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index dabbc04853ac..a0ea0c160fd6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -149,14 +149,9 @@ static u16 rs_fw_set_config_flags(struct iwl_mvm *mvm, if (he_cap && he_cap->has_he && (he_cap->he_cap_elem.phy_cap_info[3] & - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_MASK)) { + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK)) flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK; - if (he_cap->he_cap_elem.phy_cap_info[3] & - IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_2) - flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_2_MSK; - } - return flags; } -- cgit v1.2.3 From a98e2802a654e240d9020546fd29e5632da5f848 Mon Sep 17 00:00:00 2001 From: Ihab Zhaika Date: Sun, 5 Aug 2018 15:05:45 +0300 Subject: iwlwifi: correct one of the PCI struct names One of the cfg struct names is mistakenly "iwl22000", when it should be "iwl22560". Chage-Id: If9fbfa4bceef81d028c90c98d47115fbe39da547 Signed-off-by: Ihab Zhaika Fixes: 2f7a3863191a ("iwlwifi: rename the temporary name of A000 to the official 22000") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 4 +-- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 34 ++++++++++++------------- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 4 +-- 4 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 588433da5ab1..310bef797a43 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -198,8 +198,8 @@ const struct iwl_cfg iwl22000_2ac_cfg_jf = { IWL_DEVICE_22500, }; -const struct iwl_cfg iwl22000_2ax_cfg_hr = { - .name = "Intel(R) Dual Band Wireless AX 22000", +const struct iwl_cfg iwl22560_2ax_cfg_hr = { + .name = "Intel(R) Wireless-AX 22560", .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 1261a29f3b40..6695aa8fbfba 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -570,6 +570,7 @@ extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl22000_2ac_cfg_hr; extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; extern const struct iwl_cfg iwl22000_2ac_cfg_jf; +extern const struct iwl_cfg iwl22560_2ax_cfg_hr; extern const struct iwl_cfg iwl22000_2ax_cfg_hr; extern const struct iwl_cfg iwl22260_2ax_cfg; extern const struct iwl_cfg killer1650x_2ax_cfg; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 4462133c12ba..6694efc6a431 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -871,32 +871,32 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)}, /* 22000 Series */ - {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0040, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0078, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0040, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0078, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0030, iwl22000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x2720, 0x1080, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x1080, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0310, iwl22000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40C0, 0x0310, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)}, - {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl22000_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl22000_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)}, {IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)}, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 633444d2f930..55ccfa22b3c0 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3585,10 +3585,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, #if IS_ENABLED(CONFIG_IWLMVM) trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID); - if (cfg == &iwl22000_2ax_cfg_hr) { + if (cfg == &iwl22560_2ax_cfg_hr) { if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { - trans->cfg = &iwl22000_2ax_cfg_hr; + trans->cfg = &iwl22560_2ax_cfg_hr; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { trans->cfg = &iwl22000_2ax_cfg_jf; -- cgit v1.2.3 From 5b74a9368958d9d424425f6e89b59fed49df6f96 Mon Sep 17 00:00:00 2001 From: Ihab Zhaika Date: Sun, 5 Aug 2018 16:05:25 +0300 Subject: iwlwifi: add new cards for 22560, 9260 and killer series add few PCI ID'S for 22560, 9260 and killer series. Signed-off-by: Ihab Zhaika Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 24 +++++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 ++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 46 +++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 310bef797a43..285e02e1e7b7 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -281,6 +281,30 @@ const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0 = { IWL_DEVICE_22500, }; +const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = { + .name = "Killer(R) Wireless-AX 1650i Wireless Network Adapter (22560NGW)", + .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, + IWL_DEVICE_22500, + /* + * This device doesn't support receiving BlockAck with a large bitmap + * so we need to restrict the size of transmitted aggregation to the + * HT size; mac80211 would otherwise pick the HE max (256) by default. + */ + .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, +}; + +const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = { + .name = "Killer(R) Wireless-AX 1650s Wireless Network Adapter (22560D2W)", + .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, + IWL_DEVICE_22500, + /* + * This device doesn't support receiving BlockAck with a large bitmap + * so we need to restrict the size of transmitted aggregation to the + * HT size; mac80211 would otherwise pick the HE max (256) by default. + */ + .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, +}; + const struct iwl_cfg iwl22000_2ax_cfg_jf = { .name = "Intel(R) Dual Band Wireless AX 22000", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 6695aa8fbfba..e50cf8c88dfd 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -573,6 +573,8 @@ extern const struct iwl_cfg iwl22000_2ac_cfg_jf; extern const struct iwl_cfg iwl22560_2ax_cfg_hr; extern const struct iwl_cfg iwl22000_2ax_cfg_hr; extern const struct iwl_cfg iwl22260_2ax_cfg; +extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0; +extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0; extern const struct iwl_cfg killer1650x_2ax_cfg; extern const struct iwl_cfg killer1650w_2ax_cfg; extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 6694efc6a431..461135f8cef1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -566,6 +566,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0014, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0018, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x001C, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0030, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_cfg)}, @@ -596,12 +597,14 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)}, @@ -871,18 +874,45 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)}, /* 22000 Series */ + {IWL_PCI_DEVICE(0x02F0, 0x0070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x0074, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x007C, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x0310, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x02F0, 0x4070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0074, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x007C, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0310, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x06F0, 0x4070, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0030, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0040, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0078, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x2720, 0x0030, iwl22000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x2720, 0x1080, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0074, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x007C, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0310, iwl22000_2ac_cfg_hr_cdb)}, + {IWL_PCI_DEVICE(0x2720, 0x0A10, iwl22000_2ac_cfg_hr_cdb)}, + {IWL_PCI_DEVICE(0x2720, 0x1080, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x2720, 0x4070, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0074, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x007C, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x4070, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)}, @@ -890,13 +920,23 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x0074, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x007C, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0x43F0, 0x4070, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0074, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x007C, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)}, {IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)}, -- cgit v1.2.3 From 606b9ab67784b02572269d0c76f28bbef9328c6b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 4 Oct 2018 10:41:45 +0300 Subject: iwlwifi: mvm: fix firmware statistics usage The new (CDB) statistics API is used by non-CDB devices as well. Look at the right TLV flag to know which version of the statistics notification to use. To avoid confusion, remove the _cdb suffix from the structure name. While at it, remove a structure that was never used. Signed-off-by: Emmanuel Grumbach Fixes: 678d9b6dddea ("iwlwifi: mvm: update rx statistics cmd api") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/stats.h | 15 +++++---------- drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 10 +++++----- 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h b/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h index 53cb622aa9ab..318843138490 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/stats.h @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -29,6 +30,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -363,14 +365,7 @@ struct mvm_statistics_general_v8 { u8 reserved[4 - (NUM_MAC_INDEX % 4)]; } __packed; /* STATISTICS_GENERAL_API_S_VER_8 */ -struct mvm_statistics_general_cdb_v9 { - struct mvm_statistics_general_common_v19 common; - __le32 beacon_counter[NUM_MAC_INDEX_CDB]; - u8 beacon_average_energy[NUM_MAC_INDEX_CDB]; - u8 reserved[4 - (NUM_MAC_INDEX_CDB % 4)]; -} __packed; /* STATISTICS_GENERAL_API_S_VER_9 */ - -struct mvm_statistics_general_cdb { +struct mvm_statistics_general { struct mvm_statistics_general_common common; __le32 beacon_counter[MAC_INDEX_AUX]; u8 beacon_average_energy[MAC_INDEX_AUX]; @@ -435,11 +430,11 @@ struct iwl_notif_statistics_v11 { struct mvm_statistics_load_v1 load_stats; } __packed; /* STATISTICS_NTFY_API_S_VER_11 */ -struct iwl_notif_statistics_cdb { +struct iwl_notif_statistics { __le32 flag; struct mvm_statistics_rx rx; struct mvm_statistics_tx tx; - struct mvm_statistics_general_cdb general; + struct mvm_statistics_general general; struct mvm_statistics_load load_stats; } __packed; /* STATISTICS_NTFY_API_S_VER_13 */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 6653a238f32e..235ab26ca429 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -599,8 +599,8 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac, * data copied into the "data" struct, but rather the data from * the notification directly. */ - if (iwl_mvm_is_cdb_supported(mvm)) { - struct mvm_statistics_general_cdb *general = + if (iwl_mvm_has_new_rx_stats_api(mvm)) { + struct mvm_statistics_general *general = data->general; mvmvif->beacon_stats.num_beacons = @@ -723,7 +723,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, else expected_size = sizeof(struct iwl_notif_statistics_v10); } else { - expected_size = sizeof(struct iwl_notif_statistics_cdb); + expected_size = sizeof(struct iwl_notif_statistics); } if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) != expected_size, @@ -753,7 +753,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, flags = stats->flag; } else { - struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data; + struct iwl_notif_statistics *stats = (void *)&pkt->data; data.mac_id = stats->rx.general.mac_id; data.beacon_filter_average_energy = @@ -792,7 +792,7 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, bytes = (void *)&v11->load_stats.byte_count; air_time = (void *)&v11->load_stats.air_time; } else { - struct iwl_notif_statistics_cdb *stats = (void *)&pkt->data; + struct iwl_notif_statistics *stats = (void *)&pkt->data; energy = (void *)&stats->load_stats.avg_energy; bytes = (void *)&stats->load_stats.byte_count; -- cgit v1.2.3 From b7226f104cef442635de488cdfa95b715ae4c6d3 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 4 Oct 2018 14:28:02 +0300 Subject: iwlwifi: remove support for 9000 A-step devices We don't support 9000 A-step devices anymore, so we can remove support for loading both the a0/a0 and a0/b0 FWs. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 110 ++++++++---------------- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 6 -- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 27 +++--- 3 files changed, 45 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index f2114137c13f..09618f176f4f 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -73,21 +73,12 @@ #define IWL9000_SMEM_OFFSET 0x400000 #define IWL9000_SMEM_LEN 0x68000 -#define IWL9000A_FW_PRE "iwlwifi-9000-pu-a0-jf-a0-" -#define IWL9000B_FW_PRE "iwlwifi-9000-pu-b0-jf-b0-" -#define IWL9000RFB_FW_PRE "iwlwifi-9000-pu-a0-jf-b0-" -#define IWL9260A_FW_PRE "iwlwifi-9260-th-a0-jf-a0-" -#define IWL9260B_FW_PRE "iwlwifi-9260-th-b0-jf-b0-" -#define IWL9000A_MODULE_FIRMWARE(api) \ - IWL9000A_FW_PRE __stringify(api) ".ucode" -#define IWL9000B_MODULE_FIRMWARE(api) \ - IWL9000B_FW_PRE __stringify(api) ".ucode" -#define IWL9000RFB_MODULE_FIRMWARE(api) \ - IWL9000RFB_FW_PRE __stringify(api) ".ucode" -#define IWL9260A_MODULE_FIRMWARE(api) \ - IWL9260A_FW_PRE __stringify(api) ".ucode" -#define IWL9260B_MODULE_FIRMWARE(api) \ - IWL9260B_FW_PRE __stringify(api) ".ucode" +#define IWL9000_FW_PRE "iwlwifi-9000-pu-b0-jf-b0-" +#define IWL9260_FW_PRE "iwlwifi-9260-th-b0-jf-b0-" +#define IWL9000_MODULE_FIRMWARE(api) \ + IWL9000_FW_PRE __stringify(api) ".ucode" +#define IWL9260_MODULE_FIRMWARE(api) \ + IWL9260_FW_PRE __stringify(api) ".ucode" static const struct iwl_base_params iwl9000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, @@ -162,81 +153,67 @@ static const struct iwl_tt_params iwl9000_tt_params = { const struct iwl_cfg iwl9160_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9160", - .fw_name_pre = IWL9260A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE, + .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; const struct iwl_cfg iwl9260_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9260", - .fw_name_pre = IWL9260A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE, + .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; const struct iwl_cfg iwl9260_killer_2ac_cfg = { .name = "Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW)", - .fw_name_pre = IWL9260A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE, + .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; const struct iwl_cfg iwl9270_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9270", - .fw_name_pre = IWL9260A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE, + .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; const struct iwl_cfg iwl9460_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9460", - .fw_name_pre = IWL9260A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE, + .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; const struct iwl_cfg iwl9460_2ac_cfg_soc = { .name = "Intel(R) Dual Band Wireless AC 9460", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, }; const struct iwl_cfg iwl9461_2ac_cfg_soc = { - .name = "Intel(R) Dual Band Wireless AC 9461", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, + .name = "Intel(R) Dual Band Wireless AC 9461", + .fw_name_pre = IWL9000_FW_PRE, + IWL_DEVICE_9000, + .integrated = true, + .soc_latency = 5000, }; const struct iwl_cfg iwl9462_2ac_cfg_soc = { - .name = "Intel(R) Dual Band Wireless AC 9462", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, - IWL_DEVICE_9000, - .integrated = true, - .soc_latency = 5000, + .name = "Intel(R) Dual Band Wireless AC 9462", + .fw_name_pre = IWL9000_FW_PRE, + IWL_DEVICE_9000, + .integrated = true, + .soc_latency = 5000, }; const struct iwl_cfg iwl9560_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9560", - .fw_name_pre = IWL9260A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9260B_FW_PRE, + .fw_name_pre = IWL9260_FW_PRE, IWL_DEVICE_9000, }; const struct iwl_cfg iwl9560_2ac_cfg_soc = { .name = "Intel(R) Dual Band Wireless AC 9560", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, @@ -244,9 +221,7 @@ const struct iwl_cfg iwl9560_2ac_cfg_soc = { const struct iwl_cfg iwl9560_killer_2ac_cfg_soc = { .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, @@ -254,9 +229,7 @@ const struct iwl_cfg iwl9560_killer_2ac_cfg_soc = { const struct iwl_cfg iwl9560_killer_s_2ac_cfg_soc = { .name = "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, @@ -264,9 +237,7 @@ const struct iwl_cfg iwl9560_killer_s_2ac_cfg_soc = { const struct iwl_cfg iwl9460_2ac_cfg_shared_clk = { .name = "Intel(R) Dual Band Wireless AC 9460", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, @@ -275,9 +246,7 @@ const struct iwl_cfg iwl9460_2ac_cfg_shared_clk = { const struct iwl_cfg iwl9461_2ac_cfg_shared_clk = { .name = "Intel(R) Dual Band Wireless AC 9461", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, @@ -286,9 +255,7 @@ const struct iwl_cfg iwl9461_2ac_cfg_shared_clk = { const struct iwl_cfg iwl9462_2ac_cfg_shared_clk = { .name = "Intel(R) Dual Band Wireless AC 9462", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, @@ -297,9 +264,7 @@ const struct iwl_cfg iwl9462_2ac_cfg_shared_clk = { const struct iwl_cfg iwl9560_2ac_cfg_shared_clk = { .name = "Intel(R) Dual Band Wireless AC 9560", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, @@ -308,9 +273,7 @@ const struct iwl_cfg iwl9560_2ac_cfg_shared_clk = { const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk = { .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, @@ -319,17 +282,12 @@ const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk = { const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk = { .name = "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)", - .fw_name_pre = IWL9000A_FW_PRE, - .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, - .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + .fw_name_pre = IWL9000_FW_PRE, IWL_DEVICE_9000, .integrated = true, .soc_latency = 5000, .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK }; -MODULE_FIRMWARE(IWL9000A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL9000B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL9000RFB_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL9260A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL9260B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL9260_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index e50cf8c88dfd..7698cadd4ff9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -335,10 +335,6 @@ struct iwl_csr_params { * @fw_name_pre: Firmware filename prefix. The api version and extension * (.ucode) will be added to filename before loading from disk. The * filename is constructed as fw_name_pre.ucode. - * @fw_name_pre_b_or_c_step: same as @fw_name_pre, only for b or c steps - * (if supported) - * @fw_name_pre_rf_next_step: same as @fw_name_pre_b_or_c_step, only for rf - * next step. Supported only in integrated solutions. * @ucode_api_max: Highest version of uCode API supported by driver. * @ucode_api_min: Lowest version of uCode API supported by driver. * @max_inst_size: The maximal length of the fw inst section (only DVM) @@ -392,8 +388,6 @@ struct iwl_cfg { /* params specific to an individual device within a device family */ const char *name; const char *fw_name_pre; - const char *fw_name_pre_b_or_c_step; - const char *fw_name_pre_rf_next_step; /* params not likely to change within a device family */ const struct iwl_base_params *base_params; /* params likely to change within a device family */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index bf1be985f36b..2efa1dfe9b4c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -210,18 +210,15 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) { const struct iwl_cfg *cfg = drv->trans->cfg; char tag[8]; - const char *fw_pre_name; if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_9000 && - (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_B_STEP || - CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_C_STEP)) - fw_pre_name = cfg->fw_name_pre_b_or_c_step; - else if (drv->trans->cfg->integrated && - CSR_HW_RFID_STEP(drv->trans->hw_rf_id) == SILICON_B_STEP && - cfg->fw_name_pre_rf_next_step) - fw_pre_name = cfg->fw_name_pre_rf_next_step; - else - fw_pre_name = cfg->fw_name_pre; + (CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_B_STEP && + CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_C_STEP)) { + IWL_ERR(drv, + "Only HW steps B and C are currently supported (0x%0x)\n", + drv->trans->hw_rev); + return -EINVAL; + } if (first) { drv->fw_index = cfg->ucode_api_max; @@ -235,15 +232,13 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) IWL_ERR(drv, "no suitable firmware found!\n"); if (cfg->ucode_api_min == cfg->ucode_api_max) { - IWL_ERR(drv, "%s%d is required\n", fw_pre_name, + IWL_ERR(drv, "%s%d is required\n", cfg->fw_name_pre, cfg->ucode_api_max); } else { IWL_ERR(drv, "minimum version required: %s%d\n", - fw_pre_name, - cfg->ucode_api_min); + cfg->fw_name_pre, cfg->ucode_api_min); IWL_ERR(drv, "maximum version supported: %s%d\n", - fw_pre_name, - cfg->ucode_api_max); + cfg->fw_name_pre, cfg->ucode_api_max); } IWL_ERR(drv, @@ -252,7 +247,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) } snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%s.ucode", - fw_pre_name, tag); + cfg->fw_name_pre, tag); IWL_DEBUG_INFO(drv, "attempting to load firmware '%s'\n", drv->firmware_name); -- cgit v1.2.3 From c688e3964a43c85ed27137c9df75072991140922 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 4 Oct 2018 15:20:38 +0300 Subject: iwlwifi: pcie: remove unnecessary iwl_pcie_enable_rx_wake() function This function was only used by 9000 A-step devices, which we don't support anymore, so it can be removed. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 2 -- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 26 ---------------------- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 4 ---- 3 files changed, 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index d6fc6ce73e0a..971785b17e09 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1029,8 +1029,6 @@ static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans); int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans); -void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable); - void iwl_pcie_rx_allocator_work(struct work_struct *data); /* common functions that are used by gen2 transport */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index e965cc588850..541da1d44762 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -868,30 +868,6 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); } -void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable) -{ - if (trans->cfg->device_family != IWL_DEVICE_FAMILY_9000) - return; - - if (CSR_HW_REV_STEP(trans->hw_rev) != SILICON_A_STEP) - return; - - if (!trans->cfg->integrated) - return; - - /* - * Turn on the chicken-bits that cause MAC wakeup for RX-related - * values. - * This costs some power, but needed for W/A 9000 integrated A-step - * bug where shadow registers are not in the retention list and their - * value is lost when NIC powers down - */ - iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, - CSR_MAC_SHADOW_REG_CTRL_RX_WAKE); - iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTL2, - CSR_MAC_SHADOW_REG_CTL2_RX_WAKE); -} - static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -979,8 +955,6 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) /* Set interrupt coalescing timer to default (2048 usecs) */ iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); - - iwl_pcie_enable_rx_wake(trans, true); } void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 55ccfa22b3c0..40e59e701273 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1530,8 +1530,6 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, iwl_clear_bit(trans, CSR_GP_CNTRL, BIT(trans->cfg->csr->flag_init_done)); - iwl_pcie_enable_rx_wake(trans, false); - if (reset) { /* * reset TX queues -- some of their registers reset during S3 @@ -1558,8 +1556,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, return 0; } - iwl_pcie_enable_rx_wake(trans, true); - iwl_set_bit(trans, CSR_GP_CNTRL, BIT(trans->cfg->csr->flag_mac_access_req)); iwl_set_bit(trans, CSR_GP_CNTRL, -- cgit v1.2.3 From 1122135df03664a4aa0f5129bc5d9c9f30b90f17 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 4 Oct 2018 15:23:37 +0300 Subject: iwlwifi: pcie: remove suspend/resume workaround for 9000A devices We don't support 9000 A-step devices anymore, so we can remove the suspend/resume workaround. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 40e59e701273..e72bd9796b5b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3567,17 +3567,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", trans->hw_rev); - /* - * 9000-series integrated A-step has a problem with suspend/resume - * and sometimes even causes the whole platform to get stuck. This - * workaround makes the hardware not go into the problematic state. - */ - if (trans->cfg->integrated && - trans->cfg->device_family == IWL_DEVICE_FAMILY_9000 && - CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP) - iwl_set_bit(trans, CSR_HOST_CHICKEN, - CSR_HOST_CHICKEN_PM_IDLE_SRC_DIS_SB_PME); - #if IS_ENABLED(CONFIG_IWLMVM) trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID); -- cgit v1.2.3 From 7e08baeb3c6d57b333a08306875a5cd49b4d95b5 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 2 Oct 2018 14:13:48 +0300 Subject: iwlwifi: wrt: add 22000 device familiy prph dump support Add prph dump addresses to support prph dump in 22000 HW. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 168 ++++++++++++++++++++++------ 1 file changed, 131 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index d4d6544f8833..5f16879ab26a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -469,6 +469,93 @@ static const struct iwl_prph_range iwl_prph_dump_addr_9000[] = { { .start = 0x00a02400, .end = 0x00a02758 }, }; +static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = { + { .start = 0x00a00000, .end = 0x00a00000 }, + { .start = 0x00a0000c, .end = 0x00a00024 }, + { .start = 0x00a0002c, .end = 0x00a00034 }, + { .start = 0x00a0003c, .end = 0x00a0003c }, + { .start = 0x00a00410, .end = 0x00a00418 }, + { .start = 0x00a00420, .end = 0x00a00420 }, + { .start = 0x00a00428, .end = 0x00a00428 }, + { .start = 0x00a00430, .end = 0x00a0043c }, + { .start = 0x00a00444, .end = 0x00a00444 }, + { .start = 0x00a00840, .end = 0x00a00840 }, + { .start = 0x00a00850, .end = 0x00a00858 }, + { .start = 0x00a01004, .end = 0x00a01008 }, + { .start = 0x00a01010, .end = 0x00a01010 }, + { .start = 0x00a01018, .end = 0x00a01018 }, + { .start = 0x00a01024, .end = 0x00a01024 }, + { .start = 0x00a0102c, .end = 0x00a01034 }, + { .start = 0x00a0103c, .end = 0x00a01040 }, + { .start = 0x00a01048, .end = 0x00a01050 }, + { .start = 0x00a01058, .end = 0x00a01058 }, + { .start = 0x00a01060, .end = 0x00a01070 }, + { .start = 0x00a0108c, .end = 0x00a0108c }, + { .start = 0x00a01c20, .end = 0x00a01c28 }, + { .start = 0x00a01d10, .end = 0x00a01d10 }, + { .start = 0x00a01e28, .end = 0x00a01e2c }, + { .start = 0x00a01e60, .end = 0x00a01e60 }, + { .start = 0x00a01e80, .end = 0x00a01e80 }, + { .start = 0x00a01ea0, .end = 0x00a01ea0 }, + { .start = 0x00a02000, .end = 0x00a0201c }, + { .start = 0x00a02024, .end = 0x00a02024 }, + { .start = 0x00a02040, .end = 0x00a02048 }, + { .start = 0x00a020c0, .end = 0x00a020e0 }, + { .start = 0x00a02400, .end = 0x00a02404 }, + { .start = 0x00a0240c, .end = 0x00a02414 }, + { .start = 0x00a0241c, .end = 0x00a0243c }, + { .start = 0x00a02448, .end = 0x00a024bc }, + { .start = 0x00a024c4, .end = 0x00a024cc }, + { .start = 0x00a02508, .end = 0x00a02508 }, + { .start = 0x00a02510, .end = 0x00a02514 }, + { .start = 0x00a0251c, .end = 0x00a0251c }, + { .start = 0x00a0252c, .end = 0x00a0255c }, + { .start = 0x00a02564, .end = 0x00a025a0 }, + { .start = 0x00a025a8, .end = 0x00a025b4 }, + { .start = 0x00a025c0, .end = 0x00a025c0 }, + { .start = 0x00a025e8, .end = 0x00a025f4 }, + { .start = 0x00a02c08, .end = 0x00a02c18 }, + { .start = 0x00a02c2c, .end = 0x00a02c38 }, + { .start = 0x00a02c68, .end = 0x00a02c78 }, + { .start = 0x00a03000, .end = 0x00a03000 }, + { .start = 0x00a03010, .end = 0x00a03014 }, + { .start = 0x00a0301c, .end = 0x00a0302c }, + { .start = 0x00a03034, .end = 0x00a03038 }, + { .start = 0x00a03040, .end = 0x00a03044 }, + { .start = 0x00a03060, .end = 0x00a03068 }, + { .start = 0x00a03070, .end = 0x00a03070 }, + { .start = 0x00a0307c, .end = 0x00a03084 }, + { .start = 0x00a0308c, .end = 0x00a03090 }, + { .start = 0x00a03098, .end = 0x00a03098 }, + { .start = 0x00a030a0, .end = 0x00a030a0 }, + { .start = 0x00a030a8, .end = 0x00a030b4 }, + { .start = 0x00a030bc, .end = 0x00a030c0 }, + { .start = 0x00a030c8, .end = 0x00a030f4 }, + { .start = 0x00a03100, .end = 0x00a0312c }, + { .start = 0x00a03c00, .end = 0x00a03c5c }, + { .start = 0x00a04400, .end = 0x00a04454 }, + { .start = 0x00a04460, .end = 0x00a04474 }, + { .start = 0x00a044c0, .end = 0x00a044ec }, + { .start = 0x00a04500, .end = 0x00a04504 }, + { .start = 0x00a04510, .end = 0x00a04538 }, + { .start = 0x00a04540, .end = 0x00a04548 }, + { .start = 0x00a04560, .end = 0x00a04560 }, + { .start = 0x00a04570, .end = 0x00a0457c }, + { .start = 0x00a04590, .end = 0x00a04590 }, + { .start = 0x00a04598, .end = 0x00a04598 }, + { .start = 0x00a045c0, .end = 0x00a045f4 }, + { .start = 0x00a0c000, .end = 0x00a0c018 }, + { .start = 0x00a0c020, .end = 0x00a0c028 }, + { .start = 0x00a0c038, .end = 0x00a0c094 }, + { .start = 0x00a0c0c0, .end = 0x00a0c104 }, + { .start = 0x00a0c10c, .end = 0x00a0c118 }, + { .start = 0x00a0c150, .end = 0x00a0c174 }, + { .start = 0x00a0c17c, .end = 0x00a0c188 }, + { .start = 0x00a0c190, .end = 0x00a0c198 }, + { .start = 0x00a0c1a0, .end = 0x00a0c1a8 }, + { .start = 0x00a0c1b0, .end = 0x00a0c1b8 }, +}; + static void iwl_read_prph_block(struct iwl_trans *trans, u32 start, u32 len_bytes, __le32 *data) { @@ -478,15 +565,20 @@ static void iwl_read_prph_block(struct iwl_trans *trans, u32 start, *data++ = cpu_to_le32(iwl_read_prph_no_grab(trans, start + i)); } -static void iwl_dump_prph(struct iwl_trans *trans, - struct iwl_fw_error_dump_data **data, +static void iwl_dump_prph(struct iwl_fw_runtime *fwrt, const struct iwl_prph_range *iwl_prph_dump_addr, - u32 range_len) + u32 range_len, void *ptr) { struct iwl_fw_error_dump_prph *prph; + struct iwl_trans *trans = fwrt->trans; + struct iwl_fw_error_dump_data **data = + (struct iwl_fw_error_dump_data **)ptr; unsigned long flags; u32 i; + if (!data) + return; + IWL_DEBUG_INFO(trans, "WRT PRPH dump\n"); if (!iwl_trans_grab_nic_access(trans, &flags)) @@ -552,37 +644,47 @@ static struct scatterlist *alloc_sgtable(int size) return table; } -static int iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt) +static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt, + const struct iwl_prph_range *iwl_prph_dump_addr, + u32 range_len, void *ptr) { - u32 prph_len = 0; - int i; + u32 *prph_len = (u32 *)ptr; + int i, num_bytes_in_chunk; + + if (!prph_len) + return; - for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm); - i++) { + for (i = 0; i < range_len; i++) { /* The range includes both boundaries */ - int num_bytes_in_chunk = - iwl_prph_dump_addr_comm[i].end - - iwl_prph_dump_addr_comm[i].start + 4; + num_bytes_in_chunk = + iwl_prph_dump_addr[i].end - + iwl_prph_dump_addr[i].start + 4; - prph_len += sizeof(struct iwl_fw_error_dump_data) + + *prph_len += sizeof(struct iwl_fw_error_dump_data) + sizeof(struct iwl_fw_error_dump_prph) + num_bytes_in_chunk; } +} - if (fwrt->trans->cfg->mq_rx_supported) { - for (i = 0; i < - ARRAY_SIZE(iwl_prph_dump_addr_9000); i++) { - /* The range includes both boundaries */ - int num_bytes_in_chunk = - iwl_prph_dump_addr_9000[i].end - - iwl_prph_dump_addr_9000[i].start + 4; - - prph_len += sizeof(struct iwl_fw_error_dump_data) + - sizeof(struct iwl_fw_error_dump_prph) + - num_bytes_in_chunk; +static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr, + void (*handler)(struct iwl_fw_runtime *, + const struct iwl_prph_range *, + u32, void *)) +{ + u32 range_len; + + if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) { + range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000); + handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr); + } else { + range_len = ARRAY_SIZE(iwl_prph_dump_addr_comm); + handler(fwrt, iwl_prph_dump_addr_comm, range_len, ptr); + + if (fwrt->trans->cfg->mq_rx_supported) { + range_len = ARRAY_SIZE(iwl_prph_dump_addr_9000); + handler(fwrt, iwl_prph_dump_addr_9000, range_len, ptr); } } - return prph_len; } static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt, @@ -747,9 +849,9 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, fifo_len += iwl_fw_txf_len(fwrt, mem_cfg); /* Make room for PRPH registers */ - if (!fwrt->trans->cfg->gen2 && - iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PRPH)) - prph_len += iwl_fw_get_prph_len(fwrt); + if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PRPH)) + iwl_fw_prph_handler(fwrt, &prph_len, + iwl_fw_get_prph_len); if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 && iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_RADIO_REG)) @@ -941,16 +1043,8 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, if (iwl_fw_dbg_is_paging_enabled(fwrt)) iwl_dump_paging(fwrt, &dump_data); - if (prph_len) { - iwl_dump_prph(fwrt->trans, &dump_data, - iwl_prph_dump_addr_comm, - ARRAY_SIZE(iwl_prph_dump_addr_comm)); - - if (fwrt->trans->cfg->mq_rx_supported) - iwl_dump_prph(fwrt->trans, &dump_data, - iwl_prph_dump_addr_9000, - ARRAY_SIZE(iwl_prph_dump_addr_9000)); - } + if (prph_len) + iwl_fw_prph_handler(fwrt, &dump_data, iwl_dump_prph); out: dump_file->file_len = cpu_to_le32(file_len); -- cgit v1.2.3 From c281f13792f64372f49b63eab4c1ce88282448d2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Oct 2018 09:35:00 +0200 Subject: iwlwifi: mvm: make NVM access actually fail on failures On any failure, including if we crash the firmware or get garbage data, we currently ignore this and pretend the OTP was empty. Clearly, this isn't typically the case. In cases other than the firmware saying it can't read the requested section, or the section having ended, make the access actually fail and trickle the error up through the layers to fail init. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index 6fc5cc1f2b5b..f08934b03cf3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -179,7 +179,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM access command failed with status %d (device: %s)\n", ret, mvm->cfg->name); - ret = -EIO; + ret = -ENODATA; } goto exit; } @@ -380,8 +380,12 @@ int iwl_nvm_init(struct iwl_mvm *mvm) /* we override the constness for initial read */ ret = iwl_nvm_read_section(mvm, section, nvm_buffer, size_read); - if (ret < 0) + if (ret == -ENODATA) { + ret = 0; continue; + } + if (ret < 0) + break; size_read += ret; temp = kmemdup(nvm_buffer, ret, GFP_KERNEL); if (!temp) { @@ -454,7 +458,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm) IWL_DEBUG_EEPROM(mvm->trans->dev, "nvm version = %x\n", mvm->nvm_data->nvm_version); - return 0; + return ret < 0 ? ret : 0; } struct iwl_mcc_update_resp * -- cgit v1.2.3 From cfbc6c4c5b91c7725ef14465b98ac347d31f2334 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 21 Aug 2018 15:23:39 +0300 Subject: iwlwifi: mvm: support mac80211 TXQs model Move to use the new mac80211 TXQs implementation. This has quite a few benefits for us. We can get rid of the awkward mapping of DQA to mac80211 queues. We can stop buffering traffic while waiting for the queue to be allocated. We can also use mac80211 AMSDUs instead of building it ourselves. The usage is pretty simple: Each ieee80211_txq contains iwl_mvm_txq. There is such a queue for each TID, and one for management frames. We keep having static AP queues for probes and non-bufferable MMPDUs, along with broadcast and multicast queues. Those are being used from the "old" TX invocation path - iwl_mvm_mac_tx. When there is a new frame in a TXQ, iwl_mvm_mac_wake_tx is being called, and either invokes the TX path, or allocates the queue if it does not exist. Most of the TX path is left untouched, although we can consider cleaning it up some more, for example get rid of the duplication of txq_id in both iwl_mvm_txq and iwl_mvm_dqa_txq_info. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 8 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 5 +- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 72 +---- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 113 +++++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 54 +++- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 87 +++--- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 360 +++++++++------------- drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 4 - drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 71 +---- 9 files changed, 331 insertions(+), 443 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 01b5338201d6..36ed7d6fc971 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2125,7 +2125,6 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) file->private_data = inode->i_private; - ieee80211_stop_queues(mvm->hw); synchronize_net(); mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; @@ -2140,10 +2139,9 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) rtnl_unlock(); if (err > 0) err = -EINVAL; - if (err) { - ieee80211_wake_queues(mvm->hw); + if (err) return err; - } + mvm->d3_test_active = true; mvm->keep_vif = NULL; return 0; @@ -2223,8 +2221,6 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) mvm->hw, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif); - ieee80211_wake_queues(mvm->hw); - return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 0d6c313b6669..27582d70d45a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -295,7 +295,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, struct iwl_notification_wait alive_wait; struct iwl_mvm_alive_data alive_data; const struct fw_img *fw; - int ret, i; + int ret; enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img; static const u16 alive_cmd[] = { MVM_ALIVE }; @@ -373,9 +373,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, mvm->queue_info[IWL_MVM_DQA_CMD_QUEUE].tid_bitmap = BIT(IWL_MAX_TID_COUNT + 2); - for (i = 0; i < IEEE80211_MAX_QUEUES; i++) - atomic_set(&mvm->mac80211_queue_stop_count[i], 0); - set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); #ifdef CONFIG_IWLWIFI_DEBUGFS iwl_fw_set_dbg_rec_on(&mvm->fwrt); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index eb66269ddf73..a79c79701cc4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -97,11 +97,6 @@ struct iwl_mvm_mac_iface_iterator_data { bool found_vif; }; -struct iwl_mvm_hw_queues_iface_iterator_data { - struct ieee80211_vif *exclude_vif; - unsigned long used_hw_queues; -}; - static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { @@ -208,61 +203,6 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac, data->preferred_tsf = NUM_TSF_IDS; } -/* - * Get the mask of the queues used by the vif - */ -u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif) -{ - u32 qmask = 0, ac; - - if (vif->type == NL80211_IFTYPE_P2P_DEVICE) - return BIT(IWL_MVM_OFFCHANNEL_QUEUE); - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - if (vif->hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE) - qmask |= BIT(vif->hw_queue[ac]); - } - - if (vif->type == NL80211_IFTYPE_AP || - vif->type == NL80211_IFTYPE_ADHOC) - qmask |= BIT(vif->cab_queue); - - return qmask; -} - -static void iwl_mvm_iface_hw_queues_iter(void *_data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct iwl_mvm_hw_queues_iface_iterator_data *data = _data; - - /* exclude the given vif */ - if (vif == data->exclude_vif) - return; - - data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif); -} - -unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, - struct ieee80211_vif *exclude_vif) -{ - struct iwl_mvm_hw_queues_iface_iterator_data data = { - .exclude_vif = exclude_vif, - .used_hw_queues = - BIT(IWL_MVM_OFFCHANNEL_QUEUE) | - BIT(mvm->aux_queue) | - BIT(IWL_MVM_DQA_GCAST_QUEUE), - }; - - lockdep_assert_held(&mvm->mutex); - - /* mark all VIF used hw queues */ - ieee80211_iterate_active_interfaces_atomic( - mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, - iwl_mvm_iface_hw_queues_iter, &data); - - return data.used_hw_queues; -} - static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, struct ieee80211_vif *vif) { @@ -360,8 +300,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, iwl_mvm_mac_iface_iterator, &data); - used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, vif); - /* * In the case we're getting here during resume, it's similar to * firmware restart, and with RESUME_ALL the iterator will find @@ -416,9 +354,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) * the ones here - no real limit */ queue_limit = IEEE80211_MAX_QUEUES; - BUILD_BUG_ON(IEEE80211_MAX_QUEUES > - BITS_PER_BYTE * - sizeof(mvm->hw_queue_to_mac80211[0])); /* * Find available queues, and allocate them to the ACs. When in @@ -446,9 +381,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) * queue value (when queue is enabled). */ mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; - vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; - } else { - vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; } mvmvif->bcast_sta.sta_id = IWL_MVM_INVALID_STA; @@ -462,8 +394,6 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) exit_fail: memset(mvmvif, 0, sizeof(struct iwl_mvm_vif)); - memset(vif->hw_queue, IEEE80211_INVAL_HW_QUEUE, sizeof(vif->hw_queue)); - vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; return ret; } @@ -1185,7 +1115,7 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) - ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue); + ctxt_ap->mcast_qid = cpu_to_le32(mvmvif->cab_queue); /* * Only set the beacon time when the MAC is being added, when we diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 310a36dd33cf..58bb92b0ef05 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -425,7 +425,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ieee80211_hw_set(hw, SIGNAL_DBM); ieee80211_hw_set(hw, SPECTRUM_MGMT); ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); - ieee80211_hw_set(hw, QUEUE_CONTROL); ieee80211_hw_set(hw, WANT_MONITOR_VIF); ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); @@ -439,6 +438,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); ieee80211_hw_set(hw, DEAUTH_NEED_MGD_TX_PREP); ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); + ieee80211_hw_set(hw, BUFF_MMPDU_TXQ); + ieee80211_hw_set(hw, STA_MMPDU_TXQ); if (iwl_mvm_has_tlc_offload(mvm)) { ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW); @@ -549,6 +550,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->sta_data_size = sizeof(struct iwl_mvm_sta); hw->vif_data_size = sizeof(struct iwl_mvm_vif); hw->chanctx_data_size = sizeof(u16); + hw->txq_data_size = sizeof(struct iwl_mvm_txq); hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_P2P_CLIENT) | @@ -798,7 +800,6 @@ static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm, goto out; __skb_queue_tail(&mvm->d0i3_tx, skb); - ieee80211_stop_queues(mvm->hw); /* trigger wakeup */ iwl_mvm_ref(mvm, IWL_MVM_REF_TX); @@ -818,13 +819,15 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, struct ieee80211_sta *sta = control->sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (void *)skb->data; + bool offchannel = IEEE80211_SKB_CB(skb)->flags & + IEEE80211_TX_CTL_TX_OFFCHAN; if (iwl_mvm_is_radio_killed(mvm)) { IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n"); goto drop; } - if (info->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && + if (offchannel && !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) && !test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status)) goto drop; @@ -837,8 +840,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, sta = NULL; /* If there is no sta, and it's not offchannel - send through AP */ - if (info->control.vif->type == NL80211_IFTYPE_STATION && - info->hw_queue != IWL_MVM_OFFCHANNEL_QUEUE && !sta) { + if (!sta && info->control.vif->type == NL80211_IFTYPE_STATION && + !offchannel) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(info->control.vif); u8 ap_sta_id = READ_ONCE(mvmvif->ap_sta_id); @@ -866,6 +869,77 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, ieee80211_free_txskb(hw, skb); } +void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq); + struct sk_buff *skb = NULL; + + spin_lock(&mvmtxq->tx_path_lock); + + rcu_read_lock(); + while (likely(!mvmtxq->stopped && + (mvm->trans->system_pm_mode == + IWL_PLAT_PM_MODE_DISABLED))) { + skb = ieee80211_tx_dequeue(hw, txq); + + if (!skb) + break; + + if (!txq->sta) + iwl_mvm_tx_skb_non_sta(mvm, skb); + else + iwl_mvm_tx_skb(mvm, skb, txq->sta); + } + rcu_read_unlock(); + + spin_unlock(&mvmtxq->tx_path_lock); +} + +static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw, + struct ieee80211_txq *txq) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq); + + /* + * Please note that racing is handled very carefully here: + * mvmtxq->txq_id is updated during allocation, and mvmtxq->list is + * deleted afterwards. + * This means that if: + * mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list): + * queue is allocated and we can TX. + * mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list): + * a race, should defer the frame. + * mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list): + * need to allocate the queue and defer the frame. + * mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list): + * queue is already scheduled for allocation, no need to allocate, + * should defer the frame. + */ + + /* If the queue is allocated TX and return. */ + if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) { + /* + * Check that list is empty to avoid a race where txq_id is + * already updated, but the queue allocation work wasn't + * finished + */ + if (unlikely(txq->sta && !list_empty(&mvmtxq->list))) + return; + + iwl_mvm_mac_itxq_xmit(hw, txq); + return; + } + + /* The list is being deleted only after the queue is fully allocated. */ + if (!list_empty(&mvmtxq->list)) + return; + + list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs); + schedule_work(&mvm->add_stream_wk); +} + static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg) { if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) @@ -1107,7 +1181,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) iwl_mvm_reset_phy_ctxts(mvm); memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); - memset(mvm->sta_deferred_frames, 0, sizeof(mvm->sta_deferred_frames)); memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); @@ -2883,32 +2956,6 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm, peer_addr, action); } -static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm, - struct iwl_mvm_sta *mvm_sta) -{ - struct iwl_mvm_tid_data *tid_data; - struct sk_buff *skb; - int i; - - spin_lock_bh(&mvm_sta->lock); - for (i = 0; i <= IWL_MAX_TID_COUNT; i++) { - tid_data = &mvm_sta->tid_data[i]; - - while ((skb = __skb_dequeue(&tid_data->deferred_tx_frames))) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - /* - * The first deferred frame should've stopped the MAC - * queues, so we should never get a second deferred - * frame for the RA/TID. - */ - iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue)); - ieee80211_free_txskb(mvm->hw, skb); - } - } - spin_unlock_bh(&mvm_sta->lock); -} - static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -2942,7 +2989,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, */ if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST) { - iwl_mvm_purge_deferred_tx_frames(mvm, mvm_sta); flush_work(&mvm->add_stream_wk); /* @@ -4680,6 +4726,7 @@ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) const struct ieee80211_ops iwl_mvm_hw_ops = { .tx = iwl_mvm_mac_tx, + .wake_tx_queue = iwl_mvm_mac_wake_tx_queue, .ampdu_action = iwl_mvm_mac_ampdu_action, .start = iwl_mvm_mac_start, .reconfig_complete = iwl_mvm_mac_reconfig_complete, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 1aa690e081ff..39ee3ace59b6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -778,6 +778,40 @@ struct iwl_mvm_geo_profile { u8 values[ACPI_GEO_TABLE_SIZE]; }; +struct iwl_mvm_txq { + struct list_head list; + u16 txq_id; + /* Protects TX path invocation from two places */ + spinlock_t tx_path_lock; + bool stopped; +}; + +static inline struct iwl_mvm_txq * +iwl_mvm_txq_from_mac80211(struct ieee80211_txq *txq) +{ + return (void *)txq->drv_priv; +} + +static inline struct iwl_mvm_txq * +iwl_mvm_txq_from_tid(struct ieee80211_sta *sta, u8 tid) +{ + if (tid == IWL_MAX_TID_COUNT) + tid = IEEE80211_NUM_TIDS; + + return (void *)sta->txq[tid]->drv_priv; +} + +/** + * struct iwl_mvm_tvqm_txq_info - maps TVQM hw queue to tid + * + * @sta_id: sta id + * @txq_tid: txq tid + */ +struct iwl_mvm_tvqm_txq_info { + u8 sta_id; + u8 txq_tid; +}; + struct iwl_mvm_dqa_txq_info { u8 ra_sta_id; /* The RA this queue is mapped to, if exists */ bool reserved; /* Is this the TXQ reserved for a STA */ @@ -843,13 +877,13 @@ struct iwl_mvm { u64 on_time_scan; } radio_stats, accu_radio_stats; - u16 hw_queue_to_mac80211[IWL_MAX_TVQM_QUEUES]; - - struct iwl_mvm_dqa_txq_info queue_info[IWL_MAX_HW_QUEUES]; + struct list_head add_stream_txqs; + union { + struct iwl_mvm_dqa_txq_info queue_info[IWL_MAX_HW_QUEUES]; + struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES]; + }; struct work_struct add_stream_wk; /* To add streams to queues */ - atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES]; - const char *nvm_file_name; struct iwl_nvm_data *nvm_data; /* NVM sections */ @@ -863,7 +897,6 @@ struct iwl_mvm { /* data related to data path */ struct iwl_rx_phy_info last_phy_info; struct ieee80211_sta __rcu *fw_id_to_mac_id[IWL_MVM_STATION_COUNT]; - unsigned long sta_deferred_frames[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; u8 rx_ba_sessions; /* configured by mac80211 */ @@ -1470,6 +1503,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, __le16 fc); +void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq); + #ifdef CONFIG_IWLWIFI_DEBUG const char *iwl_mvm_get_tx_fail_reason(u32 status); #else @@ -1599,7 +1634,6 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool force_assoc_off, const u8 *bssid_override); int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); -u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif); void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, @@ -1615,8 +1649,6 @@ void iwl_mvm_window_status_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif); -unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, - struct ieee80211_vif *exclude_vif); void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, @@ -1906,10 +1938,6 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) iwl_trans_stop_device(mvm->trans); } -/* Stop/start all mac queues in a given bitmap */ -void iwl_mvm_start_mac_queues(struct iwl_mvm *mvm, unsigned long mq); -void iwl_mvm_stop_mac_queues(struct iwl_mvm *mvm, unsigned long mq); - /* Re-configure the SCD for a queue that has already been configured */ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id, int tid, int frame_limit, u16 ssn); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 30c5127034a0..d257c143e624 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -685,6 +685,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work); INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk); INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk); + INIT_LIST_HEAD(&mvm->add_stream_txqs); spin_lock_init(&mvm->d0i3_tx_lock); spin_lock_init(&mvm->refs_lock); @@ -1079,24 +1080,6 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, iwl_mvm_rx_common(mvm, rxb, pkt); } -void iwl_mvm_stop_mac_queues(struct iwl_mvm *mvm, unsigned long mq) -{ - int q; - - if (WARN_ON_ONCE(!mq)) - return; - - for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { - if (atomic_inc_return(&mvm->mac80211_queue_stop_count[q]) > 1) { - IWL_DEBUG_TX_QUEUES(mvm, - "mac80211 %d already stopped\n", q); - continue; - } - - ieee80211_stop_queue(mvm->hw, q); - } -} - static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode, const struct iwl_device_cmd *cmd) { @@ -1109,38 +1092,66 @@ static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode, iwl_trans_block_txq_ptrs(mvm->trans, false); } -static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) +static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, + int hw_queue, bool start) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - unsigned long mq = mvm->hw_queue_to_mac80211[hw_queue]; + struct ieee80211_sta *sta; + struct ieee80211_txq *txq; + struct iwl_mvm_txq *mvmtxq; + int i; + unsigned long tid_bitmap; + struct iwl_mvm_sta *mvmsta; + u8 sta_id; - iwl_mvm_stop_mac_queues(mvm, mq); -} + sta_id = iwl_mvm_has_new_tx_api(mvm) ? + mvm->tvqm_info[hw_queue].sta_id : + mvm->queue_info[hw_queue].ra_sta_id; -void iwl_mvm_start_mac_queues(struct iwl_mvm *mvm, unsigned long mq) -{ - int q; - - if (WARN_ON_ONCE(!mq)) + if (WARN_ON_ONCE(sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))) return; - for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { - if (atomic_dec_return(&mvm->mac80211_queue_stop_count[q]) > 0) { - IWL_DEBUG_TX_QUEUES(mvm, - "mac80211 %d still stopped\n", q); - continue; - } + rcu_read_lock(); - ieee80211_wake_queue(mvm->hw, q); + sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); + if (IS_ERR_OR_NULL(sta)) + goto out; + mvmsta = iwl_mvm_sta_from_mac80211(sta); + + if (iwl_mvm_has_new_tx_api(mvm)) { + int tid = mvm->tvqm_info[hw_queue].txq_tid; + + tid_bitmap = BIT(tid); + } else { + tid_bitmap = mvm->queue_info[hw_queue].tid_bitmap; + } + + for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { + int tid = i; + + if (tid == IWL_MAX_TID_COUNT) + tid = IEEE80211_NUM_TIDS; + + txq = sta->txq[tid]; + mvmtxq = iwl_mvm_txq_from_mac80211(txq); + mvmtxq->stopped = !start; + + if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) + iwl_mvm_mac_itxq_xmit(mvm->hw, txq); } + +out: + rcu_read_unlock(); } -static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) +static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) { - struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - unsigned long mq = mvm->hw_queue_to_mac80211[hw_queue]; + iwl_mvm_queue_state_change(op_mode, hw_queue, false); +} - iwl_mvm_start_mac_queues(mvm, mq); +static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int hw_queue) +{ + iwl_mvm_queue_state_change(op_mode, hw_queue, true); } static void iwl_mvm_set_rfkill_state(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index e28009832da0..09f294c466da 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -356,24 +356,16 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue, return ret; } -static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, - int mac80211_queue, u8 tid, u8 flags) +static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + int queue, u8 tid, u8 flags) { struct iwl_scd_txq_cfg_cmd cmd = { .scd_queue = queue, .action = SCD_CFG_DISABLE_QUEUE, }; - bool remove_mac_queue = mac80211_queue != IEEE80211_INVAL_HW_QUEUE; int ret; - if (WARN_ON(remove_mac_queue && mac80211_queue >= IEEE80211_MAX_QUEUES)) - return -EINVAL; - if (iwl_mvm_has_new_tx_api(mvm)) { - if (remove_mac_queue) - mvm->hw_queue_to_mac80211[queue] &= - ~BIT(mac80211_queue); - iwl_trans_txq_free(mvm->trans, queue); return 0; @@ -384,36 +376,15 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); - /* - * If there is another TID with the same AC - don't remove the MAC queue - * from the mapping - */ - if (tid < IWL_MAX_TID_COUNT) { - unsigned long tid_bitmap = - mvm->queue_info[queue].tid_bitmap; - int ac = tid_to_mac80211_ac[tid]; - int i; - - for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) { - if (tid_to_mac80211_ac[i] == ac) - remove_mac_queue = false; - } - } - - if (remove_mac_queue) - mvm->hw_queue_to_mac80211[queue] &= - ~BIT(mac80211_queue); - cmd.action = mvm->queue_info[queue].tid_bitmap ? SCD_CFG_ENABLE_QUEUE : SCD_CFG_DISABLE_QUEUE; if (cmd.action == SCD_CFG_DISABLE_QUEUE) mvm->queue_info[queue].status = IWL_MVM_QUEUE_FREE; IWL_DEBUG_TX_QUEUES(mvm, - "Disabling TXQ #%d tids=0x%x (mac80211 map:0x%x)\n", + "Disabling TXQ #%d tids=0x%x\n", queue, - mvm->queue_info[queue].tid_bitmap, - mvm->hw_queue_to_mac80211[queue]); + mvm->queue_info[queue].tid_bitmap); /* If the queue is still enabled - nothing left to do in this func */ if (cmd.action == SCD_CFG_ENABLE_QUEUE) @@ -423,15 +394,19 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, cmd.tid = mvm->queue_info[queue].txq_tid; /* Make sure queue info is correct even though we overwrite it */ - WARN(mvm->queue_info[queue].tid_bitmap || - mvm->hw_queue_to_mac80211[queue], - "TXQ #%d info out-of-sync - mac map=0x%x, tids=0x%x\n", - queue, mvm->hw_queue_to_mac80211[queue], - mvm->queue_info[queue].tid_bitmap); + WARN(mvm->queue_info[queue].tid_bitmap, + "TXQ #%d info out-of-sync - tids=0x%x\n", + queue, mvm->queue_info[queue].tid_bitmap); /* If we are here - the queue is freed and we can zero out these vals */ mvm->queue_info[queue].tid_bitmap = 0; - mvm->hw_queue_to_mac80211[queue] = 0; + + if (sta) { + struct iwl_mvm_txq *mvmtxq = + iwl_mvm_txq_from_tid(sta, tid); + + mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; + } /* Regardless if this is a reserved TXQ for a STA - mark it as false */ mvm->queue_info[queue].reserved = false; @@ -517,9 +492,14 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue) spin_lock_bh(&mvmsta->lock); /* Unmap MAC queues and TIDs from this queue */ for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { + struct iwl_mvm_txq *mvmtxq = + iwl_mvm_txq_from_tid(sta, tid); + if (mvmsta->tid_data[tid].state == IWL_AGG_ON) disable_agg_tids |= BIT(tid); mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE; + + mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; } mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */ @@ -541,10 +521,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue) } static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue, + struct ieee80211_sta *old_sta, u8 new_sta_id) { struct iwl_mvm_sta *mvmsta; - u8 txq_curr_ac, sta_id, tid; + u8 sta_id, tid; unsigned long disable_agg_tids = 0; bool same_sta; int ret; @@ -554,7 +535,6 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue, if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) return -EINVAL; - txq_curr_ac = mvm->queue_info[queue].mac80211_ac; sta_id = mvm->queue_info[queue].ra_sta_id; tid = mvm->queue_info[queue].txq_tid; @@ -570,9 +550,7 @@ static int iwl_mvm_free_inactive_queue(struct iwl_mvm *mvm, int queue, iwl_mvm_invalidate_sta_queue(mvm, queue, disable_agg_tids, false); - ret = iwl_mvm_disable_txq(mvm, queue, - mvmsta->vif->hw_queue[txq_curr_ac], - tid, 0); + ret = iwl_mvm_disable_txq(mvm, old_sta, queue, tid, 0); if (ret) { IWL_ERR(mvm, "Failed to free inactive queue %d (ret=%d)\n", @@ -662,16 +640,15 @@ static int iwl_mvm_get_shared_queue(struct iwl_mvm *mvm, * in such a case, otherwise - if no redirection required - it does nothing, * unless the %force param is true. */ -static int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid, - int ac, int ssn, unsigned int wdg_timeout, - bool force) +static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid, + int ac, int ssn, unsigned int wdg_timeout, + bool force, struct iwl_mvm_txq *txq) { struct iwl_scd_txq_cfg_cmd cmd = { .scd_queue = queue, .action = SCD_CFG_DISABLE_QUEUE, }; bool shared_queue; - unsigned long mq; int ret; if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) @@ -695,14 +672,14 @@ static int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid, cmd.sta_id = mvm->queue_info[queue].ra_sta_id; cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[mvm->queue_info[queue].mac80211_ac]; cmd.tid = mvm->queue_info[queue].txq_tid; - mq = mvm->hw_queue_to_mac80211[queue]; shared_queue = hweight16(mvm->queue_info[queue].tid_bitmap) > 1; IWL_DEBUG_TX_QUEUES(mvm, "Redirecting TXQ #%d to FIFO #%d\n", queue, iwl_mvm_ac_to_tx_fifo[ac]); - /* Stop MAC queues and wait for this queue to empty */ - iwl_mvm_stop_mac_queues(mvm, mq); + /* Stop the queue and wait for it to empty */ + txq->stopped = true; + ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue)); if (ret) { IWL_ERR(mvm, "Error draining queue %d before reconfig\n", @@ -743,8 +720,8 @@ static int iwl_mvm_scd_queue_redirect(struct iwl_mvm *mvm, int queue, int tid, iwl_trans_txq_set_shared_mode(mvm->trans, queue, true); out: - /* Continue using the MAC queues */ - iwl_mvm_start_mac_queues(mvm, mq); + /* Continue using the queue */ + txq->stopped = false; return ret; } @@ -769,7 +746,7 @@ static int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, return -ENOSPC; } -static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue, +static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, u8 sta_id, u8 tid, unsigned int timeout) { int queue, size = IWL_DEFAULT_QUEUE_SIZE; @@ -792,10 +769,7 @@ static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, int mac80211_queue, IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n", queue, sta_id, tid); - mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue); - IWL_DEBUG_TX_QUEUES(mvm, - "Enabling TXQ #%d (mac80211 map:0x%x)\n", - queue, mvm->hw_queue_to_mac80211[queue]); + IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d\n", queue); return queue; } @@ -805,9 +779,10 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm, int tid) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct iwl_mvm_txq *mvmtxq = + iwl_mvm_txq_from_tid(sta, tid); unsigned int wdg_timeout = iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false); - u8 mac_queue = mvmsta->vif->hw_queue[ac]; int queue = -1; lockdep_assert_held(&mvm->mutex); @@ -815,11 +790,16 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm, IWL_DEBUG_TX_QUEUES(mvm, "Allocating queue for sta %d on tid %d\n", mvmsta->sta_id, tid); - queue = iwl_mvm_tvqm_enable_txq(mvm, mac_queue, mvmsta->sta_id, tid, - wdg_timeout); + queue = iwl_mvm_tvqm_enable_txq(mvm, mvmsta->sta_id, tid, wdg_timeout); if (queue < 0) return queue; + if (sta) { + mvmtxq->txq_id = queue; + mvm->tvqm_info[queue].txq_tid = tid; + mvm->tvqm_info[queue].sta_id = mvmsta->sta_id; + } + IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue); spin_lock_bh(&mvmsta->lock); @@ -829,8 +809,9 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm, return 0; } -static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue, - int mac80211_queue, u8 sta_id, u8 tid) +static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, + int queue, u8 sta_id, u8 tid) { bool enable_queue = true; @@ -845,14 +826,6 @@ static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue, if (mvm->queue_info[queue].tid_bitmap) enable_queue = false; - if (mac80211_queue != IEEE80211_INVAL_HW_QUEUE) { - WARN(mac80211_queue >= - BITS_PER_BYTE * sizeof(mvm->hw_queue_to_mac80211[0]), - "cannot track mac80211 queue %d (queue %d, sta %d, tid %d)\n", - mac80211_queue, queue, sta_id, tid); - mvm->hw_queue_to_mac80211[queue] |= BIT(mac80211_queue); - } - mvm->queue_info[queue].tid_bitmap |= BIT(tid); mvm->queue_info[queue].ra_sta_id = sta_id; @@ -866,16 +839,22 @@ static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue, mvm->queue_info[queue].txq_tid = tid; } + if (sta) { + struct iwl_mvm_txq *mvmtxq = + iwl_mvm_txq_from_tid(sta, tid); + + mvmtxq->txq_id = queue; + } + IWL_DEBUG_TX_QUEUES(mvm, - "Enabling TXQ #%d tids=0x%x (mac80211 map:0x%x)\n", - queue, mvm->queue_info[queue].tid_bitmap, - mvm->hw_queue_to_mac80211[queue]); + "Enabling TXQ #%d tids=0x%x\n", + queue, mvm->queue_info[queue].tid_bitmap); return enable_queue; } -static bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, - int mac80211_queue, u16 ssn, +static bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, + int queue, u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, unsigned int wdg_timeout) { @@ -895,8 +874,7 @@ static bool iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, return false; /* Send the enabling command if we need to */ - if (!iwl_mvm_update_txq_mapping(mvm, queue, mac80211_queue, - cfg->sta_id, cfg->tid)) + if (!iwl_mvm_update_txq_mapping(mvm, sta, queue, cfg->sta_id, cfg->tid)) return false; inc_ssn = iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, @@ -989,9 +967,10 @@ static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue) ssn = IEEE80211_SEQ_TO_SN(mvmsta->tid_data[tid].seq_number); - ret = iwl_mvm_scd_queue_redirect(mvm, queue, tid, - tid_to_mac80211_ac[tid], ssn, - wdg_timeout, true); + ret = iwl_mvm_redirect_queue(mvm, queue, tid, + tid_to_mac80211_ac[tid], ssn, + wdg_timeout, true, + iwl_mvm_txq_from_tid(sta, tid)); if (ret) { IWL_ERR(mvm, "Failed to redirect TXQ %d\n", queue); return; @@ -1068,11 +1047,9 @@ static bool iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm, * Remove the ones that did. */ for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { - int mac_queue = mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]; u16 tid_bitmap; mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE; - mvm->hw_queue_to_mac80211[queue] &= ~BIT(mac_queue); mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); tid_bitmap = mvm->queue_info[queue].tid_bitmap; @@ -1105,10 +1082,6 @@ static bool iwl_mvm_remove_inactive_tids(struct iwl_mvm *mvm, * sure all TIDs have existing corresponding mac queues enabled */ tid_bitmap = mvm->queue_info[queue].tid_bitmap; - for_each_set_bit(tid, &tid_bitmap, IWL_MAX_TID_COUNT + 1) { - mvm->hw_queue_to_mac80211[queue] |= - BIT(mvmsta->vif->hw_queue[tid_to_mac80211_ac[tid]]); - } /* If the queue is marked as shared - "unshare" it */ if (hweight16(mvm->queue_info[queue].tid_bitmap) == 1 && @@ -1136,6 +1109,7 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta) unsigned long unshare_queues = 0; unsigned long changetid_queues = 0; int i, ret, free_queue = -ENOSPC; + struct ieee80211_sta *queue_owner = NULL; lockdep_assert_held(&mvm->mutex); @@ -1201,13 +1175,14 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta) inactive_tid_bitmap, &unshare_queues, &changetid_queues); - if (ret >= 0 && free_queue < 0) + if (ret >= 0 && free_queue < 0) { + queue_owner = sta; free_queue = ret; + } /* only unlock sta lock - we still need the queue info lock */ spin_unlock_bh(&mvmsta->lock); } - rcu_read_unlock(); /* Reconfigure queues requiring reconfiguation */ for_each_set_bit(i, &unshare_queues, IWL_MAX_HW_QUEUES) @@ -1216,18 +1191,21 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta) iwl_mvm_change_queue_tid(mvm, i); if (free_queue >= 0 && alloc_for_sta != IWL_MVM_INVALID_STA) { - ret = iwl_mvm_free_inactive_queue(mvm, free_queue, + ret = iwl_mvm_free_inactive_queue(mvm, free_queue, queue_owner, alloc_for_sta); - if (ret) + if (ret) { + rcu_read_unlock(); return ret; + } } + rcu_read_unlock(); + return free_queue; } static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, - struct ieee80211_sta *sta, u8 ac, int tid, - struct ieee80211_hdr *hdr) + struct ieee80211_sta *sta, u8 ac, int tid) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_trans_txq_scd_cfg cfg = { @@ -1238,7 +1216,6 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, }; unsigned int wdg_timeout = iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false); - u8 mac_queue = mvmsta->vif->hw_queue[ac]; int queue = -1; unsigned long disable_agg_tids = 0; enum iwl_mvm_agg_state queue_state; @@ -1257,12 +1234,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, ssn = IEEE80211_SEQ_TO_SN(mvmsta->tid_data[tid].seq_number); spin_unlock_bh(&mvmsta->lock); - /* - * Non-QoS, QoS NDP and MGMT frames should go to a MGMT queue, if one - * exists - */ - if (!ieee80211_is_data_qos(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) { + if (tid == IWL_MAX_TID_COUNT) { queue = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, IWL_MVM_DQA_MIN_MGMT_QUEUE, IWL_MVM_DQA_MAX_MGMT_QUEUE); @@ -1341,8 +1313,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, } } - inc_ssn = iwl_mvm_enable_txq(mvm, queue, mac_queue, - ssn, &cfg, wdg_timeout); + inc_ssn = iwl_mvm_enable_txq(mvm, sta, queue, ssn, &cfg, wdg_timeout); /* * Mark queue as shared in transport if shared @@ -1384,8 +1355,9 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, } } else { /* Redirect queue, if needed */ - ret = iwl_mvm_scd_queue_redirect(mvm, queue, tid, ac, ssn, - wdg_timeout, false); + ret = iwl_mvm_redirect_queue(mvm, queue, tid, ac, ssn, + wdg_timeout, false, + iwl_mvm_txq_from_tid(sta, tid)); if (ret) goto out_err; } @@ -1393,7 +1365,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm, return 0; out_err: - iwl_mvm_disable_txq(mvm, queue, mac_queue, tid, 0); + iwl_mvm_disable_txq(mvm, sta, queue, tid, 0); return ret; } @@ -1406,87 +1378,34 @@ static inline u8 iwl_mvm_tid_to_ac_queue(int tid) return tid_to_mac80211_ac[tid]; } -static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm, - struct ieee80211_sta *sta, int tid) -{ - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - struct sk_buff_head deferred_tx; - u8 mac_queue; - bool no_queue = false; /* Marks if there is a problem with the queue */ - u8 ac; - - lockdep_assert_held(&mvm->mutex); - - skb = skb_peek(&tid_data->deferred_tx_frames); - if (!skb) - return; - hdr = (void *)skb->data; - - ac = iwl_mvm_tid_to_ac_queue(tid); - mac_queue = IEEE80211_SKB_CB(skb)->hw_queue; - - if (tid_data->txq_id == IWL_MVM_INVALID_QUEUE && - iwl_mvm_sta_alloc_queue(mvm, sta, ac, tid, hdr)) { - IWL_ERR(mvm, - "Can't alloc TXQ for sta %d tid %d - dropping frame\n", - mvmsta->sta_id, tid); - - /* - * Mark queue as problematic so later the deferred traffic is - * freed, as we can do nothing with it - */ - no_queue = true; - } - - __skb_queue_head_init(&deferred_tx); - - /* Disable bottom-halves when entering TX path */ - local_bh_disable(); - spin_lock(&mvmsta->lock); - skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx); - mvmsta->deferred_traffic_tid_map &= ~BIT(tid); - spin_unlock(&mvmsta->lock); - - while ((skb = __skb_dequeue(&deferred_tx))) - if (no_queue || iwl_mvm_tx_skb(mvm, skb, sta)) - ieee80211_free_txskb(mvm->hw, skb); - local_bh_enable(); - - /* Wake queue */ - iwl_mvm_start_mac_queues(mvm, BIT(mac_queue)); -} - void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) { struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, add_stream_wk); - struct ieee80211_sta *sta; - struct iwl_mvm_sta *mvmsta; - unsigned long deferred_tid_traffic; - int sta_id, tid; mutex_lock(&mvm->mutex); iwl_mvm_inactivity_check(mvm, IWL_MVM_INVALID_STA); - /* Go over all stations with deferred traffic */ - for_each_set_bit(sta_id, mvm->sta_deferred_frames, - IWL_MVM_STATION_COUNT) { - clear_bit(sta_id, mvm->sta_deferred_frames); - sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], - lockdep_is_held(&mvm->mutex)); - if (IS_ERR_OR_NULL(sta)) - continue; + while (!list_empty(&mvm->add_stream_txqs)) { + struct iwl_mvm_txq *mvmtxq; + struct ieee80211_txq *txq; + u8 tid; - mvmsta = iwl_mvm_sta_from_mac80211(sta); - deferred_tid_traffic = mvmsta->deferred_traffic_tid_map; + mvmtxq = list_first_entry(&mvm->add_stream_txqs, + struct iwl_mvm_txq, list); + + txq = container_of((void *)mvmtxq, struct ieee80211_txq, + drv_priv); + tid = txq->tid; + if (tid == IEEE80211_NUM_TIDS) + tid = IWL_MAX_TID_COUNT; - for_each_set_bit(tid, &deferred_tid_traffic, - IWL_MAX_TID_COUNT + 1) - iwl_mvm_tx_deferred_stream(mvm, sta, tid); + iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid); + list_del_init(&mvmtxq->list); + local_bh_disable(); + iwl_mvm_mac_itxq_xmit(mvm->hw, txq); + local_bh_enable(); } mutex_unlock(&mvm->mutex); @@ -1542,10 +1461,11 @@ static int iwl_mvm_reserve_sta_stream(struct iwl_mvm *mvm, * Note that re-enabling aggregations isn't done in this function. */ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm, - struct iwl_mvm_sta *mvm_sta) + struct ieee80211_sta *sta) { - unsigned int wdg_timeout = - iwl_mvm_get_wd_timeout(mvm, mvm_sta->vif, false, false); + struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); + unsigned int wdg = + iwl_mvm_get_wd_timeout(mvm, mvm_sta->vif, false, false); int i; struct iwl_trans_txq_scd_cfg cfg = { .sta_id = mvm_sta->sta_id, @@ -1561,23 +1481,18 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data = &mvm_sta->tid_data[i]; int txq_id = tid_data->txq_id; int ac; - u8 mac_queue; if (txq_id == IWL_MVM_INVALID_QUEUE) continue; - skb_queue_head_init(&tid_data->deferred_tx_frames); - ac = tid_to_mac80211_ac[i]; - mac_queue = mvm_sta->vif->hw_queue[ac]; if (iwl_mvm_has_new_tx_api(mvm)) { IWL_DEBUG_TX_QUEUES(mvm, "Re-mapping sta %d tid %d\n", mvm_sta->sta_id, i); - txq_id = iwl_mvm_tvqm_enable_txq(mvm, mac_queue, - mvm_sta->sta_id, - i, wdg_timeout); + txq_id = iwl_mvm_tvqm_enable_txq(mvm, mvm_sta->sta_id, + i, wdg); tid_data->txq_id = txq_id; /* @@ -1600,8 +1515,7 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm, "Re-mapping sta %d tid %d to queue %d\n", mvm_sta->sta_id, i, txq_id); - iwl_mvm_enable_txq(mvm, txq_id, mac_queue, seq, &cfg, - wdg_timeout); + iwl_mvm_enable_txq(mvm, sta, txq_id, seq, &cfg, wdg); mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_READY; } } @@ -1691,7 +1605,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, if (ret) goto err; - iwl_mvm_realloc_queues_after_restart(mvm, mvm_sta); + iwl_mvm_realloc_queues_after_restart(mvm, sta); sta_update = true; sta_flags = iwl_mvm_has_new_tx_api(mvm) ? 0 : STA_MODIFY_QUEUES; goto update_fw; @@ -1724,9 +1638,17 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, * frames until the queue is allocated */ mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE; - skb_queue_head_init(&mvm_sta->tid_data[i].deferred_tx_frames); } - mvm_sta->deferred_traffic_tid_map = 0; + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { + struct iwl_mvm_txq *mvmtxq = + iwl_mvm_txq_from_mac80211(sta->txq[i]); + + mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; + INIT_LIST_HEAD(&mvmtxq->list); + spin_lock_init(&mvmtxq->tx_path_lock); + } + mvm_sta->agg_tids = 0; if (iwl_mvm_has_new_rx_api(mvm) && @@ -1861,9 +1783,9 @@ static int iwl_mvm_rm_sta_common(struct iwl_mvm *mvm, u8 sta_id) static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct iwl_mvm_sta *mvm_sta) + struct ieee80211_sta *sta) { - int ac; + struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); int i; lockdep_assert_held(&mvm->mutex); @@ -1872,11 +1794,17 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm, if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE) continue; - ac = iwl_mvm_tid_to_ac_queue(i); - iwl_mvm_disable_txq(mvm, mvm_sta->tid_data[i].txq_id, - vif->hw_queue[ac], i, 0); + iwl_mvm_disable_txq(mvm, sta, mvm_sta->tid_data[i].txq_id, i, + 0); mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE; } + + for (i = 0; i < ARRAY_SIZE(sta->txq); i++) { + struct iwl_mvm_txq *mvmtxq = + iwl_mvm_txq_from_mac80211(sta->txq[i]); + + mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; + } } int iwl_mvm_wait_sta_queues_empty(struct iwl_mvm *mvm, @@ -1938,7 +1866,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, ret = iwl_mvm_drain_sta(mvm, mvm_sta, false); - iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta); + iwl_mvm_disable_sta_queues(mvm, vif, sta); /* If there is a TXQ still marked as reserved - free it */ if (mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) { @@ -2044,7 +1972,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue, if (iwl_mvm_has_new_tx_api(mvm)) { int tvqm_queue = - iwl_mvm_tvqm_enable_txq(mvm, *queue, sta_id, + iwl_mvm_tvqm_enable_txq(mvm, sta_id, IWL_MAX_TID_COUNT, wdg_timeout); *queue = tvqm_queue; @@ -2057,7 +1985,7 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue, .frame_limit = IWL_FRAME_LIMIT, }; - iwl_mvm_enable_txq(mvm, *queue, *queue, 0, &cfg, wdg_timeout); + iwl_mvm_enable_txq(mvm, NULL, *queue, 0, &cfg, wdg_timeout); } } @@ -2135,8 +2063,7 @@ int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) lockdep_assert_held(&mvm->mutex); - iwl_mvm_disable_txq(mvm, mvm->snif_queue, mvm->snif_queue, - IWL_MAX_TID_COUNT, 0); + iwl_mvm_disable_txq(mvm, NULL, mvm->snif_queue, IWL_MAX_TID_COUNT, 0); ret = iwl_mvm_rm_sta_common(mvm, mvm->snif_sta.sta_id); if (ret) IWL_WARN(mvm, "Failed sending remove station\n"); @@ -2195,8 +2122,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) bsta->tfd_queue_msk |= BIT(queue); - iwl_mvm_enable_txq(mvm, queue, vif->hw_queue[0], 0, - &cfg, wdg_timeout); + iwl_mvm_enable_txq(mvm, NULL, queue, 0, &cfg, wdg_timeout); } if (vif->type == NL80211_IFTYPE_ADHOC) @@ -2215,8 +2141,7 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) * to firmware so enable queue here - after the station was added */ if (iwl_mvm_has_new_tx_api(mvm)) { - queue = iwl_mvm_tvqm_enable_txq(mvm, vif->hw_queue[0], - bsta->sta_id, + queue = iwl_mvm_tvqm_enable_txq(mvm, bsta->sta_id, IWL_MAX_TID_COUNT, wdg_timeout); @@ -2254,7 +2179,7 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm, return; } - iwl_mvm_disable_txq(mvm, queue, vif->hw_queue[0], IWL_MAX_TID_COUNT, 0); + iwl_mvm_disable_txq(mvm, NULL, queue, IWL_MAX_TID_COUNT, 0); if (iwl_mvm_has_new_tx_api(mvm)) return; @@ -2377,10 +2302,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) * Note that this is done here as we want to avoid making DQA * changes in mac80211 layer. */ - if (vif->type == NL80211_IFTYPE_ADHOC) { - vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; - mvmvif->cab_queue = vif->cab_queue; - } + if (vif->type == NL80211_IFTYPE_ADHOC) + mvmvif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE; /* * While in previous FWs we had to exclude cab queue from TFD queue @@ -2388,9 +2311,9 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) */ if (!iwl_mvm_has_new_tx_api(mvm) && fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) { - iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, - &cfg, timeout); - msta->tfd_queue_msk |= BIT(vif->cab_queue); + iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg, + timeout); + msta->tfd_queue_msk |= BIT(mvmvif->cab_queue); } ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr, mvmvif->id, mvmvif->color); @@ -2407,15 +2330,14 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) * tfd_queue_mask. */ if (iwl_mvm_has_new_tx_api(mvm)) { - int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->cab_queue, - msta->sta_id, + int queue = iwl_mvm_tvqm_enable_txq(mvm, msta->sta_id, 0, timeout); mvmvif->cab_queue = queue; } else if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) - iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, - &cfg, timeout); + iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg, + timeout); if (mvmvif->ap_wep_key) { u8 key_offset = iwl_mvm_set_fw_key_idx(mvm); @@ -2446,8 +2368,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0); - iwl_mvm_disable_txq(mvm, mvmvif->cab_queue, vif->cab_queue, - 0, 0); + iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0); ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); if (ret) @@ -2976,8 +2897,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, } if (alloc_queue) - iwl_mvm_enable_txq(mvm, queue, - vif->hw_queue[tid_to_mac80211_ac[tid]], ssn, + iwl_mvm_enable_txq(mvm, sta, queue, ssn, &cfg, wdg_timeout); /* Send ADD_STA command to enable aggs only if the queue isn't shared */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index d52cd888f77d..0614296244b3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -297,7 +297,6 @@ enum iwl_mvm_agg_state { /** * struct iwl_mvm_tid_data - holds the states for each RA / TID - * @deferred_tx_frames: deferred TX frames for this RA/TID * @seq_number: the next WiFi sequence number to use * @next_reclaimed: the WiFi sequence number of the next packet to be acked. * This is basically (last acked packet++). @@ -318,7 +317,6 @@ enum iwl_mvm_agg_state { * tpt_meas_start */ struct iwl_mvm_tid_data { - struct sk_buff_head deferred_tx_frames; u16 seq_number; u16 next_reclaimed; /* The rest is Tx AGG related */ @@ -427,8 +425,6 @@ struct iwl_mvm_sta { struct iwl_mvm_key_pn __rcu *ptk_pn[4]; struct iwl_mvm_rxq_dup_data *dup_data; - u16 deferred_traffic_tid_map; - u8 reserved_queue; /* Temporary, until the new TLC will control the Tx protection */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 995fe2a6abbb..dfdfaa9ecfdb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -602,11 +602,12 @@ static void iwl_mvm_skb_prepare_status(struct sk_buff *skb, } static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, - struct ieee80211_tx_info *info, __le16 fc) + struct ieee80211_tx_info *info, + struct ieee80211_hdr *hdr) { - struct iwl_mvm_vif *mvmvif; - - mvmvif = iwl_mvm_vif_from_mac80211(info->control.vif); + struct iwl_mvm_vif *mvmvif = + iwl_mvm_vif_from_mac80211(info->control.vif); + __le16 fc = hdr->frame_control; switch (info->control.vif->type) { case NL80211_IFTYPE_AP: @@ -625,7 +626,9 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, (!ieee80211_is_bufferable_mmpdu(fc) || ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc))) return mvm->probe_queue; - if (info->hw_queue == info->control.vif->cab_queue) + + if (!ieee80211_has_order(fc) && !ieee80211_is_probe_req(fc) && + is_multicast_ether_addr(hdr->addr1)) return mvmvif->cab_queue; WARN_ONCE(info->control.vif->type != NL80211_IFTYPE_ADHOC, @@ -634,8 +637,6 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, case NL80211_IFTYPE_P2P_DEVICE: if (ieee80211_is_mgmt(fc)) return mvm->p2p_dev_queue; - if (info->hw_queue == info->control.vif->cab_queue) - return mvmvif->cab_queue; WARN_ON_ONCE(1); return mvm->p2p_dev_queue; @@ -713,6 +714,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) u8 sta_id; int hdrlen = ieee80211_hdrlen(hdr->frame_control); __le16 fc = hdr->frame_control; + bool offchannel = IEEE80211_SKB_CB(skb)->flags & + IEEE80211_TX_CTL_TX_OFFCHAN; int queue = -1; memcpy(&info, skb->cb, sizeof(info)); @@ -720,11 +723,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU)) return -1; - if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && - (!info.control.vif || - info.hw_queue != info.control.vif->cab_queue))) - return -1; - if (info.control.vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(info.control.vif); @@ -737,14 +735,12 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) else sta_id = mvmvif->mcast_sta.sta_id; - queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, - hdr->frame_control); - + queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, hdr); } else if (info.control.vif->type == NL80211_IFTYPE_MONITOR) { queue = mvm->snif_queue; sta_id = mvm->snif_sta.sta_id; } else if (info.control.vif->type == NL80211_IFTYPE_STATION && - info.hw_queue == IWL_MVM_OFFCHANNEL_QUEUE) { + offchannel) { /* * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets * that can be used in 2 different types of vifs, P2P & @@ -758,8 +754,10 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) } } - if (queue < 0) + if (queue < 0) { + IWL_ERR(mvm, "No queue was found. Dropping TX\n"); return -1; + } if (unlikely(ieee80211_is_probe_resp(fc))) iwl_mvm_probe_resp_set_noa(mvm, skb); @@ -1002,34 +1000,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, } #endif -static void iwl_mvm_tx_add_stream(struct iwl_mvm *mvm, - struct iwl_mvm_sta *mvm_sta, u8 tid, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - u8 mac_queue = info->hw_queue; - struct sk_buff_head *deferred_tx_frames; - - lockdep_assert_held(&mvm_sta->lock); - - mvm_sta->deferred_traffic_tid_map |= BIT(tid); - set_bit(mvm_sta->sta_id, mvm->sta_deferred_frames); - - deferred_tx_frames = &mvm_sta->tid_data[tid].deferred_tx_frames; - - skb_queue_tail(deferred_tx_frames, skb); - - /* - * The first deferred frame should've stopped the MAC queues, so we - * should never get a second deferred frame for the RA/TID. - * In case of GSO the first packet may have been split, so don't warn. - */ - if (skb_queue_len(deferred_tx_frames) == 1) { - iwl_mvm_stop_mac_queues(mvm, BIT(mac_queue)); - schedule_work(&mvm->add_stream_wk); - } -} - /* Check if there are any timed-out TIDs on a given shared TXQ */ static bool iwl_mvm_txq_should_update(struct iwl_mvm *mvm, int txq_id) { @@ -1088,7 +1058,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, __le16 fc; u16 seq_number = 0; u8 tid = IWL_MAX_TID_COUNT; - u16 txq_id = info->hw_queue; + u16 txq_id; bool is_ampdu = false; int hdrlen; @@ -1152,14 +1122,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM); - /* Check if TXQ needs to be allocated or re-activated */ - if (unlikely(txq_id == IWL_MVM_INVALID_QUEUE)) { - iwl_mvm_tx_add_stream(mvm, mvmsta, tid, skb); - - /* - * The frame is now deferred, and the worker scheduled - * will re-allocate it, so we can free it for now. - */ + if (WARN_ON_ONCE(txq_id == IWL_MVM_INVALID_QUEUE)) { iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); spin_unlock(&mvmsta->lock); return 0; -- cgit v1.2.3 From 438af9698b0f161286c6e5d24255c3c231988b39 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 28 Aug 2018 10:08:35 +0300 Subject: iwlwifi: mvm: support mac80211 AMSDU Support getting mac80211 building AMSDUs for us. Remove GSO support from mvm - we don't need it anymore. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 33 ++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 + drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c | 14 ++ drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 14 ++ drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 229 +--------------------- 5 files changed, 67 insertions(+), 226 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 58bb92b0ef05..3b24cced3f6f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -440,6 +440,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW); ieee80211_hw_set(hw, BUFF_MMPDU_TXQ); ieee80211_hw_set(hw, STA_MMPDU_TXQ); + ieee80211_hw_set(hw, TX_AMSDU); + ieee80211_hw_set(hw, TX_FRAG_LIST); if (iwl_mvm_has_tlc_offload(mvm)) { ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW); @@ -485,6 +487,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; + hw->max_tx_fragments = mvm->trans->max_skb_frags; BUILD_BUG_ON(ARRAY_SIZE(mvm->ciphers) < ARRAY_SIZE(mvm_ciphers) + 6); memcpy(mvm->ciphers, mvm_ciphers, sizeof(mvm_ciphers)); @@ -751,6 +754,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) } hw->netdev_features |= mvm->cfg->features; + hw->netdev_features &= ~(NETIF_F_TSO | NETIF_F_TSO6); if (!iwl_mvm_is_csum_supported(mvm)) { hw->netdev_features &= ~(IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM); @@ -3035,6 +3039,8 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr, NL80211_TDLS_SETUP); } + + sta->max_rc_amsdu_len = 1; } else if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_AUTH) { /* @@ -4724,6 +4730,32 @@ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) mutex_unlock(&mvm->mutex); } +static bool iwl_mvm_can_hw_csum(struct sk_buff *skb) +{ + u8 protocol = ip_hdr(skb)->protocol; + + if (!IS_ENABLED(CONFIG_INET)) + return false; + + return protocol == IPPROTO_TCP || protocol == IPPROTO_UDP; +} + +static bool iwl_mvm_mac_can_aggregate(struct ieee80211_hw *hw, + struct sk_buff *head, + struct sk_buff *skb) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + /* For now don't aggregate IPv6 in AMSDU */ + if (skb->protocol != htons(ETH_P_IP)) + return false; + + if (!iwl_mvm_is_csum_supported(mvm)) + return true; + + return iwl_mvm_can_hw_csum(skb) == iwl_mvm_can_hw_csum(head); +} + const struct ieee80211_ops iwl_mvm_hw_ops = { .tx = iwl_mvm_mac_tx, .wake_tx_queue = iwl_mvm_mac_wake_tx_queue, @@ -4800,6 +4832,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { #endif .get_survey = iwl_mvm_mac_get_survey, .sta_statistics = iwl_mvm_mac_sta_statistics, + .can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate, #ifdef CONFIG_IWLWIFI_DEBUGFS .sta_add_debugfs = iwl_mvm_sta_add_debugfs, #endif diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 39ee3ace59b6..503e51d32e7f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1504,6 +1504,9 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, __le16 fc); void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq); +unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, + unsigned int tid); #ifdef CONFIG_IWLWIFI_DEBUG const char *iwl_mvm_get_tx_fail_reason(u32 status); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index a0ea0c160fd6..a28283ff7295 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -315,12 +315,26 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, if (flags & IWL_TLC_NOTIF_FLAG_AMSDU) { u16 size = le32_to_cpu(notif->amsdu_size); + int i; if (WARN_ON(sta->max_amsdu_len < size)) goto out; mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled); mvmsta->max_amsdu_len = size; + sta->max_rc_amsdu_len = mvmsta->max_amsdu_len; + + for (i = 0; i < IWL_MAX_TID_COUNT; i++) { + if (mvmsta->amsdu_enabled & BIT(i)) + sta->max_tid_amsdu_len[i] = + iwl_mvm_max_amsdu_size(mvm, sta, i); + else + /* + * Not so elegant, but this will effectively + * prevent AMSDU on this TID + */ + sta->max_tid_amsdu_len[i] = 1; + } IWL_DEBUG_RATE(mvm, "AMSDU update. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n", diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 089972280daa..9b5682ce4b39 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -1744,6 +1744,7 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta, enum rs_action scale_action) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + int i; /* * In case TLC offload is not active amsdu_enabled is either 0xFFFF @@ -1757,6 +1758,19 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta, mvmsta->amsdu_enabled = 0xFFFF; mvmsta->max_amsdu_len = sta->max_amsdu_len; + sta->max_rc_amsdu_len = mvmsta->max_amsdu_len; + + for (i = 0; i < IWL_MAX_TID_COUNT; i++) { + if (mvmsta->amsdu_enabled) + sta->max_tid_amsdu_len[i] = + iwl_mvm_max_amsdu_size(mvm, sta, i); + else + /* + * Not so elegant, but this will effectively + * prevent AMSDU on this TID + */ + sta->max_tid_amsdu_len[i] = 1; + } } /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index dfdfaa9ecfdb..2f2c355c13b0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -779,78 +779,8 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) return 0; } -#ifdef CONFIG_INET - -static int -iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes, - netdev_features_t netdev_flags, - struct sk_buff_head *mpdus_skb) -{ - struct sk_buff *tmp, *next; - struct ieee80211_hdr *hdr = (void *)skb->data; - char cb[sizeof(skb->cb)]; - u16 i = 0; - unsigned int tcp_payload_len; - unsigned int mss = skb_shinfo(skb)->gso_size; - bool ipv4 = (skb->protocol == htons(ETH_P_IP)); - u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0; - - skb_shinfo(skb)->gso_size = num_subframes * mss; - memcpy(cb, skb->cb, sizeof(cb)); - - next = skb_gso_segment(skb, netdev_flags); - skb_shinfo(skb)->gso_size = mss; - if (WARN_ON_ONCE(IS_ERR(next))) - return -EINVAL; - else if (next) - consume_skb(skb); - - while (next) { - tmp = next; - next = tmp->next; - - memcpy(tmp->cb, cb, sizeof(tmp->cb)); - /* - * Compute the length of all the data added for the A-MSDU. - * This will be used to compute the length to write in the TX - * command. We have: SNAP + IP + TCP for n -1 subframes and - * ETH header for n subframes. - */ - tcp_payload_len = skb_tail_pointer(tmp) - - skb_transport_header(tmp) - - tcp_hdrlen(tmp) + tmp->data_len; - - if (ipv4) - ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); - - if (tcp_payload_len > mss) { - skb_shinfo(tmp)->gso_size = mss; - } else { - if (ieee80211_is_data_qos(hdr->frame_control)) { - u8 *qc; - - if (ipv4) - ip_send_check(ip_hdr(tmp)); - - qc = ieee80211_get_qos_ctl((void *)tmp->data); - *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; - } - skb_shinfo(tmp)->gso_size = 0; - } - - tmp->prev = NULL; - tmp->next = NULL; - - __skb_queue_tail(mpdus_skb, tmp); - i++; - } - - return 0; -} - -static unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm, - struct ieee80211_sta *sta, - unsigned int tid) +unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, unsigned int tid) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); enum nl80211_band band = mvmsta->vif->bss_conf.chandef.chan->band; @@ -878,128 +808,6 @@ static unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm, mvm->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256); } -static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff_head *mpdus_skb) -{ - struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - struct ieee80211_hdr *hdr = (void *)skb->data; - unsigned int mss = skb_shinfo(skb)->gso_size; - unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len; - u16 snap_ip_tcp, pad; - unsigned int dbg_max_amsdu_len; - netdev_features_t netdev_flags = NETIF_F_CSUM_MASK | NETIF_F_SG; - u8 tid; - - snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) + - tcp_hdrlen(skb); - - dbg_max_amsdu_len = READ_ONCE(mvm->max_amsdu_len); - - if (!mvmsta->max_amsdu_len || - !ieee80211_is_data_qos(hdr->frame_control) || - (!mvmsta->amsdu_enabled && !dbg_max_amsdu_len)) - return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); - - /* - * Do not build AMSDU for IPv6 with extension headers. - * ask stack to segment and checkum the generated MPDUs for us. - */ - if (skb->protocol == htons(ETH_P_IPV6) && - ((struct ipv6hdr *)skb_network_header(skb))->nexthdr != - IPPROTO_TCP) { - netdev_flags &= ~NETIF_F_CSUM_MASK; - return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); - } - - tid = ieee80211_get_tid(hdr); - if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) - return -EINVAL; - - /* - * No need to lock amsdu_in_ampdu_allowed since it can't be modified - * during an BA session. - */ - if (info->flags & IEEE80211_TX_CTL_AMPDU && - !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) - return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); - - if (iwl_mvm_vif_low_latency(iwl_mvm_vif_from_mac80211(mvmsta->vif)) || - !(mvmsta->amsdu_enabled & BIT(tid))) - return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); - - max_amsdu_len = iwl_mvm_max_amsdu_size(mvm, sta, tid); - - if (unlikely(dbg_max_amsdu_len)) - max_amsdu_len = min_t(unsigned int, max_amsdu_len, - dbg_max_amsdu_len); - - /* - * Limit A-MSDU in A-MPDU to 4095 bytes when VHT is not - * supported. This is a spec requirement (IEEE 802.11-2015 - * section 8.7.3 NOTE 3). - */ - if (info->flags & IEEE80211_TX_CTL_AMPDU && - !sta->vht_cap.vht_supported) - max_amsdu_len = min_t(unsigned int, max_amsdu_len, 4095); - - /* Sub frame header + SNAP + IP header + TCP header + MSS */ - subf_len = sizeof(struct ethhdr) + snap_ip_tcp + mss; - pad = (4 - subf_len) & 0x3; - - /* - * If we have N subframes in the A-MSDU, then the A-MSDU's size is - * N * subf_len + (N - 1) * pad. - */ - num_subframes = (max_amsdu_len + pad) / (subf_len + pad); - - if (sta->max_amsdu_subframes && - num_subframes > sta->max_amsdu_subframes) - num_subframes = sta->max_amsdu_subframes; - - tcp_payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - - tcp_hdrlen(skb) + skb->data_len; - - /* - * Make sure we have enough TBs for the A-MSDU: - * 2 for each subframe - * 1 more for each fragment - * 1 more for the potential data in the header - */ - if ((num_subframes * 2 + skb_shinfo(skb)->nr_frags + 1) > - mvm->trans->max_skb_frags) - num_subframes = 1; - - if (num_subframes > 1) - *ieee80211_get_qos_ctl(hdr) |= IEEE80211_QOS_CTL_A_MSDU_PRESENT; - - /* This skb fits in one single A-MSDU */ - if (num_subframes * mss >= tcp_payload_len) { - __skb_queue_tail(mpdus_skb, skb); - return 0; - } - - /* - * Trick the segmentation function to make it - * create SKBs that can fit into one A-MSDU. - */ - return iwl_mvm_tx_tso_segment(skb, num_subframes, netdev_flags, - mpdus_skb); -} -#else /* CONFIG_INET */ -static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff_head *mpdus_skb) -{ - /* Impossible to get TSO with CONFIG_INET */ - WARN_ON(1); - - return -1; -} -#endif - /* Check if there are any timed-out TIDs on a given shared TXQ */ static bool iwl_mvm_txq_should_update(struct iwl_mvm *mvm, int txq_id) { @@ -1178,9 +986,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct ieee80211_tx_info info; - struct sk_buff_head mpdus_skbs; - unsigned int payload_len; - int ret; if (WARN_ON_ONCE(!mvmsta)) return -1; @@ -1190,35 +995,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, memcpy(&info, skb->cb, sizeof(info)); - if (!skb_is_gso(skb)) - return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); - - payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - - tcp_hdrlen(skb) + skb->data_len; - - if (payload_len <= skb_shinfo(skb)->gso_size) - return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); - - __skb_queue_head_init(&mpdus_skbs); - - ret = iwl_mvm_tx_tso(mvm, skb, &info, sta, &mpdus_skbs); - if (ret) - return ret; - - if (WARN_ON(skb_queue_empty(&mpdus_skbs))) - return ret; - - while (!skb_queue_empty(&mpdus_skbs)) { - skb = __skb_dequeue(&mpdus_skbs); - - ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta); - if (ret) { - __skb_queue_purge(&mpdus_skbs); - return ret; - } - } - - return 0; + return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); } static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, -- cgit v1.2.3 From e7eed19a28f095d0b5d94992fd6b5d0c5bdbb637 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 17 Oct 2018 09:04:09 +0300 Subject: iwlwifi: mvm: fix values in the table example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We erroneously had some values for NGI in the table we give as an example in rs_fill_rates_for_column(), when they should be SGI. Change them so that they match what we say. Reported-by: Rémy Grünblatt Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 9b5682ce4b39..09866f50857a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -3346,12 +3346,12 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm, /* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI * column the rate table should look like this: * - * rate[0] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI - * rate[1] 0x400D019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI - * rate[2] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI - * rate[3] 0x400D018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI - * rate[4] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI - * rate[5] 0x400D017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI + * rate[0] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI + * rate[1] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI + * rate[2] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI + * rate[3] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI + * rate[4] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI + * rate[5] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI * rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI * rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI * rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI -- cgit v1.2.3 From af84282e2b48143894383d4d6d7812d72e292be9 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 5 Oct 2018 09:02:49 +0000 Subject: iwlwifi: use kmemdup in iwl_parse_nvm_mcc_info() Use kmemdup rather than duplicating its implementation in iwl_parse_nvm_mcc_info(). Signed-off-by: YueHaibing Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 173ade96f119..484ef4556953 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1195,14 +1195,12 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, regd_to_copy = sizeof(struct ieee80211_regdomain) + valid_rules * sizeof(struct ieee80211_reg_rule); - copy_rd = kzalloc(regd_to_copy, GFP_KERNEL); + copy_rd = kmemdup(regd, regd_to_copy, GFP_KERNEL); if (!copy_rd) { copy_rd = ERR_PTR(-ENOMEM); goto out; } - memcpy(copy_rd, regd, regd_to_copy); - out: kfree(regdb_ptrs); kfree(regd); -- cgit v1.2.3 From d6f9c7721064d99112ce56590a9a3fafe8ffc209 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 11 Oct 2018 10:57:57 +0100 Subject: iwlwifi: fix spelling mistake "registrating" -> "registering" Trivial fix to spelling mistake in IWL_ERR error message Signed-off-by: Colin Ian King Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index c219bca5cff4..bd3c3b921d4c 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -1054,7 +1054,7 @@ static void iwl_bg_restart(struct work_struct *data) ieee80211_restart_hw(priv->hw); else IWL_ERR(priv, - "Cannot request restart before registrating with mac80211\n"); + "Cannot request restart before registering with mac80211\n"); } else { WARN_ON(1); } -- cgit v1.2.3 From 08f7d8b69aaf137db8ee0a2d7c9e6cd6383ae250 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 18 Oct 2018 11:03:06 +0300 Subject: iwlwifi: mvm: bring back mvm GSO code We have a slightly better TCP performance with GSO. Add it back, it can co-exist with the code that builds AMSDUs in mac80211. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 1 - drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 224 +++++++++++++++++++++- 2 files changed, 223 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 3b24cced3f6f..ebb3814dd922 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -754,7 +754,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) } hw->netdev_features |= mvm->cfg->features; - hw->netdev_features &= ~(NETIF_F_TSO | NETIF_F_TSO6); if (!iwl_mvm_is_csum_supported(mvm)) { hw->netdev_features &= ~(IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 2f2c355c13b0..da8b69c9468c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -808,6 +808,197 @@ unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm *mvm, mvm->fwrt.smem_cfg.lmac[lmac].txfifo_size[txf] - 256); } +#ifdef CONFIG_INET + +static int +iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes, + netdev_features_t netdev_flags, + struct sk_buff_head *mpdus_skb) +{ + struct sk_buff *tmp, *next; + struct ieee80211_hdr *hdr = (void *)skb->data; + char cb[sizeof(skb->cb)]; + u16 i = 0; + unsigned int tcp_payload_len; + unsigned int mss = skb_shinfo(skb)->gso_size; + bool ipv4 = (skb->protocol == htons(ETH_P_IP)); + u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0; + + skb_shinfo(skb)->gso_size = num_subframes * mss; + memcpy(cb, skb->cb, sizeof(cb)); + + next = skb_gso_segment(skb, netdev_flags); + skb_shinfo(skb)->gso_size = mss; + if (WARN_ON_ONCE(IS_ERR(next))) + return -EINVAL; + else if (next) + consume_skb(skb); + + while (next) { + tmp = next; + next = tmp->next; + + memcpy(tmp->cb, cb, sizeof(tmp->cb)); + /* + * Compute the length of all the data added for the A-MSDU. + * This will be used to compute the length to write in the TX + * command. We have: SNAP + IP + TCP for n -1 subframes and + * ETH header for n subframes. + */ + tcp_payload_len = skb_tail_pointer(tmp) - + skb_transport_header(tmp) - + tcp_hdrlen(tmp) + tmp->data_len; + + if (ipv4) + ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); + + if (tcp_payload_len > mss) { + skb_shinfo(tmp)->gso_size = mss; + } else { + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc; + + if (ipv4) + ip_send_check(ip_hdr(tmp)); + + qc = ieee80211_get_qos_ctl((void *)tmp->data); + *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; + } + skb_shinfo(tmp)->gso_size = 0; + } + + tmp->prev = NULL; + tmp->next = NULL; + + __skb_queue_tail(mpdus_skb, tmp); + i++; + } + + return 0; +} + +static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff_head *mpdus_skb) +{ + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct ieee80211_hdr *hdr = (void *)skb->data; + unsigned int mss = skb_shinfo(skb)->gso_size; + unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len; + u16 snap_ip_tcp, pad; + unsigned int dbg_max_amsdu_len; + netdev_features_t netdev_flags = NETIF_F_CSUM_MASK | NETIF_F_SG; + u8 tid; + + snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) + + tcp_hdrlen(skb); + + dbg_max_amsdu_len = READ_ONCE(mvm->max_amsdu_len); + + if (!mvmsta->max_amsdu_len || + !ieee80211_is_data_qos(hdr->frame_control) || + (!mvmsta->amsdu_enabled && !dbg_max_amsdu_len)) + return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); + + /* + * Do not build AMSDU for IPv6 with extension headers. + * ask stack to segment and checkum the generated MPDUs for us. + */ + if (skb->protocol == htons(ETH_P_IPV6) && + ((struct ipv6hdr *)skb_network_header(skb))->nexthdr != + IPPROTO_TCP) { + netdev_flags &= ~NETIF_F_CSUM_MASK; + return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); + } + + tid = ieee80211_get_tid(hdr); + if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) + return -EINVAL; + + /* + * No need to lock amsdu_in_ampdu_allowed since it can't be modified + * during an BA session. + */ + if (info->flags & IEEE80211_TX_CTL_AMPDU && + !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) + return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); + + if (iwl_mvm_vif_low_latency(iwl_mvm_vif_from_mac80211(mvmsta->vif)) || + !(mvmsta->amsdu_enabled & BIT(tid))) + return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); + + max_amsdu_len = iwl_mvm_max_amsdu_size(mvm, sta, tid); + + if (unlikely(dbg_max_amsdu_len)) + max_amsdu_len = min_t(unsigned int, max_amsdu_len, + dbg_max_amsdu_len); + + /* + * Limit A-MSDU in A-MPDU to 4095 bytes when VHT is not + * supported. This is a spec requirement (IEEE 802.11-2015 + * section 8.7.3 NOTE 3). + */ + if (info->flags & IEEE80211_TX_CTL_AMPDU && + !sta->vht_cap.vht_supported) + max_amsdu_len = min_t(unsigned int, max_amsdu_len, 4095); + + /* Sub frame header + SNAP + IP header + TCP header + MSS */ + subf_len = sizeof(struct ethhdr) + snap_ip_tcp + mss; + pad = (4 - subf_len) & 0x3; + + /* + * If we have N subframes in the A-MSDU, then the A-MSDU's size is + * N * subf_len + (N - 1) * pad. + */ + num_subframes = (max_amsdu_len + pad) / (subf_len + pad); + + if (sta->max_amsdu_subframes && + num_subframes > sta->max_amsdu_subframes) + num_subframes = sta->max_amsdu_subframes; + + tcp_payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - + tcp_hdrlen(skb) + skb->data_len; + + /* + * Make sure we have enough TBs for the A-MSDU: + * 2 for each subframe + * 1 more for each fragment + * 1 more for the potential data in the header + */ + if ((num_subframes * 2 + skb_shinfo(skb)->nr_frags + 1) > + mvm->trans->max_skb_frags) + num_subframes = 1; + + if (num_subframes > 1) + *ieee80211_get_qos_ctl(hdr) |= IEEE80211_QOS_CTL_A_MSDU_PRESENT; + + /* This skb fits in one single A-MSDU */ + if (num_subframes * mss >= tcp_payload_len) { + __skb_queue_tail(mpdus_skb, skb); + return 0; + } + + /* + * Trick the segmentation function to make it + * create SKBs that can fit into one A-MSDU. + */ + return iwl_mvm_tx_tso_segment(skb, num_subframes, netdev_flags, + mpdus_skb); +} +#else /* CONFIG_INET */ +static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff_head *mpdus_skb) +{ + /* Impossible to get TSO with CONFIG_INET */ + WARN_ON(1); + + return -1; +} +#endif + /* Check if there are any timed-out TIDs on a given shared TXQ */ static bool iwl_mvm_txq_should_update(struct iwl_mvm *mvm, int txq_id) { @@ -986,6 +1177,9 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct ieee80211_tx_info info; + struct sk_buff_head mpdus_skbs; + unsigned int payload_len; + int ret; if (WARN_ON_ONCE(!mvmsta)) return -1; @@ -995,7 +1189,35 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, memcpy(&info, skb->cb, sizeof(info)); - return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); + if (!skb_is_gso(skb)) + return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); + + payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - + tcp_hdrlen(skb) + skb->data_len; + + if (payload_len <= skb_shinfo(skb)->gso_size) + return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); + + __skb_queue_head_init(&mpdus_skbs); + + ret = iwl_mvm_tx_tso(mvm, skb, &info, sta, &mpdus_skbs); + if (ret) + return ret; + + if (WARN_ON(skb_queue_empty(&mpdus_skbs))) + return ret; + + while (!skb_queue_empty(&mpdus_skbs)) { + skb = __skb_dequeue(&mpdus_skbs); + + ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta); + if (ret) { + __skb_queue_purge(&mpdus_skbs); + return ret; + } + } + + return 0; } static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, -- cgit v1.2.3 From 4f1e85f0b8e270351c709de90d17a96b9f6e16a4 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Tue, 16 Oct 2018 15:29:45 +0300 Subject: iwlwifi: mvm: Flush transmit queues on P2P Device ROC done When a time event for a P2P Device interface is done, it is possible that there is still a frame pending for transmission that should be flushed. Set the IWL_MVM_STATUS_NEED_FLUSH_P2P to indicate to the ROC worker that P2P Device station queue need also to be flushed. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index e1a6f4e22253..9fa1a36dcda3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -334,6 +334,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, switch (te_data->vif->type) { case NL80211_IFTYPE_P2P_DEVICE: ieee80211_remain_on_channel_expired(mvm->hw); + set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status); iwl_mvm_roc_finished(mvm); break; case NL80211_IFTYPE_STATION: -- cgit v1.2.3 From 055b22e770dd073d87bbb6416596456b2a4d708c Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Wed, 17 Oct 2018 14:06:19 +0300 Subject: iwlwifi: mvm: Set Tx rate and flags when there is not station When a frame is transmitted without a station, need to set the rate and flags in the Tx command, as the FW does not have any information as to what rate and flags should be used for this frame. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index da8b69c9468c..2adef6e3e0ac 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -533,10 +533,11 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, /* * For data packets rate info comes from the fw. Only - * set rate/antenna during connection establishment. + * set rate/antenna during connection establishment or in case + * no station is given. */ - if (sta && (!ieee80211_is_data(hdr->frame_control) || - mvmsta->sta_state < IEEE80211_STA_AUTHORIZED)) { + if (!sta || !ieee80211_is_data(hdr->frame_control) || + mvmsta->sta_state < IEEE80211_STA_AUTHORIZED) { flags |= IWL_TX_FLAGS_CMD_RATE; rate_n_flags = iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, -- cgit v1.2.3 From 8dd2cea8b65012003234b97c7f3dfaa61a3b4bd8 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Wed, 17 Oct 2018 16:51:59 +0300 Subject: iwlwifi: mvm: Do not set RTS/CTS protection for P2P Device MAC As this is not needed and might cause interoperability issues during pairing with devices that would not reply to RTS frames. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index a79c79701cc4..11714eb8da5e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -793,8 +793,6 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm, iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action); - cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT); - /* Override the filter flags to accept only probe requests */ cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); -- cgit v1.2.3 From a74231ba4b57d54244c04cb59f61a1554bf015a7 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Mon, 8 Oct 2018 13:37:43 +0300 Subject: iwlwifi: update hcmds documentation A few commands refer to a struct that no longer exists in the mentioned name. Our trace-cmd parsing scripts rely on these mentioned names and can't find them, resulting in these commands not being parsed nicely. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/commands.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 8b4922bbe139..89c0cfddcc3f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -415,7 +415,11 @@ enum iwl_legacy_cmds { TX_ANT_CONFIGURATION_CMD = 0x98, /** - * @STATISTICS_CMD: &struct iwl_statistics_cmd + * @STATISTICS_CMD: + * one of &struct iwl_statistics_cmd, + * &struct iwl_notif_statistics_v11, + * &struct iwl_notif_statistics_v10, + * &struct iwl_notif_statistics */ STATISTICS_CMD = 0x9c, @@ -423,7 +427,7 @@ enum iwl_legacy_cmds { * @STATISTICS_NOTIFICATION: * one of &struct iwl_notif_statistics_v10, * &struct iwl_notif_statistics_v11, - * &struct iwl_notif_statistics_cdb + * &struct iwl_notif_statistics */ STATISTICS_NOTIFICATION = 0x9d, -- cgit v1.2.3 From 45dc7ba4b423cbec14fccbb17c884614aa2006f8 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Sun, 21 Oct 2018 16:04:58 +0300 Subject: iwlwifi: mvm: make num_active_macs unsigned There is no point in having num_active_macs signed since it should never be negative. Set it to be an unsigned variable to ensure this. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c index d1d76bb9a750..9da0dae78510 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sf.c @@ -7,6 +7,7 @@ * * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,6 +29,7 @@ * * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,7 +66,7 @@ struct iwl_mvm_active_iface_iterator_data { struct ieee80211_vif *ignore_vif; u8 sta_vif_ap_sta_id; enum iwl_sf_state sta_vif_state; - int num_active_macs; + u32 num_active_macs; }; /* -- cgit v1.2.3 From 162b22c93e66530405d793a830f75da3fc48ed31 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Sun, 21 Oct 2018 14:39:05 +0300 Subject: iwlwifi: tighten boundary checks The driver assumes certain sizes and lengths aren't crossed in some places. Make sure this indeed happens. Found by Klocwork. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 24 ++++++++++++++++++----- drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 6 +++++- 3 files changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 5f16879ab26a..56e99b5661f7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -835,6 +835,8 @@ _iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, if (!fwrt->trans->cfg->dccm_offset || !fwrt->trans->cfg->dccm_len) { const struct fw_img *img; + if (fwrt->cur_fw_img >= IWL_UCODE_TYPE_MAX) + return NULL; img = &fwrt->fw->img[fwrt->cur_fw_img]; sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset; sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 2adef6e3e0ac..ac62eb8c4b36 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1024,7 +1024,12 @@ static void iwl_mvm_tx_airtime(struct iwl_mvm *mvm, int airtime) { int mac = mvmsta->mac_id_n_color & FW_CTXT_ID_MSK; - struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac]; + struct iwl_mvm_tcm_mac *mdata; + + if (mac >= NUM_MAC_INDEX_DRIVER) + return; + + mdata = &mvm->tcm.data[mac]; if (mvm->tcm.paused) return; @@ -1035,14 +1040,21 @@ static void iwl_mvm_tx_airtime(struct iwl_mvm *mvm, mdata->tx.airtime += airtime; } -static void iwl_mvm_tx_pkt_queued(struct iwl_mvm *mvm, - struct iwl_mvm_sta *mvmsta, int tid) +static int iwl_mvm_tx_pkt_queued(struct iwl_mvm *mvm, + struct iwl_mvm_sta *mvmsta, int tid) { u32 ac = tid_to_mac80211_ac[tid]; int mac = mvmsta->mac_id_n_color & FW_CTXT_ID_MSK; - struct iwl_mvm_tcm_mac *mdata = &mvm->tcm.data[mac]; + struct iwl_mvm_tcm_mac *mdata; + + if (mac >= NUM_MAC_INDEX_DRIVER) + return -EINVAL; + + mdata = &mvm->tcm.data[mac]; mdata->tx.pkts[ac]++; + + return 0; } /* @@ -1162,7 +1174,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, spin_unlock(&mvmsta->lock); - iwl_mvm_tx_pkt_queued(mvm, mvmsta, tid == IWL_MAX_TID_COUNT ? 0 : tid); + if (iwl_mvm_tx_pkt_queued(mvm, mvmsta, + tid == IWL_MAX_TID_COUNT ? 0 : tid)) + goto drop; return 0; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 156ca1b1f621..af2791502b7d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -214,7 +214,11 @@ static int iwl_pcie_gen2_set_tb(struct iwl_trans *trans, { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int idx = iwl_pcie_gen2_get_num_tbs(trans, tfd); - struct iwl_tfh_tb *tb = &tfd->tbs[idx]; + struct iwl_tfh_tb *tb; + + if (WARN_ON(idx >= IWL_NUM_OF_TBS)) + return -EINVAL; + tb = &tfd->tbs[idx]; /* Each TFD can point to a maximum max_tbs Tx buffers */ if (le16_to_cpu(tfd->num_tbs) >= trans_pcie->max_tbs) { -- cgit v1.2.3 From c1f33442976b52676aa8b5ee9140b0b85bb4bd75 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Mon, 22 Oct 2018 10:12:28 +0300 Subject: iwlwifi: memcpy from dev_cmd and not dev_cmd->hdr Klocwork complains about copying from dev_cmd->hdr if copying more than 4 bytes since it means part of the copy is from the next field. This isn't a real bug, but for not failing Klocwork next time - fix this. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 4 ++-- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index af2791502b7d..d2bd7f528a20 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -412,7 +412,7 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx_amsdu(struct iwl_trans *trans, goto out_err; /* building the A-MSDU might have changed this data, memcpy it now */ - memcpy(&txq->first_tb_bufs[idx], &dev_cmd->hdr, IWL_FIRST_TB_SIZE); + memcpy(&txq->first_tb_bufs[idx], dev_cmd, IWL_FIRST_TB_SIZE); return tfd; out_err: @@ -473,7 +473,7 @@ iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans, tb_phys = iwl_pcie_get_first_tb_dma(txq, idx); /* The first TB points to bi-directional DMA data */ - memcpy(&txq->first_tb_bufs[idx], &dev_cmd->hdr, IWL_FIRST_TB_SIZE); + memcpy(&txq->first_tb_bufs[idx], dev_cmd, IWL_FIRST_TB_SIZE); iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, IWL_FIRST_TB_SIZE); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index ee990a7a5411..7073116c73b7 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -2438,8 +2438,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, } /* building the A-MSDU might have changed this data, so memcpy it now */ - memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr, - IWL_FIRST_TB_SIZE); + memcpy(&txq->first_tb_bufs[txq->write_ptr], dev_cmd, IWL_FIRST_TB_SIZE); tfd = iwl_pcie_get_tfd(trans, txq, txq->write_ptr); /* Set up entry for this TFD in Tx byte-count array */ -- cgit v1.2.3 From b0d795a9ae558209656b18930c2b4def5f8fdfb8 Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Sun, 21 Oct 2018 18:27:26 +0300 Subject: iwlwifi: mvm: avoid possible access out of array. The value in txq_id can be out of array scope, validate it before accessing the array. Signed-off-by: Mordechay Goodstein Fixes: cf961e16620f ("iwlwifi: mvm: support dqa-mode agg on non-shared queue") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 09f294c466da..5f42897dcd55 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2702,7 +2702,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_tid_data *tid_data; u16 normalized_ssn; - int txq_id; + u16 txq_id; int ret; if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) @@ -2744,17 +2744,24 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, */ txq_id = mvmsta->tid_data[tid].txq_id; if (txq_id == IWL_MVM_INVALID_QUEUE) { - txq_id = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, - IWL_MVM_DQA_MIN_DATA_QUEUE, - IWL_MVM_DQA_MAX_DATA_QUEUE); - if (txq_id < 0) { - ret = txq_id; + ret = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, + IWL_MVM_DQA_MIN_DATA_QUEUE, + IWL_MVM_DQA_MAX_DATA_QUEUE); + if (ret < 0) { IWL_ERR(mvm, "Failed to allocate agg queue\n"); goto out; } + txq_id = ret; + /* TXQ hasn't yet been enabled, so mark it only as reserved */ mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_RESERVED; + } else if (WARN_ON(txq_id >= IWL_MAX_HW_QUEUES)) { + ret = -ENXIO; + IWL_ERR(mvm, "tid_id %d out of range (0, %d)!\n", + tid, IWL_MAX_HW_QUEUES - 1); + goto out; + } else if (unlikely(mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_SHARED)) { ret = -ENXIO; -- cgit v1.2.3 From acf42a957e341abcafd28d5e89a5e8bfffd67989 Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Sun, 21 Oct 2018 18:48:13 +0300 Subject: iwlwifi: avoid access out of memory allocated The value in num_lmac can be bigger than mem_cfg->lmac array, warn in case it's bigger. Signed-off-by: Mordechay Goodstein Fixes: 68025d5f9bfe ("iwlwifi: dbg: refactor dump code to improve readability") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 56e99b5661f7..a97bf17da14d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -748,6 +748,9 @@ static int iwl_fw_rxf_len(struct iwl_fw_runtime *fwrt, ADD_LEN(fifo_len, mem_cfg->rxfifo2_size, hdr_len); /* Count RXF1 sizes */ + if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC)) + mem_cfg->num_lmacs = MAX_NUM_LMAC; + for (i = 0; i < mem_cfg->num_lmacs; i++) ADD_LEN(fifo_len, mem_cfg->lmac[i].rxfifo1_size, hdr_len); @@ -766,6 +769,9 @@ static int iwl_fw_txf_len(struct iwl_fw_runtime *fwrt, goto dump_internal_txf; /* Count TXF sizes */ + if (WARN_ON(mem_cfg->num_lmacs > MAX_NUM_LMAC)) + mem_cfg->num_lmacs = MAX_NUM_LMAC; + for (i = 0; i < mem_cfg->num_lmacs; i++) { int j; -- cgit v1.2.3 From f9119304e1c9c6a634afe9a88f8b228f3997109d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 23 Oct 2018 20:51:56 +0200 Subject: iwlwifi: fw api: remove unused/deprecated filter status These are unused by both firmware and driver, remove them. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/rx.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 0791a854fc8f..b4f7ea30a7c1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -209,8 +209,6 @@ enum iwl_rx_phy_flags { * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors * @RX_MPDU_RES_STATUS_STA_ID_MSK: station ID mask * @RX_MDPU_RES_STATUS_STA_ID_SHIFT: station ID bit shift - * @RX_MPDU_RES_STATUS_FILTERING_MSK: filter status - * @RX_MPDU_RES_STATUS2_FILTERING_MSK: filter status 2 */ enum iwl_mvm_rx_status { RX_MPDU_RES_STATUS_CRC_OK = BIT(0), @@ -238,8 +236,6 @@ enum iwl_mvm_rx_status { RX_MPDU_RES_STATUS_CSUM_OK = BIT(17), RX_MDPU_RES_STATUS_STA_ID_SHIFT = 24, RX_MPDU_RES_STATUS_STA_ID_MSK = 0x1f << RX_MDPU_RES_STATUS_STA_ID_SHIFT, - RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000), - RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000), }; /* 9000 series API */ -- cgit v1.2.3 From ec95b2701d244501068690ad2c43d184413ffc85 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 24 Oct 2018 09:50:08 +0200 Subject: iwlwifi: fw api: document WoWLAN patterns command Document the WoWLAN patterns command structure. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/d3.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 6fae02fa4cad..86ea0784e1a3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -224,8 +224,18 @@ struct iwl_wowlan_pattern { #define IWL_WOWLAN_MAX_PATTERNS 20 +/** + * struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns + */ struct iwl_wowlan_patterns_cmd { + /** + * @n_patterns: number of patterns + */ __le32 n_patterns; + + /** + * @patterns: the patterns, array length in @n_patterns + */ struct iwl_wowlan_pattern patterns[]; } __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */ -- cgit v1.2.3 From 94816278383eab18c660652bfb7bc929c0d7aef1 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Tue, 25 Sep 2018 12:05:22 +0300 Subject: net/mlx5e: RX, Make sure packet header does not cross page boundary In the non-linear SKB memory scheme of Striding RQ, a packet header could cross page boundary. This requires special care in fast path that costs LoC, additional runtime instructions and branches. It could happen when the header (up to 256B) does not fit in a single stride. Avoid this by working with a stride size that fits the maximum possible header. Stride is increased form 64B to 256B. Performance: Tested packet rate for UDP streams, single ring, on ConnectX-5. Configuration: Set Striding RQ and LRO ON (to enabled the non-linear SKB scheme). GRO OFF, early drop by TC rule. 64B: 4x worse memory utilization, no page-crossers headers - No degradation (5,887,305 pps). - The reduction in memory utilization is compensated by the saving of branches tests. 192B: 1.33x worse memory utilization, avoid page-crossers headers - Before: 5,727,252. After: 5,777,037. ~1% gain. 256B: Same memory util, no page-crossers - Before: 5,691,885. After: 5,748,007. ~1% gain. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 11 ++++----- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 +-- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 27 ++++------------------- 3 files changed, 9 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 8fa8fdd30b85..6def2c972bf0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -76,15 +76,14 @@ struct page_pool; #define MLX5_SKB_FRAG_SZ(len) (SKB_DATA_ALIGN(len) + \ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) +#define MLX5E_RX_MAX_HEAD (256) + #define MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(mdev) \ (6 + MLX5_CAP_GEN(mdev, cache_line_128byte)) /* HW restriction */ #define MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, req) \ max_t(u32, MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(mdev), req) -#define MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev) MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, 6) -#define MLX5_MPWRQ_CQE_CMPRS_LOG_STRIDE_SZ(mdev) MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, 8) -#define MLX5E_MPWQE_STRIDE_SZ(mdev, cqe_cmprs) \ - (cqe_cmprs ? MLX5_MPWRQ_CQE_CMPRS_LOG_STRIDE_SZ(mdev) : \ - MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev)) +#define MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev) \ + MLX5_MPWRQ_LOG_STRIDE_SZ(mdev, order_base_2(MLX5E_RX_MAX_HEAD)) #define MLX5_MPWRQ_LOG_WQE_SZ 18 #define MLX5_MPWRQ_WQE_PAGE_ORDER (MLX5_MPWRQ_LOG_WQE_SZ - PAGE_SHIFT > 0 ? \ @@ -119,8 +118,6 @@ struct page_pool; #define MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE_MPW 0x2 -#define MLX5E_RX_MAX_HEAD (256) - #define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024) #define MLX5E_DEFAULT_LRO_TIMEOUT 32 #define MLX5E_LRO_TIMEOUT_ARR_SIZE 4 diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 8cfd2ec7c0a2..1bf547a2b905 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -171,8 +171,7 @@ static u8 mlx5e_mpwqe_get_log_stride_size(struct mlx5_core_dev *mdev, if (mlx5e_rx_mpwqe_is_linear_skb(mdev, params)) return order_base_2(mlx5e_rx_get_linear_frag_sz(params)); - return MLX5E_MPWQE_STRIDE_SZ(mdev, - MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)); + return MLX5_MPWRQ_DEF_LOG_STRIDE_SZ(mdev); } static u8 mlx5e_mpwqe_get_log_num_strides(struct mlx5_core_dev *mdev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index f86e4804e83e..c02532254411 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -369,7 +369,7 @@ mlx5e_add_skb_frag(struct mlx5e_rq *rq, struct sk_buff *skb, static inline void mlx5e_copy_skb_header(struct device *pdev, struct sk_buff *skb, struct mlx5e_dma_info *dma_info, - int offset_from, int offset_to, u32 headlen) + int offset_from, u32 headlen) { const void *from = page_address(dma_info->page) + offset_from; /* Aligning len to sizeof(long) optimizes memcpy performance */ @@ -377,24 +377,7 @@ mlx5e_copy_skb_header(struct device *pdev, struct sk_buff *skb, dma_sync_single_for_cpu(pdev, dma_info->addr + offset_from, len, DMA_FROM_DEVICE); - skb_copy_to_linear_data_offset(skb, offset_to, from, len); -} - -static inline void -mlx5e_copy_skb_header_mpwqe(struct device *pdev, - struct sk_buff *skb, - struct mlx5e_dma_info *dma_info, - u32 offset, u32 headlen) -{ - u16 headlen_pg = min_t(u32, headlen, PAGE_SIZE - offset); - - mlx5e_copy_skb_header(pdev, skb, dma_info, offset, 0, headlen_pg); - - if (unlikely(offset + headlen > PAGE_SIZE)) { - dma_info++; - mlx5e_copy_skb_header(pdev, skb, dma_info, 0, headlen_pg, - headlen - headlen_pg); - } + skb_copy_to_linear_data(skb, from, len); } static void @@ -973,8 +956,7 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe, } /* copy header */ - mlx5e_copy_skb_header(rq->pdev, skb, head_wi->di, head_wi->offset, - 0, headlen); + mlx5e_copy_skb_header(rq->pdev, skb, head_wi->di, head_wi->offset, headlen); /* skb linear part was allocated with headlen and aligned to long */ skb->tail += headlen; skb->len += headlen; @@ -1096,8 +1078,7 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w di++; } /* copy header */ - mlx5e_copy_skb_header_mpwqe(rq->pdev, skb, head_di, - head_offset, headlen); + mlx5e_copy_skb_header(rq->pdev, skb, head_di, head_offset, headlen); /* skb linear part was allocated with headlen and aligned to long */ skb->tail += headlen; skb->len += headlen; -- cgit v1.2.3 From 79d356ef2c10b19fdd3269b975579aa0be21710c Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 12 Sep 2018 18:32:49 +0300 Subject: net/mlx5e: Take CQ decompress fields into a separate structure Only the Receive CQ makes use of these fields. Take them out into a separate struct and save space in the generic CQ structure. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 15 +-- drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 127 ++++++++++++++---------- 2 files changed, 81 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 6def2c972bf0..587f94d68dc9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -306,16 +306,18 @@ struct mlx5e_cq { struct mlx5_core_cq mcq; struct mlx5e_channel *channel; + /* control */ + struct mlx5_core_dev *mdev; + struct mlx5_wq_ctrl wq_ctrl; +} ____cacheline_aligned_in_smp; + +struct mlx5e_cq_decomp { /* cqe decompression */ struct mlx5_cqe64 title; struct mlx5_mini_cqe8 mini_arr[MLX5_MINI_CQE_ARRAY_SIZE]; u8 mini_arr_idx; - u16 decmprs_left; - u16 decmprs_wqe_counter; - - /* control */ - struct mlx5_core_dev *mdev; - struct mlx5_wq_ctrl wq_ctrl; + u16 left; + u16 wqe_counter; } ____cacheline_aligned_in_smp; struct mlx5e_tx_wqe_info { @@ -578,6 +580,7 @@ struct mlx5e_rq { struct net_device *netdev; struct mlx5e_rq_stats *stats; struct mlx5e_cq cq; + struct mlx5e_cq_decomp cqd; struct mlx5e_page_cache page_cache; struct hwtstamp_config *tstamp; struct mlx5_clock *clock; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index c02532254411..be396e5e4e39 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -52,40 +52,45 @@ static inline bool mlx5e_rx_hw_stamp(struct hwtstamp_config *config) return config->rx_filter == HWTSTAMP_FILTER_ALL; } -static inline void mlx5e_read_cqe_slot(struct mlx5e_cq *cq, u32 cqcc, - void *data) +static inline void mlx5e_read_cqe_slot(struct mlx5_cqwq *wq, + u32 cqcc, void *data) { - u32 ci = mlx5_cqwq_ctr2ix(&cq->wq, cqcc); + u32 ci = mlx5_cqwq_ctr2ix(wq, cqcc); - memcpy(data, mlx5_cqwq_get_wqe(&cq->wq, ci), sizeof(struct mlx5_cqe64)); + memcpy(data, mlx5_cqwq_get_wqe(wq, ci), sizeof(struct mlx5_cqe64)); } static inline void mlx5e_read_title_slot(struct mlx5e_rq *rq, - struct mlx5e_cq *cq, u32 cqcc) + struct mlx5_cqwq *wq, + u32 cqcc) { - mlx5e_read_cqe_slot(cq, cqcc, &cq->title); - cq->decmprs_left = be32_to_cpu(cq->title.byte_cnt); - cq->decmprs_wqe_counter = be16_to_cpu(cq->title.wqe_counter); + struct mlx5e_cq_decomp *cqd = &rq->cqd; + struct mlx5_cqe64 *title = &cqd->title; + + mlx5e_read_cqe_slot(wq, cqcc, title); + cqd->left = be32_to_cpu(title->byte_cnt); + cqd->wqe_counter = be16_to_cpu(title->wqe_counter); rq->stats->cqe_compress_blks++; } -static inline void mlx5e_read_mini_arr_slot(struct mlx5e_cq *cq, u32 cqcc) +static inline void mlx5e_read_mini_arr_slot(struct mlx5_cqwq *wq, + struct mlx5e_cq_decomp *cqd, + u32 cqcc) { - mlx5e_read_cqe_slot(cq, cqcc, cq->mini_arr); - cq->mini_arr_idx = 0; + mlx5e_read_cqe_slot(wq, cqcc, cqd->mini_arr); + cqd->mini_arr_idx = 0; } -static inline void mlx5e_cqes_update_owner(struct mlx5e_cq *cq, u32 cqcc, int n) +static inline void mlx5e_cqes_update_owner(struct mlx5_cqwq *wq, int n) { - struct mlx5_cqwq *wq = &cq->wq; - + u32 cqcc = wq->cc; u8 op_own = mlx5_cqwq_get_ctr_wrap_cnt(wq, cqcc) & 1; u32 ci = mlx5_cqwq_ctr2ix(wq, cqcc); u32 wq_sz = mlx5_cqwq_get_size(wq); u32 ci_top = min_t(u32, wq_sz, ci + n); for (; ci < ci_top; ci++, n--) { - struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, ci); + struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(wq, ci); cqe->op_own = op_own; } @@ -93,7 +98,7 @@ static inline void mlx5e_cqes_update_owner(struct mlx5e_cq *cq, u32 cqcc, int n) if (unlikely(ci == wq_sz)) { op_own = !op_own; for (ci = 0; ci < n; ci++) { - struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, ci); + struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(wq, ci); cqe->op_own = op_own; } @@ -101,68 +106,79 @@ static inline void mlx5e_cqes_update_owner(struct mlx5e_cq *cq, u32 cqcc, int n) } static inline void mlx5e_decompress_cqe(struct mlx5e_rq *rq, - struct mlx5e_cq *cq, u32 cqcc) + struct mlx5_cqwq *wq, + u32 cqcc) { - cq->title.byte_cnt = cq->mini_arr[cq->mini_arr_idx].byte_cnt; - cq->title.check_sum = cq->mini_arr[cq->mini_arr_idx].checksum; - cq->title.op_own &= 0xf0; - cq->title.op_own |= 0x01 & (cqcc >> cq->wq.fbc.log_sz); - cq->title.wqe_counter = cpu_to_be16(cq->decmprs_wqe_counter); + struct mlx5e_cq_decomp *cqd = &rq->cqd; + struct mlx5_mini_cqe8 *mini_cqe = &cqd->mini_arr[cqd->mini_arr_idx]; + struct mlx5_cqe64 *title = &cqd->title; + + title->byte_cnt = mini_cqe->byte_cnt; + title->check_sum = mini_cqe->checksum; + title->op_own &= 0xf0; + title->op_own |= 0x01 & (cqcc >> wq->fbc.log_sz); + title->wqe_counter = cpu_to_be16(cqd->wqe_counter); if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) - cq->decmprs_wqe_counter += - mpwrq_get_cqe_consumed_strides(&cq->title); + cqd->wqe_counter += mpwrq_get_cqe_consumed_strides(title); else - cq->decmprs_wqe_counter = - mlx5_wq_cyc_ctr2ix(&rq->wqe.wq, cq->decmprs_wqe_counter + 1); + cqd->wqe_counter = + mlx5_wq_cyc_ctr2ix(&rq->wqe.wq, cqd->wqe_counter + 1); } static inline void mlx5e_decompress_cqe_no_hash(struct mlx5e_rq *rq, - struct mlx5e_cq *cq, u32 cqcc) + struct mlx5_cqwq *wq, + u32 cqcc) { - mlx5e_decompress_cqe(rq, cq, cqcc); - cq->title.rss_hash_type = 0; - cq->title.rss_hash_result = 0; + struct mlx5e_cq_decomp *cqd = &rq->cqd; + + mlx5e_decompress_cqe(rq, wq, cqcc); + cqd->title.rss_hash_type = 0; + cqd->title.rss_hash_result = 0; } static inline u32 mlx5e_decompress_cqes_cont(struct mlx5e_rq *rq, - struct mlx5e_cq *cq, + struct mlx5_cqwq *wq, int update_owner_only, int budget_rem) { - u32 cqcc = cq->wq.cc + update_owner_only; + struct mlx5e_cq_decomp *cqd = &rq->cqd; + u32 cqcc = wq->cc + update_owner_only; u32 cqe_count; u32 i; - cqe_count = min_t(u32, cq->decmprs_left, budget_rem); + cqe_count = min_t(u32, cqd->left, budget_rem); for (i = update_owner_only; i < cqe_count; - i++, cq->mini_arr_idx++, cqcc++) { - if (cq->mini_arr_idx == MLX5_MINI_CQE_ARRAY_SIZE) - mlx5e_read_mini_arr_slot(cq, cqcc); + i++, cqd->mini_arr_idx++, cqcc++) { + if (cqd->mini_arr_idx == MLX5_MINI_CQE_ARRAY_SIZE) + mlx5e_read_mini_arr_slot(wq, cqd, cqcc); - mlx5e_decompress_cqe_no_hash(rq, cq, cqcc); - rq->handle_rx_cqe(rq, &cq->title); + mlx5e_decompress_cqe_no_hash(rq, wq, cqcc); + rq->handle_rx_cqe(rq, &cqd->title); } - mlx5e_cqes_update_owner(cq, cq->wq.cc, cqcc - cq->wq.cc); - cq->wq.cc = cqcc; - cq->decmprs_left -= cqe_count; + mlx5e_cqes_update_owner(wq, cqcc - wq->cc); + wq->cc = cqcc; + cqd->left -= cqe_count; rq->stats->cqe_compress_pkts += cqe_count; return cqe_count; } static inline u32 mlx5e_decompress_cqes_start(struct mlx5e_rq *rq, - struct mlx5e_cq *cq, + struct mlx5_cqwq *wq, int budget_rem) { - mlx5e_read_title_slot(rq, cq, cq->wq.cc); - mlx5e_read_mini_arr_slot(cq, cq->wq.cc + 1); - mlx5e_decompress_cqe(rq, cq, cq->wq.cc); - rq->handle_rx_cqe(rq, &cq->title); - cq->mini_arr_idx++; + struct mlx5e_cq_decomp *cqd = &rq->cqd; + u32 cc = wq->cc; - return mlx5e_decompress_cqes_cont(rq, cq, 1, budget_rem) - 1; + mlx5e_read_title_slot(rq, wq, cc); + mlx5e_read_mini_arr_slot(wq, cqd, cc + 1); + mlx5e_decompress_cqe(rq, wq, cc); + rq->handle_rx_cqe(rq, &cqd->title); + cqd->mini_arr_idx++; + + return mlx5e_decompress_cqes_cont(rq, wq, 1, budget_rem) - 1; } static inline bool mlx5e_page_is_reserved(struct page *page) @@ -1184,16 +1200,17 @@ mpwrq_cqe_out: int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget) { struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq); + struct mlx5_cqwq *cqwq = &cq->wq; struct mlx5_cqe64 *cqe; int work_done = 0; if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state))) return 0; - if (cq->decmprs_left) - work_done += mlx5e_decompress_cqes_cont(rq, cq, 0, budget); + if (rq->cqd.left) + work_done += mlx5e_decompress_cqes_cont(rq, cqwq, 0, budget); - cqe = mlx5_cqwq_get_cqe(&cq->wq); + cqe = mlx5_cqwq_get_cqe(cqwq); if (!cqe) { if (unlikely(work_done)) goto out; @@ -1203,21 +1220,21 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget) do { if (mlx5_get_cqe_format(cqe) == MLX5_COMPRESSED) { work_done += - mlx5e_decompress_cqes_start(rq, cq, + mlx5e_decompress_cqes_start(rq, cqwq, budget - work_done); continue; } - mlx5_cqwq_pop(&cq->wq); + mlx5_cqwq_pop(cqwq); rq->handle_rx_cqe(rq, cqe); - } while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(&cq->wq))); + } while ((++work_done < budget) && (cqe = mlx5_cqwq_get_cqe(cqwq))); out: if (rq->xdp_prog) mlx5e_xdp_rx_poll_complete(rq); - mlx5_cqwq_update_db_record(&cq->wq); + mlx5_cqwq_update_db_record(cqwq); /* ensure cq space is freed before enabling more cqes */ wmb(); -- cgit v1.2.3 From 149e566fef8120a00c49f24e8f570186200e1e81 Mon Sep 17 00:00:00 2001 From: Moshe Shemesh Date: Thu, 25 Oct 2018 15:03:38 +0300 Subject: net/mlx5e: Expand XPS cpumask to cover all online cpus Currently we have one cpu in XPS cpumask per tx queue, this is good enough for default configuration where there is a tx queue per cpu. However, once configuration changes to use less tx queues, part of the cpus are not XPS-mapped and so the select queue decision falls back to hash calculation and balancing is not guaranteed. Expand XPS cpumask to enable using all cpus even when number of tx queues is smaller than number of cpus. Signed-off-by: Moshe Shemesh Reviewed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 34 +++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 587f94d68dc9..3e35a90cf21a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -638,6 +638,7 @@ struct mlx5e_channel { struct hwtstamp_config *tstamp; int ix; int cpu; + cpumask_var_t xps_cpumask; }; struct mlx5e_channels { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 1bf547a2b905..2cf6816f1426 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1949,6 +1949,29 @@ static int mlx5e_set_tx_maxrate(struct net_device *dev, int index, u32 rate) return err; } +static int mlx5e_alloc_xps_cpumask(struct mlx5e_channel *c, + struct mlx5e_params *params) +{ + int num_comp_vectors = mlx5_comp_vectors_count(c->mdev); + int irq; + + if (!zalloc_cpumask_var(&c->xps_cpumask, GFP_KERNEL)) + return -ENOMEM; + + for (irq = c->ix; irq < num_comp_vectors; irq += params->num_channels) { + int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(c->mdev, irq)); + + cpumask_set_cpu(cpu, c->xps_cpumask); + } + + return 0; +} + +static void mlx5e_free_xps_cpumask(struct mlx5e_channel *c) +{ + free_cpumask_var(c->xps_cpumask); +} + static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, struct mlx5e_params *params, struct mlx5e_channel_param *cparam, @@ -1981,9 +2004,12 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix, c->num_tc = params->num_tc; c->xdp = !!params->xdp_prog; c->stats = &priv->channel_stats[ix].ch; - c->irq_desc = irq_to_desc(irq); + err = mlx5e_alloc_xps_cpumask(c, params); + if (err) + goto err_free_channel; + netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64); err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq_cq, &c->icosq.cq); @@ -2066,6 +2092,9 @@ err_close_icosq_cq: err_napi_del: netif_napi_del(&c->napi); + mlx5e_free_xps_cpumask(c); + +err_free_channel: kvfree(c); return err; @@ -2078,7 +2107,7 @@ static void mlx5e_activate_channel(struct mlx5e_channel *c) for (tc = 0; tc < c->num_tc; tc++) mlx5e_activate_txqsq(&c->sq[tc]); mlx5e_activate_rq(&c->rq); - netif_set_xps_queue(c->netdev, get_cpu_mask(c->cpu), c->ix); + netif_set_xps_queue(c->netdev, c->xps_cpumask, c->ix); } static void mlx5e_deactivate_channel(struct mlx5e_channel *c) @@ -2106,6 +2135,7 @@ static void mlx5e_close_channel(struct mlx5e_channel *c) mlx5e_close_tx_cqs(c); mlx5e_close_cq(&c->icosq.cq); netif_napi_del(&c->napi); + mlx5e_free_xps_cpumask(c); kvfree(c); } -- cgit v1.2.3 From 71129676ab59dc63ba9e48a09a3386242a516751 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Sun, 20 Jan 2019 10:30:25 +0200 Subject: net/mlx5e: Return the allocated flow directly from __mlx5e_add_fdb_flow This confusing construction confuses the compiler which can't see that flow is initialized if !err: drivers/net/ethernet/mellanox/mlx5/core/en_tc.c: In function `mlx5e_configure_flower` drivers/net/ethernet/mellanox/mlx5/core/en_tc.c:2727:28: warning: `flow` may be used uninitialized in this function [-Wmaybe-uninitialized] There is no reason for two function outputs, just return the pointer directly and use ERR_PTR to encode a failure. Signed-off-by: Jason Gunthorpe Signed-off-by: Tariq Toukan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index cae6c6d48984..74159d39dd66 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2767,14 +2767,13 @@ err_free: return err; } -static int +static struct mlx5e_tc_flow * __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct tc_cls_flower_offload *f, u16 flow_flags, struct net_device *filter_dev, struct mlx5_eswitch_rep *in_rep, - struct mlx5_core_dev *in_mdev, - struct mlx5e_tc_flow **__flow) + struct mlx5_core_dev *in_mdev) { struct netlink_ext_ack *extack = f->common.extack; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; @@ -2814,15 +2813,13 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, if (err) goto err_free; - *__flow = flow; - - return 0; + return flow; err_free: kfree(flow); kvfree(parse_attr); out: - return err; + return ERR_PTR(err); } static int mlx5e_tc_add_fdb_peer_flow(struct tc_cls_flower_offload *f, @@ -2855,11 +2852,13 @@ static int mlx5e_tc_add_fdb_peer_flow(struct tc_cls_flower_offload *f, in_mdev = priv->mdev; parse_attr = flow->esw_attr->parse_attr; - err = __mlx5e_add_fdb_flow(peer_priv, f, flow->flags, - parse_attr->filter_dev, - flow->esw_attr->in_rep, in_mdev, &peer_flow); - if (err) + peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow->flags, + parse_attr->filter_dev, + flow->esw_attr->in_rep, in_mdev); + if (IS_ERR(peer_flow)) { + err = PTR_ERR(peer_flow); goto out; + } flow->peer_flow = peer_flow; flow->flags |= MLX5E_TC_FLOW_DUP; @@ -2885,10 +2884,10 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow; int err; - err = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep, - in_mdev, &flow); - if (err) - goto out; + flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep, + in_mdev); + if (IS_ERR(flow)) + return PTR_ERR(flow); if (is_peer_flow_needed(flow)) { err = mlx5e_tc_add_fdb_peer_flow(f, flow); -- cgit v1.2.3 From 8e4ca98609a55d696c96dd260df7a2c5f7398299 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Tue, 18 Dec 2018 21:18:20 +0200 Subject: net/mlx5: Add trace points for flow tables create/destroy We were not tracking flow tables so far, add it up. Signed-off-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- .../mellanox/mlx5/core/diag/fs_tracepoint.c | 2 ++ .../mellanox/mlx5/core/diag/fs_tracepoint.h | 35 ++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 2 ++ 3 files changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c index 424457ff9759..8ecac81a385d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c @@ -258,6 +258,8 @@ const char *parse_fs_dst(struct trace_seq *p, return ret; } +EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_ft); +EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_ft); EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_fg); EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fg); EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_set_fte); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h index d027ce00c8ce..a4cf123e3f17 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h @@ -61,6 +61,41 @@ const char *parse_fs_dst(struct trace_seq *p, const struct mlx5_flow_destination *dst, u32 counter_id); +TRACE_EVENT(mlx5_fs_add_ft, + TP_PROTO(const struct mlx5_flow_table *ft), + TP_ARGS(ft), + TP_STRUCT__entry( + __field(const struct mlx5_flow_table *, ft) + __field(u32, id) + __field(u32, level) + __field(u32, type) + ), + TP_fast_assign( + __entry->ft = ft; + __entry->id = ft->id; + __entry->level = ft->level; + __entry->type = ft->type; + ), + TP_printk("ft=%p id=%u level=%u type=%u \n", + __entry->ft, __entry->id, __entry->level, __entry->type) + ); + +TRACE_EVENT(mlx5_fs_del_ft, + TP_PROTO(const struct mlx5_flow_table *ft), + TP_ARGS(ft), + TP_STRUCT__entry( + __field(const struct mlx5_flow_table *, ft) + __field(u32, id) + ), + TP_fast_assign( + __entry->ft = ft; + __entry->id = ft->id; + + ), + TP_printk("ft=%p id=%u\n", + __entry->ft, __entry->id) + ); + TRACE_EVENT(mlx5_fs_add_fg, TP_PROTO(const struct mlx5_flow_group *fg), TP_ARGS(fg), diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 79f122b45def..b2df7c3749fb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -397,6 +397,7 @@ static void del_hw_flow_table(struct fs_node *node) fs_get_obj(ft, node); dev = get_dev(&ft->node); root = find_root(&ft->node); + trace_mlx5_fs_del_ft(ft); if (node->active) { err = root->cmds->destroy_flow_table(dev, ft); @@ -1019,6 +1020,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa fs_prio->num_ft++; up_write_ref_node(&fs_prio->node); mutex_unlock(&root->chain_lock); + trace_mlx5_fs_add_ft(ft); return ft; destroy_ft: root->cmds->destroy_flow_table(root->dev, ft); -- cgit v1.2.3 From 9659e49a6db45474000e4df1a2875bd0d5ab2390 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Fri, 2 Nov 2018 18:21:27 -0700 Subject: net/mlx5e: Separate between ethtool and netdev software stats folding mlx5e_grp_sw_update_stats can be called from two threads, 1) ndo_get_stats64 2) get_ethtool_stats For this reason and to minimize concurrency issue impact on 64bit machines mlx5e_grp_sw_update_stats folds the software stats into a temporary variable then copies it to the global driver stats, both ethtool and ndo statistics callbacks will use the global software stats variable to report whatever stats they need. Actually ndo_get_stats64 doesn't need to fold the whole software stats (mlx5e_grp_sw_update_stats), all it needs is five counters to fill the rtnl_link_stats64 relevant stats parameter. Hence this patch introduces a simpler helper function to fold software stats for ndo_get_stats64 which will work directly on rtnl_link_stats64 stats parameter and not on the global or even temporary mlx5e_sw_stats variable. Since now mlx5e_grp_sw_update_stats is not called by ndo_get_stats64 we can make it static and remove the temp var. Unlike mlx5e_grp_sw_update_stats the new fold stats function doesn't need to zero out the output statistics parameter since it is already done by the stack @dev_get_stats(). This patch is fixing stack usage of mlx5e_grp_sw_update_stats on x86 gcc-4.9 and higher, the concurrency issue between mlx5's ndo_get_stats64 and get_ethtool_stats is resolved as well. Fixes: 8bfaf07f7806 ("net/mlx5e: Present SW stats when state is not opened") Reported-by: Arnd Bergmann Reported-by: Andrew Morton Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 30 +++++++++++++++++----- drivers/net/ethernet/mellanox/mlx5/core/en_stats.c | 6 ++--- drivers/net/ethernet/mellanox/mlx5/core/en_stats.h | 1 - 3 files changed, 25 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 2cf6816f1426..01d0895b6264 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3521,11 +3521,32 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type, } } +static void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s) +{ + int i; + + for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) { + struct mlx5e_channel_stats *channel_stats = &priv->channel_stats[i]; + struct mlx5e_rq_stats *rq_stats = &channel_stats->rq; + int j; + + s->rx_packets += rq_stats->packets; + s->rx_bytes += rq_stats->bytes; + + for (j = 0; j < priv->max_opened_tc; j++) { + struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j]; + + s->tx_packets += sq_stats->packets; + s->tx_bytes += sq_stats->bytes; + s->tx_dropped += sq_stats->dropped; + } + } +} + void mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct mlx5e_priv *priv = netdev_priv(dev); - struct mlx5e_sw_stats *sstats = &priv->stats.sw; struct mlx5e_vport_stats *vstats = &priv->stats.vport; struct mlx5e_pport_stats *pstats = &priv->stats.pport; @@ -3540,12 +3561,7 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) stats->tx_packets = PPORT_802_3_GET(pstats, a_frames_transmitted_ok); stats->tx_bytes = PPORT_802_3_GET(pstats, a_octets_transmitted_ok); } else { - mlx5e_grp_sw_update_stats(priv); - stats->rx_packets = sstats->rx_packets; - stats->rx_bytes = sstats->rx_bytes; - stats->tx_packets = sstats->tx_packets; - stats->tx_bytes = sstats->tx_bytes; - stats->tx_dropped = sstats->tx_queue_dropped; + mlx5e_fold_sw_stats64(priv, stats); } stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index d3fe48ff9da9..1a78e05cbba8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -127,9 +127,9 @@ static int mlx5e_grp_sw_fill_stats(struct mlx5e_priv *priv, u64 *data, int idx) return idx; } -void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv) +static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv) { - struct mlx5e_sw_stats temp, *s = &temp; + struct mlx5e_sw_stats *s = &priv->stats.sw; int i; memset(s, 0, sizeof(*s)); @@ -212,8 +212,6 @@ void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv) s->tx_cqes += sq_stats->cqes; } } - - memcpy(&priv->stats.sw, s, sizeof(*s)); } static const struct counter_desc q_stats_desc[] = { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index fe91ec06e3c7..4640d4f986f8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -277,7 +277,6 @@ struct mlx5e_stats_grp { extern const struct mlx5e_stats_grp mlx5e_stats_grps[]; extern const int mlx5e_num_stats_grps; -void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv); void mlx5e_grp_802_3_update_stats(struct mlx5e_priv *priv); #endif /* __MLX5_EN_STATS_H__ */ -- cgit v1.2.3 From 168af00a3b7b4cb9522687ea08bc2dfa5e9b5774 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Thu, 8 Nov 2018 11:37:24 +0200 Subject: net/mlx5e: Present the representors SW stats when state is not opened This behavior is already adopted for all other cases in the cited patch. The representor's functions were missed, here we modify the them to behave similarly. Fixes: 8bfaf07f7806 ("net/mlx5e: Present SW stats when state is not opened") Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 04736212a21c..22f686b779ef 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -162,21 +162,19 @@ static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv) static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv) { struct mlx5e_sw_stats *s = &priv->stats.sw; - struct mlx5e_rq_stats *rq_stats; - struct mlx5e_sq_stats *sq_stats; int i, j; memset(s, 0, sizeof(*s)); - for (i = 0; i < priv->channels.num; i++) { - struct mlx5e_channel *c = priv->channels.c[i]; - - rq_stats = c->rq.stats; + for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) { + struct mlx5e_channel_stats *channel_stats = + &priv->channel_stats[i]; + struct mlx5e_rq_stats *rq_stats = &channel_stats->rq; s->rx_packets += rq_stats->packets; s->rx_bytes += rq_stats->bytes; - for (j = 0; j < priv->channels.params.num_tc; j++) { - sq_stats = c->sq[j].stats; + for (j = 0; j < priv->max_opened_tc; j++) { + struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j]; s->tx_packets += sq_stats->packets; s->tx_bytes += sq_stats->bytes; @@ -195,8 +193,7 @@ static void mlx5e_rep_get_ethtool_stats(struct net_device *dev, return; mutex_lock(&priv->state_lock); - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) - mlx5e_rep_update_sw_counters(priv); + mlx5e_rep_update_sw_counters(priv); mlx5e_rep_update_hw_counters(priv); mutex_unlock(&priv->state_lock); -- cgit v1.2.3 From b832d4fdf105b5464d786e321e3c9e012e67cdfb Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Wed, 12 Dec 2018 01:42:30 -0800 Subject: net/mlx5e: Reuse fold sw stats in representors Representors software stats are basic, this patch is reusing the mlx5e_fold_sw_stats in representors, which sums up the basic stats64 for a mlx5e netdevice. Fixes: 8bfaf07f7806 ("net/mlx5e: Present SW stats when state is not opened") Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 34 ++++++----------------- 3 files changed, 10 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 3e35a90cf21a..6dd74ef69389 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -804,6 +804,7 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe, void mlx5e_update_stats(struct mlx5e_priv *priv); void mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats); +void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s); void mlx5e_init_l2_addr(struct mlx5e_priv *priv); int mlx5e_self_test_num(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 01d0895b6264..17b6babbed8a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3521,7 +3521,7 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type, } } -static void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s) +void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s) { int i; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 22f686b779ef..edb34b397c53 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -162,25 +162,16 @@ static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv) static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv) { struct mlx5e_sw_stats *s = &priv->stats.sw; - int i, j; + struct rtnl_link_stats64 stats64 = {}; memset(s, 0, sizeof(*s)); - for (i = 0; i < mlx5e_get_netdev_max_channels(priv->netdev); i++) { - struct mlx5e_channel_stats *channel_stats = - &priv->channel_stats[i]; - struct mlx5e_rq_stats *rq_stats = &channel_stats->rq; - - s->rx_packets += rq_stats->packets; - s->rx_bytes += rq_stats->bytes; - - for (j = 0; j < priv->max_opened_tc; j++) { - struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j]; + mlx5e_fold_sw_stats64(priv, &stats64); - s->tx_packets += sq_stats->packets; - s->tx_bytes += sq_stats->bytes; - s->tx_queue_dropped += sq_stats->dropped; - } - } + s->rx_packets = stats64.rx_packets; + s->rx_bytes = stats64.rx_bytes; + s->tx_packets = stats64.tx_packets; + s->tx_bytes = stats64.tx_bytes; + s->tx_queue_dropped = stats64.tx_dropped; } static void mlx5e_rep_get_ethtool_stats(struct net_device *dev, @@ -1226,17 +1217,8 @@ mlx5e_get_sw_stats64(const struct net_device *dev, struct rtnl_link_stats64 *stats) { struct mlx5e_priv *priv = netdev_priv(dev); - struct mlx5e_sw_stats *sstats = &priv->stats.sw; - - mlx5e_rep_update_sw_counters(priv); - - stats->rx_packets = sstats->rx_packets; - stats->rx_bytes = sstats->rx_bytes; - stats->tx_packets = sstats->tx_packets; - stats->tx_bytes = sstats->tx_bytes; - - stats->tx_dropped = sstats->tx_queue_dropped; + mlx5e_fold_sw_stats64(priv, stats); return 0; } -- cgit v1.2.3 From f72b4644b224aab3f7d4f8134349b20a8dcb0575 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 25 Jan 2019 15:44:16 +0100 Subject: s390/qeth: streamline TX buffer management Consolidate the code that marks the current buffer to be flushed, and let qeth_fill_buffer() advance the Output Queue's buffer cursor. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index e63e03143ca7..e08b924f7454 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3928,7 +3928,6 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, { struct qdio_buffer *buffer = buf->buffer; bool is_first_elem = true; - int flush_cnt = 0; __skb_queue_tail(&buf->skb_list, skb); @@ -3949,24 +3948,22 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, if (!queue->do_pack) { QETH_CARD_TEXT(queue->card, 6, "fillbfnp"); - /* set state to PRIMED -> will be flushed */ - atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); - flush_cnt = 1; } else { QETH_CARD_TEXT(queue->card, 6, "fillbfpa"); if (queue->card->options.performance_stats) queue->card->perf_stats.skbs_sent_pack++; - if (buf->next_element_to_fill >= - QETH_MAX_BUFFER_ELEMENTS(queue->card)) { - /* - * packed buffer if full -> set state PRIMED - * -> will be flushed - */ - atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); - flush_cnt = 1; - } + + /* If the buffer still has free elements, keep using it. */ + if (buf->next_element_to_fill < + QETH_MAX_BUFFER_ELEMENTS(queue->card)) + return 0; } - return flush_cnt; + + /* flush out the buffer */ + atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED); + queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % + QDIO_MAX_BUFFERS_PER_Q; + return 1; } static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, @@ -3982,7 +3979,6 @@ static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue, */ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) return -EBUSY; - queue->next_buf_to_fill = (index + 1) % QDIO_MAX_BUFFERS_PER_Q; qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len); qeth_flush_buffers(queue, index, 1); return 0; @@ -4040,10 +4036,9 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, } } } - tmp = qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len); - queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) % - QDIO_MAX_BUFFERS_PER_Q; - flush_count += tmp; + + flush_count += qeth_fill_buffer(queue, buffer, skb, hdr, offset, + hd_len); if (flush_count) qeth_flush_buffers(queue, start_index, flush_count); else if (!atomic_read(&queue->set_pci_flags_count)) -- cgit v1.2.3 From 44eb086f9af9a7f562b087a70ef69506df20e9b7 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 25 Jan 2019 15:44:17 +0100 Subject: s390/qeth: remove bogus netif_wake_queue() qeth_qdio_cq_handler() doesn't replenish the Output Queue(s), and thus has no reason to wake the txq. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index e08b924f7454..f784d5c528a9 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3558,8 +3558,6 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err, card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init + count) % QDIO_MAX_BUFFERS_PER_Q; - netif_wake_queue(card->dev); - if (card->options.performance_stats) { int delta_t = qeth_get_micros(); delta_t -= card->perf_stats.cq_start_time; -- cgit v1.2.3 From e22355ea3f3cd6e3ff46b2c7d23c454762e82989 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 25 Jan 2019 15:44:18 +0100 Subject: s390/qeth: consolidate open/stop netdev ops The L2 and L3 code for these ops is almost identical, we only need to provide a custom ndo_validate_addr() for L2 that checks whether programming the MAC address succeeded. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 4 ++ drivers/s390/net/qeth_core_main.c | 53 +++++++++++++++++++++++ drivers/s390/net/qeth_l2_main.c | 88 ++++++++++----------------------------- drivers/s390/net/qeth_l3_main.c | 63 +++------------------------- 4 files changed, 84 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 0ee026947f20..ffec26ff512d 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -1047,6 +1047,10 @@ netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t); netdev_features_t qeth_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features); +int qeth_open_internal(struct net_device *dev); +int qeth_open(struct net_device *dev); +int qeth_stop(struct net_device *dev); + int qeth_vm_request_mac(struct qeth_card *card); int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index f784d5c528a9..db1aaa796bef 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -6652,6 +6652,59 @@ netdev_features_t qeth_features_check(struct sk_buff *skb, } EXPORT_SYMBOL_GPL(qeth_features_check); +int qeth_open_internal(struct net_device *dev) +{ + struct qeth_card *card = dev->ml_priv; + + QETH_CARD_TEXT(card, 4, "qethopen"); + if (card->state == CARD_STATE_UP) + return 0; + if (card->state != CARD_STATE_SOFTSETUP) + return -ENODEV; + + if (qdio_stop_irq(CARD_DDEV(card), 0) < 0) + return -EIO; + + card->data.state = CH_STATE_UP; + card->state = CARD_STATE_UP; + netif_start_queue(dev); + + napi_enable(&card->napi); + local_bh_disable(); + napi_schedule(&card->napi); + /* kick-start the NAPI softirq: */ + local_bh_enable(); + return 0; +} +EXPORT_SYMBOL_GPL(qeth_open_internal); + +int qeth_open(struct net_device *dev) +{ + struct qeth_card *card = dev->ml_priv; + + QETH_CARD_TEXT(card, 5, "qethope_"); + if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { + QETH_CARD_TEXT(card, 3, "openREC"); + return -ERESTARTSYS; + } + return qeth_open_internal(dev); +} +EXPORT_SYMBOL_GPL(qeth_open); + +int qeth_stop(struct net_device *dev) +{ + struct qeth_card *card = dev->ml_priv; + + QETH_CARD_TEXT(card, 4, "qethstop"); + netif_tx_disable(dev); + if (card->state == CARD_STATE_UP) { + card->state = CARD_STATE_SOFTSETUP; + napi_disable(&card->napi); + } + return 0; +} +EXPORT_SYMBOL_GPL(qeth_stop); + static int __init qeth_core_init(void) { int rc; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index f108d4b44605..8b9181c8bc7e 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -25,7 +25,6 @@ #include "qeth_l2.h" static int qeth_l2_set_offline(struct ccwgroup_device *); -static int qeth_l2_stop(struct net_device *); static void qeth_bridgeport_query_support(struct qeth_card *card); static void qeth_bridge_state_change(struct qeth_card *card, struct qeth_ipa_cmd *cmd); @@ -343,9 +342,8 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && (card->state == CARD_STATE_UP)) { - if (recovery_mode && - card->info.type != QETH_CARD_TYPE_OSN) { - qeth_l2_stop(card->dev); + if (recovery_mode && !IS_OSN(card)) { + qeth_stop(card->dev); } else { rtnl_lock(); dev_close(card->dev); @@ -460,6 +458,17 @@ out: return 0; } +static int qeth_l2_validate_addr(struct net_device *dev) +{ + struct qeth_card *card = dev->ml_priv; + + if (IS_OSN(card) || (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) + return eth_validate_addr(dev); + + QETH_CARD_TEXT(card, 4, "nomacadr"); + return -EPERM; +} + static int qeth_l2_set_mac_address(struct net_device *dev, void *p) { struct sockaddr *addr = p; @@ -712,62 +721,6 @@ tx_drop: return NETDEV_TX_OK; } -static int __qeth_l2_open(struct net_device *dev) -{ - struct qeth_card *card = dev->ml_priv; - int rc = 0; - - QETH_CARD_TEXT(card, 4, "qethopen"); - if (card->state == CARD_STATE_UP) - return rc; - if (card->state != CARD_STATE_SOFTSETUP) - return -ENODEV; - - if ((card->info.type != QETH_CARD_TYPE_OSN) && - (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) { - QETH_CARD_TEXT(card, 4, "nomacadr"); - return -EPERM; - } - card->data.state = CH_STATE_UP; - card->state = CARD_STATE_UP; - netif_start_queue(dev); - - if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { - napi_enable(&card->napi); - local_bh_disable(); - napi_schedule(&card->napi); - /* kick-start the NAPI softirq: */ - local_bh_enable(); - } else - rc = -EIO; - return rc; -} - -static int qeth_l2_open(struct net_device *dev) -{ - struct qeth_card *card = dev->ml_priv; - - QETH_CARD_TEXT(card, 5, "qethope_"); - if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { - QETH_CARD_TEXT(card, 3, "openREC"); - return -ERESTARTSYS; - } - return __qeth_l2_open(dev); -} - -static int qeth_l2_stop(struct net_device *dev) -{ - struct qeth_card *card = dev->ml_priv; - - QETH_CARD_TEXT(card, 4, "qethstop"); - netif_tx_disable(dev); - if (card->state == CARD_STATE_UP) { - card->state = CARD_STATE_SOFTSETUP; - napi_disable(&card->napi); - } - return 0; -} - static const struct device_type qeth_l2_devtype = { .name = "qeth_layer2", .groups = qeth_l2_attr_groups, @@ -822,12 +775,12 @@ static const struct ethtool_ops qeth_l2_osn_ops = { }; static const struct net_device_ops qeth_l2_netdev_ops = { - .ndo_open = qeth_l2_open, - .ndo_stop = qeth_l2_stop, + .ndo_open = qeth_open, + .ndo_stop = qeth_stop, .ndo_get_stats = qeth_get_stats, .ndo_start_xmit = qeth_l2_hard_start_xmit, .ndo_features_check = qeth_features_check, - .ndo_validate_addr = eth_validate_addr, + .ndo_validate_addr = qeth_l2_validate_addr, .ndo_set_rx_mode = qeth_l2_set_rx_mode, .ndo_do_ioctl = qeth_do_ioctl, .ndo_set_mac_address = qeth_l2_set_mac_address, @@ -1001,10 +954,11 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) qeth_enable_hw_features(card->dev); if (recover_flag == CARD_STATE_RECOVER) { - if (recovery_mode && - card->info.type != QETH_CARD_TYPE_OSN) { - __qeth_l2_open(card->dev); - qeth_l2_set_rx_mode(card->dev); + if (recovery_mode && !IS_OSN(card)) { + if (!qeth_l2_validate_addr(card->dev)) { + qeth_open_internal(card->dev); + qeth_l2_set_rx_mode(card->dev); + } } else { rtnl_lock(); dev_open(card->dev, NULL); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 42a7cdc59b76..b8a2493a6607 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -40,7 +40,6 @@ static int qeth_l3_set_offline(struct ccwgroup_device *); -static int qeth_l3_stop(struct net_device *); static void qeth_l3_set_rx_mode(struct net_device *dev); static int qeth_l3_register_addr_entry(struct qeth_card *, struct qeth_ipaddr *); @@ -1410,7 +1409,7 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) card->write.state == CH_STATE_UP && (card->state == CARD_STATE_UP)) { if (recovery_mode) - qeth_l3_stop(card->dev); + qeth_stop(card->dev); else { rtnl_lock(); dev_close(card->dev); @@ -2100,56 +2099,6 @@ tx_drop: return NETDEV_TX_OK; } -static int __qeth_l3_open(struct net_device *dev) -{ - struct qeth_card *card = dev->ml_priv; - int rc = 0; - - QETH_CARD_TEXT(card, 4, "qethopen"); - if (card->state == CARD_STATE_UP) - return rc; - if (card->state != CARD_STATE_SOFTSETUP) - return -ENODEV; - card->data.state = CH_STATE_UP; - card->state = CARD_STATE_UP; - netif_start_queue(dev); - - if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) { - napi_enable(&card->napi); - local_bh_disable(); - napi_schedule(&card->napi); - /* kick-start the NAPI softirq: */ - local_bh_enable(); - } else - rc = -EIO; - return rc; -} - -static int qeth_l3_open(struct net_device *dev) -{ - struct qeth_card *card = dev->ml_priv; - - QETH_CARD_TEXT(card, 5, "qethope_"); - if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { - QETH_CARD_TEXT(card, 3, "openREC"); - return -ERESTARTSYS; - } - return __qeth_l3_open(dev); -} - -static int qeth_l3_stop(struct net_device *dev) -{ - struct qeth_card *card = dev->ml_priv; - - QETH_CARD_TEXT(card, 4, "qethstop"); - netif_tx_disable(dev); - if (card->state == CARD_STATE_UP) { - card->state = CARD_STATE_SOFTSETUP; - napi_disable(&card->napi); - } - return 0; -} - static const struct ethtool_ops qeth_l3_ethtool_ops = { .get_link = ethtool_op_get_link, .get_strings = qeth_core_get_strings, @@ -2193,8 +2142,8 @@ static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb, } static const struct net_device_ops qeth_l3_netdev_ops = { - .ndo_open = qeth_l3_open, - .ndo_stop = qeth_l3_stop, + .ndo_open = qeth_open, + .ndo_stop = qeth_stop, .ndo_get_stats = qeth_get_stats, .ndo_start_xmit = qeth_l3_hard_start_xmit, .ndo_validate_addr = eth_validate_addr, @@ -2208,8 +2157,8 @@ static const struct net_device_ops qeth_l3_netdev_ops = { }; static const struct net_device_ops qeth_l3_osa_netdev_ops = { - .ndo_open = qeth_l3_open, - .ndo_stop = qeth_l3_stop, + .ndo_open = qeth_open, + .ndo_stop = qeth_stop, .ndo_get_stats = qeth_get_stats, .ndo_start_xmit = qeth_l3_hard_start_xmit, .ndo_features_check = qeth_l3_osa_features_check, @@ -2414,7 +2363,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) if (recover_flag == CARD_STATE_RECOVER) { rtnl_lock(); if (recovery_mode) { - __qeth_l3_open(card->dev); + qeth_open_internal(card->dev); qeth_l3_set_rx_mode(card->dev); } else { dev_open(card->dev, NULL); -- cgit v1.2.3 From 654e3d48bebbebf6c244a004833d5e0ffe6191b4 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 25 Jan 2019 15:44:19 +0100 Subject: s390/qeth: register MAC address earlier commit 4789a2188048 ("s390/qeth: fix race when setting MAC address") resolved a race where our initial programming of dev_addr into the HW and a call to ndo_set_mac_address() could run concurrently. In this case, we could end up getting confused about which address was actually set in the HW. The quick fix was to introduce additional locking that blocks any ndo_set_mac_address() while the device is being set online. But the race primarily originated from the fact that we first register the netdevice, and only then program its dev_addr. By re-ordering this sequence, userspace will only be able to change the MAC address _after_ we have finished with setting the initial dev_addr. Still, the same MAC address race can also occur during a subsequent call to qeth_l2_set_online(). So keep around the locking for now, until a follow-up patch fully resolves this. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 8b9181c8bc7e..3aa11f32dcd5 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -97,8 +97,7 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC); if (rc == 0) { dev_info(&card->gdev->dev, - "MAC address %pM successfully registered on device %s\n", - mac, card->dev->name); + "MAC address %pM successfully registered\n", mac); } else { switch (rc) { case -EEXIST: @@ -458,6 +457,15 @@ out: return 0; } +static void qeth_l2_register_dev_addr(struct qeth_card *card) +{ + if (!is_valid_ether_addr(card->dev->dev_addr)) + qeth_l2_request_initial_mac(card); + + if (!IS_OSN(card) && !qeth_l2_send_setmac(card, card->dev->dev_addr)) + card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; +} + static int qeth_l2_validate_addr(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; @@ -845,8 +853,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) PAGE_SIZE * (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)); } - if (!is_valid_ether_addr(card->dev->dev_addr)) - qeth_l2_request_initial_mac(card); netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT); rc = register_netdev(card->dev); if (!rc && carrier_ok) @@ -901,14 +907,12 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) dev_info(&card->gdev->dev, "The device represents a Bridge Capable Port\n"); + qeth_l2_register_dev_addr(card); + rc = qeth_l2_setup_netdev(card, carrier_ok); if (rc) goto out_remove; - if (card->info.type != QETH_CARD_TYPE_OSN && - !qeth_l2_send_setmac(card, card->dev->dev_addr)) - card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; - if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { if (card->info.hwtrap && qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) -- cgit v1.2.3 From 340c0936f23ba7628e7c94702759d1dd1fb9721e Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 25 Jan 2019 15:44:20 +0100 Subject: s390/qeth: remove TX disable from online path At best this is redundant, at worst it papers over a race in the offline / online code. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 2 -- drivers/s390/net/qeth_l3_main.c | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 3aa11f32dcd5..0d04e5a89341 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -944,8 +944,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) if (card->info.type != QETH_CARD_TYPE_OSN) qeth_l2_process_vlans(card); - netif_tx_disable(card->dev); - rc = qeth_init_qdio_queues(card); if (rc) { QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index b8a2493a6607..2065030e1a62 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2346,7 +2346,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) if (rc) QETH_DBF_TEXT_(SETUP, 2, "5err%04x", rc); } - netif_tx_disable(card->dev); rc = qeth_init_qdio_queues(card); if (rc) { -- cgit v1.2.3 From fa3d2e60596bafcfc9542c0b89f19a5880d1ff41 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 25 Jan 2019 15:44:21 +0100 Subject: s390/qeth: delay netdevice registration Re-order the code flow a bit so that all initial HW setup is done before putting the netdevice into play. For a netdevice that hasn't been registered before, we also don't need to re-enable its HW features or check for recovery actions. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 9 --------- drivers/s390/net/qeth_l2_main.c | 40 ++++++++++++++++++++++----------------- drivers/s390/net/qeth_l3_main.c | 34 +++++++++++++++++++-------------- 3 files changed, 43 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index db1aaa796bef..06bd42a846fa 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5147,13 +5147,6 @@ retriable: *carrier_ok = true; } - if (qeth_netdev_is_registered(card->dev)) { - if (*carrier_ok) - netif_carrier_on(card->dev); - else - netif_carrier_off(card->dev); - } - card->options.ipa4.supported_funcs = 0; card->options.ipa6.supported_funcs = 0; card->options.adp.supported_funcs = 0; @@ -6538,7 +6531,6 @@ void qeth_enable_hw_features(struct net_device *dev) struct qeth_card *card = dev->ml_priv; netdev_features_t features; - rtnl_lock(); features = dev->features; /* force-off any feature that needs an IPA sequence. * netdev_update_features() will restart them. @@ -6548,7 +6540,6 @@ void qeth_enable_hw_features(struct net_device *dev) if (features != dev->features) dev_warn(&card->gdev->dev, "Device recovery failed to restore all offload features\n"); - rtnl_unlock(); } EXPORT_SYMBOL_GPL(qeth_enable_hw_features); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 0d04e5a89341..295ec94b226f 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -803,9 +803,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) { int rc; - if (qeth_netdev_is_registered(card->dev)) - return 0; - card->dev->priv_flags |= IFF_UNICAST_FLT; card->dev->netdev_ops = &qeth_l2_netdev_ops; if (card->info.type == QETH_CARD_TYPE_OSN) { @@ -886,6 +883,7 @@ static void qeth_l2_trace_features(struct qeth_card *card) static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); + struct net_device *dev = card->dev; int rc = 0; enum qeth_card_states recover_flag; bool carrier_ok; @@ -909,10 +907,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) qeth_l2_register_dev_addr(card); - rc = qeth_l2_setup_netdev(card, carrier_ok); - if (rc) - goto out_remove; - if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { if (card->info.hwtrap && qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) @@ -954,18 +948,30 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) qeth_set_allowed_threads(card, 0xffffffff, 0); - qeth_enable_hw_features(card->dev); - if (recover_flag == CARD_STATE_RECOVER) { - if (recovery_mode && !IS_OSN(card)) { - if (!qeth_l2_validate_addr(card->dev)) { - qeth_open_internal(card->dev); - qeth_l2_set_rx_mode(card->dev); + if (!qeth_netdev_is_registered(dev)) { + rc = qeth_l2_setup_netdev(card, carrier_ok); + if (rc) + goto out_remove; + } else { + rtnl_lock(); + if (carrier_ok) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + + qeth_enable_hw_features(dev); + + if (recover_flag == CARD_STATE_RECOVER) { + if (recovery_mode && !IS_OSN(card)) { + if (!qeth_l2_validate_addr(dev)) { + qeth_open_internal(dev); + qeth_l2_set_rx_mode(dev); + } + } else { + dev_open(dev, NULL); } - } else { - rtnl_lock(); - dev_open(card->dev, NULL); - rtnl_unlock(); } + rtnl_unlock(); } /* let user_space know that device is online */ kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 2065030e1a62..e60d2c44d479 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2178,9 +2178,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok) unsigned int headroom; int rc; - if (qeth_netdev_is_registered(card->dev)) - return 0; - if (card->info.type == QETH_CARD_TYPE_OSD || card->info.type == QETH_CARD_TYPE_OSX) { if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) || @@ -2296,6 +2293,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); + struct net_device *dev = card->dev; int rc = 0; enum qeth_card_states recover_flag; bool carrier_ok; @@ -2313,10 +2311,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) goto out_remove; } - rc = qeth_l3_setup_netdev(card, carrier_ok); - if (rc) - goto out_remove; - if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { if (card->info.hwtrap && qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) @@ -2358,14 +2352,26 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) qeth_set_allowed_threads(card, 0xffffffff, 0); qeth_l3_recover_ip(card); - qeth_enable_hw_features(card->dev); - if (recover_flag == CARD_STATE_RECOVER) { + if (!qeth_netdev_is_registered(dev)) { + rc = qeth_l3_setup_netdev(card, carrier_ok); + if (rc) + goto out_remove; + } else { rtnl_lock(); - if (recovery_mode) { - qeth_open_internal(card->dev); - qeth_l3_set_rx_mode(card->dev); - } else { - dev_open(card->dev, NULL); + if (carrier_ok) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + + qeth_enable_hw_features(dev); + + if (recover_flag == CARD_STATE_RECOVER) { + if (recovery_mode) { + qeth_open_internal(dev); + qeth_l3_set_rx_mode(dev); + } else { + dev_open(dev, NULL); + } } rtnl_unlock(); } -- cgit v1.2.3 From e6e771b3d8975ec88009f03826c6921d78edc9bf Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 25 Jan 2019 15:44:22 +0100 Subject: s390/qeth: detach netdevice while card is offline When a qeth card is offline, it has no connection to the HW. So none of our control callbacks can run IO against it, and we can only cache the input (eg a new MAC address) without providing proper feedback to the caller. In this context, it seems much more reasonable to simply detach the netdevice and let the kernel reject any interaction with it. This also makes all sorts of internal state checks and locking obsolete. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 5 ---- drivers/s390/net/qeth_core_main.c | 51 ++------------------------------------- drivers/s390/net/qeth_l2_main.c | 47 +++++++++--------------------------- drivers/s390/net/qeth_l3_main.c | 19 ++++++--------- 4 files changed, 20 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index ffec26ff512d..df270ef3964c 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -802,7 +802,6 @@ struct qeth_card { unsigned long thread_start_mask; unsigned long thread_allowed_mask; unsigned long thread_running_mask; - struct task_struct *recovery_task; spinlock_t ip_lock; struct qeth_ipato ipato; struct list_head cmd_waiter_list; @@ -976,11 +975,8 @@ extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS]; struct net_device *qeth_clone_netdev(struct net_device *orig); struct qeth_card *qeth_get_card_by_busid(char *bus_id); -void qeth_set_recovery_task(struct qeth_card *); -void qeth_clear_recovery_task(struct qeth_card *); void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int); int qeth_threads_running(struct qeth_card *, unsigned long); -int qeth_wait_for_threads(struct qeth_card *, unsigned long); int qeth_do_run_thread(struct qeth_card *, unsigned long); void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long); void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long); @@ -1047,7 +1043,6 @@ netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t); netdev_features_t qeth_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features); -int qeth_open_internal(struct net_device *dev); int qeth_open(struct net_device *dev); int qeth_stop(struct net_device *dev); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 06bd42a846fa..f7c097a613fc 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -193,23 +193,6 @@ const char *qeth_get_cardname_short(struct qeth_card *card) return "n/a"; } -void qeth_set_recovery_task(struct qeth_card *card) -{ - card->recovery_task = current; -} -EXPORT_SYMBOL_GPL(qeth_set_recovery_task); - -void qeth_clear_recovery_task(struct qeth_card *card) -{ - card->recovery_task = NULL; -} -EXPORT_SYMBOL_GPL(qeth_clear_recovery_task); - -static bool qeth_is_recovery_task(const struct qeth_card *card) -{ - return card->recovery_task == current; -} - void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads, int clear_start_mask) { @@ -236,15 +219,6 @@ int qeth_threads_running(struct qeth_card *card, unsigned long threads) } EXPORT_SYMBOL_GPL(qeth_threads_running); -int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads) -{ - if (qeth_is_recovery_task(card)) - return 0; - return wait_event_interruptible(card->wait_q, - qeth_threads_running(card, threads) == 0); -} -EXPORT_SYMBOL_GPL(qeth_wait_for_threads); - void qeth_clear_working_pool_list(struct qeth_card *card) { struct qeth_buffer_pool_entry *pool_entry, *tmp; @@ -5923,9 +5897,6 @@ int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!card) return -ENODEV; - if (!qeth_card_hw_is_reachable(card)) - return -ENODEV; - if (card->info.type == QETH_CARD_TYPE_OSN) return -EPERM; @@ -6236,8 +6207,6 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev, /* Check if we can obtain more accurate information. */ /* If QUERY_CARD_INFO command is not supported or fails, */ /* just return the heuristics that was filled above. */ - if (!qeth_card_hw_is_reachable(card)) - return -ENODEV; rc = qeth_query_card_info(card, &carrier_info); if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */ return 0; @@ -6608,10 +6577,7 @@ netdev_features_t qeth_fix_features(struct net_device *dev, features &= ~NETIF_F_TSO; if (!qeth_is_supported6(card, IPA_OUTBOUND_TSO)) features &= ~NETIF_F_TSO6; - /* if the card isn't up, remove features that require hw changes */ - if (card->state == CARD_STATE_DOWN || - card->state == CARD_STATE_RECOVER) - features &= ~QETH_HW_FEATURES; + QETH_DBF_HEX(SETUP, 2, &features, sizeof(features)); return features; } @@ -6643,7 +6609,7 @@ netdev_features_t qeth_features_check(struct sk_buff *skb, } EXPORT_SYMBOL_GPL(qeth_features_check); -int qeth_open_internal(struct net_device *dev) +int qeth_open(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; @@ -6667,19 +6633,6 @@ int qeth_open_internal(struct net_device *dev) local_bh_enable(); return 0; } -EXPORT_SYMBOL_GPL(qeth_open_internal); - -int qeth_open(struct net_device *dev) -{ - struct qeth_card *card = dev->ml_priv; - - QETH_CARD_TEXT(card, 5, "qethope_"); - if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { - QETH_CARD_TEXT(card, 3, "openREC"); - return -ERESTARTSYS; - } - return qeth_open_internal(dev); -} EXPORT_SYMBOL_GPL(qeth_open); int qeth_stop(struct net_device *dev) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 295ec94b226f..18dfb1b5e690 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -283,10 +283,7 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, QETH_CARD_TEXT_(card, 4, "aid:%d", vid); if (!vid) return 0; - if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { - QETH_CARD_TEXT(card, 3, "aidREC"); - return 0; - } + id = kmalloc(sizeof(*id), GFP_KERNEL); if (id) { id->vid = vid; @@ -312,10 +309,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, int rc = 0; QETH_CARD_TEXT_(card, 4, "kid:%d", vid); - if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { - QETH_CARD_TEXT(card, 3, "kidREC"); - return 0; - } + mutex_lock(&card->vid_list_mutex); list_for_each_entry(id, &card->vid_list, list) { if (id->vid == vid) { @@ -496,39 +490,22 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { - QETH_CARD_TEXT(card, 3, "setmcREC"); - return -ERESTARTSYS; - } - - /* avoid racing against concurrent state change: */ - if (!mutex_trylock(&card->conf_mutex)) - return -EAGAIN; - - if (!qeth_card_hw_is_reachable(card)) { - ether_addr_copy(dev->dev_addr, addr->sa_data); - goto out_unlock; - } - /* don't register the same address twice */ if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) && (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) - goto out_unlock; + return 0; /* add the new address, switch over, drop the old */ rc = qeth_l2_send_setmac(card, addr->sa_data); if (rc) - goto out_unlock; + return rc; ether_addr_copy(old_addr, dev->dev_addr); ether_addr_copy(dev->dev_addr, addr->sa_data); if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED) qeth_l2_remove_mac(card, old_addr); card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; - -out_unlock: - mutex_unlock(&card->conf_mutex); - return rc; + return 0; } static void qeth_promisc_to_bridge(struct qeth_card *card) @@ -603,9 +580,6 @@ static void qeth_l2_set_rx_mode(struct net_device *dev) return; QETH_CARD_TEXT(card, 3, "setmulti"); - if (qeth_threads_running(card, QETH_RECOVER_THREAD) && - (card->state != CARD_STATE_UP)) - return; spin_lock_bh(&card->mclock); @@ -959,12 +933,13 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) else netif_carrier_off(dev); + netif_device_attach(dev); qeth_enable_hw_features(dev); if (recover_flag == CARD_STATE_RECOVER) { if (recovery_mode && !IS_OSN(card)) { if (!qeth_l2_validate_addr(dev)) { - qeth_open_internal(dev); + qeth_open(dev); qeth_l2_set_rx_mode(dev); } } else { @@ -1011,7 +986,11 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); + rtnl_lock(); + netif_device_detach(card->dev); netif_carrier_off(card->dev); + rtnl_unlock(); + recover_flag = card->state; if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); @@ -1052,7 +1031,6 @@ static int qeth_l2_recover(void *ptr) QETH_CARD_TEXT(card, 2, "recover2"); dev_warn(&card->gdev->dev, "A recovery process has been started for the device\n"); - qeth_set_recovery_task(card); __qeth_l2_set_offline(card->gdev, 1); rc = __qeth_l2_set_online(card->gdev, 1); if (!rc) @@ -1063,7 +1041,6 @@ static int qeth_l2_recover(void *ptr) dev_warn(&card->gdev->dev, "The qeth device driver " "failed to recover an error on the device\n"); } - qeth_clear_recovery_task(card); qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); return 0; @@ -1084,7 +1061,6 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); - netif_device_detach(card->dev); qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (gdev->state == CCWGROUP_OFFLINE) @@ -1114,7 +1090,6 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev) rc = __qeth_l2_set_online(card->gdev, 0); qeth_set_allowed_threads(card, 0xffffffff, 0); - netif_device_attach(card->dev); if (rc) dev_warn(&card->gdev->dev, "The qeth device driver " "failed to recover an error on the device\n"); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e60d2c44d479..59535ecb1487 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1280,10 +1280,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, QETH_CARD_TEXT_(card, 4, "kid:%d", vid); - if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { - QETH_CARD_TEXT(card, 3, "kidREC"); - return 0; - } clear_bit(vid, card->active_vlans); qeth_l3_set_rx_mode(dev); return 0; @@ -1472,9 +1468,7 @@ static void qeth_l3_set_rx_mode(struct net_device *dev) int i, rc; QETH_CARD_TEXT(card, 3, "setmulti"); - if (qeth_threads_running(card, QETH_RECOVER_THREAD) && - (card->state != CARD_STATE_UP)) - return; + if (!card->options.sniffer) { spin_lock_bh(&card->mclock); @@ -2363,11 +2357,12 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) else netif_carrier_off(dev); + netif_device_attach(dev); qeth_enable_hw_features(dev); if (recover_flag == CARD_STATE_RECOVER) { if (recovery_mode) { - qeth_open_internal(dev); + qeth_open(dev); qeth_l3_set_rx_mode(dev); } else { dev_open(dev, NULL); @@ -2413,7 +2408,11 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); + rtnl_lock(); + netif_device_detach(card->dev); netif_carrier_off(card->dev); + rtnl_unlock(); + recover_flag = card->state; if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); @@ -2460,7 +2459,6 @@ static int qeth_l3_recover(void *ptr) QETH_CARD_TEXT(card, 2, "recover2"); dev_warn(&card->gdev->dev, "A recovery process has been started for the device\n"); - qeth_set_recovery_task(card); __qeth_l3_set_offline(card->gdev, 1); rc = __qeth_l3_set_online(card->gdev, 1); if (!rc) @@ -2471,7 +2469,6 @@ static int qeth_l3_recover(void *ptr) dev_warn(&card->gdev->dev, "The qeth device driver " "failed to recover an error on the device\n"); } - qeth_clear_recovery_task(card); qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); return 0; @@ -2481,7 +2478,6 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); - netif_device_detach(card->dev); qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (gdev->state == CCWGROUP_OFFLINE) @@ -2511,7 +2507,6 @@ static int qeth_l3_pm_resume(struct ccwgroup_device *gdev) rc = __qeth_l3_set_online(card->gdev, 0); qeth_set_allowed_threads(card, 0xffffffff, 0); - netif_device_attach(card->dev); if (rc) dev_warn(&card->gdev->dev, "The qeth device driver " "failed to recover an error on the device\n"); -- cgit v1.2.3 From 5fc692a7ffaf635588625aae8af6c3bc14dd6ea5 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 25 Jan 2019 15:44:23 +0100 Subject: s390/qeth: remove VLAN tracking for L2 devices For recovery purposes, qeth keeps track of all registered VIDs. Replace this by using the infrastructure introduced in commit 9daae9bd47cf ("net: Call add/kill vid ndo on vlan filter feature toggling"). By managing NETIF_F_HW_VLAN_CTAG_FILTER as a hw_feature, netdev_update_features() will select it from dev->wanted_features and replay all of the netdevice's VIDs to its ndo_vlan_rx_add_vid() callback. z/VM NICs strictly require VLAN registration, so don't expose it as hw_feature there but add a little hack in qeth_enable_hw_features() to make things work regardless. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 7 ----- drivers/s390/net/qeth_core_main.c | 12 ++++---- drivers/s390/net/qeth_core_mpc.h | 1 + drivers/s390/net/qeth_l2_main.c | 61 +++++++-------------------------------- 4 files changed, 18 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index df270ef3964c..d65650ef6b41 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -741,11 +741,6 @@ struct qeth_discipline { struct qeth_ipa_cmd *cmd); }; -struct qeth_vlan_vid { - struct list_head list; - unsigned short vid; -}; - enum qeth_addr_disposition { QETH_DISP_ADDR_DELETE = 0, QETH_DISP_ADDR_DO_NOTHING = 1, @@ -792,8 +787,6 @@ struct qeth_card { wait_queue_head_t wait_q; spinlock_t mclock; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; - struct mutex vid_list_mutex; /* vid_list */ - struct list_head vid_list; DECLARE_HASHTABLE(mac_htable, 4); DECLARE_HASHTABLE(ip_htable, 4); DECLARE_HASHTABLE(ip_mc_htable, 4); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index f7c097a613fc..dcc06e48b70b 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1404,7 +1404,6 @@ static void qeth_setup_card(struct qeth_card *card) spin_lock_init(&card->thread_mask_lock); mutex_init(&card->conf_mutex); mutex_init(&card->discipline_mutex); - mutex_init(&card->vid_list_mutex); INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread); INIT_LIST_HEAD(&card->cmd_waiter_list); init_waitqueue_head(&card->wait_q); @@ -6489,8 +6488,6 @@ static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on) return (rc_ipv6) ? rc_ipv6 : rc_ipv4; } -#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \ - NETIF_F_IPV6_CSUM | NETIF_F_TSO6) /** * qeth_enable_hw_features() - (Re-)Enable HW functions for device features * @dev: a net_device @@ -6501,10 +6498,15 @@ void qeth_enable_hw_features(struct net_device *dev) netdev_features_t features; features = dev->features; - /* force-off any feature that needs an IPA sequence. + /* force-off any feature that might need an IPA sequence. * netdev_update_features() will restart them. */ - dev->features &= ~QETH_HW_FEATURES; + dev->features &= ~dev->hw_features; + /* toggle VLAN filter, so that VIDs are re-programmed: */ + if (IS_LAYER2(card) && IS_VM_NIC(card)) { + dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + dev->wanted_features |= NETIF_F_HW_VLAN_CTAG_FILTER; + } netdev_update_features(dev); if (features != dev->features) dev_warn(&card->gdev->dev, diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 1ab321926f64..c7fb14a61eed 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -81,6 +81,7 @@ enum qeth_card_types { #define IS_IQD(card) ((card)->info.type == QETH_CARD_TYPE_IQD) #define IS_OSD(card) ((card)->info.type == QETH_CARD_TYPE_OSD) +#define IS_OSM(card) ((card)->info.type == QETH_CARD_TYPE_OSM) #define IS_OSN(card) ((card)->info.type == QETH_CARD_TYPE_OSN) #define IS_VM_NIC(card) ((card)->info.guestlan) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 18dfb1b5e690..82f50cc30b0a 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -261,69 +261,28 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, qeth_l2_send_setdelvlan_cb, NULL)); } -static void qeth_l2_process_vlans(struct qeth_card *card) -{ - struct qeth_vlan_vid *id; - - QETH_CARD_TEXT(card, 3, "L2prcvln"); - mutex_lock(&card->vid_list_mutex); - list_for_each_entry(id, &card->vid_list, list) { - qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN); - } - mutex_unlock(&card->vid_list_mutex); -} - static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) { struct qeth_card *card = dev->ml_priv; - struct qeth_vlan_vid *id; - int rc; QETH_CARD_TEXT_(card, 4, "aid:%d", vid); if (!vid) return 0; - id = kmalloc(sizeof(*id), GFP_KERNEL); - if (id) { - id->vid = vid; - rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN); - if (rc) { - kfree(id); - return rc; - } - mutex_lock(&card->vid_list_mutex); - list_add_tail(&id->list, &card->vid_list); - mutex_unlock(&card->vid_list_mutex); - } else { - return -ENOMEM; - } - return 0; + return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN); } static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid) { - struct qeth_vlan_vid *id, *tmpid = NULL; struct qeth_card *card = dev->ml_priv; - int rc = 0; QETH_CARD_TEXT_(card, 4, "kid:%d", vid); + if (!vid) + return 0; - mutex_lock(&card->vid_list_mutex); - list_for_each_entry(id, &card->vid_list, list) { - if (id->vid == vid) { - list_del(&id->list); - tmpid = id; - break; - } - } - mutex_unlock(&card->vid_list_mutex); - if (tmpid) { - rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN); - kfree(tmpid); - } - return rc; + return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN); } static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) @@ -718,7 +677,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) if (rc) return rc; } - INIT_LIST_HEAD(&card->vid_list); + hash_init(card->mac_htable); card->info.hwtrap = 0; qeth_l2_vnicc_set_defaults(card); @@ -787,10 +746,13 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) card->dev->needed_headroom = sizeof(struct qeth_hdr); } - if (card->info.type == QETH_CARD_TYPE_OSM) + if (IS_OSM(card)) { card->dev->features |= NETIF_F_VLAN_CHALLENGED; - else + } else { + if (!IS_VM_NIC(card)) + card->dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + } if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) { card->dev->features |= NETIF_F_SG; @@ -909,9 +871,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) goto out_remove; } - if (card->info.type != QETH_CARD_TYPE_OSN) - qeth_l2_process_vlans(card); - rc = qeth_init_qdio_queues(card); if (rc) { QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); -- cgit v1.2.3 From df6f1856db02fc9ee8d629e6a9fcf674615a623b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 25 Jan 2019 20:38:38 +0100 Subject: r8169: add general EEE support for chip versions from RTL8168g This patch adds the general framework to deal with EEE in this driver plus EEE support for chip versions from RTL8168g. We don't touch the default chip settings, therefore EEE will usually be disabled and it's up to the user to enable it. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 202 +++++++++++++++++++++++++++++++++-- 1 file changed, 192 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 83c4663e6cd3..f46bf1187339 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1984,6 +1984,172 @@ static int rtl_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) return 0; } +static int rtl_get_eee_supp(struct rtl8169_private *tp) +{ + struct phy_device *phydev = tp->phydev; + int ret; + + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: + phy_write(phydev, 0x1f, 0x0a5c); + ret = phy_read(phydev, 0x12); + phy_write(phydev, 0x1f, 0x0000); + break; + default: + ret = -EPROTONOSUPPORT; + break; + } + + return ret; +} + +static int rtl_get_eee_lpadv(struct rtl8169_private *tp) +{ + struct phy_device *phydev = tp->phydev; + int ret; + + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: + phy_write(phydev, 0x1f, 0x0a5d); + ret = phy_read(phydev, 0x11); + phy_write(phydev, 0x1f, 0x0000); + break; + default: + ret = -EPROTONOSUPPORT; + break; + } + + return ret; +} + +static int rtl_get_eee_adv(struct rtl8169_private *tp) +{ + struct phy_device *phydev = tp->phydev; + int ret; + + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: + phy_write(phydev, 0x1f, 0x0a5d); + ret = phy_read(phydev, 0x10); + phy_write(phydev, 0x1f, 0x0000); + break; + default: + ret = -EPROTONOSUPPORT; + break; + } + + return ret; +} + +static int rtl_set_eee_adv(struct rtl8169_private *tp, int val) +{ + struct phy_device *phydev = tp->phydev; + int ret = 0; + + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: + phy_write(phydev, 0x1f, 0x0a5d); + phy_write(phydev, 0x10, val); + phy_write(phydev, 0x1f, 0x0000); + break; + default: + ret = -EPROTONOSUPPORT; + break; + } + + return ret; +} + +static int rtl8169_get_eee(struct net_device *dev, struct ethtool_eee *data) +{ + struct rtl8169_private *tp = netdev_priv(dev); + struct device *d = tp_to_dev(tp); + int ret; + + pm_runtime_get_noresume(d); + + if (!pm_runtime_active(d)) { + ret = -EOPNOTSUPP; + goto out; + } + + /* Get Supported EEE */ + ret = rtl_get_eee_supp(tp); + if (ret < 0) + goto out; + data->supported = mmd_eee_cap_to_ethtool_sup_t(ret); + + /* Get advertisement EEE */ + ret = rtl_get_eee_adv(tp); + if (ret < 0) + goto out; + data->advertised = mmd_eee_adv_to_ethtool_adv_t(ret); + data->eee_enabled = !!data->advertised; + + /* Get LP advertisement EEE */ + ret = rtl_get_eee_lpadv(tp); + if (ret < 0) + goto out; + data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(ret); + data->eee_active = !!(data->advertised & data->lp_advertised); +out: + pm_runtime_put_noidle(d); + return ret < 0 ? ret : 0; +} + +static int rtl8169_set_eee(struct net_device *dev, struct ethtool_eee *data) +{ + struct rtl8169_private *tp = netdev_priv(dev); + struct device *d = tp_to_dev(tp); + int old_adv, adv = 0, cap, ret; + + pm_runtime_get_noresume(d); + + if (!dev->phydev || !pm_runtime_active(d)) { + ret = -EOPNOTSUPP; + goto out; + } + + if (dev->phydev->autoneg == AUTONEG_DISABLE || + dev->phydev->duplex != DUPLEX_FULL) { + ret = -EPROTONOSUPPORT; + goto out; + } + + /* Get Supported EEE */ + ret = rtl_get_eee_supp(tp); + if (ret < 0) + goto out; + cap = ret; + + ret = rtl_get_eee_adv(tp); + if (ret < 0) + goto out; + old_adv = ret; + + if (data->eee_enabled) { + adv = !data->advertised ? cap : + ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap; + /* Mask prohibited EEE modes */ + adv &= ~dev->phydev->eee_broken_modes; + } + + if (old_adv != adv) { + ret = rtl_set_eee_adv(tp, adv); + if (ret < 0) + goto out; + + /* Restart autonegotiation so the new modes get sent to the + * link partner. + */ + ret = phy_restart_aneg(dev->phydev); + } + +out: + pm_runtime_put_noidle(d); + return ret < 0 ? ret : 0; +} + static const struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, .get_regs_len = rtl8169_get_regs_len, @@ -2000,6 +2166,8 @@ static const struct ethtool_ops rtl8169_ethtool_ops = { .get_ethtool_stats = rtl8169_get_ethtool_stats, .get_ts_info = ethtool_op_get_ts_info, .nway_reset = phy_ethtool_nway_reset, + .get_eee = rtl8169_get_eee, + .set_eee = rtl8169_set_eee, .get_link_ksettings = phy_ethtool_get_link_ksettings, .set_link_ksettings = phy_ethtool_set_link_ksettings, }; @@ -2393,6 +2561,18 @@ static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) rtl_apply_firmware(tp); } +static void rtl8168_config_eee_mac(struct rtl8169_private *tp) +{ + rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0003, 0x0000, ERIAR_EXGMAC); +} + +static void rtl8168g_config_eee_phy(struct rtl8169_private *tp) +{ + phy_write(tp->phydev, 0x1f, 0x0a43); + phy_set_bits(tp->phydev, 0x11, BIT(4)); + phy_write(tp->phydev, 0x1f, 0x0000); +} + static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { @@ -3442,13 +3622,13 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x14, 0x1065); rtl8168g_disable_aldps(tp); - - rtl_writephy(tp, 0x1f, 0x0000); + rtl8168g_config_eee_phy(tp); } static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp) { rtl_apply_firmware(tp); + rtl8168g_config_eee_phy(tp); } static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp) @@ -3554,8 +3734,7 @@ static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); rtl8168g_disable_aldps(tp); - - rtl_writephy(tp, 0x1f, 0x0000); + rtl8168g_config_eee_phy(tp); } static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp) @@ -3624,8 +3803,7 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); rtl8168g_disable_aldps(tp); - - rtl_writephy(tp, 0x1f, 0x0000); + rtl8168g_config_eee_phy(tp); } static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp) @@ -3654,8 +3832,7 @@ static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); rtl8168g_disable_aldps(tp); - - rtl_writephy(tp, 0x1f, 0x0000); + rtl8168g_config_eee_phy(tp); } static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp) @@ -3733,8 +3910,7 @@ static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); rtl8168g_disable_aldps(tp); - - rtl_writephy(tp, 0x1f, 0x0000); + rtl8168g_config_eee_phy(tp); } static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) @@ -5017,6 +5193,8 @@ static void rtl_hw_start_8168g(struct rtl8169_private *tp) /* Adjust EEE LED frequency */ RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07); + rtl8168_config_eee_mac(tp); + rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC); rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC); @@ -5119,6 +5297,8 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) /* Adjust EEE LED frequency */ RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07); + rtl8168_config_eee_mac(tp); + RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN); RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN); @@ -5199,6 +5379,8 @@ static void rtl_hw_start_8168ep(struct rtl8169_private *tp) /* Adjust EEE LED frequency */ RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07); + rtl8168_config_eee_mac(tp); + rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC); RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN); -- cgit v1.2.3 From b6c7fa401625d949e5e370f32e74f22c3bbaed51 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 25 Jan 2019 20:39:42 +0100 Subject: r8169: enable EEE per default on chip versions from RTL8168g Enable EEE per default on chip versions from RTL8168g. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index f46bf1187339..9e335d2c74a5 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -2172,6 +2172,14 @@ static const struct ethtool_ops rtl8169_ethtool_ops = { .set_link_ksettings = phy_ethtool_set_link_ksettings, }; +static void rtl_enable_eee(struct rtl8169_private *tp) +{ + int supported = rtl_get_eee_supp(tp); + + if (supported > 0) + rtl_set_eee_adv(tp, supported); +} + static void rtl8169_get_mac_version(struct rtl8169_private *tp) { /* @@ -3623,12 +3631,14 @@ static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) rtl8168g_disable_aldps(tp); rtl8168g_config_eee_phy(tp); + rtl_enable_eee(tp); } static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp) { rtl_apply_firmware(tp); rtl8168g_config_eee_phy(tp); + rtl_enable_eee(tp); } static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp) @@ -3735,6 +3745,7 @@ static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp) rtl8168g_disable_aldps(tp); rtl8168g_config_eee_phy(tp); + rtl_enable_eee(tp); } static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp) @@ -3804,6 +3815,7 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp) rtl8168g_disable_aldps(tp); rtl8168g_config_eee_phy(tp); + rtl_enable_eee(tp); } static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp) @@ -3833,6 +3845,7 @@ static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp) rtl8168g_disable_aldps(tp); rtl8168g_config_eee_phy(tp); + rtl_enable_eee(tp); } static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp) @@ -3911,6 +3924,7 @@ static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp) rtl8168g_disable_aldps(tp); rtl8168g_config_eee_phy(tp); + rtl_enable_eee(tp); } static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) -- cgit v1.2.3 From 84239b445964b15045e1418ebf28e74121ace309 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 25 Jan 2019 02:28:59 +0000 Subject: ptp: fix debugfs_simple_attr.cocci warnings Use DEFINE_DEBUGFS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTRIBUTE for debugfs files. Semantic patch information: Rationale: DEFINE_SIMPLE_ATTRIBUTE + debugfs_create_file() imposes some significant overhead as compared to DEFINE_DEBUGFS_ATTRIBUTE + debugfs_create_file_unsafe(). Generated by: scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci Signed-off-by: YueHaibing Acked-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/ptp/ptp_qoriq_debugfs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_qoriq_debugfs.c b/drivers/ptp/ptp_qoriq_debugfs.c index d904332b240d..970595021088 100644 --- a/drivers/ptp/ptp_qoriq_debugfs.c +++ b/drivers/ptp/ptp_qoriq_debugfs.c @@ -33,8 +33,8 @@ static int ptp_qoriq_fiper1_lpbk_set(void *data, u64 val) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(ptp_qoriq_fiper1_fops, ptp_qoriq_fiper1_lpbk_get, - ptp_qoriq_fiper1_lpbk_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(ptp_qoriq_fiper1_fops, ptp_qoriq_fiper1_lpbk_get, + ptp_qoriq_fiper1_lpbk_set, "%llu\n"); static int ptp_qoriq_fiper2_lpbk_get(void *data, u64 *val) { @@ -64,8 +64,8 @@ static int ptp_qoriq_fiper2_lpbk_set(void *data, u64 val) return 0; } -DEFINE_SIMPLE_ATTRIBUTE(ptp_qoriq_fiper2_fops, ptp_qoriq_fiper2_lpbk_get, - ptp_qoriq_fiper2_lpbk_set, "%llu\n"); +DEFINE_DEBUGFS_ATTRIBUTE(ptp_qoriq_fiper2_fops, ptp_qoriq_fiper2_lpbk_get, + ptp_qoriq_fiper2_lpbk_set, "%llu\n"); void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp) { @@ -79,11 +79,11 @@ void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp) qoriq_ptp->debugfs_root = root; - if (!debugfs_create_file("fiper1-loopback", 0600, root, qoriq_ptp, - &ptp_qoriq_fiper1_fops)) + if (!debugfs_create_file_unsafe("fiper1-loopback", 0600, root, + qoriq_ptp, &ptp_qoriq_fiper1_fops)) goto err_node; - if (!debugfs_create_file("fiper2-loopback", 0600, root, qoriq_ptp, - &ptp_qoriq_fiper2_fops)) + if (!debugfs_create_file_unsafe("fiper2-loopback", 0600, root, + qoriq_ptp, &ptp_qoriq_fiper2_fops)) goto err_node; return; -- cgit v1.2.3 From cc07d2714a846457bec930c88da814a19deeecfc Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 26 Jan 2019 10:35:30 +0100 Subject: r8169: add EEE support for RTL8168f Add EEE support for RTL8168f to the recently added EEE handling framework in the driver. This patch leaves the chip defaults, means EEE typically is disabled initially and it's up to the user to enable it via ethtool. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 9e335d2c74a5..4572de1703b8 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1990,6 +1990,12 @@ static int rtl_get_eee_supp(struct rtl8169_private *tp) int ret; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_34: + case RTL_GIGA_MAC_VER_35: + case RTL_GIGA_MAC_VER_36: + case RTL_GIGA_MAC_VER_38: + ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE); + break; case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: phy_write(phydev, 0x1f, 0x0a5c); ret = phy_read(phydev, 0x12); @@ -2009,6 +2015,12 @@ static int rtl_get_eee_lpadv(struct rtl8169_private *tp) int ret; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_34: + case RTL_GIGA_MAC_VER_35: + case RTL_GIGA_MAC_VER_36: + case RTL_GIGA_MAC_VER_38: + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE); + break; case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: phy_write(phydev, 0x1f, 0x0a5d); ret = phy_read(phydev, 0x11); @@ -2028,6 +2040,12 @@ static int rtl_get_eee_adv(struct rtl8169_private *tp) int ret; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_34: + case RTL_GIGA_MAC_VER_35: + case RTL_GIGA_MAC_VER_36: + case RTL_GIGA_MAC_VER_38: + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV); + break; case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: phy_write(phydev, 0x1f, 0x0a5d); ret = phy_read(phydev, 0x10); @@ -2047,6 +2065,12 @@ static int rtl_set_eee_adv(struct rtl8169_private *tp, int val) int ret = 0; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_34: + case RTL_GIGA_MAC_VER_35: + case RTL_GIGA_MAC_VER_36: + case RTL_GIGA_MAC_VER_38: + ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val); + break; case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: phy_write(phydev, 0x1f, 0x0a5d); phy_write(phydev, 0x10, val); @@ -2574,6 +2598,21 @@ static void rtl8168_config_eee_mac(struct rtl8169_private *tp) rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0003, 0x0000, ERIAR_EXGMAC); } +static void rtl8168f_config_eee_phy(struct rtl8169_private *tp) +{ + struct phy_device *phydev = tp->phydev; + + phy_write(phydev, 0x1f, 0x0007); + phy_write(phydev, 0x1e, 0x0020); + phy_set_bits(phydev, 0x15, BIT(8)); + + phy_write(phydev, 0x1f, 0x0005); + phy_write(phydev, 0x05, 0x8b85); + phy_set_bits(phydev, 0x06, BIT(13)); + + phy_write(phydev, 0x1f, 0x0000); +} + static void rtl8168g_config_eee_phy(struct rtl8169_private *tp) { phy_write(tp->phydev, 0x1f, 0x0a43); @@ -3348,6 +3387,8 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) rtl_w0w1_phy(tp, 0x06, 0x4000, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); + rtl8168f_config_eee_phy(tp); + /* EEE setting */ rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0003, 0x0000, ERIAR_EXGMAC); rtl_writephy(tp, 0x1f, 0x0005); @@ -3398,6 +3439,8 @@ static void rtl8168f_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x05, 0x8b86); rtl_w0w1_phy(tp, 0x06, 0x0001, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); + + rtl8168f_config_eee_phy(tp); } static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) @@ -5113,6 +5156,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) /* Adjust EEE LED frequency */ RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07); + rtl8168_config_eee_mac(tp); + RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN); RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN); RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en); @@ -5145,6 +5190,8 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp) RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN); RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN); RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en); + + rtl8168_config_eee_mac(tp); } static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) -- cgit v1.2.3 From 1563daa3cacf36196b0e943cca3de6804ccb0b43 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 26 Jan 2019 10:36:35 +0100 Subject: r8169: enable EEE per default on RTL8168f Enable EEE per default on RTL8168f. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 4572de1703b8..3e650bd9e94b 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3388,23 +3388,7 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); rtl8168f_config_eee_phy(tp); - - /* EEE setting */ - rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0003, 0x0000, ERIAR_EXGMAC); - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x2000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0020); - rtl_w0w1_phy(tp, 0x15, 0x0100, 0x0000); - rtl_writephy(tp, 0x1f, 0x0002); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0d, 0x0007); - rtl_writephy(tp, 0x0e, 0x003c); - rtl_writephy(tp, 0x0d, 0x4007); - rtl_writephy(tp, 0x0e, 0x0006); - rtl_writephy(tp, 0x0d, 0x0000); + rtl_enable_eee(tp); /* Green feature */ rtl_writephy(tp, 0x1f, 0x0003); @@ -3441,6 +3425,7 @@ static void rtl8168f_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); rtl8168f_config_eee_phy(tp); + rtl_enable_eee(tp); } static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) @@ -3574,22 +3559,6 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp) rtl_w0w1_phy(tp, 0x06, 0x8000, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); - /* eee setting */ - rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC); - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0020); - rtl_w0w1_phy(tp, 0x15, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0d, 0x0007); - rtl_writephy(tp, 0x0e, 0x003c); - rtl_writephy(tp, 0x0d, 0x4007); - rtl_writephy(tp, 0x0e, 0x0000); - rtl_writephy(tp, 0x0d, 0x0000); - /* Green feature */ rtl_writephy(tp, 0x1f, 0x0003); rtl_w0w1_phy(tp, 0x19, 0x0000, 0x0001); -- cgit v1.2.3 From 217e288c9718b383d68cacec50e37ec2c085c485 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sun, 27 Jan 2019 00:49:10 +0800 Subject: net: hns3: don't update packet statistics for packets dropped by hardware Packet statistics for netdev should not include the packets dropped by hardware. Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 327dde2765ab..5ef3bdc7c808 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1425,9 +1425,7 @@ static void hns3_nic_get_stats64(struct net_device *netdev, start = u64_stats_fetch_begin_irq(&ring->syncp); tx_bytes += ring->stats.tx_bytes; tx_pkts += ring->stats.tx_pkts; - tx_drop += ring->stats.tx_busy; tx_drop += ring->stats.sw_err_cnt; - tx_errors += ring->stats.tx_busy; tx_errors += ring->stats.sw_err_cnt; } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); @@ -1438,7 +1436,6 @@ static void hns3_nic_get_stats64(struct net_device *netdev, rx_bytes += ring->stats.rx_bytes; rx_pkts += ring->stats.rx_pkts; rx_drop += ring->stats.non_vld_descs; - rx_drop += ring->stats.err_pkt_len; rx_drop += ring->stats.l2_err; rx_errors += ring->stats.non_vld_descs; rx_errors += ring->stats.l2_err; -- cgit v1.2.3 From ac864c2346d087dd3739435af1b8d36be5f60c75 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sun, 27 Jan 2019 00:49:11 +0800 Subject: net: hns3: clear pci private data when unload hns3 driver When unload hns3 driver, we should clear the pci private data. Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 5ef3bdc7c808..cec09235b1ef 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1781,6 +1781,7 @@ static void hns3_remove(struct pci_dev *pdev) hns3_disable_sriov(pdev); hnae3_unregister_ae_dev(ae_dev); + pci_set_drvdata(pdev, NULL); } /** -- cgit v1.2.3 From 1821dce9ae6c6d70e9e9ea93638855e7a27797ca Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sun, 27 Jan 2019 00:49:12 +0800 Subject: net: hns3: add error handling in hclge_ieee_setets Currently hclge_ieee_setets returns error directly when there is error, which may cause netdev not up problem. This patch adds some error handling when setting ETS configuration fails. Fixes: cacde272dd00 ("net: hns3: Add hclge_dcb module for the support of DCB feature") Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 3a4a54ee5204..90b566e8e454 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -232,12 +232,13 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) ret = hclge_ieee_ets_to_tm_info(hdev, ets); if (ret) - return ret; + goto err_out; if (map_changed) { ret = hclge_client_setup_tc(hdev); if (ret) - return ret; + goto err_out; + ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); if (ret) return ret; @@ -248,6 +249,16 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) } return hclge_tm_dwrr_cfg(hdev); + +err_out: + if (!map_changed) + return ret; + + if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT)) + return ret; + + hclge_notify_client(hdev, HNAE3_UP_CLIENT); + return ret; } static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) -- cgit v1.2.3 From 47ef6deccdfffaef8f56c5021a83a774fc77ee13 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sun, 27 Jan 2019 00:49:13 +0800 Subject: net: hns3: fix return value handle issue for hclge_set_loopback() In current code, it always return 0, even loopback mode setting failed. It's incorrect. This patch fixes return value handle for loopback test. Fixes: 0f29fc23b21d ("net: hns3: Fix for loopback selftest failed problem") Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 8 ++++---- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index abb78696d7ce..ed73f7fc9171 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -117,7 +117,7 @@ static int hns3_lp_up(struct net_device *ndev, enum hnae3_loop loop_mode) ret = hns3_lp_setup(ndev, loop_mode, true); usleep_range(10000, 20000); - return 0; + return ret; } static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode) @@ -334,10 +334,10 @@ static void hns3_self_test(struct net_device *ndev, continue; data[test_index] = hns3_lp_up(ndev, loop_type); - if (!data[test_index]) { + if (!data[test_index]) data[test_index] = hns3_lp_run_test(ndev, loop_type); - hns3_lp_down(ndev, loop_type); - } + + hns3_lp_down(ndev, loop_type); if (data[test_index]) eth_test->flags |= ETH_TEST_FL_FAILED; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 64b1589e549f..d5482f9c422c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5332,6 +5332,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle, break; } + if (ret) + return ret; + kinfo = &vport->nic.kinfo; for (i = 0; i < kinfo->num_tqps; i++) { ret = hclge_tqp_enable(hdev, i, 0, en); -- cgit v1.2.3 From 28673b33c75621b52971b5d5aeed0be59de0bda5 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sun, 27 Jan 2019 00:49:14 +0800 Subject: net: hns3: fix broadcast promisc issue for revision 0x20 For revision 0x20, vlan filter is always bypassed when enable broadcast promisc mode. In this case, broadcast packets with any vlan id can be accpeted. We should disable broadcast promisc mode until user want enable it. Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support") Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 ++-- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index cec09235b1ef..322af28ab4b5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -506,7 +506,7 @@ static u8 hns3_get_netdev_flags(struct net_device *netdev) u8 flags = 0; if (netdev->flags & IFF_PROMISC) { - flags = HNAE3_USER_UPE | HNAE3_USER_MPE; + flags = HNAE3_USER_UPE | HNAE3_USER_MPE | HNAE3_BPE; } else { flags |= HNAE3_VLAN_FLTR; if (netdev->flags & IFF_ALLMULTI) @@ -541,13 +541,13 @@ static void hns3_nic_set_rx_mode(struct net_device *netdev) } } - hns3_update_promisc_mode(netdev, new_flags); /* User mode Promisc mode enable and vlan filtering is disabled to * let all packets in. MAC-VLAN Table overflow Promisc enabled and * vlan fitering is enabled */ hns3_enable_vlan_filter(netdev, new_flags & HNAE3_VLAN_FLTR); h->netdev_flags = new_flags; + hns3_update_promisc_mode(netdev, new_flags); } int hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index d5482f9c422c..558389a18353 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3843,8 +3843,16 @@ static int hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc, struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; struct hclge_promisc_param param; + bool en_bc_pmc = true; - hclge_promisc_param_init(¶m, en_uc_pmc, en_mc_pmc, true, + /* For revision 0x20, if broadcast promisc enabled, vlan filter is + * always bypassed. So broadcast promisc should be disabled until + * user enable promisc mode + */ + if (handle->pdev->revision == 0x20) + en_bc_pmc = handle->netdev_flags & HNAE3_BPE ? true : false; + + hclge_promisc_param_init(¶m, en_uc_pmc, en_mc_pmc, en_bc_pmc, vport->vport_id); return hclge_cmd_set_promisc_mode(hdev, ¶m); } -- cgit v1.2.3 From 350fda0a0af9d077e895c7b01a4901d354ae656e Mon Sep 17 00:00:00 2001 From: liuzhongzhu Date: Sun, 27 Jan 2019 00:49:15 +0800 Subject: net: hns3: After setting the loopback, add the status of getting MAC After setting the serdes loopback, you need to determine the status of the MAC negotiation. If a status exception is obtained after 200ms, a timeout error is returned. Signed-off-by: liuzhongzhu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 558389a18353..ae8336c18264 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5237,8 +5237,15 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, { #define HCLGE_SERDES_RETRY_MS 10 #define HCLGE_SERDES_RETRY_NUM 100 + +#define HCLGE_MAC_LINK_STATUS_MS 20 +#define HCLGE_MAC_LINK_STATUS_NUM 10 +#define HCLGE_MAC_LINK_STATUS_DOWN 0 +#define HCLGE_MAC_LINK_STATUS_UP 1 + struct hclge_serdes_lb_cmd *req; struct hclge_desc desc; + int mac_link_ret = 0; int ret, i = 0; u8 loop_mode_b; @@ -5261,8 +5268,10 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, if (en) { req->enable = loop_mode_b; req->mask = loop_mode_b; + mac_link_ret = HCLGE_MAC_LINK_STATUS_UP; } else { req->mask = loop_mode_b; + mac_link_ret = HCLGE_MAC_LINK_STATUS_DOWN; } ret = hclge_cmd_send(&hdev->hw, &desc, 1); @@ -5294,7 +5303,19 @@ static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en, } hclge_cfg_mac_mode(hdev, en); - return 0; + + i = 0; + do { + /* serdes Internal loopback, independent of the network cable.*/ + msleep(HCLGE_MAC_LINK_STATUS_MS); + ret = hclge_get_mac_link_status(hdev); + if (ret == mac_link_ret) + return 0; + } while (++i < HCLGE_MAC_LINK_STATUS_NUM); + + dev_err(&hdev->pdev->dev, "config mac mode timeout\n"); + + return -EBUSY; } static int hclge_tqp_enable(struct hclge_dev *hdev, int tqp_id, -- cgit v1.2.3 From c2a39d981da7a04874d3ba17ac6122b8e62ec8e1 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sun, 27 Jan 2019 00:49:16 +0800 Subject: net: hns3: do reinitialization while mqprio configuration changed When user changes the mqprio configuration, enet need to be uninited and inited besides down'ed and up'ed, because the queue num may change when the TC num changes. Also, it is more suitable to do the down/unint/init/up operation in hclge module using hclge_notify_client, because this config change may affect PF and its VF. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 17 ++--------------- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 322af28ab4b5..927a980fc211 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1482,7 +1482,6 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) u8 tc = mqprio_qopt->qopt.num_tc; u16 mode = mqprio_qopt->mode; u8 hw = mqprio_qopt->qopt.hw; - bool if_running; int ret; if (!((hw == TC_MQPRIO_HW_OFFLOAD_TCS && @@ -1495,24 +1494,12 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) if (!netdev) return -EINVAL; - if_running = netif_running(netdev); - if (if_running) { - hns3_nic_net_stop(netdev); - msleep(100); - } - ret = (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ? kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP; if (ret) - goto out; - - ret = hns3_nic_set_real_num_queue(netdev); - -out: - if (if_running) - hns3_nic_net_open(netdev); + return ret; - return ret; + return hns3_nic_set_real_num_queue(netdev); } static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 90b566e8e454..6c387b21f882 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -370,12 +370,25 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) if (ret) return -EINVAL; + ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT); + if (ret) + return ret; + + ret = hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT); + if (ret) + return ret; + hclge_tm_schd_info_update(hdev, tc); hclge_tm_prio_tc_info_update(hdev, prio_tc); ret = hclge_tm_init_hw(hdev, false); - if (ret) + if (ret) { + if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT)) + return ret; + + hclge_notify_client(hdev, HNAE3_UP_CLIENT); return ret; + } hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; @@ -384,7 +397,11 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) else hdev->flag &= ~HCLGE_FLAG_MQPRIO_ENABLE; - return 0; + ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT); + if (ret) + return ret; + + return hclge_notify_client(hdev, HNAE3_UP_CLIENT); } static const struct hnae3_dcb_ops hns3_dcb_ops = { -- cgit v1.2.3 From a1ef124e6e8621e9472098a7a37655ef4bace423 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sun, 27 Jan 2019 00:49:17 +0800 Subject: net: hns3: remove dcb_ops->map_update in hclge_dcb After doing down/uninit/init/up in hclge_dcb, it is not necessary to call dcb_ops->map_update in enet, so hclge_map_update can be called directly in hclge_dcb. This is for preparing to call hns3_nic_set_real_num_queue with netdev down when user changes mqprio configuration. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 - drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 10 +--------- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 9 +++++---- 3 files changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index dc3db45361d3..585800e634e6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -477,7 +477,6 @@ struct hnae3_dcb_ops { u8 (*getdcbx)(struct hnae3_handle *); u8 (*setdcbx)(struct hnae3_handle *, u8); - int (*map_update)(struct hnae3_handle *); int (*setup_tc)(struct hnae3_handle *, u8, u8 *); }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 927a980fc211..0ecaeab2dad4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3737,7 +3737,6 @@ static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc) { struct hnae3_knic_private_info *kinfo = &handle->kinfo; struct net_device *ndev = kinfo->netdev; - int ret; if (tc > HNAE3_MAX_TC) return -EINVAL; @@ -3745,14 +3744,7 @@ static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc) if (!ndev) return -ENODEV; - ret = (kinfo->dcb_ops && kinfo->dcb_ops->map_update) ? - kinfo->dcb_ops->map_update(handle) : -EOPNOTSUPP; - if (ret) - return ret; - - ret = hns3_nic_set_real_num_queue(ndev); - - return ret; + return hns3_nic_set_real_num_queue(ndev); } static int hns3_recover_hw_addr(struct net_device *ndev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 6c387b21f882..de8e38cca507 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -156,10 +156,8 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets, return 0; } -static int hclge_map_update(struct hnae3_handle *h) +static int hclge_map_update(struct hclge_dev *hdev) { - struct hclge_vport *vport = hclge_get_vport(h); - struct hclge_dev *hdev = vport->back; int ret; ret = hclge_tm_schd_setup_hw(hdev); @@ -235,6 +233,10 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) goto err_out; if (map_changed) { + ret = hclge_map_update(hdev); + if (ret) + goto err_out; + ret = hclge_client_setup_tc(hdev); if (ret) goto err_out; @@ -411,7 +413,6 @@ static const struct hnae3_dcb_ops hns3_dcb_ops = { .ieee_setpfc = hclge_ieee_setpfc, .getdcbx = hclge_getdcbx, .setdcbx = hclge_setdcbx, - .map_update = hclge_map_update, .setup_tc = hclge_setup_tc, }; -- cgit v1.2.3 From 1cce5eb6506d8e4924927062398e8d9ff6411536 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sun, 27 Jan 2019 00:49:18 +0800 Subject: net: hns3: call hns3_nic_set_real_num_queue with netdev down hns3_client_setup_tc in enet is for updating TC configuration to stack, and hclge_setup_tc in hclge_dcb is mainly for setting the configuration to hardware. This patch removes the hns3_nic_set_real_num_queue from hns3_setup_tc in enet, and call hclge_client_setup_tc to update TC configuration to stack with netdev down, because the netdev down operation is done in hclge_dcb now. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 7 +------ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 0ecaeab2dad4..93e3e38ba852 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1482,7 +1482,6 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) u8 tc = mqprio_qopt->qopt.num_tc; u16 mode = mqprio_qopt->mode; u8 hw = mqprio_qopt->qopt.hw; - int ret; if (!((hw == TC_MQPRIO_HW_OFFLOAD_TCS && mode == TC_MQPRIO_MODE_CHANNEL) || (!hw && tc == 0))) @@ -1494,12 +1493,8 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data) if (!netdev) return -EINVAL; - ret = (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ? + return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ? kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP; - if (ret) - return ret; - - return hns3_nic_set_real_num_queue(netdev); } static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index de8e38cca507..961aedb0e20f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -384,13 +384,12 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) hclge_tm_prio_tc_info_update(hdev, prio_tc); ret = hclge_tm_init_hw(hdev, false); - if (ret) { - if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT)) - return ret; + if (ret) + goto err_out; - hclge_notify_client(hdev, HNAE3_UP_CLIENT); - return ret; - } + ret = hclge_client_setup_tc(hdev); + if (ret) + goto err_out; hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; @@ -404,6 +403,13 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc) return ret; return hclge_notify_client(hdev, HNAE3_UP_CLIENT); + +err_out: + if (hclge_notify_client(hdev, HNAE3_INIT_CLIENT)) + return ret; + + hclge_notify_client(hdev, HNAE3_UP_CLIENT); + return ret; } static const struct hnae3_dcb_ops hns3_dcb_ops = { -- cgit v1.2.3 From 51e8439f34962794f6c5010a44893fe58450b8df Mon Sep 17 00:00:00 2001 From: Peng Li Date: Sun, 27 Jan 2019 00:49:19 +0800 Subject: net: hns3: add 8 BD limit for tx flow A single transmit packet can span up to 8 descriptors according to the HW limit. If a skb has more than 8 frags, driver uses skb_copy to get a new skb which has less frags. Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 28 ++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 93e3e38ba852..216f3dd25cd6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1133,6 +1133,7 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, struct hns3_enet_ring *ring) { struct sk_buff *skb = *out_skb; + struct sk_buff *new_skb = NULL; struct skb_frag_struct *frag; int bdnum_for_frag; int frag_num; @@ -1155,7 +1156,19 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, buf_num += bdnum_for_frag; } - if (buf_num > ring_space(ring)) + if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { + buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; + if (ring_space(ring) < buf_num) + return -EBUSY; + /* manual split the send packet */ + new_skb = skb_copy(skb, GFP_ATOMIC); + if (!new_skb) + return -ENOMEM; + dev_kfree_skb_any(skb); + *out_skb = new_skb; + } + + if (unlikely(ring_space(ring) < buf_num)) return -EBUSY; *bnum = buf_num; @@ -1166,11 +1179,24 @@ static int hns3_nic_maybe_stop_tx(struct sk_buff **out_skb, int *bnum, struct hns3_enet_ring *ring) { struct sk_buff *skb = *out_skb; + struct sk_buff *new_skb = NULL; int buf_num; /* No. of segments (plus a header) */ buf_num = skb_shinfo(skb)->nr_frags + 1; + if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { + buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; + if (ring_space(ring) < buf_num) + return -EBUSY; + /* manual split the send packet */ + new_skb = skb_copy(skb, GFP_ATOMIC); + if (!new_skb) + return -ENOMEM; + dev_kfree_skb_any(skb); + *out_skb = new_skb; + } + if (unlikely(ring_space(ring) < buf_num)) return -EBUSY; -- cgit v1.2.3 From b7b585c286ab021bdb1d0c14b93c58b6bfbe3ef0 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sun, 27 Jan 2019 00:49:20 +0800 Subject: net: hns3: add initialization for nic state This patch adds initialization for nic state, sets flag HNS3_NIC_STATE_DOWN when initialize, clears it before vectors and napi being enabled in the hns3_nic_net_up(), and sets it back in the error handler. Signed-off-by: Jian Shen Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 216f3dd25cd6..4b38c37eef8f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -348,6 +348,8 @@ static int hns3_nic_net_up(struct net_device *netdev) return ret; } + clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); + /* enable the vectors */ for (i = 0; i < priv->vector_num; i++) hns3_vector_enable(&priv->tqp_vector[i]); @@ -361,11 +363,10 @@ static int hns3_nic_net_up(struct net_device *netdev) if (ret) goto out_start_err; - clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); - return 0; out_start_err: + set_bit(HNS3_NIC_STATE_DOWN, &priv->state); while (j--) hns3_tqp_disable(h->kinfo.tqp[j]); @@ -3614,6 +3615,7 @@ static int hns3_client_init(struct hnae3_handle *handle) priv->netdev = netdev; priv->ae_handle = handle; priv->tx_timeout_count = 0; + set_bit(HNS3_NIC_STATE_DOWN, &priv->state); handle->kinfo.netdev = netdev; handle->priv = (void *)priv; -- cgit v1.2.3 From f01f5559cac89e57f2420aa77abf35f2e7b09104 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sun, 27 Jan 2019 00:49:21 +0800 Subject: net: hns3: don't allow vf to enable promisc mode VF can receive packets of other functions when in promisc mode. It's not safe, so don't allow VF to enable promisc mode. Signed-off-by: Jian Shen Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 7 ++--- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 32 ++++++++++++---------- 2 files changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index a1de451a85df..3603034aa45c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -203,12 +203,11 @@ static int hclge_map_unmap_ring_to_vf_vector(struct hclge_vport *vport, bool en, static int hclge_set_vf_promisc_mode(struct hclge_vport *vport, struct hclge_mbx_vf_to_pf_cmd *req) { - bool en_uc = req->msg[1] ? true : false; - bool en_mc = req->msg[2] ? true : false; + bool en_bc = req->msg[1] ? true : false; struct hclge_promisc_param param; - /* always enable broadcast promisc bit */ - hclge_promisc_param_init(¶m, en_uc, en_mc, true, vport->vport_id); + /* vf is not allowed to enable unicast/multicast broadcast */ + hclge_promisc_param_init(¶m, false, false, en_bc, vport->vport_id); return hclge_cmd_set_promisc_mode(vport->back, ¶m); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 24b54083b5f9..fc99a0c70164 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -969,33 +969,29 @@ static int hclgevf_put_vector(struct hnae3_handle *handle, int vector) } static int hclgevf_cmd_set_promisc_mode(struct hclgevf_dev *hdev, - bool en_uc_pmc, bool en_mc_pmc) + bool en_bc_pmc) { struct hclge_mbx_vf_to_pf_cmd *req; struct hclgevf_desc desc; - int status; + int ret; req = (struct hclge_mbx_vf_to_pf_cmd *)desc.data; hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_VF_TO_PF, false); req->msg[0] = HCLGE_MBX_SET_PROMISC_MODE; - req->msg[1] = en_uc_pmc ? 1 : 0; - req->msg[2] = en_mc_pmc ? 1 : 0; + req->msg[1] = en_bc_pmc ? 1 : 0; - status = hclgevf_cmd_send(&hdev->hw, &desc, 1); - if (status) + ret = hclgevf_cmd_send(&hdev->hw, &desc, 1); + if (ret) dev_err(&hdev->pdev->dev, - "Set promisc mode fail, status is %d.\n", status); + "Set promisc mode fail, status is %d.\n", ret); - return status; + return ret; } -static int hclgevf_set_promisc_mode(struct hnae3_handle *handle, - bool en_uc_pmc, bool en_mc_pmc) +static int hclgevf_set_promisc_mode(struct hclgevf_dev *hdev, bool en_bc_pmc) { - struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); - - return hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc); + return hclgevf_cmd_set_promisc_mode(hdev, en_bc_pmc); } static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, int tqp_id, @@ -2382,6 +2378,15 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev) if (ret) goto err_config; + /* vf is not allowed to enable unicast/multicast promisc mode. + * For revision 0x20, default to disable broadcast promisc mode, + * firmware makes sure broadcast packets can be accepted. + * For revision 0x21, default to enable broadcast promisc mode. + */ + ret = hclgevf_set_promisc_mode(hdev, true); + if (ret) + goto err_config; + /* Initialize RSS for this VF */ ret = hclgevf_rss_init_hw(hdev); if (ret) { @@ -2646,7 +2651,6 @@ static const struct hnae3_ae_ops hclgevf_ops = { .get_vector = hclgevf_get_vector, .put_vector = hclgevf_put_vector, .reset_queue = hclgevf_reset_tqp, - .set_promisc_mode = hclgevf_set_promisc_mode, .get_mac_addr = hclgevf_get_mac_addr, .set_mac_addr = hclgevf_set_mac_addr, .add_uc_addr = hclgevf_add_uc_addr, -- cgit v1.2.3 From 662a14d0c71e9e775383b0fd6796c9eb47d29ecc Mon Sep 17 00:00:00 2001 From: Bryan Whitehead Date: Wed, 23 Jan 2019 15:18:47 -0500 Subject: lan743x: Provide Read/Write Access to on chip OTP The LAN743x includes on chip One-Time-Programmable (OTP) memory. This patch extends the ethtool EEPROM read/write interface to access OTP memory space. The currently existing interface is limited, as it does not allow OTP read, and OTP writes are restricted to offset==0, length==512, and data[0]==0xF3. This patch removes these restrictions and adds a private flag called OTP_ACCESS, which is used to switch between EEPROM, and OTP modes. The private flag OTP_ACCESS is configurable through the ethtool --set-priv-flags command. And visible through the ethtool --show-priv-flags command. By default OTP_ACCESS is false, and there for previously existing EEPROM commands will work exactly the same. However now access to OTP requires one extra step of setting OTP_ACCESS to true. This flag controls the read, write, and length reporting, functions of ethtool. EEPROM presence is not checked when setting or clearing this flag. If the EEPROM is not present, the user, as before, will need to diagnose that using existing read and write function of ethtool, while OTP_ACCESS is false. Updates for V2: Added comments as to why this patch is needed. Added comments explaining that EEPROM presence is not check when setting or clearing the OTP_ACCESS flag. Added length checking to all otp/eeprom read/write functions. Signed-off-by: Bryan Whitehead Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/lan743x_ethtool.c | 217 ++++++++++++++++++----- drivers/net/ethernet/microchip/lan743x_main.h | 17 +- 2 files changed, 182 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c index 07c1eb63415a..3a0b289d9771 100644 --- a/drivers/net/ethernet/microchip/lan743x_ethtool.c +++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c @@ -14,61 +14,138 @@ #define EEPROM_INDICATOR_1 (0xA5) #define EEPROM_INDICATOR_2 (0xAA) #define EEPROM_MAC_OFFSET (0x01) -#define MAX_EEPROM_SIZE 512 +#define MAX_EEPROM_SIZE (512) +#define MAX_OTP_SIZE (1024) #define OTP_INDICATOR_1 (0xF3) #define OTP_INDICATOR_2 (0xF7) -static int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset, - u32 length, u8 *data) +static int lan743x_otp_power_up(struct lan743x_adapter *adapter) +{ + u32 reg_value; + + reg_value = lan743x_csr_read(adapter, OTP_PWR_DN); + + if (reg_value & OTP_PWR_DN_PWRDN_N_) { + /* clear it and wait to be cleared */ + reg_value &= ~OTP_PWR_DN_PWRDN_N_; + lan743x_csr_write(adapter, OTP_PWR_DN, reg_value); + + usleep_range(100, 20000); + } + + return 0; +} + +static void lan743x_otp_power_down(struct lan743x_adapter *adapter) +{ + u32 reg_value; + + reg_value = lan743x_csr_read(adapter, OTP_PWR_DN); + if (!(reg_value & OTP_PWR_DN_PWRDN_N_)) { + /* set power down bit */ + reg_value |= OTP_PWR_DN_PWRDN_N_; + lan743x_csr_write(adapter, OTP_PWR_DN, reg_value); + } +} + +static void lan743x_otp_set_address(struct lan743x_adapter *adapter, + u32 address) +{ + lan743x_csr_write(adapter, OTP_ADDR_HIGH, (address >> 8) & 0x03); + lan743x_csr_write(adapter, OTP_ADDR_LOW, address & 0xFF); +} + +static void lan743x_otp_read_go(struct lan743x_adapter *adapter) +{ + lan743x_csr_write(adapter, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_); + lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_); +} + +static int lan743x_otp_wait_till_not_busy(struct lan743x_adapter *adapter) { unsigned long timeout; - u32 buf; + u32 reg_val; + + timeout = jiffies + HZ; + do { + if (time_after(jiffies, timeout)) { + netif_warn(adapter, drv, adapter->netdev, + "Timeout on OTP_STATUS completion\n"); + return -EIO; + } + udelay(1); + reg_val = lan743x_csr_read(adapter, OTP_STATUS); + } while (reg_val & OTP_STATUS_BUSY_); + + return 0; +} + +static int lan743x_otp_read(struct lan743x_adapter *adapter, u32 offset, + u32 length, u8 *data) +{ + int ret; int i; - buf = lan743x_csr_read(adapter, OTP_PWR_DN); + if (offset + length > MAX_OTP_SIZE) + return -EINVAL; - if (buf & OTP_PWR_DN_PWRDN_N_) { - /* clear it and wait to be cleared */ - lan743x_csr_write(adapter, OTP_PWR_DN, 0); - - timeout = jiffies + HZ; - do { - udelay(1); - buf = lan743x_csr_read(adapter, OTP_PWR_DN); - if (time_after(jiffies, timeout)) { - netif_warn(adapter, drv, adapter->netdev, - "timeout on OTP_PWR_DN completion\n"); - return -EIO; - } - } while (buf & OTP_PWR_DN_PWRDN_N_); + ret = lan743x_otp_power_up(adapter); + if (ret < 0) + return ret; + + ret = lan743x_otp_wait_till_not_busy(adapter); + if (ret < 0) + return ret; + + for (i = 0; i < length; i++) { + lan743x_otp_set_address(adapter, offset + i); + + lan743x_otp_read_go(adapter); + ret = lan743x_otp_wait_till_not_busy(adapter); + if (ret < 0) + return ret; + data[i] = lan743x_csr_read(adapter, OTP_READ_DATA); } + lan743x_otp_power_down(adapter); + + return 0; +} + +static int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset, + u32 length, u8 *data) +{ + int ret; + int i; + + if (offset + length > MAX_OTP_SIZE) + return -EINVAL; + + ret = lan743x_otp_power_up(adapter); + if (ret < 0) + return ret; + + ret = lan743x_otp_wait_till_not_busy(adapter); + if (ret < 0) + return ret; + /* set to BYTE program mode */ lan743x_csr_write(adapter, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_); for (i = 0; i < length; i++) { - lan743x_csr_write(adapter, OTP_ADDR1, - ((offset + i) >> 8) & - OTP_ADDR1_15_11_MASK_); - lan743x_csr_write(adapter, OTP_ADDR2, - ((offset + i) & - OTP_ADDR2_10_3_MASK_)); + lan743x_otp_set_address(adapter, offset + i); + lan743x_csr_write(adapter, OTP_PRGM_DATA, data[i]); lan743x_csr_write(adapter, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_); lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_); - timeout = jiffies + HZ; - do { - udelay(1); - buf = lan743x_csr_read(adapter, OTP_STATUS); - if (time_after(jiffies, timeout)) { - netif_warn(adapter, drv, adapter->netdev, - "Timeout on OTP_STATUS completion\n"); - return -EIO; - } - } while (buf & OTP_STATUS_BUSY_); + ret = lan743x_otp_wait_till_not_busy(adapter); + if (ret < 0) + return ret; } + lan743x_otp_power_down(adapter); + return 0; } @@ -120,6 +197,9 @@ static int lan743x_eeprom_read(struct lan743x_adapter *adapter, u32 val; int i; + if (offset + length > MAX_EEPROM_SIZE) + return -EINVAL; + retval = lan743x_eeprom_confirm_not_busy(adapter); if (retval) return retval; @@ -148,6 +228,9 @@ static int lan743x_eeprom_write(struct lan743x_adapter *adapter, u32 val; int i; + if (offset + length > MAX_EEPROM_SIZE) + return -EINVAL; + retval = lan743x_eeprom_confirm_not_busy(adapter); if (retval) return retval; @@ -207,6 +290,11 @@ static void lan743x_ethtool_set_msglevel(struct net_device *netdev, static int lan743x_ethtool_get_eeprom_len(struct net_device *netdev) { + struct lan743x_adapter *adapter = netdev_priv(netdev); + + if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) + return MAX_OTP_SIZE; + return MAX_EEPROM_SIZE; } @@ -214,8 +302,14 @@ static int lan743x_ethtool_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee, u8 *data) { struct lan743x_adapter *adapter = netdev_priv(netdev); + int ret = 0; + + if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) + ret = lan743x_otp_read(adapter, ee->offset, ee->len, data); + else + ret = lan743x_eeprom_read(adapter, ee->offset, ee->len, data); - return lan743x_eeprom_read(adapter, ee->offset, ee->len, data); + return ret; } static int lan743x_ethtool_set_eeprom(struct net_device *netdev, @@ -224,17 +318,18 @@ static int lan743x_ethtool_set_eeprom(struct net_device *netdev, struct lan743x_adapter *adapter = netdev_priv(netdev); int ret = -EINVAL; - if (ee->magic == LAN743X_EEPROM_MAGIC) - ret = lan743x_eeprom_write(adapter, ee->offset, ee->len, - data); - /* Beware! OTP is One Time Programming ONLY! - * So do some strict condition check before messing up - */ - else if ((ee->magic == LAN743X_OTP_MAGIC) && - (ee->offset == 0) && - (ee->len == MAX_EEPROM_SIZE) && - (data[0] == OTP_INDICATOR_1)) - ret = lan743x_otp_write(adapter, ee->offset, ee->len, data); + if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) { + /* Beware! OTP is One Time Programming ONLY! */ + if (ee->magic == LAN743X_OTP_MAGIC) { + ret = lan743x_otp_write(adapter, ee->offset, + ee->len, data); + } + } else { + if (ee->magic == LAN743X_EEPROM_MAGIC) { + ret = lan743x_eeprom_write(adapter, ee->offset, + ee->len, data); + } + } return ret; } @@ -360,6 +455,10 @@ static const u32 lan743x_set2_hw_cnt_addr[] = { STAT_TX_COUNTER_ROLLOVER_STATUS }; +static const char lan743x_priv_flags_strings[][ETH_GSTRING_LEN] = { + "OTP_ACCESS", +}; + static void lan743x_ethtool_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { @@ -375,6 +474,10 @@ static void lan743x_ethtool_get_strings(struct net_device *netdev, lan743x_set2_hw_cnt_strings, sizeof(lan743x_set2_hw_cnt_strings)); break; + case ETH_SS_PRIV_FLAGS: + memcpy(data, lan743x_priv_flags_strings, + sizeof(lan743x_priv_flags_strings)); + break; } } @@ -399,6 +502,22 @@ static void lan743x_ethtool_get_ethtool_stats(struct net_device *netdev, } } +static u32 lan743x_ethtool_get_priv_flags(struct net_device *netdev) +{ + struct lan743x_adapter *adapter = netdev_priv(netdev); + + return adapter->flags; +} + +static int lan743x_ethtool_set_priv_flags(struct net_device *netdev, u32 flags) +{ + struct lan743x_adapter *adapter = netdev_priv(netdev); + + adapter->flags = flags; + + return 0; +} + static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { @@ -411,6 +530,8 @@ static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset) ret += ARRAY_SIZE(lan743x_set2_hw_cnt_strings); return ret; } + case ETH_SS_PRIV_FLAGS: + return ARRAY_SIZE(lan743x_priv_flags_strings); default: return -EOPNOTSUPP; } @@ -705,6 +826,8 @@ const struct ethtool_ops lan743x_ethtool_ops = { .set_eeprom = lan743x_ethtool_set_eeprom, .get_strings = lan743x_ethtool_get_strings, .get_ethtool_stats = lan743x_ethtool_get_ethtool_stats, + .get_priv_flags = lan743x_ethtool_get_priv_flags, + .set_priv_flags = lan743x_ethtool_set_priv_flags, .get_sset_count = lan743x_ethtool_get_sset_count, .get_rxnfc = lan743x_ethtool_get_rxnfc, .get_rxfh_key_size = lan743x_ethtool_get_rxfh_key_size, diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h index 2d6eea18973e..3b02eeae5f45 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.h +++ b/drivers/net/ethernet/microchip/lan743x_main.h @@ -26,6 +26,8 @@ #define FPGA_REV_GET_MAJOR_(fpga_rev) ((fpga_rev) & 0x000000FF) #define HW_CFG (0x010) +#define HW_CFG_RELOAD_TYPE_ALL_ (0x00000FC0) +#define HW_CFG_EE_OTP_RELOAD_ BIT(4) #define HW_CFG_LRST_ BIT(1) #define PMT_CTL (0x014) @@ -453,17 +455,19 @@ #define OTP_PWR_DN (0x1000) #define OTP_PWR_DN_PWRDN_N_ BIT(0) -#define OTP_ADDR1 (0x1004) -#define OTP_ADDR1_15_11_MASK_ (0x1F) - -#define OTP_ADDR2 (0x1008) -#define OTP_ADDR2_10_3_MASK_ (0xFF) +#define OTP_ADDR_HIGH (0x1004) +#define OTP_ADDR_LOW (0x1008) #define OTP_PRGM_DATA (0x1010) #define OTP_PRGM_MODE (0x1014) #define OTP_PRGM_MODE_BYTE_ BIT(0) +#define OTP_READ_DATA (0x1018) + +#define OTP_FUNC_CMD (0x1020) +#define OTP_FUNC_CMD_READ_ BIT(0) + #define OTP_TST_CMD (0x1024) #define OTP_TST_CMD_PRGVRFY_ BIT(3) @@ -713,6 +717,9 @@ struct lan743x_adapter { struct lan743x_phy phy; struct lan743x_tx tx[LAN743X_MAX_TX_CHANNELS]; struct lan743x_rx rx[LAN743X_MAX_RX_CHANNELS]; + +#define LAN743X_ADAPTER_FLAG_OTP BIT(0) + u32 flags; }; #define LAN743X_COMPONENT_FLAG_RX(channel) BIT(20 + (channel)) -- cgit v1.2.3 From 461448398ac104b014530680dbac09e577cd2695 Mon Sep 17 00:00:00 2001 From: Jiong Wang Date: Sat, 26 Jan 2019 12:26:12 -0500 Subject: nfp: bpf: implement jitting of JMP32 This patch implements code-gen for new JMP32 instructions on NFP. Reviewed-by: Jakub Kicinski Signed-off-by: Jiong Wang Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/netronome/nfp/bpf/jit.c | 97 ++++++++++++++++++++------- drivers/net/ethernet/netronome/nfp/bpf/main.h | 22 +++++- 2 files changed, 93 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index 3308fd92c017..aa3a2098a583 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c @@ -1334,8 +1334,9 @@ wrp_test_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, wrp_test_reg_one(nfp_prog, insn->dst_reg * 2, alu_op, insn->src_reg * 2, br_mask, insn->off); - wrp_test_reg_one(nfp_prog, insn->dst_reg * 2 + 1, alu_op, - insn->src_reg * 2 + 1, br_mask, insn->off); + if (is_mbpf_jmp64(meta)) + wrp_test_reg_one(nfp_prog, insn->dst_reg * 2 + 1, alu_op, + insn->src_reg * 2 + 1, br_mask, insn->off); return 0; } @@ -1390,13 +1391,15 @@ static int cmp_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) else emit_alu(nfp_prog, reg_none(), tmp_reg, alu_op, reg_a(reg)); - tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); - if (!code->swap) - emit_alu(nfp_prog, reg_none(), - reg_a(reg + 1), carry_op, tmp_reg); - else - emit_alu(nfp_prog, reg_none(), - tmp_reg, carry_op, reg_a(reg + 1)); + if (is_mbpf_jmp64(meta)) { + tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); + if (!code->swap) + emit_alu(nfp_prog, reg_none(), + reg_a(reg + 1), carry_op, tmp_reg); + else + emit_alu(nfp_prog, reg_none(), + tmp_reg, carry_op, reg_a(reg + 1)); + } emit_br(nfp_prog, code->br_mask, insn->off, 0); @@ -1423,8 +1426,9 @@ static int cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) } emit_alu(nfp_prog, reg_none(), reg_a(areg), ALU_OP_SUB, reg_b(breg)); - emit_alu(nfp_prog, reg_none(), - reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1)); + if (is_mbpf_jmp64(meta)) + emit_alu(nfp_prog, reg_none(), + reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1)); emit_br(nfp_prog, code->br_mask, insn->off, 0); return 0; @@ -3048,6 +3052,19 @@ static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) return 0; } +static int jeq32_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +{ + const struct bpf_insn *insn = &meta->insn; + swreg tmp_reg; + + tmp_reg = ur_load_imm_any(nfp_prog, insn->imm, imm_b(nfp_prog)); + emit_alu(nfp_prog, reg_none(), + reg_a(insn->dst_reg * 2), ALU_OP_XOR, tmp_reg); + emit_br(nfp_prog, BR_BEQ, insn->off, 0); + + return 0; +} + static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { const struct bpf_insn *insn = &meta->insn; @@ -3061,9 +3078,10 @@ static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) /* Upper word of the mask can only be 0 or ~0 from sign extension, * so either ignore it or OR the whole thing in. */ - if (imm >> 32) + if (is_mbpf_jmp64(meta) && imm >> 32) { emit_alu(nfp_prog, reg_none(), reg_a(dst_gpr + 1), ALU_OP_OR, imm_b(nfp_prog)); + } emit_br(nfp_prog, BR_BNE, insn->off, 0); return 0; @@ -3073,11 +3091,16 @@ static int jne_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { const struct bpf_insn *insn = &meta->insn; u64 imm = insn->imm; /* sign extend */ + bool is_jmp32 = is_mbpf_jmp32(meta); swreg tmp_reg; if (!imm) { - emit_alu(nfp_prog, reg_none(), reg_a(insn->dst_reg * 2), - ALU_OP_OR, reg_b(insn->dst_reg * 2 + 1)); + if (is_jmp32) + emit_alu(nfp_prog, reg_none(), reg_none(), ALU_OP_NONE, + reg_b(insn->dst_reg * 2)); + else + emit_alu(nfp_prog, reg_none(), reg_a(insn->dst_reg * 2), + ALU_OP_OR, reg_b(insn->dst_reg * 2 + 1)); emit_br(nfp_prog, BR_BNE, insn->off, 0); return 0; } @@ -3087,6 +3110,9 @@ static int jne_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) reg_a(insn->dst_reg * 2), ALU_OP_XOR, tmp_reg); emit_br(nfp_prog, BR_BNE, insn->off, 0); + if (is_jmp32) + return 0; + tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); emit_alu(nfp_prog, reg_none(), reg_a(insn->dst_reg * 2 + 1), ALU_OP_XOR, tmp_reg); @@ -3101,10 +3127,13 @@ static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) emit_alu(nfp_prog, imm_a(nfp_prog), reg_a(insn->dst_reg * 2), ALU_OP_XOR, reg_b(insn->src_reg * 2)); - emit_alu(nfp_prog, imm_b(nfp_prog), reg_a(insn->dst_reg * 2 + 1), - ALU_OP_XOR, reg_b(insn->src_reg * 2 + 1)); - emit_alu(nfp_prog, reg_none(), - imm_a(nfp_prog), ALU_OP_OR, imm_b(nfp_prog)); + if (is_mbpf_jmp64(meta)) { + emit_alu(nfp_prog, imm_b(nfp_prog), + reg_a(insn->dst_reg * 2 + 1), ALU_OP_XOR, + reg_b(insn->src_reg * 2 + 1)); + emit_alu(nfp_prog, reg_none(), imm_a(nfp_prog), ALU_OP_OR, + imm_b(nfp_prog)); + } emit_br(nfp_prog, BR_BEQ, insn->off, 0); return 0; @@ -3369,6 +3398,28 @@ static const instr_cb_t instr_cb[256] = { [BPF_JMP | BPF_JSLE | BPF_X] = cmp_reg, [BPF_JMP | BPF_JSET | BPF_X] = jset_reg, [BPF_JMP | BPF_JNE | BPF_X] = jne_reg, + [BPF_JMP32 | BPF_JEQ | BPF_K] = jeq32_imm, + [BPF_JMP32 | BPF_JGT | BPF_K] = cmp_imm, + [BPF_JMP32 | BPF_JGE | BPF_K] = cmp_imm, + [BPF_JMP32 | BPF_JLT | BPF_K] = cmp_imm, + [BPF_JMP32 | BPF_JLE | BPF_K] = cmp_imm, + [BPF_JMP32 | BPF_JSGT | BPF_K] =cmp_imm, + [BPF_JMP32 | BPF_JSGE | BPF_K] =cmp_imm, + [BPF_JMP32 | BPF_JSLT | BPF_K] =cmp_imm, + [BPF_JMP32 | BPF_JSLE | BPF_K] =cmp_imm, + [BPF_JMP32 | BPF_JSET | BPF_K] =jset_imm, + [BPF_JMP32 | BPF_JNE | BPF_K] = jne_imm, + [BPF_JMP32 | BPF_JEQ | BPF_X] = jeq_reg, + [BPF_JMP32 | BPF_JGT | BPF_X] = cmp_reg, + [BPF_JMP32 | BPF_JGE | BPF_X] = cmp_reg, + [BPF_JMP32 | BPF_JLT | BPF_X] = cmp_reg, + [BPF_JMP32 | BPF_JLE | BPF_X] = cmp_reg, + [BPF_JMP32 | BPF_JSGT | BPF_X] =cmp_reg, + [BPF_JMP32 | BPF_JSGE | BPF_X] =cmp_reg, + [BPF_JMP32 | BPF_JSLT | BPF_X] =cmp_reg, + [BPF_JMP32 | BPF_JSLE | BPF_X] =cmp_reg, + [BPF_JMP32 | BPF_JSET | BPF_X] =jset_reg, + [BPF_JMP32 | BPF_JNE | BPF_X] = jne_reg, [BPF_JMP | BPF_CALL] = call, [BPF_JMP | BPF_EXIT] = jmp_exit, }; @@ -3397,7 +3448,7 @@ static int nfp_fixup_branches(struct nfp_prog *nfp_prog) list_for_each_entry(meta, &nfp_prog->insns, l) { if (meta->flags & FLAG_INSN_SKIP_MASK) continue; - if (BPF_CLASS(meta->insn.code) != BPF_JMP) + if (!is_mbpf_jmp(meta)) continue; if (meta->insn.code == (BPF_JMP | BPF_EXIT) && !nfp_is_main_function(meta)) @@ -3758,16 +3809,14 @@ static void nfp_bpf_opt_neg_add_sub(struct nfp_prog *nfp_prog) if (meta->flags & FLAG_INSN_SKIP_MASK) continue; - if (BPF_CLASS(insn.code) != BPF_ALU && - BPF_CLASS(insn.code) != BPF_ALU64 && - BPF_CLASS(insn.code) != BPF_JMP) + if (!is_mbpf_alu(meta) && !is_mbpf_jmp(meta)) continue; if (BPF_SRC(insn.code) != BPF_K) continue; if (insn.imm >= 0) continue; - if (BPF_CLASS(insn.code) == BPF_JMP) { + if (is_mbpf_jmp(meta)) { switch (BPF_OP(insn.code)) { case BPF_JGE: case BPF_JSGE: @@ -4338,7 +4387,7 @@ void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog) unsigned int dst_idx; bool pseudo_call; - if (BPF_CLASS(code) != BPF_JMP) + if (!is_mbpf_jmp(meta)) continue; if (BPF_OP(code) == BPF_EXIT) continue; diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.h b/drivers/net/ethernet/netronome/nfp/bpf/main.h index 5813c3e13ebe..b25a48218bcf 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.h +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.h @@ -365,6 +365,21 @@ static inline bool is_mbpf_load(const struct nfp_insn_meta *meta) return (meta->insn.code & ~BPF_SIZE_MASK) == (BPF_LDX | BPF_MEM); } +static inline bool is_mbpf_jmp32(const struct nfp_insn_meta *meta) +{ + return mbpf_class(meta) == BPF_JMP32; +} + +static inline bool is_mbpf_jmp64(const struct nfp_insn_meta *meta) +{ + return mbpf_class(meta) == BPF_JMP; +} + +static inline bool is_mbpf_jmp(const struct nfp_insn_meta *meta) +{ + return is_mbpf_jmp32(meta) || is_mbpf_jmp64(meta); +} + static inline bool is_mbpf_store(const struct nfp_insn_meta *meta) { return (meta->insn.code & ~BPF_SIZE_MASK) == (BPF_STX | BPF_MEM); @@ -419,10 +434,13 @@ static inline bool is_mbpf_cond_jump(const struct nfp_insn_meta *meta) { u8 op; - if (BPF_CLASS(meta->insn.code) != BPF_JMP) + if (is_mbpf_jmp32(meta)) + return true; + + if (!is_mbpf_jmp64(meta)) return false; - op = BPF_OP(meta->insn.code); + op = mbpf_op(meta); return op != BPF_JA && op != BPF_EXIT && op != BPF_CALL; } -- cgit v1.2.3 From 7304720d70a223186d192d766e9b5d25470a705d Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Thu, 24 Jan 2019 22:45:38 +0800 Subject: atheros: atl2: replace dev_kfree_skb_any() by dev_consume_skb_any() atl2_xmit_frame() should call dev_consume_skb_any() when the transmission is successful. It makes drop profiles more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atlx/atl2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index bb41becb6609..c44e95255aa1 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -909,7 +909,7 @@ static netdev_tx_t atl2_xmit_frame(struct sk_buff *skb, (adapter->txd_write_ptr >> 2)); mmiowb(); - dev_kfree_skb_any(skb); + dev_consume_skb_any(skb); return NETDEV_TX_OK; } -- cgit v1.2.3 From 085c4c7dd2b6558fb079fad07d6e9064f5e0b4c2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 25 Jan 2019 23:22:29 +0900 Subject: net: lmc: remove -I. header search path The header search path -I. in kernel Makefiles is very suspicious; it allows the compiler to search for headers in the top of $(srctree), where obviously no header file exists. I was able to build without this header search path. Signed-off-by: Masahiro Yamada Signed-off-by: David S. Miller --- drivers/net/wan/lmc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/lmc/Makefile b/drivers/net/wan/lmc/Makefile index 609710d64eb5..247f60c401ef 100644 --- a/drivers/net/wan/lmc/Makefile +++ b/drivers/net/wan/lmc/Makefile @@ -14,4 +14,4 @@ lmc-objs := lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o # -DDEBUG \ # -DLMC_PACKET_LOG -ccflags-y := -I. $(DBGDEF) +ccflags-y := $(DBGDEF) -- cgit v1.2.3 From 0e0213965c97685efe814f51271f2f2699a8972d Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Fri, 25 Jan 2019 12:35:10 +0000 Subject: net: phy: at803x: Use helpers to access MMD PHY registers Libphy provides a standard set of helpers to access the MMD PHY registers. Use those instead of relying on custom driver-specific functions. Signed-off-by: Carlo Caione Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 512562084283..90dc62c15fc5 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -35,9 +35,6 @@ #define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A -#define AT803X_MMD_ACCESS_CONTROL 0x0D -#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E -#define AT803X_FUNC_DATA 0x4003 #define AT803X_REG_CHIP_CONFIG 0x1f #define AT803X_BT_BX_REG_SEL 0x8000 @@ -164,16 +161,9 @@ static int at803x_set_wol(struct phy_device *phydev, if (!is_valid_ether_addr(mac)) return -EINVAL; - for (i = 0; i < 3; i++) { - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, - AT803X_DEVICE_ADDR); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, - offsets[i]); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, - AT803X_FUNC_DATA); - phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, - mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); - } + for (i = 0; i < 3; i++) + phy_write_mmd(phydev, AT803X_DEVICE_ADDR, offsets[i], + mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); value = phy_read(phydev, AT803X_INTR_ENABLE); value |= AT803X_INTR_ENABLE_WOL; -- cgit v1.2.3 From 00df214b1faae520880cc5c57e206f21239ef741 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Sun, 27 Jan 2019 16:33:59 +0800 Subject: Bluetooth: btrtl: Restore old logic to assume firmware is already loaded Realtek bluetooth may not work after reboot: [ 12.446130] Bluetooth: hci0: RTL: rtl: unknown IC info, lmp subver a99e, hci rev 826c, hci ver 0008 This is a regression introduced by commit 26503ad25de8 ("Bluetooth: btrtl: split the device initialization into smaller parts"). The new logic errors out early when no matching IC info can be found, in this case it means the firmware is already loaded. So let's assume the firmware is already loaded when we can't find matching IC info, like the old logic did. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=201921 Fixes: 26503ad25de8 ("Bluetooth: btrtl: split the device initialization into smaller parts") Cc: stable@vger.kernel.org # 4.19+ Signed-off-by: Kai-Heng Feng Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btrtl.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 41405de27d66..c91bba00df4e 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -552,10 +552,9 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev, hdev->bus); if (!btrtl_dev->ic_info) { - rtl_dev_err(hdev, "rtl: unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x", + rtl_dev_info(hdev, "rtl: unknown IC info, lmp subver %04x, hci rev %04x, hci ver %04x", lmp_subver, hci_rev, hci_ver); - ret = -EINVAL; - goto err_free; + return btrtl_dev; } if (btrtl_dev->ic_info->has_rom_version) { @@ -610,6 +609,11 @@ int btrtl_download_firmware(struct hci_dev *hdev, * standard btusb. Once that firmware is uploaded, the subver changes * to a different value. */ + if (!btrtl_dev->ic_info) { + rtl_dev_info(hdev, "rtl: assuming no firmware upload needed\n"); + return 0; + } + switch (btrtl_dev->ic_info->lmp_subver) { case RTL_ROM_LMP_8723A: case RTL_ROM_LMP_3499: -- cgit v1.2.3 From 42d704e01817b4d64f1971a1f2e992a69bd5c772 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 28 Jan 2019 12:02:07 +0000 Subject: mlxsw: spectrum_acl: Remove unnecessary arg on action_replace call path No need to pass ruleset/group and chunk pointers on action_replace call path, nobody uses them. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 3 +-- drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c | 3 +-- drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c | 5 +---- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 3 +-- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c | 2 -- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c | 1 - drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 11 ++++------- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 5 +---- 8 files changed, 9 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 9384b108c8c2..4fe0996c7cdd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -721,8 +721,7 @@ struct mlxsw_sp_acl_tcam_ops { void *region_priv, void *chunk_priv, void *entry_priv); int (*entry_action_replace)(struct mlxsw_sp *mlxsw_sp, - void *region_priv, void *chunk_priv, - void *entry_priv, + void *region_priv, void *entry_priv, struct mlxsw_sp_acl_rule_info *rulei); int (*entry_activity_get)(struct mlxsw_sp *mlxsw_sp, void *region_priv, void *entry_priv, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c index fe270c1a26a6..6e444525713f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c @@ -194,8 +194,7 @@ static void mlxsw_sp1_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp1_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, - void *region_priv, void *chunk_priv, - void *entry_priv, + void *region_priv, void *entry_priv, struct mlxsw_sp_acl_rule_info *rulei) { return -EOPNOTSUPP; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c index 234ab51916db..d380b3403960 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c @@ -212,18 +212,15 @@ static void mlxsw_sp2_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp2_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, - void *region_priv, void *chunk_priv, - void *entry_priv, + void *region_priv, void *entry_priv, struct mlxsw_sp_acl_rule_info *rulei) { struct mlxsw_sp2_acl_tcam_region *region = region_priv; - struct mlxsw_sp2_acl_tcam_chunk *chunk = chunk_priv; struct mlxsw_sp2_acl_tcam_entry *entry = entry_priv; entry->act_block = rulei->act_block; return mlxsw_sp_acl_atcam_entry_action_replace(mlxsw_sp, ®ion->aregion, - &chunk->achunk, &entry->aentry, rulei); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 695d33358988..bd40ed065f3e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -742,8 +742,7 @@ int mlxsw_sp_acl_rule_action_replace(struct mlxsw_sp *mlxsw_sp, rulei = mlxsw_sp_acl_rule_rulei(rule); rulei->act_block = afa_block; - return ops->rule_action_replace(mlxsw_sp, ruleset->priv, rule->priv, - rule->rulei); + return ops->rule_action_replace(mlxsw_sp, rule->priv, rule->rulei); } struct mlxsw_sp_acl_rule * diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index 80fb268d51a5..40dc76a5c412 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -603,7 +603,6 @@ void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, - struct mlxsw_sp_acl_atcam_chunk *achunk, struct mlxsw_sp_acl_atcam_entry *aentry, struct mlxsw_sp_acl_rule_info *rulei) { @@ -612,7 +611,6 @@ mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, if (mlxsw_sp_acl_atcam_is_centry(aentry)) err = mlxsw_sp_acl_ctcam_entry_action_replace(mlxsw_sp, &aregion->cregion, - &achunk->cchunk, &aentry->centry, rulei); else diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c index ac222833a5cf..05680a7e6c56 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c @@ -223,7 +223,6 @@ void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_region *cregion, - struct mlxsw_sp_acl_ctcam_chunk *cchunk, struct mlxsw_sp_acl_ctcam_entry *centry, struct mlxsw_sp_acl_rule_info *rulei) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index fe230acf92a9..5d29c5050401 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -781,7 +781,6 @@ static void mlxsw_sp_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, struct mlxsw_sp_acl_tcam_entry *entry, struct mlxsw_sp_acl_rule_info *rulei) { @@ -789,7 +788,7 @@ mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk; struct mlxsw_sp_acl_tcam_region *region = chunk->region; - return ops->entry_action_replace(mlxsw_sp, region->priv, chunk->priv, + return ops->entry_action_replace(mlxsw_sp, region->priv, entry->priv, rulei); } @@ -955,7 +954,6 @@ mlxsw_sp_acl_tcam_flower_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv) static int mlxsw_sp_acl_tcam_flower_rule_action_replace(struct mlxsw_sp *mlxsw_sp, - void *ruleset_priv, void *rule_priv, struct mlxsw_sp_acl_rule_info *rulei) { @@ -1084,14 +1082,13 @@ mlxsw_sp_acl_tcam_mr_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv) static int mlxsw_sp_acl_tcam_mr_rule_action_replace(struct mlxsw_sp *mlxsw_sp, - void *ruleset_priv, void *rule_priv, + void *rule_priv, struct mlxsw_sp_acl_rule_info *rulei) { - struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv; struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv; - return mlxsw_sp_acl_tcam_entry_action_replace(mlxsw_sp, &ruleset->group, - &rule->entry, rulei); + return mlxsw_sp_acl_tcam_entry_action_replace(mlxsw_sp, &rule->entry, + rulei); } static int diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 0f1a9dee63de..10512b7c6d50 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -48,8 +48,7 @@ struct mlxsw_sp_acl_profile_ops { void *ruleset_priv, void *rule_priv, struct mlxsw_sp_acl_rule_info *rulei); void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv); - int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp, - void *ruleset_priv, void *rule_priv, + int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp, void *rule_priv, struct mlxsw_sp_acl_rule_info *rulei); int (*rule_activity_get)(struct mlxsw_sp *mlxsw_sp, void *rule_priv, bool *activity); @@ -126,7 +125,6 @@ void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_entry *centry); int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_ctcam_region *cregion, - struct mlxsw_sp_acl_ctcam_chunk *cchunk, struct mlxsw_sp_acl_ctcam_entry *centry, struct mlxsw_sp_acl_rule_info *rulei); static inline unsigned int @@ -224,7 +222,6 @@ void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_entry *aentry); int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, - struct mlxsw_sp_acl_atcam_chunk *achunk, struct mlxsw_sp_acl_atcam_entry *aentry, struct mlxsw_sp_acl_rule_info *rulei); int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp, -- cgit v1.2.3 From 038418eeb95539e6c22ae89f91d068346b5c1b9a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 28 Jan 2019 12:02:08 +0000 Subject: mlxsw: spectrum_acl: Move mr_ruleset and mr_rule structs Move the struct to the place where they belong, alongside with the rest of the MR code. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 5d29c5050401..11456e1f236f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -862,15 +862,6 @@ struct mlxsw_sp_acl_tcam_flower_rule { struct mlxsw_sp_acl_tcam_entry entry; }; -struct mlxsw_sp_acl_tcam_mr_ruleset { - struct mlxsw_sp_acl_tcam_chunk *chunk; - struct mlxsw_sp_acl_tcam_group group; -}; - -struct mlxsw_sp_acl_tcam_mr_rule { - struct mlxsw_sp_acl_tcam_entry entry; -}; - static int mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam, @@ -984,6 +975,15 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = { .rule_activity_get = mlxsw_sp_acl_tcam_flower_rule_activity_get, }; +struct mlxsw_sp_acl_tcam_mr_ruleset { + struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_group group; +}; + +struct mlxsw_sp_acl_tcam_mr_rule { + struct mlxsw_sp_acl_tcam_entry entry; +}; + static int mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam, -- cgit v1.2.3 From 3021afe16828123dc6c13be4a4df325ec386477c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 28 Jan 2019 12:02:09 +0000 Subject: mlxsw: spectrum_acl: Fix rul/rule typo Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index bd40ed065f3e..a69e3462b65e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -805,7 +805,7 @@ static void mlxsw_sp_acl_rule_activity_work_schedule(struct mlxsw_sp_acl *acl) msecs_to_jiffies(interval)); } -static void mlxsw_sp_acl_rul_activity_update_work(struct work_struct *work) +static void mlxsw_sp_acl_rule_activity_update_work(struct work_struct *work) { struct mlxsw_sp_acl *acl = container_of(work, struct mlxsw_sp_acl, rule_activity_update.dw.work); @@ -884,7 +884,7 @@ int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp) /* Create the delayed work for the rule activity_update */ INIT_DELAYED_WORK(&acl->rule_activity_update.dw, - mlxsw_sp_acl_rul_activity_update_work); + mlxsw_sp_acl_rule_activity_update_work); acl->rule_activity_update.interval = MLXSW_SP_ACL_RULE_ACTIVITY_UPDATE_PERIOD_MS; mlxsw_core_schedule_dw(&acl->rule_activity_update.dw, 0); return 0; -- cgit v1.2.3 From 2adeb5f1c3f5b69b1dfe515db29403cdc09b13b2 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 28 Jan 2019 12:02:10 +0000 Subject: mlxsw: spectrum_switchdev: Add more extack messages Add more extack messages that let the user know why VXLAN offload failed. Signed-off-by: Ido Schimmel Suggested-by: David Ahern Cc: David Ahern Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 0f4e68d31cc3..a4a9fe992193 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -2027,6 +2027,7 @@ mlxsw_sp_bridge_8021q_vxlan_join(struct mlxsw_sp_bridge_device *bridge_device, return 0; if (mlxsw_sp_fid_vni_is_set(fid)) { + NL_SET_ERR_MSG_MOD(extack, "VNI is already set on FID"); err = -EINVAL; goto err_vni_exists; } @@ -2213,10 +2214,13 @@ mlxsw_sp_bridge_8021d_vxlan_join(struct mlxsw_sp_bridge_device *bridge_device, int err; fid = mlxsw_sp_fid_8021d_lookup(mlxsw_sp, bridge_device->dev->ifindex); - if (!fid) + if (!fid) { + NL_SET_ERR_MSG_MOD(extack, "Did not find a corresponding FID"); return -EINVAL; + } if (mlxsw_sp_fid_vni_is_set(fid)) { + NL_SET_ERR_MSG_MOD(extack, "VNI is already set on FID"); err = -EINVAL; goto err_vni_exists; } @@ -3231,8 +3235,10 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp, * the lookup function to return 'vxlan_dev' */ if (flag_untagged && flag_pvid && - mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid)) + mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid)) { + NL_SET_ERR_MSG_MOD(extack, "VLAN already mapped to a different VNI"); return -EINVAL; + } if (!netif_running(vxlan_dev)) return 0; -- cgit v1.2.3 From 8e067bb3fc921f31450403d82ef664832735c424 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 28 Jan 2019 17:17:40 +0100 Subject: benet: remove broken and unused macro is_broadcast_packet() expands to compare_ether_addr() which doesn't exist since commit 7367d0b573d1 ("drivers/net: Convert uses of compare_ether_addr to ether_addr_equal"). It turns out it's actually not used. Signed-off-by: Lubomir Rintel Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index d5026909dec5..3c7c04406a2b 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1270,10 +1270,6 @@ static void be_xmit_flush(struct be_adapter *adapter, struct be_tx_obj *txo) #define is_arp_allowed_on_bmc(adapter, skb) \ (is_arp(skb) && is_arp_filt_enabled(adapter)) -#define is_broadcast_packet(eh, adapter) \ - (is_multicast_ether_addr(eh->h_dest) && \ - !compare_ether_addr(eh->h_dest, adapter->netdev->broadcast)) - #define is_arp(skb) (skb->protocol == htons(ETH_P_ARP)) #define is_arp_filt_enabled(adapter) \ -- cgit v1.2.3 From 666db4862f2d373bb054b9fdde3d0ee1e7cd18c5 Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 28 Jan 2019 19:27:54 +0200 Subject: qed: Revise load sequence to avoid PCI errors Initiating final cleanup after an ungraceful driver unload can lead to bad PCI accesses towards the host. This patch revises the load sequence so final cleanup is sent while the internal master enable is cleared, to prevent the host accesses, and clears the internal error indications just before enabling the internal master enable. Signed-off-by: Tomer Tayar Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 1 - drivers/net/ethernet/qlogic/qed/qed_dev.c | 117 ++++++++++++++---------- drivers/net/ethernet/qlogic/qed/qed_dev_api.h | 12 +++ drivers/net/ethernet/qlogic/qed/qed_int.c | 126 +++++++++++++------------- drivers/net/ethernet/qlogic/qed/qed_int.h | 3 + drivers/net/ethernet/qlogic/qed/qed_mcp.c | 21 +++++ drivers/net/ethernet/qlogic/qed/qed_mcp.h | 10 ++ 7 files changed, 178 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 24a90163775e..b352e313e1f6 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -554,7 +554,6 @@ struct qed_hwfn { u8 dp_level; char name[NAME_SIZE]; - bool first_on_engine; bool hw_init_done; u8 num_funcs_on_engine; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 8f6551421945..fa5f07e65672 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -1959,11 +1959,6 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, (p_hwfn->hw_info.personality == QED_PCI_FCOE) ? 1 : 0); STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_ROCE_RT_OFFSET, 0); - /* Cleanup chip from previous driver if such remains exist */ - rc = qed_final_cleanup(p_hwfn, p_ptt, rel_pf_id, false); - if (rc) - return rc; - /* Sanity check before the PF init sequence that uses DMAE */ rc = qed_dmae_sanity(p_hwfn, p_ptt, "pf_phase"); if (rc) @@ -2007,17 +2002,15 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, return rc; } -static int qed_change_pci_hwfn(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt, - u8 enable) +int qed_pglueb_set_pfid_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, bool b_enable) { - u32 delay_idx = 0, val, set_val = enable ? 1 : 0; + u32 delay_idx = 0, val, set_val = b_enable ? 1 : 0; - /* Change PF in PXP */ - qed_wr(p_hwfn, p_ptt, - PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, set_val); + /* Configure the PF's internal FID_enable for master transactions */ + qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, set_val); - /* wait until value is set - try for 1 second every 50us */ + /* Wait until value is set - try for 1 second every 50us */ for (delay_idx = 0; delay_idx < 20000; delay_idx++) { val = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER); @@ -2071,13 +2064,19 @@ static int qed_vf_start(struct qed_hwfn *p_hwfn, return 0; } +static void qed_pglueb_clear_err(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) +{ + qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR, + BIT(p_hwfn->abs_pf_id)); +} + int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) { struct qed_load_req_params load_req_params; u32 load_code, resp, param, drv_mb_param; bool b_default_mtu = true; struct qed_hwfn *p_hwfn; - int rc = 0, mfw_rc, i; + int rc = 0, i; u16 ether_type; if ((p_params->int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { @@ -2092,7 +2091,7 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) } for_each_hwfn(cdev, i) { - struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + p_hwfn = &cdev->hwfns[i]; /* If management didn't provide a default, set one of our own */ if (!p_hwfn->hw_info.mtu) { @@ -2105,9 +2104,6 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) continue; } - /* Enable DMAE in PXP */ - rc = qed_change_pci_hwfn(p_hwfn, p_hwfn->p_main_ptt, true); - rc = qed_calc_hw_mode(p_hwfn); if (rc) return rc; @@ -2148,8 +2144,34 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) qed_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt); - p_hwfn->first_on_engine = (load_code == - FW_MSG_CODE_DRV_LOAD_ENGINE); + /* Clean up chip from previous driver if such remains exist. + * This is not needed when the PF is the first one on the + * engine, since afterwards we are going to init the FW. + */ + if (load_code != FW_MSG_CODE_DRV_LOAD_ENGINE) { + rc = qed_final_cleanup(p_hwfn, p_hwfn->p_main_ptt, + p_hwfn->rel_pf_id, false); + if (rc) { + DP_NOTICE(p_hwfn, "Final cleanup failed\n"); + goto load_err; + } + } + + /* Log and clear previous pglue_b errors if such exist */ + qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt); + + /* Enable the PF's internal FID_enable in the PXP */ + rc = qed_pglueb_set_pfid_enable(p_hwfn, p_hwfn->p_main_ptt, + true); + if (rc) + goto load_err; + + /* Clear the pglue_b was_error indication. + * In E4 it must be done after the BME and the internal + * FID_enable for the PF are set, since VDMs may cause the + * indication to be set again. + */ + qed_pglueb_clear_err(p_hwfn, p_hwfn->p_main_ptt); switch (load_code) { case FW_MSG_CODE_DRV_LOAD_ENGINE: @@ -2180,39 +2202,29 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) break; } - if (rc) + if (rc) { DP_NOTICE(p_hwfn, "init phase failed for loadcode 0x%x (rc %d)\n", - load_code, rc); + load_code, rc); + goto load_err; + } - /* ACK mfw regardless of success or failure of initialization */ - mfw_rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, - DRV_MSG_CODE_LOAD_DONE, - 0, &load_code, ¶m); + rc = qed_mcp_load_done(p_hwfn, p_hwfn->p_main_ptt); if (rc) return rc; - if (mfw_rc) { - DP_NOTICE(p_hwfn, "Failed sending LOAD_DONE command\n"); - return mfw_rc; - } - - /* Check if there is a DID mismatch between nvm-cfg/efuse */ - if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR) - DP_NOTICE(p_hwfn, - "warning: device configuration is not supported on this board type. The device may not function as expected.\n"); /* send DCBX attention request command */ DP_VERBOSE(p_hwfn, QED_MSG_DCB, "sending phony dcbx set command to trigger DCBx attention handling\n"); - mfw_rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, - DRV_MSG_CODE_SET_DCBX, - 1 << DRV_MB_PARAM_DCBX_NOTIFY_SHIFT, - &load_code, ¶m); - if (mfw_rc) { + rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, + DRV_MSG_CODE_SET_DCBX, + 1 << DRV_MB_PARAM_DCBX_NOTIFY_SHIFT, + &resp, ¶m); + if (rc) { DP_NOTICE(p_hwfn, "Failed to send DCBX attention request\n"); - return mfw_rc; + return rc; } p_hwfn->hw_init_done = true; @@ -2261,6 +2273,12 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) } return 0; + +load_err: + /* The MFW load lock should be released also when initialization fails. + */ + qed_mcp_load_done(p_hwfn, p_hwfn->p_main_ptt); + return rc; } #define QED_HW_STOP_RETRY_LIMIT (10) @@ -2395,14 +2413,16 @@ int qed_hw_stop(struct qed_dev *cdev) p_hwfn = QED_LEADING_HWFN(cdev); p_ptt = QED_LEADING_HWFN(cdev)->p_main_ptt; - /* Disable DMAE in PXP - in CMT, this should only be done for - * first hw-function, and only after all transactions have - * stopped for all active hw-functions. + /* Clear the PF's internal FID_enable in the PXP. + * In CMT this should only be done for first hw-function, and + * only after all transactions have stopped for all active + * hw-functions. */ - rc = qed_change_pci_hwfn(p_hwfn, p_ptt, false); + rc = qed_pglueb_set_pfid_enable(p_hwfn, p_ptt, false); if (rc) { DP_NOTICE(p_hwfn, - "qed_change_pci_hwfn failed. rc = %d.\n", rc); + "qed_pglueb_set_pfid_enable() failed. rc = %d.\n", + rc); rc2 = -EINVAL; } } @@ -2502,9 +2522,8 @@ static void qed_hw_hwfn_prepare(struct qed_hwfn *p_hwfn) PGLUE_B_REG_PGL_ADDR_94_F0_BB, 0); } - /* Clean Previous errors if such exist */ - qed_wr(p_hwfn, p_hwfn->p_main_ptt, - PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR, 1 << p_hwfn->abs_pf_id); + /* Clean previous pglue_b errors if such exist */ + qed_pglueb_clear_err(p_hwfn, p_hwfn->p_main_ptt); /* enable internal target-read */ qed_wr(p_hwfn, p_hwfn->p_main_ptt, diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h index acccd85170aa..e4b4e3b78e8a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h +++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h @@ -472,6 +472,18 @@ int qed_get_queue_coalesce(struct qed_hwfn *p_hwfn, u16 *coal, void *handle); int qed_set_queue_coalesce(u16 rx_coal, u16 tx_coal, void *p_handle); +/** + * @brief qed_pglueb_set_pfid_enable - Enable or disable PCI BUS MASTER + * + * @param p_hwfn + * @param p_ptt + * @param b_enable - true/false + * + * @return int + */ +int qed_pglueb_set_pfid_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, bool b_enable); + /** * @brief db_recovery_add - add doorbell information to the doorbell * recovery mechanism. diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index 92340919d852..e23980e301b6 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -255,112 +255,114 @@ out: #define PGLUE_ATTENTION_ICPL_VALID (1 << 23) #define PGLUE_ATTENTION_ZLR_VALID (1 << 25) #define PGLUE_ATTENTION_ILT_VALID (1 << 23) -static int qed_pglub_rbc_attn_cb(struct qed_hwfn *p_hwfn) + +int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) { u32 tmp; - tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, - PGLUE_B_REG_TX_ERR_WR_DETAILS2); + tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS2); if (tmp & PGLUE_ATTENTION_VALID) { u32 addr_lo, addr_hi, details; - addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + addr_lo = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_ADD_31_0); - addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + addr_hi = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_ADD_63_32); - details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + details = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS); - DP_INFO(p_hwfn, - "Illegal write by chip to [%08x:%08x] blocked.\n" - "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" - "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", - addr_hi, addr_lo, details, - (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), - (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), - GET_FIELD(details, - PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, - tmp, - GET_FIELD(tmp, - PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0, - GET_FIELD(tmp, - PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, - GET_FIELD(tmp, - PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0); + DP_NOTICE(p_hwfn, + "Illegal write by chip to [%08x:%08x] blocked.\n" + "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" + "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", + addr_hi, addr_lo, details, + (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), + (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), + GET_FIELD(details, + PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, + tmp, + GET_FIELD(tmp, + PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0, + GET_FIELD(tmp, + PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, + GET_FIELD(tmp, + PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0); } - tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, - PGLUE_B_REG_TX_ERR_RD_DETAILS2); + tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_DETAILS2); if (tmp & PGLUE_ATTENTION_RD_VALID) { u32 addr_lo, addr_hi, details; - addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + addr_lo = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_ADD_31_0); - addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + addr_hi = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_ADD_63_32); - details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + details = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_DETAILS); - DP_INFO(p_hwfn, - "Illegal read by chip from [%08x:%08x] blocked.\n" - " Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" - " Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", - addr_hi, addr_lo, details, - (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), - (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), - GET_FIELD(details, - PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, - tmp, - GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 - : 0, - GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, - GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 - : 0); + DP_NOTICE(p_hwfn, + "Illegal read by chip from [%08x:%08x] blocked.\n" + "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" + "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", + addr_hi, addr_lo, details, + (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), + (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), + GET_FIELD(details, + PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, + tmp, + GET_FIELD(tmp, + PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0, + GET_FIELD(tmp, + PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, + GET_FIELD(tmp, + PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0); } - tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, - PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL); + tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL); if (tmp & PGLUE_ATTENTION_ICPL_VALID) - DP_INFO(p_hwfn, "ICPL error - %08x\n", tmp); + DP_NOTICE(p_hwfn, "ICPL error - %08x\n", tmp); - tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, - PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS); + tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS); if (tmp & PGLUE_ATTENTION_ZLR_VALID) { u32 addr_hi, addr_lo; - addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + addr_lo = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_ZLR_ERR_ADD_31_0); - addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + addr_hi = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_ZLR_ERR_ADD_63_32); - DP_INFO(p_hwfn, "ZLR eror - %08x [Address %08x:%08x]\n", - tmp, addr_hi, addr_lo); + DP_NOTICE(p_hwfn, "ZLR error - %08x [Address %08x:%08x]\n", + tmp, addr_hi, addr_lo); } - tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, - PGLUE_B_REG_VF_ILT_ERR_DETAILS2); + tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_VF_ILT_ERR_DETAILS2); if (tmp & PGLUE_ATTENTION_ILT_VALID) { u32 addr_hi, addr_lo, details; - addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + addr_lo = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_VF_ILT_ERR_ADD_31_0); - addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + addr_hi = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_VF_ILT_ERR_ADD_63_32); - details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + details = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_VF_ILT_ERR_DETAILS); - DP_INFO(p_hwfn, - "ILT error - Details %08x Details2 %08x [Address %08x:%08x]\n", - details, tmp, addr_hi, addr_lo); + DP_NOTICE(p_hwfn, + "ILT error - Details %08x Details2 %08x [Address %08x:%08x]\n", + details, tmp, addr_hi, addr_lo); } /* Clear the indications */ - qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, - PGLUE_B_REG_LATCHED_ERRORS_CLR, (1 << 2)); + qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_LATCHED_ERRORS_CLR, BIT(2)); return 0; } +static int qed_pglueb_rbc_attn_cb(struct qed_hwfn *p_hwfn) +{ + return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt); +} + #define QED_DORQ_ATTENTION_REASON_MASK (0xfffff) #define QED_DORQ_ATTENTION_OPAQUE_MASK (0xffff) #define QED_DORQ_ATTENTION_OPAQUE_SHIFT (0x0) @@ -540,7 +542,7 @@ static struct aeu_invert_reg aeu_descs[NUM_ATTN_REGS] = { {"PGLUE misc_flr", ATTENTION_SINGLE, NULL, MAX_BLOCK_ID}, {"PGLUE B RBC", ATTENTION_PAR_INT, - qed_pglub_rbc_attn_cb, BLOCK_PGLUE_B}, + qed_pglueb_rbc_attn_cb, BLOCK_PGLUE_B}, {"PGLUE misc_mctp", ATTENTION_SINGLE, NULL, MAX_BLOCK_ID}, {"Flash event", ATTENTION_SINGLE, NULL, MAX_BLOCK_ID}, diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h b/drivers/net/ethernet/qlogic/qed/qed_int.h index d81a62ebd524..1f356ed4f761 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.h +++ b/drivers/net/ethernet/qlogic/qed/qed_int.h @@ -431,4 +431,7 @@ int qed_int_set_timer_res(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, #define QED_MAPPING_MEMORY_SIZE(dev) (NUM_OF_SBS(dev)) +int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + #endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index e7f18e34ff0d..1024484d7dd8 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -1070,6 +1070,27 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn, return 0; } +int qed_mcp_load_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) +{ + u32 resp = 0, param = 0; + int rc; + + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_LOAD_DONE, 0, &resp, + ¶m); + if (rc) { + DP_NOTICE(p_hwfn, + "Failed to send a LOAD_DONE command, rc = %d\n", rc); + return rc; + } + + /* Check if there is a DID mismatch between nvm-cfg/efuse */ + if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR) + DP_NOTICE(p_hwfn, + "warning: device configuration is not supported on this board type. The device may not function as expected.\n"); + + return 0; +} + int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { struct qed_mcp_mb_params mb_params; diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index eddf67798d6f..387c5e649136 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -800,6 +800,16 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, struct qed_load_req_params *p_params); +/** + * @brief Sends a LOAD_DONE message to the MFW + * + * @param p_hwfn + * @param p_ptt + * + * @return int - 0 - Operation was successful. + */ +int qed_mcp_load_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); + /** * @brief Sends a UNLOAD_REQ message to the MFW * -- cgit v1.2.3 From 64515dc899df898991b2b7e56f69f56f014ea888 Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 28 Jan 2019 19:27:55 +0200 Subject: qed: Add infrastructure for error detection and recovery This patch adds the detection and handling of a parity error ("process kill event"), including the update of the protocol drivers, and the prevention of any HW access that will lead to device access towards the host while recovery is in progress. It also provides the means for the protocol drivers to trigger a recovery process on their decision. Signed-off-by: Tomer Tayar Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 4 ++ drivers/net/ethernet/qlogic/qed/qed_dev.c | 41 +++++++---- drivers/net/ethernet/qlogic/qed/qed_hsi.h | 2 +- drivers/net/ethernet/qlogic/qed/qed_hw.c | 11 +++ drivers/net/ethernet/qlogic/qed/qed_main.c | 30 ++++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 94 ++++++++++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.h | 32 +++++++++ drivers/net/ethernet/qlogic/qed/qed_reg_addr.h | 2 + drivers/net/ethernet/qlogic/qed/qed_spq.c | 22 ++++++ drivers/net/ethernet/qlogic/qed/qed_sriov.c | 9 ++- include/linux/qed/qed_if.h | 20 ++++++ 11 files changed, 251 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index b352e313e1f6..3b0955d34716 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -804,6 +804,9 @@ struct qed_dev { u32 mcp_nvm_resp; + /* Recovery */ + bool recov_in_prog; + /* Linux specific here */ struct qede_dev *edev; struct pci_dev *pdev; @@ -943,6 +946,7 @@ void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt); u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len, u8 *input_buf, u32 max_size, u8 *unzip_buf); +void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn); void qed_get_protocol_stats(struct qed_dev *cdev, enum qed_mcp_protocol_type type, union qed_mcp_protocol_stats *stats); diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index fa5f07e65672..b17003d9066c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -2140,6 +2140,11 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) "Load request was sent. Load code: 0x%x\n", load_code); + /* Only relevant for recovery: + * Clear the indication after LOAD_REQ is responded by the MFW. + */ + cdev->recov_in_prog = false; + qed_mcp_set_capabilities(p_hwfn, p_hwfn->p_main_ptt); qed_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt); @@ -2291,6 +2296,9 @@ static void qed_hw_timers_stop(struct qed_dev *cdev, qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0); qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0); + if (cdev->recov_in_prog) + return; + for (i = 0; i < QED_HW_STOP_RETRY_LIMIT; i++) { if ((!qed_rd(p_hwfn, p_ptt, TM_REG_PF_SCAN_ACTIVE_CONN)) && @@ -2353,12 +2361,14 @@ int qed_hw_stop(struct qed_dev *cdev) p_hwfn->hw_init_done = false; /* Send unload command to MCP */ - rc = qed_mcp_unload_req(p_hwfn, p_ptt); - if (rc) { - DP_NOTICE(p_hwfn, - "Failed sending a UNLOAD_REQ command. rc = %d.\n", - rc); - rc2 = -EINVAL; + if (!cdev->recov_in_prog) { + rc = qed_mcp_unload_req(p_hwfn, p_ptt); + if (rc) { + DP_NOTICE(p_hwfn, + "Failed sending a UNLOAD_REQ command. rc = %d.\n", + rc); + rc2 = -EINVAL; + } } qed_slowpath_irq_sync(p_hwfn); @@ -2400,16 +2410,18 @@ int qed_hw_stop(struct qed_dev *cdev) qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_DB_ENABLE, 0); qed_wr(p_hwfn, p_ptt, QM_REG_PF_EN, 0); - qed_mcp_unload_done(p_hwfn, p_ptt); - if (rc) { - DP_NOTICE(p_hwfn, - "Failed sending a UNLOAD_DONE command. rc = %d.\n", - rc); - rc2 = -EINVAL; + if (!cdev->recov_in_prog) { + rc = qed_mcp_unload_done(p_hwfn, p_ptt); + if (rc) { + DP_NOTICE(p_hwfn, + "Failed sending a UNLOAD_DONE command. rc = %d.\n", + rc); + rc2 = -EINVAL; + } } } - if (IS_PF(cdev)) { + if (IS_PF(cdev) && !cdev->recov_in_prog) { p_hwfn = QED_LEADING_HWFN(cdev); p_ptt = QED_LEADING_HWFN(cdev)->p_main_ptt; @@ -3459,6 +3471,7 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn, void __iomem *p_doorbells, enum qed_pci_personality personality) { + struct qed_dev *cdev = p_hwfn->cdev; int rc = 0; /* Split PCI bars evenly between hwfns */ @@ -3511,7 +3524,7 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn, /* Sending a mailbox to the MFW should be done after qed_get_hw_info() * is called as it sets the ports number in an engine. */ - if (IS_LEAD_HWFN(p_hwfn)) { + if (IS_LEAD_HWFN(p_hwfn) && !cdev->recov_in_prog) { rc = qed_mcp_initiate_pf_flr(p_hwfn, p_hwfn->p_main_ptt); if (rc) DP_NOTICE(p_hwfn, "Failed to initiate PF FLR\n"); diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index b13cfb449d8f..417121e74ee9 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -12827,7 +12827,7 @@ enum MFW_DRV_MSG_TYPE { MFW_DRV_MSG_LLDP_DATA_UPDATED, MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED, MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED, - MFW_DRV_MSG_RESERVED4, + MFW_DRV_MSG_ERROR_RECOVERY, MFW_DRV_MSG_BW_UPDATE, MFW_DRV_MSG_S_TAG_UPDATE, MFW_DRV_MSG_GET_LAN_STATS, diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.c b/drivers/net/ethernet/qlogic/qed/qed_hw.c index 70504dcf4087..72ec1c6bdf70 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hw.c +++ b/drivers/net/ethernet/qlogic/qed/qed_hw.c @@ -703,6 +703,17 @@ static int qed_dmae_execute_command(struct qed_hwfn *p_hwfn, int qed_status = 0; u32 offset = 0; + if (p_hwfn->cdev->recov_in_prog) { + DP_VERBOSE(p_hwfn, + NETIF_MSG_HW, + "Recovery is in progress. Avoid DMAE transaction [{src: addr 0x%llx, type %d}, {dst: addr 0x%llx, type %d}, size %d].\n", + src_addr, src_type, dst_addr, dst_type, + size_in_dwords); + + /* Let the flow complete w/o any error handling */ + return 0; + } + qed_dmae_opcode(p_hwfn, (src_type == QED_DMAE_ADDRESS_GRC), (dst_type == QED_DMAE_ADDRESS_GRC), diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 6adf5bda9811..b47352643fb5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -359,6 +359,8 @@ static struct qed_dev *qed_probe(struct pci_dev *pdev, qed_init_dp(cdev, params->dp_module, params->dp_level); + cdev->recov_in_prog = params->recov_in_prog; + rc = qed_init_pci(cdev, pdev); if (rc) { DP_ERR(cdev, "init pci failed\n"); @@ -2203,6 +2205,15 @@ static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type, return qed_mcp_get_nvm_image(hwfn, type, buf, len); } +void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn) +{ + struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common; + void *cookie = p_hwfn->cdev->ops_cookie; + + if (ops && ops->schedule_recovery_handler) + ops->schedule_recovery_handler(cookie); +} + static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal, void *handle) { @@ -2226,6 +2237,23 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) return status; } +static int qed_recovery_process(struct qed_dev *cdev) +{ + struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); + struct qed_ptt *p_ptt; + int rc = 0; + + p_ptt = qed_ptt_acquire(p_hwfn); + if (!p_ptt) + return -EAGAIN; + + rc = qed_start_recovery_process(p_hwfn, p_ptt); + + qed_ptt_release(p_hwfn, p_ptt); + + return rc; +} + static int qed_update_wol(struct qed_dev *cdev, bool enabled) { struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); @@ -2380,6 +2408,8 @@ const struct qed_common_ops qed_common_ops_pass = { .nvm_get_image = &qed_nvm_get_image, .set_coalesce = &qed_set_coalesce, .set_led = &qed_set_led, + .recovery_process = &qed_recovery_process, + .recovery_prolog = &qed_recovery_prolog, .update_drv_state = &qed_update_drv_state, .update_mac = &qed_update_mac, .update_mtu = &qed_update_mtu, diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 1024484d7dd8..bb8541847aa5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -1549,6 +1549,60 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up) return 0; } +u32 qed_get_process_kill_counter(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 path_offsize_addr, path_offsize, path_addr, proc_kill_cnt; + + if (IS_VF(p_hwfn->cdev)) + return -EINVAL; + + path_offsize_addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, + PUBLIC_PATH); + path_offsize = qed_rd(p_hwfn, p_ptt, path_offsize_addr); + path_addr = SECTION_ADDR(path_offsize, QED_PATH_ID(p_hwfn)); + + proc_kill_cnt = qed_rd(p_hwfn, p_ptt, + path_addr + + offsetof(struct public_path, process_kill)) & + PROCESS_KILL_COUNTER_MASK; + + return proc_kill_cnt; +} + +static void qed_mcp_handle_process_kill(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_dev *cdev = p_hwfn->cdev; + u32 proc_kill_cnt; + + /* Prevent possible attentions/interrupts during the recovery handling + * and till its load phase, during which they will be re-enabled. + */ + qed_int_igu_disable_int(p_hwfn, p_ptt); + + DP_NOTICE(p_hwfn, "Received a process kill indication\n"); + + /* The following operations should be done once, and thus in CMT mode + * are carried out by only the first HW function. + */ + if (p_hwfn != QED_LEADING_HWFN(cdev)) + return; + + if (cdev->recov_in_prog) { + DP_NOTICE(p_hwfn, + "Ignoring the indication since a recovery process is already in progress\n"); + return; + } + + cdev->recov_in_prog = true; + + proc_kill_cnt = qed_get_process_kill_counter(p_hwfn, p_ptt); + DP_NOTICE(p_hwfn, "Process kill counter: %d\n", proc_kill_cnt); + + qed_schedule_recovery_handler(p_hwfn); +} + static void qed_mcp_send_protocol_stats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, enum MFW_DRV_MSG_TYPE type) @@ -1779,6 +1833,9 @@ int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE: qed_mcp_handle_transceiver_change(p_hwfn, p_ptt); break; + case MFW_DRV_MSG_ERROR_RECOVERY: + qed_mcp_handle_process_kill(p_hwfn, p_ptt); + break; case MFW_DRV_MSG_GET_LAN_STATS: case MFW_DRV_MSG_GET_FCOE_STATS: case MFW_DRV_MSG_GET_ISCSI_STATS: @@ -2324,6 +2381,43 @@ int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn, return 0; } +int qed_start_recovery_process(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) +{ + struct qed_dev *cdev = p_hwfn->cdev; + + if (cdev->recov_in_prog) { + DP_NOTICE(p_hwfn, + "Avoid triggering a recovery since such a process is already in progress\n"); + return -EAGAIN; + } + + DP_NOTICE(p_hwfn, "Triggering a recovery process\n"); + qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_GENERAL_ATTN_35, 0x1); + + return 0; +} + +#define QED_RECOVERY_PROLOG_SLEEP_MS 100 + +int qed_recovery_prolog(struct qed_dev *cdev) +{ + struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); + struct qed_ptt *p_ptt = p_hwfn->p_main_ptt; + int rc; + + /* Allow ongoing PCIe transactions to complete */ + msleep(QED_RECOVERY_PROLOG_SLEEP_MS); + + /* Clear the PF's internal FID_enable in the PXP */ + rc = qed_pglueb_set_pfid_enable(p_hwfn, p_ptt, false); + if (rc) + DP_NOTICE(p_hwfn, + "qed_pglueb_set_pfid_enable() failed. rc = %d.\n", + rc); + + return rc; +} + static int qed_mcp_config_vf_msix_bb(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, u8 vf_id, u8 num) diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 387c5e649136..6e1d72a669ae 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -440,6 +440,38 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, struct qed_mcp_drv_version *p_ver); +/** + * @brief Read the MFW process kill counter + * + * @param p_hwfn + * @param p_ptt + * + * @return u32 + */ +u32 qed_get_process_kill_counter(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief Trigger a recovery process + * + * @param p_hwfn + * @param p_ptt + * + * @return int + */ +int qed_start_recovery_process(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); + +/** + * @brief A recovery handler must call this function as its first step. + * It is assumed that the handler is not run from an interrupt context. + * + * @param cdev + * @param p_ptt + * + * @return int + */ +int qed_recovery_prolog(struct qed_dev *cdev); + /** * @brief Notify MFW about the change in base device properties * diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index 8939ed6e08b7..5ce825ca5f24 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -518,6 +518,8 @@ 0x180824UL #define MISC_REG_AEU_GENERAL_ATTN_0 \ 0x008400UL +#define MISC_REG_AEU_GENERAL_ATTN_35 \ + 0x00848cUL #define CAU_REG_SB_ADDR_MEMORY \ 0x1c8000UL #define CAU_REG_SB_VAR_MEMORY \ diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index eb88bbc6b193..3e0f7c46bb1b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -790,6 +790,17 @@ static int qed_spq_pend_post(struct qed_hwfn *p_hwfn) SPQ_HIGH_PRI_RESERVE_DEFAULT); } +static void qed_spq_recov_set_ret_code(struct qed_spq_entry *p_ent, + u8 *fw_return_code) +{ + if (!fw_return_code) + return; + + if (p_ent->elem.hdr.protocol_id == PROTOCOLID_ROCE || + p_ent->elem.hdr.protocol_id == PROTOCOLID_IWARP) + *fw_return_code = RDMA_RETURN_OK; +} + /* Avoid overriding of SPQ entries when getting out-of-order completions, by * marking the completions in a bitmap and increasing the chain consumer only * for the first successive completed entries. @@ -825,6 +836,17 @@ int qed_spq_post(struct qed_hwfn *p_hwfn, return -EINVAL; } + if (p_hwfn->cdev->recov_in_prog) { + DP_VERBOSE(p_hwfn, + QED_MSG_SPQ, + "Recovery is in progress. Skip spq post [cmd %02x protocol %02x]\n", + p_ent->elem.hdr.cmd_id, p_ent->elem.hdr.protocol_id); + + /* Let the flow complete w/o any error handling */ + qed_spq_recov_set_ret_code(p_ent, fw_return_code); + return 0; + } + /* Complete the entry */ rc = qed_spq_fill_entry(p_hwfn, p_ent); diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index ca6290fa0f30..71e28be58102 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -4447,6 +4447,13 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled) if (cdev->p_iov_info && cdev->p_iov_info->num_vfs && pci_enabled) pci_disable_sriov(cdev->pdev); + if (cdev->recov_in_prog) { + DP_VERBOSE(cdev, + QED_MSG_IOV, + "Skip SRIOV disable operations in the device since a recovery is in progress\n"); + goto out; + } + for_each_hwfn(cdev, i) { struct qed_hwfn *hwfn = &cdev->hwfns[i]; struct qed_ptt *ptt = qed_ptt_acquire(hwfn); @@ -4486,7 +4493,7 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled) qed_ptt_release(hwfn, ptt); } - +out: qed_iov_set_vfs_to_disable(cdev, false); return 0; diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 5f818fda96bd..35170f74ed80 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -763,6 +763,7 @@ struct qed_probe_params { u32 dp_module; u8 dp_level; bool is_vf; + bool recov_in_prog; }; #define QED_DRV_VER_STR_SIZE 12 @@ -809,6 +810,7 @@ struct qed_common_cb_ops { void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc); void (*link_update)(void *dev, struct qed_link_output *link); + void (*schedule_recovery_handler)(void *dev); void (*dcbx_aen)(void *dev, struct qed_dcbx_get *get, u32 mib_type); void (*get_generic_tlv_data)(void *dev, struct qed_generic_tlvs *data); void (*get_protocol_tlv_data)(void *dev, void *data); @@ -1056,6 +1058,24 @@ struct qed_common_ops { int (*db_recovery_del)(struct qed_dev *cdev, void __iomem *db_addr, void *db_data); +/** + * @brief recovery_process - Trigger a recovery process + * + * @param cdev + * + * @return 0 on success, error otherwise. + */ + int (*recovery_process)(struct qed_dev *cdev); + +/** + * @brief recovery_prolog - Execute the prolog operations of a recovery process + * + * @param cdev + * + * @return 0 on success, error otherwise. + */ + int (*recovery_prolog)(struct qed_dev *cdev); + /** * @brief update_drv_state - API to inform the change in the driver state. * -- cgit v1.2.3 From ccc67ef50b9085b895738d7720840eb6fe98745e Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 28 Jan 2019 19:27:56 +0200 Subject: qede: Error recovery process This patch adds the error recovery process in the qede driver. The process includes a partial/customized driver unload and load, which allows it to look like a short suspend period to the kernel while preserving the net devices' state. Signed-off-by: Tomer Tayar Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede.h | 3 + drivers/net/ethernet/qlogic/qede/qede_main.c | 292 ++++++++++++++++++++++----- drivers/net/ethernet/qlogic/qede/qede_rdma.c | 63 ++++-- include/linux/qed/qede_rdma.h | 10 +- 4 files changed, 294 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 613249d1e967..843416404aeb 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -162,6 +162,7 @@ struct qede_rdma_dev { struct list_head entry; struct list_head rdma_event_list; struct workqueue_struct *rdma_wq; + bool exp_recovery; }; struct qede_ptp; @@ -264,6 +265,7 @@ struct qede_dev { enum QEDE_STATE { QEDE_STATE_CLOSED, QEDE_STATE_OPEN, + QEDE_STATE_RECOVERY, }; #define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo)) @@ -462,6 +464,7 @@ struct qede_fastpath { #define QEDE_CSUM_UNNECESSARY BIT(1) #define QEDE_TUNN_CSUM_UNNECESSARY BIT(2) +#define QEDE_SP_RECOVERY 0 #define QEDE_SP_RX_MODE 1 #ifdef CONFIG_RFS_ACCEL diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 5a74fcbdbc2b..6b4d96635238 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -133,23 +133,12 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id); static void qede_remove(struct pci_dev *pdev); static void qede_shutdown(struct pci_dev *pdev); static void qede_link_update(void *dev, struct qed_link_output *link); +static void qede_schedule_recovery_handler(void *dev); +static void qede_recovery_handler(struct qede_dev *edev); static void qede_get_eth_tlv_data(void *edev, void *data); static void qede_get_generic_tlv_data(void *edev, struct qed_generic_tlvs *data); -/* The qede lock is used to protect driver state change and driver flows that - * are not reentrant. - */ -void __qede_lock(struct qede_dev *edev) -{ - mutex_lock(&edev->qede_lock); -} - -void __qede_unlock(struct qede_dev *edev) -{ - mutex_unlock(&edev->qede_lock); -} - #ifdef CONFIG_QED_SRIOV static int qede_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, u8 qos, __be16 vlan_proto) @@ -231,6 +220,7 @@ static struct qed_eth_cb_ops qede_ll_ops = { .arfs_filter_op = qede_arfs_filter_op, #endif .link_update = qede_link_update, + .schedule_recovery_handler = qede_schedule_recovery_handler, .get_generic_tlv_data = qede_get_generic_tlv_data, .get_protocol_tlv_data = qede_get_eth_tlv_data, }, @@ -950,11 +940,57 @@ err: return -ENOMEM; } +/* The qede lock is used to protect driver state change and driver flows that + * are not reentrant. + */ +void __qede_lock(struct qede_dev *edev) +{ + mutex_lock(&edev->qede_lock); +} + +void __qede_unlock(struct qede_dev *edev) +{ + mutex_unlock(&edev->qede_lock); +} + +/* This version of the lock should be used when acquiring the RTNL lock is also + * needed in addition to the internal qede lock. + */ +void qede_lock(struct qede_dev *edev) +{ + rtnl_lock(); + __qede_lock(edev); +} + +void qede_unlock(struct qede_dev *edev) +{ + __qede_unlock(edev); + rtnl_unlock(); +} + static void qede_sp_task(struct work_struct *work) { struct qede_dev *edev = container_of(work, struct qede_dev, sp_task.work); + /* The locking scheme depends on the specific flag: + * In case of QEDE_SP_RECOVERY, acquiring the RTNL lock is required to + * ensure that ongoing flows are ended and new ones are not started. + * In other cases - only the internal qede lock should be acquired. + */ + + if (test_and_clear_bit(QEDE_SP_RECOVERY, &edev->sp_flags)) { +#ifdef CONFIG_QED_SRIOV + /* SRIOV must be disabled outside the lock to avoid a deadlock. + * The recovery of the active VFs is currently not supported. + */ + qede_sriov_configure(edev->pdev, 0); +#endif + qede_lock(edev); + qede_recovery_handler(edev); + qede_unlock(edev); + } + __qede_lock(edev); if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags)) @@ -1031,6 +1067,7 @@ static void qede_log_probe(struct qede_dev *edev) enum qede_probe_mode { QEDE_PROBE_NORMAL, + QEDE_PROBE_RECOVERY, }; static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, @@ -1051,6 +1088,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, probe_params.dp_module = dp_module; probe_params.dp_level = dp_level; probe_params.is_vf = is_vf; + probe_params.recov_in_prog = (mode == QEDE_PROBE_RECOVERY); cdev = qed_ops->common->probe(pdev, &probe_params); if (!cdev) { rc = -ENODEV; @@ -1078,11 +1116,20 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, if (rc) goto err2; - edev = qede_alloc_etherdev(cdev, pdev, &dev_info, dp_module, - dp_level); - if (!edev) { - rc = -ENOMEM; - goto err2; + if (mode != QEDE_PROBE_RECOVERY) { + edev = qede_alloc_etherdev(cdev, pdev, &dev_info, dp_module, + dp_level); + if (!edev) { + rc = -ENOMEM; + goto err2; + } + } else { + struct net_device *ndev = pci_get_drvdata(pdev); + + edev = netdev_priv(ndev); + edev->cdev = cdev; + memset(&edev->stats, 0, sizeof(edev->stats)); + memcpy(&edev->dev_info, &dev_info, sizeof(dev_info)); } if (is_vf) @@ -1090,28 +1137,31 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, qede_init_ndev(edev); - rc = qede_rdma_dev_add(edev); + rc = qede_rdma_dev_add(edev, (mode == QEDE_PROBE_RECOVERY)); if (rc) goto err3; - /* Prepare the lock prior to the registration of the netdev, - * as once it's registered we might reach flows requiring it - * [it's even possible to reach a flow needing it directly - * from there, although it's unlikely]. - */ - INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task); - mutex_init(&edev->qede_lock); - rc = register_netdev(edev->ndev); - if (rc) { - DP_NOTICE(edev, "Cannot register net-device\n"); - goto err4; + if (mode != QEDE_PROBE_RECOVERY) { + /* Prepare the lock prior to the registration of the netdev, + * as once it's registered we might reach flows requiring it + * [it's even possible to reach a flow needing it directly + * from there, although it's unlikely]. + */ + INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task); + mutex_init(&edev->qede_lock); + + rc = register_netdev(edev->ndev); + if (rc) { + DP_NOTICE(edev, "Cannot register net-device\n"); + goto err4; + } } edev->ops->common->set_name(cdev, edev->ndev->name); /* PTP not supported on VFs */ if (!is_vf) - qede_ptp_enable(edev, true); + qede_ptp_enable(edev, (mode == QEDE_PROBE_NORMAL)); edev->ops->register_ops(cdev, &qede_ll_ops, edev); @@ -1126,7 +1176,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, return 0; err4: - qede_rdma_dev_remove(edev); + qede_rdma_dev_remove(edev, (mode == QEDE_PROBE_RECOVERY)); err3: free_netdev(edev->ndev); err2: @@ -1162,6 +1212,7 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id) enum qede_remove_mode { QEDE_REMOVE_NORMAL, + QEDE_REMOVE_RECOVERY, }; static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) @@ -1172,15 +1223,19 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) DP_INFO(edev, "Starting qede_remove\n"); - qede_rdma_dev_remove(edev); - unregister_netdev(ndev); - cancel_delayed_work_sync(&edev->sp_task); + qede_rdma_dev_remove(edev, (mode == QEDE_REMOVE_RECOVERY)); - qede_ptp_disable(edev); + if (mode != QEDE_REMOVE_RECOVERY) { + unregister_netdev(ndev); - edev->ops->common->set_power_state(cdev, PCI_D0); + cancel_delayed_work_sync(&edev->sp_task); - pci_set_drvdata(pdev, NULL); + edev->ops->common->set_power_state(cdev, PCI_D0); + + pci_set_drvdata(pdev, NULL); + } + + qede_ptp_disable(edev); /* Use global ops since we've freed edev */ qed_ops->common->slowpath_stop(cdev); @@ -1194,7 +1249,8 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) * [e.g., QED register callbacks] won't break anything when * accessing the netdevice. */ - free_netdev(ndev); + if (mode != QEDE_REMOVE_RECOVERY) + free_netdev(ndev); dev_info(&pdev->dev, "Ending qede_remove successfully\n"); } @@ -1539,6 +1595,58 @@ static int qede_alloc_mem_load(struct qede_dev *edev) return 0; } +static void qede_empty_tx_queue(struct qede_dev *edev, + struct qede_tx_queue *txq) +{ + unsigned int pkts_compl = 0, bytes_compl = 0; + struct netdev_queue *netdev_txq; + int rc, len = 0; + + netdev_txq = netdev_get_tx_queue(edev->ndev, txq->ndev_txq_id); + + while (qed_chain_get_cons_idx(&txq->tx_pbl) != + qed_chain_get_prod_idx(&txq->tx_pbl)) { + DP_VERBOSE(edev, NETIF_MSG_IFDOWN, + "Freeing a packet on tx queue[%d]: chain_cons 0x%x, chain_prod 0x%x\n", + txq->index, qed_chain_get_cons_idx(&txq->tx_pbl), + qed_chain_get_prod_idx(&txq->tx_pbl)); + + rc = qede_free_tx_pkt(edev, txq, &len); + if (rc) { + DP_NOTICE(edev, + "Failed to free a packet on tx queue[%d]: chain_cons 0x%x, chain_prod 0x%x\n", + txq->index, + qed_chain_get_cons_idx(&txq->tx_pbl), + qed_chain_get_prod_idx(&txq->tx_pbl)); + break; + } + + bytes_compl += len; + pkts_compl++; + txq->sw_tx_cons++; + } + + netdev_tx_completed_queue(netdev_txq, pkts_compl, bytes_compl); +} + +static void qede_empty_tx_queues(struct qede_dev *edev) +{ + int i; + + for_each_queue(i) + if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { + int cos; + + for_each_cos_in_txq(edev, cos) { + struct qede_fastpath *fp; + + fp = &edev->fp_array[i]; + qede_empty_tx_queue(edev, + &fp->txq[cos]); + } + } +} + /* This function inits fp content and resets the SB, RXQ and TXQ structures */ static void qede_init_fp(struct qede_dev *edev) { @@ -2053,6 +2161,7 @@ out: enum qede_unload_mode { QEDE_UNLOAD_NORMAL, + QEDE_UNLOAD_RECOVERY, }; static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, @@ -2068,7 +2177,8 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, clear_bit(QEDE_FLAGS_LINK_REQUESTED, &edev->flags); - edev->state = QEDE_STATE_CLOSED; + if (mode != QEDE_UNLOAD_RECOVERY) + edev->state = QEDE_STATE_CLOSED; qede_rdma_dev_event_close(edev); @@ -2076,17 +2186,20 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, netif_tx_disable(edev->ndev); netif_carrier_off(edev->ndev); - /* Reset the link */ - memset(&link_params, 0, sizeof(link_params)); - link_params.link_up = false; - edev->ops->common->set_link(edev->cdev, &link_params); - rc = qede_stop_queues(edev); - if (rc) { - qede_sync_free_irqs(edev); - goto out; - } + if (mode != QEDE_UNLOAD_RECOVERY) { + /* Reset the link */ + memset(&link_params, 0, sizeof(link_params)); + link_params.link_up = false; + edev->ops->common->set_link(edev->cdev, &link_params); - DP_INFO(edev, "Stopped Queues\n"); + rc = qede_stop_queues(edev); + if (rc) { + qede_sync_free_irqs(edev); + goto out; + } + + DP_INFO(edev, "Stopped Queues\n"); + } qede_vlan_mark_nonconfigured(edev); edev->ops->fastpath_stop(edev->cdev); @@ -2102,18 +2215,26 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, qede_napi_disable_remove(edev); + if (mode == QEDE_UNLOAD_RECOVERY) + qede_empty_tx_queues(edev); + qede_free_mem_load(edev); qede_free_fp_array(edev); out: if (!is_locked) __qede_unlock(edev); + + if (mode != QEDE_UNLOAD_RECOVERY) + DP_NOTICE(edev, "Link is down\n"); + DP_INFO(edev, "Ending qede unload\n"); } enum qede_load_mode { QEDE_LOAD_NORMAL, QEDE_LOAD_RELOAD, + QEDE_LOAD_RECOVERY, }; static int qede_load(struct qede_dev *edev, enum qede_load_mode mode, @@ -2293,6 +2414,77 @@ static void qede_link_update(void *dev, struct qed_link_output *link) } } +static void qede_schedule_recovery_handler(void *dev) +{ + struct qede_dev *edev = dev; + + if (edev->state == QEDE_STATE_RECOVERY) { + DP_NOTICE(edev, + "Avoid scheduling a recovery handling since already in recovery state\n"); + return; + } + + set_bit(QEDE_SP_RECOVERY, &edev->sp_flags); + schedule_delayed_work(&edev->sp_task, 0); + + DP_INFO(edev, "Scheduled a recovery handler\n"); +} + +static void qede_recovery_failed(struct qede_dev *edev) +{ + netdev_err(edev->ndev, "Recovery handling has failed. Power cycle is needed.\n"); + + netif_device_detach(edev->ndev); + + if (edev->cdev) + edev->ops->common->set_power_state(edev->cdev, PCI_D3hot); +} + +static void qede_recovery_handler(struct qede_dev *edev) +{ + u32 curr_state = edev->state; + int rc; + + DP_NOTICE(edev, "Starting a recovery process\n"); + + /* No need to acquire first the qede_lock since is done by qede_sp_task + * before calling this function. + */ + edev->state = QEDE_STATE_RECOVERY; + + edev->ops->common->recovery_prolog(edev->cdev); + + if (curr_state == QEDE_STATE_OPEN) + qede_unload(edev, QEDE_UNLOAD_RECOVERY, true); + + __qede_remove(edev->pdev, QEDE_REMOVE_RECOVERY); + + rc = __qede_probe(edev->pdev, edev->dp_module, edev->dp_level, + IS_VF(edev), QEDE_PROBE_RECOVERY); + if (rc) { + edev->cdev = NULL; + goto err; + } + + if (curr_state == QEDE_STATE_OPEN) { + rc = qede_load(edev, QEDE_LOAD_RECOVERY, true); + if (rc) + goto err; + + qede_config_rx_mode(edev->ndev); + udp_tunnel_get_rx_info(edev->ndev); + } + + edev->state = curr_state; + + DP_NOTICE(edev, "Recovery handling is done\n"); + + return; + +err: + qede_recovery_failed(edev); +} + static bool qede_is_txq_full(struct qede_dev *edev, struct qede_tx_queue *txq) { struct netdev_queue *netdev_txq; diff --git a/drivers/net/ethernet/qlogic/qede/qede_rdma.c b/drivers/net/ethernet/qlogic/qede/qede_rdma.c index 1900bf7e67d1..ffabc2d2f082 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_rdma.c +++ b/drivers/net/ethernet/qlogic/qede/qede_rdma.c @@ -50,6 +50,8 @@ static void _qede_rdma_dev_add(struct qede_dev *edev) if (!qedr_drv) return; + /* Leftovers from previous error recovery */ + edev->rdma_info.exp_recovery = false; edev->rdma_info.qedr_dev = qedr_drv->add(edev->cdev, edev->pdev, edev->ndev); } @@ -87,21 +89,26 @@ static void qede_rdma_destroy_wq(struct qede_dev *edev) destroy_workqueue(edev->rdma_info.rdma_wq); } -int qede_rdma_dev_add(struct qede_dev *edev) +int qede_rdma_dev_add(struct qede_dev *edev, bool recovery) { - int rc = 0; + int rc; - if (qede_rdma_supported(edev)) { - rc = qede_rdma_create_wq(edev); - if (rc) - return rc; + if (!qede_rdma_supported(edev)) + return 0; - INIT_LIST_HEAD(&edev->rdma_info.entry); - mutex_lock(&qedr_dev_list_lock); - list_add_tail(&edev->rdma_info.entry, &qedr_dev_list); - _qede_rdma_dev_add(edev); - mutex_unlock(&qedr_dev_list_lock); - } + /* Cannot start qedr while recovering since it wasn't fully stopped */ + if (recovery) + return 0; + + rc = qede_rdma_create_wq(edev); + if (rc) + return rc; + + INIT_LIST_HEAD(&edev->rdma_info.entry); + mutex_lock(&qedr_dev_list_lock); + list_add_tail(&edev->rdma_info.entry, &qedr_dev_list); + _qede_rdma_dev_add(edev); + mutex_unlock(&qedr_dev_list_lock); return rc; } @@ -110,19 +117,30 @@ static void _qede_rdma_dev_remove(struct qede_dev *edev) { if (qedr_drv && qedr_drv->remove && edev->rdma_info.qedr_dev) qedr_drv->remove(edev->rdma_info.qedr_dev); - edev->rdma_info.qedr_dev = NULL; } -void qede_rdma_dev_remove(struct qede_dev *edev) +void qede_rdma_dev_remove(struct qede_dev *edev, bool recovery) { if (!qede_rdma_supported(edev)) return; - qede_rdma_destroy_wq(edev); - mutex_lock(&qedr_dev_list_lock); - _qede_rdma_dev_remove(edev); - list_del(&edev->rdma_info.entry); - mutex_unlock(&qedr_dev_list_lock); + /* Cannot remove qedr while recovering since it wasn't fully stopped */ + if (!recovery) { + qede_rdma_destroy_wq(edev); + mutex_lock(&qedr_dev_list_lock); + if (!edev->rdma_info.exp_recovery) + _qede_rdma_dev_remove(edev); + edev->rdma_info.qedr_dev = NULL; + list_del(&edev->rdma_info.entry); + mutex_unlock(&qedr_dev_list_lock); + } else { + if (!edev->rdma_info.exp_recovery) { + mutex_lock(&qedr_dev_list_lock); + _qede_rdma_dev_remove(edev); + mutex_unlock(&qedr_dev_list_lock); + } + edev->rdma_info.exp_recovery = true; + } } static void _qede_rdma_dev_open(struct qede_dev *edev) @@ -204,7 +222,8 @@ void qede_rdma_unregister_driver(struct qedr_driver *drv) mutex_lock(&qedr_dev_list_lock); list_for_each_entry(edev, &qedr_dev_list, rdma_info.entry) { - if (edev->rdma_info.qedr_dev) + /* If device has experienced recovery it was already removed */ + if (edev->rdma_info.qedr_dev && !edev->rdma_info.exp_recovery) _qede_rdma_dev_remove(edev); } qedr_drv = NULL; @@ -284,6 +303,10 @@ static void qede_rdma_add_event(struct qede_dev *edev, { struct qede_rdma_event_work *event_node; + /* If a recovery was experienced avoid adding the event */ + if (edev->rdma_info.exp_recovery) + return; + if (!edev->rdma_info.qedr_dev) return; diff --git a/include/linux/qed/qede_rdma.h b/include/linux/qed/qede_rdma.h index 9904617a9730..5a00c7a473bf 100644 --- a/include/linux/qed/qede_rdma.h +++ b/include/linux/qed/qede_rdma.h @@ -74,21 +74,23 @@ void qede_rdma_unregister_driver(struct qedr_driver *drv); bool qede_rdma_supported(struct qede_dev *dev); #if IS_ENABLED(CONFIG_QED_RDMA) -int qede_rdma_dev_add(struct qede_dev *dev); +int qede_rdma_dev_add(struct qede_dev *dev, bool recovery); void qede_rdma_dev_event_open(struct qede_dev *dev); void qede_rdma_dev_event_close(struct qede_dev *dev); -void qede_rdma_dev_remove(struct qede_dev *dev); +void qede_rdma_dev_remove(struct qede_dev *dev, bool recovery); void qede_rdma_event_changeaddr(struct qede_dev *edr); #else -static inline int qede_rdma_dev_add(struct qede_dev *dev) +static inline int qede_rdma_dev_add(struct qede_dev *dev, + bool recovery) { return 0; } static inline void qede_rdma_dev_event_open(struct qede_dev *dev) {} static inline void qede_rdma_dev_event_close(struct qede_dev *dev) {} -static inline void qede_rdma_dev_remove(struct qede_dev *dev) {} +static inline void qede_rdma_dev_remove(struct qede_dev *dev, + bool recovery) {} static inline void qede_rdma_event_changeaddr(struct qede_dev *edr) {} #endif #endif -- cgit v1.2.3 From bbcbf2eede69c5f54a431fb96c11248a7910748c Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 29 Jan 2019 16:13:08 +1100 Subject: enetc: include linux/vmalloc.h for vzalloc etc Fixes: d4fd0404c1c9 ("enetc: Introduce basic PF and VF ENETC ethernet drivers") Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/enetc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 37b587c541ee..5bb9eb35d76d 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -5,6 +5,7 @@ #include #include #include +#include /* ENETC overhead: optional extension BD + 1 BD gap */ #define ENETC_TXBDS_NEEDED(val) ((val) + 2) -- cgit v1.2.3 From ac93e2fa85502fa7ad540f656e70b2516af56d7b Mon Sep 17 00:00:00 2001 From: Veerasenareddy Burru Date: Mon, 28 Jan 2019 19:38:31 +0000 Subject: liquidio: fix the validation of rx checksum status from NIC hardware Fixed the code that was incorrectly interpreting the rx checksum validation status from hardware, and updating kernel that the packet arrived with correct checksum though the packet arrived with incorrect checksum and hardware also indicated checksum is not correct. Signed-off-by: Veerasenareddy Burru Acked-by: Derek Chickles Signed-off-by: Felix Manlunas Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/liquidio/lio_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c index 825a28e5b544..e21bf3724611 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_core.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c @@ -661,7 +661,8 @@ liquidio_push_packet(u32 octeon_id __attribute__((unused)), (((rh->r_dh.encap_on) && (rh->r_dh.csum_verified & CNNIC_TUN_CSUM_VERIFIED)) || (!(rh->r_dh.encap_on) && - (rh->r_dh.csum_verified & CNNIC_CSUM_VERIFIED)))) + ((rh->r_dh.csum_verified & CNNIC_CSUM_VERIFIED) == + CNNIC_CSUM_VERIFIED)))) /* checksum has already been verified */ skb->ip_summed = CHECKSUM_UNNECESSARY; else -- cgit v1.2.3 From 0899dd34d095a352de244055aa611bbb3208e8cb Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Fri, 26 Oct 2018 10:01:39 +0300 Subject: iwlwifi: pcie: fix the use of a wrong define The code checks that we haven't exceeded the maximum number of TBs by comparing to a define of gen1 instead of gen2, fix it. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index d2bd7f528a20..8807ea9d693c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -216,7 +216,7 @@ static int iwl_pcie_gen2_set_tb(struct iwl_trans *trans, int idx = iwl_pcie_gen2_get_num_tbs(trans, tfd); struct iwl_tfh_tb *tb; - if (WARN_ON(idx >= IWL_NUM_OF_TBS)) + if (WARN_ON(idx >= IWL_TFH_NUM_TBS)) return -EINVAL; tb = &tfd->tbs[idx]; -- cgit v1.2.3 From 937c2652768f931ac2f8ce0aa35476ccb0a603d0 Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Wed, 24 Oct 2018 12:36:18 +0300 Subject: iwlwifi: iwlmvm: ignore HE PPDU type regarding EOF When setting the EOF bit in Rx flags (propagated to radiotap) do not depend it on the PPDU type (SU/MU/TB) since it doesn't. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 7bd8676508f5..786e93f6b502 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1158,14 +1158,12 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, /* temporarily hide the radiotap data */ __skb_pull(skb, radiotap_len); - if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_SU) { - /* report the AMPDU-EOF bit on single frames */ - if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) { - rx_status->flag |= RX_FLAG_AMPDU_DETAILS; - rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; - if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF)) - rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; - } + /* report the AMPDU-EOF bit on single frames */ + if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) { + rx_status->flag |= RX_FLAG_AMPDU_DETAILS; + rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; + if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF)) + rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; } if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) @@ -1178,9 +1176,7 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE; /* toggle is switched whenever new aggregation starts */ - if (toggle_bit != mvm->ampdu_toggle && - (he_type == RATE_MCS_HE_TYPE_MU || - he_type == RATE_MCS_HE_TYPE_SU)) { + if (toggle_bit != mvm->ampdu_toggle) { rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; if (phy_data->d0 & cpu_to_le32(IWL_RX_PHY_DATA0_HE_DELIM_EOF)) rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; -- cgit v1.2.3 From c97781d1d9563dc594074177dfedd848da648223 Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Wed, 24 Oct 2018 18:37:46 +0300 Subject: iwlwifi: iwlmvm: in monitor NDP notif take the NSS from rx_vec Take the NSS value from 'rx_vec' rather than from 'rate_n_flags'. The rate_n_flags has only 2 bits for the NSS giving a max of 4SS (0 = 1SS etc.). Since there may be up to 8SS use the rx_vec which has 3 bits for the NSS. While at it, fix the rx_vec array to length of 2. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/rx.h | 5 ++++- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index b4f7ea30a7c1..11c25f32a286 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -719,6 +719,9 @@ struct iwl_rx_mpdu_desc { #define RX_NO_DATA_FRAME_TIME_POS 0 #define RX_NO_DATA_FRAME_TIME_MSK (0xfffff << RX_NO_DATA_FRAME_TIME_POS) +#define RX_NO_DATA_RX_VEC0_HE_NSTS_MSK 0x03800000 +#define RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK 0x38000000 + /** * struct iwl_rx_no_data - RX no data descriptor * @info: 7:0 frame type, 15:8 RX error type @@ -739,7 +742,7 @@ struct iwl_rx_no_data { __le32 fr_time; __le32 rate; __le32 phy_info[2]; - __le32 rx_vec[3]; + __le32 rx_vec[2]; } __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 786e93f6b502..07ddd7bc07ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1701,15 +1701,24 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, } else if (rate_n_flags & RATE_MCS_VHT_MSK) { u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS; - rx_status->nss = - ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >> - RATE_VHT_MCS_NSS_POS) + 1; rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK; rx_status->encoding = RX_ENC_VHT; rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT; if (rate_n_flags & RATE_MCS_BF_MSK) rx_status->enc_flags |= RX_ENC_FLAG_BF; - } else if (!(rate_n_flags & RATE_MCS_HE_MSK)) { + /* + * take the nss from the rx_vec since the rate_n_flags has + * only 2 bits for the nss which gives a max of 4 ss but + * there may be up to 8 spatial streams + */ + rx_status->nss = + le32_get_bits(desc->rx_vec[0], + RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1; + } else if (rate_n_flags & RATE_MCS_HE_MSK) { + rx_status->nss = + le32_get_bits(desc->rx_vec[0], + RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1; + } else { int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, rx_status->band); -- cgit v1.2.3 From 85d78bb173db2b12b30ae786e54038046d6d9d47 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 24 Oct 2018 13:43:26 +0300 Subject: iwlwifi: pcie: add prints to track virtual ID In case there are bugs in this area, this data can help with debugging. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 541da1d44762..4ecf87c1cda3 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -256,6 +256,9 @@ static void iwl_pcie_restock_bd(struct iwl_trans *trans, bd[rxq->write] = cpu_to_le64(rxb->page_dma | rxb->vid); } + + IWL_DEBUG_RX(trans, "Assigned virtual RB ID %u to queue %d index %d\n", + (u32)rxb->vid, rxq->id, rxq->write); } /* @@ -1342,6 +1345,8 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, if (rxb->invalid) goto out_err; + IWL_DEBUG_RX(trans, "Got virtual RB ID %u\n", (u32)rxb->vid); + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) rxb->size = le32_to_cpu(rxq->cd[i].size) & IWL_RX_CD_SIZE; @@ -1393,11 +1398,12 @@ restart: emergency = true; } + IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i); + rxb = iwl_pcie_get_rxb(trans, rxq, i); if (!rxb) goto out; - IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i); iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency, i); i = (i + 1) & (rxq->queue_size - 1); -- cgit v1.2.3 From 677837b8b3ea10bcffa0ec8aec503a362b52c8a2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Oct 2018 11:04:30 +0200 Subject: iwlwifi: mvm: fix %16 to %016 print format With just %16, it means 16 characters padding, but we really don't want to print "0x 1F4547B", but instead want to have this filled with zeroes, so we need the 0. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 11714eb8da5e..b1d6dea7672e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1345,7 +1345,7 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr); status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK; IWL_DEBUG_RX(mvm, - "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n", + "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n", status, beacon_notify_hdr->failure_frame, le64_to_cpu(beacon->tsf), mvm->ap_last_beacon_gp2, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index e8659bf50890..5dbbd35ee630 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -248,7 +248,7 @@ void iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) IWL_ERR(mvm, "FW Error notification: seq 0x%04X service 0x%08X\n", le16_to_cpu(err_resp->bad_cmd_seq_num), le32_to_cpu(err_resp->error_service)); - IWL_ERR(mvm, "FW Error notification: timestamp 0x%16llX\n", + IWL_ERR(mvm, "FW Error notification: timestamp 0x%016llX\n", le64_to_cpu(err_resp->timestamp)); } -- cgit v1.2.3 From 486af86332c7f062e0fc63c604023f2bbe2c50d3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 29 Oct 2018 09:44:03 +0100 Subject: iwlwifi: mvm: read IWL_RX_MPDU_PHY_SHORT_PREAMBLE only for CCK Due to a general shortage of RX API bits, the firmware is going to reuse this bit on non-CCK frames to mean something else. Use it only on CCK frames to prepare for that change. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 07ddd7bc07ce..9342f61b702e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1408,7 +1408,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; } /* set the preamble flag if appropriate */ - if (phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE) + if (rate_n_flags & RATE_MCS_CCK_MSK && + phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE) rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE; if (likely(!(phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) { -- cgit v1.2.3 From cefec29ebdde94b364e5b31a802034df259344ab Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 24 Oct 2018 09:04:36 +0200 Subject: iwlwifi: pcie: align licensing to dual GPL/BSD These files have a long history of code changes, but analysing the remaining code leads to having only a few changes that are not already owned by Intel, notably from - Andy Lutomirski - Joonwoo Park - Kirtika Ruchandani - Rajat Jain - Stanislaw Gruszka remaining in the code today. Note that - I myself was working for Intel and for any possibly code that might be before my employment there give permission - Wizery employees were working for Intel More specifically, we identified the following commits that (partially may) remain today: 25c03d8e8c13 Joonwoo Park ("iwlwifi: do not schedule tasklet when rcv unused irq") f36d04abe684 Stanislaw Gruszka ("iwlwifi: use dma_alloc_coherent") 387f3381f732 Stanislaw Gruszka ("iwlwifi: fix dma mappings and skbs leak") 2624e96ce16b Stanislaw Gruszka ("iwlwifi: fix possible data overwrite in hcmd callback") bfe4b80e9f73 Stanislaw Gruszka ("iwlwifi: always check if got h/w access before write") d536c32b45d2 Andy Lutomirski ("iwlwifi: pcie: log when waking the NIC for hcmd submission fails") a6d24fad00d9 Rajat Jain ("iwlwifi: pcie: dump registers when HW becomes inaccessible") fb12777ab59b Kirtika Ruchandani ("iwlwifi: Add more call-sites for pcie reg dumper") 3a73a30049f2 Stanislaw Gruszka ("iwlwifi: cleanup/fix memory barriers") aa5affbacb24 Stanislaw Gruszka ("iwlwifi: dump stack when fail to gain access to the device") Align the licenses with their permission to clean up and to make it all identical. CC: Joonwoo Park CC: Stanislaw Gruszka CC: Andy Lutomirski CC: Rajat Jain CC: Kirtika Ruchandani Acked-by: Johannes Berg Acked-by: Kirtika Ruchandani Acked-by: Stanislaw Gruszka Acked-by: Joonwoo Park Acked-by: Rajat Jain Acked-by: Andy Lutomirski Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 41 ++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/iwl-io.h | 38 +++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 44 ++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 44 ++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 44 ++++++++++++++++++++-- 5 files changed, 192 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 4f10914f6048..ffd1e649bfa0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -1,10 +1,13 @@ /****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 - 2016 Intel Deutschland GmbH * - * Portions of this file are derived from the ipw3945 project. - * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. @@ -15,12 +18,44 @@ * more details. * * The full GNU General Public License is included in this distribution in the - * file called LICENSE. + * file called COPYING. * * Contact Information: * Intel Linux Wireless * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * + * BSD LICENSE + * + * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2015 - 2016 Intel Deutschland GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * *****************************************************************************/ #include #include diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index 38085850a2d3..61477e58352d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -1,8 +1,9 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. * - * Portions of this file are derived from the ipw3945 project. + * GPL LICENSE SUMMARY * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -14,14 +15,43 @@ * more details. * * The full GNU General Public License is included in this distribution in the - * file called LICENSE. + * file called COPYING. * * Contact Information: * Intel Linux Wireless * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * + * BSD LICENSE + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * *****************************************************************************/ - #ifndef __iwl_io_h__ #define __iwl_io_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 971785b17e09..0d16bcc3141f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1,13 +1,15 @@ /****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY * * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2018 Intel Corporation * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. @@ -18,12 +20,46 @@ * more details. * * The full GNU General Public License is included in this distribution in the - * file called LICENSE. + * file called COPYING. * * Contact Information: * Intel Linux Wireless * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * + * BSD LICENSE + * + * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * *****************************************************************************/ #ifndef __iwl_trans_int_pcie_h__ #define __iwl_trans_int_pcie_h__ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 4ecf87c1cda3..77c0b343456d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1,13 +1,15 @@ /****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2018 Intel Corporation * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. @@ -18,12 +20,46 @@ * more details. * * The full GNU General Public License is included in this distribution in the - * file called LICENSE. + * file called COPYING. * * Contact Information: * Intel Linux Wireless * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * + * BSD LICENSE + * + * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * *****************************************************************************/ #include #include diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 7073116c73b7..07395502f419 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1,13 +1,15 @@ /****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2018 Intel Corporation * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. @@ -18,12 +20,46 @@ * more details. * * The full GNU General Public License is included in this distribution in the - * file called LICENSE. + * file called COPYING. * * Contact Information: * Intel Linux Wireless * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * + * BSD LICENSE + * + * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * *****************************************************************************/ #include #include -- cgit v1.2.3 From e6aeeb4f45178197c956a5795f49648db67607bd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 29 Oct 2018 13:50:05 +0100 Subject: iwlwifi: mvm: clean up LDBG config command usage Clean up the LDBG config command to not be called "continuous recording", and while at it actually remove the continuous recording implementation completely since it was only used for store & forward architectures. This also fixes a bug at least in iwl_fw_dbg_buffer_allocation() because what's now "__le32 type" (matching the firmware) used to be "__le16 enable_recording", so the buffer allocation config sub-struct would erroneously have started at the wrong offset. In the other cases this didn't actually lead to a bug as other bytes in pad[] were all zeroes, so accessing the 16-bit value as a 32-bit value wouldn't make a difference (in little endian.) Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/debug.h | 33 ++++++++--------- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 12 +++---- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 13 ++++--- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 43 ----------------------- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 ++ 5 files changed, 29 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h index dc1fa377087a..988584973aba 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h @@ -335,29 +335,11 @@ struct iwl_dbg_mem_access_rsp { __le32 data[]; } __packed; /* DEBUG_(U|L)MAC_RD_WR_RSP_API_S_VER_1 */ -#define CONT_REC_COMMAND_SIZE 80 -#define ENABLE_CONT_RECORDING 0x15 -#define DISABLE_CONT_RECORDING 0x16 +#define LDBG_CFG_COMMAND_SIZE 80 #define BUFFER_ALLOCATION 0x27 #define START_DEBUG_RECORDING 0x29 #define STOP_DEBUG_RECORDING 0x2A -/* - * struct iwl_continuous_record_mode - recording mode - */ -struct iwl_continuous_record_mode { - __le16 enable_recording; -} __packed; - -/* - * struct iwl_continuous_record_cmd - enable/disable continuous recording - */ -struct iwl_continuous_record_cmd { - struct iwl_continuous_record_mode record_mode; - u8 pad[CONT_REC_COMMAND_SIZE - - sizeof(struct iwl_continuous_record_mode)]; -} __packed; - /* maximum fragments to be allocated per target of allocationId */ #define IWL_BUFFER_LOCATION_MAX_FRAGS 2 @@ -385,4 +367,17 @@ struct iwl_buffer_allocation_cmd { struct iwl_fragment_data fragments[IWL_BUFFER_LOCATION_MAX_FRAGS]; } __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_1 */ +/** + * struct iwl_ldbg_config_cmd - LDBG config command + * @type: configuration type + * @pad: reserved space for type-dependent data + */ +struct iwl_ldbg_config_cmd { + __le32 type; + union { + u8 pad[LDBG_CFG_COMMAND_SIZE - sizeof(__le32)]; + struct iwl_buffer_allocation_cmd buffer_allocation; + }; /* LDBG_CFG_BODY_API_U_VER_2 (partially) */ +} __packed; /* LDBG_CFG_CMD_API_S_VER_2 */ + #endif /* __iwl_fw_api_debug_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index a97bf17da14d..917aafe1a9db 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1678,20 +1678,20 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_allocation_tlv *alloc) { struct iwl_trans *trans = fwrt->trans; - struct iwl_continuous_record_cmd cont_rec = {}; - struct iwl_buffer_allocation_cmd *cmd = (void *)&cont_rec.pad[0]; + struct iwl_ldbg_config_cmd ldbg_cmd = { + .type = cpu_to_le32(BUFFER_ALLOCATION), + }; + struct iwl_buffer_allocation_cmd *cmd = &ldbg_cmd.buffer_allocation; struct iwl_host_cmd hcmd = { .id = LDBG_CONFIG_CMD, .flags = CMD_ASYNC, - .data[0] = &cont_rec, - .len[0] = sizeof(cont_rec), + .data[0] = &ldbg_cmd, + .len[0] = sizeof(ldbg_cmd), }; void *virtual_addr = NULL; u32 size = le32_to_cpu(alloc->size); dma_addr_t phys_addr; - cont_rec.record_mode.enable_recording = cpu_to_le16(BUFFER_ALLOCATION); - if (!trans->num_blocks && le32_to_cpu(alloc->buffer_location) != IWL_FW_INI_LOCATION_DRAM_PATH) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 40dcc3deb257..7cd206e6fb9e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -271,18 +271,17 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, static int iwl_fw_dbg_start_stop_hcmd(struct iwl_fw_runtime *fwrt, bool start) { - struct iwl_continuous_record_cmd cont_rec = {}; + struct iwl_ldbg_config_cmd cmd = { + .type = start ? cpu_to_le32(START_DEBUG_RECORDING) : + cpu_to_le32(STOP_DEBUG_RECORDING), + }; struct iwl_host_cmd hcmd = { .id = LDBG_CONFIG_CMD, .flags = CMD_ASYNC, - .data[0] = &cont_rec, - .len[0] = sizeof(cont_rec), + .data[0] = &cmd, + .len[0] = sizeof(cmd), }; - cont_rec.record_mode.enable_recording = start ? - cpu_to_le16(START_DEBUG_RECORDING) : - cpu_to_le16(STOP_DEBUG_RECORDING); - return iwl_trans_send_cmd(fwrt->trans, &hcmd); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 52c361a6124c..514aaec6d59e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1206,47 +1206,6 @@ static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -/* - * Enable / Disable continuous recording. - * Cause the FW to start continuous recording, by sending the relevant hcmd. - * Enable: input of every integer larger than 0, ENABLE_CONT_RECORDING. - * Disable: for 0 as input, DISABLE_CONT_RECORDING. - */ -static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm, - char *buf, size_t count, - loff_t *ppos) -{ - struct iwl_trans *trans = mvm->trans; - const struct iwl_fw_dbg_dest_tlv_v1 *dest = trans->dbg_dest_tlv; - struct iwl_continuous_record_cmd cont_rec = {}; - int ret, rec_mode; - - if (!iwl_mvm_firmware_running(mvm)) - return -EIO; - - if (!dest) - return -EOPNOTSUPP; - - if (dest->monitor_mode != SMEM_MODE || - trans->cfg->device_family < IWL_DEVICE_FAMILY_8000) - return -EOPNOTSUPP; - - ret = kstrtoint(buf, 0, &rec_mode); - if (ret) - return ret; - - cont_rec.record_mode.enable_recording = rec_mode ? - cpu_to_le16(ENABLE_CONT_RECORDING) : - cpu_to_le16(DISABLE_CONT_RECORDING); - - mutex_lock(&mvm->mutex); - ret = iwl_mvm_send_cmd_pdu(mvm, LDBG_CONFIG_CMD, 0, - sizeof(cont_rec), &cont_rec); - mutex_unlock(&mvm->mutex); - - return ret ?: count; -} - static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) @@ -1800,7 +1759,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); -MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8); MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8); MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, (IWL_RSS_INDIRECTION_TABLE_SIZE * 2)); @@ -2004,7 +1962,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(max_amsdu_len, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200); - MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200); #ifdef CONFIG_ACPI diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index d257c143e624..ee2ef3f0042c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -737,6 +737,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, trans_cfg.rx_buf_size = rb_size_default; } + BUILD_BUG_ON(sizeof(struct iwl_ldbg_config_cmd) != + LDBG_CFG_COMMAND_SIZE); + trans->wide_cmd_header = true; trans_cfg.bc_table_dword = mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560; -- cgit v1.2.3 From 0f8bf03c86602cb0cb1236f49a0c9340f786f5b4 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 13 Aug 2018 15:30:35 +0300 Subject: iwlwifi: mvm: save and export regdb blob from the NVM Sometimes we want to debug issues related to the regulatory blob in the NVM. To make that easier, add a debugfs entry to export it together with the other nvm blobs we export. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 5 +++++ 3 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 514aaec6d59e..cbbd4b076e17 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -2028,6 +2028,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) if (!debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir, &mvm->nvm_phy_sku_blob)) goto err; + if (!debugfs_create_blob("nvm_reg", S_IRUSR, + mvm->debugfs_dir, &mvm->nvm_reg_blob)) + goto err; debugfs_create_file("mem", 0600, dbgfs_dir, mvm, &iwl_dbgfs_mem_ops); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 503e51d32e7f..c314f77f657f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -965,6 +965,7 @@ struct iwl_mvm { struct debugfs_blob_wrapper nvm_calib_blob; struct debugfs_blob_wrapper nvm_prod_blob; struct debugfs_blob_wrapper nvm_phy_sku_blob; + struct debugfs_blob_wrapper nvm_reg_blob; struct iwl_mvm_frame_stats drv_rx_stats; spinlock_t drv_stats_lock; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index f08934b03cf3..7bdbd010ae6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -416,6 +416,11 @@ int iwl_nvm_init(struct iwl_mvm *mvm) mvm->nvm_phy_sku_blob.data = temp; mvm->nvm_phy_sku_blob.size = ret; break; + case NVM_SECTION_TYPE_REGULATORY_SDP: + case NVM_SECTION_TYPE_REGULATORY: + mvm->nvm_reg_blob.data = temp; + mvm->nvm_reg_blob.size = ret; + break; default: if (section == mvm->cfg->nvm_hw_section_num) { mvm->nvm_hw_blob.data = temp; -- cgit v1.2.3 From da0df827cd15813c064d5859926b5f1e779d0061 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 31 Oct 2018 10:21:10 +0200 Subject: iwlwifi: make iwl_fw_dbg_start_stop_hcmd() inline This function is supposed to be used as an inline function and is in a header file, so make it inline. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 7cd206e6fb9e..d8090d4b5c43 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -269,7 +269,8 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, iwl_fw_dbg_get_trigger((fwrt)->fw,\ (trig))) -static int iwl_fw_dbg_start_stop_hcmd(struct iwl_fw_runtime *fwrt, bool start) +static inline int +iwl_fw_dbg_start_stop_hcmd(struct iwl_fw_runtime *fwrt, bool start) { struct iwl_ldbg_config_cmd cmd = { .type = start ? cpu_to_le32(START_DEBUG_RECORDING) : -- cgit v1.2.3 From e78da25e19c2dd31018c358d0717e4f6cfe317c8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Oct 2018 08:48:49 +0100 Subject: iwlwifi: move iwl_enable_{rx,tx}_ampdu to iwl-modparams.h These inlines just check the module parameters, so they don't need a configuration parameter and can move to a better place. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c | 23 +++------------------- drivers/net/wireless/intel/iwlwifi/iwl-modparams.h | 18 +++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 22 ++------------------- 3 files changed, 23 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 49b71dbf8490..54b759cec8b3 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -1,6 +1,7 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. + * Copyright (C) 2018 Intel Corporation * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -710,24 +711,6 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } -static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg) -{ - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) - return false; - return true; -} - -static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) -{ - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) - return false; - if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG) - return true; - - /* disabled by default */ - return false; -} - static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_ampdu_params *params) @@ -752,7 +735,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if (!iwl_enable_rx_ampdu(priv->cfg)) + if (!iwl_enable_rx_ampdu()) break; IWL_DEBUG_HT(priv, "start Rx\n"); ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn); @@ -764,7 +747,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, case IEEE80211_AMPDU_TX_START: if (!priv->trans->ops->txq_enable) break; - if (!iwl_enable_tx_ampdu(priv->cfg)) + if (!iwl_enable_tx_ampdu()) break; IWL_DEBUG_HT(priv, "start Tx\n"); ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h index 73b1c46f1158..0cae2ef9b9df 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h @@ -152,4 +152,22 @@ struct iwl_mod_params { bool enable_ini; }; +static inline bool iwl_enable_rx_ampdu(void) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) + return false; + return true; +} + +static inline bool iwl_enable_tx_ampdu(void) +{ + if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) + return false; + if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG) + return true; + + /* enabled by default */ + return true; +} + #endif /* #__iwl_modparams_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index ebb3814dd922..78b35c9595a3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -943,24 +943,6 @@ static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw, schedule_work(&mvm->add_stream_wk); } -static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg) -{ - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) - return false; - return true; -} - -static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) -{ - if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) - return false; - if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG) - return true; - - /* enabled by default */ - return true; -} - #define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...) \ do { \ if (!(le16_to_cpu(_tid_bm) & BIT(_tid))) \ @@ -1073,7 +1055,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, mvmvif = iwl_mvm_vif_from_mac80211(vif); cancel_delayed_work(&mvmvif->uapsd_nonagg_detected_wk); } - if (!iwl_enable_rx_ampdu(mvm->cfg)) { + if (!iwl_enable_rx_ampdu()) { ret = -EINVAL; break; } @@ -1085,7 +1067,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, timeout); break; case IEEE80211_AMPDU_TX_START: - if (!iwl_enable_tx_ampdu(mvm->cfg)) { + if (!iwl_enable_tx_ampdu()) { ret = -EINVAL; break; } -- cgit v1.2.3 From 94a8d87c47642bc0b99f1c9204b111b5826f1838 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 5 Nov 2018 11:07:58 +0200 Subject: iwlwifi: mvm: pre-initialize alive_data in wait_alive() The function we pass to the wait alive notification procedure may may not even get called if the timeout occurs before the function is called. To prevent accessing unitialized data in alive_data, pre-set it to zero in the declaration. Found by static analyzers. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 27582d70d45a..d3dc9d276e0f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -293,7 +293,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, enum iwl_ucode_type ucode_type) { struct iwl_notification_wait alive_wait; - struct iwl_mvm_alive_data alive_data; + struct iwl_mvm_alive_data alive_data = {}; const struct fw_img *fw; int ret; enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img; -- cgit v1.2.3 From 29cf396f08f6476935c445faddcaf90f2fe2fa87 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 5 Nov 2018 15:45:54 +0200 Subject: iwlwifi: calculate pointers from out_cmd instead of out_cmd->hdr The out_cmd structure starts with a header, so there's no need to use &out_cmd->hdr, out_cmd alone is enough. We use this when calculating other addresses and klocwork gets confused with that because it thinks we are trying to access hdr (as an array) beyond its size. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 8807ea9d693c..f3d2e8fe920b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -838,14 +838,14 @@ static int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans, /* start the TFD with the minimum copy bytes */ tb0_size = min_t(int, copy_size, IWL_FIRST_TB_SIZE); - memcpy(&txq->first_tb_bufs[idx], &out_cmd->hdr, tb0_size); + memcpy(&txq->first_tb_bufs[idx], out_cmd, tb0_size); iwl_pcie_gen2_set_tb(trans, tfd, iwl_pcie_get_first_tb_dma(txq, idx), tb0_size); /* map first command fragment, if any remains */ if (copy_size > tb0_size) { phys_addr = dma_map_single(trans->dev, - ((u8 *)&out_cmd->hdr) + tb0_size, + (u8 *)out_cmd + tb0_size, copy_size - tb0_size, DMA_TO_DEVICE); if (dma_mapping_error(trans->dev, phys_addr)) { -- cgit v1.2.3 From 9adcc117bc7d16e5ef226fec0a1d1f25765bf9ce Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 6 Nov 2018 08:24:12 +0200 Subject: iwlwifi: make sure cur_fw_img is valid before accessing img Harden the fwrt->fw->img array access by making sure the cur_fw_img value doesn't go out of bounds. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index d8090d4b5c43..330229d2a61d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -381,6 +381,7 @@ static inline bool iwl_fw_dbg_is_paging_enabled(struct iwl_fw_runtime *fwrt) { return iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_PAGING) && !fwrt->trans->cfg->gen2 && + fwrt->cur_fw_img < IWL_UCODE_TYPE_MAX && fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size && fwrt->fw_paging_db[0].fw_paging_block; } -- cgit v1.2.3 From 34a880d8bd4c29f7aaf02a46e2569234bd178528 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Thu, 1 Nov 2018 16:30:15 +0200 Subject: iwlwifi: mvm: remove sta key on wep ap If WEP is used, no one removes the STA key upon STA removal, leading to a situation where after 16 connect/disconnects - the AP could no longer decrypt incoming data frames since iwl_mvm_set_fw_key_idx() called from iwl_mvm_set_sta_key() during association returns STA_KEY_IDX_INVALID, thus not setting the key for that connecting STA. Fix this by removing the key in the driver when the STA is removed. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 78b35c9595a3..b4a55349336f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3091,6 +3091,16 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr, NL80211_TDLS_DISABLE_LINK); } + + /* Remove STA key if this is an AP using WEP */ + if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) { + int rm_ret = iwl_mvm_remove_sta_key(mvm, vif, sta, + mvmvif->ap_wep_key); + + if (!ret) + ret = rm_ret; + } + } else { ret = -EIO; } -- cgit v1.2.3 From fefbf85305ecd28c383c2d83694b147217605059 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 31 Oct 2018 13:29:21 +0200 Subject: iwlwifi: monitor dumping flow cleanup Since we use a dumping mask, checking if only monitor was requested is redundant. Remove the unneeded code. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index e72bd9796b5b..472a85d9a358 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3169,8 +3169,7 @@ static struct iwl_trans_dump_data struct iwl_txq *cmdq = trans_pcie->txq[trans_pcie->cmd_queue]; struct iwl_fw_error_dump_txcmd *txcmd; struct iwl_trans_dump_data *dump_data; - u32 len, num_rbs = 0; - u32 monitor_len; + u32 len, num_rbs = 0, monitor_len = 0; int i, ptr; bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) && !trans->cfg->mq_rx_supported && @@ -3187,19 +3186,8 @@ static struct iwl_trans_dump_data cmdq->n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE); /* FW monitor */ - monitor_len = iwl_trans_get_fw_monitor_len(trans, &len); - - if (dump_mask == BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)) { - dump_data = vzalloc(len); - if (!dump_data) - return NULL; - - data = (void *)dump_data->data; - len = iwl_trans_pcie_dump_monitor(trans, &data, monitor_len); - dump_data->len = len; - - return dump_data; - } + if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)) + monitor_len = iwl_trans_get_fw_monitor_len(trans, &len); /* CSR registers */ if (dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR)) -- cgit v1.2.3 From 698478c49294eb3d4d64f7a3b61d460495826078 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 29 Oct 2018 11:23:45 +0200 Subject: iwlwifi: mvm: add an option to dereference vif by id Currently whenever we get firmware notification with mac id, we iterate over all the interfaces to find the ID. This is a bit cumbersome. Instead, adding an array of RCU pointers, like we have for station IDs. This is not expensive space wise since we have only up to 4 active MACs, and not complicated code wise, since we have a clear point to init and de-init it. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 99 ++++++++++------------- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 14 ++++ drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 22 +++-- 4 files changed, 72 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index b1d6dea7672e..c868ebfa10ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1382,35 +1382,47 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, } } -static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, - struct ieee80211_vif *vif) +void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) { - struct iwl_missed_beacons_notif *missed_beacons = _data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_missed_beacons_notif *mb = (void *)pkt->data; struct iwl_fw_dbg_trigger_missed_bcon *bcon_trig; struct iwl_fw_dbg_trigger_tlv *trigger; u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx; u32 rx_missed_bcon, rx_missed_bcon_since_rx; + struct ieee80211_vif *vif; + u32 id = le32_to_cpu(mb->mac_id); - if (mvmvif->id != (u16)le32_to_cpu(missed_beacons->mac_id)) - return; + IWL_DEBUG_INFO(mvm, + "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n", + le32_to_cpu(mb->mac_id), + le32_to_cpu(mb->consec_missed_beacons), + le32_to_cpu(mb->consec_missed_beacons_since_last_rx), + le32_to_cpu(mb->num_recvd_beacons), + le32_to_cpu(mb->num_expected_beacons)); + + rcu_read_lock(); + + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); + if (!vif) + goto out; - rx_missed_bcon = le32_to_cpu(missed_beacons->consec_missed_beacons); + rx_missed_bcon = le32_to_cpu(mb->consec_missed_beacons); rx_missed_bcon_since_rx = - le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx); + le32_to_cpu(mb->consec_missed_beacons_since_last_rx); /* * TODO: the threshold should be adjusted based on latency conditions, * and/or in case of a CS flow on one of the other AP vifs. */ - if (le32_to_cpu(missed_beacons->consec_missed_beacons_since_last_rx) > + if (le32_to_cpu(mb->consec_missed_beacons_since_last_rx) > IWL_MVM_MISSED_BEACONS_THRESHOLD) ieee80211_beacon_loss(vif); trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), FW_DBG_TRIGGER_MISSED_BEACONS); if (!trigger) - return; + goto out; bcon_trig = (void *)trigger->data; stop_trig_missed_bcon = le32_to_cpu(bcon_trig->stop_consec_missed_bcon); @@ -1422,28 +1434,11 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac, if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx || rx_missed_bcon >= stop_trig_missed_bcon) iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL); -} - -void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_missed_beacons_notif *mb = (void *)pkt->data; - - IWL_DEBUG_INFO(mvm, - "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n", - le32_to_cpu(mb->mac_id), - le32_to_cpu(mb->consec_missed_beacons), - le32_to_cpu(mb->consec_missed_beacons_since_last_rx), - le32_to_cpu(mb->num_recvd_beacons), - le32_to_cpu(mb->num_expected_beacons)); - - ieee80211_iterate_active_interfaces_atomic(mvm->hw, - IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_beacon_loss_iterator, - mb); iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS); + +out: + rcu_read_unlock(); } void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, @@ -1485,16 +1480,29 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, ieee80211_rx_napi(mvm->hw, NULL, skb, NULL); } -static void iwl_mvm_probe_resp_data_iter(void *_data, u8 *mac, - struct ieee80211_vif *vif) +void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) { - struct iwl_probe_resp_data_notif *notif = _data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_probe_resp_data_notif *notif = (void *)pkt->data; struct iwl_probe_resp_data *old_data, *new_data; + int len = iwl_rx_packet_payload_len(pkt); + u32 id = le32_to_cpu(notif->mac_id); + struct ieee80211_vif *vif; + struct iwl_mvm_vif *mvmvif; + + if (WARN_ON_ONCE(len < sizeof(*notif))) + return; + + IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n", + notif->noa_active, notif->csa_counter); - if (mvmvif->id != (u16)le32_to_cpu(notif->mac_id)) + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, false); + if (!vif) return; + mvmvif = iwl_mvm_vif_from_mac80211(vif); + new_data = kzalloc(sizeof(*new_data), GFP_KERNEL); if (!new_data) return; @@ -1525,25 +1533,6 @@ static void iwl_mvm_probe_resp_data_iter(void *_data, u8 *mac, ieee80211_csa_set_counter(vif, notif->csa_counter); } -void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_probe_resp_data_notif *notif = (void *)pkt->data; - int len = iwl_rx_packet_payload_len(pkt); - - if (WARN_ON_ONCE(len < sizeof(*notif))) - return; - - IWL_DEBUG_INFO(mvm, "Probe response data notif: noa %d, csa %d\n", - notif->noa_active, notif->csa_counter); - - ieee80211_iterate_active_interfaces(mvm->hw, - IEEE80211_IFACE_ITER_ACTIVE, - iwl_mvm_probe_resp_data_iter, - notif); -} - void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index b4a55349336f..e3da6992f244 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1471,6 +1471,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, if (ret) goto out_unlock; + rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif); + /* Counting number of interfaces is needed for legacy PM */ if (vif->type != NL80211_IFTYPE_P2P_DEVICE) mvm->vif_count++; @@ -1662,6 +1664,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, iwl_mvm_power_update_mac(mvm); iwl_mvm_mac_ctxt_remove(mvm, vif); + RCU_INIT_POINTER(mvm->vif_id_to_mac[mvmvif->id], NULL); + if (vif->type == NL80211_IFTYPE_MONITOR) mvm->monitor_on = false; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index c314f77f657f..d326843636cb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -989,6 +989,7 @@ struct iwl_mvm { u8 refs[IWL_MVM_REF_COUNT]; u8 vif_count; + struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER]; /* -1 for always, 0 for never, >0 for that many times */ s8 fw_restart; @@ -1241,6 +1242,19 @@ iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id) return iwl_mvm_sta_from_mac80211(sta); } +static inline struct ieee80211_vif * +iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu) +{ + if (WARN_ON(vif_id >= ARRAY_SIZE(mvm->vif_id_to_mac))) + return NULL; + + if (rcu) + return rcu_dereference(mvm->vif_id_to_mac[vif_id]); + + return rcu_dereference_protected(mvm->vif_id_to_mac[vif_id], + lockdep_is_held(&mvm->mutex)); +} + static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) { return !iwlwifi_mod_params.d0i3_disable && diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 5dbbd35ee630..211c4638d690 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -1136,19 +1136,14 @@ static void iwl_mvm_tcm_uapsd_nonagg_detected_wk(struct work_struct *wk) "AP isn't using AMPDU with uAPSD enabled"); } -static void iwl_mvm_uapsd_agg_disconnect_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void iwl_mvm_uapsd_agg_disconnect(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - int *mac_id = data; if (vif->type != NL80211_IFTYPE_STATION) return; - if (mvmvif->id != *mac_id) - return; - if (!vif->bss_conf.assoc) return; @@ -1158,10 +1153,10 @@ static void iwl_mvm_uapsd_agg_disconnect_iter(void *data, u8 *mac, !mvmvif->queue_params[IEEE80211_AC_BK].uapsd) return; - if (mvm->tcm.data[*mac_id].uapsd_nonagg_detect.detected) + if (mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected) return; - mvm->tcm.data[*mac_id].uapsd_nonagg_detect.detected = true; + mvm->tcm.data[mvmvif->id].uapsd_nonagg_detect.detected = true; IWL_INFO(mvm, "detected AP should do aggregation but isn't, likely due to U-APSD\n"); schedule_delayed_work(&mvmvif->uapsd_nonagg_detected_wk, 15 * HZ); @@ -1174,6 +1169,7 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm, u64 bytes = mvm->tcm.data[mac].uapsd_nonagg_detect.rx_bytes; u64 tpt; unsigned long rate; + struct ieee80211_vif *vif; rate = ewma_rate_read(&mvm->tcm.data[mac].uapsd_nonagg_detect.rate); @@ -1202,9 +1198,11 @@ static void iwl_mvm_check_uapsd_agg_expected_tpt(struct iwl_mvm *mvm, return; } - ieee80211_iterate_active_interfaces_atomic( - mvm->hw, IEEE80211_IFACE_ITER_NORMAL, - iwl_mvm_uapsd_agg_disconnect_iter, &mac); + rcu_read_lock(); + vif = rcu_dereference(mvm->vif_id_to_mac[mac]); + if (vif) + iwl_mvm_uapsd_agg_disconnect(mvm, vif); + rcu_read_unlock(); } static void iwl_mvm_tcm_iterator(void *_data, u8 *mac, -- cgit v1.2.3 From 1f7698abedeeb3fef3cbcf78e16f925df675a179 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 8 Nov 2018 09:51:56 +0100 Subject: iwlwifi: mvm: fix A-MPDU reference assignment The current code assigns the reference, and then goes to increment it if the toggle bit has changed. That way, we get Toggle 0 0 0 0 1 1 1 1 ID 1 1 1 1 1 2 2 2 Fix that by assigning the post-toggle ID to get Toggle 0 0 0 0 1 1 1 1 ID 1 1 1 1 2 2 2 2 Reported-by: Danny Alexander Signed-off-by: Johannes Berg Fixes: fbe4112791b8 ("iwlwifi: mvm: update mpdu metadata API") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 9342f61b702e..120e3f2d21aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1438,12 +1438,12 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE; rx_status->flag |= RX_FLAG_AMPDU_DETAILS; - rx_status->ampdu_reference = mvm->ampdu_ref; /* toggle is switched whenever new aggregation starts */ if (toggle_bit != mvm->ampdu_toggle) { mvm->ampdu_ref++; mvm->ampdu_toggle = toggle_bit; } + rx_status->ampdu_reference = mvm->ampdu_ref; } rcu_read_lock(); -- cgit v1.2.3 From fba8248e7e67b7e1098e69284aeccbcb2110fa86 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 25 Oct 2018 20:11:51 +0300 Subject: iwlwifi: mvm: get rid of tx_path_lock TX path lock was introduced in order to prevent out of order invocations of TX. This can happen in the following flow: TX path invoked from net dev Packet dequeued TX path invoked from RX path Packet dequeued Packet TXed Packet TXed However, we don't really need a lock. If TX path is already invoked from some location, other paths can simply abort their execution, instead of waiting to the first path to finish, and then discover queue is (likely) empty or stopped. Replace the lock with an atomic variable to track TX ownership. This simplifies the locking dependencies between RX and TX paths, and should improve performance. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 48 ++++++++++++++++------- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 +- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 4 +- 3 files changed, 36 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index e3da6992f244..dd0761e5cf6a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -878,25 +878,45 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq); struct sk_buff *skb = NULL; - spin_lock(&mvmtxq->tx_path_lock); + /* + * No need for threads to be pending here, they can leave the first + * taker all the work. + * + * mvmtxq->tx_request logic: + * + * If 0, no one is currently TXing, set to 1 to indicate current thread + * will now start TX and other threads should quit. + * + * If 1, another thread is currently TXing, set to 2 to indicate to + * that thread that there was another request. Since that request may + * have raced with the check whether the queue is empty, the TXing + * thread should check the queue's status one more time before leaving. + * This check is done in order to not leave any TX hanging in the queue + * until the next TX invocation (which may not even happen). + * + * If 2, another thread is currently TXing, and it will already double + * check the queue, so do nothing. + */ + if (atomic_fetch_add_unless(&mvmtxq->tx_request, 1, 2)) + return; rcu_read_lock(); - while (likely(!mvmtxq->stopped && - (mvm->trans->system_pm_mode == - IWL_PLAT_PM_MODE_DISABLED))) { - skb = ieee80211_tx_dequeue(hw, txq); + do { + while (likely(!mvmtxq->stopped && + (mvm->trans->system_pm_mode == + IWL_PLAT_PM_MODE_DISABLED))) { + skb = ieee80211_tx_dequeue(hw, txq); - if (!skb) - break; + if (!skb) + break; - if (!txq->sta) - iwl_mvm_tx_skb_non_sta(mvm, skb); - else - iwl_mvm_tx_skb(mvm, skb, txq->sta); - } + if (!txq->sta) + iwl_mvm_tx_skb_non_sta(mvm, skb); + else + iwl_mvm_tx_skb(mvm, skb, txq->sta); + } + } while (atomic_dec_return(&mvmtxq->tx_request)); rcu_read_unlock(); - - spin_unlock(&mvmtxq->tx_path_lock); } static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index d326843636cb..a289b9488c03 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -781,8 +781,7 @@ struct iwl_mvm_geo_profile { struct iwl_mvm_txq { struct list_head list; u16 txq_id; - /* Protects TX path invocation from two places */ - spinlock_t tx_path_lock; + atomic_t tx_request; bool stopped; }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 5f42897dcd55..c5a01470a3bc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1403,9 +1403,7 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid); list_del_init(&mvmtxq->list); - local_bh_disable(); iwl_mvm_mac_itxq_xmit(mvm->hw, txq); - local_bh_enable(); } mutex_unlock(&mvm->mutex); @@ -1646,7 +1644,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE; INIT_LIST_HEAD(&mvmtxq->list); - spin_lock_init(&mvmtxq->tx_path_lock); + atomic_set(&mvmtxq->tx_request, 0); } mvm_sta->agg_tids = 0; -- cgit v1.2.3 From 3a894a9f319f0b4a36857683c4caacc371a40d25 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Oct 2018 14:47:52 +0100 Subject: iwlwifi: remove TOF implementation This is an ancient (~2015) implementation that no longer matches the firmware in any way, and most likely never worked. Remove all of it so it can be reintroduced properly. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/commands.h | 12 - drivers/net/wireless/intel/iwlwifi/fw/api/tof.h | 393 ----------- drivers/net/wireless/intel/iwlwifi/fw/file.h | 2 - drivers/net/wireless/intel/iwlwifi/mvm/Makefile | 1 - .../net/wireless/intel/iwlwifi/mvm/debugfs-vif.c | 770 --------------------- drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 3 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 - drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 8 - drivers/net/wireless/intel/iwlwifi/mvm/tof.c | 305 -------- drivers/net/wireless/intel/iwlwifi/mvm/tof.h | 89 --- 10 files changed, 2 insertions(+), 1584 deletions(-) delete mode 100644 drivers/net/wireless/intel/iwlwifi/fw/api/tof.h delete mode 100644 drivers/net/wireless/intel/iwlwifi/mvm/tof.c delete mode 100644 drivers/net/wireless/intel/iwlwifi/mvm/tof.h (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 89c0cfddcc3f..baba7bcee5fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -77,7 +77,6 @@ * @DATA_PATH_GROUP: data path group, uses command IDs from * &enum iwl_data_path_subcmd_ids * @NAN_GROUP: NAN group, uses command IDs from &enum iwl_nan_subcmd_ids - * @TOF_GROUP: TOF group, uses command IDs from &enum iwl_tof_subcmd_ids * @PROT_OFFLOAD_GROUP: protocol offload group, uses command IDs from * &enum iwl_prot_offload_subcmd_ids * @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from @@ -92,7 +91,6 @@ enum iwl_mvm_command_groups { PHY_OPS_GROUP = 0x4, DATA_PATH_GROUP = 0x5, NAN_GROUP = 0x7, - TOF_GROUP = 0x8, PROT_OFFLOAD_GROUP = 0xb, REGULATORY_AND_NVM_GROUP = 0xc, DEBUG_GROUP = 0xf, @@ -352,16 +350,6 @@ enum iwl_legacy_cmds { */ PHY_DB_CMD = 0x6c, - /** - * @TOF_CMD: &struct iwl_tof_config_cmd - */ - TOF_CMD = 0x10, - - /** - * @TOF_NOTIFICATION: &struct iwl_tof_gen_resp_cmd - */ - TOF_NOTIFICATION = 0x11, - /** * @POWER_TABLE_CMD: &struct iwl_device_power_cmd */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tof.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tof.h deleted file mode 100644 index 7328a1606146..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tof.h +++ /dev/null @@ -1,393 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __iwl_fw_api_tof_h__ -#define __iwl_fw_api_tof_h__ - -/* ToF sub-group command IDs */ -enum iwl_mvm_tof_sub_grp_ids { - TOF_RANGE_REQ_CMD = 0x1, - TOF_CONFIG_CMD = 0x2, - TOF_RANGE_ABORT_CMD = 0x3, - TOF_RANGE_REQ_EXT_CMD = 0x4, - TOF_RESPONDER_CONFIG_CMD = 0x5, - TOF_NW_INITIATED_RES_SEND_CMD = 0x6, - TOF_NEIGHBOR_REPORT_REQ_CMD = 0x7, - TOF_NEIGHBOR_REPORT_RSP_NOTIF = 0xFC, - TOF_NW_INITIATED_REQ_RCVD_NOTIF = 0xFD, - TOF_RANGE_RESPONSE_NOTIF = 0xFE, - TOF_MCSI_DEBUG_NOTIF = 0xFB, -}; - -/** - * struct iwl_tof_config_cmd - ToF configuration - * @tof_disabled: 0 enabled, 1 - disabled - * @one_sided_disabled: 0 enabled, 1 - disabled - * @is_debug_mode: 1 debug mode, 0 - otherwise - * @is_buf_required: 1 channel estimation buffer required, 0 - otherwise - */ -struct iwl_tof_config_cmd { - __le32 sub_grp_cmd_id; - u8 tof_disabled; - u8 one_sided_disabled; - u8 is_debug_mode; - u8 is_buf_required; -} __packed; - -/** - * struct iwl_tof_responder_config_cmd - ToF AP mode (for debug) - * @burst_period: future use: (currently hard coded in the LMAC) - * The interval between two sequential bursts. - * @min_delta_ftm: future use: (currently hard coded in the LMAC) - * The minimum delay between two sequential FTM Responses - * in the same burst. - * @burst_duration: future use: (currently hard coded in the LMAC) - * The total time for all FTMs handshake in the same burst. - * Affect the time events duration in the LMAC. - * @num_of_burst_exp: future use: (currently hard coded in the LMAC) - * The number of bursts for the current ToF request. Affect - * the number of events allocations in the current iteration. - * @get_ch_est: for xVT only, NA for driver - * @abort_responder: when set to '1' - Responder will terminate its activity - * (all other fields in the command are ignored) - * @recv_sta_req_params: 1 - Responder will ignore the other Responder's - * params and use the recomended Initiator params. - * 0 - otherwise - * @channel_num: current AP Channel - * @bandwidth: current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz - * @rate: current AP rate - * @ctrl_ch_position: coding of the control channel position relative to - * the center frequency: - * - * 40 MHz - * 0 below center, 1 above center - * - * 80 MHz - * bits [0..1] - * * 0 the near 20MHz to the center, - * * 1 the far 20MHz to the center - * bit[2] - * as above 40MHz - * @ftm_per_burst: FTMs per Burst - * @ftm_resp_ts_avail: '0' - we don't measure over the Initial FTM Response, - * '1' - we measure over the Initial FTM Response - * @asap_mode: ASAP / Non ASAP mode for the current WLS station - * @sta_id: index of the AP STA when in AP mode - * @tsf_timer_offset_msecs: The dictated time offset (mSec) from the AP's TSF - * @toa_offset: Artificial addition [0.1nsec] for the ToA - to be used for debug - * purposes, simulating station movement by adding various values - * to this field - * @bssid: Current AP BSSID - */ -struct iwl_tof_responder_config_cmd { - __le32 sub_grp_cmd_id; - __le16 burst_period; - u8 min_delta_ftm; - u8 burst_duration; - u8 num_of_burst_exp; - u8 get_ch_est; - u8 abort_responder; - u8 recv_sta_req_params; - u8 channel_num; - u8 bandwidth; - u8 rate; - u8 ctrl_ch_position; - u8 ftm_per_burst; - u8 ftm_resp_ts_avail; - u8 asap_mode; - u8 sta_id; - __le16 tsf_timer_offset_msecs; - __le16 toa_offset; - u8 bssid[ETH_ALEN]; -} __packed; - -/** - * struct iwl_tof_range_request_ext_cmd - extended range req for WLS - * @tsf_timer_offset_msec: the recommended time offset (mSec) from the AP's TSF - * @reserved: reserved - * @min_delta_ftm: Minimal time between two consecutive measurements, - * in units of 100us. 0 means no preference by station - * @ftm_format_and_bw20M: FTM Channel Spacing/Format for 20MHz: recommended - * value be sent to the AP - * @ftm_format_and_bw40M: FTM Channel Spacing/Format for 40MHz: recommended - * value to be sent to the AP - * @ftm_format_and_bw80M: FTM Channel Spacing/Format for 80MHz: recommended - * value to be sent to the AP - */ -struct iwl_tof_range_req_ext_cmd { - __le32 sub_grp_cmd_id; - __le16 tsf_timer_offset_msec; - __le16 reserved; - u8 min_delta_ftm; - u8 ftm_format_and_bw20M; - u8 ftm_format_and_bw40M; - u8 ftm_format_and_bw80M; -} __packed; - -#define IWL_MVM_TOF_MAX_APS 21 - -/** - * struct iwl_tof_range_req_ap_entry - AP configuration parameters - * @channel_num: Current AP Channel - * @bandwidth: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz - * @tsf_delta_direction: TSF relatively to the subject AP - * @ctrl_ch_position: Coding of the control channel position relative to the - * center frequency. - * 40MHz 0 below center, 1 above center - * 80MHz bits [0..1]: 0 the near 20MHz to the center, - * 1 the far 20MHz to the center - * bit[2] as above 40MHz - * @bssid: AP's bss id - * @measure_type: Measurement type: 0 - two sided, 1 - One sided - * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of the - * number of measurement iterations (min 2^0 = 1, max 2^14) - * @burst_period: Recommended value to be sent to the AP. Measurement - * periodicity In units of 100ms. ignored if num_of_bursts = 0 - * @samples_per_burst: 2-sided: the number of FTMs pairs in single Burst (1-31) - * 1-sided: how many rts/cts pairs should be used per burst. - * @retries_per_sample: Max number of retries that the LMAC should send - * in case of no replies by the AP. - * @tsf_delta: TSF Delta in units of microseconds. - * The difference between the AP TSF and the device local clock. - * @location_req: Location Request Bit[0] LCI should be sent in the FTMR - * Bit[1] Civic should be sent in the FTMR - * @asap_mode: 0 - non asap mode, 1 - asap mode (not relevant for one sided) - * @enable_dyn_ack: Enable Dynamic ACK BW. - * 0 Initiator interact with regular AP - * 1 Initiator interact with Responder machine: need to send the - * Initiator Acks with HT 40MHz / 80MHz, since the Responder should - * use it for its ch est measurement (this flag will be set when we - * configure the opposite machine to be Responder). - * @rssi: Last received value - * leagal values: -128-0 (0x7f). above 0x0 indicating an invalid value. - */ -struct iwl_tof_range_req_ap_entry { - u8 channel_num; - u8 bandwidth; - u8 tsf_delta_direction; - u8 ctrl_ch_position; - u8 bssid[ETH_ALEN]; - u8 measure_type; - u8 num_of_bursts; - __le16 burst_period; - u8 samples_per_burst; - u8 retries_per_sample; - __le32 tsf_delta; - u8 location_req; - u8 asap_mode; - u8 enable_dyn_ack; - s8 rssi; -} __packed; - -/** - * enum iwl_tof_response_mode - * @IWL_MVM_TOF_RESPOSE_ASAP: report each AP measurement separately as soon as - * possible (not supported for this release) - * @IWL_MVM_TOF_RESPOSE_TIMEOUT: report all AP measurements as a batch upon - * timeout expiration - * @IWL_MVM_TOF_RESPOSE_COMPLETE: report all AP measurements as a batch at the - * earlier of: measurements completion / timeout - * expiration. - */ -enum iwl_tof_response_mode { - IWL_MVM_TOF_RESPOSE_ASAP = 1, - IWL_MVM_TOF_RESPOSE_TIMEOUT, - IWL_MVM_TOF_RESPOSE_COMPLETE, -}; - -/** - * struct iwl_tof_range_req_cmd - start measurement cmd - * @request_id: A Token incremented per request. The same Token will be - * sent back in the range response - * @initiator: 0- NW initiated, 1 - Client Initiated - * @one_sided_los_disable: '0'- run ML-Algo for both ToF/OneSided, - * '1' - run ML-Algo for ToF only - * @req_timeout: Requested timeout of the response in units of 100ms. - * This is equivalent to the session time configured to the - * LMAC in Initiator Request - * @report_policy: Supported partially for this release: For current release - - * the range report will be uploaded as a batch when ready or - * when the session is done (successfully / partially). - * one of iwl_tof_response_mode. - * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) - * @macaddr_random: '0' Use default source MAC address (i.e. p2_p), - * '1' Use MAC Address randomization according to the below - * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template. - * Bits set to 1 shall be randomized by the UMAC - * @ap: per-AP request data - */ -struct iwl_tof_range_req_cmd { - __le32 sub_grp_cmd_id; - u8 request_id; - u8 initiator; - u8 one_sided_los_disable; - u8 req_timeout; - u8 report_policy; - u8 los_det_disable; - u8 num_of_ap; - u8 macaddr_random; - u8 macaddr_template[ETH_ALEN]; - u8 macaddr_mask[ETH_ALEN]; - struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; -} __packed; - -/** - * struct iwl_tof_gen_resp_cmd - generic ToF response - */ -struct iwl_tof_gen_resp_cmd { - __le32 sub_grp_cmd_id; - u8 data[]; -} __packed; - -/** - * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response) - * @bssid: BSSID of the AP - * @measure_status: current APs measurement status, one of - * &enum iwl_tof_entry_status. - * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz - * @rtt: The Round Trip Time that took for the last measurement for - * current AP [nSec] - * @rtt_variance: The Variance of the RTT values measured for current AP - * @rtt_spread: The Difference between the maximum and the minimum RTT - * values measured for current AP in the current session [nsec] - * @rssi: RSSI as uploaded in the Channel Estimation notification - * @rssi_spread: The Difference between the maximum and the minimum RSSI values - * measured for current AP in the current session - * @reserved: reserved - * @range: Measured range [cm] - * @range_variance: Measured range variance [cm] - * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was - * uploaded by the LMAC - */ -struct iwl_tof_range_rsp_ap_entry_ntfy { - u8 bssid[ETH_ALEN]; - u8 measure_status; - u8 measure_bw; - __le32 rtt; - __le32 rtt_variance; - __le32 rtt_spread; - s8 rssi; - u8 rssi_spread; - __le16 reserved; - __le32 range; - __le32 range_variance; - __le32 timestamp; -} __packed; - -/** - * struct iwl_tof_range_rsp_ntfy - - * @request_id: A Token ID of the corresponding Range request - * @request_status: status of current measurement session - * @last_in_batch: reprot policy (when not all responses are uploaded at once) - * @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) - * @ap: per-AP data - */ -struct iwl_tof_range_rsp_ntfy { - u8 request_id; - u8 request_status; - u8 last_in_batch; - u8 num_of_aps; - struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS]; -} __packed; - -#define IWL_MVM_TOF_MCSI_BUF_SIZE (245) -/** - * struct iwl_tof_mcsi_notif - used for debug - * @token: token ID for the current session - * @role: '0' - initiator, '1' - responder - * @reserved: reserved - * @initiator_bssid: initiator machine - * @responder_bssid: responder machine - * @mcsi_buffer: debug data - */ -struct iwl_tof_mcsi_notif { - u8 token; - u8 role; - __le16 reserved; - u8 initiator_bssid[ETH_ALEN]; - u8 responder_bssid[ETH_ALEN]; - u8 mcsi_buffer[IWL_MVM_TOF_MCSI_BUF_SIZE * 4]; -} __packed; - -/** - * struct iwl_tof_neighbor_report_notif - * @bssid: BSSID of the AP which sent the report - * @request_token: same token as the corresponding request - * @status: - * @report_ie_len: the length of the response frame starting from the Element ID - * @data: the IEs - */ -struct iwl_tof_neighbor_report { - u8 bssid[ETH_ALEN]; - u8 request_token; - u8 status; - __le16 report_ie_len; - u8 data[]; -} __packed; - -/** - * struct iwl_tof_range_abort_cmd - * @request_id: corresponds to a range request - * @reserved: reserved - */ -struct iwl_tof_range_abort_cmd { - __le32 sub_grp_cmd_id; - u8 request_id; - u8 reserved[3]; -} __packed; - -#endif diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 81f557c0b58d..dfe02bdb7481 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -303,7 +303,6 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory * @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan. * @IWL_UCODE_TLV_CAPA_BEAMFORMER: supports Beamformer - * @IWL_UCODE_TLV_CAPA_TOF_SUPPORT: supports Time of Flight (802.11mc FTM) * @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current * tx power value into TPC Report action frame and Link Measurement Report @@ -369,7 +368,6 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_LAR_SUPPORT = (__force iwl_ucode_tlv_capa_t)1, IWL_UCODE_TLV_CAPA_UMAC_SCAN = (__force iwl_ucode_tlv_capa_t)2, IWL_UCODE_TLV_CAPA_BEAMFORMER = (__force iwl_ucode_tlv_capa_t)3, - IWL_UCODE_TLV_CAPA_TOF_SUPPORT = (__force iwl_ucode_tlv_capa_t)5, IWL_UCODE_TLV_CAPA_TDLS_SUPPORT = (__force iwl_ucode_tlv_capa_t)6, IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = (__force iwl_ucode_tlv_capa_t)8, IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = (__force iwl_ucode_tlv_capa_t)9, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile index 9ffd21918b5a..87373b099fd9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile @@ -7,7 +7,6 @@ iwlmvm-y += power.o coex.o iwlmvm-y += tt.o offloading.o tdls.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o -iwlmvm-y += tof.o iwlmvm-$(CONFIG_PM) += d3.o ccflags-y += -I$(src)/../ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 33b0af24a537..1c0f84049573 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -60,7 +60,6 @@ * *****************************************************************************/ #include "mvm.h" -#include "fw/api/tof.h" #include "debugfs.h" static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, @@ -523,751 +522,6 @@ static ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } -static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif, - char *buf, - size_t count, loff_t *ppos) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - u32 value; - int ret = -EINVAL; - char *data; - - mutex_lock(&mvm->mutex); - - data = iwl_dbgfs_is_match("tof_disabled=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.tof_cfg.tof_disabled = value; - goto out; - } - - data = iwl_dbgfs_is_match("one_sided_disabled=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.tof_cfg.one_sided_disabled = value; - goto out; - } - - data = iwl_dbgfs_is_match("is_debug_mode=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.tof_cfg.is_debug_mode = value; - goto out; - } - - data = iwl_dbgfs_is_match("is_buf=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.tof_cfg.is_buf_required = value; - goto out; - } - - data = iwl_dbgfs_is_match("send_tof_cfg=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) { - ret = iwl_mvm_tof_config_cmd(mvm); - goto out; - } - } - -out: - mutex_unlock(&mvm->mutex); - - return ret ?: count; -} - -static ssize_t iwl_dbgfs_tof_enable_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct iwl_tof_config_cmd *cmd; - - cmd = &mvm->tof_data.tof_cfg; - - mutex_lock(&mvm->mutex); - - pos += scnprintf(buf + pos, bufsz - pos, "tof_disabled = %d\n", - cmd->tof_disabled); - pos += scnprintf(buf + pos, bufsz - pos, "one_sided_disabled = %d\n", - cmd->one_sided_disabled); - pos += scnprintf(buf + pos, bufsz - pos, "is_debug_mode = %d\n", - cmd->is_debug_mode); - pos += scnprintf(buf + pos, bufsz - pos, "is_buf_required = %d\n", - cmd->is_buf_required); - - mutex_unlock(&mvm->mutex); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, - char *buf, - size_t count, loff_t *ppos) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - u32 value; - int ret = 0; - char *data; - - mutex_lock(&mvm->mutex); - - data = iwl_dbgfs_is_match("burst_period=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (!ret) - mvm->tof_data.responder_cfg.burst_period = - cpu_to_le16(value); - goto out; - } - - data = iwl_dbgfs_is_match("min_delta_ftm=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.min_delta_ftm = value; - goto out; - } - - data = iwl_dbgfs_is_match("burst_duration=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.burst_duration = value; - goto out; - } - - data = iwl_dbgfs_is_match("num_of_burst_exp=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.num_of_burst_exp = value; - goto out; - } - - data = iwl_dbgfs_is_match("abort_responder=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.abort_responder = value; - goto out; - } - - data = iwl_dbgfs_is_match("get_ch_est=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.get_ch_est = value; - goto out; - } - - data = iwl_dbgfs_is_match("recv_sta_req_params=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.recv_sta_req_params = value; - goto out; - } - - data = iwl_dbgfs_is_match("channel_num=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.channel_num = value; - goto out; - } - - data = iwl_dbgfs_is_match("bandwidth=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.bandwidth = value; - goto out; - } - - data = iwl_dbgfs_is_match("rate=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.rate = value; - goto out; - } - - data = iwl_dbgfs_is_match("bssid=", buf); - if (data) { - u8 *mac = mvm->tof_data.responder_cfg.bssid; - - if (!mac_pton(data, mac)) { - ret = -EINVAL; - goto out; - } - } - - data = iwl_dbgfs_is_match("tsf_timer_offset_msecs=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.tsf_timer_offset_msecs = - cpu_to_le16(value); - goto out; - } - - data = iwl_dbgfs_is_match("toa_offset=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.toa_offset = - cpu_to_le16(value); - goto out; - } - - data = iwl_dbgfs_is_match("center_freq=", buf); - if (data) { - struct iwl_tof_responder_config_cmd *cmd = - &mvm->tof_data.responder_cfg; - - ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) { - enum nl80211_band band = (cmd->channel_num <= 14) ? - NL80211_BAND_2GHZ : - NL80211_BAND_5GHZ; - struct ieee80211_channel chn = { - .band = band, - .center_freq = ieee80211_channel_to_frequency( - cmd->channel_num, band), - }; - struct cfg80211_chan_def chandef = { - .chan = &chn, - .center_freq1 = - ieee80211_channel_to_frequency(value, - band), - }; - - cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef); - } - goto out; - } - - data = iwl_dbgfs_is_match("ftm_per_burst=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.ftm_per_burst = value; - goto out; - } - - data = iwl_dbgfs_is_match("ftm_resp_ts_avail=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.ftm_resp_ts_avail = value; - goto out; - } - - data = iwl_dbgfs_is_match("asap_mode=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.asap_mode = value; - goto out; - } - - data = iwl_dbgfs_is_match("send_responder_cfg=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) { - ret = iwl_mvm_tof_responder_cmd(mvm, vif); - goto out; - } - } - -out: - mutex_unlock(&mvm->mutex); - - return ret ?: count; -} - -static ssize_t iwl_dbgfs_tof_responder_params_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct iwl_tof_responder_config_cmd *cmd; - - cmd = &mvm->tof_data.responder_cfg; - - mutex_lock(&mvm->mutex); - - pos += scnprintf(buf + pos, bufsz - pos, "burst_period = %d\n", - le16_to_cpu(cmd->burst_period)); - pos += scnprintf(buf + pos, bufsz - pos, "burst_duration = %d\n", - cmd->burst_duration); - pos += scnprintf(buf + pos, bufsz - pos, "bandwidth = %d\n", - cmd->bandwidth); - pos += scnprintf(buf + pos, bufsz - pos, "channel_num = %d\n", - cmd->channel_num); - pos += scnprintf(buf + pos, bufsz - pos, "ctrl_ch_position = 0x%x\n", - cmd->ctrl_ch_position); - pos += scnprintf(buf + pos, bufsz - pos, "bssid = %pM\n", - cmd->bssid); - pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %d\n", - cmd->min_delta_ftm); - pos += scnprintf(buf + pos, bufsz - pos, "num_of_burst_exp = %d\n", - cmd->num_of_burst_exp); - pos += scnprintf(buf + pos, bufsz - pos, "rate = %d\n", cmd->rate); - pos += scnprintf(buf + pos, bufsz - pos, "abort_responder = %d\n", - cmd->abort_responder); - pos += scnprintf(buf + pos, bufsz - pos, "get_ch_est = %d\n", - cmd->get_ch_est); - pos += scnprintf(buf + pos, bufsz - pos, "recv_sta_req_params = %d\n", - cmd->recv_sta_req_params); - pos += scnprintf(buf + pos, bufsz - pos, "ftm_per_burst = %d\n", - cmd->ftm_per_burst); - pos += scnprintf(buf + pos, bufsz - pos, "ftm_resp_ts_avail = %d\n", - cmd->ftm_resp_ts_avail); - pos += scnprintf(buf + pos, bufsz - pos, "asap_mode = %d\n", - cmd->asap_mode); - pos += scnprintf(buf + pos, bufsz - pos, - "tsf_timer_offset_msecs = %d\n", - le16_to_cpu(cmd->tsf_timer_offset_msecs)); - pos += scnprintf(buf + pos, bufsz - pos, "toa_offset = %d\n", - le16_to_cpu(cmd->toa_offset)); - - mutex_unlock(&mvm->mutex); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, - char *buf, size_t count, - loff_t *ppos) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - u32 value; - int ret = 0; - char *data; - - mutex_lock(&mvm->mutex); - - data = iwl_dbgfs_is_match("request_id=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req.request_id = value; - goto out; - } - - data = iwl_dbgfs_is_match("initiator=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req.initiator = value; - goto out; - } - - data = iwl_dbgfs_is_match("one_sided_los_disable=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req.one_sided_los_disable = value; - goto out; - } - - data = iwl_dbgfs_is_match("req_timeout=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req.req_timeout = value; - goto out; - } - - data = iwl_dbgfs_is_match("report_policy=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req.report_policy = value; - goto out; - } - - data = iwl_dbgfs_is_match("macaddr_random=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req.macaddr_random = value; - goto out; - } - - data = iwl_dbgfs_is_match("num_of_ap=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req.num_of_ap = value; - goto out; - } - - data = iwl_dbgfs_is_match("macaddr_template=", buf); - if (data) { - u8 mac[ETH_ALEN]; - - if (!mac_pton(data, mac)) { - ret = -EINVAL; - goto out; - } - memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN); - goto out; - } - - data = iwl_dbgfs_is_match("macaddr_mask=", buf); - if (data) { - u8 mac[ETH_ALEN]; - - if (!mac_pton(data, mac)) { - ret = -EINVAL; - goto out; - } - memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN); - goto out; - } - - data = iwl_dbgfs_is_match("ap=", buf); - if (data) { - struct iwl_tof_range_req_ap_entry ap = {}; - int size = sizeof(struct iwl_tof_range_req_ap_entry); - u16 burst_period; - u8 *mac = ap.bssid; - unsigned int i; - - if (sscanf(data, "%u %hhd %hhd %hhd" - "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx" - "%hhd %hhd %hd" - "%hhd %hhd %d" - "%hhx %hhd %hhd %hhd", - &i, &ap.channel_num, &ap.bandwidth, - &ap.ctrl_ch_position, - mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5, - &ap.measure_type, &ap.num_of_bursts, - &burst_period, - &ap.samples_per_burst, &ap.retries_per_sample, - &ap.tsf_delta, &ap.location_req, &ap.asap_mode, - &ap.enable_dyn_ack, &ap.rssi) != 20) { - ret = -EINVAL; - goto out; - } - if (i >= IWL_MVM_TOF_MAX_APS) { - IWL_ERR(mvm, "Invalid AP index %d\n", i); - ret = -EINVAL; - goto out; - } - - ap.burst_period = cpu_to_le16(burst_period); - - memcpy(&mvm->tof_data.range_req.ap[i], &ap, size); - goto out; - } - - data = iwl_dbgfs_is_match("send_range_request=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) - ret = iwl_mvm_tof_range_request_cmd(mvm, vif); - goto out; - } - - ret = -EINVAL; -out: - mutex_unlock(&mvm->mutex); - return ret ?: count; -} - -static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - char buf[512]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct iwl_tof_range_req_cmd *cmd; - int i; - - cmd = &mvm->tof_data.range_req; - - mutex_lock(&mvm->mutex); - - pos += scnprintf(buf + pos, bufsz - pos, "request_id= %d\n", - cmd->request_id); - pos += scnprintf(buf + pos, bufsz - pos, "initiator= %d\n", - cmd->initiator); - pos += scnprintf(buf + pos, bufsz - pos, "one_sided_los_disable = %d\n", - cmd->one_sided_los_disable); - pos += scnprintf(buf + pos, bufsz - pos, "req_timeout= %d\n", - cmd->req_timeout); - pos += scnprintf(buf + pos, bufsz - pos, "report_policy= %d\n", - cmd->report_policy); - pos += scnprintf(buf + pos, bufsz - pos, "macaddr_random= %d\n", - cmd->macaddr_random); - pos += scnprintf(buf + pos, bufsz - pos, "macaddr_template= %pM\n", - cmd->macaddr_template); - pos += scnprintf(buf + pos, bufsz - pos, "macaddr_mask= %pM\n", - cmd->macaddr_mask); - pos += scnprintf(buf + pos, bufsz - pos, "num_of_ap= %d\n", - cmd->num_of_ap); - for (i = 0; i < cmd->num_of_ap; i++) { - struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i]; - - pos += scnprintf(buf + pos, bufsz - pos, - "ap %.2d: channel_num=%hhd bw=%hhd" - " control=%hhd bssid=%pM type=%hhd" - " num_of_bursts=%hhd burst_period=%hd ftm=%hhd" - " retries=%hhd tsf_delta=%d" - " tsf_delta_direction=%hhd location_req=0x%hhx " - " asap=%hhd enable=%hhd rssi=%hhd\n", - i, ap->channel_num, ap->bandwidth, - ap->ctrl_ch_position, ap->bssid, - ap->measure_type, ap->num_of_bursts, - ap->burst_period, ap->samples_per_burst, - ap->retries_per_sample, ap->tsf_delta, - ap->tsf_delta_direction, - ap->location_req, ap->asap_mode, - ap->enable_dyn_ack, ap->rssi); - } - - mutex_unlock(&mvm->mutex); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif, - char *buf, - size_t count, loff_t *ppos) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - u32 value; - int ret = 0; - char *data; - - mutex_lock(&mvm->mutex); - - data = iwl_dbgfs_is_match("tsf_timer_offset_msec=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req_ext.tsf_timer_offset_msec = - cpu_to_le16(value); - goto out; - } - - data = iwl_dbgfs_is_match("min_delta_ftm=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req_ext.min_delta_ftm = value; - goto out; - } - - data = iwl_dbgfs_is_match("ftm_format_and_bw20M=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req_ext.ftm_format_and_bw20M = - value; - goto out; - } - - data = iwl_dbgfs_is_match("ftm_format_and_bw40M=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req_ext.ftm_format_and_bw40M = - value; - goto out; - } - - data = iwl_dbgfs_is_match("ftm_format_and_bw80M=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.range_req_ext.ftm_format_and_bw80M = - value; - goto out; - } - - data = iwl_dbgfs_is_match("send_range_req_ext=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) - ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif); - goto out; - } - - ret = -EINVAL; -out: - mutex_unlock(&mvm->mutex); - return ret ?: count; -} - -static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - struct iwl_tof_range_req_ext_cmd *cmd; - - cmd = &mvm->tof_data.range_req_ext; - - mutex_lock(&mvm->mutex); - - pos += scnprintf(buf + pos, bufsz - pos, - "tsf_timer_offset_msec = %hd\n", - cmd->tsf_timer_offset_msec); - pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n", - cmd->min_delta_ftm); - pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw20M = %hhd\n", - cmd->ftm_format_and_bw20M); - pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw40M = %hhd\n", - cmd->ftm_format_and_bw40M); - pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw80M = %hhd\n", - cmd->ftm_format_and_bw80M); - - mutex_unlock(&mvm->mutex); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif, - char *buf, - size_t count, loff_t *ppos) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - u32 value; - int abort_id, ret = 0; - char *data; - - mutex_lock(&mvm->mutex); - - data = iwl_dbgfs_is_match("abort_id=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.last_abort_id = value; - goto out; - } - - data = iwl_dbgfs_is_match("send_range_abort=", buf); - if (data) { - ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) { - abort_id = mvm->tof_data.last_abort_id; - ret = iwl_mvm_tof_range_abort_cmd(mvm, abort_id); - goto out; - } - } - -out: - mutex_unlock(&mvm->mutex); - return ret ?: count; -} - -static ssize_t iwl_dbgfs_tof_range_abort_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - char buf[32]; - int pos = 0; - const size_t bufsz = sizeof(buf); - int last_abort_id; - - mutex_lock(&mvm->mutex); - last_abort_id = mvm->tof_data.last_abort_id; - mutex_unlock(&mvm->mutex); - - pos += scnprintf(buf + pos, bufsz - pos, "last_abort_id = %d\n", - last_abort_id); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ieee80211_vif *vif = file->private_data; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_mvm *mvm = mvmvif->mvm; - char *buf; - int pos = 0; - const size_t bufsz = sizeof(struct iwl_tof_range_rsp_ntfy) + 256; - struct iwl_tof_range_rsp_ntfy *cmd; - int i, ret; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - mutex_lock(&mvm->mutex); - cmd = &mvm->tof_data.range_resp; - - pos += scnprintf(buf + pos, bufsz - pos, "request_id = %d\n", - cmd->request_id); - pos += scnprintf(buf + pos, bufsz - pos, "status = %d\n", - cmd->request_status); - pos += scnprintf(buf + pos, bufsz - pos, "last_in_batch = %d\n", - cmd->last_in_batch); - pos += scnprintf(buf + pos, bufsz - pos, "num_of_aps = %d\n", - cmd->num_of_aps); - for (i = 0; i < cmd->num_of_aps; i++) { - struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i]; - - pos += scnprintf(buf + pos, bufsz - pos, - "ap %.2d: bssid=%pM status=%hhd bw=%hhd" - " rtt=%d rtt_var=%d rtt_spread=%d" - " rssi=%hhd rssi_spread=%hhd" - " range=%d range_var=%d" - " time_stamp=%d\n", - i, ap->bssid, ap->measure_status, - ap->measure_bw, - ap->rtt, ap->rtt_variance, ap->rtt_spread, - ap->rssi, ap->rssi_spread, ap->range, - ap->range_variance, ap->timestamp); - } - mutex_unlock(&mvm->mutex); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf, size_t count, loff_t *ppos) { @@ -1458,12 +712,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256); MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10); MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20); MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_enable, 32); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_request, 512); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext, 32); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_abort, 32); -MVM_DEBUGFS_READ_FILE_OPS(tof_range_response); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32); MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32); MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff); @@ -1506,24 +754,6 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) mvmvif == mvm->bf_allowed_vif) MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, 0600); - if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT) && - !vif->p2p && (vif->type != NL80211_IFTYPE_P2P_DEVICE)) { - if (IWL_MVM_TOF_IS_RESPONDER && vif->type == NL80211_IFTYPE_AP) - MVM_DEBUGFS_ADD_FILE_VIF(tof_responder_params, - mvmvif->dbgfs_dir, 0600); - - MVM_DEBUGFS_ADD_FILE_VIF(tof_range_request, mvmvif->dbgfs_dir, - 0600); - MVM_DEBUGFS_ADD_FILE_VIF(tof_range_req_ext, mvmvif->dbgfs_dir, - 0600); - MVM_DEBUGFS_ADD_FILE_VIF(tof_enable, mvmvif->dbgfs_dir, - 0600); - MVM_DEBUGFS_ADD_FILE_VIF(tof_range_abort, mvmvif->dbgfs_dir, - 0600); - MVM_DEBUGFS_ADD_FILE_VIF(tof_range_response, mvmvif->dbgfs_dir, - 0400); - } - /* * Create symlink for convenience pointing to interface specific * debugfs entries for the driver. For example, under diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 143c7fcaea41..851bfb259f10 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -89,7 +91,6 @@ #include "fw/api/sf.h" #include "fw/api/sta.h" #include "fw/api/stats.h" -#include "fw/api/tof.h" #include "fw/api/tx.h" #endif /* __fw_api_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index a289b9488c03..5d28080e257e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -83,7 +83,6 @@ #include "sta.h" #include "fw-api.h" #include "constants.h" -#include "tof.h" #include "fw/runtime.h" #include "fw/dbg.h" #include "fw/acpi.h" @@ -1124,7 +1123,6 @@ struct iwl_mvm { u32 ciphers[IWL_MVM_NUM_CIPHERS]; struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; - struct iwl_mvm_tof_data tof_data; struct ieee80211_vif *nan_vif; #define IWL_MAX_BAID 32 @@ -1184,7 +1182,6 @@ enum iwl_mvm_init_status { IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE = BIT(0), IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE = BIT(1), IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE = BIT(2), - IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE = BIT(3), }; static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index ee2ef3f0042c..93b7cc5910fe 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -301,8 +301,6 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER_ASYNC_LOCKED), RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, RX_HANDLER_SYNC), - RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler, - RX_HANDLER_ASYNC_LOCKED), RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF, iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC), RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, @@ -329,8 +327,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { HCMD_NAME(SCAN_REQ_UMAC), HCMD_NAME(SCAN_ABORT_UMAC), HCMD_NAME(SCAN_COMPLETE_UMAC), - HCMD_NAME(TOF_CMD), - HCMD_NAME(TOF_NOTIFICATION), HCMD_NAME(BA_WINDOW_STATUS_NOTIFICATION_ID), HCMD_NAME(ADD_STA_KEY), HCMD_NAME(ADD_STA), @@ -846,8 +842,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, if (iwl_mvm_is_d0i3_supported(mvm)) iwl_trans_unref(mvm->trans); - iwl_mvm_tof_init(mvm); - iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx); return op_mode; @@ -913,8 +907,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) cancel_delayed_work_sync(&mvm->tcm.work); - iwl_mvm_tof_clean(mvm); - iwl_fw_runtime_free(&mvm->fwrt); mutex_destroy(&mvm->mutex); mutex_destroy(&mvm->d0i3_suspend_mutex); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tof.c b/drivers/net/wireless/intel/iwlwifi/mvm/tof.c deleted file mode 100644 index 01e0a999063b..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tof.c +++ /dev/null @@ -1,305 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2015 Intel Deutschland GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2015 Intel Deutschland GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#include "mvm.h" -#include "fw/api/tof.h" - -#define IWL_MVM_TOF_RANGE_REQ_MAX_ID 256 - -void iwl_mvm_tof_init(struct iwl_mvm *mvm) -{ - struct iwl_mvm_tof_data *tof_data = &mvm->tof_data; - - if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) - return; - - memset(tof_data, 0, sizeof(*tof_data)); - - tof_data->tof_cfg.sub_grp_cmd_id = cpu_to_le32(TOF_CONFIG_CMD); - -#ifdef CONFIG_IWLWIFI_DEBUGFS - if (IWL_MVM_TOF_IS_RESPONDER) { - tof_data->responder_cfg.sub_grp_cmd_id = - cpu_to_le32(TOF_RESPONDER_CONFIG_CMD); - tof_data->responder_cfg.sta_id = IWL_MVM_INVALID_STA; - } -#endif - - tof_data->range_req.sub_grp_cmd_id = cpu_to_le32(TOF_RANGE_REQ_CMD); - tof_data->range_req.req_timeout = 1; - tof_data->range_req.initiator = 1; - tof_data->range_req.report_policy = 3; - - tof_data->range_req_ext.sub_grp_cmd_id = - cpu_to_le32(TOF_RANGE_REQ_EXT_CMD); - - mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID; - mvm->init_status |= IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE; -} - -void iwl_mvm_tof_clean(struct iwl_mvm *mvm) -{ - struct iwl_mvm_tof_data *tof_data = &mvm->tof_data; - - if (!fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_TOF_SUPPORT) || - !(mvm->init_status & IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE)) - return; - - memset(tof_data, 0, sizeof(*tof_data)); - mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID; - mvm->init_status &= ~IWL_MVM_INIT_STATUS_TOF_INIT_COMPLETE; -} - -static void iwl_tof_iterator(void *_data, u8 *mac, - struct ieee80211_vif *vif) -{ - bool *enabled = _data; - - /* non bss vif exists */ - if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) - *enabled = false; -} - -int iwl_mvm_tof_config_cmd(struct iwl_mvm *mvm) -{ - struct iwl_tof_config_cmd *cmd = &mvm->tof_data.tof_cfg; - bool enabled; - - lockdep_assert_held(&mvm->mutex); - - if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) - return -EINVAL; - - ieee80211_iterate_active_interfaces_atomic(mvm->hw, - IEEE80211_IFACE_ITER_NORMAL, - iwl_tof_iterator, &enabled); - if (!enabled) { - IWL_DEBUG_INFO(mvm, "ToF is not supported (non bss vif)\n"); - return -EINVAL; - } - - mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID; - return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD, - IWL_ALWAYS_LONG_GROUP, 0), - 0, sizeof(*cmd), cmd); -} - -int iwl_mvm_tof_range_abort_cmd(struct iwl_mvm *mvm, u8 id) -{ - struct iwl_tof_range_abort_cmd cmd = { - .sub_grp_cmd_id = cpu_to_le32(TOF_RANGE_ABORT_CMD), - .request_id = id, - }; - - lockdep_assert_held(&mvm->mutex); - - if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) - return -EINVAL; - - if (id != mvm->tof_data.active_range_request) { - IWL_ERR(mvm, "Invalid range request id %d (active %d)\n", - id, mvm->tof_data.active_range_request); - return -EINVAL; - } - - /* after abort is sent there's no active request anymore */ - mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID; - - return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD, - IWL_ALWAYS_LONG_GROUP, 0), - 0, sizeof(cmd), &cmd); -} - -#ifdef CONFIG_IWLWIFI_DEBUGFS -int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) -{ - struct iwl_tof_responder_config_cmd *cmd = &mvm->tof_data.responder_cfg; - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - - lockdep_assert_held(&mvm->mutex); - - if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) - return -EINVAL; - - if (vif->p2p || vif->type != NL80211_IFTYPE_AP || - !mvmvif->ap_ibss_active) { - IWL_ERR(mvm, "Cannot start responder, not in AP mode\n"); - return -EIO; - } - - cmd->sta_id = mvmvif->bcast_sta.sta_id; - memcpy(cmd->bssid, vif->addr, ETH_ALEN); - return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD, - IWL_ALWAYS_LONG_GROUP, 0), - 0, sizeof(*cmd), cmd); -} -#endif - -int iwl_mvm_tof_range_request_cmd(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) -{ - struct iwl_host_cmd cmd = { - .id = iwl_cmd_id(TOF_CMD, IWL_ALWAYS_LONG_GROUP, 0), - .len = { sizeof(mvm->tof_data.range_req), }, - /* no copy because of the command size */ - .dataflags = { IWL_HCMD_DFL_NOCOPY, }, - }; - - lockdep_assert_held(&mvm->mutex); - - if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) - return -EINVAL; - - if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) { - IWL_ERR(mvm, "Cannot send range request, not STA mode\n"); - return -EIO; - } - - /* nesting of range requests is not supported in FW */ - if (mvm->tof_data.active_range_request != - IWL_MVM_TOF_RANGE_REQ_MAX_ID) { - IWL_ERR(mvm, "Cannot send range req, already active req %d\n", - mvm->tof_data.active_range_request); - return -EIO; - } - - mvm->tof_data.active_range_request = mvm->tof_data.range_req.request_id; - - cmd.data[0] = &mvm->tof_data.range_req; - return iwl_mvm_send_cmd(mvm, &cmd); -} - -int iwl_mvm_tof_range_request_ext_cmd(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) -{ - lockdep_assert_held(&mvm->mutex); - - if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) - return -EINVAL; - - if (ieee80211_vif_type_p2p(vif) != NL80211_IFTYPE_STATION) { - IWL_ERR(mvm, "Cannot send ext range req, not in STA mode\n"); - return -EIO; - } - - return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD, - IWL_ALWAYS_LONG_GROUP, 0), - 0, sizeof(mvm->tof_data.range_req_ext), - &mvm->tof_data.range_req_ext); -} - -static int iwl_mvm_tof_range_resp(struct iwl_mvm *mvm, void *data) -{ - struct iwl_tof_range_rsp_ntfy *resp = (void *)data; - - if (resp->request_id != mvm->tof_data.active_range_request) { - IWL_ERR(mvm, "Request id mismatch, got %d, active %d\n", - resp->request_id, mvm->tof_data.active_range_request); - return -EIO; - } - - memcpy(&mvm->tof_data.range_resp, resp, - sizeof(struct iwl_tof_range_rsp_ntfy)); - mvm->tof_data.active_range_request = IWL_MVM_TOF_RANGE_REQ_MAX_ID; - - return 0; -} - -static int iwl_mvm_tof_mcsi_notif(struct iwl_mvm *mvm, void *data) -{ - struct iwl_tof_mcsi_notif *resp = (struct iwl_tof_mcsi_notif *)data; - - IWL_DEBUG_INFO(mvm, "MCSI notification, token %d\n", resp->token); - return 0; -} - -static int iwl_mvm_tof_nb_report_notif(struct iwl_mvm *mvm, void *data) -{ - struct iwl_tof_neighbor_report *report = - (struct iwl_tof_neighbor_report *)data; - - IWL_DEBUG_INFO(mvm, "NB report, bssid %pM, token %d, status 0x%x\n", - report->bssid, report->request_token, report->status); - return 0; -} - -void iwl_mvm_tof_resp_handler(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_tof_gen_resp_cmd *resp = (void *)pkt->data; - - lockdep_assert_held(&mvm->mutex); - - switch (le32_to_cpu(resp->sub_grp_cmd_id)) { - case TOF_RANGE_RESPONSE_NOTIF: - iwl_mvm_tof_range_resp(mvm, resp->data); - break; - case TOF_MCSI_DEBUG_NOTIF: - iwl_mvm_tof_mcsi_notif(mvm, resp->data); - break; - case TOF_NEIGHBOR_REPORT_RSP_NOTIF: - iwl_mvm_tof_nb_report_notif(mvm, resp->data); - break; - default: - IWL_ERR(mvm, "Unknown sub-group command 0x%x\n", - resp->sub_grp_cmd_id); - break; - } -} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tof.h b/drivers/net/wireless/intel/iwlwifi/mvm/tof.h deleted file mode 100644 index 8138d0606c52..000000000000 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tof.h +++ /dev/null @@ -1,89 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2015 Intel Deutschland GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * The full GNU General Public License is included in this distribution - * in the file called COPYING. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2015 Intel Deutschland GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __tof_h__ -#define __tof_h__ - -#include "fw/api/tof.h" - -struct iwl_mvm_tof_data { - struct iwl_tof_config_cmd tof_cfg; - struct iwl_tof_range_req_cmd range_req; - struct iwl_tof_range_req_ext_cmd range_req_ext; -#ifdef CONFIG_IWLWIFI_DEBUGFS - struct iwl_tof_responder_config_cmd responder_cfg; -#endif - struct iwl_tof_range_rsp_ntfy range_resp; - u8 last_abort_id; - u16 active_range_request; -}; - -void iwl_mvm_tof_init(struct iwl_mvm *mvm); -void iwl_mvm_tof_clean(struct iwl_mvm *mvm); -int iwl_mvm_tof_config_cmd(struct iwl_mvm *mvm); -int iwl_mvm_tof_range_abort_cmd(struct iwl_mvm *mvm, u8 id); -int iwl_mvm_tof_range_request_cmd(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); -void iwl_mvm_tof_resp_handler(struct iwl_mvm *mvm, - struct iwl_rx_cmd_buffer *rxb); -int iwl_mvm_tof_range_request_ext_cmd(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); -#ifdef CONFIG_IWLWIFI_DEBUGFS -int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); -#endif -#endif /* __tof_h__ */ -- cgit v1.2.3 From 4841914ef44066f2dce153770dd828ef307f28bb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 9 Nov 2018 11:03:29 +0100 Subject: iwlwifi: dvm: remove useless condition If we're in the else branch of checking "tt->state == IWL_TI_CT_KILL" so there's no point in checking "tt->state != IWL_TI_CT_KILL" again. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/dvm/tt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c index 4de2727ac63e..a156dcf5b7d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tt.c @@ -1,6 +1,7 @@ /****************************************************************************** * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. + * Copyright (C) 2018 Intel Corporation * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -325,9 +326,9 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) iwl_prepare_ct_kill_task(priv); tt->state = old_state; } - } else if (old_state == IWL_TI_CT_KILL && - tt->state != IWL_TI_CT_KILL) + } else if (old_state == IWL_TI_CT_KILL) { iwl_perform_ct_kill_task(priv, false); + } IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n", tt->state); IWL_DEBUG_TEMP(priv, "Power Index change to %u\n", -- cgit v1.2.3 From 93079fd5c0597a89f6fa3a1a3334739de10d6b07 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 9 Nov 2018 10:58:53 +0100 Subject: iwlwifi: pcie: use u32* argument to iwl_trans_get_fw_monitor_len() That's what we pass, and we don't want/need any negative values. Found by sparse/smatch. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 472a85d9a358..f74281508197 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3114,7 +3114,7 @@ iwl_trans_pcie_dump_monitor(struct iwl_trans *trans, return len; } -static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, int *len) +static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len) { if (trans->num_blocks) { *len += sizeof(struct iwl_fw_error_dump_data) + -- cgit v1.2.3 From babea2d4fe76c6515da6231e8d940044bad686b1 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Sun, 4 Nov 2018 21:56:31 +0200 Subject: iwlwifi: mvm: Disconnect on large beacon loss Some buggy APs stop sending beacons, but continue to ack our null data packets or even run some traffic. It's better not to stick connected to such an AP forever, so disconnect after some larger beacon loss threshold is crossed. Signed-off-by: Andrei Otcheretianski Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 5 +++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index c868ebfa10ce..7cfdd07d8736 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1415,8 +1415,9 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, * TODO: the threshold should be adjusted based on latency conditions, * and/or in case of a CS flow on one of the other AP vifs. */ - if (le32_to_cpu(mb->consec_missed_beacons_since_last_rx) > - IWL_MVM_MISSED_BEACONS_THRESHOLD) + if (rx_missed_bcon > IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG) + iwl_mvm_connection_loss(mvm, vif, "missed beacons"); + else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD) ieee80211_beacon_loss(vif); trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5d28080e257e..55f08e433331 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -94,6 +94,8 @@ /* RSSI offset for WkP */ #define IWL_RSSI_OFFSET 50 #define IWL_MVM_MISSED_BEACONS_THRESHOLD 8 +#define IWL_MVM_MISSED_BEACONS_THRESHOLD_LONG 16 + /* A TimeUnit is 1024 microsecond */ #define MSEC_TO_TU(_msec) (_msec*1000/1024) -- cgit v1.2.3 From 6c161980ba482d063c6453a32924a706858043ea Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Oct 2018 10:29:31 +0100 Subject: iwlwifi: mvm: add location APIs Add the location/time-of-flight/FTM APIs that we'll use in follow-up patches to implement FTM responder and initiator. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/commands.h | 3 + .../net/wireless/intel/iwlwifi/fw/api/location.h | 691 +++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 17 + 4 files changed, 712 insertions(+) create mode 100644 drivers/net/wireless/intel/iwlwifi/fw/api/location.h (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index baba7bcee5fc..0290b333d860 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -77,6 +77,8 @@ * @DATA_PATH_GROUP: data path group, uses command IDs from * &enum iwl_data_path_subcmd_ids * @NAN_GROUP: NAN group, uses command IDs from &enum iwl_nan_subcmd_ids + * @LOCATION_GROUP: location group, uses command IDs from + * &enum iwl_location_subcmd_ids * @PROT_OFFLOAD_GROUP: protocol offload group, uses command IDs from * &enum iwl_prot_offload_subcmd_ids * @REGULATORY_AND_NVM_GROUP: regulatory/NVM group, uses command IDs from @@ -91,6 +93,7 @@ enum iwl_mvm_command_groups { PHY_OPS_GROUP = 0x4, DATA_PATH_GROUP = 0x5, NAN_GROUP = 0x7, + LOCATION_GROUP = 0x8, PROT_OFFLOAD_GROUP = 0xb, REGULATORY_AND_NVM_GROUP = 0xc, DEBUG_GROUP = 0xf, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h new file mode 100644 index 000000000000..0df0851b9513 --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -0,0 +1,691 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef __iwl_fw_api_location_h__ +#define __iwl_fw_api_location_h__ + +/** + * enum iwl_location_subcmd_ids - location group command IDs + */ +enum iwl_location_subcmd_ids { + /** + * @TOF_RANGE_REQ_CMD: TOF ranging request, + * uses &struct iwl_tof_range_req_cmd + */ + TOF_RANGE_REQ_CMD = 0x0, + /** + * @TOF_CONFIG_CMD: TOF configuration, uses &struct iwl_tof_config_cmd + */ + TOF_CONFIG_CMD = 0x1, + /** + * @TOF_RANGE_ABORT_CMD: abort ongoing ranging, uses + * &struct iwl_tof_range_abort_cmd + */ + TOF_RANGE_ABORT_CMD = 0x2, + /** + * @TOF_RANGE_REQ_EXT_CMD: TOF extended ranging config, + * uses &struct iwl_tof_range_request_ext_cmd + */ + TOF_RANGE_REQ_EXT_CMD = 0x3, + /** + * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration, + * uses &struct iwl_tof_responder_config_cmd + */ + TOF_RESPONDER_CONFIG_CMD = 0x4, + /** + * @TOF_RESPONDER_DYN_CONFIG_CMD: FTM dynamic configuration, + * uses &struct iwl_tof_responder_dyn_config_cmd + */ + TOF_RESPONDER_DYN_CONFIG_CMD = 0x5, + /** + * @TOF_LC_NOTIF: used for LCI/civic location, contains just + * the action frame + */ + TOF_LC_NOTIF = 0xFC, + /** + * @TOF_RESPONDER_STATS: FTM responder statistics notification, + * uses &struct iwl_ftm_responder_stats + */ + TOF_RESPONDER_STATS = 0xFD, + /** + * @TOF_MCSI_DEBUG_NOTIF: MCSI debug notification, uses + * &struct iwl_tof_mcsi_notif + */ + TOF_MCSI_DEBUG_NOTIF = 0xFE, + /** + * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using + * &struct iwl_tof_range_rsp_ntfy + */ + TOF_RANGE_RESPONSE_NOTIF = 0xFF, +}; + +/** + * struct iwl_tof_config_cmd - ToF configuration + * @tof_disabled: indicates if ToF is disabled (or not) + * @one_sided_disabled: indicates if one-sided is disabled (or not) + * @is_debug_mode: indiciates if debug mode is active + * @is_buf_required: indicates if channel estimation buffer is required + */ +struct iwl_tof_config_cmd { + u8 tof_disabled; + u8 one_sided_disabled; + u8 is_debug_mode; + u8 is_buf_required; +} __packed; + +/** + * enum iwl_tof_bandwidth - values for iwl_tof_range_req_ap_entry.bandwidth + * @IWL_TOF_BW_20_LEGACY: 20 MHz non-HT + * @IWL_TOF_BW_20_HT: 20 MHz HT + * @IWL_TOF_BW_40: 40 MHz + * @IWL_TOF_BW_80: 80 MHz + * @IWL_TOF_BW_160: 160 MHz + */ +enum iwl_tof_bandwidth { + IWL_TOF_BW_20_LEGACY, + IWL_TOF_BW_20_HT, + IWL_TOF_BW_40, + IWL_TOF_BW_80, + IWL_TOF_BW_160, +}; /* LOCAT_BW_TYPE_E */ + +/* + * enum iwl_tof_algo_type - Algorithym type for range measurement request + */ +enum iwl_tof_algo_type { + IWL_TOF_ALGO_TYPE_MAX_LIKE = 0, + IWL_TOF_ALGO_TYPE_LINEAR_REG = 1, + IWL_TOF_ALGO_TYPE_FFT = 2, + + /* Keep last */ + IWL_TOF_ALGO_TYPE_INVALID, +}; /* ALGO_TYPE_E */ + +/* + * enum iwl_tof_mcsi_ntfy - Enable/Disable MCSI notifications + */ +enum iwl_tof_mcsi_enable { + IWL_TOF_MCSI_DISABLED = 0, + IWL_TOF_MCSI_ENABLED = 1, +}; /* MCSI_ENABLE_E */ + +/** + * enum iwl_tof_responder_cmd_valid_field - valid fields in the responder cfg + * @IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO: channel info is valid + * @IWL_TOF_RESPONDER_CMD_VALID_TOA_OFFSET: ToA offset is valid + * @IWL_TOF_RESPONDER_CMD_VALID_COMMON_CALIB: common calibration mode is valid + * @IWL_TOF_RESPONDER_CMD_VALID_SPECIFIC_CALIB: spefici calibration mode is + * valid + * @IWL_TOF_RESPONDER_CMD_VALID_BSSID: BSSID is valid + * @IWL_TOF_RESPONDER_CMD_VALID_TX_ANT: TX antenna is valid + * @IWL_TOF_RESPONDER_CMD_VALID_ALGO_TYPE: algorithm type is valid + * @IWL_TOF_RESPONDER_CMD_VALID_NON_ASAP_SUPPORT: non-ASAP support is valid + * @IWL_TOF_RESPONDER_CMD_VALID_STATISTICS_REPORT_SUPPORT: statistics report + * support is valid + * @IWL_TOF_RESPONDER_CMD_VALID_MCSI_NOTIF_SUPPORT: MCSI notification support + * is valid + * @IWL_TOF_RESPONDER_CMD_VALID_FAST_ALGO_SUPPORT: fast algorithm support + * is valid + * @IWL_TOF_RESPONDER_CMD_VALID_RETRY_ON_ALGO_FAIL: retry on algorithm failure + * is valid + * @IWL_TOF_RESPONDER_CMD_VALID_STA_ID: station ID is valid + */ +enum iwl_tof_responder_cmd_valid_field { + IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO = BIT(0), + IWL_TOF_RESPONDER_CMD_VALID_TOA_OFFSET = BIT(1), + IWL_TOF_RESPONDER_CMD_VALID_COMMON_CALIB = BIT(2), + IWL_TOF_RESPONDER_CMD_VALID_SPECIFIC_CALIB = BIT(3), + IWL_TOF_RESPONDER_CMD_VALID_BSSID = BIT(4), + IWL_TOF_RESPONDER_CMD_VALID_TX_ANT = BIT(5), + IWL_TOF_RESPONDER_CMD_VALID_ALGO_TYPE = BIT(6), + IWL_TOF_RESPONDER_CMD_VALID_NON_ASAP_SUPPORT = BIT(7), + IWL_TOF_RESPONDER_CMD_VALID_STATISTICS_REPORT_SUPPORT = BIT(8), + IWL_TOF_RESPONDER_CMD_VALID_MCSI_NOTIF_SUPPORT = BIT(9), + IWL_TOF_RESPONDER_CMD_VALID_FAST_ALGO_SUPPORT = BIT(10), + IWL_TOF_RESPONDER_CMD_VALID_RETRY_ON_ALGO_FAIL = BIT(11), + IWL_TOF_RESPONDER_CMD_VALID_STA_ID = BIT(12), +}; + +/** + * enum iwl_tof_responder_cfg_flags - responder configuration flags + * @IWL_TOF_RESPONDER_FLAGS_NON_ASAP_SUPPORT: non-ASAP support + * @IWL_TOF_RESPONDER_FLAGS_REPORT_STATISTICS: report statistics + * @IWL_TOF_RESPONDER_FLAGS_REPORT_MCSI: report MCSI + * @IWL_TOF_RESPONDER_FLAGS_ALGO_TYPE: algorithm type + * @IWL_TOF_RESPONDER_FLAGS_TOA_OFFSET_MODE: ToA offset mode + * @IWL_TOF_RESPONDER_FLAGS_COMMON_CALIB_MODE: common calibration mode + * @IWL_TOF_RESPONDER_FLAGS_SPECIFIC_CALIB_MODE: specific calibration mode + * @IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT: fast algorithm support + * @IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL: retry on algorithm fail + * @IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT: TX antenna mask + */ +enum iwl_tof_responder_cfg_flags { + IWL_TOF_RESPONDER_FLAGS_NON_ASAP_SUPPORT = BIT(0), + IWL_TOF_RESPONDER_FLAGS_REPORT_STATISTICS = BIT(1), + IWL_TOF_RESPONDER_FLAGS_REPORT_MCSI = BIT(2), + IWL_TOF_RESPONDER_FLAGS_ALGO_TYPE = BIT(3) | BIT(4) | BIT(5), + IWL_TOF_RESPONDER_FLAGS_TOA_OFFSET_MODE = BIT(6), + IWL_TOF_RESPONDER_FLAGS_COMMON_CALIB_MODE = BIT(7), + IWL_TOF_RESPONDER_FLAGS_SPECIFIC_CALIB_MODE = BIT(8), + IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT = BIT(9), + IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL = BIT(10), + IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_ABC_MSK, +}; + +/** + * struct iwl_tof_responder_config_cmd - ToF AP mode (for debug) + * @cmd_valid_fields: &iwl_tof_responder_cmd_valid_field + * @responder_cfg_flags: &iwl_tof_responder_cfg_flags + * @bandwidth: current AP Bandwidth: &enum iwl_tof_bandwidth + * @rate: current AP rate + * @channel_num: current AP Channel + * @ctrl_ch_position: coding of the control channel position relative to + * the center frequency, see iwl_mvm_get_ctrl_pos() + * @sta_id: index of the AP STA when in AP mode + * @reserved1: reserved + * @toa_offset: Artificial addition [pSec] for the ToA - to be used for debug + * purposes, simulating station movement by adding various values + * to this field + * @common_calib: XVT: common calibration value + * @specific_calib: XVT: specific calibration value + * @bssid: Current AP BSSID + * @reserved2: reserved + */ +struct iwl_tof_responder_config_cmd { + __le32 cmd_valid_fields; + __le32 responder_cfg_flags; + u8 bandwidth; + u8 rate; + u8 channel_num; + u8 ctrl_ch_position; + u8 sta_id; + u8 reserved1; + __le16 toa_offset; + __le16 common_calib; + __le16 specific_calib; + u8 bssid[ETH_ALEN]; + __le16 reserved2; +} __packed; /* TOF_RESPONDER_CONFIG_CMD_API_S_VER_6 */ + +#define IWL_LCI_CIVIC_IE_MAX_SIZE 400 + +/** + * struct iwl_tof_responder_dyn_config_cmd - Dynamic responder settings + * @lci_len: The length of the 1st (LCI) part in the @lci_civic buffer + * @civic_len: The length of the 2nd (CIVIC) part in the @lci_civic buffer + * @lci_civic: The LCI/CIVIC buffer. LCI data (if exists) comes first, then, if + * needed, 0-padding such that the next part is dword-aligned, then CIVIC + * data (if exists) follows, and then 0-padding again to complete a + * 4-multiple long buffer. + */ +struct iwl_tof_responder_dyn_config_cmd { + __le32 lci_len; + __le32 civic_len; + u8 lci_civic[]; +} __packed; /* TOF_RESPONDER_DYN_CONFIG_CMD_API_S_VER_2 */ + +/** + * struct iwl_tof_range_request_ext_cmd - extended range req for WLS + * @tsf_timer_offset_msec: the recommended time offset (mSec) from the AP's TSF + * @reserved: reserved + * @min_delta_ftm: Minimal time between two consecutive measurements, + * in units of 100us. 0 means no preference by station + * @ftm_format_and_bw20M: FTM Channel Spacing/Format for 20MHz: recommended + * value be sent to the AP + * @ftm_format_and_bw40M: FTM Channel Spacing/Format for 40MHz: recommended + * value to be sent to the AP + * @ftm_format_and_bw80M: FTM Channel Spacing/Format for 80MHz: recommended + * value to be sent to the AP + */ +struct iwl_tof_range_req_ext_cmd { + __le16 tsf_timer_offset_msec; + __le16 reserved; + u8 min_delta_ftm; + u8 ftm_format_and_bw20M; + u8 ftm_format_and_bw40M; + u8 ftm_format_and_bw80M; +} __packed; + +/** + * enum iwl_tof_location_query - values for query bitmap + * @IWL_TOF_LOC_LCI: query LCI + * @IWL_TOF_LOC_CIVIC: query civic + */ +enum iwl_tof_location_query { + IWL_TOF_LOC_LCI = 0x01, + IWL_TOF_LOC_CIVIC = 0x02, +}; + + /** + * struct iwl_tof_range_req_ap_entry - AP configuration parameters + * @channel_num: Current AP Channel + * @bandwidth: Current AP Bandwidth. One of iwl_tof_bandwidth. + * @tsf_delta_direction: TSF relatively to the subject AP + * @ctrl_ch_position: Coding of the control channel position relative to the + * center frequency, see iwl_mvm_get_ctrl_pos(). + * @bssid: AP's BSSID + * @measure_type: Measurement type: 0 - two sided, 1 - One sided + * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of the + * number of measurement iterations (min 2^0 = 1, max 2^14) + * @burst_period: Recommended value to be sent to the AP. Measurement + * periodicity In units of 100ms. ignored if num_of_bursts = 0 + * @samples_per_burst: 2-sided: the number of FTMs pairs in single Burst (1-31); + * 1-sided: how many rts/cts pairs should be used per burst. + * @retries_per_sample: Max number of retries that the LMAC should send + * in case of no replies by the AP. + * @tsf_delta: TSF Delta in units of microseconds. + * The difference between the AP TSF and the device local clock. + * @location_req: Location Request Bit[0] LCI should be sent in the FTMR; + * Bit[1] Civic should be sent in the FTMR + * @asap_mode: 0 - non asap mode, 1 - asap mode (not relevant for one sided) + * @enable_dyn_ack: Enable Dynamic ACK BW. + * 0: Initiator interact with regular AP; + * 1: Initiator interact with Responder machine: need to send the + * Initiator Acks with HT 40MHz / 80MHz, since the Responder should + * use it for its ch est measurement (this flag will be set when we + * configure the opposite machine to be Responder). + * @rssi: Last received value + * legal values: -128-0 (0x7f). above 0x0 indicating an invalid value. + * @algo_type: &enum iwl_tof_algo_type + * @notify_mcsi: &enum iwl_tof_mcsi_ntfy. + * @reserved: For alignment and future use + */ +struct iwl_tof_range_req_ap_entry { + u8 channel_num; + u8 bandwidth; + u8 tsf_delta_direction; + u8 ctrl_ch_position; + u8 bssid[ETH_ALEN]; + u8 measure_type; + u8 num_of_bursts; + __le16 burst_period; + u8 samples_per_burst; + u8 retries_per_sample; + __le32 tsf_delta; + u8 location_req; + u8 asap_mode; + u8 enable_dyn_ack; + s8 rssi; + u8 algo_type; + u8 notify_mcsi; + __le16 reserved; +} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */ + +/** + * enum iwl_tof_response_mode + * @IWL_MVM_TOF_RESPONSE_ASAP: report each AP measurement separately as soon as + * possible (not supported for this release) + * @IWL_MVM_TOF_RESPONSE_TIMEOUT: report all AP measurements as a batch upon + * timeout expiration + * @IWL_MVM_TOF_RESPONSE_COMPLETE: report all AP measurements as a batch at the + * earlier of: measurements completion / timeout + * expiration. + */ +enum iwl_tof_response_mode { + IWL_MVM_TOF_RESPONSE_ASAP, + IWL_MVM_TOF_RESPONSE_TIMEOUT, + IWL_MVM_TOF_RESPONSE_COMPLETE, +}; + +/** + * enum iwl_tof_initiator_flags + * + * @IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED: disable fast algo, meaning run + * the algo on ant A+B, instead of only one of them. + * @IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_A: open RX antenna A for FTMs RX + * @IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_B: open RX antenna B for FTMs RX + * @IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_C: open RX antenna C for FTMs RX + * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A: use antenna A fo TX ACKs during FTM + * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B: use antenna B fo TX ACKs during FTM + * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C: use antenna C fo TX ACKs during FTM + * @IWL_TOF_INITIATOR_FLAGS_MINDELTA_NO_PREF: no preference for minDeltaFTM + */ +enum iwl_tof_initiator_flags { + IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED = BIT(0), + IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_A = BIT(1), + IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_B = BIT(2), + IWL_TOF_INITIATOR_FLAGS_RX_CHAIN_SEL_C = BIT(3), + IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A = BIT(4), + IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B = BIT(5), + IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C = BIT(6), + IWL_TOF_INITIATOR_FLAGS_MINDELTA_NO_PREF = BIT(7), +}; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ + +#define IWL_MVM_TOF_MAX_APS 5 +#define IWL_MVM_TOF_MAX_TWO_SIDED_APS 5 + +/** + * struct iwl_tof_range_req_cmd - start measurement cmd + * @initiator_flags: see flags @ iwl_tof_initiator_flags + * @request_id: A Token incremented per request. The same Token will be + * sent back in the range response + * @initiator: 0- NW initiated, 1 - Client Initiated + * @one_sided_los_disable: '0'- run ML-Algo for both ToF/OneSided, + * '1' - run ML-Algo for ToF only + * @req_timeout: Requested timeout of the response in units of 100ms. + * This is equivalent to the session time configured to the + * LMAC in Initiator Request + * @report_policy: Supported partially for this release: For current release - + * the range report will be uploaded as a batch when ready or + * when the session is done (successfully / partially). + * one of iwl_tof_response_mode. + * @reserved0: reserved + * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) + * @macaddr_random: '0' Use default source MAC address (i.e. p2_p), + * '1' Use MAC Address randomization according to the below + * @range_req_bssid: ranging request BSSID + * @macaddr_template: MAC address template to use for non-randomized bits + * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template. + * Bits set to 1 shall be randomized by the UMAC + * @ftm_rx_chains: Rx chain to open to receive Responder's FTMs (XVT) + * @ftm_tx_chains: Tx chain to send the ack to the Responder FTM (XVT) + * @common_calib: The common calib value to inject to this measurement calc + * @specific_calib: The specific calib value to inject to this measurement calc + * @ap: per-AP request data + */ +struct iwl_tof_range_req_cmd { + __le32 initiator_flags; + u8 request_id; + u8 initiator; + u8 one_sided_los_disable; + u8 req_timeout; + u8 report_policy; + u8 reserved0; + u8 num_of_ap; + u8 macaddr_random; + u8 range_req_bssid[ETH_ALEN]; + u8 macaddr_template[ETH_ALEN]; + u8 macaddr_mask[ETH_ALEN]; + u8 ftm_rx_chains; + u8 ftm_tx_chains; + __le16 common_calib; + __le16 specific_calib; + struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; +} __packed; +/* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ + +/* + * enum iwl_tof_range_request_status - status of the sent request + * @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the + * request + * @IWL_TOF_RANGE_REQUEST_STATUS_BUSY - FW is busy with a previous request, the + * sent request will not be handled + */ +enum iwl_tof_range_request_status { + IWL_TOF_RANGE_REQUEST_STATUS_SUCCESS, + IWL_TOF_RANGE_REQUEST_STATUS_BUSY, +}; + +/** + * enum iwl_tof_entry_status + * + * @IWL_TOF_ENTRY_SUCCESS: successful measurement. + * @IWL_TOF_ENTRY_GENERAL_FAILURE: General failure. + * @IWL_TOF_ENTRY_NO_RESPONSE: Responder didn't reply to the request. + * @IWL_TOF_ENTRY_REQUEST_REJECTED: Responder rejected the request. + * @IWL_TOF_ENTRY_NOT_SCHEDULED: Time event was scheduled but not called yet. + * @IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT: Time event triggered but no + * measurement was completed. + * @IWL_TOF_ENTRY_TARGET_DIFF_CH_CANNOT_CHANGE: No range due inability to switch + * from the primary channel. + * @IWL_TOF_ENTRY_RANGE_NOT_SUPPORTED: Device doesn't support FTM. + * @IWL_TOF_ENTRY_REQUEST_ABORT_UNKNOWN_REASON: Request aborted due to unknown + * reason. + * @IWL_TOF_ENTRY_LOCATION_INVALID_T1_T4_TIME_STAMP: Failure due to invalid + * T1/T4. + * @IWL_TOF_ENTRY_11MC_PROTOCOL_FAILURE: Failure due to invalid FTM frame + * structure. + * @IWL_TOF_ENTRY_REQUEST_CANNOT_SCHED: Request cannot be scheduled. + * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE: Responder cannot serve the + * initiator for some period, period supplied in @refusal_period. + * @IWL_TOF_ENTRY_BAD_REQUEST_ARGS: Bad request arguments. + * @IWL_TOF_ENTRY_WIFI_NOT_ENABLED: Wifi not enabled. + * @IWL_TOF_ENTRY_RESPONDER_OVERRIDE_PARAMS: Responder override the original + * parameters within the current session. + */ +enum iwl_tof_entry_status { + IWL_TOF_ENTRY_SUCCESS = 0, + IWL_TOF_ENTRY_GENERAL_FAILURE = 1, + IWL_TOF_ENTRY_NO_RESPONSE = 2, + IWL_TOF_ENTRY_REQUEST_REJECTED = 3, + IWL_TOF_ENTRY_NOT_SCHEDULED = 4, + IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT = 5, + IWL_TOF_ENTRY_TARGET_DIFF_CH_CANNOT_CHANGE = 6, + IWL_TOF_ENTRY_RANGE_NOT_SUPPORTED = 7, + IWL_TOF_ENTRY_REQUEST_ABORT_UNKNOWN_REASON = 8, + IWL_TOF_ENTRY_LOCATION_INVALID_T1_T4_TIME_STAMP = 9, + IWL_TOF_ENTRY_11MC_PROTOCOL_FAILURE = 10, + IWL_TOF_ENTRY_REQUEST_CANNOT_SCHED = 11, + IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE = 12, + IWL_TOF_ENTRY_BAD_REQUEST_ARGS = 13, + IWL_TOF_ENTRY_WIFI_NOT_ENABLED = 14, + IWL_TOF_ENTRY_RESPONDER_OVERRIDE_PARAMS = 15, +}; /* LOCATION_RANGE_RSP_AP_ENTRY_NTFY_API_S_VER_2 */ + +/** + * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response) + * @bssid: BSSID of the AP + * @measure_status: current APs measurement status, one of + * &enum iwl_tof_entry_status. + * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz + * @rtt: The Round Trip Time that took for the last measurement for + * current AP [pSec] + * @rtt_variance: The Variance of the RTT values measured for current AP + * @rtt_spread: The Difference between the maximum and the minimum RTT + * values measured for current AP in the current session [pSec] + * @rssi: RSSI as uploaded in the Channel Estimation notification + * @rssi_spread: The Difference between the maximum and the minimum RSSI values + * measured for current AP in the current session + * @reserved: reserved + * @refusal_period: refusal period in case of + * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec] + * @range: Measured range [cm] + * @range_variance: Measured range variance [cm] + * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was + * uploaded by the LMAC + * @t2t3_initiator: as calculated from the algo in the initiator + * @t1t4_responder: as calculated from the algo in the responder + * @common_calib: Calib val that was used in for this AP measurement + * @specific_calib: val that was used in for this AP measurement + * @papd_calib_output: The result of the tof papd calibration that was injected + * into the algorithm. + */ +struct iwl_tof_range_rsp_ap_entry_ntfy { + u8 bssid[ETH_ALEN]; + u8 measure_status; + u8 measure_bw; + __le32 rtt; + __le32 rtt_variance; + __le32 rtt_spread; + s8 rssi; + u8 rssi_spread; + u8 reserved; + u8 refusal_period; + __le32 range; + __le32 range_variance; + __le32 timestamp; + __le32 t2t3_initiator; + __le32 t1t4_responder; + __le16 common_calib; + __le16 specific_calib; + __le32 papd_calib_output; +} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */ + +/** + * enum iwl_tof_response_status - tof response status + * + * @IWL_TOF_RESPONSE_SUCCESS: successful range. + * @IWL_TOF_RESPONSE_TIMEOUT: request aborted due to timeout expiration. + * partial result of ranges done so far is included in the response. + * @IWL_TOF_RESPONSE_ABORTED: Measurement aborted by command. + * @IWL_TOF_RESPONSE_FAILED: Measurement request command failed. + */ +enum iwl_tof_response_status { + IWL_TOF_RESPONSE_SUCCESS = 0, + IWL_TOF_RESPONSE_TIMEOUT = 1, + IWL_TOF_RESPONSE_ABORTED = 4, + IWL_TOF_RESPONSE_FAILED = 5, +}; /* LOCATION_RNG_RSP_STATUS */ + +/** + * struct iwl_tof_range_rsp_ntfy - ranging response notification + * @request_id: A Token ID of the corresponding Range request + * @request_status: status of current measurement session, one of + * &enum iwl_tof_response_status. + * @last_in_batch: reprot policy (when not all responses are uploaded at once) + * @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) + * @ap: per-AP data + */ +struct iwl_tof_range_rsp_ntfy { + u8 request_id; + u8 request_status; + u8 last_in_batch; + u8 num_of_aps; + struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS]; +} __packed; + +#define IWL_MVM_TOF_MCSI_BUF_SIZE (245) +/** + * struct iwl_tof_mcsi_notif - used for debug + * @token: token ID for the current session + * @role: '0' - initiator, '1' - responder + * @reserved: reserved + * @initiator_bssid: initiator machine + * @responder_bssid: responder machine + * @mcsi_buffer: debug data + */ +struct iwl_tof_mcsi_notif { + u8 token; + u8 role; + __le16 reserved; + u8 initiator_bssid[ETH_ALEN]; + u8 responder_bssid[ETH_ALEN]; + u8 mcsi_buffer[IWL_MVM_TOF_MCSI_BUF_SIZE * 4]; +} __packed; + +/** + * struct iwl_tof_range_abort_cmd + * @request_id: corresponds to a range request + * @reserved: reserved + */ +struct iwl_tof_range_abort_cmd { + u8 request_id; + u8 reserved[3]; +} __packed; + +enum ftm_responder_stats_flags { + FTM_RESP_STAT_NON_ASAP_STARTED = BIT(0), + FTM_RESP_STAT_NON_ASAP_IN_WIN = BIT(1), + FTM_RESP_STAT_NON_ASAP_OUT_WIN = BIT(2), + FTM_RESP_STAT_TRIGGER_DUP = BIT(3), + FTM_RESP_STAT_DUP = BIT(4), + FTM_RESP_STAT_DUP_IN_WIN = BIT(5), + FTM_RESP_STAT_DUP_OUT_WIN = BIT(6), + FTM_RESP_STAT_SCHED_SUCCESS = BIT(7), + FTM_RESP_STAT_ASAP_REQ = BIT(8), + FTM_RESP_STAT_NON_ASAP_REQ = BIT(9), + FTM_RESP_STAT_ASAP_RESP = BIT(10), + FTM_RESP_STAT_NON_ASAP_RESP = BIT(11), + FTM_RESP_STAT_FAIL_INITIATOR_INACTIVE = BIT(12), + FTM_RESP_STAT_FAIL_INITIATOR_OUT_WIN = BIT(13), + FTM_RESP_STAT_FAIL_INITIATOR_RETRY_LIM = BIT(14), + FTM_RESP_STAT_FAIL_NEXT_SERVED = BIT(15), + FTM_RESP_STAT_FAIL_TRIGGER_ERR = BIT(16), + FTM_RESP_STAT_FAIL_GC = BIT(17), + FTM_RESP_STAT_SUCCESS = BIT(18), + FTM_RESP_STAT_INTEL_IE = BIT(19), + FTM_RESP_STAT_INITIATOR_ACTIVE = BIT(20), + FTM_RESP_STAT_MEASUREMENTS_AVAILABLE = BIT(21), + FTM_RESP_STAT_TRIGGER_UNKNOWN = BIT(22), + FTM_RESP_STAT_PROCESS_FAIL = BIT(23), + FTM_RESP_STAT_ACK = BIT(24), + FTM_RESP_STAT_NACK = BIT(25), + FTM_RESP_STAT_INVALID_INITIATOR_ID = BIT(26), + FTM_RESP_STAT_TIMER_MIN_DELTA = BIT(27), + FTM_RESP_STAT_INITIATOR_REMOVED = BIT(28), + FTM_RESP_STAT_INITIATOR_ADDED = BIT(29), + FTM_RESP_STAT_ERR_LIST_FULL = BIT(30), + FTM_RESP_STAT_INITIATOR_SCHED_NOW = BIT(31), +}; /* RESP_IND_E */ + +/** + * struct iwl_ftm_responder_stats - FTM responder statistics + * @addr: initiator address + * @success_ftm: number of successful ftm frames + * @ftm_per_burst: num of FTM frames that were received + * @flags: &enum ftm_responder_stats_flags + * @duration: actual duration of FTM + * @allocated_duration: time that was allocated for this FTM session + * @bw: FTM request bandwidth + * @rate: FTM request rate + * @reserved: for alingment and future use + */ +struct iwl_ftm_responder_stats { + u8 addr[ETH_ALEN]; + u8 success_ftm; + u8 ftm_per_burst; + __le32 flags; + __le32 duration; + __le32 allocated_duration; + u8 bw; + u8 rate; + __le16 reserved; +} __packed; /* TOF_RESPONDER_STATISTICS_NTFY_S_VER_2 */ + +#endif /* __iwl_fw_api_location_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 851bfb259f10..e3eb812e0248 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -91,6 +91,7 @@ #include "fw/api/sf.h" #include "fw/api/sta.h" #include "fw/api/stats.h" +#include "fw/api/location.h" #include "fw/api/tx.h" #endif /* __fw_api_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 93b7cc5910fe..c7ec36ceb661 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -457,6 +457,22 @@ static const struct iwl_hcmd_names iwl_mvm_debug_names[] = { HCMD_NAME(MFU_ASSERT_DUMP_NTF), }; +/* Please keep this array *SORTED* by hex value. + * Access is done through binary search + */ +static const struct iwl_hcmd_names iwl_mvm_location_names[] = { + HCMD_NAME(TOF_RANGE_REQ_CMD), + HCMD_NAME(TOF_CONFIG_CMD), + HCMD_NAME(TOF_RANGE_ABORT_CMD), + HCMD_NAME(TOF_RANGE_REQ_EXT_CMD), + HCMD_NAME(TOF_RESPONDER_CONFIG_CMD), + HCMD_NAME(TOF_RESPONDER_DYN_CONFIG_CMD), + HCMD_NAME(TOF_LC_NOTIF), + HCMD_NAME(TOF_RESPONDER_STATS), + HCMD_NAME(TOF_MCSI_DEBUG_NOTIF), + HCMD_NAME(TOF_RANGE_RESPONSE_NOTIF), +}; + /* Please keep this array *SORTED* by hex value. * Access is done through binary search */ @@ -479,6 +495,7 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = { [MAC_CONF_GROUP] = HCMD_ARR(iwl_mvm_mac_conf_names), [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), [DATA_PATH_GROUP] = HCMD_ARR(iwl_mvm_data_path_names), + [LOCATION_GROUP] = HCMD_ARR(iwl_mvm_location_names), [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names), [REGULATORY_AND_NVM_GROUP] = HCMD_ARR(iwl_mvm_regulatory_and_nvm_names), -- cgit v1.2.3 From 5213e8a8a28d2c4c143fec94e57c866a958ed52d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 25 Oct 2018 09:15:21 +0200 Subject: iwlwifi: mvm: implement CSI reporting Implement CSI (channel estimation matrix) reporting in the mvm driver, if the firmware has the capability. Currently only a debugfs API is provided as the API is still under discussion. For now, RX aggregation must be disabled to use this feature on data frames as we haven't found a good way to attach the data to A-MPDUs, given complexities with multi-queue. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/datapath.h | 55 ++++++++++++++++++++++ .../net/wireless/intel/iwlwifi/fw/api/location.h | 20 ++++++++ drivers/net/wireless/intel/iwlwifi/fw/api/rx.h | 2 + drivers/net/wireless/intel/iwlwifi/fw/file.h | 7 ++- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 1 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 20 ++++---- 7 files changed, 94 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index fdc54a5dc9de..93c06e6c1ced 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -104,6 +104,12 @@ enum iwl_data_path_subcmd_ids { */ HE_AIR_SNIFFER_CONFIG_CMD = 0x13, + /** + * @CHEST_COLLECTOR_FILTER_CONFIG_CMD: Configure the CSI + * matrix collection, uses &struct iwl_channel_estimation_cfg + */ + CHEST_COLLECTOR_FILTER_CONFIG_CMD = 0x14, + /** * @RX_NO_DATA_NOTIF: &struct iwl_rx_no_data */ @@ -156,4 +162,53 @@ struct iwl_mu_group_mgmt_notif { __le32 user_position[4]; } __packed; /* MU_GROUP_MNG_NTFY_API_S_VER_1 */ +enum iwl_channel_estimation_flags { + IWL_CHANNEL_ESTIMATION_ENABLE = BIT(0), + IWL_CHANNEL_ESTIMATION_TIMER = BIT(1), + IWL_CHANNEL_ESTIMATION_COUNTER = BIT(2), +}; + +/** + * struct iwl_channel_estimation_cfg - channel estimation reporting config + */ +struct iwl_channel_estimation_cfg { + /** + * @flags: flags, see &enum iwl_channel_estimation_flags + */ + __le32 flags; + /** + * @timer: if enabled via flags, automatically disable after this many + * microseconds + */ + __le32 timer; + /** + * @count: if enabled via flags, automatically disable after this many + * frames with channel estimation matrix were captured + */ + __le32 count; + /** + * @rate_n_flags_mask: only try to record the channel estimation matrix + * if the rate_n_flags value for the received frame (let's call + * that rx_rnf) matches the mask/value given here like this: + * (rx_rnf & rate_n_flags_mask) == rate_n_flags_val. + */ + __le32 rate_n_flags_mask; + /** + * @rate_n_flags_val: see @rate_n_flags_mask + */ + __le32 rate_n_flags_val; + /** + * @reserved: reserved (for alignment) + */ + __le32 reserved; + /** + * @frame_types: bitmap of frame types to capture, the received frame's + * subtype|type takes 6 bits in the frame and the corresponding bit + * in this field must be set to 1 to capture channel estimation for + * that frame type. Set to all-ones to enable capturing for all + * frame types. + */ + __le64 frame_types; +} __packed; /* CHEST_COLLECTOR_FILTER_CMD_API_S_VER_1 */ + #endif /* __iwl_fw_api_datapath_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 0df0851b9513..6da91ec0df55 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -93,6 +93,15 @@ enum iwl_location_subcmd_ids { * uses &struct iwl_tof_responder_dyn_config_cmd */ TOF_RESPONDER_DYN_CONFIG_CMD = 0x5, + /** + * @CSI_HEADER_NOTIFICATION: CSI header + */ + CSI_HEADER_NOTIFICATION = 0xFA, + /** + * @CSI_CHUNKS_NOTIFICATION: CSI chunk, + * uses &struct iwl_csi_chunk_notification + */ + CSI_CHUNKS_NOTIFICATION = 0xFB, /** * @TOF_LC_NOTIF: used for LCI/civic location, contains just * the action frame @@ -688,4 +697,15 @@ struct iwl_ftm_responder_stats { __le16 reserved; } __packed; /* TOF_RESPONDER_STATISTICS_NTFY_S_VER_2 */ +#define IWL_CSI_CHUNK_CTL_NUM_MASK 0x3 +#define IWL_CSI_CHUNK_CTL_IDX_MASK 0xc + +struct iwl_csi_chunk_notification { + __le32 token; + __le16 seq; + __le16 ctl; + __le32 size; + u8 data[]; +} __packed; /* CSI_CHUNKS_HDR_NTFY_API_S_VER_1 */ + #endif /* __iwl_fw_api_location_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 11c25f32a286..6e8224ce8906 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -333,6 +333,8 @@ enum iwl_rx_mpdu_phy_info { IWL_RX_MPDU_PHY_AMPDU = BIT(5), IWL_RX_MPDU_PHY_AMPDU_TOGGLE = BIT(6), IWL_RX_MPDU_PHY_SHORT_PREAMBLE = BIT(7), + /* short preamble is only for CCK, for non-CCK overridden by this */ + IWL_RX_MPDU_PHY_NCCK_ADDTL_NTFY = BIT(7), IWL_RX_MPDU_PHY_TSF_OVERLOAD = BIT(8), }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index dfe02bdb7481..f73c5c697690 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -356,10 +356,13 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_TX_POWER_ACK: reduced TX power API has larger * command size (command version 4) that supports toggling ACK TX * power reduction. - * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload * @IWL_UCODE_TLV_CAPA_D3_DEBUG: supports debug recording during D3 * @IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT: MCC response support 11ax * capability. + * @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured + * to report the CSI information with (certain) RX frames + * + * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -410,6 +413,8 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_D3_DEBUG = (__force iwl_ucode_tlv_capa_t)87, IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88, IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89, + IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90, + IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96, NUM_IWL_UCODE_TLV_CAPA diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index cbbd4b076e17..91b46361ac9f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -69,6 +69,7 @@ #include "sta.h" #include "iwl-io.h" #include "debugfs.h" +#include "iwl-modparams.h" #include "fw/error-dump.h" static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index c7ec36ceb661..5e4f8b767d10 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -445,6 +445,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), HCMD_NAME(STA_HE_CTXT_CMD), HCMD_NAME(RFH_QUEUE_CONFIG_CMD), + HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), HCMD_NAME(STA_PM_NOTIF), HCMD_NAME(MU_GROUP_MGMT_NOTIF), HCMD_NAME(RX_QUEUES_NOTIFICATION), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 120e3f2d21aa..7b6f4585fec9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -201,18 +201,10 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); if (!(rx_status->flag & RX_FLAG_NO_PSDU) && - iwl_mvm_check_pn(mvm, skb, queue, sta)) { + iwl_mvm_check_pn(mvm, skb, queue, sta)) kfree_skb(skb); - } else { - unsigned int radiotap_len = 0; - - if (rx_status->flag & RX_FLAG_RADIOTAP_HE) - radiotap_len += sizeof(struct ieee80211_radiotap_he); - if (rx_status->flag & RX_FLAG_RADIOTAP_HE_MU) - radiotap_len += sizeof(struct ieee80211_radiotap_he_mu); - __skb_push(skb, radiotap_len); + else ieee80211_rx_napi(mvm->hw, sta, skb, napi); - } } static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, @@ -1438,9 +1430,15 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, bool toggle_bit = phy_info & IWL_RX_MPDU_PHY_AMPDU_TOGGLE; rx_status->flag |= RX_FLAG_AMPDU_DETAILS; - /* toggle is switched whenever new aggregation starts */ + /* + * Toggle is switched whenever new aggregation starts. Make + * sure ampdu_reference is never 0 so we can later use it to + * see if the frame was really part of an A-MPDU or not. + */ if (toggle_bit != mvm->ampdu_toggle) { mvm->ampdu_ref++; + if (mvm->ampdu_ref == 0) + mvm->ampdu_ref++; mvm->ampdu_toggle = toggle_bit; } rx_status->ampdu_reference = mvm->ampdu_ref; -- cgit v1.2.3 From 57e861d9362ed303ac5c0df1bc11760979de9f55 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Sun, 18 Nov 2018 18:01:43 +0200 Subject: iwlwifi: mvm: Change FW channel info API Change iwl_fw_channel_info structure so it can have channel number greater than 255. This is needed for 6 GHz channel numbers. Change all relevant structs and member accesses accordingly. The new API is indicated by a TLV capability bit. Signed-off-by: David Spinadel Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h | 51 ++++++++++++++++---- drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h | 19 ++++++-- .../net/wireless/intel/iwlwifi/fw/api/time-event.h | 34 ++++++++----- drivers/net/wireless/intel/iwlwifi/fw/file.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 30 +++++++----- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 55 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | 24 ++++------ drivers/net/wireless/intel/iwlwifi/mvm/tdls.c | 33 ++++++------- .../net/wireless/intel/iwlwifi/mvm/time-event.c | 4 +- 9 files changed, 182 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h index 45f61c6af14e..b833b80ea3d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -95,17 +97,36 @@ #define PHY_VHT_CTRL_POS_4_ABOVE (0x7) /* + * struct iwl_fw_channel_info_v1 - channel information + * * @band: PHY_BAND_* * @channel: channel number * @width: PHY_[VHT|LEGACY]_CHANNEL_* * @ctrl channel: PHY_[VHT|LEGACY]_CTRL_* */ -struct iwl_fw_channel_info { +struct iwl_fw_channel_info_v1 { u8 band; u8 channel; u8 width; u8 ctrl_pos; -} __packed; +} __packed; /* CHANNEL_CONFIG_API_S_VER_1 */ + +/* + * struct iwl_fw_channel_info - channel information + * + * @channel: channel number + * @band: PHY_BAND_* + * @width: PHY_[VHT|LEGACY]_CHANNEL_* + * @ctrl channel: PHY_[VHT|LEGACY]_CTRL_* + * @reserved: for future use and alignment + */ +struct iwl_fw_channel_info { + __le32 channel; + u8 band; + u8 width; + u8 ctrl_pos; + u8 reserved; +} __packed; /*CHANNEL_CONFIG_API_S_VER_2 */ #define PHY_RX_CHAIN_DRIVER_FORCE_POS (0) #define PHY_RX_CHAIN_DRIVER_FORCE_MSK \ @@ -133,6 +154,22 @@ struct iwl_fw_channel_info { #define NUM_PHY_CTX 3 /* TODO: complete missing documentation */ +/** + * struct iwl_phy_context_cmd_tail - tail of iwl_phy_ctx_cmd for alignment with + * various channel structures. + * + * @txchain_info: ??? + * @rxchain_info: ??? + * @acquisition_data: ??? + * @dsp_cfg_flags: set to 0 + */ +struct iwl_phy_context_cmd_tail { + __le32 txchain_info; + __le32 rxchain_info; + __le32 acquisition_data; + __le32 dsp_cfg_flags; +} __packed; + /** * struct iwl_phy_context_cmd - config of the PHY context * ( PHY_CONTEXT_CMD = 0x8 ) @@ -142,10 +179,7 @@ struct iwl_fw_channel_info { * other value means apply new params after X usecs * @tx_param_color: ??? * @ci: channel info - * @txchain_info: ??? - * @rxchain_info: ??? - * @acquisition_data: ??? - * @dsp_cfg_flags: set to 0 + * @tail: command tail */ struct iwl_phy_context_cmd { /* COMMON_INDEX_HDR_API_S_VER_1 */ @@ -155,10 +189,7 @@ struct iwl_phy_context_cmd { __le32 apply_time; __le32 tx_param_color; struct iwl_fw_channel_info ci; - __le32 txchain_info; - __le32 rxchain_info; - __le32 acquisition_data; - __le32 dsp_cfg_flags; + struct iwl_phy_context_cmd_tail tail; } __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ #endif /* __iwl_fw_api_phy_ctxt_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h index 7c6c2462d0e8..b089285ac466 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -110,6 +112,17 @@ struct iwl_tdls_channel_switch_frame { u8 data[IWL_TDLS_CH_SW_FRAME_MAX_SIZE]; } __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */ +/** + * struct iwl_tdls_channel_switch_cmd_tail - tail of iwl_tdls_channel_switch_cmd + * + * @timing: timing related data for command + * @frame: channel-switch request/response template, depending to switch_type + */ +struct iwl_tdls_channel_switch_cmd_tail { + struct iwl_tdls_channel_switch_timing timing; + struct iwl_tdls_channel_switch_frame frame; +} __packed; + /** * struct iwl_tdls_channel_switch_cmd - TDLS channel switch command * @@ -119,15 +132,13 @@ struct iwl_tdls_channel_switch_frame { * @switch_type: see &enum iwl_tdls_channel_switch_type * @peer_sta_id: station id of TDLS peer * @ci: channel we switch to - * @timing: timing related data for command - * @frame: channel-switch request/response template, depending to switch_type + * @tail: command tail */ struct iwl_tdls_channel_switch_cmd { u8 switch_type; __le32 peer_sta_id; struct iwl_fw_channel_info ci; - struct iwl_tdls_channel_switch_timing timing; - struct iwl_tdls_channel_switch_frame frame; + struct iwl_tdls_channel_switch_cmd_tail tail; } __packed; /* TDLS_STA_CHANNEL_SWITCH_CMD_API_S_VER_1 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h index f824bebceb06..4621ef93a2cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -317,6 +319,25 @@ struct iwl_time_event_notif { __le32 status; } __packed; /* MAC_TIME_EVENT_NTFY_API_S_VER_1 */ +/* + * struct iwl_hs20_roc_req_tail - tail of iwl_hs20_roc_req + * + * @node_addr: Our MAC Address + * @reserved: reserved for alignment + * @apply_time: GP2 value to start (should always be the current GP2 value) + * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max + * time by which start of the event is allowed to be postponed. + * @duration: event duration in TU To calculate event duration: + * timeEventDuration = min(duration, remainingQuota) + */ +struct iwl_hs20_roc_req_tail { + u8 node_addr[ETH_ALEN]; + __le16 reserved; + __le32 apply_time; + __le32 apply_time_max_delay; + __le32 duration; +} __packed; + /* * Aux ROC command * @@ -336,13 +357,6 @@ struct iwl_time_event_notif { * @sta_id_and_color: station id and color, resumed during "Remain On Channel" * activity. * @channel_info: channel info - * @node_addr: Our MAC Address - * @reserved: reserved for alignment - * @apply_time: GP2 value to start (should always be the current GP2 value) - * @apply_time_max_delay: Maximum apply time delay value in TU. Defines max - * time by which start of the event is allowed to be postponed. - * @duration: event duration in TU To calculate event duration: - * timeEventDuration = min(duration, remainingQuota) */ struct iwl_hs20_roc_req { /* COMMON_INDEX_HDR_API_S_VER_1 hdr */ @@ -351,11 +365,7 @@ struct iwl_hs20_roc_req { __le32 event_unique_id; __le32 sta_id_and_color; struct iwl_fw_channel_info channel_info; - u8 node_addr[ETH_ALEN]; - __le16 reserved; - __le32 apply_time; - __le32 apply_time_max_delay; - __le32 duration; + struct iwl_hs20_roc_req_tail tail; } __packed; /* HOT_SPOT_CMD_API_S_VER_1 */ /* diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index f73c5c697690..e8b00b795cbb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -333,6 +333,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm * @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related * @IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2: firmware implements Coex Schema 2 + * @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band + * (6 GHz). * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT @@ -395,6 +397,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_TLC_OFFLOAD = (__force iwl_ucode_tlv_capa_t)43, IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45, + IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48, IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index dd0761e5cf6a..1762b1fcb3db 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3520,14 +3520,20 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, .id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)), .sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id), - /* Set the channel info data */ - .channel_info.band = (channel->band == NL80211_BAND_2GHZ) ? - PHY_BAND_24 : PHY_BAND_5, - .channel_info.channel = channel->hw_value, - .channel_info.width = PHY_VHT_CHANNEL_MODE20, - /* Set the time and duration */ - .apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)), - }; + }; + struct iwl_hs20_roc_req_tail *tail = iwl_mvm_chan_info_cmd_tail(mvm, + &aux_roc_req.channel_info); + u16 len = sizeof(aux_roc_req) - iwl_mvm_chan_info_padding(mvm); + + /* Set the channel info data */ + iwl_mvm_set_chan_info(mvm, &aux_roc_req.channel_info, channel->hw_value, + (channel->band == NL80211_BAND_2GHZ) ? + PHY_BAND_24 : PHY_BAND_5, + PHY_VHT_CHANNEL_MODE20, + 0); + + /* Set the time and duration */ + tail->apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)); delay = AUX_ROC_MIN_DELAY; req_dur = MSEC_TO_TU(duration); @@ -3552,15 +3558,15 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, } } - aux_roc_req.duration = cpu_to_le32(req_dur); - aux_roc_req.apply_time_max_delay = cpu_to_le32(delay); + tail->duration = cpu_to_le32(req_dur); + tail->apply_time_max_delay = cpu_to_le32(delay); IWL_DEBUG_TE(mvm, "ROC: Requesting to remain on channel %u for %ums (requested = %ums, max_delay = %ums, dtim_interval = %ums)\n", channel->hw_value, req_dur, duration, delay, dtim_interval); /* Set the node address */ - memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN); + memcpy(tail->node_addr, vif->addr, ETH_ALEN); lockdep_assert_held(&mvm->mutex); @@ -3591,7 +3597,7 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, ARRAY_SIZE(time_event_response), iwl_mvm_rx_aux_roc, te_data); - res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req), + res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, len, &aux_roc_req); if (res) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 55f08e433331..59d655436a8f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -2059,4 +2059,59 @@ void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw, struct dentry *dir); #endif +/* Channel info utils */ +static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm) +{ + return fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS); +} + +static inline void *iwl_mvm_chan_info_cmd_tail(struct iwl_mvm *mvm, + struct iwl_fw_channel_info *ci) +{ + return (u8 *)ci + (iwl_mvm_has_ultra_hb_channel(mvm) ? + sizeof(struct iwl_fw_channel_info) : + sizeof(struct iwl_fw_channel_info_v1)); +} + +static inline size_t iwl_mvm_chan_info_padding(struct iwl_mvm *mvm) +{ + return iwl_mvm_has_ultra_hb_channel(mvm) ? 0 : + sizeof(struct iwl_fw_channel_info) - + sizeof(struct iwl_fw_channel_info_v1); +} + +static inline void iwl_mvm_set_chan_info(struct iwl_mvm *mvm, + struct iwl_fw_channel_info *ci, + u32 chan, u8 band, u8 width, + u8 ctrl_pos) +{ + if (iwl_mvm_has_ultra_hb_channel(mvm)) { + ci->channel = cpu_to_le32(chan); + ci->band = band; + ci->width = width; + ci->ctrl_pos = ctrl_pos; + } else { + struct iwl_fw_channel_info_v1 *ci_v1 = + (struct iwl_fw_channel_info_v1 *)ci; + + ci_v1->channel = chan; + ci_v1->band = band; + ci_v1->width = width; + ci_v1->ctrl_pos = ctrl_pos; + } +} + +static inline void +iwl_mvm_set_chan_info_chandef(struct iwl_mvm *mvm, + struct iwl_fw_channel_info *ci, + struct cfg80211_chan_def *chandef) +{ + iwl_mvm_set_chan_info(mvm, ci, chandef->chan->hw_value, + (chandef->chan->band == NL80211_BAND_2GHZ ? + PHY_BAND_24 : PHY_BAND_5), + iwl_mvm_get_channel_width(chandef), + iwl_mvm_get_ctrl_pos(chandef)); +} + #endif /* __IWL_MVM_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c index 7f5434b34d0d..f369173db11c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c @@ -143,14 +143,11 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, u8 chains_static, u8 chains_dynamic) { u8 active_cnt, idle_cnt; + struct iwl_phy_context_cmd_tail *tail = + iwl_mvm_chan_info_cmd_tail(mvm, &cmd->ci); /* Set the channel info data */ - cmd->ci.band = (chandef->chan->band == NL80211_BAND_2GHZ ? - PHY_BAND_24 : PHY_BAND_5); - - cmd->ci.channel = chandef->chan->hw_value; - cmd->ci.width = iwl_mvm_get_channel_width(chandef); - cmd->ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef); + iwl_mvm_set_chan_info_chandef(mvm, &cmd->ci, chandef); /* Set rx the chains */ idle_cnt = chains_static; @@ -168,17 +165,17 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, active_cnt = 2; } - cmd->rxchain_info = cpu_to_le32(iwl_mvm_get_valid_rx_ant(mvm) << + tail->rxchain_info = cpu_to_le32(iwl_mvm_get_valid_rx_ant(mvm) << PHY_RX_CHAIN_VALID_POS); - cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); - cmd->rxchain_info |= cpu_to_le32(active_cnt << + tail->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); + tail->rxchain_info |= cpu_to_le32(active_cnt << PHY_RX_CHAIN_MIMO_CNT_POS); #ifdef CONFIG_IWLWIFI_DEBUGFS if (unlikely(mvm->dbgfs_rx_phyinfo)) - cmd->rxchain_info = cpu_to_le32(mvm->dbgfs_rx_phyinfo); + tail->rxchain_info = cpu_to_le32(mvm->dbgfs_rx_phyinfo); #endif - cmd->txchain_info = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm)); + tail->txchain_info = cpu_to_le32(iwl_mvm_get_valid_tx_ant(mvm)); } /* @@ -195,6 +192,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm, { struct iwl_phy_context_cmd cmd; int ret; + u16 len = sizeof(cmd) - iwl_mvm_chan_info_padding(mvm); /* Set the command header fields */ iwl_mvm_phy_ctxt_cmd_hdr(ctxt, &cmd, action, apply_time); @@ -203,9 +201,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm, iwl_mvm_phy_ctxt_cmd_data(mvm, &cmd, chandef, chains_static, chains_dynamic); - ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, 0, - sizeof(struct iwl_phy_context_cmd), - &cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, 0, len, &cmd); if (ret) IWL_ERR(mvm, "PHY ctxt cmd error. ret=%d\n", ret); return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c index e02f4eb20359..859aa5a4e6b5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c @@ -399,6 +399,9 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, struct ieee80211_tx_info *info; struct ieee80211_hdr *hdr; struct iwl_tdls_channel_switch_cmd cmd = {0}; + struct iwl_tdls_channel_switch_cmd_tail *tail = + iwl_mvm_chan_info_cmd_tail(mvm, &cmd.ci); + u16 len = sizeof(cmd) - iwl_mvm_chan_info_padding(mvm); int ret; lockdep_assert_held(&mvm->mutex); @@ -414,9 +417,9 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, } cmd.switch_type = type; - cmd.timing.frame_timestamp = cpu_to_le32(timestamp); - cmd.timing.switch_time = cpu_to_le32(switch_time); - cmd.timing.switch_timeout = cpu_to_le32(switch_timeout); + tail->timing.frame_timestamp = cpu_to_le32(timestamp); + tail->timing.switch_time = cpu_to_le32(switch_time); + tail->timing.switch_timeout = cpu_to_le32(switch_timeout); rcu_read_lock(); sta = ieee80211_find_sta(vif, peer); @@ -448,21 +451,16 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, } } - if (chandef) { - cmd.ci.band = (chandef->chan->band == NL80211_BAND_2GHZ ? - PHY_BAND_24 : PHY_BAND_5); - cmd.ci.channel = chandef->chan->hw_value; - cmd.ci.width = iwl_mvm_get_channel_width(chandef); - cmd.ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef); - } + if (chandef) + iwl_mvm_set_chan_info_chandef(mvm, &cmd.ci, chandef); /* keep quota calculation simple for now - 50% of DTIM for TDLS */ - cmd.timing.max_offchan_duration = + tail->timing.max_offchan_duration = cpu_to_le32(TU_TO_US(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int) / 2); /* Switch time is the first element in the switch-timing IE. */ - cmd.frame.switch_time_offset = cpu_to_le32(ch_sw_tm_ie + 2); + tail->frame.switch_time_offset = cpu_to_le32(ch_sw_tm_ie + 2); info = IEEE80211_SKB_CB(skb); hdr = (void *)skb->data; @@ -472,20 +470,19 @@ iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm, ret = -EINVAL; goto out; } - iwl_mvm_set_tx_cmd_ccmp(info, &cmd.frame.tx_cmd); + iwl_mvm_set_tx_cmd_ccmp(info, &tail->frame.tx_cmd); } - iwl_mvm_set_tx_cmd(mvm, skb, &cmd.frame.tx_cmd, info, + iwl_mvm_set_tx_cmd(mvm, skb, &tail->frame.tx_cmd, info, mvmsta->sta_id); - iwl_mvm_set_tx_cmd_rate(mvm, &cmd.frame.tx_cmd, info, sta, + iwl_mvm_set_tx_cmd_rate(mvm, &tail->frame.tx_cmd, info, sta, hdr->frame_control); rcu_read_unlock(); - memcpy(cmd.frame.data, skb->data, skb->len); + memcpy(tail->frame.data, skb->data, skb->len); - ret = iwl_mvm_send_cmd_pdu(mvm, TDLS_CHANNEL_SWITCH_CMD, 0, - sizeof(cmd), &cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, TDLS_CHANNEL_SWITCH_CMD, 0, len, &cmd); if (ret) { IWL_ERR(mvm, "Failed to send TDLS_CHANNEL_SWITCH cmd: %d\n", ret); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 9fa1a36dcda3..5b34100e9099 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -687,6 +687,8 @@ static void iwl_mvm_remove_aux_roc_te(struct iwl_mvm *mvm, struct iwl_mvm_time_event_data *te_data) { struct iwl_hs20_roc_req aux_cmd = {}; + u16 len = sizeof(aux_cmd) - iwl_mvm_chan_info_padding(mvm); + u32 uid; int ret; @@ -700,7 +702,7 @@ static void iwl_mvm_remove_aux_roc_te(struct iwl_mvm *mvm, IWL_DEBUG_TE(mvm, "Removing BSS AUX ROC TE 0x%x\n", le32_to_cpu(aux_cmd.event_unique_id)); ret = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, - sizeof(aux_cmd), &aux_cmd); + len, &aux_cmd); if (WARN_ON(ret)) return; -- cgit v1.2.3 From 311590a3a21eda3f787a3dce1b8bf675f0d63bf7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 19 Nov 2018 09:32:39 +0200 Subject: iwlwifi: mvm: freeze management TXQ timer when station goes to sleep We maintain a timer for each Tx queue to detect stalls and be able to recover / debug. When we work in AP mode, we can freeze the Tx queue timer if a station goes to sleep, because we don't want to warn about stalls that are caused by faulty clients that don't wake up on time. This mechanism was applied to the queues of the clients, but the management queue was omitted. Fix that. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 1762b1fcb3db..d4b05caabc74 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -2776,7 +2776,7 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, return; spin_lock_bh(&mvmsta->lock); - for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { + for (tid = 0; tid < ARRAY_SIZE(mvmsta->tid_data); tid++) { struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; if (tid_data->txq_id == IWL_MVM_INVALID_QUEUE) -- cgit v1.2.3 From fdd6c9419b6ff2498b0cffd0a89d74e823700ffa Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Tue, 13 Nov 2018 18:36:42 +0200 Subject: iwlwifi: mvm: disable completely low latency mode with debugfs We introduce a new state for latency, force mode, in force mode you can enable always to be in low latency or always to be in non low latency. This is required for test mode in max TpT test. Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/mvm/debugfs-vif.c | 53 ++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 58 ++++++++++++++++++++-- 2 files changed, 103 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 1c0f84049573..2453ceabf00d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -543,21 +543,64 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf, return count; } +static ssize_t +iwl_dbgfs_low_latency_force_write(struct ieee80211_vif *vif, char *buf, + size_t count, loff_t *ppos) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm *mvm = mvmvif->mvm; + u8 value; + int ret; + + ret = kstrtou8(buf, 0, &value); + if (ret) + return ret; + + if (value > NUM_LOW_LATENCY_FORCE) + return -EINVAL; + + mutex_lock(&mvm->mutex); + if (value == LOW_LATENCY_FORCE_UNSET) { + iwl_mvm_update_low_latency(mvm, vif, false, + LOW_LATENCY_DEBUGFS_FORCE); + iwl_mvm_update_low_latency(mvm, vif, false, + LOW_LATENCY_DEBUGFS_FORCE_ENABLE); + } else { + iwl_mvm_update_low_latency(mvm, vif, + value == LOW_LATENCY_FORCE_ON, + LOW_LATENCY_DEBUGFS_FORCE); + iwl_mvm_update_low_latency(mvm, vif, true, + LOW_LATENCY_DEBUGFS_FORCE_ENABLE); + } + mutex_unlock(&mvm->mutex); + return count; +} + static ssize_t iwl_dbgfs_low_latency_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ieee80211_vif *vif = file->private_data; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - char buf[30] = {}; + char format[] = "traffic=%d\ndbgfs=%d\nvcmd=%d\nvif_type=%d\n" + "dbgfs_force_enable=%d\ndbgfs_force=%d\nactual=%d\n"; + + /* + * all values in format are boolean so the size of format is enough + * for holding the result string + */ + char buf[sizeof(format) + 1] = {}; int len; - len = scnprintf(buf, sizeof(buf) - 1, - "traffic=%d\ndbgfs=%d\nvcmd=%d\nvif_type=%d\n", + len = scnprintf(buf, sizeof(buf) - 1, format, !!(mvmvif->low_latency & LOW_LATENCY_TRAFFIC), !!(mvmvif->low_latency & LOW_LATENCY_DEBUGFS), !!(mvmvif->low_latency & LOW_LATENCY_VCMD), - !!(mvmvif->low_latency & LOW_LATENCY_VIF_TYPE)); + !!(mvmvif->low_latency & LOW_LATENCY_VIF_TYPE), + !!(mvmvif->low_latency & + LOW_LATENCY_DEBUGFS_FORCE_ENABLE), + !!(mvmvif->low_latency & LOW_LATENCY_DEBUGFS_FORCE), + !!(mvmvif->low_latency_actual)); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -710,6 +753,7 @@ MVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt); MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32); MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256); MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10); +MVM_DEBUGFS_WRITE_FILE_OPS(low_latency_force, 10); MVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20); MVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10); MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32); @@ -745,6 +789,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt, mvmvif->dbgfs_dir, 0400); MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, 0400); MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir, 0600); + MVM_DEBUGFS_ADD_FILE_VIF(low_latency_force, mvmvif->dbgfs_dir, 0600); MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving, mvmvif->dbgfs_dir, 0600); MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir, 0600); MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, 0600); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 59d655436a8f..5c9adf72691f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -299,18 +299,39 @@ enum iwl_bt_force_ant_mode { BT_FORCE_ANT_MAX, }; +/** + * struct iwl_mvm_low_latency_force - low latency force mode set by debugfs + * @LOW_LATENCY_FORCE_UNSET: unset force mode + * @LOW_LATENCY_FORCE_ON: for low latency on + * @LOW_LATENCY_FORCE_OFF: for low latency off + * @NUM_LOW_LATENCY_FORCE: max num of modes + */ +enum iwl_mvm_low_latency_force { + LOW_LATENCY_FORCE_UNSET, + LOW_LATENCY_FORCE_ON, + LOW_LATENCY_FORCE_OFF, + NUM_LOW_LATENCY_FORCE +}; + /** * struct iwl_mvm_low_latency_cause - low latency set causes * @LOW_LATENCY_TRAFFIC: indicates low latency traffic was detected * @LOW_LATENCY_DEBUGFS: low latency mode set from debugfs * @LOW_LATENCY_VCMD: low latency mode set from vendor command * @LOW_LATENCY_VIF_TYPE: low latency mode set because of vif type (ap) +* @LOW_LATENCY_DEBUGFS_FORCE_ENABLE: indicate that force mode is enabled +* the actual set/unset is done with LOW_LATENCY_DEBUGFS_FORCE +* @LOW_LATENCY_DEBUGFS_FORCE: low latency force mode from debugfs +* set this with LOW_LATENCY_DEBUGFS_FORCE_ENABLE flag +* in low_latency. */ enum iwl_mvm_low_latency_cause { LOW_LATENCY_TRAFFIC = BIT(0), LOW_LATENCY_DEBUGFS = BIT(1), LOW_LATENCY_VCMD = BIT(2), LOW_LATENCY_VIF_TYPE = BIT(3), + LOW_LATENCY_DEBUGFS_FORCE_ENABLE = BIT(4), + LOW_LATENCY_DEBUGFS_FORCE = BIT(5), }; /** @@ -361,8 +382,10 @@ struct iwl_probe_resp_data { * @pm_enabled - Indicate if MAC power management is allowed * @monitor_active: indicates that monitor context is configured, and that the * interface should get quota etc. - * @low_latency: indicates low latency is set, see - * enum &iwl_mvm_low_latency_cause for causes. + * @low_latency: bit flags for low latency + * see enum &iwl_mvm_low_latency_cause for causes. + * @low_latency_actual: boolean, indicates low latency is set, + * as a result from low_latency bit flags and takes force into account. * @ps_disabled: indicates that this interface requires PS to be disabled * @queue_params: QoS params for this MAC * @bcast_sta: station used for broadcast packets. Used by the following @@ -394,7 +417,8 @@ struct iwl_mvm_vif { bool ap_ibss_active; bool pm_enabled; bool monitor_active; - u8 low_latency; + u8 low_latency: 6; + u8 low_latency_actual: 1; bool ps_disabled; struct iwl_mvm_vif_bf_data bf_data; @@ -1918,17 +1942,43 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) * binding, so this has no real impact. For now, just return * the current desired low-latency state. */ - return mvmvif->low_latency; + return mvmvif->low_latency_actual; } static inline void iwl_mvm_vif_set_low_latency(struct iwl_mvm_vif *mvmvif, bool set, enum iwl_mvm_low_latency_cause cause) { + u8 new_state; + if (set) mvmvif->low_latency |= cause; else mvmvif->low_latency &= ~cause; + + /* + * if LOW_LATENCY_DEBUGFS_FORCE_ENABLE is enabled no changes are + * allowed to actual mode. + */ + if (mvmvif->low_latency & LOW_LATENCY_DEBUGFS_FORCE_ENABLE && + cause != LOW_LATENCY_DEBUGFS_FORCE_ENABLE) + return; + + if (cause == LOW_LATENCY_DEBUGFS_FORCE_ENABLE && set) + /* + * We enter force state + */ + new_state = !!(mvmvif->low_latency & + LOW_LATENCY_DEBUGFS_FORCE); + else + /* + * Check if any other one set low latency + */ + new_state = !!(mvmvif->low_latency & + ~(LOW_LATENCY_DEBUGFS_FORCE_ENABLE | + LOW_LATENCY_DEBUGFS_FORCE)); + + mvmvif->low_latency_actual = new_state; } /* Return a bitmask with all the hw supported queues, except for the -- cgit v1.2.3 From 98f0d01abcb98b69e3b838f1c46ab9bb9ad0fa84 Mon Sep 17 00:00:00 2001 From: Ihab Zhaika Date: Tue, 20 Nov 2018 09:33:57 +0200 Subject: iwlwifi: update product name for 9260 and 9560 update the product name for the some of the cards from the series of 9260 and 9560 Signed-off-by: Ihab Zhaika Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 6 + drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 29 ++++ drivers/net/wireless/intel/iwlwifi/iwl-config.h | 5 + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 188 ++++++++++++------------ 4 files changed, 134 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 285e02e1e7b7..eb93711d474b 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -269,6 +269,12 @@ const struct iwl_cfg iwl9560_2ac_cfg_qu_b0_jf_b0 = { IWL_DEVICE_22500, }; +const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0 = { + .name = "Intel(R) Wireless-AC 9560 160MHz", + .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, + IWL_DEVICE_22500, +}; + const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = { .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 09618f176f4f..113bcf7735a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -163,6 +163,12 @@ const struct iwl_cfg iwl9260_2ac_cfg = { IWL_DEVICE_9000, }; +const struct iwl_cfg iwl9260_2ac_160_cfg = { + .name = "Intel(R) Wireless-AC 9260 160MHz", + .fw_name_pre = IWL9260_FW_PRE, + IWL_DEVICE_9000, +}; + const struct iwl_cfg iwl9260_killer_2ac_cfg = { .name = "Killer (R) Wireless-AC 1550 Wireless Network Adapter (9260NGW)", .fw_name_pre = IWL9260_FW_PRE, @@ -211,6 +217,12 @@ const struct iwl_cfg iwl9560_2ac_cfg = { IWL_DEVICE_9000, }; +const struct iwl_cfg iwl9560_2ac_160_cfg = { + .name = "Intel(R) Wireless-AC 9560 160MHz", + .fw_name_pre = IWL9260_FW_PRE, + IWL_DEVICE_9000, +}; + const struct iwl_cfg iwl9560_2ac_cfg_soc = { .name = "Intel(R) Dual Band Wireless AC 9560", .fw_name_pre = IWL9000_FW_PRE, @@ -219,6 +231,14 @@ const struct iwl_cfg iwl9560_2ac_cfg_soc = { .soc_latency = 5000, }; +const struct iwl_cfg iwl9560_2ac_160_cfg_soc = { + .name = "Intel(R) Wireless-AC 9560 160MHz", + .fw_name_pre = IWL9000_FW_PRE, + IWL_DEVICE_9000, + .integrated = true, + .soc_latency = 5000, +}; + const struct iwl_cfg iwl9560_killer_2ac_cfg_soc = { .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", .fw_name_pre = IWL9000_FW_PRE, @@ -271,6 +291,15 @@ const struct iwl_cfg iwl9560_2ac_cfg_shared_clk = { .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK }; +const struct iwl_cfg iwl9560_2ac_160_cfg_shared_clk = { + .name = "Intel(R) Wireless-AC 9560 160MHz", + .fw_name_pre = IWL9000_FW_PRE, + IWL_DEVICE_9000, + .integrated = true, + .soc_latency = 5000, + .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK +}; + const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk = { .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", .fw_name_pre = IWL9000_FW_PRE, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 7698cadd4ff9..ff942532fac3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -545,20 +545,24 @@ extern const struct iwl_cfg iwl8275_2ac_cfg; extern const struct iwl_cfg iwl4165_2ac_cfg; extern const struct iwl_cfg iwl9160_2ac_cfg; extern const struct iwl_cfg iwl9260_2ac_cfg; +extern const struct iwl_cfg iwl9260_2ac_160_cfg; extern const struct iwl_cfg iwl9260_killer_2ac_cfg; extern const struct iwl_cfg iwl9270_2ac_cfg; extern const struct iwl_cfg iwl9460_2ac_cfg; extern const struct iwl_cfg iwl9560_2ac_cfg; +extern const struct iwl_cfg iwl9560_2ac_160_cfg; extern const struct iwl_cfg iwl9460_2ac_cfg_soc; extern const struct iwl_cfg iwl9461_2ac_cfg_soc; extern const struct iwl_cfg iwl9462_2ac_cfg_soc; extern const struct iwl_cfg iwl9560_2ac_cfg_soc; +extern const struct iwl_cfg iwl9560_2ac_160_cfg_soc; extern const struct iwl_cfg iwl9560_killer_2ac_cfg_soc; extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_soc; extern const struct iwl_cfg iwl9460_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9461_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9462_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9560_2ac_cfg_shared_clk; +extern const struct iwl_cfg iwl9560_2ac_160_cfg_shared_clk; extern const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl22000_2ac_cfg_hr; @@ -574,6 +578,7 @@ extern const struct iwl_cfg killer1650w_2ax_cfg; extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0; extern const struct iwl_cfg iwl9462_2ac_cfg_qu_b0_jf_b0; extern const struct iwl_cfg iwl9560_2ac_cfg_qu_b0_jf_b0; +extern const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0; extern const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0; extern const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0; extern const struct iwl_cfg iwl22000_2ax_cfg_jf; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 461135f8cef1..a22e47639a4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -513,10 +513,10 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x24FD, 0x9074, iwl8265_2ac_cfg)}, /* 9000 Series */ - {IWL_PCI_DEVICE(0x02F0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -531,17 +531,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x02F0, 0x02A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x02F0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x4030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x06F0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x06F0, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x06F0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -556,21 +556,21 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x06F0, 0x02A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x06F0, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x06F0, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x06F0, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x06F0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x4030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0014, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0018, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x001C, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0030, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0014, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0018, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x001C, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0030, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x003C, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x003C, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0060, iwl9460_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0064, iwl9460_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x00A0, iwl9460_2ac_cfg)}, @@ -594,26 +594,26 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x1552, iwl9560_killer_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x1610, iwl9270_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x8014, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x8010, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0214, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x271C, 0x0214, iwl9260_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -631,17 +631,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2720, 0x1210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2720, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x003C, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0060, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -659,17 +659,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x30DC, 0x1210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x30DC, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x30DC, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x4030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_160_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_160_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_160_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x0060, iwl9460_2ac_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x0064, iwl9461_2ac_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x00A0, iwl9462_2ac_cfg_shared_clk)}, @@ -687,18 +687,18 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x31DC, 0x1210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x31DC, 0x1551, iwl9560_killer_s_2ac_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x1552, iwl9560_killer_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x2030, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x2034, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x2030, iwl9560_2ac_160_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x2034, iwl9560_2ac_160_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_160_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_160_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x40A4, iwl9462_2ac_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x4234, iwl9560_2ac_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x31DC, 0x42A4, iwl9462_2ac_cfg_shared_clk)}, - {IWL_PCI_DEVICE(0x34F0, 0x0030, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x0030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x34F0, 0x003C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, @@ -713,18 +713,18 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x34F0, 0x02A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x1551, killer1550s_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x1552, killer1550i_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x34F0, 0x2030, iwl9560_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x34F0, 0x2034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x34F0, 0x4030, iwl9560_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x34F0, 0x4034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x2030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x2034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x4030, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x4034, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x40A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x4234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x42A4, iwl9462_2ac_cfg_qu_b0_jf_b0)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x3DF0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0038, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x003C, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x3DF0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x3DF0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x3DF0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -742,17 +742,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x3DF0, 0x1210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x3DF0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x3DF0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x3DF0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x4030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x3DF0, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x3DF0, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x3DF0, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -770,19 +770,19 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x43F0, 0x1210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x43F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x43F0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x4030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x42A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0000, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0010, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x0038, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x003C, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0060, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -808,18 +808,18 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x9DF0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x2010, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x2034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x2034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x9DF0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x4030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -837,17 +837,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA0F0, 0x1210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0xA0F0, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA0F0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x42A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x0038, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x003C, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x0060, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -865,10 +865,10 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA370, 0x1210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0xA370, 0x1551, iwl9560_killer_s_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x1552, iwl9560_killer_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x2030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x2034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0xA370, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x2030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x2034, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x4030, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x4034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)}, @@ -891,7 +891,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x06F0, 0x4070, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0030, iwl22000_2ac_cfg_hr_cdb)}, + {IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x0040, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0074, iwl22560_2ax_cfg_hr)}, -- cgit v1.2.3 From 81444538ac586613e7ac3f04a85be2c22bc8a550 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 20 Nov 2018 17:14:06 +0100 Subject: iwlwifi: mvm: document monitor mode reorder buffer bypass The reorder buffer is bypassed because the firmware won't have any BA sessions, document this. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 7b6f4585fec9..9fde322904f4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -658,6 +658,8 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, * This also covers the case of receiving a Block Ack Request * outside a BA session; we'll pass it to mac80211 and that * then sends a delBA action frame. + * This also covers pure monitor mode, in which case we won't + * have any BA sessions. */ if (baid == IWL_RX_REORDER_DATA_INVALID_BAID) return false; -- cgit v1.2.3 From 9bf13bee2d74a3b7bc0a59b1af7ad5f0a37f2176 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 20 Nov 2018 17:58:46 +0100 Subject: iwlwifi: mvm: include configured sniffer AID in radiotap In order to make more sense out of the captured radiotap data e.g. when the configured AID changes, add the currently configured AID to the radiotap data as a vendor extension field. This is made race-free by updating the included value from inside the RX path (using a notification wait) for the command response from the firmware, which thus means it's serialized with frame RX. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 44 ++++++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 4 +++ drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 39 +++++++++++++++++--- 4 files changed, 84 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 91b46361ac9f..e136475a34f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1682,11 +1682,33 @@ iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf, return ret ?: count; } +struct iwl_mvm_sniffer_apply { + struct iwl_mvm *mvm; + u16 aid; +}; + +static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data, + struct iwl_rx_packet *pkt, void *data) +{ + struct iwl_mvm_sniffer_apply *apply = data; + + apply->mvm->cur_aid = cpu_to_le16(apply->aid); + + return true; +} + static ssize_t iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { + struct iwl_notification_wait wait; struct iwl_he_monitor_cmd he_mon_cmd = {}; + struct iwl_mvm_sniffer_apply apply = { + .mvm = mvm, + }; + u16 wait_cmds[] = { + iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD, DATA_PATH_GROUP, 0), + }; u32 aid; int ret; @@ -1702,10 +1724,30 @@ iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf, he_mon_cmd.aid = cpu_to_le16(aid); + apply.aid = aid; + mutex_lock(&mvm->mutex); + + /* + * Use the notification waiter to get our function triggered + * in sequence with other RX. This ensures that frames we get + * on the RX queue _before_ the new configuration is applied + * still have mvm->cur_aid pointing to the old AID, and that + * frames on the RX queue _after_ the firmware processed the + * new configuration (and sent the response, synchronously) + * get mvm->cur_aid correctly set to the new AID. + */ + iwl_init_notification_wait(&mvm->notif_wait, &wait, + wait_cmds, ARRAY_SIZE(wait_cmds), + iwl_mvm_sniffer_apply, &apply); + ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD, DATA_PATH_GROUP, 0), 0, sizeof(he_mon_cmd), &he_mon_cmd); + + /* no need to really wait, we already did anyway */ + iwl_remove_notification(&mvm->notif_wait, &wait); + mutex_unlock(&mvm->mutex); return ret ?: count; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index d4b05caabc74..531d2de131da 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1167,6 +1167,8 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) iwl_mvm_stop_device(mvm); + mvm->cur_aid = 0; + mvm->scan_status = 0; mvm->ps_disabled = false; mvm->calibrating = false; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5c9adf72691f..ac526b412aa6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1164,6 +1164,10 @@ struct iwl_mvm { /* does a monitor vif exist (only one can exist hence bool) */ bool monitor_on; + + /* sniffer data to include in radiotap */ + __le16 cur_aid; + #ifdef CONFIG_ACPI struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM]; struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES]; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 9fde322904f4..79860f6ac7ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -192,11 +192,40 @@ static void iwl_mvm_create_skb(struct sk_buff *skb, struct ieee80211_hdr *hdr, } } +static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, + struct sk_buff *skb) +{ + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_vendor_radiotap *radiotap; + int size = sizeof(*radiotap) + sizeof(__le16); + + if (!mvm->cur_aid) + return; + + radiotap = skb_put(skb, size); + radiotap->align = 1; + /* Intel OUI */ + radiotap->oui[0] = 0xf6; + radiotap->oui[1] = 0x54; + radiotap->oui[2] = 0x25; + /* radiotap sniffer config sub-namespace */ + radiotap->subns = 1; + radiotap->present = 0x1; + radiotap->len = size - sizeof(*radiotap); + radiotap->pad = 0; + + /* fill the data now */ + memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid)); + + rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA; +} + /* iwl_mvm_pass_packet_to_mac80211 - passes the packet for mac80211 */ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, struct napi_struct *napi, struct sk_buff *skb, int queue, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, + bool csi) { struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); @@ -465,7 +494,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm, while ((skb = __skb_dequeue(skb_list))) { iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, reorder_buf->queue, - sta); + sta, false); reorder_buf->num_stored--; } } @@ -1304,6 +1333,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, .d4 = desc->phy_data4, .info_type = IWL_RX_PHY_INFO_TYPE_NONE, }; + bool csi = false; if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))) return; @@ -1599,7 +1629,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, iwl_mvm_create_skb(skb, hdr, len, crypt_len, rxb); if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc)) - iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta); + iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, + sta, csi); out: rcu_read_unlock(); } @@ -1732,7 +1763,7 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->rate_idx = rate; } - iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta); + iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta, false); out: rcu_read_unlock(); } -- cgit v1.2.3 From 487ec49c358a5c9d4fed386cee7f17a81572a7df Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 22 Nov 2018 08:01:30 +0200 Subject: iwlwifi: trigger dump on assert prior to setting the device up In the regular flow, when we receive an assert, ieee80211_reconfig is called which reconfig the driver using iwl_mvm_mac_start. iwl_mvm_mac_start is clearing the restart bit and does dump collection. Prior to setting the device up, ieee80211_reconfig does not call iwl_mvm_mac_start since there is nothing to reconfig and we miss the dump collection of the assert. solve it by checking the restart bit before we stop the device and trigger a dump collection in case it is set. note that we don't need to do it in the fmac case since in fmac assert flow in iwl_fmac_nic_error we call iwl_fw_dbg_collect_desc so we can be sure that there will a dump collection in iwl_fmac_stop_device. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index ac526b412aa6..12e9ecc3ee27 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1997,6 +1997,16 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) { lockdep_assert_held(&mvm->mutex); + /* If IWL_MVM_STATUS_HW_RESTART_REQUESTED bit is set then we received + * an assert. Since we failed to bring the interface up, mac80211 + * will not attempt to reconfig the device, + * which handles the dump collection in assert flow, + * so trigger dump collection here. + */ + if (test_and_clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status)) + iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, + false, 0); /* calling this function without using dump_start/end since at this * point we already hold the op mode mutex */ -- cgit v1.2.3 From 40ecdd01d46e67fddff4407f7c37554d9640d1ea Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Wed, 7 Nov 2018 18:51:06 +0200 Subject: iwlwifi: mvm: update firmware when MU EDCA params change When MU EDCA params change, resend the STA_HE_CTXT command updating the MU EDCA params. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 531d2de131da..c9effd7f0ef8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -2252,6 +2252,12 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); } + /* Update MU EDCA params */ + if (changes & BSS_CHANGED_QOS && mvmvif->associated && + bss_conf->assoc && vif->bss_conf.he_support && + !iwlwifi_mod_params.disable_11ax) + iwl_mvm_cfg_he_sta(mvm, vif, mvmvif->ap_sta_id); + /* * If we're not associated yet, take the (new) BSSID before associating * so the firmware knows. If we're already associated, then use the old -- cgit v1.2.3 From 07a44b322397b1a5e8c96ceef8ce352fe79ac7ee Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 26 Nov 2018 11:19:00 +0200 Subject: iwlwifi: dbg_ini: allocate dram buffer with proper flags Use the same flags we use in the legacy buffer allocation. Missing __GFP_NOWARN will cause an unwanted warning incase we fail to allocate. Missing __GFP_ZERO will give a buffer initially filled with garbage which can make debug difficult in case our wrap count is zero. Signed-off-by: Shahar S Matityahu Fixes: d47902f9f71d ("iwlwifi: dbg: add apply point logic") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 917aafe1a9db..947f282c05a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1697,8 +1697,10 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, IWL_FW_INI_LOCATION_DRAM_PATH) return; - virtual_addr = dma_alloc_coherent(fwrt->trans->dev, size, - &phys_addr, GFP_KERNEL); + virtual_addr = + dma_alloc_coherent(fwrt->trans->dev, size, &phys_addr, + GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO | + __GFP_COMP); /* TODO: alloc fragments if needed */ if (!virtual_addr) -- cgit v1.2.3 From cd0fc658fbb77b07b9bcd2fa315acfda40e02539 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 26 Nov 2018 11:02:54 +0200 Subject: iwlwifi: dbg_ini: properly handle ini user trigger in case of a user trigger while ini is enable we change FW_DBG_TRIGGER_USER to IWL_FW_TRIGGER_ID_USER_TRIGGER in iwl_fw_dbg_collect and then again we attempt to do so in _iwl_fw_error_ini_dump which causes to abort the dump. Fix it by removing the second check in _iwl_fw_error_ini_dump. Signed-off-by: Shahar S Matityahu Fixes: 7a14c23dcdee ("iwlwifi: dbg: dump data according to the new ini TLVs") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 947f282c05a9..07dc2919b0b4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1254,10 +1254,6 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, if (id == FW_DBG_TRIGGER_FW_ASSERT) id = IWL_FW_TRIGGER_ID_FW_ASSERT; - else if (id == FW_DBG_TRIGGER_USER) - id = IWL_FW_TRIGGER_ID_USER_TRIGGER; - else if (id < FW_DBG_TRIGGER_MAX) - return NULL; if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) return NULL; -- cgit v1.2.3 From b2aea95c183360e3a3add84e349915b87f3680b2 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 26 Nov 2018 10:34:37 +0200 Subject: iwlwifi: dbg_ini: retrieve dump_delay value properly The driver uses ignore_consec instead of dump_delay. Fix it by using dump_delay as expected. Signed-off-by: Shahar S Matityahu Fixes: fe1b7d6c2888 ("iwlwifi: add support for triggering ini triggers") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 07dc2919b0b4..02ad87022e78 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1489,7 +1489,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, if (WARN_ON(!fwrt->dump.active_trigs[id].active)) return -EINVAL; - delay = le32_to_cpu(fwrt->dump.active_trigs[id].conf->ignore_consec); + delay = le32_to_cpu(fwrt->dump.active_trigs[id].conf->dump_delay); occur = le32_to_cpu(fwrt->dump.active_trigs[id].conf->occurrences); if (!occur) return 0; -- cgit v1.2.3 From 55fbf0d21c443dc98a0c537d3db5a29be54c04de Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 26 Nov 2018 10:29:15 +0200 Subject: iwlwifi: dbg_ini: set dump mask BIT(n) instead of n The driver sets dump_mask value instead of BIT(value). fix it by updating dump_mask correctly. Signed-off-by: Shahar S Matityahu Fixes: 7a14c23dcdee ("iwlwifi: dbg: dump data according to the new ini TLVs") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 02ad87022e78..22efd94da6d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1216,13 +1216,13 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, iwl_dump_prph_ini(fwrt->trans, data, reg); break; case IWL_FW_INI_REGION_DRAM_BUFFER: - *dump_mask |= IWL_FW_ERROR_DUMP_FW_MONITOR; + *dump_mask |= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR); break; case IWL_FW_INI_REGION_PAGING: if (iwl_fw_dbg_is_paging_enabled(fwrt)) iwl_dump_paging(fwrt, data); else - *dump_mask |= IWL_FW_ERROR_DUMP_PAGING; + *dump_mask |= BIT(IWL_FW_ERROR_DUMP_PAGING); break; case IWL_FW_INI_REGION_TXF: iwl_fw_dump_txf(fwrt, data); -- cgit v1.2.3 From 01f377dc927da6e42cbffb00fc8d431c8341da3f Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 26 Nov 2018 11:33:09 +0200 Subject: iwiwifi: fix bad monitor buffer register addresses The monitor buffer register address is wrong. Set the right address Signed-off-by: Shahar S Matityahu Fixes: c2d202017da1 ("iwlwifi: pcie: add firmware monitor capabilities") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 9d89b7d7f9fa..3aaa5f06461c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -358,12 +358,12 @@ /* FW monitor */ #define MON_BUFF_SAMPLE_CTL (0xa03c00) -#define MON_BUFF_BASE_ADDR (0xa03c3c) +#define MON_BUFF_BASE_ADDR (0xa03c1c) #define MON_BUFF_END_ADDR (0xa03c40) #define MON_BUFF_WRPTR (0xa03c44) #define MON_BUFF_CYCLE_CNT (0xa03c48) /* FW monitor family 8000 and on */ -#define MON_BUFF_BASE_ADDR_VER2 (0xa03c3c) +#define MON_BUFF_BASE_ADDR_VER2 (0xa03c1c) #define MON_BUFF_END_ADDR_VER2 (0xa03c20) #define MON_BUFF_WRPTR_VER2 (0xa03c24) #define MON_BUFF_CYCLE_CNT_VER2 (0xa03c28) -- cgit v1.2.3 From 2de66bb87351086ce9bef37c1b98d9bae93eddcd Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Mon, 28 Jan 2019 15:08:09 -0800 Subject: Bluetooth: btusb: btusb_intel_cmd_timeout: use sleeping functions The btusb_intel_cmd_timeout() is called from workqueue contexts, so use the helper functions that can sleep. Signed-off-by: Rajat Jain Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 5de0c2e59b97..9a890b2a7ee1 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -523,9 +523,9 @@ static void btusb_intel_cmd_timeout(struct hci_dev *hdev) } bt_dev_err(hdev, "Initiating HW reset via gpio"); - gpiod_set_value(reset_gpio, 1); - mdelay(100); - gpiod_set_value(reset_gpio, 0); + gpiod_set_value_cansleep(reset_gpio, 1); + msleep(100); + gpiod_set_value_cansleep(reset_gpio, 0); } static inline void btusb_free_frags(struct btusb_data *data) -- cgit v1.2.3 From 017a01ccfbc5a35aed83acbf2ee2735f8c3efe8a Mon Sep 17 00:00:00 2001 From: Raghuram Hegde Date: Tue, 29 Jan 2019 17:54:48 +0530 Subject: Bluetooth: btusb: Add shutdown routine for BTUSB_INTEL_NEW devices If BT operations (BREDR inquiry/LE scan) were triggered through the stack, followed by BT turn off through 'hciconfig hci0 down', the controller would still be active and consume power. Also, there is a possibility that a race condition/ synchronization issue might arise on the subsequent BT turn on, as the controller might try to push the events that were queued up before processing the HCI Reset command. btusb_shutdown_intel_new routine shall reset the controller and stop all BT operation. Advantages: 1. Power save on the platform 2. Host and controller will be in Sync. Signed-off-by: Raghuram Hegde Signed-off-by: Chethan T N Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 9a890b2a7ee1..d4c8d989e714 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2434,6 +2434,24 @@ static int btusb_shutdown_intel(struct hci_dev *hdev) return 0; } +static int btusb_shutdown_intel_new(struct hci_dev *hdev) +{ + struct sk_buff *skb; + + /* Send HCI Reset to the controller to stop any BT activity which + * were triggered. This will help to save power and maintain the + * sync b/w Host and controller + */ + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "HCI reset during shutdown failed"); + return PTR_ERR(skb); + } + kfree_skb(skb); + + return 0; +} + #ifdef CONFIG_PM /* Configure an out-of-band gpio as wake-up pin, if specified in device tree */ static int marvell_config_oob_wake(struct hci_dev *hdev) @@ -3139,6 +3157,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->manufacturer = 2; hdev->send = btusb_send_frame_intel; hdev->setup = btusb_setup_intel_new; + hdev->shutdown = btusb_shutdown_intel_new; hdev->hw_error = btintel_hw_error; hdev->set_diag = btintel_set_diag; hdev->set_bdaddr = btintel_set_bdaddr; -- cgit v1.2.3 From 18d79f721e0a5338280cee1891800ff1f611502e Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Tue, 29 Jan 2019 15:20:19 +0530 Subject: cxgb4vf: Update port information in cxgb4vf_open() It's possible that the basic port information could have changed since we first read it. Signed-off-by: Arjun Vynipadath Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 2fab87e86561..1fa24af8099f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -791,6 +791,13 @@ static int cxgb4vf_open(struct net_device *dev) return err; } + /* It's possible that the basic port information could have + * changed since we first read it. + */ + err = t4vf_update_port_info(pi); + if (err < 0) + return err; + /* * Note that this interface is up and start everything up ... */ -- cgit v1.2.3 From 9f672984338d160aa262be7ad6d19fd182dc384d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 29 Jan 2019 10:44:44 -0600 Subject: cxgb4: clip_tbl: Use struct_size() in kvzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = kvzalloc(sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kvzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c index 5701272aa7f7..ce28820c57c9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c +++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c @@ -289,8 +289,7 @@ struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start, if (clipt_size < CLIPT_MIN_HASH_BUCKETS) return NULL; - ctbl = kvzalloc(sizeof(*ctbl) + - clipt_size*sizeof(struct list_head), GFP_KERNEL); + ctbl = kvzalloc(struct_size(ctbl, hash_list, clipt_size), GFP_KERNEL); if (!ctbl) return NULL; -- cgit v1.2.3 From c829f5f52db9bae0379b98fca2645f6ca9b0fb1e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 29 Jan 2019 11:05:23 -0600 Subject: cxgb4: cxgb4_tc_u32: use struct_size() in kvzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = kvzalloc(sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kvzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c index c7d2b4dc7568..02fc63fa7f25 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c @@ -444,8 +444,7 @@ struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap) if (!max_tids) return NULL; - t = kvzalloc(sizeof(*t) + - (max_tids * sizeof(struct cxgb4_link)), GFP_KERNEL); + t = kvzalloc(struct_size(t, table, max_tids), GFP_KERNEL); if (!t) return NULL; -- cgit v1.2.3 From 782a624d00fa22e7499f5abc29747501ec671313 Mon Sep 17 00:00:00 2001 From: Vasundhara Volam Date: Mon, 28 Jan 2019 18:00:27 +0530 Subject: bnxt_en: Add bnxt_en initial port params table and register it Register devlink_port with devlink and create initial port params table for bnxt_en. The table consists of a generic parameter: wake_on_lan: Enables Wake on Lan for this port when magic packet is received with this port's MAC address using ACPI pattern. If enabled, the controller asserts a wake pin upon reception of WoL packet. ACPI (Advanced Configuration and Power Interface) is an industry specification for the efficient handling of power consumption in desktop and mobile computers. v2->v3: - Modify bnxt_dl_wol_validate(), to throw error message when user gives value other than DEVLINK_PARAM_WAKE_MAGIC ot to disable WOL. - Use netdev_err() instead of netdev_warn(), when devlink_port_register() and devlink_port_params_register() returns error. Also, don't log rc in this message. Cc: Michael Chan Signed-off-by: Vasundhara Volam Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1 + drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 43 ++++++++++++++++++++++- drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index a451796deefe..5c886a700bcc 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1609,6 +1609,7 @@ struct bnxt { /* devlink interface and vf-rep structs */ struct devlink *dl; + struct devlink_port dl_port; enum devlink_eswitch_mode eswitch_mode; struct bnxt_vf_rep **vf_reps; /* array of vf-rep ptrs */ u16 *cfa_code_map; /* cfa_code -> vf_idx map */ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index 7f56032e44ac..a6abfa4fb168 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -37,6 +37,8 @@ static const struct bnxt_dl_nvm_param nvm_params[] = { NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7}, {BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK, BNXT_NVM_SHARED_CFG, 1}, + + {DEVLINK_PARAM_GENERIC_ID_WOL, NVM_OFF_WOL, BNXT_NVM_PORT_CFG, 1}, }; static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, @@ -70,7 +72,8 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, bytesize = roundup(nvm_param.num_bits, BITS_PER_BYTE) / BITS_PER_BYTE; switch (bytesize) { case 1: - if (nvm_param.num_bits == 1) + if (nvm_param.num_bits == 1 && + nvm_param.id != DEVLINK_PARAM_GENERIC_ID_WOL) buf = &val->vbool; else buf = &val->vu8; @@ -164,6 +167,17 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 id, return 0; } +static int bnxt_dl_wol_validate(struct devlink *dl, u32 id, + union devlink_param_value val, + struct netlink_ext_ack *extack) +{ + if (val.vu8 && val.vu8 != DEVLINK_PARAM_WAKE_MAGIC) { + NL_SET_ERR_MSG_MOD(extack, "WOL type is not supported"); + return -EINVAL; + } + return 0; +} + static const struct devlink_param bnxt_dl_params[] = { DEVLINK_PARAM_GENERIC(ENABLE_SRIOV, BIT(DEVLINK_PARAM_CMODE_PERMANENT), @@ -188,6 +202,12 @@ static const struct devlink_param bnxt_dl_params[] = { NULL), }; +static const struct devlink_param bnxt_dl_port_params[] = { + DEVLINK_PARAM_GENERIC(WOL, BIT(DEVLINK_PARAM_CMODE_PERMANENT), + bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, + bnxt_dl_wol_validate), +}; + int bnxt_dl_register(struct bnxt *bp) { struct devlink *dl; @@ -225,8 +245,26 @@ int bnxt_dl_register(struct bnxt *bp) goto err_dl_unreg; } + rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id); + if (rc) { + netdev_err(bp->dev, "devlink_port_register failed"); + goto err_dl_param_unreg; + } + devlink_port_type_eth_set(&bp->dl_port, bp->dev); + + rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params, + ARRAY_SIZE(bnxt_dl_port_params)); + if (rc) { + netdev_err(bp->dev, "devlink_port_params_register failed"); + goto err_dl_port_unreg; + } return 0; +err_dl_port_unreg: + devlink_port_unregister(&bp->dl_port); +err_dl_param_unreg: + devlink_params_unregister(dl, bnxt_dl_params, + ARRAY_SIZE(bnxt_dl_params)); err_dl_unreg: devlink_unregister(dl); err_dl_free: @@ -242,6 +280,9 @@ void bnxt_dl_unregister(struct bnxt *bp) if (!dl) return; + devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params, + ARRAY_SIZE(bnxt_dl_port_params)); + devlink_port_unregister(&bp->dl_port); devlink_params_unregister(dl, bnxt_dl_params, ARRAY_SIZE(bnxt_dl_params)); devlink_unregister(dl); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h index 5b6b2c7d97cf..da065ca84cc7 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h @@ -35,6 +35,7 @@ static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl) #define NVM_OFF_MSIX_VEC_PER_PF_MAX 108 #define NVM_OFF_MSIX_VEC_PER_PF_MIN 114 +#define NVM_OFF_WOL 152 #define NVM_OFF_IGNORE_ARI 164 #define NVM_OFF_DIS_GRE_VER_CHECK 171 #define NVM_OFF_ENABLE_SRIOV 401 -- cgit v1.2.3 From cb56e214679ffd1e30e980c56349831c5a00cfdf Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 30 Jan 2019 08:58:33 +0000 Subject: mlxsw: spectrum_acl: Include delta bits into hashtable key Currently only ERP mask masked bits in key are considered for the hashtable key. That leads to false negative collisions and fallbacks to C-TCAM in case two keys differ only in delta bits. Fix this by taking full encoded key as a hashtable key, including delta bits. Reported-by: Nir Dotan Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_atcam.c | 21 ++++++++++----------- .../mellanox/mlxsw/spectrum_acl_bloom_filter.c | 2 +- .../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 10 ++++++---- 3 files changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index 40dc76a5c412..cda0a7170c34 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -390,8 +390,7 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, if (err) return err; - lkey_id = aregion->ops->lkey_id_get(aregion, aentry->ht_key.enc_key, - erp_id); + lkey_id = aregion->ops->lkey_id_get(aregion, aentry->enc_key, erp_id); if (IS_ERR(lkey_id)) return PTR_ERR(lkey_id); aentry->lkey_id = lkey_id; @@ -399,7 +398,7 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block); mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_WRITE, priority, region->tcam_region_info, - aentry->ht_key.enc_key, erp_id, + aentry->enc_key, erp_id, aentry->delta_info.start, aentry->delta_info.mask, aentry->delta_info.value, @@ -424,12 +423,11 @@ mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_lkey_id *lkey_id = aentry->lkey_id; struct mlxsw_sp_acl_tcam_region *region = aregion->region; u8 erp_id = mlxsw_sp_acl_erp_mask_erp_id(aentry->erp_mask); - char *enc_key = aentry->ht_key.enc_key; char ptce3_pl[MLXSW_REG_PTCE3_LEN]; mlxsw_reg_ptce3_pack(ptce3_pl, false, MLXSW_REG_PTCE3_OP_WRITE_WRITE, 0, region->tcam_region_info, - enc_key, erp_id, + aentry->enc_key, erp_id, aentry->delta_info.start, aentry->delta_info.mask, aentry->delta_info.value, @@ -458,7 +456,7 @@ mlxsw_sp_acl_atcam_region_entry_action_replace(struct mlxsw_sp *mlxsw_sp, kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block); mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_UPDATE, priority, region->tcam_region_info, - aentry->ht_key.enc_key, erp_id, + aentry->enc_key, erp_id, aentry->delta_info.start, aentry->delta_info.mask, aentry->delta_info.value, @@ -481,15 +479,15 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, int err; mlxsw_afk_encode(afk, region->key_info, &rulei->values, - aentry->full_enc_key, mask); + aentry->ht_key.full_enc_key, mask); erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, false); if (IS_ERR(erp_mask)) return PTR_ERR(erp_mask); aentry->erp_mask = erp_mask; aentry->ht_key.erp_id = mlxsw_sp_acl_erp_mask_erp_id(erp_mask); - memcpy(aentry->ht_key.enc_key, aentry->full_enc_key, - sizeof(aentry->ht_key.enc_key)); + memcpy(aentry->enc_key, aentry->ht_key.full_enc_key, + sizeof(aentry->enc_key)); /* Compute all needed delta information and clear the delta bits * from the encrypted key. @@ -498,8 +496,9 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, aentry->delta_info.start = mlxsw_sp_acl_erp_delta_start(delta); aentry->delta_info.mask = mlxsw_sp_acl_erp_delta_mask(delta); aentry->delta_info.value = - mlxsw_sp_acl_erp_delta_value(delta, aentry->full_enc_key); - mlxsw_sp_acl_erp_delta_clear(delta, aentry->ht_key.enc_key); + mlxsw_sp_acl_erp_delta_value(delta, + aentry->ht_key.full_enc_key); + mlxsw_sp_acl_erp_delta_clear(delta, aentry->enc_key); /* Add rule to the list of A-TCAM rules, assuming this * rule is intended to A-TCAM. In case this rule does diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c index f5c381dcb015..9545b572747e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c @@ -133,7 +133,7 @@ mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion, memcpy(chunk + MLXSW_BLOOM_CHUNK_PAD_BYTES, &erp_region_id, sizeof(erp_region_id)); memcpy(chunk + MLXSW_BLOOM_CHUNK_KEY_OFFSET, - &aentry->ht_key.enc_key[chunk_key_offsets[chunk_index]], + &aentry->enc_key[chunk_key_offsets[chunk_index]], MLXSW_BLOOM_CHUNK_KEY_BYTES); chunk += MLXSW_BLOOM_KEY_CHUNK_BYTES; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 10512b7c6d50..0858d5b06353 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -161,9 +161,9 @@ struct mlxsw_sp_acl_atcam_region { }; struct mlxsw_sp_acl_atcam_entry_ht_key { - char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key, - * minus delta bits. - */ + char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded + * key. + */ u8 erp_id; }; @@ -175,7 +175,9 @@ struct mlxsw_sp_acl_atcam_entry { struct rhash_head ht_node; struct list_head list; /* Member in entries_list */ struct mlxsw_sp_acl_atcam_entry_ht_key ht_key; - char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */ + char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key, + * minus delta bits. + */ struct { u16 start; u8 mask; -- cgit v1.2.3 From a97cfe4de1bee89db3286ad0a4201dc6d2b72456 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 30 Jan 2019 08:58:34 +0000 Subject: mlxsw: spectrum_acl: Add C-TCAM spill tracepoint Add some visibility to the rule addition process and trace whenever rule spilled into C-TCAM. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_atcam.c | 3 ++ include/trace/events/mlxsw.h | 38 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 include/trace/events/mlxsw.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index cda0a7170c34..a74a390901ac 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -7,6 +7,8 @@ #include #include #include +#define CREATE_TRACE_POINTS +#include #include "reg.h" #include "core.h" @@ -578,6 +580,7 @@ int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, /* It is possible we failed to add the rule to the A-TCAM due to * exceeded number of masks. Try to spill into C-TCAM. */ + trace_mlxsw_sp_acl_atcam_entry_add_ctcam_spill(mlxsw_sp, aregion); err = mlxsw_sp_acl_ctcam_entry_add(mlxsw_sp, &aregion->cregion, &achunk->cchunk, &aentry->centry, rulei, true); diff --git a/include/trace/events/mlxsw.h b/include/trace/events/mlxsw.h new file mode 100644 index 000000000000..6c2bafcade18 --- /dev/null +++ b/include/trace/events/mlxsw.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ +/* Copyright (c) 2019 Mellanox Technologies. All rights reserved */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mlxsw + +#if !defined(_MLXSW_TRACEPOINT_H) || defined(TRACE_HEADER_MULTI_READ) +#define _MLXSW_TRACEPOINT_H + +#include + +struct mlxsw_sp; +struct mlxsw_sp_acl_atcam_region; + +TRACE_EVENT(mlxsw_sp_acl_atcam_entry_add_ctcam_spill, + TP_PROTO(const struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_acl_atcam_region *aregion), + + TP_ARGS(mlxsw_sp, aregion), + + TP_STRUCT__entry( + __field(const void *, mlxsw_sp) + __field(const void *, aregion) + ), + + TP_fast_assign( + __entry->mlxsw_sp = mlxsw_sp; + __entry->aregion = aregion; + ), + + TP_printk("mlxsw_sp %p, aregion %p", + __entry->mlxsw_sp, __entry->aregion) +); + +#endif /* _MLXSW_TRACEPOINT_H */ + +/* This part must be outside protection */ +#include -- cgit v1.2.3 From 889bcbdeee57376b7724e3cff46931c1a951bf3e Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Wed, 30 Jan 2019 11:24:04 +1000 Subject: net: ethernet: mediatek: support MT7621 SoC ethernet hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Mediatek MT7621 SoC contains the same ethernet hardware module as used on a number of other MediaTek SoC parts. There are some minor differences to deal with but we can use the same driver to support them all. This patch is based on work by Bjørn Mork , and his original patch is at: https://github.com/bmork/LEDE/commit/3293bc63f5461ca1eb0bbc4ed90145335e7e3404 There is an additional compatible devicetree type added, and the primary change to the code required is to support a single interrupt (for both RX and TX interrupts). Signed-off-by: Bjørn Mork [gerg@kernel.org: rebase to mainline and irq handler fix] Signed-off-by: Greg Ungerer Reviewed-by: Florian Fainelli Acked-by: Sean Wang Signed-off-by: David S. Miller --- drivers/net/ethernet/mediatek/Kconfig | 2 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 48 ++++++++++++++++++++++++----- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 +++ 3 files changed, 46 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mediatek/Kconfig b/drivers/net/ethernet/mediatek/Kconfig index f9149d2a4694..43656f961891 100644 --- a/drivers/net/ethernet/mediatek/Kconfig +++ b/drivers/net/ethernet/mediatek/Kconfig @@ -1,6 +1,6 @@ config NET_VENDOR_MEDIATEK bool "MediaTek ethernet driver" - depends on ARCH_MEDIATEK + depends on ARCH_MEDIATEK || SOC_MT7621 ---help--- If you have a Mediatek SoC with ethernet, say Y. diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 49f926b7a91c..94d4663e3933 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1745,6 +1745,22 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth) return IRQ_HANDLED; } +static irqreturn_t mtk_handle_irq(int irq, void *_eth) +{ + struct mtk_eth *eth = _eth; + + if (mtk_r32(eth, MTK_PDMA_INT_MASK) & MTK_RX_DONE_INT) { + if (mtk_r32(eth, MTK_PDMA_INT_STATUS) & MTK_RX_DONE_INT) + mtk_handle_irq_rx(irq, _eth); + } + if (mtk_r32(eth, MTK_QDMA_INT_MASK) & MTK_TX_DONE_INT) { + if (mtk_r32(eth, MTK_QMTK_INT_STATUS) & MTK_TX_DONE_INT) + mtk_handle_irq_tx(irq, _eth); + } + + return IRQ_HANDLED; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void mtk_poll_controller(struct net_device *dev) { @@ -2485,7 +2501,10 @@ static int mtk_probe(struct platform_device *pdev) } for (i = 0; i < 3; i++) { - eth->irq[i] = platform_get_irq(pdev, i); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0) + eth->irq[i] = eth->irq[0]; + else + eth->irq[i] = platform_get_irq(pdev, i); if (eth->irq[i] < 0) { dev_err(&pdev->dev, "no IRQ%d resource found\n", i); return -ENXIO; @@ -2528,13 +2547,21 @@ static int mtk_probe(struct platform_device *pdev) goto err_deinit_hw; } - err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0, - dev_name(eth->dev), eth); - if (err) - goto err_free_dev; + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { + err = devm_request_irq(eth->dev, eth->irq[0], + mtk_handle_irq, 0, + dev_name(eth->dev), eth); + } else { + err = devm_request_irq(eth->dev, eth->irq[1], + mtk_handle_irq_tx, 0, + dev_name(eth->dev), eth); + if (err) + goto err_free_dev; - err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0, - dev_name(eth->dev), eth); + err = devm_request_irq(eth->dev, eth->irq[2], + mtk_handle_irq_rx, 0, + dev_name(eth->dev), eth); + } if (err) goto err_free_dev; @@ -2607,6 +2634,12 @@ static const struct mtk_soc_data mt2701_data = { .required_pctl = true, }; +static const struct mtk_soc_data mt7621_data = { + .caps = MTK_SHARED_INT, + .required_clks = MT7621_CLKS_BITMAP, + .required_pctl = false, +}; + static const struct mtk_soc_data mt7622_data = { .caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW | MTK_HWLRO, .required_clks = MT7622_CLKS_BITMAP, @@ -2621,6 +2654,7 @@ static const struct mtk_soc_data mt7623_data = { const struct of_device_id of_mtk_match[] = { { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data}, + { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data}, { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data}, { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data}, {}, diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h index 46819297fc3e..f7501997cea0 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -363,6 +363,7 @@ #define ETHSYS_CHIPID4_7 0x4 #define MT7623_ETH 7623 #define MT7622_ETH 7622 +#define MT7621_ETH 7621 /* ethernet subsystem config register */ #define ETHSYS_SYSCFG0 0x14 @@ -488,6 +489,8 @@ enum mtk_clks_map { BIT(MTK_CLK_SGMII_CDR_FB) | \ BIT(MTK_CLK_SGMII_CK) | \ BIT(MTK_CLK_ETH2PLL)) +#define MT7621_CLKS_BITMAP (0) + enum mtk_dev_state { MTK_HW_INIT, MTK_RESETTING @@ -567,6 +570,7 @@ struct mtk_rx_ring { #define MTK_DUAL_GMAC_SHARED_SGMII (BIT(11) | MTK_GMAC1_SGMII | \ MTK_GMAC2_SGMII) #define MTK_HWLRO BIT(12) +#define MTK_SHARED_INT BIT(13) #define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x)) /* struct mtk_eth_data - This is the structure holding all differences -- cgit v1.2.3 From ddda1ac116c852bb969541ed53cffef7255c4961 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Wed, 30 Jan 2019 11:24:05 +1000 Subject: net: dsa: mt7530: support the 7530 switch on the Mediatek MT7621 SoC The MediaTek MT7621 SoC device contains a 7530 switch, and the existing linux kernel 7530 DSA switch driver can be used with it. The bulk of the changes required stem from the 7621 having different regulator and pad setup. The existing setup of these in the 7530 driver appears to be very specific to its implemtation in the Mediatek 7623 SoC. (Not entirely surprising given the 7623 is a quad core ARM based SoC, and the 7621 is a dual core, dual thread MIPS based SoC). Create a new devicetree type, "mediatek,mt7621", to support the 7530 switch in the 7621 SoC. There appears to be no usable ID register to distinguish it from a 7530 in other hardware at runtime. This is used to carry out the appropriate configuration and setup. Signed-off-by: Greg Ungerer Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Acked-by: Sean Wang Signed-off-by: David S. Miller --- drivers/net/dsa/mt7530.c | 96 ++++++++++++++++++++++++++++-------------------- drivers/net/dsa/mt7530.h | 9 +++++ 2 files changed, 66 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index a8a2c728afba..c2b61500f958 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -621,17 +621,19 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int port, struct mt7530_priv *priv = ds->priv; if (phy_is_pseudo_fixed_link(phydev)) { - dev_dbg(priv->dev, "phy-mode for master device = %x\n", - phydev->interface); - - /* Setup TX circuit incluing relevant PAD and driving */ - mt7530_pad_clk_setup(ds, phydev->interface); - - /* 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); + if (priv->id == ID_MT7530) { + dev_dbg(priv->dev, "phy-mode for master device = %x\n", + phydev->interface); + + /* Setup TX circuit incluing relevant PAD and driving */ + mt7530_pad_clk_setup(ds, phydev->interface); + + /* 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); + } } else { u16 lcl_adv = 0, rmt_adv = 0; u8 flowctrl; @@ -687,6 +689,10 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv, /* Unknown unicast frame fordwarding to the cpu port */ mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port))); + /* Set CPU port number */ + if (priv->id == ID_MT7621) + mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port)); + /* CPU port gets connected to all user ports of * the switch */ @@ -1219,24 +1225,27 @@ mt7530_setup(struct dsa_switch *ds) * as two netdev instances. */ dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent; - priv->ethernet = syscon_node_to_regmap(dn); - if (IS_ERR(priv->ethernet)) - return PTR_ERR(priv->ethernet); - regulator_set_voltage(priv->core_pwr, 1000000, 1000000); - ret = regulator_enable(priv->core_pwr); - if (ret < 0) { - dev_err(priv->dev, - "Failed to enable core power: %d\n", ret); - return ret; - } + if (priv->id == ID_MT7530) { + priv->ethernet = syscon_node_to_regmap(dn); + if (IS_ERR(priv->ethernet)) + return PTR_ERR(priv->ethernet); + + regulator_set_voltage(priv->core_pwr, 1000000, 1000000); + ret = regulator_enable(priv->core_pwr); + if (ret < 0) { + dev_err(priv->dev, + "Failed to enable core power: %d\n", ret); + return ret; + } - regulator_set_voltage(priv->io_pwr, 3300000, 3300000); - ret = regulator_enable(priv->io_pwr); - if (ret < 0) { - dev_err(priv->dev, "Failed to enable io pwr: %d\n", - ret); - return ret; + regulator_set_voltage(priv->io_pwr, 3300000, 3300000); + ret = regulator_enable(priv->io_pwr); + if (ret < 0) { + dev_err(priv->dev, "Failed to enable io pwr: %d\n", + ret); + return ret; + } } /* Reset whole chip through gpio pin or memory-mapped registers for @@ -1326,6 +1335,13 @@ static const struct dsa_switch_ops mt7530_switch_ops = { .port_vlan_del = mt7530_port_vlan_del, }; +static const struct of_device_id mt7530_of_match[] = { + { .compatible = "mediatek,mt7621", .data = (void *)ID_MT7621, }, + { .compatible = "mediatek,mt7530", .data = (void *)ID_MT7530, }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mt7530_of_match); + static int mt7530_probe(struct mdio_device *mdiodev) { @@ -1356,13 +1372,21 @@ mt7530_probe(struct mdio_device *mdiodev) } } - priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); - if (IS_ERR(priv->core_pwr)) - return PTR_ERR(priv->core_pwr); + /* 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->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); - if (IS_ERR(priv->io_pwr)) - return PTR_ERR(priv->io_pwr); + if (priv->id == ID_MT7530) { + priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); + if (IS_ERR(priv->core_pwr)) + return PTR_ERR(priv->core_pwr); + + priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); + if (IS_ERR(priv->io_pwr)) + return PTR_ERR(priv->io_pwr); + } /* Not MCM that indicates switch works as the remote standalone * integrated circuit so the GPIO pin would be used to complete @@ -1408,12 +1432,6 @@ mt7530_remove(struct mdio_device *mdiodev) mutex_destroy(&priv->reg_mutex); } -static const struct of_device_id mt7530_of_match[] = { - { .compatible = "mediatek,mt7530" }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, mt7530_of_match); - static struct mdio_driver mt7530_mdio_driver = { .probe = mt7530_probe, .remove = mt7530_remove, diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index d9b407a22a58..a95ed958df5b 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -19,6 +19,11 @@ #define MT7530_NUM_FDB_RECORDS 2048 #define MT7530_ALL_MEMBERS 0xff +enum { + ID_MT7530 = 0, + ID_MT7621 = 1, +}; + #define NUM_TRGMII_CTRL 5 #define TRGMII_BASE(x) (0x10000 + (x)) @@ -36,6 +41,9 @@ #define UNM_FFP(x) (((x) & 0xff) << 16) #define UNU_FFP(x) (((x) & 0xff) << 8) #define UNU_FFP_MASK UNU_FFP(~0) +#define CPU_EN BIT(7) +#define CPU_PORT(x) ((x) << 4) +#define CPU_MASK (0xf << 4) /* Registers for address table access */ #define MT7530_ATA1 0x74 @@ -430,6 +438,7 @@ struct mt7530_priv { struct regulator *core_pwr; struct regulator *io_pwr; struct gpio_desc *reset; + unsigned int id; bool mcm; struct mt7530_port ports[MT7530_NUM_PORTS]; -- cgit v1.2.3 From 1a6e552df33c0dca4fecd0a179833d1b5233012a Mon Sep 17 00:00:00 2001 From: liyongxin Date: Thu, 31 Jan 2019 04:55:41 +0800 Subject: net: hns3: reuse the definition of l3 and l4 header info union Union l3_hdr_info and l4_hdr_info have already been defined in the hns3_enet.h, so it is unnecessary to define them elsewhere. This patch removes the redundant definition, and reuses the one defined in the hns3_enet.h. Signed-off-by: liyongxin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 32 ++++--------------------- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 1 + 2 files changed, 6 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 4b38c37eef8f..048b5fbdf8fa 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -655,11 +655,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen, static int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto, u8 *il4_proto) { - union { - struct iphdr *v4; - struct ipv6hdr *v6; - unsigned char *hdr; - } l3; + union l3_hdr_info l3; unsigned char *l4_hdr; unsigned char *exthdr; u8 l4_proto_tmp; @@ -712,17 +708,8 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto, u8 il4_proto, u32 *type_cs_vlan_tso, u32 *ol_type_vlan_len_msec) { - union { - struct iphdr *v4; - struct ipv6hdr *v6; - unsigned char *hdr; - } l3; - union { - struct tcphdr *tcp; - struct udphdr *udp; - struct gre_base_hdr *gre; - unsigned char *hdr; - } l4; + union l3_hdr_info l3; + union l4_hdr_info l4; unsigned char *l2_hdr; u8 l4_proto = ol4_proto; u32 ol2_len; @@ -821,12 +808,7 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto, static bool hns3_tunnel_csum_bug(struct sk_buff *skb) { #define IANA_VXLAN_PORT 4789 - union { - struct tcphdr *tcp; - struct udphdr *udp; - struct gre_base_hdr *gre; - unsigned char *hdr; - } l4; + union l4_hdr_info l4; l4.hdr = skb_transport_header(skb); @@ -842,11 +824,7 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto, u8 il4_proto, u32 *type_cs_vlan_tso, u32 *ol_type_vlan_len_msec) { - union { - struct iphdr *v4; - struct ipv6hdr *v6; - unsigned char *hdr; - } l3; + union l3_hdr_info l3; u32 l4_proto = ol4_proto; l3.hdr = skb_network_header(skb); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index f3d248626ab3..71ff8f4d6c18 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -574,6 +574,7 @@ union l3_hdr_info { union l4_hdr_info { struct tcphdr *tcp; struct udphdr *udp; + struct gre_base_hdr *gre; unsigned char *hdr; }; -- cgit v1.2.3 From 8e1445a653c9f9a51fca6f80b8df82b523e1c4ba Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Thu, 31 Jan 2019 04:55:42 +0800 Subject: net: hns3: fix VF dump register issue In original codes, the .get_regs_len and .get_regs were missed assigned. This patch fixes it. Fixes: 1600c3e5f23e ("net: hns3: Support "ethtool -d" for HNS3 VF driver") Signed-off-by: Jian Shen Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index ed73f7fc9171..76ef06a7c261 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -1115,6 +1115,8 @@ static const struct ethtool_ops hns3vf_ethtool_ops = { .get_channels = hns3_get_channels, .get_coalesce = hns3_get_coalesce, .set_coalesce = hns3_set_coalesce, + .get_regs_len = hns3_get_regs_len, + .get_regs = hns3_get_regs, .get_link = hns3_get_link, }; -- cgit v1.2.3 From fc0c174f4223b7340999e1b3004dbc3b3b9b06de Mon Sep 17 00:00:00 2001 From: Peng Li Date: Thu, 31 Jan 2019 04:55:43 +0800 Subject: net: hns3: use the correct interface to stop|open port dev_close() stop the netdev and the service base on the netdev will stop. But ndev->netdev_ops->ndo_stop() may only stop HW and stack queue, the service base on the netdev can still work. Fixes: 5668abda0931 ("net: hns3: add support for set_ringparam") Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 76ef06a7c261..63f5f56bda94 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -805,7 +805,7 @@ static int hns3_set_ringparam(struct net_device *ndev, old_desc_num, new_desc_num); if (if_running) - dev_close(ndev); + ndev->netdev_ops->ndo_stop(ndev); ret = hns3_uninit_all_ring(priv); if (ret) @@ -822,7 +822,7 @@ static int hns3_set_ringparam(struct net_device *ndev, } if (if_running) - ret = dev_open(ndev, NULL); + ret = ndev->netdev_ops->ndo_open(ndev); return ret; } -- cgit v1.2.3 From 74354140a579008fd164241e3697d9c37e5b8989 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 31 Jan 2019 04:55:44 +0800 Subject: net: hns3: change hnae3_register_ae_dev() to int hnae3_register_ae_dev() may fail, and it should return a error code to its caller, so change hnae3_register_ae_dev() return type to int. Also, when hnae3_register_ae_dev() return error, hns3_probe() should do some error handling and return the error code. Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.c | 10 +++++++++- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 8 ++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c b/drivers/net/ethernet/hisilicon/hns3/hnae3.c index 781e5dee3c70..50011aafbae4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.c +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c @@ -238,7 +238,7 @@ EXPORT_SYMBOL(hnae3_unregister_ae_algo); * @ae_dev: the AE device * NOTE: the duplicated name will not be checked */ -void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev) +int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev) { const struct pci_device_id *id; struct hnae3_ae_algo *ae_algo; @@ -259,6 +259,7 @@ void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev) if (!ae_dev->ops) { dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n"); + ret = -EOPNOTSUPP; goto out_err; } @@ -285,8 +286,15 @@ void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev) ret); } + mutex_unlock(&hnae3_common_lock); + + return 0; + out_err: + list_del(&ae_dev->node); mutex_unlock(&hnae3_common_lock); + + return ret; } EXPORT_SYMBOL(hnae3_register_ae_dev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 585800e634e6..c29f82aa5ba1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -587,7 +587,7 @@ struct hnae3_handle { #define hnae3_get_bit(origin, shift) \ hnae3_get_field((origin), (0x1 << (shift)), (shift)) -void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev); +int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev); void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev); void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 048b5fbdf8fa..6520e1c1a837 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1752,9 +1752,13 @@ static int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hns3_get_dev_capability(pdev, ae_dev); pci_set_drvdata(pdev, ae_dev); - hnae3_register_ae_dev(ae_dev); + ret = hnae3_register_ae_dev(ae_dev); + if (ret) { + devm_kfree(&pdev->dev, ae_dev); + pci_set_drvdata(pdev, NULL); + } - return 0; + return ret; } /* hns3_remove - Device removal routine -- cgit v1.2.3 From de67a690cc27024c22328ce8ff3a2ed32f30fe7d Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Thu, 31 Jan 2019 04:55:45 +0800 Subject: net: hns3: only support tc 0 for VF When the VF shares the same TC config as PF, the business running on PF and VF must have samiliar module. For simplicity, we are not considering VF sharing the same tc configuration as PF use case, so this patch removes the support of TC configuration from VF and forcing VF to just use single TC. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c | 12 +++++------- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 10 +++++++--- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 22 ++++++++++++++++------ 3 files changed, 28 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c index 961aedb0e20f..1161361a973b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c @@ -93,13 +93,11 @@ static int hclge_dcb_common_validate(struct hclge_dev *hdev, u8 num_tc, } } - for (i = 0; i < hdev->num_alloc_vport; i++) { - if (num_tc > hdev->vport[i].alloc_tqps) { - dev_err(&hdev->pdev->dev, - "allocated tqp(%u) checking failed, %u > tqp(%u)\n", - i, num_tc, hdev->vport[i].alloc_tqps); - return -EINVAL; - } + if (num_tc > hdev->vport[0].alloc_tqps) { + dev_err(&hdev->pdev->dev, + "allocated tqp checking failed, %u > tqp(%u)\n", + num_tc, hdev->vport[0].alloc_tqps); + return -EINVAL; } return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 3603034aa45c..6afb0a4b73f7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -319,10 +319,14 @@ static int hclge_get_vf_tcinfo(struct hclge_vport *vport, struct hclge_mbx_vf_to_pf_cmd *mbx_req, bool gen_resp) { - struct hclge_dev *hdev = vport->back; - int ret; + struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; + u8 vf_tc_map = 0; + int i, ret; + + for (i = 0; i < kinfo->num_tc; i++) + vf_tc_map |= BIT(i); - ret = hclge_gen_resp_to_vf(vport, mbx_req, 0, &hdev->hw_tc_map, + ret = hclge_gen_resp_to_vf(vport, mbx_req, 0, &vf_tc_map, sizeof(u8)); return ret; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index 9f4069fb786b..aafc69f4bfdd 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -520,8 +520,14 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) u16 max_rss_size; u8 i; - vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit; - kinfo->num_tc = min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc); + /* TC configuration is shared by PF/VF in one port, only allow + * one tc for VF for simplicity. VF's vport_id is non zero. + */ + kinfo->num_tc = vport->vport_id ? 1 : + min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc); + vport->qs_offset = (vport->vport_id ? hdev->tm_info.num_tc : 0) + + (vport->vport_id ? (vport->vport_id - 1) : 0); + max_rss_size = min_t(u16, hdev->rss_size_max, vport->alloc_tqps / kinfo->num_tc); @@ -538,12 +544,12 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) } kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size; - vport->qs_offset = hdev->tm_info.num_tc * vport->vport_id; vport->dwrr = 100; /* 100 percent as init */ vport->alloc_rss_size = kinfo->rss_size; + vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit; for (i = 0; i < HNAE3_MAX_TC; i++) { - if (hdev->hw_tc_map & BIT(i)) { + if (hdev->hw_tc_map & BIT(i) && i < kinfo->num_tc) { kinfo->tc_info[i].enable = true; kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size; kinfo->tc_info[i].tqp_count = kinfo->rss_size; @@ -766,13 +772,17 @@ static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev) if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { /* Cfg qs -> pri mapping, one by one mapping */ - for (k = 0; k < hdev->num_alloc_vport; k++) - for (i = 0; i < hdev->tm_info.num_tc; i++) { + for (k = 0; k < hdev->num_alloc_vport; k++) { + struct hnae3_knic_private_info *kinfo = + &vport[k].nic.kinfo; + + for (i = 0; i < kinfo->num_tc; i++) { ret = hclge_tm_qs_to_pri_map_cfg( hdev, vport[k].qs_offset + i, i); if (ret) return ret; } + } } else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) { /* Cfg qs -> pri mapping, qs = tc, pri = vf, 8 qs -> 1 pri */ for (k = 0; k < hdev->num_alloc_vport; k++) -- cgit v1.2.3 From c8a8045b2d0a974149d65bbe6a7acbcde93cf85b Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 31 Jan 2019 04:55:46 +0800 Subject: net: hns3: Fix NULL deref when unloading driver When the driver is unloading, if there is a calling of ndo_open occurs between phy_disconnect() and unregister_netdev(), it will end up causing the kernel to eventually hit a NULL deref: [14942.417828] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048 [14942.529878] Mem abort info: [14942.551166] ESR = 0x96000006 [14942.567070] Exception class = DABT (current EL), IL = 32 bits [14942.623081] SET = 0, FnV = 0 [14942.639112] EA = 0, S1PTW = 0 [14942.643628] Data abort info: [14942.659227] ISV = 0, ISS = 0x00000006 [14942.674870] CM = 0, WnR = 0 [14942.679449] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000224ad6ad [14942.695595] [0000000000000048] pgd=00000021e6673003, pud=00000021dbf01003, pmd=0000000000000000 [14942.723163] Internal error: Oops: 96000006 [#1] PREEMPT SMP [14942.729358] Modules linked in: hns3(O) hclge(O) pv680_mii(O) hnae3(O) [last unloaded: hclge] [14942.738907] CPU: 1 PID: 26629 Comm: kworker/u4:13 Tainted: G O 4.18.0-rc1-12928-ga960791-dirty #145 [14942.749491] Hardware name: Huawei Technologies Co., Ltd. D05/D05, BIOS Hi1620 FPGA TB BOOT BIOS B763 08/17/2018 [14942.760392] Workqueue: events_power_efficient phy_state_machine [14942.766644] pstate: 80c00009 (Nzcv daif +PAN +UAO) [14942.771918] pc : test_and_set_bit+0x18/0x38 [14942.776589] lr : netif_carrier_off+0x24/0x70 [14942.781033] sp : ffff0000121abd20 [14942.784518] x29: ffff0000121abd20 x28: 0000000000000000 [14942.790208] x27: ffff0000164d3cd8 x26: ffff8021da68b7b8 [14942.795832] x25: 0000000000000000 x24: ffff8021eb407800 [14942.801445] x23: 0000000000000000 x22: 0000000000000000 [14942.807046] x21: 0000000000000001 x20: 0000000000000000 [14942.812672] x19: 0000000000000000 x18: ffff000009781708 [14942.818284] x17: 00000000004970e8 x16: ffff00000816ad48 [14942.823900] x15: 0000000000000000 x14: 0000000000000008 [14942.829528] x13: 0000000000000000 x12: 0000000000000f65 [14942.835149] x11: 0000000000000001 x10: 00000000000009d0 [14942.840753] x9 : ffff0000121abaa0 x8 : 0000000000000000 [14942.846360] x7 : ffff000009781708 x6 : 0000000000000003 [14942.851970] x5 : 0000000000000020 x4 : 0000000000000004 [14942.857575] x3 : 0000000000000002 x2 : 0000000000000001 [14942.863180] x1 : 0000000000000048 x0 : 0000000000000000 [14942.868875] Process kworker/u4:13 (pid: 26629, stack limit = 0x00000000c909dbf3) [14942.876464] Call trace: [14942.879200] test_and_set_bit+0x18/0x38 [14942.883376] phy_link_change+0x38/0x78 [14942.887378] phy_state_machine+0x3dc/0x4f8 [14942.891968] process_one_work+0x158/0x470 [14942.896223] worker_thread+0x50/0x470 [14942.900219] kthread+0x104/0x130 [14942.903905] ret_from_fork+0x10/0x1c [14942.907755] Code: d2800022 8b400c21 f9800031 9ac32044 (c85f7c22) [14942.914185] ---[ end trace 968c9e12eb740b23 ]--- So this patch fixes it by modifying the timing to do phy_connect_direct() and phy_disconnect(). Fixes: 256727da7395 ("net: hns3: Add MDIO support to HNS3 Ethernet driver for hip08 SoC") Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 ++ drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 28 ++++++++++++++++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 20 ++-------------- .../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 8 +++++-- .../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h | 4 ++-- 5 files changed, 40 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index c29f82aa5ba1..e05b4926feb2 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -464,6 +464,8 @@ struct hnae3_ae_ops { int (*set_gro_en)(struct hnae3_handle *handle, int enable); u16 (*get_global_queue_id)(struct hnae3_handle *handle, u16 queue_id); void (*set_timer_task)(struct hnae3_handle *handle, bool enable); + int (*mac_connect_phy)(struct hnae3_handle *handle); + void (*mac_disconnect_phy)(struct hnae3_handle *handle); }; struct hnae3_dcb_ops { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 6520e1c1a837..ac9b0aa258ec 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3531,6 +3531,25 @@ static int hns3_init_mac_addr(struct net_device *netdev, bool init) return ret; } +static int hns3_init_phy(struct net_device *netdev) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + int ret = 0; + + if (h->ae_algo->ops->mac_connect_phy) + ret = h->ae_algo->ops->mac_connect_phy(h); + + return ret; +} + +static void hns3_uninit_phy(struct net_device *netdev) +{ + struct hnae3_handle *h = hns3_get_handle(netdev); + + if (h->ae_algo->ops->mac_disconnect_phy) + h->ae_algo->ops->mac_disconnect_phy(h); +} + static int hns3_restore_fd_rules(struct net_device *netdev) { struct hnae3_handle *h = hns3_get_handle(netdev); @@ -3640,6 +3659,10 @@ static int hns3_client_init(struct hnae3_handle *handle) goto out_init_ring_data; } + ret = hns3_init_phy(netdev); + if (ret) + goto out_init_phy; + ret = register_netdev(netdev); if (ret) { dev_err(priv->dev, "probe register netdev fail!\n"); @@ -3664,6 +3687,9 @@ static int hns3_client_init(struct hnae3_handle *handle) return ret; out_reg_netdev_fail: + hns3_uninit_phy(netdev); +out_init_phy: + hns3_uninit_all_ring(priv); out_init_ring_data: (void)hns3_nic_uninit_vector_data(priv); out_init_vector_data: @@ -3698,6 +3724,8 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset) hns3_force_clear_all_rx_ring(handle); + hns3_uninit_phy(netdev); + ret = hns3_nic_uninit_vector_data(priv); if (ret) netdev_err(netdev, "uninit vector error\n"); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index ae8336c18264..795ebedde284 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7050,16 +7050,6 @@ static void hclge_get_mdix_mode(struct hnae3_handle *handle, *tp_mdix = ETH_TP_MDI; } -static int hclge_init_instance_hw(struct hclge_dev *hdev) -{ - return hclge_mac_connect_phy(hdev); -} - -static void hclge_uninit_instance_hw(struct hclge_dev *hdev) -{ - hclge_mac_disconnect_phy(hdev); -} - static int hclge_init_client_instance(struct hnae3_client *client, struct hnae3_ae_dev *ae_dev) { @@ -7079,13 +7069,6 @@ static int hclge_init_client_instance(struct hnae3_client *client, if (ret) goto clear_nic; - ret = hclge_init_instance_hw(hdev); - if (ret) { - client->ops->uninit_instance(&vport->nic, - 0); - goto clear_nic; - } - hnae3_set_client_init_flag(client, ae_dev, 1); if (hdev->roce_client && @@ -7170,7 +7153,6 @@ static void hclge_uninit_client_instance(struct hnae3_client *client, if (client->type == HNAE3_CLIENT_ROCE) return; if (hdev->nic_client && client->ops->uninit_instance) { - hclge_uninit_instance_hw(hdev); client->ops->uninit_instance(&vport->nic, 0); hdev->nic_client = NULL; vport->nic.client = NULL; @@ -8076,6 +8058,8 @@ static const struct hnae3_ae_ops hclge_ops = { .set_gro_en = hclge_gro_en, .get_global_queue_id = hclge_covert_handle_qid_global, .set_timer_task = hclge_set_timer_task, + .mac_connect_phy = hclge_mac_connect_phy, + .mac_disconnect_phy = hclge_mac_disconnect_phy, }; static struct hnae3_ae_algo ae_algo = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index dabb8437f8dc..84f28785ba28 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -195,8 +195,10 @@ static void hclge_mac_adjust_link(struct net_device *netdev) netdev_err(netdev, "failed to configure flow control.\n"); } -int hclge_mac_connect_phy(struct hclge_dev *hdev) +int hclge_mac_connect_phy(struct hnae3_handle *handle) { + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; struct net_device *netdev = hdev->vport[0].nic.netdev; struct phy_device *phydev = hdev->hw.mac.phydev; __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; @@ -229,8 +231,10 @@ int hclge_mac_connect_phy(struct hclge_dev *hdev) return 0; } -void hclge_mac_disconnect_phy(struct hclge_dev *hdev) +void hclge_mac_disconnect_phy(struct hnae3_handle *handle) { + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_dev *hdev = vport->back; struct phy_device *phydev = hdev->hw.mac.phydev; if (!phydev) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h index 5fbf7dddb5d9..ef095d9c566f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h @@ -5,8 +5,8 @@ #define __HCLGE_MDIO_H int hclge_mac_mdio_config(struct hclge_dev *hdev); -int hclge_mac_connect_phy(struct hclge_dev *hdev); -void hclge_mac_disconnect_phy(struct hclge_dev *hdev); +int hclge_mac_connect_phy(struct hnae3_handle *handle); +void hclge_mac_disconnect_phy(struct hnae3_handle *handle); void hclge_mac_start_phy(struct hclge_dev *hdev); void hclge_mac_stop_phy(struct hclge_dev *hdev); -- cgit v1.2.3 From e215278548f9ea412e2be794efa1c84c6817c657 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 31 Jan 2019 04:55:47 +0800 Subject: net: hns3: fix netif_napi_del() not do problem when unloading When the driver is unloading, if a global reset occurs, unmap_ring_from_vector() in the hns3_nic_uninit_vector_data() will fail, and hns3_nic_uninit_vector_data() just return. There may be some netif_napi_del() not be done. Since hardware will unmap all ring while resetting, so hns3_nic_uninit_vector_data() should ignore this error, and do the rest uninitialization. Fixes: 76ad4f0ee747 ("net: hns3: Add support of HNS3 Ethernet Driver for hip08 SoC") Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 27 +++++++------------------ 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index ac9b0aa258ec..c546b874d659 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3183,12 +3183,12 @@ static void hns3_clear_ring_group(struct hns3_enet_ring_group *group) group->count = 0; } -static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) +static void hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) { struct hnae3_ring_chain_node vector_ring_chain; struct hnae3_handle *h = priv->ae_handle; struct hns3_enet_tqp_vector *tqp_vector; - int i, ret; + int i; for (i = 0; i < priv->vector_num; i++) { tqp_vector = &priv->tqp_vector[i]; @@ -3196,15 +3196,10 @@ static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) if (!tqp_vector->rx_group.ring && !tqp_vector->tx_group.ring) continue; - ret = hns3_get_vector_ring_chain(tqp_vector, - &vector_ring_chain); - if (ret) - return ret; + hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain); - ret = h->ae_algo->ops->unmap_ring_from_vector(h, + h->ae_algo->ops->unmap_ring_from_vector(h, tqp_vector->vector_irq, &vector_ring_chain); - if (ret) - return ret; hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain); @@ -3220,8 +3215,6 @@ static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) hns3_clear_ring_group(&tqp_vector->tx_group); netif_napi_del(&priv->tqp_vector[i].napi); } - - return 0; } static int hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv) @@ -3691,7 +3684,7 @@ out_reg_netdev_fail: out_init_phy: hns3_uninit_all_ring(priv); out_init_ring_data: - (void)hns3_nic_uninit_vector_data(priv); + hns3_nic_uninit_vector_data(priv); out_init_vector_data: hns3_nic_dealloc_vector_data(priv); out_alloc_vector_data: @@ -3726,9 +3719,7 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset) hns3_uninit_phy(netdev); - ret = hns3_nic_uninit_vector_data(priv); - if (ret) - netdev_err(netdev, "uninit vector error\n"); + hns3_nic_uninit_vector_data(priv); ret = hns3_nic_dealloc_vector_data(priv); if (ret) @@ -4121,11 +4112,7 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle) hns3_force_clear_all_rx_ring(handle); - ret = hns3_nic_uninit_vector_data(priv); - if (ret) { - netdev_err(netdev, "uninit vector error\n"); - return ret; - } + hns3_nic_uninit_vector_data(priv); hns3_store_coal(priv); -- cgit v1.2.3 From 472d7ecee20e8fea18e6223cc1d383b6c3483502 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Thu, 31 Jan 2019 04:55:48 +0800 Subject: net: hns3: fix for rss result nonuniform The rss result is more uniform when use recommended hash key from microsoft, instead of the one generated by netdev_rss_key_fill(). Also using hash algorithm "xor" is better than "toeplitz". This patch modifies the default hash key and hash algorithm. Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 18 +++++++++++++++--- .../net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 14 +++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 795ebedde284..42f0f8824b47 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -295,6 +295,14 @@ static const struct hclge_mac_mgr_tbl_entry_cmd hclge_mgr_table[] = { }, }; +static const u8 hclge_hash_key[] = { + 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, + 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, + 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, + 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, + 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA +}; + static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) { #define HCLGE_MAC_CMD_NUM 21 @@ -3652,8 +3660,11 @@ void hclge_rss_indir_init_cfg(struct hclge_dev *hdev) static void hclge_rss_init_cfg(struct hclge_dev *hdev) { + int i, rss_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ; struct hclge_vport *vport = hdev->vport; - int i; + + if (hdev->pdev->revision >= 0x21) + rss_algo = HCLGE_RSS_HASH_ALGO_SIMPLE; for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { vport[i].rss_tuple_sets.ipv4_tcp_en = @@ -3673,9 +3684,10 @@ static void hclge_rss_init_cfg(struct hclge_dev *hdev) vport[i].rss_tuple_sets.ipv6_fragment_en = HCLGE_RSS_INPUT_TUPLE_OTHER; - vport[i].rss_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ; + vport[i].rss_algo = rss_algo; - netdev_rss_key_fill(vport[i].rss_hash_key, HCLGE_RSS_KEY_SIZE); + memcpy(vport[i].rss_hash_key, hclge_hash_key, + HCLGE_RSS_KEY_SIZE); } hclge_rss_indir_init_cfg(hdev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index fc99a0c70164..93f306f42cf4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -21,6 +21,14 @@ static const struct pci_device_id ae_algovf_pci_tbl[] = { {0, } }; +static const u8 hclgevf_hash_key[] = { + 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, + 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0, + 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, + 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, + 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA +}; + MODULE_DEVICE_TABLE(pci, ae_algovf_pci_tbl); static const u32 cmdq_reg_addr_list[] = {HCLGEVF_CMDQ_TX_ADDR_L_REG, @@ -1789,9 +1797,9 @@ static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev) rss_cfg->rss_size = hdev->rss_size_max; if (hdev->pdev->revision >= 0x21) { - rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ; - netdev_rss_key_fill(rss_cfg->rss_hash_key, - HCLGEVF_RSS_KEY_SIZE); + rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE; + memcpy(rss_cfg->rss_hash_key, hclgevf_hash_key, + HCLGEVF_RSS_KEY_SIZE); ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo, rss_cfg->rss_hash_key); -- cgit v1.2.3 From 9fc55413270fffe1b5ebdea03489d763c62c0305 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Thu, 31 Jan 2019 04:55:49 +0800 Subject: net: hns3: fix improper error handling in the hclge_init_ae_dev() While hclge_init_umv_space() failed in the hclge_init_ae_dev(), we should undo all the operation which has been done successfully, the last success operation maybe hclge_mac_mdio_config(), so if hclge_init_umv_space() failed, we also need to undo it. Fixes: 288475b2ad01 ("{topost} net: hns3: refine umv space allocation") Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 42f0f8824b47..b531eac12fea 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7383,7 +7383,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) ret = hclge_init_umv_space(hdev); if (ret) { dev_err(&pdev->dev, "umv space init error, ret=%d.\n", ret); - goto err_msi_irq_uninit; + goto err_mdiobus_unreg; } ret = hclge_mac_init(hdev); -- cgit v1.2.3 From eed9535f9f716a532ec0c5d6cc7a48584acdf435 Mon Sep 17 00:00:00 2001 From: Peng Li Date: Thu, 31 Jan 2019 04:55:50 +0800 Subject: net: hns3: fix an issue for hclgevf_ae_get_hdev HNS3 VF driver support NIC and Roce, hdev stores NIC handle and Roce handle, should use correct parameter for container_of. Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 93f306f42cf4..95f926971e3b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -86,7 +86,12 @@ static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG, static inline struct hclgevf_dev *hclgevf_ae_get_hdev( struct hnae3_handle *handle) { - return container_of(handle, struct hclgevf_dev, nic); + if (!handle->client) + return container_of(handle, struct hclgevf_dev, nic); + else if (handle->client->type == HNAE3_CLIENT_ROCE) + return container_of(handle, struct hclgevf_dev, roce); + else + return container_of(handle, struct hclgevf_dev, nic); } static int hclgevf_tqps_update_stats(struct hnae3_handle *handle) -- cgit v1.2.3 From c59a85c07e77a7669e5b4d2ffa878b6894ec3953 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Thu, 31 Jan 2019 04:55:51 +0800 Subject: net: hns3: stop sending keep alive msg to PF when VF is resetting When VF is resetting, it can't communicate to PF with mailbox msg. This patch adds reset state checking before sending keep alive msg to PF. Fixes: a6d818e31d08 ("net: hns3: Add vport alive state checking support") Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 95f926971e3b..b9cdbd5dd6cb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1624,6 +1624,10 @@ static void hclgevf_keep_alive_task(struct work_struct *work) int ret; hdev = container_of(work, struct hclgevf_dev, keep_alive_task); + + if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state)) + return; + ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_KEEP_ALIVE, 0, NULL, 0, false, &respmsg, sizeof(u8)); if (ret) -- cgit v1.2.3 From 9abeb7d8cf8719bf221bf371f97fbf0971657be3 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Thu, 31 Jan 2019 04:55:52 +0800 Subject: net: hns3: keep flow director state unchanged when reset In orginal codes, driver always enables flow director when intializing. When user disable flow director with command ethtool -K, the flow director will be enabled again after resetting. This patch fixes it by only enabling it when first initialzing. Fixes: 6871af29b3ab ("net: hns3: Add reset handle for flow director") Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 10 ++++++---- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index b531eac12fea..2ffbf07ff829 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1007,6 +1007,9 @@ static int hclge_configure(struct hclge_dev *hdev) hdev->tm_info.hw_pfc_map = 0; hdev->wanted_umv_size = cfg.umv_space; + if (hnae3_dev_fd_supported(hdev)) + hdev->fd_en = true; + ret = hclge_parse_speed(cfg.default_speed, &hdev->hw.mac.speed); if (ret) { dev_err(&hdev->pdev->dev, "Get wrong speed ret=%d.\n", ret); @@ -3973,7 +3976,6 @@ static int hclge_init_fd_config(struct hclge_dev *hdev) return -EOPNOTSUPP; } - hdev->fd_cfg.fd_en = true; hdev->fd_cfg.proto_support = TCP_V4_FLOW | UDP_V4_FLOW | SCTP_V4_FLOW | TCP_V6_FLOW | UDP_V6_FLOW | SCTP_V6_FLOW | IPV4_USER_FLOW | IPV6_USER_FLOW; @@ -4731,7 +4733,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle, if (!hnae3_dev_fd_supported(hdev)) return -EOPNOTSUPP; - if (!hdev->fd_cfg.fd_en) { + if (!hdev->fd_en) { dev_warn(&hdev->pdev->dev, "Please enable flow director first\n"); return -EOPNOTSUPP; @@ -4884,7 +4886,7 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle) return 0; /* if fd is disabled, should not restore it when reset */ - if (!hdev->fd_cfg.fd_en) + if (!hdev->fd_en) return 0; hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list, rule_node) { @@ -5170,7 +5172,7 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable) struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - hdev->fd_cfg.fd_en = enable; + hdev->fd_en = enable; if (!enable) hclge_del_all_fd_entries(handle, false); else diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 2c413c63c6c9..c939f4a7f5f0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -583,7 +583,6 @@ struct hclge_fd_key_cfg { struct hclge_fd_cfg { u8 fd_mode; - u8 fd_en; u16 max_key_length; u32 proto_support; u32 rule_num[2]; /* rule entry number */ @@ -758,6 +757,7 @@ struct hclge_dev { struct hclge_fd_cfg fd_cfg; struct hlist_head fd_rule_list; u16 hclge_fd_rule_num; + u8 fd_en; u16 wanted_umv_size; /* max available unicast mac vlan space */ -- cgit v1.2.3 From 3864be551405b582ae38fbcdfdbb6e49052f5f6d Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 30 Jan 2019 14:38:11 +0200 Subject: iwlwifi: mvm: fix merge damage in iwl_mvm_rx_mpdu_mq() A call to iwl_mvm_add_rtap_sniffer_config() was missing due to a merge damage when I submitted the patch mentioned below. And this causes the following compilation warning: drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c:195:13: warning: 'iwl_mvm_add_rtap_sniffer_config' defined but not used [-Wunused-function] static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fix it by adding the if block that calls this function. Fixes: 9bf13bee2d74 ("iwlwifi: mvm: include configured sniffer AID in radiotap") Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 79860f6ac7ca..2c56f73d688e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1476,6 +1476,9 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->ampdu_reference = mvm->ampdu_ref; } + if (unlikely(mvm->monitor_on)) + iwl_mvm_add_rtap_sniffer_config(mvm, skb); + rcu_read_lock(); if (desc->status & cpu_to_le16(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) { -- cgit v1.2.3 From 913564fbc2df0b5061c79fc203f8ddb17b30b78b Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 31 Jan 2019 10:48:10 +0100 Subject: macvlan: use netif_is_macvlan_port() Replace the macvlan_port_exists() macro with its twin from netdevice.h Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index cf22a79af66b..26e53832b095 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -119,8 +119,6 @@ static struct macvlan_port *macvlan_port_get_rtnl(const struct net_device *dev) return rtnl_dereference(dev->rx_handler_data); } -#define macvlan_port_exists(dev) (dev->priv_flags & IFF_MACVLAN_PORT) - static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, const unsigned char *addr) { @@ -1378,7 +1376,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, if (!tb[IFLA_ADDRESS]) eth_hw_addr_random(dev); - if (!macvlan_port_exists(lowerdev)) { + if (!netif_is_macvlan_port(lowerdev)) { err = macvlan_port_create(lowerdev); if (err < 0) return err; @@ -1638,7 +1636,7 @@ static int macvlan_device_event(struct notifier_block *unused, struct macvlan_port *port; LIST_HEAD(list_kill); - if (!macvlan_port_exists(dev)) + if (!netif_is_macvlan_port(dev)) return NOTIFY_DONE; port = macvlan_port_get_rtnl(dev); -- cgit v1.2.3 From fa6821cbf1d9724284ef0906c9a01a5fbf13a35c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 31 Jan 2019 19:57:26 +0100 Subject: r8169: improve WoL handling WoL handling for the RTL8168 family is a little bit tricky because of different types of broken BIOS and/or chip quirks. Two known issues: 1. Network properly resumes from suspend only if WoL is enabled in the chip. 2. Some notebooks wake up immediately if system is suspended and network device is wakeup-enabled. Few patches tried to deal with this: 7edf6d314cd0 ("r8169: disable WOL per default") 18041b523692 ("r8169: restore previous behavior to accept BIOS WoL settings") Currently we have the situation that the chip WoL settings as set by the BIOS are respected (to prevent issue 1), but the device doesn't get wakeup-enabled (to prevent issue 2). This leads to another issue: If systemd is told to set WoL it first checks whether the requested settings are active already (and does nothing if yes). Due to the chip WoL flags being set properly systemd assumes that WoL is configured properly in our case. Result is that device doesn't get wakeup-enabled and WoL doesn't work (until it's set e.g. by ethtool). This patch now: - leaves the chip WoL settings as is (to prevent issue 1) - keeps the behavior to not wakeup-enable the device initially (to prevent issue 2) - In addition we report WoL as being disabled in get_wol, matching that device isn't wakeup-enabled. If systemd is told to enable WoL, it will therefore detect that it has to do something and will call set_wol. Of course the user still has the option to override this with e.g. ethtool. v2: - Don't just exclude __rtl8169_get_wol() from compiling, remove it. v3: - adjust commit message Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 39 +----------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 3e650bd9e94b..9dc68981751b 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1371,41 +1371,6 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp) #define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - u8 options; - u32 wolopts = 0; - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(tp, Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: - if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2) - wolopts |= WAKE_MAGIC; - break; - default: - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - break; - } - - options = RTL_R8(tp, Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct rtl8169_private *tp = netdev_priv(dev); @@ -4284,7 +4249,7 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) static bool rtl_wol_pll_power_down(struct rtl8169_private *tp) { - if (!__rtl8169_get_wol(tp)) + if (!device_may_wakeup(tp_to_dev(tp))) return false; phy_speed_down(tp->phydev, false); @@ -7441,8 +7406,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; } - tp->saved_wolopts = __rtl8169_get_wol(tp); - mutex_init(&tp->wk.mutex); INIT_WORK(&tp->wk.work, rtl_task); u64_stats_init(&tp->rx_stats.syncp); -- cgit v1.2.3 From c2e28ef7711ffcb083474ee5f154264c6ec1ec07 Mon Sep 17 00:00:00 2001 From: Tomislav Požega Date: Thu, 27 Dec 2018 15:05:25 +0100 Subject: rt2x00: reduce tx power to nominal level on RT6352 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current implementation of RT6352 support provides too high tx power at least on iPA/eLNA devices. Reduce amplification of variable gain amplifier by 6dB to match board target power of 17dBm. Transmited signal strength with this patch is similar to that of stock firmware or pandorabox firmware. Throughput measured with iperf improves. Device tested: Xiaomi Miwifi Mini. Signed-off-by: Tomislav Požega Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 0e95555aec62..7f813f6f8792 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -5477,7 +5477,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); rt2800_register_write(rt2x00dev, MIMO_PS_CFG, 0x00000002); rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x00150F0F); - rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x06060606); + rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000); rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0); rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0); rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, 0x6C6C666C); -- cgit v1.2.3 From db040dfa53e2905111e400b28d0bd6f38c78d348 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 8 Jan 2019 11:26:32 -0600 Subject: qtnfmac: use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/commands.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 659e7649fe22..cf386f579060 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -914,9 +914,8 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus, if (WARN_ON(resp->n_reg_rules > NL80211_MAX_SUPP_REG_RULES)) return -E2BIG; - hwinfo->rd = kzalloc(sizeof(*hwinfo->rd) - + sizeof(struct ieee80211_reg_rule) - * resp->n_reg_rules, GFP_KERNEL); + hwinfo->rd = kzalloc(struct_size(hwinfo->rd, reg_rules, + resp->n_reg_rules), GFP_KERNEL); if (!hwinfo->rd) return -ENOMEM; -- cgit v1.2.3 From 434256833d8eb988cb7f3b8a41699e2fe48d9332 Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Tue, 8 Jan 2019 11:42:21 -0600 Subject: libertas: add checks for the return value of sysfs_create_group sysfs_create_group() could fail. The fix checkes its return values and issue error messages if it fails. Signed-off-by: Kangjie Lu Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/mesh.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas/mesh.c b/drivers/net/wireless/marvell/libertas/mesh.c index b0cb16ef8d1d..2315fdff56c2 100644 --- a/drivers/net/wireless/marvell/libertas/mesh.c +++ b/drivers/net/wireless/marvell/libertas/mesh.c @@ -797,7 +797,12 @@ static void lbs_persist_config_init(struct net_device *dev) { int ret; ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group); + if (ret) + pr_err("failed to create boot_opts_group.\n"); + ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group); + if (ret) + pr_err("failed to create mesh_ie_group.\n"); } static void lbs_persist_config_remove(struct net_device *dev) -- cgit v1.2.3 From 46b87976d7a8a75759a13a6db0e1a5f166011968 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Tue, 8 Jan 2019 22:49:23 +0000 Subject: rtl8723ae: Take the FW LPS mode handling out This appears to trigger a firmware bug and causes severe problems with rtl8723ae PCI devices. When the power save mode is activated for longer periods of time the firmware stops to receive any packets. This problem was exposed by commit 873ffe154ae0 ("rtlwifi: Fix logic error in enter/exit power-save mode"). Previously the power save mode was only active rarely and only for a short time so that the problem was not noticeable. Signed-off-by: Bernd Edlinger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 07b82700d1de..3103151dda2b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -266,8 +266,8 @@ static struct rtl_hal_ops rtl8723e_hal_ops = { static struct rtl_mod_params rtl8723e_mod_params = { .sw_crypto = false, .inactiveps = true, - .swctrl_lps = false, - .fwctrl_lps = true, + .swctrl_lps = true, + .fwctrl_lps = false, .aspm_support = 1, .debug_level = 0, .debug_mask = 0, @@ -395,8 +395,8 @@ module_param_named(disable_watchdog, rtl8723e_mod_params.disable_watchdog, bool, 0444); MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n"); -MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n"); -MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n"); +MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n"); +MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n"); MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n"); MODULE_PARM_DESC(aspm, "Set to 1 to enable ASPM (default 1)\n"); MODULE_PARM_DESC(debug_level, "Set debug level (0-5) (default 0)"); -- cgit v1.2.3 From 5bb5385fbf3e31e72ee81e05c14f958dab2d53b6 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Tue, 8 Jan 2019 22:49:40 +0000 Subject: rtl8723ae: Dont use old data for input gain control When no beacon was received, the value in dm.undec_sm_pwdb is most likely out of date and should not be used to adjust the input path. Assume instead that the signal level is low. Fix the state machine in rtl8723e_dm_cck_packet_detection_thresh which did not clear pre_cck_fa_state when changing cur_cck_pd_state from CCK_PD_STAGE_LOWRSSI/CCK_FA_STAGE_LOW to CCK_PD_STAGE_HIGHRSSI and back again to CCK_PD_STAGE_LOWRSSI/CCK_FA_STAGE_LOW, the register RCCK0_CCA not written to 0x83 on the second change. Explicitly initialize pre_cck_fa_state/cur_cck_fa_state in rtl_dm_diginit. Signed-off-by: Bernd Edlinger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/core.c | 2 ++ drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c | 8 ++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 4bf7967590ca..ce23339bf9fb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1957,5 +1957,7 @@ void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igvalue) dm_digtable->bt30_cur_igi = 0x32; dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX; dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI; + dm_digtable->pre_cck_fa_state = 0; + dm_digtable->cur_cck_fa_state = 0; } EXPORT_SYMBOL(rtl_dm_diginit); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c index 42a6fba90ba9..902b94466c55 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c @@ -151,8 +151,14 @@ static u8 rtl8723e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtlpriv); long rssi_val_min = 0; + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION && + rtlpriv->link_info.bcn_rx_inperiod == 0) + return 0; + if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) && (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) { if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) @@ -417,6 +423,8 @@ static void rtl8723e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) } else { rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47); + dm_digtable->pre_cck_fa_state = 0; + dm_digtable->cur_cck_fa_state = 0; } dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state; -- cgit v1.2.3 From 28484b6b37ba4a500a2913e5b64456a5717259cf Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Tue, 8 Jan 2019 22:49:52 +0000 Subject: rtl8723ae: Re-introduce the adaptive rate control This re-introduces the function rtl8723e_dm_refresh_rate_adaptive_mask. This function was present in a previous version of the code base, it works just fine for me -- as long as it is not using stale data. Unlike the original version of this function it avoids using dm.undec_sm_pwdb when no beacon was received. Fixed a style nit in rtl8723e_dm_init_rate_adaptive_mask. Signed-off-by: Bernd Edlinger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8723ae/dm.c | 87 +++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c index 902b94466c55..acfd54c6f8dd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c @@ -673,7 +673,7 @@ void rtl8723e_dm_check_txpower_tracking(struct ieee80211_hw *hw) void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *p_ra = &(rtlpriv->ra); + struct rate_adaptive *p_ra = &rtlpriv->ra; p_ra->ratr_state = DM_RATR_STA_INIT; p_ra->pre_ratr_state = DM_RATR_STA_INIT; @@ -685,6 +685,89 @@ void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) } +void rtl8723e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rate_adaptive *p_ra = &rtlpriv->ra; + u32 low_rssithresh_for_ra, high_rssithresh_for_ra; + struct ieee80211_sta *sta = NULL; + + if (is_hal_stop(rtlhal)) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + " driver is going to unload\n"); + return; + } + + if (!rtlpriv->dm.useramask) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + " driver does not control rate adaptive mask\n"); + return; + } + + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { + switch (p_ra->pre_ratr_state) { + case DM_RATR_STA_HIGH: + high_rssithresh_for_ra = 50; + low_rssithresh_for_ra = 20; + break; + case DM_RATR_STA_MIDDLE: + high_rssithresh_for_ra = 55; + low_rssithresh_for_ra = 20; + break; + case DM_RATR_STA_LOW: + high_rssithresh_for_ra = 60; + low_rssithresh_for_ra = 25; + break; + default: + high_rssithresh_for_ra = 50; + low_rssithresh_for_ra = 20; + break; + } + + if (rtlpriv->link_info.bcn_rx_inperiod == 0) + switch (p_ra->pre_ratr_state) { + case DM_RATR_STA_HIGH: + default: + p_ra->ratr_state = DM_RATR_STA_MIDDLE; + break; + case DM_RATR_STA_MIDDLE: + case DM_RATR_STA_LOW: + p_ra->ratr_state = DM_RATR_STA_LOW; + break; + } + else if (rtlpriv->dm.undec_sm_pwdb > high_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_HIGH; + else if (rtlpriv->dm.undec_sm_pwdb > low_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_MIDDLE; + else + p_ra->ratr_state = DM_RATR_STA_LOW; + + if (p_ra->pre_ratr_state != p_ra->ratr_state) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI = %ld\n", + rtlpriv->dm.undec_sm_pwdb); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI_LEVEL = %d\n", p_ra->ratr_state); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "PreState = %d, CurState = %d\n", + p_ra->pre_ratr_state, p_ra->ratr_state); + + rcu_read_lock(); + sta = rtl_find_sta(hw, mac->bssid); + if (sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, + p_ra->ratr_state, + true); + rcu_read_unlock(); + + p_ra->pre_ratr_state = p_ra->ratr_state; + } + } +} + void rtl8723e_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -834,7 +917,7 @@ void rtl8723e_dm_watchdog(struct ieee80211_hw *hw) rtl8723e_dm_dynamic_bb_powersaving(hw); rtl8723e_dm_dynamic_txpower(hw); rtl8723e_dm_check_txpower_tracking(hw); - /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ + rtl8723e_dm_refresh_rate_adaptive_mask(hw); rtl8723e_dm_bt_coexist(hw); rtl8723e_dm_check_edca_turbo(hw); } -- cgit v1.2.3 From 051337d412d2127735b65d7752e99a7478c96db3 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Tue, 8 Jan 2019 22:50:09 +0000 Subject: rtlwifi: Don't clear num_rx_inperiod too early This patch moves the clearing of rtlpriv->link_info.num_rx_inperiod in rtl_watchdog_wq_callback a few lines down. This is necessary since it is still used in the "AP off" detection code block. Moved clearing of rtlpriv->link_info.num_rx_inperiod as well for consistency. Signed-off-by: Bernd Edlinger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index ef9b502ce576..7aa68fe5d791 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -2172,8 +2172,6 @@ label_lps_done: ; } - rtlpriv->link_info.num_rx_inperiod = 0; - rtlpriv->link_info.num_tx_inperiod = 0; for (tid = 0; tid <= 7; tid++) rtlpriv->link_info.tidtx_inperiod[tid] = 0; @@ -2236,6 +2234,8 @@ label_lps_done: rtlpriv->btcoexist.btc_info.in_4way = false; } + rtlpriv->link_info.num_rx_inperiod = 0; + rtlpriv->link_info.num_tx_inperiod = 0; rtlpriv->link_info.bcn_rx_inperiod = 0; /* <6> scan list */ -- cgit v1.2.3 From 1a0f547831dcee5364d77f603d6ce4a08737a50d Mon Sep 17 00:00:00 2001 From: Hemantkumar Suthar Date: Thu, 10 Jan 2019 08:45:54 +0000 Subject: mwifiex: add support for sd8977 chipset This patch adds support for 8977 chipset to mwifiex with SDIO interface. Register offsets and supported feature flags are updated. Firmware image used will be mrvl/sd8977_uapsta.bin. Signed-off-by: Hemantkumar Suthar Signed-off-by: Rakesh Parmar Signed-off-by: Cathy Luo Signed-off-by: Ganapathi Bhat Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/Kconfig | 2 +- drivers/net/wireless/marvell/mwifiex/sdio.c | 5 ++ drivers/net/wireless/marvell/mwifiex/sdio.h | 70 ++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/Kconfig b/drivers/net/wireless/marvell/mwifiex/Kconfig index 279167ddd293..524fd565cb2a 100644 --- a/drivers/net/wireless/marvell/mwifiex/Kconfig +++ b/drivers/net/wireless/marvell/mwifiex/Kconfig @@ -9,7 +9,7 @@ config MWIFIEX mwifiex. config MWIFIEX_SDIO - tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8997" + tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8977/SD8997" depends on MWIFIEX && MMC select FW_LOADER select WANT_DEV_COREDUMP diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index d49fbd58afa7..a85648342d15 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -489,6 +489,8 @@ static void mwifiex_sdio_coredump(struct device *dev) #define SDIO_DEVICE_ID_MARVELL_8887 (0x9135) /* Device ID for SD8801 */ #define SDIO_DEVICE_ID_MARVELL_8801 (0x9139) +/* Device ID for SD8977 */ +#define SDIO_DEVICE_ID_MARVELL_8977 (0x9145) /* Device ID for SD8997 */ #define SDIO_DEVICE_ID_MARVELL_8997 (0x9141) @@ -507,6 +509,8 @@ static const struct sdio_device_id mwifiex_ids[] = { .driver_data = (unsigned long)&mwifiex_sdio_sd8887}, {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801), .driver_data = (unsigned long)&mwifiex_sdio_sd8801}, + {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8977), + .driver_data = (unsigned long)&mwifiex_sdio_sd8977}, {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997), .driver_data = (unsigned long)&mwifiex_sdio_sd8997}, {}, @@ -2726,4 +2730,5 @@ MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME); +MODULE_FIRMWARE(SD8977_DEFAULT_FW_NAME); MODULE_FIRMWARE(SD8997_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.h b/drivers/net/wireless/marvell/mwifiex/sdio.h index dccf7fd1aef3..912de2cde8d9 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.h +++ b/drivers/net/wireless/marvell/mwifiex/sdio.h @@ -36,6 +36,7 @@ #define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin" #define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin" #define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin" +#define SD8977_DEFAULT_FW_NAME "mrvl/sd8977_uapsta.bin" #define SD8997_DEFAULT_FW_NAME "mrvl/sd8997_uapsta.bin" #define BLOCK_MODE 1 @@ -371,6 +372,59 @@ static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = { 0x59, 0x5c, 0x5d}, }; +static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8977 = { + .start_rd_port = 0, + .start_wr_port = 0, + .base_0_reg = 0xF8, + .base_1_reg = 0xF9, + .poll_reg = 0x5C, + .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | + CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK, + .host_int_rsr_reg = 0x4, + .host_int_status_reg = 0x0C, + .host_int_mask_reg = 0x08, + .status_reg_0 = 0xE8, + .status_reg_1 = 0xE9, + .sdio_int_mask = 0xff, + .data_port_mask = 0xffffffff, + .io_port_0_reg = 0xE4, + .io_port_1_reg = 0xE5, + .io_port_2_reg = 0xE6, + .max_mp_regs = 196, + .rd_bitmap_l = 0x10, + .rd_bitmap_u = 0x11, + .rd_bitmap_1l = 0x12, + .rd_bitmap_1u = 0x13, + .wr_bitmap_l = 0x14, + .wr_bitmap_u = 0x15, + .wr_bitmap_1l = 0x16, + .wr_bitmap_1u = 0x17, + .rd_len_p0_l = 0x18, + .rd_len_p0_u = 0x19, + .card_misc_cfg_reg = 0xd8, + .card_cfg_2_1_reg = 0xd9, + .cmd_rd_len_0 = 0xc0, + .cmd_rd_len_1 = 0xc1, + .cmd_rd_len_2 = 0xc2, + .cmd_rd_len_3 = 0xc3, + .cmd_cfg_0 = 0xc4, + .cmd_cfg_1 = 0xc5, + .cmd_cfg_2 = 0xc6, + .cmd_cfg_3 = 0xc7, + .fw_dump_host_ready = 0xcc, + .fw_dump_ctrl = 0xf0, + .fw_dump_start = 0xf1, + .fw_dump_end = 0xf8, + .func1_dump_reg_start = 0x10, + .func1_dump_reg_end = 0x17, + .func1_scratch_reg = 0xe8, + .func1_spec_reg_num = 13, + .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D, + 0x60, 0x61, 0x62, 0x64, + 0x65, 0x66, 0x68, 0x69, + 0x6a}, +}; + static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8997 = { .start_rd_port = 0, .start_wr_port = 0, @@ -532,6 +586,22 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { .can_ext_scan = true, }; +static const struct mwifiex_sdio_device mwifiex_sdio_sd8977 = { + .firmware = SD8977_DEFAULT_FW_NAME, + .reg = &mwifiex_reg_sd8977, + .max_ports = 32, + .mp_agg_pkt_limit = 16, + .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, + .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, + .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, + .supports_sdio_new_mode = true, + .has_control_mask = false, + .can_dump_fw = true, + .fw_dump_enh = true, + .can_auto_tdls = false, + .can_ext_scan = true, +}; + static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = { .firmware = SD8997_DEFAULT_FW_NAME, .reg = &mwifiex_reg_sd8997, -- cgit v1.2.3 From 126824f5ce671b4f2d1d01aa1fa7ff4de7174869 Mon Sep 17 00:00:00 2001 From: Andrey Shevchenko Date: Mon, 14 Jan 2019 09:39:35 +0000 Subject: qtnfmac: support EBUSY errcode for QLINK protocol Add support of EBUSY error code for remote procedures over QLINK protocol. Signed-off-by: Andrey Shevchenko Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/commands.c | 2 ++ drivers/net/wireless/quantenna/qtnfmac/qlink.h | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index cf386f579060..6575247c8b6b 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -72,6 +72,8 @@ static int qtnf_cmd_resp_result_decode(enum qlink_cmd_result qcode) return -EADDRINUSE; case QLINK_CMD_RESULT_EADDRNOTAVAIL: return -EADDRNOTAVAIL; + case QLINK_CMD_RESULT_EBUSY: + return -EBUSY; default: return -EFAULT; } diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 8d62addea895..f9c7f87afaf8 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -733,6 +733,7 @@ enum qlink_cmd_result { QLINK_CMD_RESULT_EALREADY, QLINK_CMD_RESULT_EADDRINUSE, QLINK_CMD_RESULT_EADDRNOTAVAIL, + QLINK_CMD_RESULT_EBUSY, }; /** -- cgit v1.2.3 From d1365e794eb31f74d7326f0c60a2aa13b2d70ac8 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 14 Jan 2019 09:39:36 +0000 Subject: qtnfmac: fix INTx interrupt handling In the current implementation INTx interrupt is deasserted after the control path processing. However this may lead to missed interrupts from the wireless card. For instance, this may happen as a result of control path activity, when another interrupt arrives before INTx is deasserted. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c index 598edb814421..cbcda57105f3 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c @@ -559,6 +559,9 @@ static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void *data) if (!priv->msi_enabled && !qtnf_topaz_intx_asserted(ts)) return IRQ_NONE; + if (!priv->msi_enabled) + qtnf_deassert_intx(ts); + priv->pcie_irq_count++; qtnf_shm_ipc_irq_handler(&priv->shm_ipc_ep_in); @@ -571,9 +574,6 @@ static irqreturn_t qtnf_pcie_topaz_interrupt(int irq, void *data) tasklet_hi_schedule(&priv->reclaim_tq); - if (!priv->msi_enabled) - qtnf_deassert_intx(ts); - return IRQ_HANDLED; } -- cgit v1.2.3 From de624a355d928b591af32f52198540b8f4b7048c Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 14 Jan 2019 09:39:38 +0000 Subject: qtnfmac: add support for 4addr mode Advertise WIPHY_FLAG_4ADDR_STATION capability to wireless core. Send use4addr interface change flag to firmware in change_virtual_intf cfg80211 callback. In order to enable adding wireless station interface to bridge one should turn on 4addr mode using the following command: $ iw dev wlan0 set 4addr on $ brctl addif br0 wlan0 If this commands succeeds, then interface can be added to bridge. Note that when wireless interface is added to bridge, wpa_supplicant should be started with appropriate -b parameter, e.g: $ wpa_supplicant -Dnl80211 -iwlan0 -c/path/to/wpa.conf -b br0 Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 21 +++++++++++++-------- drivers/net/wireless/quantenna/qtnfmac/commands.c | 14 +++++++++----- drivers/net/wireless/quantenna/qtnfmac/commands.h | 6 ++++-- drivers/net/wireless/quantenna/qtnfmac/core.c | 4 +++- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 3 ++- 5 files changed, 31 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 51b33ec78fac..a43f8120df3c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -122,7 +122,8 @@ qtnf_change_virtual_intf(struct wiphy *wiphy, struct vif_params *params) { struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); - u8 *mac_addr; + u8 *mac_addr = NULL; + int use4addr = 0; int ret; ret = qtnf_validate_iface_combinations(wiphy, vif, type); @@ -132,14 +133,14 @@ qtnf_change_virtual_intf(struct wiphy *wiphy, return ret; } - if (params) + if (params) { mac_addr = params->macaddr; - else - mac_addr = NULL; + use4addr = params->use_4addr; + } qtnf_scan_done(vif->mac, true); - ret = qtnf_cmd_send_change_intf_type(vif, type, mac_addr); + ret = qtnf_cmd_send_change_intf_type(vif, type, use4addr, mac_addr); if (ret) { pr_err("VIF%u.%u: failed to change type to %d\n", vif->mac->macid, vif->vifid, type); @@ -190,6 +191,7 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, struct qtnf_wmac *mac; struct qtnf_vif *vif; u8 *mac_addr = NULL; + int use4addr = 0; int ret; mac = wiphy_priv(wiphy); @@ -225,10 +227,12 @@ static struct wireless_dev *qtnf_add_virtual_intf(struct wiphy *wiphy, return ERR_PTR(-ENOTSUPP); } - if (params) + if (params) { mac_addr = params->macaddr; + use4addr = params->use_4addr; + } - ret = qtnf_cmd_send_add_intf(vif, type, mac_addr); + ret = qtnf_cmd_send_add_intf(vif, type, use4addr, mac_addr); if (ret) { pr_err("VIF%u.%u: failed to add VIF %pM\n", mac->macid, vif->vifid, mac_addr); @@ -1107,7 +1111,8 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_AP_UAPSD | - WIPHY_FLAG_HAS_CHANNEL_SWITCH; + WIPHY_FLAG_HAS_CHANNEL_SWITCH | + WIPHY_FLAG_4ADDR_STATION; wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; if (hw_info->hw_capab & QLINK_HW_CAPAB_DFS_OFFLOAD) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 6575247c8b6b..d03b3d03f4cc 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -734,6 +734,7 @@ out: static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype, + int use4addr, u8 *mac_addr, enum qlink_cmd_type cmd_type) { @@ -751,6 +752,7 @@ static int qtnf_cmd_send_add_change_intf(struct qtnf_vif *vif, qtnf_bus_lock(vif->mac->bus); cmd = (struct qlink_cmd_manage_intf *)cmd_skb->data; + cmd->intf_info.use4addr = use4addr; switch (iftype) { case NL80211_IFTYPE_AP: @@ -786,17 +788,19 @@ out: return ret; } -int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, - enum nl80211_iftype iftype, u8 *mac_addr) +int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype, + int use4addr, u8 *mac_addr) { - return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr, + return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr, QLINK_CMD_ADD_INTF); } int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif, - enum nl80211_iftype iftype, u8 *mac_addr) + enum nl80211_iftype iftype, + int use4addr, + u8 *mac_addr) { - return qtnf_cmd_send_add_change_intf(vif, iftype, mac_addr, + return qtnf_cmd_send_add_change_intf(vif, iftype, use4addr, mac_addr, QLINK_CMD_CHANGE_INTF); } diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h index 1ac41156c192..1c25e7905e9a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.h +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h @@ -26,9 +26,11 @@ void qtnf_cmd_send_deinit_fw(struct qtnf_bus *bus); int qtnf_cmd_get_hw_info(struct qtnf_bus *bus); int qtnf_cmd_get_mac_info(struct qtnf_wmac *mac); int qtnf_cmd_send_add_intf(struct qtnf_vif *vif, enum nl80211_iftype iftype, - u8 *mac_addr); + int use4addr, u8 *mac_addr); int qtnf_cmd_send_change_intf_type(struct qtnf_vif *vif, - enum nl80211_iftype iftype, u8 *mac_addr); + enum nl80211_iftype iftype, + int use4addr, + u8 *mac_addr); int qtnf_cmd_send_del_intf(struct qtnf_vif *vif); int qtnf_cmd_band_info_get(struct qtnf_wmac *mac, struct ieee80211_supported_band *band); diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 5d18a4a917c9..29258acfa8dc 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -195,6 +195,7 @@ static int qtnf_netdev_set_mac_address(struct net_device *ndev, void *addr) qtnf_scan_done(vif->mac, true); ret = qtnf_cmd_send_change_intf_type(vif, vif->wdev.iftype, + vif->wdev.use_4addr, sa->sa_data); if (ret) @@ -545,7 +546,8 @@ static int qtnf_core_mac_attach(struct qtnf_bus *bus, unsigned int macid) goto error; } - ret = qtnf_cmd_send_add_intf(vif, vif->wdev.iftype, vif->mac_addr); + ret = qtnf_cmd_send_add_intf(vif, vif->wdev.iftype, + vif->wdev.use_4addr, vif->mac_addr); if (ret) { pr_err("MAC%u: failed to add VIF\n", macid); goto error; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index f9c7f87afaf8..a78cb9e05068 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -105,7 +105,8 @@ struct qlink_intf_info { __le16 if_type; __le16 vlanid; u8 mac_addr[ETH_ALEN]; - u8 rsvd[2]; + u8 use4addr; + u8 rsvd[1]; } __packed; enum qlink_sta_flags { -- cgit v1.2.3 From 9fe504a1317250ab97275e6d0a6a9de39fb60b82 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 14 Jan 2019 09:39:40 +0000 Subject: qtnfmac: switch to 32bit values for RTS/FRAG thresholds Host wireless stack uses u32 type for RTS/FRAG threshold values. Switch to u32 in driver: pass u32 values to firmware and let firmware properly adapt these values according to its internal representation. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/commands.c | 8 ++++---- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 4 ++-- drivers/net/wireless/quantenna/qtnfmac/qlink_util.h | 11 +++++++++++ 3 files changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index d03b3d03f4cc..74dcbcfcd694 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -1563,11 +1563,11 @@ static int qtnf_cmd_resp_proc_phy_params(struct qtnf_wmac *mac, switch (tlv_type) { case QTN_TLV_ID_FRAG_THRESH: phy_thr = (void *)tlv; - mac_info->frag_thr = (u32)le16_to_cpu(phy_thr->thr); + mac_info->frag_thr = le32_to_cpu(phy_thr->thr); break; case QTN_TLV_ID_RTS_THRESH: phy_thr = (void *)tlv; - mac_info->rts_thr = (u32)le16_to_cpu(phy_thr->thr); + mac_info->rts_thr = le32_to_cpu(phy_thr->thr); break; case QTN_TLV_ID_SRETRY_LIMIT: limit = (void *)tlv; @@ -1815,10 +1815,10 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) qtnf_bus_lock(mac->bus); if (changed & WIPHY_PARAM_FRAG_THRESHOLD) - qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_FRAG_THRESH, + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_FRAG_THRESH, wiphy->frag_threshold); if (changed & WIPHY_PARAM_RTS_THRESHOLD) - qtnf_cmd_skb_put_tlv_u16(cmd_skb, QTN_TLV_ID_RTS_THRESH, + qtnf_cmd_skb_put_tlv_u32(cmd_skb, QTN_TLV_ID_RTS_THRESH, wiphy->rts_threshold); if (changed & WIPHY_PARAM_COVERAGE_CLASS) qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index a78cb9e05068..ace52e9d421d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -19,7 +19,7 @@ #include -#define QLINK_PROTO_VER 11 +#define QLINK_PROTO_VER 12 #define QLINK_MACID_RSVD 0xFF #define QLINK_VIFID_RSVD 0xFF @@ -1184,7 +1184,7 @@ struct qlink_iface_limit_record { struct qlink_tlv_frag_rts_thr { struct qlink_tlv_hdr hdr; - __le16 thr; + __le32 thr; } __packed; struct qlink_tlv_rlimit { diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index 960d5d97492f..fc87827cb49c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -69,6 +69,17 @@ static inline void qtnf_cmd_skb_put_tlv_u16(struct sk_buff *skb, memcpy(hdr->val, &tmp, sizeof(tmp)); } +static inline void qtnf_cmd_skb_put_tlv_u32(struct sk_buff *skb, + u16 tlv_id, u32 value) +{ + struct qlink_tlv_hdr *hdr = skb_put(skb, sizeof(*hdr) + sizeof(value)); + __le32 tmp = cpu_to_le32(value); + + hdr->type = cpu_to_le16(tlv_id); + hdr->len = cpu_to_le16(sizeof(value)); + memcpy(hdr->val, &tmp, sizeof(tmp)); +} + u16 qlink_iface_type_to_nl_mask(u16 qlink_type); u8 qlink_chan_width_mask_to_nl(u16 qlink_mask); void qlink_chandef_q2cfg(struct wiphy *wiphy, -- cgit v1.2.3 From f3c8bd46c774153f1d08f10a7baafb2946efa8fa Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 14 Jan 2019 09:39:42 +0000 Subject: qtnfmac: do not reject retry changes in driver Do not reject RETRY changes in driver. This decision should belong to firmware. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 5 ----- drivers/net/wireless/quantenna/qtnfmac/commands.c | 8 ++++++++ 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index a43f8120df3c..1b02096934f8 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -363,11 +363,6 @@ static int qtnf_set_wiphy_params(struct wiphy *wiphy, u32 changed) return -EFAULT; } - if (changed & (WIPHY_PARAM_RETRY_LONG | WIPHY_PARAM_RETRY_SHORT)) { - pr_err("MAC%u: can't modify retry params\n", mac->macid); - return -EOPNOTSUPP; - } - ret = qtnf_cmd_send_update_phy_params(mac, changed); if (ret) pr_err("MAC%u: failed to update PHY params\n", mac->macid); diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 74dcbcfcd694..0cb76acbec99 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -1824,6 +1824,14 @@ int qtnf_cmd_send_update_phy_params(struct qtnf_wmac *mac, u32 changed) qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_COVERAGE_CLASS, wiphy->coverage_class); + if (changed & WIPHY_PARAM_RETRY_LONG) + qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_LRETRY_LIMIT, + wiphy->retry_long); + + if (changed & WIPHY_PARAM_RETRY_SHORT) + qtnf_cmd_skb_put_tlv_u8(cmd_skb, QTN_TLV_ID_SRETRY_LIMIT, + wiphy->retry_short); + ret = qtnf_cmd_send(mac->bus, cmd_skb); if (ret) goto out; -- cgit v1.2.3 From ff233cb515031d95550958c5797a70222749e9a3 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 14 Jan 2019 09:39:45 +0000 Subject: qtnfmac: convert to SPDX license identifiers Replace textual license with SPDX-License-Identifier. Add an SPDX-License-Identifier for the Makefile. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/Makefile | 1 + drivers/net/wireless/quantenna/qtnfmac/bus.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/cfg80211.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/commands.c | 16 ++-------------- drivers/net/wireless/quantenna/qtnfmac/commands.h | 16 ++-------------- drivers/net/wireless/quantenna/qtnfmac/core.c | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/core.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/debug.c | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/debug.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/event.c | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/event.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/qlink_util.c | 16 ++-------------- drivers/net/wireless/quantenna/qtnfmac/qlink_util.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/trans.c | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/trans.h | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/util.c | 17 ++--------------- drivers/net/wireless/quantenna/qtnfmac/util.h | 17 ++--------------- 23 files changed, 45 insertions(+), 327 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/Makefile b/drivers/net/wireless/quantenna/Makefile index baebfbde119e..cea83d178d2e 100644 --- a/drivers/net/wireless/quantenna/Makefile +++ b/drivers/net/wireless/quantenna/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # # Copyright (c) 2015-2016 Quantenna Communications, Inc. # All rights reserved. diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h b/drivers/net/wireless/quantenna/qtnfmac/bus.h index 528ca7f5e070..7bd906cc7023 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/bus.h +++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015 Quantenna Communications - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015 Quantenna Communications. All rights reserved. */ #ifndef QTNFMAC_BUS_H #define QTNFMAC_BUS_H diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 1b02096934f8..45f4cef7de9c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2012-2012 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include #include diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h index b73425122a10..c374857283ac 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_FMAC_CFG80211_H_ #define _QTN_FMAC_CFG80211_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 0cb76acbec99..23c39735ae0c 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -1,17 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include #include diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h index 1c25e7905e9a..96dff643bbc4 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.h +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h @@ -1,17 +1,5 @@ -/* - * Copyright (c) 2016 Quantenna Communications, Inc. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2016 Quantenna Communications. All rights reserved. */ #ifndef QLINK_COMMANDS_H_ #define QLINK_COMMANDS_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.c b/drivers/net/wireless/quantenna/qtnfmac/core.c index 29258acfa8dc..ee1b75fda1dd 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.c +++ b/drivers/net/wireless/quantenna/qtnfmac/core.c @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include #include diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h index 293055049caa..a31cff46e964 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/core.h +++ b/drivers/net/wireless/quantenna/qtnfmac/core.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_FMAC_CORE_H_ #define _QTN_FMAC_CORE_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.c b/drivers/net/wireless/quantenna/qtnfmac/debug.c index 9f826b9ef5d9..ad70cdb80060 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/debug.c +++ b/drivers/net/wireless/quantenna/qtnfmac/debug.c @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include "debug.h" diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.h b/drivers/net/wireless/quantenna/qtnfmac/debug.h index d6dd12b5d434..61b45536b83a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/debug.h +++ b/drivers/net/wireless/quantenna/qtnfmac/debug.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_FMAC_DEBUG_H_ #define _QTN_FMAC_DEBUG_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 8b542b431b75..3038a000c287 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include #include diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.h b/drivers/net/wireless/quantenna/qtnfmac/event.h index ae759b602c2a..533ad99d045d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.h +++ b/drivers/net/wireless/quantenna/qtnfmac/event.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_FMAC_EVENT_H_ #define _QTN_FMAC_EVENT_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index ace52e9d421d..d958b268de02 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_QLINK_H_ #define _QTN_QLINK_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c index aeeda81b09ea..72bfd17cb687 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.c @@ -1,17 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h index fc87827cb49c..781ea7fe79f2 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink_util.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_FMAC_QLINK_UTIL_H_ #define _QTN_FMAC_QLINK_UTIL_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h index 40295a511224..82d879950b62 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qtn_hw_ids.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_HW_IDS_H_ #define _QTN_HW_IDS_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c index 2ec334199c2b..ff678951d3b2 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c +++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.c @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include #include diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h index c2a3702a9ee7..52cac5439b03 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h +++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_FMAC_SHM_IPC_H_ #define _QTN_FMAC_SHM_IPC_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h index 95a5f89a8b1a..78be70df1218 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h +++ b/drivers/net/wireless/quantenna/qtnfmac/shm_ipc_defs.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_FMAC_SHM_IPC_DEFS_H_ #define _QTN_FMAC_SHM_IPC_DEFS_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.c b/drivers/net/wireless/quantenna/qtnfmac/trans.c index 345f34ec9750..95356e280e23 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/trans.c +++ b/drivers/net/wireless/quantenna/qtnfmac/trans.c @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include #include diff --git a/drivers/net/wireless/quantenna/qtnfmac/trans.h b/drivers/net/wireless/quantenna/qtnfmac/trans.h index 9a473e07af0f..c0b76f871b31 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/trans.h +++ b/drivers/net/wireless/quantenna/qtnfmac/trans.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #ifndef _QTN_FMAC_TRANS_H_ #define _QTN_FMAC_TRANS_H_ diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.c b/drivers/net/wireless/quantenna/qtnfmac/util.c index 3bc96b264769..cda6f5f3f38a 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/util.c +++ b/drivers/net/wireless/quantenna/qtnfmac/util.c @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015-2016 Quantenna Communications, Inc. - * All rights reserved. - * - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */ #include "util.h" #include "qtn_hw_ids.h" diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.h b/drivers/net/wireless/quantenna/qtnfmac/util.h index b8744baac332..a14b7078a9c7 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/util.h +++ b/drivers/net/wireless/quantenna/qtnfmac/util.h @@ -1,18 +1,5 @@ -/* - * Copyright (c) 2015 Quantenna Communications - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2015 Quantenna Communications. All rights reserved. */ #ifndef QTNFMAC_UTIL_H #define QTNFMAC_UTIL_H -- cgit v1.2.3 From 23781af74152418055531fe7fec4e55b9502ddc2 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 14 Jan 2019 09:39:47 +0000 Subject: qtnfmac: add missing bss record to host scan cache Make sure that valid BSS entry exists in wireless core record even in the case of successful connect reported by firmware. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/event.c | 79 ++++++++++++++++++++++++-- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 4 +- 2 files changed, 78 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 3038a000c287..3fd1a9217737 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -145,6 +145,12 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, const struct qlink_event_bss_join *join_info, u16 len) { + struct wiphy *wiphy = priv_to_wiphy(vif->mac); + enum ieee80211_statuscode status = le16_to_cpu(join_info->status); + struct cfg80211_chan_def chandef; + struct cfg80211_bss *bss = NULL; + u8 *ie = NULL; + if (unlikely(len < sizeof(*join_info))) { pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", vif->mac->macid, vif->vifid, len, @@ -158,15 +164,80 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, return -EPROTO; } - pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid, - join_info->bssid); + pr_debug("VIF%u.%u: BSSID:%pM status:%u\n", + vif->mac->macid, vif->vifid, join_info->bssid, status); + + if (status == WLAN_STATUS_SUCCESS) { + qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef); + if (!cfg80211_chandef_valid(&chandef)) { + pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n", + vif->mac->macid, vif->vifid, + chandef.chan->center_freq, + chandef.center_freq1, + chandef.center_freq2, + chandef.width); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid, + NULL, 0, IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); + if (!bss) { + pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n", + vif->mac->macid, vif->vifid, + join_info->bssid, chandef.chan->hw_value); + + if (!vif->wdev.ssid_len) { + pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n", + vif->mac->macid, vif->vifid, + join_info->bssid); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + + ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL); + if (!ie) { + pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n", + vif->mac->macid, vif->vifid, + join_info->bssid); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + + ie[0] = WLAN_EID_SSID; + ie[1] = vif->wdev.ssid_len; + memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len); + + bss = cfg80211_inform_bss(wiphy, chandef.chan, + CFG80211_BSS_FTYPE_UNKNOWN, + join_info->bssid, 0, + WLAN_CAPABILITY_ESS, 100, + ie, 2 + vif->wdev.ssid_len, + 0, GFP_KERNEL); + if (!bss) { + pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n", + vif->mac->macid, vif->vifid, + join_info->bssid); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + } + } + +done: cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL, - 0, le16_to_cpu(join_info->status), GFP_KERNEL); + 0, status, GFP_KERNEL); + if (bss) { + if (!ether_addr_equal(vif->bssid, join_info->bssid)) + ether_addr_copy(vif->bssid, join_info->bssid); + cfg80211_put_bss(wiphy, bss); + } - if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) + if (status == WLAN_STATUS_SUCCESS) netif_carrier_on(vif->netdev); + kfree(ie); return 0; } diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index d958b268de02..27fdb5b01ee3 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -6,7 +6,7 @@ #include -#define QLINK_PROTO_VER 12 +#define QLINK_PROTO_VER 13 #define QLINK_MACID_RSVD 0xFF #define QLINK_VIFID_RSVD 0xFF @@ -975,11 +975,13 @@ struct qlink_event_sta_deauth { /** * struct qlink_event_bss_join - data for QLINK_EVENT_BSS_JOIN event * + * @chan: new operating channel definition * @bssid: BSSID of a BSS which interface tried to joined. * @status: status of joining attempt, see &enum ieee80211_statuscode. */ struct qlink_event_bss_join { struct qlink_event ehdr; + struct qlink_chandef chan; u8 bssid[ETH_ALEN]; __le16 status; } __packed; -- cgit v1.2.3 From 324b8cad8cfc42fbf1dcffc7ec92967f961e9032 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 14 Jan 2019 09:39:49 +0000 Subject: qtnfmac: remove unused declarations Remove declarations for inexistent functions from bus.h header. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/bus.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/bus.h b/drivers/net/wireless/quantenna/qtnfmac/bus.h index 7bd906cc7023..14b569b6d1b5 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/bus.h +++ b/drivers/net/wireless/quantenna/qtnfmac/bus.h @@ -122,7 +122,5 @@ static __always_inline void qtnf_bus_unlock(struct qtnf_bus *bus) int qtnf_core_attach(struct qtnf_bus *bus); void qtnf_core_detach(struct qtnf_bus *bus); -void qtnf_txflowblock(struct device *dev, bool state); -void qtnf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); #endif /* QTNFMAC_BUS_H */ -- cgit v1.2.3 From 3844dec0f45df0737eec86444e280057fd042507 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Mon, 14 Jan 2019 09:39:51 +0000 Subject: qtnfmac: qtnf_cmd_send_with_reply cleanup Use existing variable with dereferenced cmd_id field. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/commands.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 23c39735ae0c..0f48f541de41 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -87,14 +87,12 @@ static int qtnf_cmd_send_with_reply(struct qtnf_bus *bus, vif_id = cmd->vifid; cmd->mhdr.len = cpu_to_le16(cmd_skb->len); - pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, - le16_to_cpu(cmd->cmd_id)); + pr_debug("VIF%u.%u cmd=0x%.4X\n", mac_id, vif_id, cmd_id); if (bus->fw_state != QTNF_FW_STATE_ACTIVE && - le16_to_cpu(cmd->cmd_id) != QLINK_CMD_FW_INIT) { + cmd_id != QLINK_CMD_FW_INIT) { pr_warn("VIF%u.%u: drop cmd 0x%.4X in fw state %d\n", - mac_id, vif_id, le16_to_cpu(cmd->cmd_id), - bus->fw_state); + mac_id, vif_id, cmd_id, bus->fw_state); dev_kfree_skb(cmd_skb); return -ENODEV; } @@ -128,7 +126,7 @@ out: return qtnf_cmd_resp_result_decode(le16_to_cpu(resp->result)); pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n", - mac_id, vif_id, le16_to_cpu(cmd->cmd_id), ret); + mac_id, vif_id, cmd_id, ret); return ret; } -- cgit v1.2.3 From a4296994eb8061ee3455721a296c387c639bf635 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Tue, 15 Jan 2019 14:01:29 +0000 Subject: rt2x00: Work around a firmware bug with shared keys Apparently the rt2x61 firmware fails temporarily to decode broadcast packets if the shared keys are not assigned in the "correct" sequence. At the same time unicast packets work fine, since they are encrypted with the pairwise key. At least with WPA2 CCMP mode the shared keys are set in the following sequence: keyidx=1, 2, 1, 2. After a while only keyidx 2 gets decrypted, and keyidx 1 is ignored, probably because there is never a keyidx 3. Symptoms are arping -b works for 10 minutes, since keyidx=2 is used for broadcast, and then it stops working for 10 minutes, because keyidx=1 is used. That failure mode repeats forever. Note, the firmware does not even know which keyidx corresponds to which hw_key_idx so the firmware is trying to be smarter than the driver, which is bound to fail. As workaround the function rt61pci_config_shared_key requests software decryption of the shared keys, by returning EOPNOTSUPP. However, pairwise keys are still handled by hardware which works just fine. Signed-off-by: Bernd Edlinger Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt61pci.c | 93 ++-------------------------- 1 file changed, 4 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c index 4c5de8fc8f12..52b9fc480f8b 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c @@ -321,97 +321,12 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key) { - struct hw_key_entry key_entry; - struct rt2x00_field32 field; - u32 mask; - u32 reg; - - if (crypto->cmd == SET_KEY) { - /* - * rt2x00lib can't determine the correct free - * key_idx for shared keys. We have 1 register - * with key valid bits. The goal is simple, read - * the register, if that is full we have no slots - * left. - * Note that each BSS is allowed to have up to 4 - * shared keys, so put a mask over the allowed - * entries. - */ - mask = (0xf << crypto->bssidx); - - reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0); - reg &= mask; - - if (reg && reg == mask) - return -ENOSPC; - - key->hw_key_idx += reg ? ffz(reg) : 0; - - /* - * Upload key to hardware - */ - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - reg = SHARED_KEY_ENTRY(key->hw_key_idx); - rt2x00mmio_register_multiwrite(rt2x00dev, reg, - &key_entry, sizeof(key_entry)); - - /* - * The cipher types are stored over 2 registers. - * bssidx 0 and 1 keys are stored in SEC_CSR1 and - * bssidx 1 and 2 keys are stored in SEC_CSR5. - * Using the correct defines correctly will cause overhead, - * so just calculate the correct offset. - */ - if (key->hw_key_idx < 8) { - field.bit_offset = (3 * key->hw_key_idx); - field.bit_mask = 0x7 << field.bit_offset; - - reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR1); - rt2x00_set_field32(®, field, crypto->cipher); - rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg); - } else { - field.bit_offset = (3 * (key->hw_key_idx - 8)); - field.bit_mask = 0x7 << field.bit_offset; - - reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR5); - rt2x00_set_field32(®, field, crypto->cipher); - rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg); - } - - /* - * The driver does not support the IV/EIV generation - * in hardware. However it doesn't support the IV/EIV - * inside the ieee80211 frame either, but requires it - * to be provided separately for the descriptor. - * rt2x00lib will cut the IV/EIV data out of all frames - * given to us by mac80211, but we must tell mac80211 - * to generate the IV/EIV data. - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } - /* - * SEC_CSR0 contains only single-bit fields to indicate - * a particular key is valid. Because using the FIELD32() - * defines directly will cause a lot of overhead, we use - * a calculation to determine the correct bit directly. + * Let the software handle the shared keys, + * since the hardware decryption does not work reliably, + * because the firmware does not know the key's keyidx. */ - mask = 1 << key->hw_key_idx; - - reg = rt2x00mmio_register_read(rt2x00dev, SEC_CSR0); - if (crypto->cmd == SET_KEY) - reg |= mask; - else if (crypto->cmd == DISABLE_KEY) - reg &= ~mask; - rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg); - - return 0; + return -EOPNOTSUPP; } static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, -- cgit v1.2.3 From 6dcbe4592e7adf281a0593bb01f818b20d572b37 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 16 Jan 2019 17:25:33 +0000 Subject: libertas: fix indentation issue There is a statement that is incorrectly indented, fix it. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index 1d45da187b9b..a7cb7d06e5e6 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c @@ -676,7 +676,7 @@ int lbtf_remove_card(struct lbtf_private *priv) ieee80211_unregister_hw(hw); ieee80211_free_hw(hw); - lbtf_deb_leave(LBTF_DEB_MAIN); + lbtf_deb_leave(LBTF_DEB_MAIN); return 0; } EXPORT_SYMBOL_GPL(lbtf_remove_card); -- cgit v1.2.3 From b0535d502d1804197f3aaaaf5a3429c5779268e4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 17 Jan 2019 14:36:23 +0000 Subject: cw1200: fix indentation issues There are two lines that have indentation issues, fix these. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/st/cw1200/fwio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/st/cw1200/fwio.c b/drivers/net/wireless/st/cw1200/fwio.c index 30e7646d04af..b7881232499c 100644 --- a/drivers/net/wireless/st/cw1200/fwio.c +++ b/drivers/net/wireless/st/cw1200/fwio.c @@ -465,8 +465,8 @@ int cw1200_load_firmware(struct cw1200_common *priv) if (!(val32 & ST90TDS_CONFIG_ACCESS_MODE_BIT)) { pr_err("Device is already in QUEUE mode!\n"); - ret = -EINVAL; - goto out; + ret = -EINVAL; + goto out; } switch (priv->hw_type) { -- cgit v1.2.3 From 2d76fff865d64974da79e64bb5e9ad63c20bbb9f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 17 Jan 2019 15:28:59 +0000 Subject: rtlwifi: rtl818x: fix indentation issue There is a statement that is indented too deeply. Fix this. Signed-off-by: Colin Ian King Acked-by: John W. Linville Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c index 225c1c8851cc..e2b1bfbcfbd4 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c @@ -803,7 +803,7 @@ static void rtl8180_config_cardbus(struct ieee80211_hw *dev) rtl818x_iowrite16(priv, FEMR_SE, 0xffff); } else { reg16 = rtl818x_ioread16(priv, &priv->map->FEMR); - reg16 |= (1 << 15) | (1 << 14) | (1 << 4); + reg16 |= (1 << 15) | (1 << 14) | (1 << 4); rtl818x_iowrite16(priv, &priv->map->FEMR, reg16); } -- cgit v1.2.3 From 999eb686aa909c4609ae336979327bcf3d876462 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 18 Jan 2019 11:32:15 +0800 Subject: wireless: remove unneeded semicolon remove unneeded semicolon Signed-off-by: YueHaibing Acked-by: Ping-Ke Shih Acked-by: Steve deRosier Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 2 +- drivers/net/wireless/ath/ath6kl/init.c | 2 +- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 2 +- drivers/net/wireless/ray_cs.c | 2 +- drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 2034ccc7cc72..021eb30d1fb7 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1986,7 +1986,7 @@ static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode) /* no default handler to allow compiler to check that the * enum is fully handled */ - }; + } return ""; } diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 54132af70094..aa1c71a76ef7 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1140,7 +1140,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) len -= ie_len; data += ie_len; - }; + } ret = 0; out: diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index d64bf233b12c..ec129864cc9c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -315,7 +315,7 @@ static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev, /* bail out as things are really fishy here */ WARN(1, "invalid sdio function number: %d\n", func->num); err = -ENOMEDIUM; - }; + } if (err == -ENOMEDIUM) brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM); diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 8b2741c8edf2..44a943d18b84 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -2211,7 +2211,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, untranslate(local, skb, total_len); } } else { /* sniffer mode, so just pass whole packet */ - }; + } /************************/ /* Now pick up the rest of the fragments if any */ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c index 1263b12db5dc..11f94b1a436f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c @@ -332,7 +332,7 @@ static void _rtl8723be_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", rate_section, path, txnum); break; - }; + } } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", @@ -374,7 +374,7 @@ static u8 _rtl8723be_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", rate_section, path, txnum); break; - }; + } } else { RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", @@ -694,7 +694,7 @@ static u8 _rtl8723be_get_rate_section_index(u32 regaddr) else if (regaddr >= 0xE20 && regaddr <= 0xE4C) index = (u8)((regaddr - 0xE20) / 4); break; - }; + } return index; } -- cgit v1.2.3 From 1e1b4161e85971c5644d627fc174a4502907d563 Mon Sep 17 00:00:00 2001 From: Siva Rebbagondla Date: Fri, 18 Jan 2019 14:48:07 +0530 Subject: rsi: Suppress sdhci warnings in mmc while inserting and removing sdio module multiple times, we are getting sdhci warnings. This is because, improper assignment of ocr_avail value. Fixed this by assigning proper value. This patch is enhancement for commit 78e450719c702 ("rsi: Fix 'invalid vdd' warning in mmc"). Signed-off-by: Siva Rebbagondla Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_sdio.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 5733e440ecaf..b412b65eb1f4 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -230,16 +230,19 @@ static void rsi_reset_card(struct sdio_func *pfunction) rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err); /* Issue CMD5, arg = 0 */ - err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, 0, - (MMC_RSP_R4 | MMC_CMD_BCR), &resp); - if (err) - rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", __func__, err); - card->ocr = resp; + if (!host->ocr_avail) { + err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, 0, + (MMC_RSP_R4 | MMC_CMD_BCR), &resp); + if (err) + rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", + __func__, err); + host->ocr_avail = resp; + } /* Issue CMD5, arg = ocr. Wait till card is ready */ for (i = 0; i < 100; i++) { err = rsi_issue_sdiocommand(pfunction, SD_IO_SEND_OP_COND, - card->ocr, + host->ocr_avail, (MMC_RSP_R4 | MMC_CMD_BCR), &resp); if (err) { rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n", -- cgit v1.2.3 From 112ec26fcdc55ee1ecfe98ee9e1d6852daa25649 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 18 Jan 2019 23:12:31 +0000 Subject: wlcore: clean up an indentation issue There is a goto statement that is missing a tab for indentation. Fix this. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 903968735a74..348be0aed97e 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -1427,7 +1427,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_warning("could not set keys"); - goto out; + goto out; } out: -- cgit v1.2.3 From 3bd1505fed71d834f45e87b32ff07157fdda47e0 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 22 Jan 2019 13:47:54 +0100 Subject: mt7601u: bump supported EEPROM version As reported by Michael eeprom 0d is supported and work with the driver. Dump of /sys/kernel/debug/ieee80211/phy1/mt7601u/eeprom_param with 0d EEPORM looks like this: RSSI offset: 0 0 Reference temp: f9 LNA gain: 8 Reg channels: 1-14 Per rate power: raw:05 bw20:05 bw40:05 raw:05 bw20:05 bw40:05 raw:03 bw20:03 bw40:03 raw:03 bw20:03 bw40:03 raw:04 bw20:04 bw40:04 raw:00 bw20:00 bw40:00 raw:00 bw20:00 bw40:00 raw:00 bw20:00 bw40:00 raw:02 bw20:02 bw40:02 raw:00 bw20:00 bw40:00 Per channel power: tx_power ch1:09 ch2:09 tx_power ch3:0a ch4:0a tx_power ch5:0a ch6:0a tx_power ch7:0b ch8:0b tx_power ch9:0b ch10:0b tx_power ch11:0b ch12:0b tx_power ch13:0b ch14:0b Reported-and-tested-by: Michael Signed-off-by: Stanislaw Gruszka Acked-by: Jakub Kicinski Signed-off-by: Kalle Valo --- drivers/net/wireless/mediatek/mt7601u/eeprom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt7601u/eeprom.h b/drivers/net/wireless/mediatek/mt7601u/eeprom.h index 662d12703b69..57b503ae63f1 100644 --- a/drivers/net/wireless/mediatek/mt7601u/eeprom.h +++ b/drivers/net/wireless/mediatek/mt7601u/eeprom.h @@ -17,7 +17,7 @@ struct mt7601u_dev; -#define MT7601U_EE_MAX_VER 0x0c +#define MT7601U_EE_MAX_VER 0x0d #define MT7601U_EEPROM_SIZE 256 #define MT7601U_DEFAULT_TX_POWER 6 -- cgit v1.2.3 From 71ee1284d6267904dc2ef0172a30a93d4a2e8234 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:18 +0100 Subject: iwlegacy: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Stanislaw Gruszka Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/intel/iwlegacy/3945-mac.c | 5 +--- drivers/net/wireless/intel/iwlegacy/4965-mac.c | 5 +--- drivers/net/wireless/intel/iwlegacy/common.h | 6 ++--- drivers/net/wireless/intel/iwlegacy/debug.c | 34 +++----------------------- 4 files changed, 8 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlegacy/3945-mac.c b/drivers/net/wireless/intel/iwlegacy/3945-mac.c index 57e3b6cca234..271977f7fbb0 100644 --- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c @@ -3756,10 +3756,7 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto out_remove_sysfs; - err = il_dbgfs_register(il, DRV_NAME); - if (err) - IL_ERR("failed to create debugfs files. Ignoring error: %d\n", - err); + il_dbgfs_register(il, DRV_NAME); /* Start monitoring the killswitch */ queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll, 2 * HZ); diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index 6b4488a178a7..94222ae464ae 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -4988,10 +4988,7 @@ il4965_ucode_callback(const struct firmware *ucode_raw, void *context) if (err) goto out_unbind; - err = il_dbgfs_register(il, DRV_NAME); - if (err) - IL_ERR("failed to create debugfs files. Ignoring error: %d\n", - err); + il_dbgfs_register(il, DRV_NAME); err = sysfs_create_group(&il->pci_dev->dev.kobj, &il_attribute_group); if (err) { diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h index dc6a74a05983..b079c64ca014 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.h +++ b/drivers/net/wireless/intel/iwlegacy/common.h @@ -2974,13 +2974,11 @@ il_print_hex_dump(struct il_priv *il, int level, const void *p, u32 len) #endif /* CONFIG_IWLEGACY_DEBUG */ #ifdef CONFIG_IWLEGACY_DEBUGFS -int il_dbgfs_register(struct il_priv *il, const char *name); +void il_dbgfs_register(struct il_priv *il, const char *name); void il_dbgfs_unregister(struct il_priv *il); #else -static inline int -il_dbgfs_register(struct il_priv *il, const char *name) +static inline void il_dbgfs_register(struct il_priv *il, const char *name) { - return 0; } static inline void diff --git a/drivers/net/wireless/intel/iwlegacy/debug.c b/drivers/net/wireless/intel/iwlegacy/debug.c index d76073def677..fa211412e0ac 100644 --- a/drivers/net/wireless/intel/iwlegacy/debug.c +++ b/drivers/net/wireless/intel/iwlegacy/debug.c @@ -128,23 +128,12 @@ EXPORT_SYMBOL(il_update_stats); /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, il, \ - &il_dbgfs_##name##_ops)) \ - goto err; \ + debugfs_create_file(#name, mode, parent, il, \ + &il_dbgfs_##name##_ops); \ } while (0) #define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ - struct dentry *__tmp; \ - __tmp = debugfs_create_bool(#name, 0600, parent, ptr); \ - if (IS_ERR(__tmp) || !__tmp) \ - goto err; \ -} while (0) - -#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ - struct dentry *__tmp; \ - __tmp = debugfs_create_x32(#name, 0600, parent, ptr); \ - if (IS_ERR(__tmp) || !__tmp) \ - goto err; \ + debugfs_create_bool(#name, 0600, parent, ptr); \ } while (0) /* file operation */ @@ -1341,27 +1330,18 @@ DEBUGFS_WRITE_FILE_OPS(wd_timeout); * Create the debugfs files and directories * */ -int +void il_dbgfs_register(struct il_priv *il, const char *name) { struct dentry *phyd = il->hw->wiphy->debugfsdir; struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; dir_drv = debugfs_create_dir(name, phyd); - if (!dir_drv) - return -ENOMEM; - il->debugfs_dir = dir_drv; dir_data = debugfs_create_dir("data", dir_drv); - if (!dir_data) - goto err; dir_rf = debugfs_create_dir("rf", dir_drv); - if (!dir_rf) - goto err; dir_debug = debugfs_create_dir("debug", dir_drv); - if (!dir_debug) - goto err; DEBUGFS_ADD_FILE(nvm, dir_data, 0400); DEBUGFS_ADD_FILE(sram, dir_data, 0600); @@ -1399,12 +1379,6 @@ il_dbgfs_register(struct il_priv *il, const char *name) DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &il->disable_chain_noise_cal); DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &il->disable_tx_power_cal); - return 0; - -err: - IL_ERR("Can't create the debugfs directory\n"); - il_dbgfs_unregister(il); - return -ENOMEM; } EXPORT_SYMBOL(il_dbgfs_register); -- cgit v1.2.3 From ad2106ca00dfce85ccae7dea28168c3d9e6cc800 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:24 +0100 Subject: wlcore: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Kalle Valo Cc: Tony Lindgren Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Tony Lindgren Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/debugfs.c | 28 ++++------------------------ drivers/net/wireless/ti/wlcore/debugfs.h | 10 +++------- 2 files changed, 7 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index aeb74e74698e..68acd901d384 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -1301,11 +1301,10 @@ static const struct file_operations fw_logger_ops = { .llseek = default_llseek, }; -static int wl1271_debugfs_add_files(struct wl1271 *wl, - struct dentry *rootdir) +static void wl1271_debugfs_add_files(struct wl1271 *wl, + struct dentry *rootdir) { - int ret = 0; - struct dentry *entry, *streaming; + struct dentry *streaming; DEBUGFS_ADD(tx_queue_len, rootdir); DEBUGFS_ADD(retry_count, rootdir); @@ -1330,23 +1329,11 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(fw_logger, rootdir); streaming = debugfs_create_dir("rx_streaming", rootdir); - if (!streaming || IS_ERR(streaming)) - goto err; DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); DEBUGFS_ADD_PREFIX(dev, mem, rootdir); - - return 0; - -err: - if (IS_ERR(entry)) - ret = PTR_ERR(entry); - else - ret = -ENOMEM; - - return ret; } void wl1271_debugfs_reset(struct wl1271 *wl) @@ -1367,11 +1354,6 @@ int wl1271_debugfs_init(struct wl1271 *wl) rootdir = debugfs_create_dir(KBUILD_MODNAME, wl->hw->wiphy->debugfsdir); - if (IS_ERR(rootdir)) { - ret = PTR_ERR(rootdir); - goto out; - } - wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL); if (!wl->stats.fw_stats) { ret = -ENOMEM; @@ -1380,9 +1362,7 @@ int wl1271_debugfs_init(struct wl1271 *wl) wl->stats.fw_stats_update = jiffies; - ret = wl1271_debugfs_add_files(wl, rootdir); - if (ret < 0) - goto out_exit; + wl1271_debugfs_add_files(wl, rootdir); ret = wlcore_debugfs_init(wl, rootdir); if (ret < 0) diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h index bf14676e6515..a4952c4f587e 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.h +++ b/drivers/net/wireless/ti/wlcore/debugfs.h @@ -53,19 +53,15 @@ static const struct file_operations name## _ops = { \ #define DEBUGFS_ADD(name, parent) \ do { \ - entry = debugfs_create_file(#name, 0400, parent, \ - wl, &name## _ops); \ - if (!entry || IS_ERR(entry)) \ - goto err; \ + debugfs_create_file(#name, 0400, parent, \ + wl, &name## _ops); \ } while (0) #define DEBUGFS_ADD_PREFIX(prefix, name, parent) \ do { \ - entry = debugfs_create_file(#name, 0400, parent, \ + debugfs_create_file(#name, 0400, parent, \ wl, &prefix## _## name## _ops); \ - if (!entry || IS_ERR(entry)) \ - goto err; \ } while (0) #define DEBUGFS_FWSTATS_FILE(sub, name, fmt, struct_type) \ -- cgit v1.2.3 From 72efec9b67ae9a153d83cd75b4e04c85bffa4683 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:25 +0100 Subject: wl1251: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Kalle Valo Cc: Tony Lindgren Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Tony Lindgren Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wl1251/debugfs.c | 59 +++----------------------------- 1 file changed, 5 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wl1251/debugfs.c b/drivers/net/wireless/ti/wl1251/debugfs.c index 448da1f8c22f..c99b23aaa70e 100644 --- a/drivers/net/wireless/ti/wl1251/debugfs.c +++ b/drivers/net/wireless/ti/wl1251/debugfs.c @@ -54,11 +54,6 @@ static const struct file_operations name## _ops = { \ #define DEBUGFS_ADD(name, parent) \ wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \ wl, &name## _ops); \ - if (IS_ERR(wl->debugfs.name)) { \ - ret = PTR_ERR(wl->debugfs.name); \ - wl->debugfs.name = NULL; \ - goto out; \ - } #define DEBUGFS_DEL(name) \ do { \ @@ -354,10 +349,8 @@ static void wl1251_debugfs_delete_files(struct wl1251 *wl) DEBUGFS_DEL(excessive_retries); } -static int wl1251_debugfs_add_files(struct wl1251 *wl) +static void wl1251_debugfs_add_files(struct wl1251 *wl) { - int ret = 0; - DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); DEBUGFS_FWSTATS_ADD(rx, out_of_mem); @@ -453,12 +446,6 @@ static int wl1251_debugfs_add_files(struct wl1251 *wl) DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir); DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); - -out: - if (ret < 0) - wl1251_debugfs_delete_files(wl); - - return ret; } void wl1251_debugfs_reset(struct wl1251 *wl) @@ -471,56 +458,20 @@ void wl1251_debugfs_reset(struct wl1251 *wl) int wl1251_debugfs_init(struct wl1251 *wl) { - int ret; + wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), GFP_KERNEL); + if (!wl->stats.fw_stats) + return -ENOMEM; wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR(wl->debugfs.rootdir)) { - ret = PTR_ERR(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - goto err; - } - wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics", wl->debugfs.rootdir); - if (IS_ERR(wl->debugfs.fw_statistics)) { - ret = PTR_ERR(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - goto err_root; - } - - wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), - GFP_KERNEL); - - if (!wl->stats.fw_stats) { - ret = -ENOMEM; - goto err_fw; - } - wl->stats.fw_stats_update = jiffies; - ret = wl1251_debugfs_add_files(wl); - - if (ret < 0) - goto err_file; + wl1251_debugfs_add_files(wl); return 0; - -err_file: - kfree(wl->stats.fw_stats); - wl->stats.fw_stats = NULL; - -err_fw: - debugfs_remove(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - -err_root: - debugfs_remove(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - -err: - return ret; } void wl1251_debugfs_exit(struct wl1251 *wl) -- cgit v1.2.3 From 23f389660301d117340228f1077374b1d6ad8ed2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:26 +0100 Subject: wl12xx: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Kalle Valo Cc: Tony Lindgren Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Tony Lindgren Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wl12xx/debugfs.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wl12xx/debugfs.c b/drivers/net/wireless/ti/wl12xx/debugfs.c index 0521cbf858cf..6c3c04eca8fd 100644 --- a/drivers/net/wireless/ti/wl12xx/debugfs.c +++ b/drivers/net/wireless/ti/wl12xx/debugfs.c @@ -125,20 +125,10 @@ WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, "%u"); int wl12xx_debugfs_add_files(struct wl1271 *wl, struct dentry *rootdir) { - int ret = 0; - struct dentry *entry, *stats, *moddir; + struct dentry *stats, *moddir; moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir); - if (!moddir || IS_ERR(moddir)) { - entry = moddir; - goto err; - } - stats = debugfs_create_dir("fw_stats", moddir); - if (!stats || IS_ERR(stats)) { - entry = stats; - goto err; - } DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); @@ -232,12 +222,4 @@ int wl12xx_debugfs_add_files(struct wl1271 *wl, DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); return 0; - -err: - if (IS_ERR(entry)) - ret = PTR_ERR(entry); - else - ret = -ENOMEM; - - return ret; } -- cgit v1.2.3 From c922a3a02d2b41c0d1adc6853eface758f397472 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:27 +0100 Subject: wl18xx: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Kalle Valo Cc: Tony Lindgren Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Tony Lindgren Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wl18xx/debugfs.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c index 597e934c4630..5f4ec997ca59 100644 --- a/drivers/net/wireless/ti/wl18xx/debugfs.c +++ b/drivers/net/wireless/ti/wl18xx/debugfs.c @@ -422,20 +422,10 @@ static const struct file_operations radar_debug_mode_ops = { int wl18xx_debugfs_add_files(struct wl1271 *wl, struct dentry *rootdir) { - int ret = 0; - struct dentry *entry, *stats, *moddir; + struct dentry *stats, *moddir; moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir); - if (!moddir || IS_ERR(moddir)) { - entry = moddir; - goto err; - } - stats = debugfs_create_dir("fw_stats", moddir); - if (!stats || IS_ERR(stats)) { - entry = stats; - goto err; - } DEBUGFS_ADD(clear_fw_stats, stats); @@ -590,12 +580,4 @@ int wl18xx_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(dynamic_fw_traces, moddir); return 0; - -err: - if (IS_ERR(entry)) - ret = PTR_ERR(entry); - else - ret = -ENOMEM; - - return ret; } -- cgit v1.2.3 From 3059785bb76e8df7d6585f9b9e2869bd1bd489f6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:33 +0100 Subject: rtlwifi: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Ping-Ke Shih Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/debug.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c index d70385be9976..8186650efc56 100644 --- a/drivers/net/wireless/realtek/rtlwifi/debug.c +++ b/drivers/net/wireless/realtek/rtlwifi/debug.c @@ -463,12 +463,9 @@ static const struct file_operations file_ops_common_write = { #define RTL_DEBUGFS_ADD_CORE(name, mode, fopname) \ do { \ rtl_debug_priv_ ##name.rtlpriv = rtlpriv; \ - if (!debugfs_create_file(#name, mode, \ - parent, &rtl_debug_priv_ ##name, \ - &file_ops_ ##fopname)) \ - pr_err("Unable to initialize debugfs:%s/%s\n", \ - rtlpriv->dbg.debugfs_name, \ - #name); \ + debugfs_create_file(#name, mode, parent, \ + &rtl_debug_priv_ ##name, \ + &file_ops_ ##fopname); \ } while (0) #define RTL_DEBUGFS_ADD(name) \ @@ -486,11 +483,6 @@ void rtl_debug_add_one(struct ieee80211_hw *hw) rtlpriv->dbg.debugfs_dir = debugfs_create_dir(rtlpriv->dbg.debugfs_name, debugfs_topdir); - if (!rtlpriv->dbg.debugfs_dir) { - pr_err("Unable to init debugfs:/%s/%s\n", rtlpriv->cfg->name, - rtlpriv->dbg.debugfs_name); - return; - } parent = rtlpriv->dbg.debugfs_dir; -- cgit v1.2.3 From b089e6944af34be0e3a0345903e82b4bdc01c4af Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:35 +0100 Subject: qtnfmac: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Igor Mitsyanko Cc: Avinash Patil Cc: Sergey Matyukevich Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Reviewed-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/debug.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/debug.c b/drivers/net/wireless/quantenna/qtnfmac/debug.c index ad70cdb80060..598ece753a4b 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/debug.c +++ b/drivers/net/wireless/quantenna/qtnfmac/debug.c @@ -3,17 +3,9 @@ #include "debug.h" -#undef pr_fmt -#define pr_fmt(fmt) "qtnfmac dbg: %s: " fmt, __func__ - void qtnf_debugfs_init(struct qtnf_bus *bus, const char *name) { bus->dbg_dir = debugfs_create_dir(name, NULL); - - if (IS_ERR_OR_NULL(bus->dbg_dir)) { - pr_warn("failed to create debugfs root dir\n"); - bus->dbg_dir = NULL; - } } void qtnf_debugfs_remove(struct qtnf_bus *bus) @@ -25,9 +17,5 @@ void qtnf_debugfs_remove(struct qtnf_bus *bus) void qtnf_debugfs_add_entry(struct qtnf_bus *bus, const char *name, int (*fn)(struct seq_file *seq, void *data)) { - struct dentry *entry; - - entry = debugfs_create_devm_seqfile(bus->dev, name, bus->dbg_dir, fn); - if (IS_ERR_OR_NULL(entry)) - pr_warn("failed to add entry (%s)\n", name); + debugfs_create_devm_seqfile(bus->dev, name, bus->dbg_dir, fn); } -- cgit v1.2.3 From 80f4c5e3662adad45d63dbf9bd9d524304c3eb1c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:28 +0100 Subject: cw1200: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Solomon Peachy Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kalle Valo --- drivers/net/wireless/st/cw1200/debug.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/st/cw1200/debug.c b/drivers/net/wireless/st/cw1200/debug.c index 2231ba08bc1f..d94266d9d0b8 100644 --- a/drivers/net/wireless/st/cw1200/debug.c +++ b/drivers/net/wireless/st/cw1200/debug.c @@ -371,28 +371,14 @@ int cw1200_debug_init(struct cw1200_common *priv) d->debugfs_phy = debugfs_create_dir("cw1200", priv->hw->wiphy->debugfsdir); - if (!d->debugfs_phy) - goto err; - - if (!debugfs_create_file("status", 0400, d->debugfs_phy, - priv, &cw1200_status_fops)) - goto err; - - if (!debugfs_create_file("counters", 0400, d->debugfs_phy, - priv, &cw1200_counters_fops)) - goto err; - - if (!debugfs_create_file("wsm_dumps", 0200, d->debugfs_phy, - priv, &fops_wsm_dumps)) - goto err; + debugfs_create_file("status", 0400, d->debugfs_phy, priv, + &cw1200_status_fops); + debugfs_create_file("counters", 0400, d->debugfs_phy, priv, + &cw1200_counters_fops); + debugfs_create_file("wsm_dumps", 0200, d->debugfs_phy, priv, + &fops_wsm_dumps); return 0; - -err: - priv->debug = NULL; - debugfs_remove_recursive(d->debugfs_phy); - kfree(d); - return ret; } void cw1200_debug_release(struct cw1200_common *priv) -- cgit v1.2.3 From e9bdcdc7cdf02819ea3f4205c7286ab97a9e1a1b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:29 +0100 Subject: b43: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Cc: b43-dev@lists.infradead.org Signed-off-by: Greg Kroah-Hartman Acked-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/b43/debugfs.c | 36 +++++++---------------------- 1 file changed, 8 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/b43/debugfs.c b/drivers/net/wireless/broadcom/b43/debugfs.c index 77046384dd80..976c8ec4e992 100644 --- a/drivers/net/wireless/broadcom/b43/debugfs.c +++ b/drivers/net/wireless/broadcom/b43/debugfs.c @@ -668,15 +668,13 @@ static void b43_remove_dynamic_debug(struct b43_wldev *dev) static void b43_add_dynamic_debug(struct b43_wldev *dev) { struct b43_dfsentry *e = dev->dfsentry; - struct dentry *d; -#define add_dyn_dbg(name, id, initstate) do { \ - e->dyn_debug[id] = (initstate); \ - d = debugfs_create_bool(name, 0600, e->subdir, \ - &(e->dyn_debug[id])); \ - if (!IS_ERR(d)) \ - e->dyn_debug_dentries[id] = d; \ - } while (0) +#define add_dyn_dbg(name, id, initstate) do { \ + e->dyn_debug[id] = (initstate); \ + e->dyn_debug_dentries[id] = \ + debugfs_create_bool(name, 0600, e->subdir, \ + &(e->dyn_debug[id])); \ + } while (0) add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, false); add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, false); @@ -718,19 +716,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev) snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy)); e->subdir = debugfs_create_dir(devdir, rootdir); - if (!e->subdir || IS_ERR(e->subdir)) { - if (e->subdir == ERR_PTR(-ENODEV)) { - b43dbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not " - "enabled in kernel config\n"); - } else { - b43err(dev->wl, "debugfs: cannot create %s directory\n", - devdir); - } - dev->dfsentry = NULL; - kfree(log->log); - kfree(e); - return; - } e->mmio16read_next = 0xFFFF; /* invalid address */ e->mmio32read_next = 0xFFFF; /* invalid address */ @@ -741,13 +726,10 @@ void b43_debugfs_add_device(struct b43_wldev *dev) #define ADD_FILE(name, mode) \ do { \ - struct dentry *d; \ - d = debugfs_create_file(__stringify(name), \ + e->file_##name.dentry = \ + debugfs_create_file(__stringify(name), \ mode, e->subdir, dev, \ &fops_##name.fops); \ - e->file_##name.dentry = NULL; \ - if (!IS_ERR(d)) \ - e->file_##name.dentry = d; \ } while (0) @@ -818,8 +800,6 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev, void b43_debugfs_init(void) { rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR(rootdir)) - rootdir = NULL; } void b43_debugfs_exit(void) -- cgit v1.2.3 From 32b4ebfe7f12c2481a2aea8372683142d1341a4e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:30 +0100 Subject: b43legacy: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Larry Finger Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Cc: b43-dev@lists.infradead.org Signed-off-by: Greg Kroah-Hartman Acked-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/b43legacy/debugfs.c | 35 ++++++----------------- 1 file changed, 8 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.c b/drivers/net/wireless/broadcom/b43legacy/debugfs.c index 82ef56ed7ca1..8150adee3e34 100644 --- a/drivers/net/wireless/broadcom/b43legacy/debugfs.c +++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c @@ -361,15 +361,13 @@ static void b43legacy_remove_dynamic_debug(struct b43legacy_wldev *dev) static void b43legacy_add_dynamic_debug(struct b43legacy_wldev *dev) { struct b43legacy_dfsentry *e = dev->dfsentry; - struct dentry *d; -#define add_dyn_dbg(name, id, initstate) do { \ - e->dyn_debug[id] = (initstate); \ - d = debugfs_create_bool(name, 0600, e->subdir, \ - &(e->dyn_debug[id])); \ - if (!IS_ERR(d)) \ - e->dyn_debug_dentries[id] = d; \ - } while (0) +#define add_dyn_dbg(name, id, initstate) do { \ + e->dyn_debug[id] = (initstate); \ + e->dyn_debug_dentries[id] = \ + debugfs_create_bool(name, 0600, e->subdir, \ + &(e->dyn_debug[id])); \ + } while (0) add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, false); add_dyn_dbg("debug_dmaoverflow", B43legacy_DBG_DMAOVERFLOW, false); @@ -408,29 +406,14 @@ void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev) snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy)); e->subdir = debugfs_create_dir(devdir, rootdir); - if (!e->subdir || IS_ERR(e->subdir)) { - if (e->subdir == ERR_PTR(-ENODEV)) { - b43legacydbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not " - "enabled in kernel config\n"); - } else { - b43legacyerr(dev->wl, "debugfs: cannot create %s directory\n", - devdir); - } - dev->dfsentry = NULL; - kfree(log->log); - kfree(e); - return; - } #define ADD_FILE(name, mode) \ do { \ - struct dentry *d; \ - d = debugfs_create_file(__stringify(name), \ + e->file_##name.dentry = \ + debugfs_create_file(__stringify(name), \ mode, e->subdir, dev, \ &fops_##name.fops); \ e->file_##name.dentry = NULL; \ - if (!IS_ERR(d)) \ - e->file_##name.dentry = d; \ } while (0) @@ -492,8 +475,6 @@ void b43legacy_debugfs_log_txstat(struct b43legacy_wldev *dev, void b43legacy_debugfs_init(void) { rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR(rootdir)) - rootdir = NULL; } void b43legacy_debugfs_exit(void) -- cgit v1.2.3 From 9ae49980bdca37052ffadc10d6b63d6f98cdaae0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:31 +0100 Subject: brcmsmac: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Arend van Spriel Cc: Franky Lin Cc: Hante Meuleman Cc: Chi-Hsien Lin Cc: Wright Feng Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Cc: brcm80211-dev-list.pdl@broadcom.com Cc: brcm80211-dev-list@cypress.com Signed-off-by: Greg Kroah-Hartman Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmsmac/debug.c | 26 ++++------------------ .../wireless/broadcom/brcm80211/brcmsmac/debug.h | 2 +- 2 files changed, 5 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c index 3bd54f125776..6d776ef6ff54 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c @@ -37,27 +37,18 @@ static struct dentry *root_folder; void brcms_debugfs_init(void) { root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR(root_folder)) - root_folder = NULL; } void brcms_debugfs_exit(void) { - if (!root_folder) - return; - debugfs_remove_recursive(root_folder); root_folder = NULL; } -int brcms_debugfs_attach(struct brcms_pub *drvr) +void brcms_debugfs_attach(struct brcms_pub *drvr) { - if (!root_folder) - return -ENODEV; - drvr->dbgfs_dir = debugfs_create_dir( dev_name(&drvr->wlc->hw->d11core->dev), root_folder); - return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); } void brcms_debugfs_detach(struct brcms_pub *drvr) @@ -195,7 +186,7 @@ static const struct file_operations brcms_debugfs_def_ops = { .llseek = seq_lseek }; -static int +static void brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn, int (*read_fn)(struct seq_file *seq, void *data)) { @@ -203,27 +194,18 @@ brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn, struct dentry *dentry = drvr->dbgfs_dir; struct brcms_debugfs_entry *entry; - if (IS_ERR_OR_NULL(dentry)) - return -ENOENT; - entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); if (!entry) - return -ENOMEM; + return; entry->read = read_fn; entry->drvr = drvr; - dentry = debugfs_create_file(fn, 0444, dentry, entry, - &brcms_debugfs_def_ops); - - return PTR_ERR_OR_ZERO(dentry); + debugfs_create_file(fn, 0444, dentry, entry, &brcms_debugfs_def_ops); } void brcms_debugfs_create_files(struct brcms_pub *drvr) { - if (IS_ERR_OR_NULL(drvr->dbgfs_dir)) - return; - brcms_debugfs_add_entry(drvr, "hardware", brcms_debugfs_hardware_read); brcms_debugfs_add_entry(drvr, "macstat", brcms_debugfs_macstat_read); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h index 822781cf15d4..56898e6d789d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h @@ -68,7 +68,7 @@ void __brcms_dbg(struct device *dev, u32 level, const char *func, struct brcms_pub; void brcms_debugfs_init(void); void brcms_debugfs_exit(void); -int brcms_debugfs_attach(struct brcms_pub *drvr); +void brcms_debugfs_attach(struct brcms_pub *drvr); void brcms_debugfs_detach(struct brcms_pub *drvr); struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr); void brcms_debugfs_create_files(struct brcms_pub *drvr); -- cgit v1.2.3 From b8f1fe51898373d34f4f59f54376a952a16c5dc4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:32 +0100 Subject: rsi: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_debugfs.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_debugfs.c b/drivers/net/wireless/rsi/rsi_91x_debugfs.c index 8c6ca8e689e4..d0c35f3e2012 100644 --- a/drivers/net/wireless/rsi/rsi_91x_debugfs.c +++ b/drivers/net/wireless/rsi/rsi_91x_debugfs.c @@ -297,11 +297,6 @@ int rsi_init_dbgfs(struct rsi_hw *adapter) dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL); - if (!dev_dbgfs->subdir) { - kfree(dev_dbgfs); - return -ENOMEM; - } - for (ii = 0; ii < adapter->num_debugfs_entries; ii++) { files = &dev_debugfs_files[ii]; dev_dbgfs->rsi_files[ii] = -- cgit v1.2.3 From 2587791d57588562c21e5ef7e678f02ab2f3eb82 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:34 +0100 Subject: rt2x00: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Stanislaw Gruszka Cc: Helmut Schaa Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2x00debug.c | 27 ------------------------ 1 file changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c index 61ba573e8bf1..05a2e8da412c 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c @@ -656,36 +656,24 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) intf->driver_folder = debugfs_create_dir(intf->rt2x00dev->ops->name, rt2x00dev->hw->wiphy->debugfsdir); - if (IS_ERR(intf->driver_folder) || !intf->driver_folder) - goto exit; intf->driver_entry = rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob); - if (IS_ERR(intf->driver_entry) || !intf->driver_entry) - goto exit; intf->chipset_entry = rt2x00debug_create_file_chipset("chipset", intf, &intf->chipset_blob); - if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry) - goto exit; intf->dev_flags = debugfs_create_file("dev_flags", 0400, intf->driver_folder, intf, &rt2x00debug_fop_dev_flags); - if (IS_ERR(intf->dev_flags) || !intf->dev_flags) - goto exit; intf->cap_flags = debugfs_create_file("cap_flags", 0400, intf->driver_folder, intf, &rt2x00debug_fop_cap_flags); - if (IS_ERR(intf->cap_flags) || !intf->cap_flags) - goto exit; intf->register_folder = debugfs_create_dir("register", intf->driver_folder); - if (IS_ERR(intf->register_folder) || !intf->register_folder) - goto exit; #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \ ({ \ @@ -695,9 +683,6 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) 0600, \ (__intf)->register_folder, \ &(__intf)->offset_##__name); \ - if (IS_ERR((__intf)->__name##_off_entry) || \ - !(__intf)->__name##_off_entry) \ - goto exit; \ \ (__intf)->__name##_val_entry = \ debugfs_create_file(__stringify(__name) "_value", \ @@ -705,9 +690,6 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) (__intf)->register_folder, \ (__intf), \ &rt2x00debug_fop_##__name); \ - if (IS_ERR((__intf)->__name##_val_entry) || \ - !(__intf)->__name##_val_entry) \ - goto exit; \ } \ }) @@ -721,15 +703,10 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) intf->queue_folder = debugfs_create_dir("queue", intf->driver_folder); - if (IS_ERR(intf->queue_folder) || !intf->queue_folder) - goto exit; intf->queue_frame_dump_entry = debugfs_create_file("dump", 0400, intf->queue_folder, intf, &rt2x00debug_fop_queue_dump); - if (IS_ERR(intf->queue_frame_dump_entry) - || !intf->queue_frame_dump_entry) - goto exit; skb_queue_head_init(&intf->frame_dump_skbqueue); init_waitqueue_head(&intf->frame_dump_waitqueue); @@ -747,10 +724,6 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) #endif return; - -exit: - rt2x00debug_deregister(rt2x00dev); - rt2x00_err(rt2x00dev, "Failed to register debug handler\n"); } void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) -- cgit v1.2.3 From caac453a9be7f79a9ebf4d2efa08189fd68837e0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:36 +0100 Subject: libertas: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Kalle Valo Cc: libertas-dev@lists.infradead.org Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/debugfs.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas/debugfs.c b/drivers/net/wireless/marvell/libertas/debugfs.c index c83f44f9ddf1..fe14814af300 100644 --- a/drivers/net/wireless/marvell/libertas/debugfs.c +++ b/drivers/net/wireless/marvell/libertas/debugfs.c @@ -708,8 +708,6 @@ void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev) goto exit; priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir); - if (!priv->debugfs_dir) - goto exit; for (i=0; ievents_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir); - if (!priv->events_dir) - goto exit; for (i=0; iregs_dir = debugfs_create_dir("registers", priv->debugfs_dir); - if (!priv->regs_dir) - goto exit; for (i=0; i Date: Tue, 22 Jan 2019 16:21:37 +0100 Subject: mwifiex: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Amitkumar Karwar Cc: Nishant Sarmukadam Cc: Ganapathi Bhat Cc: Xinming Hu Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/debugfs.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index cbe4493b3266..8ab114cf3467 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -922,9 +922,8 @@ mwifiex_reset_write(struct file *file, } #define MWIFIEX_DFS_ADD_FILE(name) do { \ - if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \ - priv, &mwifiex_dfs_##name##_fops)) \ - return; \ + debugfs_create_file(#name, 0644, priv->dfs_dev_dir, priv, \ + &mwifiex_dfs_##name##_fops); \ } while (0); #define MWIFIEX_DFS_FILE_OPS(name) \ -- cgit v1.2.3 From b6958ad021c1f46675aa6d3602ce0d241a45785d Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 22 Jan 2019 16:39:34 +0100 Subject: mt7601u: do not use WARN_ON in the datapath Substitute WARN_ON with WARN_ON_ONCE in mt7601u_rx_next_seg_len routine Signed-off-by: Lorenzo Bianconi Acked-by: Jakub Kicinski Signed-off-by: Kalle Valo --- drivers/net/wireless/mediatek/mt7601u/dma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c index 7f3e3983b781..f7edeffb2b19 100644 --- a/drivers/net/wireless/mediatek/mt7601u/dma.c +++ b/drivers/net/wireless/mediatek/mt7601u/dma.c @@ -124,9 +124,9 @@ static u16 mt7601u_rx_next_seg_len(u8 *data, u32 data_len) u16 dma_len = get_unaligned_le16(data); if (data_len < min_seg_len || - WARN_ON(!dma_len) || - WARN_ON(dma_len + MT_DMA_HDRS > data_len) || - WARN_ON(dma_len & 0x3)) + WARN_ON_ONCE(!dma_len) || + WARN_ON_ONCE(dma_len + MT_DMA_HDRS > data_len) || + WARN_ON_ONCE(dma_len & 0x3)) return 0; return MT_DMA_HDRS + dma_len; -- cgit v1.2.3 From 030b43671ae88f827a415ad35700705ffc10d10d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 26 Jan 2019 00:18:00 +0900 Subject: wireless: prefix header search paths with $(srctree)/ Currently, the Kbuild core manipulates header search paths in a crazy way [1]. To fix this mess, I want all Makefiles to add explicit $(srctree)/ to the search paths in the srctree. Some Makefiles are already written in that way, but not all. The goal of this work is to make the notation consistent, and finally get rid of the gross hacks. Having whitespaces after -I does not matter since commit 48f6e3cf5bc6 ("kbuild: do not drop -I without parameter"). I also removed one header search path in: drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile I was able to compile without it. [1]: https://patchwork.kernel.org/patch/9632347/ Signed-off-by: Masahiro Yamada Acked-by: Luca Coelho Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile | 4 ++-- drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile | 6 +++--- drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile | 4 +--- drivers/net/wireless/intel/iwlwifi/dvm/Makefile | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/Makefile | 2 +- drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile | 2 +- drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile | 2 +- 7 files changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile index 22fd95a736a8..f7cf3e5f4849 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile @@ -16,8 +16,8 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ccflags-y += \ - -Idrivers/net/wireless/broadcom/brcm80211/brcmfmac \ - -Idrivers/net/wireless/broadcom/brcm80211/include + -I $(srctree)/$(src) \ + -I $(srctree)/$(src)/../include obj-$(CONFIG_BRCMFMAC) += brcmfmac.o brcmfmac-objs += \ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile index ed83f33aceb7..482d7737764d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile @@ -16,9 +16,9 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ccflags-y := \ - -Idrivers/net/wireless/broadcom/brcm80211/brcmsmac \ - -Idrivers/net/wireless/broadcom/brcm80211/brcmsmac/phy \ - -Idrivers/net/wireless/broadcom/brcm80211/include + -I $(srctree)/$(src) \ + -I $(srctree)/$(src)/phy \ + -I $(srctree)/$(src)/../include brcmsmac-y := \ mac80211_if.o \ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile index 256c91f9ac4b..bb02c6220a88 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile +++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile @@ -15,9 +15,7 @@ # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -ccflags-y := \ - -Idrivers/net/wireless/broadcom/brcm80211/brcmutil \ - -Idrivers/net/wireless/broadcom/brcm80211/include +ccflags-y := -I $(srctree)/$(src)/../include obj-$(CONFIG_BRCMUTIL) += brcmutil.o brcmutil-objs = utils.o d11.o diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/Makefile b/drivers/net/wireless/intel/iwlwifi/dvm/Makefile index 702d42b2d452..0486b17d7c41 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/dvm/Makefile @@ -11,4 +11,4 @@ iwldvm-objs += rxon.o devices.o iwldvm-$(CONFIG_IWLWIFI_LEDS) += led.o iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o -ccflags-y += -I$(src)/../ +ccflags-y += -I $(srctree)/$(src)/../ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile index 87373b099fd9..30cbd981efbd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile @@ -9,4 +9,4 @@ iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o iwlmvm-$(CONFIG_PM) += d3.o -ccflags-y += -I$(src)/../ +ccflags-y += -I $(srctree)/$(src)/../ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile index 2966681efaef..5d6b06d3c02c 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile @@ -2,4 +2,4 @@ rtl818x_pci-objs := dev.o rtl8225.o sa2400.o max2820.o grf5101.o rtl8225se.o obj-$(CONFIG_RTL8180) += rtl818x_pci.o -ccflags-y += -Idrivers/net/wireless/realtek/rtl818x +ccflags-y += -I $(srctree)/$(src)/.. diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile index ff074912a095..95bac73ece7c 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile @@ -2,4 +2,4 @@ rtl8187-objs := dev.o rtl8225.o leds.o rfkill.o obj-$(CONFIG_RTL8187) += rtl8187.o -ccflags-y += -Idrivers/net/wireless/realtek/rtl818x +ccflags-y += -I $(srctree)/$(src)/.. -- cgit v1.2.3 From 39ee6e8204b9d4bd46d57ad838fa852f5d293f99 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 1 Feb 2019 11:32:26 +0300 Subject: net: hns3: Check for allocation failure We should return -ENOMEM if the kcalloc() fails. Fixes: d174ea75c96a ("net: hns3: add statistics for PFC frames and MAC control frame") Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 2ffbf07ff829..52fc57284be8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -351,6 +351,8 @@ static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num) int ret; desc = kcalloc(desc_num, sizeof(struct hclge_desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_STATS_MAC_ALL, true); ret = hclge_cmd_send(&hdev->hw, desc, desc_num); if (ret) { -- cgit v1.2.3 From 3ebb18a48cbf03448087f9eef08cbade84fc0118 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 30 Jan 2019 18:23:14 -0600 Subject: cxgb4: sched: use struct_size() in kvzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = kvzalloc(sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kvzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/sched.c b/drivers/net/ethernet/chelsio/cxgb4/sched.c index 52edb688942b..ba6c153ee45c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sched.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sched.c @@ -478,7 +478,7 @@ struct sched_table *t4_init_sched(unsigned int sched_size) struct sched_table *s; unsigned int i; - s = kvzalloc(sizeof(*s) + sched_size * sizeof(struct sched_class), GFP_KERNEL); + s = kvzalloc(struct_size(s, tab, sched_size), GFP_KERNEL); if (!s) return NULL; -- cgit v1.2.3 From c49f0ce0b692e8018c32f529a718bb41bc934ab3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 30 Jan 2019 18:27:44 -0600 Subject: cxgb4: smt: use struct_size() in kvzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = kvzalloc(sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kvzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/smt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/smt.c b/drivers/net/ethernet/chelsio/cxgb4/smt.c index 7b2207a2a130..eaf1fb74689c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/smt.c +++ b/drivers/net/ethernet/chelsio/cxgb4/smt.c @@ -47,8 +47,7 @@ struct smt_data *t4_init_smt(void) smt_size = SMT_SIZE; - s = kvzalloc(sizeof(*s) + smt_size * sizeof(struct smt_entry), - GFP_KERNEL); + s = kvzalloc(struct_size(s, smtab, smt_size), GFP_KERNEL); if (!s) return NULL; s->smt_size = smt_size; -- cgit v1.2.3 From 6541d025906bd0b0bcb56a93eef288b8179ea8a1 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 30 Jan 2019 18:33:55 -0600 Subject: tulip: eeprom: use struct_size() in kmalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = kmalloc(sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kmalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/dec/tulip/eeprom.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c index 1812f4916917..ba0a69b363f8 100644 --- a/drivers/net/ethernet/dec/tulip/eeprom.c +++ b/drivers/net/ethernet/dec/tulip/eeprom.c @@ -224,9 +224,7 @@ subsequent_board: return; } - mtable = kmalloc(sizeof(struct mediatable) + - count * sizeof(struct medialeaf), - GFP_KERNEL); + mtable = kmalloc(struct_size(mtable, mleaf, count), GFP_KERNEL); if (mtable == NULL) return; /* Horrible, impossible failure. */ last_mediatable = tp->mtable = mtable; -- cgit v1.2.3 From ee69804714e204787ec8d06e80ec21e089f030a9 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 30 Jan 2019 18:38:59 -0600 Subject: nfp: use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = kzalloc(sizeof(struct foo) + count * sizeof(struct boo), GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c index 802c9224bb32..f6f028fa5db9 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c @@ -269,8 +269,7 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp) goto err; } - table = kzalloc(sizeof(*table) + - sizeof(struct nfp_eth_table_port) * cnt, GFP_KERNEL); + table = kzalloc(struct_size(table, ports, cnt), GFP_KERNEL); if (!table) goto err; -- cgit v1.2.3 From 4adba00839d6819cc678920095996c56b26fe96d Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 31 Jan 2019 10:50:43 -0800 Subject: nfp: devlink: report driver name and serial number Report the basic info through new devlink info API. RFCv2: - add driver name; - align serial to core changes. Signed-off-by: Jakub Kicinski Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index 808647ec3573..2ba3b3891d99 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -4,6 +4,7 @@ #include #include +#include "nfpcore/nfp.h" #include "nfpcore/nfp_nsp.h" #include "nfp_app.h" #include "nfp_main.h" @@ -171,6 +172,28 @@ static int nfp_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, return ret; } +static int +nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + struct nfp_pf *pf = devlink_priv(devlink); + const char *sn; + int err; + + err = devlink_info_driver_name_put(req, "nfp"); + if (err) + return err; + + sn = nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"); + if (sn) { + err = devlink_info_serial_number_put(req, sn); + if (err) + return err; + } + + return 0; +} + const struct devlink_ops nfp_devlink_ops = { .port_split = nfp_devlink_port_split, .port_unsplit = nfp_devlink_port_unsplit, @@ -178,6 +201,7 @@ const struct devlink_ops nfp_devlink_ops = { .sb_pool_set = nfp_devlink_sb_pool_set, .eswitch_mode_get = nfp_devlink_eswitch_mode_get, .eswitch_mode_set = nfp_devlink_eswitch_mode_set, + .info_get = nfp_devlink_info_get, }; int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) -- cgit v1.2.3 From 937a3e2645b212fdf5ce05d490d063893f5757a4 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 31 Jan 2019 10:50:44 -0800 Subject: nfp: devlink: report fixed versions Report information about the hardware. RFCv2: - add defines for board IDs which are likely to be reusable for other drivers (Jiri). Signed-off-by: Jakub Kicinski Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 36 +++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index 2ba3b3891d99..75eda34fc1b4 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -172,6 +172,40 @@ static int nfp_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, return ret; } +static const struct nfp_devlink_versions_simple { + const char *key; + const char *hwinfo; +} nfp_devlink_versions_hwinfo[] = { + { DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, "assembly.partno", }, + { DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, "assembly.revision", }, + { "board.vendor", /* fab */ "assembly.vendor", }, + { "board.model", /* code name */ "assembly.model", }, +}; + +static int +nfp_devlink_versions_get_hwinfo(struct nfp_pf *pf, struct devlink_info_req *req) +{ + unsigned int i; + int err; + + for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_hwinfo); i++) { + const struct nfp_devlink_versions_simple *info; + const char *val; + + info = &nfp_devlink_versions_hwinfo[i]; + + val = nfp_hwinfo_lookup(pf->hwinfo, info->hwinfo); + if (!val) + continue; + + err = devlink_info_version_fixed_put(req, info->key, val); + if (err) + return err; + } + + return 0; +} + static int nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, struct netlink_ext_ack *extack) @@ -191,7 +225,7 @@ nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, return err; } - return 0; + return nfp_devlink_versions_get_hwinfo(pf, req); } const struct devlink_ops nfp_devlink_ops = { -- cgit v1.2.3 From b96588400a0e46a4830a6a9420946413ae13cccc Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 31 Jan 2019 10:50:45 -0800 Subject: nfp: nsp: add support for versions command Retrieve the FW versions with the new command. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c | 61 ++++++++++++++++++++++ .../net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h | 20 +++++++ 2 files changed, 81 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c index ce1577bbbd2a..a9d53df0070c 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c @@ -7,6 +7,7 @@ * Jason McMullan */ +#include #include #include #include @@ -62,6 +63,16 @@ #define NFP_HWINFO_LOOKUP_SIZE GENMASK(11, 0) +#define NFP_VERSIONS_SIZE GENMASK(11, 0) +#define NFP_VERSIONS_CNT_OFF 0 +#define NFP_VERSIONS_BSP_OFF 2 +#define NFP_VERSIONS_CPLD_OFF 6 +#define NFP_VERSIONS_APP_OFF 10 +#define NFP_VERSIONS_BUNDLE_OFF 14 +#define NFP_VERSIONS_UNDI_OFF 18 +#define NFP_VERSIONS_NCSI_OFF 22 +#define NFP_VERSIONS_CFGR_OFF 26 + enum nfp_nsp_cmd { SPCODE_NOOP = 0, /* No operation */ SPCODE_SOFT_RESET = 1, /* Soft reset the NFP */ @@ -77,6 +88,7 @@ enum nfp_nsp_cmd { SPCODE_NSP_IDENTIFY = 13, /* Read NSP version */ SPCODE_FW_STORED = 16, /* If no FW loaded, load flash app FW */ SPCODE_HWINFO_LOOKUP = 17, /* Lookup HWinfo with overwrites etc. */ + SPCODE_VERSIONS = 21, /* Report FW versions */ }; static const struct { @@ -711,3 +723,52 @@ int nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size) return 0; } + +int nfp_nsp_versions(struct nfp_nsp *state, void *buf, unsigned int size) +{ + struct nfp_nsp_command_buf_arg versions = { + { + .code = SPCODE_VERSIONS, + .option = min_t(u32, size, NFP_VERSIONS_SIZE), + }, + .out_buf = buf, + .out_size = min_t(u32, size, NFP_VERSIONS_SIZE), + }; + + return nfp_nsp_command_buf(state, &versions); +} + +const char *nfp_nsp_versions_get(enum nfp_nsp_versions id, bool flash, + const u8 *buf, unsigned int size) +{ + static const u32 id2off[] = { + [NFP_VERSIONS_BSP] = NFP_VERSIONS_BSP_OFF, + [NFP_VERSIONS_CPLD] = NFP_VERSIONS_CPLD_OFF, + [NFP_VERSIONS_APP] = NFP_VERSIONS_APP_OFF, + [NFP_VERSIONS_BUNDLE] = NFP_VERSIONS_BUNDLE_OFF, + [NFP_VERSIONS_UNDI] = NFP_VERSIONS_UNDI_OFF, + [NFP_VERSIONS_NCSI] = NFP_VERSIONS_NCSI_OFF, + [NFP_VERSIONS_CFGR] = NFP_VERSIONS_CFGR_OFF, + }; + unsigned int field, buf_field_cnt, buf_off; + + if (id >= ARRAY_SIZE(id2off) || !id2off[id]) + return ERR_PTR(-EINVAL); + + field = id * 2 + flash; + + buf_field_cnt = get_unaligned_le16(buf); + if (buf_field_cnt <= field) + return ERR_PTR(-ENOENT); + + buf_off = get_unaligned_le16(buf + id2off[id] + flash * 2); + if (!buf_off) + return ERR_PTR(-ENOENT); + + if (buf_off >= size) + return ERR_PTR(-EINVAL); + if (strnlen(&buf[buf_off], size - buf_off) == size - buf_off) + return ERR_PTR(-EINVAL); + + return (const char *)&buf[buf_off]; +} diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h index ff33ac54097a..246e213f1514 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h @@ -38,6 +38,11 @@ static inline bool nfp_nsp_has_hwinfo_lookup(struct nfp_nsp *state) return nfp_nsp_get_abi_ver_minor(state) > 24; } +static inline bool nfp_nsp_has_versions(struct nfp_nsp *state) +{ + return nfp_nsp_get_abi_ver_minor(state) > 27; +} + enum nfp_eth_interface { NFP_INTERFACE_NONE = 0, NFP_INTERFACE_SFP = 1, @@ -208,4 +213,19 @@ enum nfp_nsp_sensor_id { int nfp_hwmon_read_sensor(struct nfp_cpp *cpp, enum nfp_nsp_sensor_id id, long *val); +#define NFP_NSP_VERSION_BUFSZ 1024 /* reasonable size, not in the ABI */ + +enum nfp_nsp_versions { + NFP_VERSIONS_BSP, + NFP_VERSIONS_CPLD, + NFP_VERSIONS_APP, + NFP_VERSIONS_BUNDLE, + NFP_VERSIONS_UNDI, + NFP_VERSIONS_NCSI, + NFP_VERSIONS_CFGR, +}; + +int nfp_nsp_versions(struct nfp_nsp *state, void *buf, unsigned int size); +const char *nfp_nsp_versions_get(enum nfp_nsp_versions id, bool flash, + const u8 *buf, unsigned int size); #endif -- cgit v1.2.3 From 7c908f467d78b7924233e328b64677453744908c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 31 Jan 2019 10:50:46 -0800 Subject: nfp: devlink: report the running and flashed versions Report versions of firmware components using the new NSP command. Signed-off-by: Jakub Kicinski Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 87 ++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index 75eda34fc1b4..dddbb0575be9 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -206,11 +206,60 @@ nfp_devlink_versions_get_hwinfo(struct nfp_pf *pf, struct devlink_info_req *req) return 0; } +static const struct nfp_devlink_versions { + enum nfp_nsp_versions id; + const char *key; +} nfp_devlink_versions_nsp[] = { + { NFP_VERSIONS_BUNDLE, "fw.bundle_id", }, + { NFP_VERSIONS_BSP, DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, }, + { NFP_VERSIONS_CPLD, "fw.cpld", }, + { NFP_VERSIONS_APP, DEVLINK_INFO_VERSION_GENERIC_FW_APP, }, + { NFP_VERSIONS_UNDI, DEVLINK_INFO_VERSION_GENERIC_FW_UNDI, }, + { NFP_VERSIONS_NCSI, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, }, + { NFP_VERSIONS_CFGR, "chip.init", }, +}; + +static int +nfp_devlink_versions_get_nsp(struct devlink_info_req *req, bool flash, + const u8 *buf, unsigned int size) +{ + unsigned int i; + int err; + + for (i = 0; i < ARRAY_SIZE(nfp_devlink_versions_nsp); i++) { + const struct nfp_devlink_versions *info; + const char *version; + + info = &nfp_devlink_versions_nsp[i]; + + version = nfp_nsp_versions_get(info->id, flash, buf, size); + if (IS_ERR(version)) { + if (PTR_ERR(version) == -ENOENT) + continue; + else + return PTR_ERR(version); + } + + if (flash) + err = devlink_info_version_stored_put(req, info->key, + version); + else + err = devlink_info_version_running_put(req, info->key, + version); + if (err) + return err; + } + + return 0; +} + static int nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, struct netlink_ext_ack *extack) { struct nfp_pf *pf = devlink_priv(devlink); + struct nfp_nsp *nsp; + char *buf = NULL; const char *sn; int err; @@ -225,7 +274,45 @@ nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, return err; } + nsp = nfp_nsp_open(pf->cpp); + if (IS_ERR(nsp)) { + NL_SET_ERR_MSG_MOD(extack, "can't access NSP"); + return PTR_ERR(nsp); + } + + if (nfp_nsp_has_versions(nsp)) { + buf = kzalloc(NFP_NSP_VERSION_BUFSZ, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + goto err_close_nsp; + } + + err = nfp_nsp_versions(nsp, buf, NFP_NSP_VERSION_BUFSZ); + if (err) + goto err_free_buf; + + err = nfp_devlink_versions_get_nsp(req, false, + buf, NFP_NSP_VERSION_BUFSZ); + if (err) + goto err_free_buf; + + err = nfp_devlink_versions_get_nsp(req, true, + buf, NFP_NSP_VERSION_BUFSZ); + if (err) + goto err_free_buf; + + kfree(buf); + } + + nfp_nsp_close(nsp); + return nfp_devlink_versions_get_hwinfo(pf, req); + +err_free_buf: + kfree(buf); +err_close_nsp: + nfp_nsp_close(nsp); + return err; } const struct devlink_ops nfp_devlink_ops = { -- cgit v1.2.3 From db0a4b3b6b83a081a9ec309cc8178e5c9b4706a5 Mon Sep 17 00:00:00 2001 From: Jiong Wang Date: Fri, 1 Feb 2019 22:39:28 +0000 Subject: nfp: bpf: correct the behavior for shifts by zero Shifts by zero do nothing, and should be treated as nops. Even though compiler is not supposed to generate such instructions and manual written assembly is unlikely to have them, but they are legal instructions and have defined behavior. This patch correct existing shifts code-gen to make sure they do nothing when shift amount is zero except when the instruction is ALU32 for which high bits need to be cleared. For shift amount bigger than type size, already, NFP JIT back-end errors out for immediate shift and only low 5 bits will be taken into account for indirect shift which is the same as x86. Reviewed-by: Jakub Kicinski Signed-off-by: Jiong Wang Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/netronome/nfp/bpf/jit.c | 30 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index aa3a2098a583..093b8ff80241 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c @@ -1967,6 +1967,9 @@ static int neg_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) */ static int __shl_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) { + if (!shift_amt) + return 0; + if (shift_amt < 32) { emit_shf(nfp_prog, reg_both(dst + 1), reg_a(dst + 1), SHF_OP_NONE, reg_b(dst), SHF_SC_R_DSHF, @@ -2079,6 +2082,9 @@ static int shl_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) */ static int __shr_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) { + if (!shift_amt) + return 0; + if (shift_amt < 32) { emit_shf(nfp_prog, reg_both(dst), reg_a(dst + 1), SHF_OP_NONE, reg_b(dst), SHF_SC_R_DSHF, shift_amt); @@ -2180,6 +2186,9 @@ static int shr_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) */ static int __ashr_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) { + if (!shift_amt) + return 0; + if (shift_amt < 32) { emit_shf(nfp_prog, reg_both(dst), reg_a(dst + 1), SHF_OP_NONE, reg_b(dst), SHF_SC_R_DSHF, shift_amt); @@ -2388,10 +2397,13 @@ static int neg_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int __ashr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) { - /* Set signedness bit (MSB of result). */ - emit_alu(nfp_prog, reg_none(), reg_a(dst), ALU_OP_OR, reg_imm(0)); - emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR, reg_b(dst), - SHF_SC_R_SHF, shift_amt); + if (shift_amt) { + /* Set signedness bit (MSB of result). */ + emit_alu(nfp_prog, reg_none(), reg_a(dst), ALU_OP_OR, + reg_imm(0)); + emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR, + reg_b(dst), SHF_SC_R_SHF, shift_amt); + } wrp_immed(nfp_prog, reg_both(dst + 1), 0); return 0; @@ -2433,12 +2445,10 @@ static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { const struct bpf_insn *insn = &meta->insn; - if (!insn->imm) - return 1; /* TODO: zero shift means indirect */ - - emit_shf(nfp_prog, reg_both(insn->dst_reg * 2), - reg_none(), SHF_OP_NONE, reg_b(insn->dst_reg * 2), - SHF_SC_L_SHF, insn->imm); + if (insn->imm) + emit_shf(nfp_prog, reg_both(insn->dst_reg * 2), + reg_none(), SHF_OP_NONE, reg_b(insn->dst_reg * 2), + SHF_SC_L_SHF, insn->imm); wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0); return 0; -- cgit v1.2.3 From ac7a1717a2cbf74c84126998db4e9864ac1fa99b Mon Sep 17 00:00:00 2001 From: Jiong Wang Date: Fri, 1 Feb 2019 22:39:29 +0000 Subject: nfp: bpf: complete ALU32 logic shift supports The following ALU32 logic shift supports are missing: BPF_ALU | BPF_LSH | BPF_X BPF_ALU | BPF_RSH | BPF_X BPF_ALU | BPF_RSH | BPF_K For BPF_RSH | BPF_K, it could be implemented using NFP direct shift instruction. For the other BPF_X shifts, NFP indirect shifts sequences need to be used. Separate code-gen hook is assigned to each instruction to make the implementation clear. Reviewed-by: Jakub Kicinski Signed-off-by: Jiong Wang Signed-off-by: Alexei Starovoitov --- drivers/net/ethernet/netronome/nfp/bpf/jit.c | 72 ++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index 093b8ff80241..4d9d3806908e 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c @@ -2441,16 +2441,75 @@ static int ashr_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) return __ashr_imm(nfp_prog, dst, insn->imm); } +static int __shr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) +{ + if (shift_amt) + emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE, + reg_b(dst), SHF_SC_R_SHF, shift_amt); + wrp_immed(nfp_prog, reg_both(dst + 1), 0); + return 0; +} + +static int shr_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +{ + const struct bpf_insn *insn = &meta->insn; + u8 dst = insn->dst_reg * 2; + + return __shr_imm(nfp_prog, dst, insn->imm); +} + +static int shr_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +{ + const struct bpf_insn *insn = &meta->insn; + u64 umin, umax; + u8 dst, src; + + dst = insn->dst_reg * 2; + umin = meta->umin_src; + umax = meta->umax_src; + if (umin == umax) + return __shr_imm(nfp_prog, dst, umin); + + src = insn->src_reg * 2; + emit_alu(nfp_prog, reg_none(), reg_a(src), ALU_OP_OR, reg_imm(0)); + emit_shf_indir(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE, + reg_b(dst), SHF_SC_R_SHF); + wrp_immed(nfp_prog, reg_both(dst + 1), 0); + return 0; +} + +static int __shl_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) +{ + if (shift_amt) + emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE, + reg_b(dst), SHF_SC_L_SHF, shift_amt); + wrp_immed(nfp_prog, reg_both(dst + 1), 0); + return 0; +} + static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) { const struct bpf_insn *insn = &meta->insn; + u8 dst = insn->dst_reg * 2; - if (insn->imm) - emit_shf(nfp_prog, reg_both(insn->dst_reg * 2), - reg_none(), SHF_OP_NONE, reg_b(insn->dst_reg * 2), - SHF_SC_L_SHF, insn->imm); - wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0); + return __shl_imm(nfp_prog, dst, insn->imm); +} +static int shl_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) +{ + const struct bpf_insn *insn = &meta->insn; + u64 umin, umax; + u8 dst, src; + + dst = insn->dst_reg * 2; + umin = meta->umin_src; + umax = meta->umax_src; + if (umin == umax) + return __shl_imm(nfp_prog, dst, umin); + + src = insn->src_reg * 2; + shl_reg64_lt32_low(nfp_prog, dst, src); + wrp_immed(nfp_prog, reg_both(dst + 1), 0); return 0; } @@ -3360,7 +3419,10 @@ static const instr_cb_t instr_cb[256] = { [BPF_ALU | BPF_DIV | BPF_X] = div_reg, [BPF_ALU | BPF_DIV | BPF_K] = div_imm, [BPF_ALU | BPF_NEG] = neg_reg, + [BPF_ALU | BPF_LSH | BPF_X] = shl_reg, [BPF_ALU | BPF_LSH | BPF_K] = shl_imm, + [BPF_ALU | BPF_RSH | BPF_X] = shr_reg, + [BPF_ALU | BPF_RSH | BPF_K] = shr_imm, [BPF_ALU | BPF_ARSH | BPF_X] = ashr_reg, [BPF_ALU | BPF_ARSH | BPF_K] = ashr_imm, [BPF_ALU | BPF_END | BPF_X] = end_reg32, -- cgit v1.2.3 From 9e50dc11b856f19908559bafe1a3eca0ddc632b2 Mon Sep 17 00:00:00 2001 From: Peng Li Date: Sat, 2 Feb 2019 22:39:26 +0800 Subject: net: hns3: fix a code style issue for hns3_update_new_int_gl() Use the same code style for rx_group and tx_group in the hns3_update_new_int_gl(). Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index c546b874d659..1d3f167ee1e4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2880,7 +2880,7 @@ static void hns3_update_new_int_gl(struct hns3_enet_tqp_vector *tqp_vector) } if (tx_group->coal.gl_adapt_enable) { - tx_update = hns3_get_new_int_gl(&tqp_vector->tx_group); + tx_update = hns3_get_new_int_gl(tx_group); if (tx_update) hns3_set_vector_coalesce_tx_gl(tqp_vector, tx_group->coal.int_gl); -- cgit v1.2.3 From 6241e71e7207102ffc733991f7a00f74098d7da0 Mon Sep 17 00:00:00 2001 From: Peng Li Date: Sat, 2 Feb 2019 22:39:27 +0800 Subject: net: hns3: fix an issue for hns3_update_new_int_gl HNS3 supports setting rx-usecs|tx-usecs as 0, but it will not update dynamically when adaptive-tx or adaptive-rx is enable. This patch removes the Redundant check. Fixes: a95e1f8666e9 ("net: hns3: change the time interval of int_gl calculating") Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 1d3f167ee1e4..bc571b3d8ddc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2777,7 +2777,7 @@ static bool hns3_get_new_int_gl(struct hns3_enet_ring_group *ring_group) u32 time_passed_ms; u16 new_int_gl; - if (!ring_group->coal.int_gl || !tqp_vector->last_jiffies) + if (!tqp_vector->last_jiffies) return false; if (ring_group->total_packets == 0) { -- cgit v1.2.3 From 1731be4c73bb4d5bbfb4b15aaab3f183ccba6fe6 Mon Sep 17 00:00:00 2001 From: Yonglong Liu Date: Sat, 2 Feb 2019 22:39:28 +0800 Subject: net: hns3: Modify parameter type from int to bool in set_gro_en The second parameter to the hook function set_gro_en is always passed in true/false, so modify it's type from int to bool. Signed-off-by: Yonglong Liu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 26 ++++++++-------------- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 2 +- 4 files changed, 12 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index e05b4926feb2..10f1cc2ba157 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -461,7 +461,7 @@ struct hnae3_ae_ops { bool (*get_hw_reset_stat)(struct hnae3_handle *handle); bool (*ae_dev_resetting)(struct hnae3_handle *handle); unsigned long (*ae_dev_reset_cnt)(struct hnae3_handle *handle); - int (*set_gro_en)(struct hnae3_handle *handle, int enable); + int (*set_gro_en)(struct hnae3_handle *handle, bool enable); u16 (*get_global_queue_id)(struct hnae3_handle *handle, u16 queue_id); void (*set_timer_task)(struct hnae3_handle *handle, bool enable); int (*mac_connect_phy)(struct hnae3_handle *handle); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index bc571b3d8ddc..db06d36d408f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1349,6 +1349,7 @@ static int hns3_nic_set_features(struct net_device *netdev, netdev_features_t changed = netdev->features ^ features; struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = priv->ae_handle; + bool enable; int ret; if (changed & (NETIF_F_TSO | NETIF_F_TSO6)) { @@ -1359,38 +1360,29 @@ static int hns3_nic_set_features(struct net_device *netdev, } if (changed & (NETIF_F_GRO_HW) && h->ae_algo->ops->set_gro_en) { - if (features & NETIF_F_GRO_HW) - ret = h->ae_algo->ops->set_gro_en(h, true); - else - ret = h->ae_algo->ops->set_gro_en(h, false); + enable = !!(features & NETIF_F_GRO_HW); + ret = h->ae_algo->ops->set_gro_en(h, enable); if (ret) return ret; } if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) && h->ae_algo->ops->enable_vlan_filter) { - if (features & NETIF_F_HW_VLAN_CTAG_FILTER) - h->ae_algo->ops->enable_vlan_filter(h, true); - else - h->ae_algo->ops->enable_vlan_filter(h, false); + enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER); + h->ae_algo->ops->enable_vlan_filter(h, enable); } if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && h->ae_algo->ops->enable_hw_strip_rxvtag) { - if (features & NETIF_F_HW_VLAN_CTAG_RX) - ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, true); - else - ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, false); - + enable = !!(features & NETIF_F_HW_VLAN_CTAG_RX); + ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, enable); if (ret) return ret; } if ((changed & NETIF_F_NTUPLE) && h->ae_algo->ops->enable_fd) { - if (features & NETIF_F_NTUPLE) - h->ae_algo->ops->enable_fd(h, true); - else - h->ae_algo->ops->enable_fd(h, false); + enable = !!(features & NETIF_F_NTUPLE); + h->ae_algo->ops->enable_fd(h, enable); } netdev->features = features; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 52fc57284be8..9630bbce5932 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7989,7 +7989,7 @@ static void hclge_get_link_mode(struct hnae3_handle *handle, } } -static int hclge_gro_en(struct hnae3_handle *handle, int enable) +static int hclge_gro_en(struct hnae3_handle *handle, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index b9cdbd5dd6cb..bc2f29e67280 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2550,7 +2550,7 @@ void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed, hdev->hw.mac.duplex = duplex; } -static int hclgevf_gro_en(struct hnae3_handle *handle, int enable) +static int hclgevf_gro_en(struct hnae3_handle *handle, bool enable) { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); -- cgit v1.2.3 From 8ca754b13f3c3b99d946665385b3b76e66aab96d Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sat, 2 Feb 2019 22:39:29 +0800 Subject: net: hns3: code optimization for hclge_rx_buffer_calc There are four steps to calcuate the rx private buffer, each step can be done in a function to avoid code duplication and aid code readability. This patch adds three separate functions do the job. Also, the function name more or less make the comment redundant, so remove some obvious comment. Signed-off-by: Yunsheng Lin Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 140 ++++++++++----------- 1 file changed, 63 insertions(+), 77 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 9630bbce5932..be7d82502f5f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1520,66 +1520,15 @@ static int hclge_tx_buffer_calc(struct hclge_dev *hdev, return 0; } -/* hclge_rx_buffer_calc: calculate the rx private buffer size for all TCs - * @hdev: pointer to struct hclge_dev - * @buf_alloc: pointer to buffer calculation data - * @return: 0: calculate sucessful, negative: fail - */ -static int hclge_rx_buffer_calc(struct hclge_dev *hdev, - struct hclge_pkt_buf_alloc *buf_alloc) +static bool hclge_rx_buf_calc_all(struct hclge_dev *hdev, bool max, + struct hclge_pkt_buf_alloc *buf_alloc) { - u32 rx_all = hdev->pkt_buf_size, aligned_mps; - int no_pfc_priv_num, pfc_priv_num; - struct hclge_priv_buf *priv; + u32 rx_all = hdev->pkt_buf_size - hclge_get_tx_buff_alloced(buf_alloc); + u32 aligned_mps = round_up(hdev->mps, HCLGE_BUF_SIZE_UNIT); int i; - aligned_mps = round_up(hdev->mps, HCLGE_BUF_SIZE_UNIT); - rx_all -= hclge_get_tx_buff_alloced(buf_alloc); - - /* When DCB is not supported, rx private - * buffer is not allocated. - */ - if (!hnae3_dev_dcb_supported(hdev)) { - if (!hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all)) - return -ENOMEM; - - return 0; - } - - /* step 1, try to alloc private buffer for all enabled tc */ - for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { - priv = &buf_alloc->priv_buf[i]; - if (hdev->hw_tc_map & BIT(i)) { - priv->enable = 1; - if (hdev->tm_info.hw_pfc_map & BIT(i)) { - priv->wl.low = aligned_mps; - priv->wl.high = - roundup(priv->wl.low + aligned_mps, - HCLGE_BUF_SIZE_UNIT); - priv->buf_size = priv->wl.high + - hdev->dv_buf_size; - } else { - priv->wl.low = 0; - priv->wl.high = 2 * aligned_mps; - priv->buf_size = priv->wl.high + - hdev->dv_buf_size; - } - } else { - priv->enable = 0; - priv->wl.low = 0; - priv->wl.high = 0; - priv->buf_size = 0; - } - } - - if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all)) - return 0; - - /* step 2, try to decrease the buffer size of - * no pfc TC's private buffer - */ for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { - priv = &buf_alloc->priv_buf[i]; + struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i]; priv->enable = 0; priv->wl.low = 0; @@ -1592,28 +1541,30 @@ static int hclge_rx_buffer_calc(struct hclge_dev *hdev, priv->enable = 1; if (hdev->tm_info.hw_pfc_map & BIT(i)) { - priv->wl.low = 256; - priv->wl.high = priv->wl.low + aligned_mps; - priv->buf_size = priv->wl.high + hdev->dv_buf_size; + priv->wl.low = max ? aligned_mps : 256; + priv->wl.high = roundup(priv->wl.low + aligned_mps, + HCLGE_BUF_SIZE_UNIT); } else { priv->wl.low = 0; - priv->wl.high = aligned_mps; - priv->buf_size = priv->wl.high + hdev->dv_buf_size; + priv->wl.high = max ? (aligned_mps * 2) : aligned_mps; } + + priv->buf_size = priv->wl.high + hdev->dv_buf_size; } - if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all)) - return 0; + return hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all); +} - /* step 3, try to reduce the number of pfc disabled TCs, - * which have private buffer - */ - /* get the total no pfc enable TC number, which have private buffer */ - no_pfc_priv_num = hclge_get_no_pfc_priv_num(hdev, buf_alloc); +static bool hclge_drop_nopfc_buf_till_fit(struct hclge_dev *hdev, + struct hclge_pkt_buf_alloc *buf_alloc) +{ + u32 rx_all = hdev->pkt_buf_size - hclge_get_tx_buff_alloced(buf_alloc); + int no_pfc_priv_num = hclge_get_no_pfc_priv_num(hdev, buf_alloc); + int i; /* let the last to be cleared first */ for (i = HCLGE_MAX_TC_NUM - 1; i >= 0; i--) { - priv = &buf_alloc->priv_buf[i]; + struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i]; if (hdev->hw_tc_map & BIT(i) && !(hdev->tm_info.hw_pfc_map & BIT(i))) { @@ -1630,17 +1581,19 @@ static int hclge_rx_buffer_calc(struct hclge_dev *hdev, break; } - if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all)) - return 0; + return hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all); +} - /* step 4, try to reduce the number of pfc enabled TCs - * which have private buffer. - */ - pfc_priv_num = hclge_get_pfc_priv_num(hdev, buf_alloc); +static bool hclge_drop_pfc_buf_till_fit(struct hclge_dev *hdev, + struct hclge_pkt_buf_alloc *buf_alloc) +{ + u32 rx_all = hdev->pkt_buf_size - hclge_get_tx_buff_alloced(buf_alloc); + int pfc_priv_num = hclge_get_pfc_priv_num(hdev, buf_alloc); + int i; /* let the last to be cleared first */ for (i = HCLGE_MAX_TC_NUM - 1; i >= 0; i--) { - priv = &buf_alloc->priv_buf[i]; + struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i]; if (hdev->hw_tc_map & BIT(i) && hdev->tm_info.hw_pfc_map & BIT(i)) { @@ -1656,7 +1609,40 @@ static int hclge_rx_buffer_calc(struct hclge_dev *hdev, pfc_priv_num == 0) break; } - if (hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all)) + + return hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all); +} + +/* hclge_rx_buffer_calc: calculate the rx private buffer size for all TCs + * @hdev: pointer to struct hclge_dev + * @buf_alloc: pointer to buffer calculation data + * @return: 0: calculate sucessful, negative: fail + */ +static int hclge_rx_buffer_calc(struct hclge_dev *hdev, + struct hclge_pkt_buf_alloc *buf_alloc) +{ + /* When DCB is not supported, rx private buffer is not allocated. */ + if (!hnae3_dev_dcb_supported(hdev)) { + u32 rx_all = hdev->pkt_buf_size; + + rx_all -= hclge_get_tx_buff_alloced(buf_alloc); + if (!hclge_is_rx_buf_ok(hdev, buf_alloc, rx_all)) + return -ENOMEM; + + return 0; + } + + if (hclge_rx_buf_calc_all(hdev, true, buf_alloc)) + return 0; + + /* try to decrease the buffer size */ + if (hclge_rx_buf_calc_all(hdev, false, buf_alloc)) + return 0; + + if (hclge_drop_nopfc_buf_till_fit(hdev, buf_alloc)) + return 0; + + if (hclge_drop_pfc_buf_till_fit(hdev, buf_alloc)) return 0; return -ENOMEM; -- cgit v1.2.3 From b671b723e0d235b516dc33c163e6296df9b4f0ca Mon Sep 17 00:00:00 2001 From: Weihang Li Date: Sat, 2 Feb 2019 22:39:30 +0800 Subject: net: hns3: add hclge_cmd_check_retval() to parse comman's return value For simplifying the code, this patch adds hclge_cmd_check_retval() to check the return value of the command. Also, according the IMP's description, when there are several descriptors in a command, then the IMP will save the return value on the last description, so hclge_cmd_check_retval() just check the last one for this case. Signed-off-by: Weihang Li Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 60 ++++++++++++---------- 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 81dbe1b6abb0..57c50b947857 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -186,6 +186,38 @@ static bool hclge_is_special_opcode(u16 opcode) return false; } +static int hclge_cmd_check_retval(struct hclge_hw *hw, struct hclge_desc *desc, + int num, int ntc) +{ + u16 opcode, desc_ret; + int handle; + int retval; + + opcode = le16_to_cpu(desc[0].opcode); + for (handle = 0; handle < num; handle++) { + desc[handle] = hw->cmq.csq.desc[ntc]; + ntc++; + if (ntc == hw->cmq.csq.desc_num) + ntc = 0; + } + if (likely(!hclge_is_special_opcode(opcode))) + desc_ret = le16_to_cpu(desc[num - 1].retval); + else + desc_ret = le16_to_cpu(desc[0].retval); + + if (desc_ret == HCLGE_CMD_EXEC_SUCCESS) + retval = 0; + else if (desc_ret == HCLGE_CMD_NO_AUTH) + retval = -EPERM; + else if (desc_ret == HCLGE_CMD_NOT_SUPPORTED) + retval = -EOPNOTSUPP; + else + retval = -EIO; + hw->cmq.last_status = desc_ret; + + return retval; +} + /** * hclge_cmd_send - send command to command queue * @hw: pointer to the hw struct @@ -203,7 +235,6 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num) u32 timeout = 0; int handle = 0; int retval = 0; - u16 opcode, desc_ret; int ntc; spin_lock_bh(&hw->cmq.csq.lock); @@ -219,7 +250,6 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num) * which will be use for hardware to write back */ ntc = hw->cmq.csq.next_to_use; - opcode = le16_to_cpu(desc[0].opcode); while (handle < num) { desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use]; *desc_to_use = desc[handle]; @@ -250,31 +280,7 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num) if (!complete) { retval = -EAGAIN; } else { - handle = 0; - while (handle < num) { - /* Get the result of hardware write back */ - desc_to_use = &hw->cmq.csq.desc[ntc]; - desc[handle] = *desc_to_use; - - if (likely(!hclge_is_special_opcode(opcode))) - desc_ret = le16_to_cpu(desc[handle].retval); - else - desc_ret = le16_to_cpu(desc[0].retval); - - if (desc_ret == HCLGE_CMD_EXEC_SUCCESS) - retval = 0; - else if (desc_ret == HCLGE_CMD_NO_AUTH) - retval = -EPERM; - else if (desc_ret == HCLGE_CMD_NOT_SUPPORTED) - retval = -EOPNOTSUPP; - else - retval = -EIO; - hw->cmq.last_status = desc_ret; - ntc++; - handle++; - if (ntc == hw->cmq.csq.desc_num) - ntc = 0; - } + retval = hclge_cmd_check_retval(hw, desc, num, ntc); } /* Clean the command send queue */ -- cgit v1.2.3 From 3a586422a5533a6c78376a779860f48ed72b9d83 Mon Sep 17 00:00:00 2001 From: Weihang Li Date: Sat, 2 Feb 2019 22:39:31 +0800 Subject: net: hns3: move some set_bit statement into hclge_prepare_mac_addr This patch does not change the code logic. There are some same set_bit statements called by add/rm_uc/mc_addr_common, and move this statements into hclge_prepare_mac_addr to reduce duplicate code. Signed-off-by: Weihang Li Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 24 ++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index be7d82502f5f..a037dc5e36b7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5586,13 +5586,19 @@ static bool hclge_is_all_function_id_zero(struct hclge_desc *desc) } static void hclge_prepare_mac_addr(struct hclge_mac_vlan_tbl_entry_cmd *new_req, - const u8 *addr) + const u8 *addr, bool is_mc) { const unsigned char *mac_addr = addr; u32 high_val = mac_addr[2] << 16 | (mac_addr[3] << 24) | (mac_addr[0]) | (mac_addr[1] << 8); u32 low_val = mac_addr[4] | (mac_addr[5] << 8); + hnae3_set_bit(new_req->flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1); + if (is_mc) { + hnae3_set_bit(new_req->entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 1); + hnae3_set_bit(new_req->mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 1); + } + new_req->mac_addr_hi32 = cpu_to_le32(high_val); new_req->mac_addr_lo16 = cpu_to_le16(low_val & 0xffff); } @@ -5863,14 +5869,13 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport, } memset(&req, 0, sizeof(req)); - hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1); hnae3_set_field(egress_port, HCLGE_MAC_EPORT_VFID_M, HCLGE_MAC_EPORT_VFID_S, vport->vport_id); req.egress_port = cpu_to_le16(egress_port); - hclge_prepare_mac_addr(&req, addr); + hclge_prepare_mac_addr(&req, addr, false); /* Lookup the mac address in the mac_vlan table, and add * it if the entry is inexistent. Repeated unicast entry @@ -5928,9 +5933,8 @@ int hclge_rm_uc_addr_common(struct hclge_vport *vport, } memset(&req, 0, sizeof(req)); - hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1); hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0); - hclge_prepare_mac_addr(&req, addr); + hclge_prepare_mac_addr(&req, addr, false); ret = hclge_remove_mac_vlan_tbl(vport, &req); if (!ret) hclge_update_umv_space(vport, true); @@ -5962,11 +5966,8 @@ int hclge_add_mc_addr_common(struct hclge_vport *vport, return -EINVAL; } memset(&req, 0, sizeof(req)); - hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1); hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0); - hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 1); - hnae3_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 1); - hclge_prepare_mac_addr(&req, addr); + hclge_prepare_mac_addr(&req, addr, true); status = hclge_lookup_mac_vlan_tbl(vport, &req, desc, true); if (!status) { /* This mac addr exist, update VFID for it */ @@ -6012,11 +6013,8 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport, } memset(&req, 0, sizeof(req)); - hnae3_set_bit(req.flags, HCLGE_MAC_VLAN_BIT0_EN_B, 1); hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0); - hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT1_EN_B, 1); - hnae3_set_bit(req.mc_mac_en, HCLGE_MAC_VLAN_BIT0_EN_B, 1); - hclge_prepare_mac_addr(&req, addr); + hclge_prepare_mac_addr(&req, addr, true); status = hclge_lookup_mac_vlan_tbl(vport, &req, desc, true); if (!status) { /* This mac addr exist, remove this handle's VFID for it */ -- cgit v1.2.3 From b6b4f987c5c4fe488f3f68460b9addc08482b164 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Sat, 2 Feb 2019 22:39:32 +0800 Subject: net: hns3: fix a wrong checking in the hclge_tx_buffer_calc() Only the TC is enabled, we need to check whether the buffer is enough, otherwise it may lead to a wrong -ENOMEM case. Fixes: 9ffe79a9c2ee ("net: hns3: Support for dynamically assigning tx buffer to TC") Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index a037dc5e36b7..5f6fc23fab5d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1506,13 +1506,14 @@ static int hclge_tx_buffer_calc(struct hclge_dev *hdev, for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { struct hclge_priv_buf *priv = &buf_alloc->priv_buf[i]; - if (total_size < hdev->tx_buf_size) - return -ENOMEM; + if (hdev->hw_tc_map & BIT(i)) { + if (total_size < hdev->tx_buf_size) + return -ENOMEM; - if (hdev->hw_tc_map & BIT(i)) priv->tx_buf_size = hdev->tx_buf_size; - else + } else { priv->tx_buf_size = 0; + } total_size -= priv->tx_buf_size; } -- cgit v1.2.3 From 9194d18b0577a63f313a6eb2e0d4723add2c32e6 Mon Sep 17 00:00:00 2001 From: liuzhongzhu Date: Sat, 2 Feb 2019 22:39:33 +0800 Subject: net: hns3: fix the problem that the supported port is empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run ethtool ethx when displaying device information in VF, the supported port and link mode items will be empty. This patch fixes it. Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") Signed-off-by: liuzhongzhu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h | 4 ++- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 31 ++++++++++++++++++++- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 32 ++++++++++++++++++++-- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 2 ++ .../ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c | 12 ++++++++ 5 files changed, 77 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 691d12174902..53089cd980d9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -40,6 +40,8 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_SET_ALIVE, /* (VF -> PF) set alive state */ HCLGE_MBX_SET_MTU, /* (VF -> PF) set mtu */ HCLGE_MBX_GET_QID_IN_PF, /* (VF -> PF) get queue id in pf */ + HCLGE_MBX_LINK_STAT_MODE, /* (PF -> VF) link mode has changed */ + HCLGE_MBX_GET_LINK_MODE, /* (VF -> PF) get the link mode of pf */ }; /* below are per-VF mac-vlan subcodes */ @@ -60,7 +62,7 @@ enum hclge_mbx_vlan_cfg_subcode { }; #define HCLGE_MBX_MAX_MSG_SIZE 16 -#define HCLGE_MBX_MAX_RESP_DATA_SIZE 8 +#define HCLGE_MBX_MAX_RESP_DATA_SIZE 16 #define HCLGE_MBX_RING_MAP_BASIC_MSG_NUM 3 #define HCLGE_MBX_RING_NODE_VARIABLE_NUM 3 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 6afb0a4b73f7..7e4a104582d6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -355,16 +355,19 @@ static int hclge_get_link_info(struct hclge_vport *vport, { struct hclge_dev *hdev = vport->back; u16 link_status; - u8 msg_data[8]; + u8 msg_data[10]; + u16 media_type; u8 dest_vfid; u16 duplex; /* mac.link can only be 0 or 1 */ link_status = (u16)hdev->hw.mac.link; duplex = hdev->hw.mac.duplex; + media_type = hdev->hw.mac.media_type; memcpy(&msg_data[0], &link_status, sizeof(u16)); memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32)); memcpy(&msg_data[6], &duplex, sizeof(u16)); + memcpy(&msg_data[8], &media_type, sizeof(u16)); dest_vfid = mbx_req->mbx_src_vfid; /* send this requested info to VF */ @@ -372,6 +375,29 @@ static int hclge_get_link_info(struct hclge_vport *vport, HCLGE_MBX_LINK_STAT_CHANGE, dest_vfid); } +static void hclge_get_link_mode(struct hclge_vport *vport, + struct hclge_mbx_vf_to_pf_cmd *mbx_req) +{ +#define HCLGE_SUPPORTED 1 + struct hclge_dev *hdev = vport->back; + unsigned long advertising; + unsigned long supported; + unsigned long send_data; + u8 msg_data[10]; + u8 dest_vfid; + + advertising = hdev->hw.mac.advertising[0]; + supported = hdev->hw.mac.supported[0]; + dest_vfid = mbx_req->mbx_src_vfid; + msg_data[0] = mbx_req->msg[2]; + + send_data = msg_data[0] == HCLGE_SUPPORTED ? supported : advertising; + + memcpy(&msg_data[2], &send_data, sizeof(unsigned long)); + hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), + HCLGE_MBX_LINK_STAT_MODE, dest_vfid); +} + static void hclge_mbx_reset_vf_queue(struct hclge_vport *vport, struct hclge_mbx_vf_to_pf_cmd *mbx_req) { @@ -556,6 +582,9 @@ void hclge_mbx_handler(struct hclge_dev *hdev) "PF failed(%d) to get qid for VF\n", ret); break; + case HCLGE_MBX_GET_LINK_MODE: + hclge_get_link_mode(vport, req); + break; default: dev_err(&hdev->pdev->dev, "un-supported mailbox message, code = %d\n", diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index bc2f29e67280..4a897cfb573b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -381,6 +381,21 @@ void hclgevf_update_link_status(struct hclgevf_dev *hdev, int link_state) } } +void hclgevf_update_link_mode(struct hclgevf_dev *hdev) +{ +#define HCLGEVF_ADVERTISING 0 +#define HCLGEVF_SUPPORTED 1 + u8 send_msg; + u8 resp_msg; + + send_msg = HCLGEVF_ADVERTISING; + hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_LINK_MODE, 0, &send_msg, + sizeof(u8), false, &resp_msg, sizeof(u8)); + send_msg = HCLGEVF_SUPPORTED; + hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_LINK_MODE, 0, &send_msg, + sizeof(u8), false, &resp_msg, sizeof(u8)); +} + static int hclgevf_set_handle_info(struct hclgevf_dev *hdev) { struct hnae3_handle *nic = &hdev->nic; @@ -1646,6 +1661,8 @@ static void hclgevf_service_task(struct work_struct *work) */ hclgevf_request_link_info(hdev); + hclgevf_update_link_mode(hdev); + hclgevf_deferred_task_schedule(hdev); clear_bit(HCLGEVF_STATE_SERVICE_SCHED, &hdev->state); @@ -1726,8 +1743,6 @@ static int hclgevf_configure(struct hclgevf_dev *hdev) { int ret; - hdev->hw.mac.media_type = HNAE3_MEDIA_TYPE_NONE; - /* get queue configuration from PF */ ret = hclgevf_get_queue_info(hdev); if (ret) @@ -1880,6 +1895,8 @@ static int hclgevf_ae_start(struct hnae3_handle *handle) hclgevf_request_link_info(hdev); + hclgevf_update_link_mode(hdev); + clear_bit(HCLGEVF_STATE_DOWN, &hdev->state); return 0; @@ -2586,6 +2603,16 @@ static unsigned long hclgevf_ae_dev_reset_cnt(struct hnae3_handle *handle) return hdev->reset_count; } +static void hclgevf_get_link_mode(struct hnae3_handle *handle, + unsigned long *supported, + unsigned long *advertising) +{ + struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + + *supported = hdev->hw.mac.supported; + *advertising = hdev->hw.mac.advertising; +} + #define MAX_SEPARATE_NUM 4 #define SEPARATOR_VALUE 0xFFFFFFFF #define REG_NUM_PER_LINE 4 @@ -2704,6 +2731,7 @@ static const struct hnae3_ae_ops hclgevf_ops = { .set_mtu = hclgevf_set_mtu, .get_global_queue_id = hclgevf_get_qid_global, .set_timer_task = hclgevf_set_timer_task, + .get_link_mode = hclgevf_get_link_mode, }; static struct hnae3_ae_algo ae_algovf = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index 787bc06944e5..eba1118a766d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -145,6 +145,8 @@ struct hclgevf_mac { int link; u8 duplex; u32 speed; + u64 supported; + u64 advertising; }; struct hclgevf_hw { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c index 84653f58b2d1..7dc3c9f79169 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c @@ -197,6 +197,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev) break; case HCLGE_MBX_LINK_STAT_CHANGE: case HCLGE_MBX_ASSERTING_RESET: + case HCLGE_MBX_LINK_STAT_MODE: /* set this mbx event as pending. This is required as we * might loose interrupt event when mbx task is busy * handling. This shall be cleared when mbx task just @@ -247,6 +248,7 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) u8 duplex; u32 speed; u32 tail; + u8 idx; /* we can safely clear it now as we are at start of the async message * processing @@ -270,12 +272,22 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev) link_status = le16_to_cpu(msg_q[1]); memcpy(&speed, &msg_q[2], sizeof(speed)); duplex = (u8)le16_to_cpu(msg_q[4]); + hdev->hw.mac.media_type = (u8)le16_to_cpu(msg_q[5]); /* update upper layer with new link link status */ hclgevf_update_link_status(hdev, link_status); hclgevf_update_speed_duplex(hdev, speed, duplex); break; + case HCLGE_MBX_LINK_STAT_MODE: + idx = (u8)le16_to_cpu(msg_q[1]); + if (idx) + memcpy(&hdev->hw.mac.supported, &msg_q[2], + sizeof(unsigned long)); + else + memcpy(&hdev->hw.mac.advertising, &msg_q[2], + sizeof(unsigned long)); + break; case HCLGE_MBX_ASSERTING_RESET: /* PF has asserted reset hence VF should go in pending * state and poll for the hardware reset status till it -- cgit v1.2.3 From f9f07091b43e3a758bd197eb99ef5f011efce7fc Mon Sep 17 00:00:00 2001 From: liuzhongzhu Date: Sat, 2 Feb 2019 22:39:34 +0800 Subject: net: hns3: optimize the maximum TC macro Multiple macros with the largest number of TCs in the system, optimized to HCLGE_MAX_TC_NUM. Signed-off-by: liuzhongzhu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 7 +++---- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 4 ++-- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index e26a25128693..ac2cd219a9fb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -312,16 +312,16 @@ struct hclge_ctrl_vector_chain_cmd { u8 rsv; }; -#define HCLGE_TC_NUM 8 +#define HCLGE_MAX_TC_NUM 8 #define HCLGE_TC0_PRI_BUF_EN_B 15 /* Bit 15 indicate enable or not */ #define HCLGE_BUF_UNIT_S 7 /* Buf size is united by 128 bytes */ struct hclge_tx_buff_alloc_cmd { - __le16 tx_pkt_buff[HCLGE_TC_NUM]; + __le16 tx_pkt_buff[HCLGE_MAX_TC_NUM]; u8 tx_buff_rsv[8]; }; struct hclge_rx_priv_buff_cmd { - __le16 buf_num[HCLGE_TC_NUM]; + __le16 buf_num[HCLGE_MAX_TC_NUM]; __le16 shared_buf; u8 rsv[6]; }; @@ -367,7 +367,6 @@ struct hclge_priv_buf { u32 enable; /* Enable TC private buffer or not */ }; -#define HCLGE_MAX_TC_NUM 8 struct hclge_shared_buf { struct hclge_waterline self; struct hclge_tc_thrd tc_thrd[HCLGE_MAX_TC_NUM]; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c index 26d80504c730..1192cf6f2321 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c @@ -691,7 +691,7 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) dev_info(&hdev->pdev->dev, "dump qos buf cfg\n"); tx_buf_cmd = (struct hclge_tx_buff_alloc_cmd *)desc[0].data; - for (i = 0; i < HCLGE_TC_NUM; i++) + for (i = 0; i < HCLGE_MAX_TC_NUM; i++) dev_info(&hdev->pdev->dev, "tx_packet_buf_tc_%d: 0x%x\n", i, tx_buf_cmd->tx_pkt_buff[i]); @@ -703,7 +703,7 @@ static void hclge_dbg_dump_qos_buf_cfg(struct hclge_dev *hdev) dev_info(&hdev->pdev->dev, "\n"); rx_buf_cmd = (struct hclge_rx_priv_buff_cmd *)desc[0].data; - for (i = 0; i < HCLGE_TC_NUM; i++) + for (i = 0; i < HCLGE_MAX_TC_NUM; i++) dev_info(&hdev->pdev->dev, "rx_packet_buf_tc_%d: 0x%x\n", i, rx_buf_cmd->buf_num[i]); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 5f6fc23fab5d..f55835dee5c7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1331,7 +1331,7 @@ static int hclge_cmd_alloc_tx_buff(struct hclge_dev *hdev, req = (struct hclge_tx_buff_alloc_cmd *)desc.data; hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TX_BUFF_ALLOC, 0); - for (i = 0; i < HCLGE_TC_NUM; i++) { + for (i = 0; i < HCLGE_MAX_TC_NUM; i++) { u32 buf_size = buf_alloc->priv_buf[i].tx_buf_size; req->tx_pkt_buff[i] = -- cgit v1.2.3 From 77af09c6780b1394a1e888a6862d49cadc0247fa Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sat, 2 Feb 2019 22:39:35 +0800 Subject: net: hns3: don't allow user to change vlan filter state When user disables vlan filter, and adds vlan device, it won't notify the driver the update the vlan filter. In this case, when user enables vlan filter again, the packets with new vlan tag will be filtered by vlan filter. Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index db06d36d408f..40b17223ee41 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1929,8 +1929,7 @@ static void hns3_set_default_feature(struct net_device *netdev) NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC; if (pdev->revision >= 0x21) { - netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER | - NETIF_F_GRO_HW; + netdev->hw_features |= NETIF_F_GRO_HW; netdev->features |= NETIF_F_GRO_HW; if (!(h->flags & HNAE3_SUPPORT_VF)) { -- cgit v1.2.3 From 6104ca87e12a5119d3e53e926bb6fe468bb328e2 Mon Sep 17 00:00:00 2001 From: liuzhongzhu Date: Sat, 2 Feb 2019 22:39:36 +0800 Subject: net: hns3: modify the upper limit judgment condition In order to prevent the variable anomaly from being larger than desc_num, the upper limit judgment condition becomes >=. Signed-off-by: liuzhongzhu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 57c50b947857..1dddfcba41a9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -197,7 +197,7 @@ static int hclge_cmd_check_retval(struct hclge_hw *hw, struct hclge_desc *desc, for (handle = 0; handle < num; handle++) { desc[handle] = hw->cmq.csq.desc[ntc]; ntc++; - if (ntc == hw->cmq.csq.desc_num) + if (ntc >= hw->cmq.csq.desc_num) ntc = 0; } if (likely(!hclge_is_special_opcode(opcode))) @@ -254,7 +254,7 @@ int hclge_cmd_send(struct hclge_hw *hw, struct hclge_desc *desc, int num) desc_to_use = &hw->cmq.csq.desc[hw->cmq.csq.next_to_use]; *desc_to_use = desc[handle]; (hw->cmq.csq.next_to_use)++; - if (hw->cmq.csq.next_to_use == hw->cmq.csq.desc_num) + if (hw->cmq.csq.next_to_use >= hw->cmq.csq.desc_num) hw->cmq.csq.next_to_use = 0; handle++; } -- cgit v1.2.3 From 54a395b63e470696884fc12629b12e24d9379111 Mon Sep 17 00:00:00 2001 From: liuzhongzhu Date: Sat, 2 Feb 2019 22:39:37 +0800 Subject: net: hns3: MAC table entry count function increases operation 0 value protection measures When updating the available MAC VLAN table counts, MAC VLAN table entry count function adds operation 0 value protection measures. Signed-off-by: liuzhongzhu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index f55835dee5c7..0a64c7f2dc6c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5830,9 +5830,12 @@ static void hclge_update_umv_space(struct hclge_vport *vport, bool is_free) if (is_free) { if (vport->used_umv_num > hdev->priv_umv_size) hdev->share_umv_size++; - vport->used_umv_num--; + + if (vport->used_umv_num > 0) + vport->used_umv_num--; } else { - if (vport->used_umv_num >= hdev->priv_umv_size) + if (vport->used_umv_num >= hdev->priv_umv_size && + hdev->share_umv_size > 0) hdev->share_umv_size--; vport->used_umv_num++; } -- cgit v1.2.3 From 5ea25b125289ed1d77da736a5d511a7d01f4bfb6 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 31 Jan 2019 22:03:48 +0100 Subject: r8169: remove rtl_wol_pll_power_down rtl_wol_pll_power_down() is used in only one place and removing it makes the code simpler and better readable. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 9dc68981751b..e8a112149a62 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -4247,17 +4247,6 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) } } -static bool rtl_wol_pll_power_down(struct rtl8169_private *tp) -{ - if (!device_may_wakeup(tp_to_dev(tp))) - return false; - - phy_speed_down(tp->phydev, false); - rtl_wol_suspend_quirk(tp); - - return true; -} - static void r8168_pll_power_down(struct rtl8169_private *tp) { if (r8168_check_dash(tp)) @@ -4267,8 +4256,11 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) tp->mac_version == RTL_GIGA_MAC_VER_33) rtl_ephy_write(tp, 0x19, 0xff64); - if (rtl_wol_pll_power_down(tp)) + if (device_may_wakeup(tp_to_dev(tp))) { + phy_speed_down(tp->phydev, false); + rtl_wol_suspend_quirk(tp); return; + } switch (tp->mac_version) { case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_33: -- cgit v1.2.3 From 87ab207981ec54dc2f2a1511cd2fbfc9bc6599ec Mon Sep 17 00:00:00 2001 From: Alex Williams Date: Thu, 31 Jan 2019 13:33:27 -0800 Subject: net: nixge: Separate ctrl and dma resources The DMA engine is a separate entity altogether, and this allows the DMA controller's address to float elsewhere in the FPGA's map. Signed-off-by: Alex Williams Signed-off-by: David S. Miller --- drivers/net/ethernet/ni/nixge.c | 74 ++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index 1e408d1a9b5f..73a98bd2fcd2 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -105,6 +105,12 @@ #define NIXGE_MAX_JUMBO_FRAME_SIZE \ (NIXGE_JUMBO_MTU + NIXGE_HDR_SIZE + NIXGE_TRL_SIZE) +enum nixge_version { + NIXGE_V2, + NIXGE_V3, + NIXGE_VERSION_COUNT +}; + struct nixge_hw_dma_bd { u32 next_lo; u32 next_hi; @@ -1225,11 +1231,59 @@ static void *nixge_get_nvmem_address(struct device *dev) return mac; } +/* Match table for of_platform binding */ +static const struct of_device_id nixge_dt_ids[] = { + { .compatible = "ni,xge-enet-2.00", .data = (void *)NIXGE_V2 }, + { .compatible = "ni,xge-enet-3.00", .data = (void *)NIXGE_V3 }, + {}, +}; +MODULE_DEVICE_TABLE(of, nixge_dt_ids); + +static int nixge_of_get_resources(struct platform_device *pdev) +{ + const struct of_device_id *of_id; + enum nixge_version version; + struct resource *ctrlres; + struct resource *dmares; + struct net_device *ndev; + struct nixge_priv *priv; + + ndev = platform_get_drvdata(pdev); + priv = netdev_priv(ndev); + of_id = of_match_node(nixge_dt_ids, pdev->dev.of_node); + if (!of_id) + return -ENODEV; + + version = (enum nixge_version)of_id->data; + if (version <= NIXGE_V2) + dmares = platform_get_resource(pdev, IORESOURCE_MEM, 0); + else + dmares = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "dma"); + + priv->dma_regs = devm_ioremap_resource(&pdev->dev, dmares); + if (IS_ERR(priv->dma_regs)) { + netdev_err(ndev, "failed to map dma regs\n"); + return PTR_ERR(priv->dma_regs); + } + if (version <= NIXGE_V2) { + priv->ctrl_regs = priv->dma_regs + NIXGE_REG_CTRL_OFFSET; + } else { + ctrlres = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "ctrl"); + priv->ctrl_regs = devm_ioremap_resource(&pdev->dev, ctrlres); + } + if (IS_ERR(priv->ctrl_regs)) { + netdev_err(ndev, "failed to map ctrl regs\n"); + return PTR_ERR(priv->ctrl_regs); + } + return 0; +} + static int nixge_probe(struct platform_device *pdev) { struct nixge_priv *priv; struct net_device *ndev; - struct resource *dmares; const u8 *mac_addr; int err; @@ -1261,14 +1315,9 @@ static int nixge_probe(struct platform_device *pdev) priv->dev = &pdev->dev; netif_napi_add(ndev, &priv->napi, nixge_poll, NAPI_POLL_WEIGHT); - - dmares = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->dma_regs = devm_ioremap_resource(&pdev->dev, dmares); - if (IS_ERR(priv->dma_regs)) { - netdev_err(ndev, "failed to map dma regs\n"); - return PTR_ERR(priv->dma_regs); - } - priv->ctrl_regs = priv->dma_regs + NIXGE_REG_CTRL_OFFSET; + err = nixge_of_get_resources(pdev); + if (err) + return err; __nixge_hw_set_mac_address(ndev); priv->tx_irq = platform_get_irq_byname(pdev, "tx"); @@ -1337,13 +1386,6 @@ static int nixge_remove(struct platform_device *pdev) return 0; } -/* Match table for of_platform binding */ -static const struct of_device_id nixge_dt_ids[] = { - { .compatible = "ni,xge-enet-2.00", }, - {}, -}; -MODULE_DEVICE_TABLE(of, nixge_dt_ids); - static struct platform_driver nixge_driver = { .probe = nixge_probe, .remove = nixge_remove, -- cgit v1.2.3 From 7831216b00531c7fad7575a207729d3b4acd6f4d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 2 Feb 2019 11:33:51 +0000 Subject: chelsio: clean up indentation issue The assignment to size is indented too far, fix this and join two lines into one. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb/sge.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb/sge.c b/drivers/net/ethernet/chelsio/cxgb/sge.c index 30de26ef3da4..47b5c8e2104b 100644 --- a/drivers/net/ethernet/chelsio/cxgb/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb/sge.c @@ -585,8 +585,7 @@ static int alloc_rx_resources(struct sge *sge, struct sge_params *p) sizeof(struct cpl_rx_data) + sge->freelQ[!sge->jumbo_fl].dma_offset; - size = (16 * 1024) - - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + size = (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); sge->freelQ[sge->jumbo_fl].rx_buffer_size = size; -- cgit v1.2.3 From 282faf3d3ac674116f61d374022285472a294c18 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 2 Feb 2019 11:37:07 +0000 Subject: bna: fix indentation issue on call to bfa_ioc_pf_failed The call to bfa_ioc_pf_failed is indented too far, fix this by removing a tab. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/brocade/bna/bfa_ioc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index cbc9175d74c5..84741d288ffa 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -743,7 +743,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event) case IOCPF_E_TIMEOUT: bfa_nw_ioc_hw_sem_release(ioc); - bfa_ioc_pf_failed(ioc); + bfa_ioc_pf_failed(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); break; -- cgit v1.2.3 From 7509ef2add7b86130f0b5e9428cc975d063be9bf Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 2 Feb 2019 11:41:29 +0000 Subject: atl1c: fix indentation issue on an if statement An if statement is indented one level too deep, fix this by removing the extra tabs. Also add some spaces to the dev_warn arguments to clean up checkpatch warnings. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 3a3b35b5df67..0f1eb1981469 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1833,10 +1833,10 @@ rrs_checked: atl1c_clean_rrd(rrd_ring, rrs, rfd_num); if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) { atl1c_clean_rfd(rfd_ring, rrs, rfd_num); - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, - "wrong packet! rrs word3 is %x\n", - rrs->word3); + if (netif_msg_rx_err(adapter)) + dev_warn(&pdev->dev, + "wrong packet! rrs word3 is %x\n", + rrs->word3); continue; } -- cgit v1.2.3 From 682a789516d323d883204c2954d53e92e269aa86 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 2 Feb 2019 11:45:26 +0000 Subject: atheros: atl2: fix an indentaion issue on a return statement A return statment is not indented correctly, fix this by adding an extra tab. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atlx/atl2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index c44e95255aa1..a7337a6d507d 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -2946,7 +2946,7 @@ static int atl2_validate_option(int *value, struct atl2_option *opt) if (*value == ent->i) { if (ent->str[0] != '\0') printk(KERN_INFO "%s\n", ent->str); - return 0; + return 0; } } break; -- cgit v1.2.3 From 46861e3e88be18846971792b763eaf520a91a802 Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Tue, 22 Jan 2019 08:48:51 +0200 Subject: net/mlx5: Set ODP SRQ support in firmware To avoid compatibility issue with older kernels the firmware doesn't allow SRQ to work with ODP unless kernel asks for it. Signed-off-by: Moni Shoua Reviewed-by: Majd Dibbiny Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 53 ++++++++++++++++++++++++++ include/linux/mlx5/device.h | 3 ++ include/linux/mlx5/mlx5_ifc.h | 1 + 3 files changed, 57 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 085e1133b8d5..e38aa206ab6d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -459,6 +459,53 @@ static int handle_hca_cap_atomic(struct mlx5_core_dev *dev) return err; } +static int handle_hca_cap_odp(struct mlx5_core_dev *dev) +{ + void *set_ctx; + void *set_hca_cap; + int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); + int err; + + if (!MLX5_CAP_GEN(dev, pg)) + return 0; + + err = mlx5_core_get_caps(dev, MLX5_CAP_ODP); + if (err) + return err; + + /** + * If all bits are cleared we shouldn't try to set it + * or we might fail while trying to access a reserved bit. + */ + if (!(MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive) || + MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive) || + MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive))) + return 0; + + set_ctx = kzalloc(set_sz, GFP_KERNEL); + if (!set_ctx) + return -ENOMEM; + + set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability); + memcpy(set_hca_cap, dev->caps.hca_cur[MLX5_CAP_ODP], + MLX5_ST_SZ_BYTES(odp_cap)); + + /* set ODP SRQ support for RC/UD and XRC transports */ + MLX5_SET(odp_cap, set_hca_cap, ud_odp_caps.srq_receive, + (MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive))); + + MLX5_SET(odp_cap, set_hca_cap, rc_odp_caps.srq_receive, + (MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive))); + + MLX5_SET(odp_cap, set_hca_cap, xrc_odp_caps.srq_receive, + (MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive))); + + err = set_caps(dev, set_ctx, set_sz, MLX5_SET_HCA_CAP_OP_MOD_ODP); + + kfree(set_ctx); + return err; +} + static int handle_hca_cap(struct mlx5_core_dev *dev) { void *set_ctx = NULL; @@ -931,6 +978,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, goto reclaim_boot_pages; } + err = handle_hca_cap_odp(dev); + if (err) { + dev_err(&pdev->dev, "handle_hca_cap_odp failed\n"); + goto reclaim_boot_pages; + } + err = mlx5_satisfy_startup_pages(dev, 0); if (err) { dev_err(&pdev->dev, "failed to allocate init pages\n"); diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 8c4a820bd4c1..0845a227a7b2 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -1201,6 +1201,9 @@ enum mlx5_qcam_feature_groups { #define MLX5_CAP_ODP(mdev, cap)\ MLX5_GET(odp_cap, mdev->caps.hca_cur[MLX5_CAP_ODP], cap) +#define MLX5_CAP_ODP_MAX(mdev, cap)\ + MLX5_GET(odp_cap, mdev->caps.hca_max[MLX5_CAP_ODP], cap) + #define MLX5_CAP_VECTOR_CALC(mdev, cap) \ MLX5_GET(vector_calc_cap, \ mdev->caps.hca_cur[MLX5_CAP_VECTOR_CALC], cap) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 5407db8ba8e1..c5c679390fbd 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -72,6 +72,7 @@ enum { enum { MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE = 0x0, + MLX5_SET_HCA_CAP_OP_MOD_ODP = 0x2, MLX5_SET_HCA_CAP_OP_MOD_ATOMIC = 0x3, }; -- cgit v1.2.3 From f66ebd14a71bd50a46801a7cabd779a1a324bf76 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 3 Feb 2019 16:07:33 +0100 Subject: net: phy: realtek: add generic Realtek PHY driver The integrated PHY's of later RTL8168 network chips report the generic PHYID 0x001cc800 (Realtek OUI, model and revision number both set to zero) and therefore currently the genphy driver is used. To be able to use the paged version of e.g. phy_write() we need a PHY driver with the read_page and write_page callbacks implemented. So basically make a copy of the genphy driver, just with the read_page and write_page callbacks being set. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/realtek.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 75543f9370f3..d8c4b9ae0fa4 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -272,6 +272,15 @@ static struct phy_driver realtek_drvs[] = { .resume = genphy_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + }, { + PHY_ID_MATCH_EXACT(0x001cc800), + .name = "Generic Realtek PHY", + .features = PHY_GBIT_FEATURES, + .config_init = genphy_config_init, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, }, { PHY_ID_MATCH_EXACT(0x001cc961), .name = "RTL8366RB Gigabit Ethernet", -- cgit v1.2.3 From 3f8cfd0d95e65ddc6aef70ef28b80cdc3d8ad7e4 Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Fri, 1 Feb 2019 17:07:04 +0530 Subject: cxgb4/cxgb4vf: Program hash region for {t4/t4vf}_change_mac() {t4/t4_vf}_change_mac() API's were only doing additions to MPS_TCAM. This will fail, when the number of tcam entries is limited particularly in vf's. This fix programs hash region with the mac address, when TCAM addtion fails for {t4/t4vf}_change_mac(). Since the locally maintained driver list for hash entries is shared across mac_{sync/unsync}(), added an extra parameter if_mac to track the address added thorugh {t4/t4vf}_change_mac() Signed-off-by: Arjun Vynipadath Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 3 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 71 +++++++++++++--- drivers/net/ethernet/chelsio/cxgb4vf/adapter.h | 3 +- .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 99 ++++++++++++++++------ 4 files changed, 136 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 2d1ca920601e..568715a13b5c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -568,7 +568,7 @@ struct sge_rspq; struct port_info { struct adapter *adapter; u16 viid; - s16 xact_addr_filt; /* index of exact MAC address filter */ + int xact_addr_filt; /* index of exact MAC address filter */ u16 rss_size; /* size of VI's RSS table slice */ s8 mdio_addr; enum fw_port_type port_type; @@ -860,6 +860,7 @@ struct doorbell_stats { struct hash_mac_addr { struct list_head list; u8 addr[ETH_ALEN]; + unsigned int iface_mac; }; struct uld_msix_bmap { diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 73fc2479b4f4..adf75d16e6d3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -433,6 +433,60 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok) } /** + * cxgb4_change_mac - Update match filter for a MAC address. + * @pi: the port_info + * @viid: the VI id + * @tcam_idx: TCAM index of existing filter for old value of MAC address, + * or -1 + * @addr: the new MAC address value + * @persist: whether a new MAC allocation should be persistent + * @add_smt: if true also add the address to the HW SMT + * + * Modifies an MPS filter and sets it to the new MAC address if + * @tcam_idx >= 0, or adds the MAC address to a new filter if + * @tcam_idx < 0. In the latter case the address is added persistently + * if @persist is %true. + * Addresses are programmed to hash region, if tcam runs out of entries. + * + */ +static int cxgb4_change_mac(struct port_info *pi, unsigned int viid, + int *tcam_idx, const u8 *addr, bool persist, + u8 *smt_idx) +{ + struct adapter *adapter = pi->adapter; + struct hash_mac_addr *entry, *new_entry; + int ret; + + ret = t4_change_mac(adapter, adapter->mbox, viid, + *tcam_idx, addr, persist, smt_idx); + /* We ran out of TCAM entries. try programming hash region. */ + if (ret == -ENOMEM) { + /* If the MAC address to be updated is in the hash addr + * list, update it from the list + */ + list_for_each_entry(entry, &adapter->mac_hlist, list) { + if (entry->iface_mac) { + ether_addr_copy(entry->addr, addr); + goto set_hash; + } + } + new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); + if (!new_entry) + return -ENOMEM; + ether_addr_copy(new_entry->addr, addr); + new_entry->iface_mac = true; + list_add_tail(&new_entry->list, &adapter->mac_hlist); +set_hash: + ret = cxgb4_set_addr_hash(pi); + } else if (ret >= 0) { + *tcam_idx = ret; + ret = 0; + } + + return ret; +} + +/* * link_start - enable a port * @dev: the port to enable * @@ -450,15 +504,9 @@ static int link_start(struct net_device *dev) */ ret = t4_set_rxmode(pi->adapter, mb, pi->viid, dev->mtu, -1, -1, -1, !!(dev->features & NETIF_F_HW_VLAN_CTAG_RX), true); - if (ret == 0) { - ret = t4_change_mac(pi->adapter, mb, pi->viid, - pi->xact_addr_filt, dev->dev_addr, true, - &pi->smt_idx); - if (ret >= 0) { - pi->xact_addr_filt = ret; - ret = 0; - } - } + if (ret == 0) + ret = cxgb4_change_mac(pi, pi->viid, &pi->xact_addr_filt, + dev->dev_addr, true, &pi->smt_idx); if (ret == 0) ret = t4_link_l1cfg(pi->adapter, mb, pi->tx_chan, &pi->link_cfg); @@ -2839,9 +2887,8 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - ret = t4_change_mac(pi->adapter, pi->adapter->pf, pi->viid, - pi->xact_addr_filt, addr->sa_data, true, - &pi->smt_idx); + ret = cxgb4_change_mac(pi, pi->viid, &pi->xact_addr_filt, + addr->sa_data, true, &pi->smt_idx); if (ret < 0) return ret; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h index 5883f09e3804..26f48a14d2f9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h @@ -94,7 +94,7 @@ struct port_info { struct adapter *adapter; /* our adapter */ u32 vlan_id; /* vlan id for VST */ u16 viid; /* virtual interface ID */ - s16 xact_addr_filt; /* index of our MAC address filter */ + int xact_addr_filt; /* index of our MAC address filter */ u16 rss_size; /* size of VI's RSS table slice */ u8 pidx; /* index into adapter port[] */ s8 mdio_addr; @@ -352,6 +352,7 @@ struct sge { struct hash_mac_addr { struct list_head list; u8 addr[ETH_ALEN]; + unsigned int iface_mac; }; struct mbox_list { diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 1fa24af8099f..84be3313fede 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -236,6 +236,73 @@ void t4vf_os_portmod_changed(struct adapter *adapter, int pidx) "inserted\n", dev->name, pi->mod_type); } +static int cxgb4vf_set_addr_hash(struct port_info *pi) +{ + struct adapter *adapter = pi->adapter; + u64 vec = 0; + bool ucast = false; + struct hash_mac_addr *entry; + + /* Calculate the hash vector for the updated list and program it */ + list_for_each_entry(entry, &adapter->mac_hlist, list) { + ucast |= is_unicast_ether_addr(entry->addr); + vec |= (1ULL << hash_mac_addr(entry->addr)); + } + return t4vf_set_addr_hash(adapter, pi->viid, ucast, vec, false); +} + +/** + * cxgb4vf_change_mac - Update match filter for a MAC address. + * @pi: the port_info + * @viid: the VI id + * @tcam_idx: TCAM index of existing filter for old value of MAC address, + * or -1 + * @addr: the new MAC address value + * @persist: whether a new MAC allocation should be persistent + * @add_smt: if true also add the address to the HW SMT + * + * Modifies an MPS filter and sets it to the new MAC address if + * @tcam_idx >= 0, or adds the MAC address to a new filter if + * @tcam_idx < 0. In the latter case the address is added persistently + * if @persist is %true. + * Addresses are programmed to hash region, if tcam runs out of entries. + * + */ +static int cxgb4vf_change_mac(struct port_info *pi, unsigned int viid, + int *tcam_idx, const u8 *addr, bool persistent) +{ + struct hash_mac_addr *new_entry, *entry; + struct adapter *adapter = pi->adapter; + int ret; + + ret = t4vf_change_mac(adapter, viid, *tcam_idx, addr, persistent); + /* We ran out of TCAM entries. try programming hash region. */ + if (ret == -ENOMEM) { + /* If the MAC address to be updated is in the hash addr + * list, update it from the list + */ + list_for_each_entry(entry, &adapter->mac_hlist, list) { + if (entry->iface_mac) { + ether_addr_copy(entry->addr, addr); + goto set_hash; + } + } + new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL); + if (!new_entry) + return -ENOMEM; + ether_addr_copy(new_entry->addr, addr); + new_entry->iface_mac = true; + list_add_tail(&new_entry->list, &adapter->mac_hlist); +set_hash: + ret = cxgb4vf_set_addr_hash(pi); + } else if (ret >= 0) { + *tcam_idx = ret; + ret = 0; + } + + return ret; +} + /* * Net device operations. * ====================== @@ -259,14 +326,10 @@ static int link_start(struct net_device *dev) */ ret = t4vf_set_rxmode(pi->adapter, pi->viid, dev->mtu, -1, -1, -1, 1, true); - if (ret == 0) { - ret = t4vf_change_mac(pi->adapter, pi->viid, - pi->xact_addr_filt, dev->dev_addr, true); - if (ret >= 0) { - pi->xact_addr_filt = ret; - ret = 0; - } - } + if (ret == 0) + ret = cxgb4vf_change_mac(pi, pi->viid, + &pi->xact_addr_filt, + dev->dev_addr, true); /* * We don't need to actually "start the link" itself since the @@ -870,21 +933,6 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev) return ns; } -static inline int cxgb4vf_set_addr_hash(struct port_info *pi) -{ - struct adapter *adapter = pi->adapter; - u64 vec = 0; - bool ucast = false; - struct hash_mac_addr *entry; - - /* Calculate the hash vector for the updated list and program it */ - list_for_each_entry(entry, &adapter->mac_hlist, list) { - ucast |= is_unicast_ether_addr(entry->addr); - vec |= (1ULL << hash_mac_addr(entry->addr)); - } - return t4vf_set_addr_hash(adapter, pi->viid, ucast, vec, false); -} - static int cxgb4vf_mac_sync(struct net_device *netdev, const u8 *mac_addr) { struct port_info *pi = netdev_priv(netdev); @@ -1166,13 +1214,12 @@ static int cxgb4vf_set_mac_addr(struct net_device *dev, void *_addr) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - ret = t4vf_change_mac(pi->adapter, pi->viid, pi->xact_addr_filt, - addr->sa_data, true); + ret = cxgb4vf_change_mac(pi, pi->viid, &pi->xact_addr_filt, + addr->sa_data, true); if (ret < 0) return ret; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - pi->xact_addr_filt = ret; return 0; } -- cgit v1.2.3 From 13c6ee2a921683bae4bb4ba57b1f5b82f49e6b8a Mon Sep 17 00:00:00 2001 From: Deepa Dinamani Date: Sat, 2 Feb 2019 07:34:48 -0800 Subject: socket: Use old_timeval types for socket timestamps As part of y2038 solution, all internal uses of struct timeval are replaced by struct __kernel_old_timeval and struct compat_timeval by struct old_timeval32. Make socket timestamps use these new types. This is mainly to be able to verify that the kernel build is y2038 safe when such non y2038 safe types are not supported anymore. Signed-off-by: Deepa Dinamani Acked-by: Willem de Bruijn Cc: isdn@linux-pingi.de Signed-off-by: David S. Miller --- drivers/isdn/mISDN/socket.c | 2 +- include/linux/skbuff.h | 6 +++--- net/bluetooth/hci_sock.c | 4 ++-- net/compat.c | 6 +++--- net/ipv4/tcp.c | 2 +- net/rds/recv.c | 2 +- net/socket.c | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 15d3ca37669a..4ab8b1b6608f 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -103,7 +103,7 @@ mISDN_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) static inline void mISDN_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) { - struct timeval tv; + struct __kernel_old_timeval tv; if (_pms(sk)->cmask & MISDN_TIME_STAMP) { skb_get_timestamp(skb, &tv); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c34595374e93..4001611a4c9f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3486,16 +3486,16 @@ static inline ktime_t skb_get_ktime(const struct sk_buff *skb) /** * skb_get_timestamp - get timestamp from a skb * @skb: skb to get stamp from - * @stamp: pointer to struct timeval to store stamp in + * @stamp: pointer to struct __kernel_old_timeval to store stamp in * * Timestamps are stored in the skb as offsets to a base timestamp. * This function converts the offset back to a struct timeval and stores * it in stamp. */ static inline void skb_get_timestamp(const struct sk_buff *skb, - struct timeval *stamp) + struct __kernel_old_timeval *stamp) { - *stamp = ktime_to_timeval(skb->tstamp); + *stamp = ns_to_kernel_old_timeval(skb->tstamp); } static inline void skb_get_timestampns(const struct sk_buff *skb, diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 1506e1632394..65228bfa4487 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1383,9 +1383,9 @@ static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, if (mask & HCI_CMSG_TSTAMP) { #ifdef CONFIG_COMPAT - struct compat_timeval ctv; + struct old_timeval32 ctv; #endif - struct timeval tv; + struct __kernel_old_timeval tv; void *data; int len; diff --git a/net/compat.c b/net/compat.c index ccf93cd0e49b..9629f053d4fa 100644 --- a/net/compat.c +++ b/net/compat.c @@ -209,8 +209,8 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat { struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; struct compat_cmsghdr cmhdr; - struct compat_timeval ctv; - struct compat_timespec cts[3]; + struct old_timeval32 ctv; + struct old_timespec32 cts[3]; int cmlen; if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { @@ -220,7 +220,7 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat if (!COMPAT_USE_64BIT_TIME) { if (level == SOL_SOCKET && type == SO_TIMESTAMP_OLD) { - struct timeval *tv = (struct timeval *)data; + struct __kernel_old_timeval *tv = (struct __kernel_old_timeval *)data; ctv.tv_sec = tv->tv_sec; ctv.tv_usec = tv->tv_usec; data = &ctv; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index e29aec59cad1..3ce41b04c0f0 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1861,7 +1861,7 @@ static void tcp_update_recv_tstamps(struct sk_buff *skb, static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, struct scm_timestamping *tss) { - struct timeval tv; + struct __kernel_old_timeval tv; bool has_timestamping = false; if (tss->ts[0].tv_sec || tss->ts[0].tv_nsec) { diff --git a/net/rds/recv.c b/net/rds/recv.c index 04e30d63a159..435bf2320cd3 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -549,7 +549,7 @@ static int rds_cmsg_recv(struct rds_incoming *inc, struct msghdr *msg, if ((inc->i_rx_tstamp != 0) && sock_flag(rds_rs_to_sk(rs), SOCK_RCVTSTAMP)) { - struct timeval tv = ktime_to_timeval(inc->i_rx_tstamp); + struct __kernel_old_timeval tv = ns_to_kernel_old_timeval(inc->i_rx_tstamp); ret = put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD, sizeof(tv), &tv); if (ret) diff --git a/net/socket.c b/net/socket.c index 5087f9e40f3a..9cc281cdb9d9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -719,7 +719,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, if (need_software_tstamp) { if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) { - struct timeval tv; + struct __kernel_old_timeval tv; skb_get_timestamp(skb, &tv); put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD, sizeof(tv), &tv); -- cgit v1.2.3 From bff5731d43efbdf0bbd2d73cab32fe6435ea1046 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Fri, 1 Feb 2019 17:56:28 -0800 Subject: net: devlink: report cell size of shared buffers Shared buffer allocation is usually done in cell increments. Drivers will either round up the allocation or refuse the configuration if it's not an exact multiple of cell size. Drivers know exactly the cell size of shared buffer, so help out users by providing this information in dumps. Signed-off-by: Jakub Kicinski Reviewed-by: Dirk van der Merwe Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 1 + drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c | 1 + include/net/devlink.h | 1 + include/uapi/linux/devlink.h | 2 ++ net/core/devlink.c | 3 +++ 5 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 12c61e0cc570..80066f437a65 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -713,6 +713,7 @@ int mlxsw_sp_sb_pool_get(struct mlxsw_core *mlxsw_core, pool_info->pool_type = (enum devlink_sb_pool_type) dir; pool_info->size = mlxsw_sp_cells_bytes(mlxsw_sp, pr->size); pool_info->threshold_type = (enum devlink_sb_threshold_type) pr->mode; + pool_info->cell_size = mlxsw_sp->sb->cell_size; return 0; } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c b/drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c index 814360ed3a20..ea2e3f829aba 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_shared_buf.c @@ -48,6 +48,7 @@ int nfp_shared_buf_pool_get(struct nfp_pf *pf, unsigned int sb, u16 pool_index, pool_info->pool_type = le32_to_cpu(get_data.pool_type); pool_info->threshold_type = le32_to_cpu(get_data.threshold_type); pool_info->size = le32_to_cpu(get_data.size) * unit_size; + pool_info->cell_size = unit_size; return 0; } diff --git a/include/net/devlink.h b/include/net/devlink.h index 1c8523920f66..74d992a68a06 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -62,6 +62,7 @@ struct devlink_sb_pool_info { enum devlink_sb_pool_type pool_type; u32 size; enum devlink_sb_threshold_type threshold_type; + u32 cell_size; }; /** diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index 7fffd879c328..054b2d1a4537 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -300,6 +300,8 @@ enum devlink_attr { DEVLINK_ATTR_INFO_VERSION_NAME, /* string */ DEVLINK_ATTR_INFO_VERSION_VALUE, /* string */ + DEVLINK_ATTR_SB_POOL_CELL_SIZE, /* u32 */ + /* add new attributes above here, update the policy in devlink.c */ __DEVLINK_ATTR_MAX, diff --git a/net/core/devlink.c b/net/core/devlink.c index eb839d74bcc0..52bf27491fb8 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -932,6 +932,9 @@ static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, pool_info.threshold_type)) goto nla_put_failure; + if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE, + pool_info.cell_size)) + goto nla_put_failure; genlmsg_end(msg, hdr); return 0; -- cgit v1.2.3 From b37ecb595dff84f187dd651e435ecf634a5d7975 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 3 Feb 2019 21:16:18 +0100 Subject: net: phy: aquantia: Shorten name space prefix to aqr_ aquantia_ as a name space prefix is rather long, resulting in lots of lines needing wrapping, reducing readability. Use the prefix aqr_ instead, which fits with the vendor naming there devices aqr107, for example. v2: - add SoB from Heiner Signed-off-by: Andrew Lunn Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 64 +++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 0578fe75d3b6..880ec4bbac4d 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -22,7 +22,7 @@ #define PHY_ID_AQR107 0x03a1b4e0 #define PHY_ID_AQR405 0x03a1b4b0 -static int aquantia_config_aneg(struct phy_device *phydev) +static int aqr_config_aneg(struct phy_device *phydev) { linkmode_copy(phydev->supported, phy_10gbit_features); linkmode_copy(phydev->advertising, phydev->supported); @@ -30,7 +30,7 @@ static int aquantia_config_aneg(struct phy_device *phydev) return 0; } -static int aquantia_config_intr(struct phy_device *phydev) +static int aqr_config_intr(struct phy_device *phydev) { int err; @@ -59,7 +59,7 @@ static int aquantia_config_intr(struct phy_device *phydev) return err; } -static int aquantia_ack_interrupt(struct phy_device *phydev) +static int aqr_ack_interrupt(struct phy_device *phydev) { int reg; @@ -67,7 +67,7 @@ static int aquantia_ack_interrupt(struct phy_device *phydev) return (reg < 0) ? reg : 0; } -static int aquantia_read_status(struct phy_device *phydev) +static int aqr_read_status(struct phy_device *phydev) { int reg; @@ -102,17 +102,17 @@ static int aquantia_read_status(struct phy_device *phydev) return 0; } -static struct phy_driver aquantia_driver[] = { +static struct phy_driver aqr_driver[] = { { .phy_id = PHY_ID_AQ1202, .phy_id_mask = 0xfffffff0, .name = "Aquantia AQ1202", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, }, { .phy_id = PHY_ID_AQ2104, @@ -120,10 +120,10 @@ static struct phy_driver aquantia_driver[] = { .name = "Aquantia AQ2104", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, }, { .phy_id = PHY_ID_AQR105, @@ -131,10 +131,10 @@ static struct phy_driver aquantia_driver[] = { .name = "Aquantia AQR105", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, }, { .phy_id = PHY_ID_AQR106, @@ -142,10 +142,10 @@ static struct phy_driver aquantia_driver[] = { .name = "Aquantia AQR106", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, }, { .phy_id = PHY_ID_AQR107, @@ -153,10 +153,10 @@ static struct phy_driver aquantia_driver[] = { .name = "Aquantia AQR107", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, }, { .phy_id = PHY_ID_AQR405, @@ -164,16 +164,16 @@ static struct phy_driver aquantia_driver[] = { .name = "Aquantia AQR405", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, }, }; -module_phy_driver(aquantia_driver); +module_phy_driver(aqr_driver); -static struct mdio_device_id __maybe_unused aquantia_tbl[] = { +static struct mdio_device_id __maybe_unused aqr_tbl[] = { { PHY_ID_AQ1202, 0xfffffff0 }, { PHY_ID_AQ2104, 0xfffffff0 }, { PHY_ID_AQR105, 0xfffffff0 }, @@ -183,7 +183,7 @@ static struct mdio_device_id __maybe_unused aquantia_tbl[] = { { } }; -MODULE_DEVICE_TABLE(mdio, aquantia_tbl); +MODULE_DEVICE_TABLE(mdio, aqr_tbl); MODULE_DESCRIPTION("Aquantia PHY driver"); MODULE_AUTHOR("Shaohui Xie "); -- cgit v1.2.3 From 81e6578c16d1685c23c09525feccbce971ffd536 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 3 Feb 2019 21:17:14 +0100 Subject: net: phy: aquantia: remove unneeded includes Remove unneeded header includes. v2: - leave kernel.h in Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 880ec4bbac4d..2b349de1d281 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -10,10 +10,7 @@ #include #include #include -#include -#include #include -#include #define PHY_ID_AQ1202 0x03a1b445 #define PHY_ID_AQ2104 0x03a1b460 -- cgit v1.2.3 From 4d5dfb666c1b58206ba6eba3c6bee0c8d6264c3d Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 3 Feb 2019 21:18:03 +0100 Subject: net: phy: aquantia: use macro PHY_ID_MATCH_MODEL Make use of macro PHY_ID_MATCH_MODEL to simplify the code. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 2b349de1d281..fde4375065df 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -101,8 +101,7 @@ static int aqr_read_status(struct phy_device *phydev) static struct phy_driver aqr_driver[] = { { - .phy_id = PHY_ID_AQ1202, - .phy_id_mask = 0xfffffff0, + PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), .name = "Aquantia AQ1202", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, @@ -112,8 +111,7 @@ static struct phy_driver aqr_driver[] = { .read_status = aqr_read_status, }, { - .phy_id = PHY_ID_AQ2104, - .phy_id_mask = 0xfffffff0, + PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), .name = "Aquantia AQ2104", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, @@ -123,8 +121,7 @@ static struct phy_driver aqr_driver[] = { .read_status = aqr_read_status, }, { - .phy_id = PHY_ID_AQR105, - .phy_id_mask = 0xfffffff0, + PHY_ID_MATCH_MODEL(PHY_ID_AQR105), .name = "Aquantia AQR105", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, @@ -134,8 +131,7 @@ static struct phy_driver aqr_driver[] = { .read_status = aqr_read_status, }, { - .phy_id = PHY_ID_AQR106, - .phy_id_mask = 0xfffffff0, + PHY_ID_MATCH_MODEL(PHY_ID_AQR106), .name = "Aquantia AQR106", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, @@ -145,8 +141,7 @@ static struct phy_driver aqr_driver[] = { .read_status = aqr_read_status, }, { - .phy_id = PHY_ID_AQR107, - .phy_id_mask = 0xfffffff0, + PHY_ID_MATCH_MODEL(PHY_ID_AQR107), .name = "Aquantia AQR107", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, @@ -156,8 +151,7 @@ static struct phy_driver aqr_driver[] = { .read_status = aqr_read_status, }, { - .phy_id = PHY_ID_AQR405, - .phy_id_mask = 0xfffffff0, + PHY_ID_MATCH_MODEL(PHY_ID_AQR405), .name = "Aquantia AQR405", .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, @@ -171,12 +165,12 @@ static struct phy_driver aqr_driver[] = { module_phy_driver(aqr_driver); static struct mdio_device_id __maybe_unused aqr_tbl[] = { - { PHY_ID_AQ1202, 0xfffffff0 }, - { PHY_ID_AQ2104, 0xfffffff0 }, - { PHY_ID_AQR105, 0xfffffff0 }, - { PHY_ID_AQR106, 0xfffffff0 }, - { PHY_ID_AQR107, 0xfffffff0 }, - { PHY_ID_AQR405, 0xfffffff0 }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, { } }; -- cgit v1.2.3 From 278f6b674f9a2b4cff73c0c8d76fc696e28e8884 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 3 Feb 2019 21:19:06 +0100 Subject: net: phy: aquantia: replace magic numbers with constants Replace magic numbers with proper constants. The original patch is from Andrew, I extended / adjusted certain parts: - Use decimal bit numbers. The datasheet uses hex bit numbers 0 .. F. - Order defines from highest to lowest bit numbers - correct some typos - add constant MDIO_AN_TX_VEND_INT_MASK2_LINK - Remove few functional improvements from the patch, they will come as a separate patch. Signed-off-by: Andrew Lunn Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 80 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index fde4375065df..482004efa62d 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -19,6 +19,48 @@ #define PHY_ID_AQR107 0x03a1b4e0 #define PHY_ID_AQR405 0x03a1b4b0 +#define MDIO_AN_TX_VEND_STATUS1 0xc800 +#define MDIO_AN_TX_VEND_STATUS1_10BASET (0x0 << 1) +#define MDIO_AN_TX_VEND_STATUS1_100BASETX (0x1 << 1) +#define MDIO_AN_TX_VEND_STATUS1_1000BASET (0x2 << 1) +#define MDIO_AN_TX_VEND_STATUS1_10GBASET (0x3 << 1) +#define MDIO_AN_TX_VEND_STATUS1_2500BASET (0x4 << 1) +#define MDIO_AN_TX_VEND_STATUS1_5000BASET (0x5 << 1) +#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK (0x7 << 1) +#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) + +#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 + +#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 +#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) + +/* Vendor specific 1, MDIO_MMD_VEND1 */ +#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 + +#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) + +#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) + static int aqr_config_aneg(struct phy_device *phydev) { linkmode_copy(phydev->supported, phy_10gbit_features); @@ -32,25 +74,35 @@ static int aqr_config_intr(struct phy_device *phydev) int err; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { - err = phy_write_mmd(phydev, MDIO_MMD_AN, 0xd401, 1); + err = phy_write_mmd(phydev, MDIO_MMD_AN, + MDIO_AN_TX_VEND_INT_MASK2, + MDIO_AN_TX_VEND_INT_MASK2_LINK); if (err < 0) return err; - err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff00, 1); + err = phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_INT_STD_MASK, + VEND1_GLOBAL_INT_STD_MASK_ALL); if (err < 0) return err; - err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff01, 0x1001); + err = phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_INT_VEND_MASK, + VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | + VEND1_GLOBAL_INT_VEND_MASK_AN); } else { - err = phy_write_mmd(phydev, MDIO_MMD_AN, 0xd401, 0); + err = phy_write_mmd(phydev, MDIO_MMD_AN, + MDIO_AN_TX_VEND_INT_MASK2, 0); if (err < 0) return err; - err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff00, 0); + err = phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_INT_STD_MASK, 0); if (err < 0) return err; - err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff01, 0); + err = phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_INT_VEND_MASK, 0); } return err; @@ -60,7 +112,8 @@ static int aqr_ack_interrupt(struct phy_device *phydev) { int reg; - reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xcc01); + reg = phy_read_mmd(phydev, MDIO_MMD_AN, + MDIO_AN_TX_VEND_INT_STATUS2); return (reg < 0) ? reg : 0; } @@ -75,21 +128,20 @@ static int aqr_read_status(struct phy_device *phydev) else phydev->link = 0; - reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800); + reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); mdelay(10); - reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800); + reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); - switch (reg) { - case 0x9: + switch (reg & MDIO_AN_TX_VEND_STATUS1_RATE_MASK) { + case MDIO_AN_TX_VEND_STATUS1_2500BASET: phydev->speed = SPEED_2500; break; - case 0x5: + case MDIO_AN_TX_VEND_STATUS1_1000BASET: phydev->speed = SPEED_1000; break; - case 0x3: + case MDIO_AN_TX_VEND_STATUS1_100BASETX: phydev->speed = SPEED_100; break; - case 0x7: default: phydev->speed = SPEED_10000; break; -- cgit v1.2.3 From 96972d24fa6d6aa163e82cff213c1280df0f958c Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Thu, 6 Sep 2018 17:56:58 +0300 Subject: iwlwifi: bump FW API to 44 for 9000 and 22000 series Start supporting API version 44 where applicable. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index eb93711d474b..c547288d32aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -56,7 +56,7 @@ #include "iwl-config.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 43 +#define IWL_22000_UCODE_API_MAX 44 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 39 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 113bcf7735a0..84adfd902002 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -57,7 +57,7 @@ #include "fw/file.h" /* Highest firmware API version supported */ -#define IWL9000_UCODE_API_MAX 43 +#define IWL9000_UCODE_API_MAX 44 /* Lowest firmware API version supported */ #define IWL9000_UCODE_API_MIN 30 -- cgit v1.2.3 From a9f802b63d00b333bd28e1378c2d1acbbe06bd1c Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 26 Nov 2018 10:23:11 +0200 Subject: iwlwifi dbg_ini: update ini structs doc update ini struct documentation to the structs being used in the FW Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index ab82b7a67967..b7525d62e26f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -155,20 +155,20 @@ struct iwl_fw_ini_region_cfg { }; __le32 size; __le32 start_addr[]; -} __packed; /* FW_INI_REGION_CONFIG_S */ +} __packed; /* FW_DEBUG_TLV_REGION_CONFIG_S */ /** * struct iwl_fw_ini_region_tlv - (IWL_FW_INI_TLV_TYPE_REGION_CFG) * DUMP sections define IDs and triggers that use those IDs TLV * @header: header * @num_regions: how many different region section and IDs are coming next - * @iwl_fw_ini_dump dump_config: list of dump configurations + * @region_config: list of dump configurations */ struct iwl_fw_ini_region_tlv { struct iwl_fw_ini_header header; __le32 num_regions; struct iwl_fw_ini_region_cfg region_config[]; -} __packed; /* FW_INI_REGION_CFG_S */ +} __packed; /* FW_DEBUG_TLV_REGIONS_S_VER_1 */ /** * struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG) @@ -196,7 +196,7 @@ struct iwl_fw_ini_trigger { __le32 trigger_data; __le32 num_regions; __le32 data[]; -} __packed; /* FW_INI_TRIGGER_CONFIG_S */ +} __packed; /* FW_TLV_DEBUG_TRIGGER_CONFIG_S */ /** * struct iwl_fw_ini_trigger_tlv - (IWL_FW_INI_TLV_TYPE_TRIGGERS_CFG) @@ -210,7 +210,7 @@ struct iwl_fw_ini_trigger_tlv { struct iwl_fw_ini_header header; __le32 num_triggers; struct iwl_fw_ini_trigger trigger_config[]; -} __packed; /* FW_INI_TRIGGER_CFG_S */ +} __packed; /* FW_TLV_DEBUG_TRIGGERS_S_VER_1 */ /** * enum iwl_fw_ini_trigger_id -- cgit v1.2.3 From 56ea8e3b4ef6a319ac8297bc50f6909dccc684ec Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 26 Nov 2018 10:25:44 +0200 Subject: iwlwifi: dbg_ini: fix iwl_fw_ini_buffer_location field enum bad naming change IWL_FW_INI_LOCATION_SRAM_INVALID into IWL_FW_INI_LOCATION_INVALID Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index b7525d62e26f..a2c4a28c46a3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -349,7 +349,7 @@ enum iwl_fw_ini_allocation_id { * @IWL_FW_INI_LOCATION_DRAM_PATH: DRAM location */ enum iwl_fw_ini_buffer_location { - IWL_FW_INI_LOCATION_SRAM_INVALID, + IWL_FW_INI_LOCATION_INVALID, IWL_FW_INI_LOCATION_SRAM_PATH, IWL_FW_INI_LOCATION_DRAM_PATH, }; /* FW_INI_BUFFER_LOCATION_E_VER_1 */ -- cgit v1.2.3 From bb0306bd6fa2ef6f4d596cc1e31e7e37ad5f48a3 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 26 Nov 2018 10:15:35 +0200 Subject: iwlwifi: dbg_ini: give better naming to region struct fields Some of the region struct fields have misleading naming change those fields to have an informative naming Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 12 +++++++----- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 21 +++++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index a2c4a28c46a3..2b4b902cffc4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -138,11 +138,13 @@ struct iwl_fw_ini_debug_flow_tlv { * @region_id: ID of this dump configuration * @region_type: &enum iwl_fw_ini_region_type * @num_regions: amount of regions in the address array. - * @allocation_id: For DRAM type field substitutes for allocation_id. * @name_len: name length * @name: file name to use for this region - * @size: size of the data, in bytes.(unused for IWL_FW_INI_REGION_DRAM_BUFFER) - * @start_addr: array of addresses. (unused for IWL_FW_INI_REGION_DRAM_BUFFER) + * @num_of_range: the amount of ranges in the region. + * @allocation_id: For DRAM type field substitutes for allocation_id + * @range_data_size: size of the data to read per range, in bytes. + * @start_addr: array of addresses. for type IWL_FW_INI_REGION_DRAM_BUFFER, + * 1 entry. For any other case, num_of_ranges entries. */ struct iwl_fw_ini_region_cfg { __le32 region_id; @@ -150,10 +152,10 @@ struct iwl_fw_ini_region_cfg { __le32 name_len; u8 name[IWL_FW_INI_MAX_NAME]; union { - __le32 num_regions; + __le32 num_of_ranges; __le32 allocation_id; }; - __le32 size; + __le32 range_data_size; __le32 start_addr[]; } __packed; /* FW_DEBUG_TLV_REGION_CONFIG_S */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 22efd94da6d3..35c2b1a23d10 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1065,7 +1065,7 @@ static void iwl_dump_prph_ini(struct iwl_trans *trans, { struct iwl_fw_error_dump_prph *prph; unsigned long flags; - u32 i, size = le32_to_cpu(reg->num_regions); + u32 i, size = le32_to_cpu(reg->num_of_ranges); IWL_DEBUG_INFO(trans, "WRT PRPH dump\n"); @@ -1074,7 +1074,7 @@ static void iwl_dump_prph_ini(struct iwl_trans *trans, for (i = 0; i < size; i++) { (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); - (*data)->len = cpu_to_le32(le32_to_cpu(reg->size) + + (*data)->len = cpu_to_le32(le32_to_cpu(reg->range_data_size) + sizeof(*prph)); prph = (void *)(*data)->data; prph->prph_start = reg->start_addr[i]; @@ -1089,8 +1089,8 @@ static void iwl_dump_csr_ini(struct iwl_trans *trans, struct iwl_fw_error_dump_data **data, struct iwl_fw_ini_region_cfg *reg) { - int i, num = le32_to_cpu(reg->num_regions); - u32 size = le32_to_cpu(reg->size); + int i, num = le32_to_cpu(reg->num_of_ranges); + u32 size = le32_to_cpu(reg->range_data_size); IWL_DEBUG_INFO(trans, "WRT CSR dump\n"); @@ -1133,13 +1133,13 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, continue; type = le32_to_cpu(reg->region_type); - num_entries = le32_to_cpu(reg->num_regions); + num_entries = le32_to_cpu(reg->num_of_ranges); switch (type) { case IWL_FW_INI_REGION_DEVICE_MEMORY: size += hdr_len + sizeof(struct iwl_fw_error_dump_named_mem) + - le32_to_cpu(reg->size); + le32_to_cpu(reg->range_data_size); break; case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: @@ -1165,7 +1165,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, break; case IWL_FW_INI_REGION_CSR: size += num_entries * - (hdr_len + le32_to_cpu(reg->size)); + (hdr_len + le32_to_cpu(reg->range_data_size)); break; case IWL_FW_INI_REGION_DRAM_BUFFER: /* Transport takes care of DRAM dumping */ @@ -1202,10 +1202,10 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, type = le32_to_cpu(reg->region_type); switch (type) { case IWL_FW_INI_REGION_DEVICE_MEMORY: - if (WARN_ON(le32_to_cpu(reg->num_regions) > 1)) + if (WARN_ON(le32_to_cpu(reg->num_of_ranges) > 1)) continue; iwl_fw_dump_named_mem(fwrt, data, - le32_to_cpu(reg->size), + le32_to_cpu(reg->range_data_size), le32_to_cpu(reg->start_addr[0]), reg->name, le32_to_cpu(reg->name_len)); @@ -1773,7 +1773,8 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, if (le32_to_cpu(reg->region_type) != IWL_FW_INI_REGION_DRAM_BUFFER) - iter += le32_to_cpu(reg->num_regions) * sizeof(__le32); + iter += le32_to_cpu(reg->num_of_ranges) * + sizeof(__le32); iter += sizeof(*reg); } -- cgit v1.2.3 From 7e316572c9c547d5c8b9d86abb37576e2e5a470c Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 20 Nov 2018 09:46:33 +0200 Subject: iwlwifi: fix bad dma handling in page_mem dumping flow Prior to gen2 we allocate the paging memory via alloc_pages which requires passing ownership on the memory between the cpu and the device using dma_sync_single_for_cpu and dma_sync_single_for_device. Add missing dma_sync_single_for_device in iwl_dump_paging after copying the memory. since gen2, we allocate the paging memory using dma_alloc_coherent which does not need passing ownership between the cpu and device. Remove unneeded call to dma_sync_single_for_cpu in iwl_trans_pcie_dump_data prior to copying the memory. Signed-off-by: Shahar S Matityahu Fixes: 5538409ba393 ("iwlwifi: pcie: support page dumping in wrt in gen2") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 3 +++ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 35c2b1a23d10..d16a8a4f0c3f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -815,6 +815,9 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt, DMA_BIDIRECTIONAL); memcpy(paging->data, page_address(pages), PAGING_BLOCK_SIZE); + dma_sync_single_for_device(fwrt->trans->dev, addr, + PAGING_BLOCK_SIZE, + DMA_BIDIRECTIONAL); (*data) = iwl_fw_error_next_data(*data); } } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index f74281508197..f26664b0f0f8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3277,16 +3277,12 @@ static struct iwl_trans_dump_data if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) { for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) { struct iwl_fw_error_dump_paging *paging; - dma_addr_t addr = - trans_pcie->init_dram.paging[i].physical; u32 page_len = trans_pcie->init_dram.paging[i].size; data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); data->len = cpu_to_le32(sizeof(*paging) + page_len); paging = (void *)data->data; paging->index = cpu_to_le32(i); - dma_sync_single_for_cpu(trans->dev, addr, page_len, - DMA_BIDIRECTIONAL); memcpy(paging->data, trans_pcie->init_dram.paging[i].block, page_len); data = iwl_fw_error_next_data(data); -- cgit v1.2.3 From b2c1bf597ffa7bab523990763fd50a692b53a48a Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Fri, 16 Nov 2018 11:18:26 +0200 Subject: iwlwifi: mvm: simplify some return conditions Simplify some return conditions found by running a semantic patch to detect unnecessary assignments to local variables. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/coex.c | 7 ++----- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 5 ++--- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 9 +++------ 3 files changed, 7 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c index 730e37744dc0..3d2abbc5c76c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c @@ -241,7 +241,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, struct iwl_bt_coex_reduced_txp_update_cmd cmd = {}; struct iwl_mvm_sta *mvmsta; u32 value; - int ret; mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id); if (!mvmsta) @@ -262,10 +261,8 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, cmd.reduced_txp = cpu_to_le32(value); mvmsta->bt_reduced_txpower = enable; - ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP, CMD_ASYNC, - sizeof(cmd), &cmd); - - return ret; + return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_REDUCED_TXP, + CMD_ASYNC, sizeof(cmd), &cmd); } struct iwl_bt_iterator_data { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 86d598d5b68f..af8156ba8084 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1976,9 +1976,8 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type) return ret; } - ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ); - - return ret; + return iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, + 1 * HZ); } int iwl_mvm_scan_size(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index c5a01470a3bc..a102a16a15f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -314,7 +314,6 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue, struct iwl_mvm_sta *mvmsta; u32 status; u8 sta_id; - int ret; if (WARN_ON(iwl_mvm_has_new_tx_api(mvm))) return -EINVAL; @@ -349,11 +348,9 @@ static int iwl_mvm_invalidate_sta_queue(struct iwl_mvm *mvm, int queue, /* Notify FW of queue removal from the STA queues */ status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, - iwl_mvm_add_sta_cmd_size(mvm), - &cmd, &status); - - return ret; + return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), + &cmd, &status); } static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, -- cgit v1.2.3 From 74a102521208554e0daf52b0aeb742c066ad1e34 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 25 Oct 2018 14:12:05 +0300 Subject: iwlwifi: mvm: support CHANNEL_SWITCH_TIME_EVENT_CMD command When we do channel switch, we used to schedule time events ourselves. This was offloaded to FW. Support the new command and flow. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/mac-cfg.h | 27 ++++++++ drivers/net/wireless/intel/iwlwifi/fw/file.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 58 +++++++++++------- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 71 ++++++++++++++++------ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + 5 files changed, 119 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index ca49db786ed6..6b4d59daacd6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -73,6 +73,10 @@ enum iwl_mac_conf_subcmd_ids { * @LOW_LATENCY_CMD: &struct iwl_mac_low_latency_cmd */ LOW_LATENCY_CMD = 0x3, + /** + * @CHANNEL_SWITCH_TIME_EVENT_CMD: &struct iwl_chan_switch_te_cmd + */ + CHANNEL_SWITCH_TIME_EVENT_CMD = 0x4, /** * @PROBE_RESPONSE_DATA_NOTIF: &struct iwl_probe_resp_data_notif */ @@ -135,6 +139,29 @@ struct iwl_channel_switch_noa_notif { __le32 id_and_color; } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */ +/** + * struct iwl_chan_switch_te_cmd - Channel Switch Time Event command + * + * @mac_id: MAC ID for channel switch + * @action: action to perform, one of FW_CTXT_ACTION_* + * @tsf: beacon tsf + * @cs_count: channel switch count from CSA/eCSA IE + * @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals + * at the new channel after the channel switch, otherwise (N == 0) expect + * beacon right after the channel switch. + * @cs_mode: 1 - quiet, 0 - otherwise + * @reserved: reserved for alignment purposes + */ +struct iwl_chan_switch_te_cmd { + __le32 mac_id; + __le32 action; + __le32 tsf; + u8 cs_count; + u8 cs_delayed_bcn_count; + u8 cs_mode; + u8 reserved; +} __packed; /* MAC_CHANNEL_SWITCH_TIME_EVENT_S_VER_2 */ + /** * struct iwl_mac_low_latency_cmd - set/clear mac to 'low-latency mode' * diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index e8b00b795cbb..db392cfc2bd4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -333,6 +333,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_TLC_OFFLOAD: firmware implements rate scaling algorithm * @IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA: firmware implements quota related * @IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2: firmware implements Coex Schema 2 + * IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD: firmware supports CSA command * @IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS: firmware supports ultra high band * (6 GHz). * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement @@ -397,6 +398,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_TLC_OFFLOAD = (__force iwl_ucode_tlv_capa_t)43, IWL_UCODE_TLV_CAPA_DYNAMIC_QUOTA = (__force iwl_ucode_tlv_capa_t)44, IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45, + IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46, IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48, IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 7cfdd07d8736..768a87e0a1c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1539,42 +1539,58 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm, { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data; - struct ieee80211_vif *csa_vif; + struct ieee80211_vif *csa_vif, *vif; struct iwl_mvm_vif *mvmvif; int len = iwl_rx_packet_payload_len(pkt); - u32 id_n_color; + u32 id_n_color, csa_id, mac_id; if (WARN_ON_ONCE(len < sizeof(*notif))) return; - rcu_read_lock(); - - csa_vif = rcu_dereference(mvm->csa_vif); - if (WARN_ON(!csa_vif || !csa_vif->csa_active)) - goto out_unlock; - id_n_color = le32_to_cpu(notif->id_and_color); + mac_id = id_n_color & FW_CTXT_ID_MSK; - mvmvif = iwl_mvm_vif_from_mac80211(csa_vif); - if (WARN(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color) != id_n_color, - "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", - FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color), id_n_color)) - goto out_unlock; + if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER)) + return; - IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n"); + rcu_read_lock(); + vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]); - schedule_delayed_work(&mvm->cs_tx_unblock_dwork, - msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT * - csa_vif->bss_conf.beacon_int)); + switch (vif->type) { + case NL80211_IFTYPE_AP: + csa_vif = rcu_dereference(mvm->csa_vif); + if (WARN_ON(!csa_vif || !csa_vif->csa_active || + csa_vif != vif)) + goto out_unlock; - ieee80211_csa_finish(csa_vif); + mvmvif = iwl_mvm_vif_from_mac80211(csa_vif); + csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); + if (WARN(csa_id != id_n_color, + "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", + csa_id, id_n_color)) + goto out_unlock; - rcu_read_unlock(); + IWL_DEBUG_INFO(mvm, "Channel Switch Started Notification\n"); - RCU_INIT_POINTER(mvm->csa_vif, NULL); + schedule_delayed_work(&mvm->cs_tx_unblock_dwork, + msecs_to_jiffies(IWL_MVM_CS_UNBLOCK_TX_TIMEOUT * + csa_vif->bss_conf.beacon_int)); - return; + ieee80211_csa_finish(csa_vif); + rcu_read_unlock(); + + RCU_INIT_POINTER(mvm->csa_vif, NULL); + return; + case NL80211_IFTYPE_STATION: + iwl_mvm_csa_client_absent(mvm, vif); + ieee80211_chswitch_done(vif, true); + break; + default: + /* should never happen */ + WARN_ON_ONCE(1); + break; + } out_unlock: rcu_read_unlock(); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index c9effd7f0ef8..8837d7667f36 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3953,25 +3953,30 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, } if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) { - u32 duration = 3 * vif->bss_conf.beacon_int; + mvmvif->csa_bcn_pending = true; - /* iwl_mvm_protect_session() reads directly from the - * device (the system time), so make sure it is - * available. - */ - ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA); - if (ret) - goto out_remove_binding; + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) { + u32 duration = 3 * vif->bss_conf.beacon_int; - /* Protect the session to make sure we hear the first - * beacon on the new channel. - */ - mvmvif->csa_bcn_pending = true; - iwl_mvm_protect_session(mvm, vif, duration, duration, - vif->bss_conf.beacon_int / 2, - true); - iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA); + /* iwl_mvm_protect_session() reads directly from the + * device (the system time), so make sure it is + * available. + */ + ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA); + if (ret) + goto out_remove_binding; + + /* Protect the session to make sure we hear the first + * beacon on the new channel. + */ + iwl_mvm_protect_session(mvm, vif, duration, duration, + vif->bss_conf.beacon_int / 2, + true); + + iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA); + } iwl_mvm_update_quotas(mvm, false, NULL); } @@ -4041,7 +4046,9 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm, disabled_vif = vif; - iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL); + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) + iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL); break; default: break; @@ -4292,6 +4299,27 @@ static void iwl_mvm_channel_switch(struct ieee80211_hw *hw, "dummy channel switch op\n"); } +static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_channel_switch *chsw) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_chan_switch_te_cmd cmd = { + .mac_id = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, + mvmvif->color)), + .action = cpu_to_le32(FW_CTXT_ACTION_ADD), + .tsf = cpu_to_le32(chsw->timestamp), + .cs_count = chsw->count, + }; + + lockdep_assert_held(&mvm->mutex); + + return iwl_mvm_send_cmd_pdu(mvm, + WIDE_ID(MAC_CONF_GROUP, + CHANNEL_SWITCH_TIME_EVENT_CMD), + 0, sizeof(cmd), &cmd); +} + static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel_switch *chsw) @@ -4359,14 +4387,19 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, if (chsw->block_tx) iwl_mvm_csa_client_absent(mvm, vif); - iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int, - apply_time); if (mvmvif->bf_data.bf_enabled) { ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); if (ret) goto out_unlock; } + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) + iwl_mvm_schedule_client_csa(mvm, vif, chsw); + else + iwl_mvm_schedule_csa_period(mvm, vif, + vif->bss_conf.beacon_int, + apply_time); break; default: break; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 5e4f8b767d10..e56b31692a20 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -421,6 +421,7 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = { * Access is done through binary search */ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = { + HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD), HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF), }; -- cgit v1.2.3 From 67b8261c49a050dccd776f13b28816dcea226d0c Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 22 Nov 2018 09:12:08 +0200 Subject: iwlwifi: differentiate between alive timeout and alive flow failure There are two cases that can cause the alive flow to fail, an assert or a timeout. Currently we mask any incoming asserts when we wait for alive. Solve this by differentiating between the two cases: 1. Let the regular error handling to handle a received assert 2. Do a dump collection in the case of a timeout Signed-off-by: Shahar S Matityahu Fixes: f38efdb29389 ("iwlwifi: add dump collection in case alive flow fails") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 31 +++++++++++++--------- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 2 +- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 4 +-- drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 1 - drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 5 ++-- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 -- 6 files changed, 24 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index d16a8a4f0c3f..0edc5bcdfb82 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1373,29 +1373,35 @@ void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt) } IWL_EXPORT_SYMBOL(iwl_fw_assert_error_dump); -void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt) +void iwl_fw_alive_timeout_dump(struct iwl_fw_runtime *fwrt) { - struct iwl_fw_dump_desc *iwl_dump_desc_no_alive = - kmalloc(sizeof(*iwl_dump_desc_no_alive), GFP_KERNEL); + struct iwl_fw_dump_desc *iwl_dump_desc_alive_timeout; - if (!iwl_dump_desc_no_alive) + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) return; - iwl_dump_desc_no_alive->trig_desc.type = - cpu_to_le32(FW_DBG_TRIGGER_NO_ALIVE); - iwl_dump_desc_no_alive->len = 0; + iwl_dump_desc_alive_timeout = + kmalloc(sizeof(*iwl_dump_desc_alive_timeout), GFP_KERNEL); + if (!iwl_dump_desc_alive_timeout) + return; + + iwl_dump_desc_alive_timeout->trig_desc.type = + cpu_to_le32(FW_DBG_TRIGGER_ALIVE_TIMEOUT); + iwl_dump_desc_alive_timeout->len = 0; if (WARN_ON(fwrt->dump.desc)) iwl_fw_free_dump_desc(fwrt); IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n", - FW_DBG_TRIGGER_NO_ALIVE); + FW_DBG_TRIGGER_ALIVE_TIMEOUT); + + /* set STATUS_FW_ERROR to collect all memory regions. */ + set_bit(STATUS_FW_ERROR, &fwrt->trans->status); - fwrt->dump.desc = iwl_dump_desc_no_alive; + fwrt->dump.desc = iwl_dump_desc_alive_timeout; iwl_fw_error_dump(fwrt); - clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status); } -IWL_EXPORT_SYMBOL(iwl_fw_alive_error_dump); +IWL_EXPORT_SYMBOL(iwl_fw_alive_timeout_dump); int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, const struct iwl_fw_dump_desc *desc, @@ -1418,8 +1424,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, fwrt->smem_cfg.num_lmacs) return -EIO; - if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status) || - test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &fwrt->status)) + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) return -EBUSY; if (WARN_ON(fwrt->dump.desc)) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 330229d2a61d..36e0f40dab3b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -435,7 +435,7 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {} #endif /* CONFIG_IWLWIFI_DEBUGFS */ void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt); -void iwl_fw_alive_error_dump(struct iwl_fw_runtime *fwrt); +void iwl_fw_alive_timeout_dump(struct iwl_fw_runtime *fwrt); void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt); void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, enum iwl_fw_ini_apply_point apply_point); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index c02425a1e64f..d06707f3a2a4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -355,7 +355,7 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data) * @FW_DBG_TDLS: trigger log collection upon TDLS related events. * @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when * the firmware sends a tx reply. - * @FW_DBG_TRIGGER_NO_ALIVE: trigger log collection if alive flow fails + * @FW_DBG_TRIGGER_ALIVE_TIMEOUT: trigger log collection if alive flow timeouts */ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_INVALID = 0, @@ -373,7 +373,7 @@ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_TX_LATENCY, FW_DBG_TRIGGER_TDLS, FW_DBG_TRIGGER_TX_STATUS, - FW_DBG_TRIGGER_NO_ALIVE, + FW_DBG_TRIGGER_ALIVE_TIMEOUT, /* must be last */ FW_DBG_TRIGGER_MAX, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index a0fcbb28114b..9ff04ffba3fa 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -90,7 +90,6 @@ struct iwl_fwrt_shared_mem_cfg { enum iwl_fw_runtime_status { IWL_FWRT_STATUS_DUMPING = 0, - IWL_FWRT_STATUS_WAIT_ALIVE, }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index d3dc9d276e0f..25c8cea1180e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -299,7 +299,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img; static const u16 alive_cmd[] = { MVM_ALIVE }; - set_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status); if (ucode_type == IWL_UCODE_REGULAR && iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) && !(fw_has_capa(&mvm->fw->ucode_capa, @@ -332,6 +331,9 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, if (ret) { struct iwl_trans *trans = mvm->trans; + if (ret == -ETIMEDOUT) + iwl_fw_alive_timeout_dump(&mvm->fwrt); + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) IWL_ERR(mvm, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", @@ -377,7 +379,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, #ifdef CONFIG_IWLWIFI_DEBUGFS iwl_fw_set_dbg_rec_on(&mvm->fwrt); #endif - clear_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status); return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index e56b31692a20..a2719a75249a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -818,8 +818,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mutex_lock(&mvm->mutex); iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE); err = iwl_run_init_mvm_ucode(mvm, true); - if (test_bit(IWL_FWRT_STATUS_WAIT_ALIVE, &mvm->fwrt.status)) - iwl_fw_alive_error_dump(&mvm->fwrt); if (!iwlmvm_mod_params.init_dbg || !err) iwl_mvm_stop_device(mvm); iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE); -- cgit v1.2.3 From ffb677dc9816c3431ad13dc893810efa9c5f34c6 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 29 Nov 2018 17:53:09 +0200 Subject: iwlwifi: dbg_ini: update ini triggers enum Align the triggers enum in the driver to the one in the FW. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 92 +++++++++++----------- 1 file changed, 46 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index 2b4b902cffc4..422f4333ba35 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -217,15 +217,12 @@ struct iwl_fw_ini_trigger_tlv { /** * enum iwl_fw_ini_trigger_id * @IWL_FW_TRIGGER_ID_FW_ASSERT: FW assert - * @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang * @IWL_FW_TRIGGER_ID_FW_HW_ERROR: HW assert - * @IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR: FW error notification - * @IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING: FW warning notification - * @IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO: FW info notification - * @IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG: FW debug notification + * @IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG: TFD queue hang + * @IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER: FW debug notification + * @IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION: FW generic notification * @IWL_FW_TRIGGER_ID_USER_TRIGGER: User trigger * @IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY: peer inactivity - * @FW_DEBUG_TLV_TRIGGER_ID_HOST_DID_INITIATED_EVENT: undefined * @IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED: TX latency * threshold was crossed * @IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED: TX failed @@ -259,50 +256,53 @@ struct iwl_fw_ini_trigger_tlv { * @IWL_FW_TRIGGER_ID_NUM: number of trigger IDs */ enum iwl_fw_ini_trigger_id { + IWL_FW_TRIGGER_ID_INVALID = 0, + /* Errors triggers */ IWL_FW_TRIGGER_ID_FW_ASSERT = 1, - IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 2, - IWL_FW_TRIGGER_ID_FW_HW_ERROR = 3, - /* Generic triggers */ - IWL_FW_TRIGGER_ID_FW_TRIGGER_ERROR = 4, - IWL_FW_TRIGGER_ID_FW_TRIGGER_WARNING = 5, - IWL_FW_TRIGGER_ID_FW_TRIGGER_INFO = 6, - IWL_FW_TRIGGER_ID_FW_TRIGGER_DEBUG = 7, - /* User Trigger */ - IWL_FW_TRIGGER_ID_USER_TRIGGER = 8, + IWL_FW_TRIGGER_ID_FW_HW_ERROR = 2, + IWL_FW_TRIGGER_ID_FW_TFD_Q_HANG = 3, + + /* FW triggers */ + IWL_FW_TRIGGER_ID_FW_DEBUG_HOST_TRIGGER = 4, + IWL_FW_TRIGGER_ID_FW_GENERIC_NOTIFOCATION = 5, + + /* User trigger */ + IWL_FW_TRIGGER_ID_USER_TRIGGER = 6, + /* Host triggers */ - IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 9, - IWL_FW_TRIGGER_ID_HOST_DID_INITIATED_EVENT = 10, - IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 11, - IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 12, - IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 13, - IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 14, - IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 15, - IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 16, - IWL_FW_TRIGGER_ID_HOST_SCAN_START = 17, - IWL_FW_TRIGGER_ID_HOST_SCAN_SUBITTED = 18, - IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 19, - IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 20, - IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 21, - IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 22, - IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 23, - IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 24, - IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 25, - IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 26, - IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 27, - IWL_FW_TRIGGER_ID_HOST_D3_START = 28, - IWL_FW_TRIGGER_ID_HOST_D3_END = 29, - IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 30, - IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 31, - IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 32, - IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 33, - IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 34, - IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 35, - IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 36, - IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 37, - IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 38, + IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_INACTIVITY = 7, + IWL_FW_TRIGGER_ID_HOST_TX_LATENCY_THRESHOLD_CROSSED = 8, + IWL_FW_TRIGGER_ID_HOST_TX_RESPONSE_STATUS_FAILED = 9, + IWL_FW_TRIGGER_ID_HOST_OS_REQ_DEAUTH_PEER = 10, + IWL_FW_TRIGGER_ID_HOST_STOP_GO_REQUEST = 11, + IWL_FW_TRIGGER_ID_HOST_START_GO_REQUEST = 12, + IWL_FW_TRIGGER_ID_HOST_JOIN_GROUP_REQUEST = 13, + IWL_FW_TRIGGER_ID_HOST_SCAN_START = 14, + IWL_FW_TRIGGER_ID_HOST_SCAN_SUBMITTED = 15, + IWL_FW_TRIGGER_ID_HOST_SCAN_PARAMS = 16, + IWL_FW_TRIGGER_ID_HOST_CHECK_FOR_HANG = 17, + IWL_FW_TRIGGER_ID_HOST_BAR_RECEIVED = 18, + IWL_FW_TRIGGER_ID_HOST_AGG_TX_RESPONSE_STATUS_FAILED = 19, + IWL_FW_TRIGGER_ID_HOST_EAPOL_TX_RESPONSE_FAILED = 20, + IWL_FW_TRIGGER_ID_HOST_FAKE_TX_RESPONSE_SUSPECTED = 21, + IWL_FW_TRIGGER_ID_HOST_AUTH_REQ_FROM_ASSOC_CLIENT = 22, + IWL_FW_TRIGGER_ID_HOST_ROAM_COMPLETE = 23, + IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAST_FAILED = 24, + IWL_FW_TRIGGER_ID_HOST_D3_START = 25, + IWL_FW_TRIGGER_ID_HOST_D3_END = 26, + IWL_FW_TRIGGER_ID_HOST_BSS_MISSED_BEACONS = 27, + IWL_FW_TRIGGER_ID_HOST_P2P_CLIENT_MISSED_BEACONS = 28, + IWL_FW_TRIGGER_ID_HOST_PEER_CLIENT_TX_FAILURES = 29, + IWL_FW_TRIGGER_ID_HOST_TX_WFD_ACTION_FRAME_FAILED = 30, + IWL_FW_TRIGGER_ID_HOST_AUTH_ASSOC_FAILED = 31, + IWL_FW_TRIGGER_ID_HOST_SCAN_COMPLETE = 32, + IWL_FW_TRIGGER_ID_HOST_SCAN_ABORT = 33, + IWL_FW_TRIGGER_ID_HOST_NIC_ALIVE = 34, + IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE = 35, + IWL_FW_TRIGGER_ID_NUM, -}; /* FW_INI_TRIGGER_ID_E_VER_1 */ +}; /* FW_DEBUG_TLV_TRIGGER_ID_E_VER_1 */ /** * enum iwl_fw_ini_apply_point -- cgit v1.2.3 From 2d0c66083d3f9d17e5c107c4427523d3acdd31ce Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 27 Nov 2018 07:42:33 +0200 Subject: iwlwifi: dbg_ini: update max region id num to support 64 regions The driver should support 64 region ids. Update IWL_FW_INI_MAX_REGION_ID accordingly. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index 422f4333ba35..b2ab675b3cf8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -131,7 +131,7 @@ struct iwl_fw_ini_debug_flow_tlv { __le32 debug_flow_cfg; } __packed; /* FW_INI_DEBUG_FLOW_TLV_S_VER_1 */ -#define IWL_FW_INI_MAX_REGION_ID 20 +#define IWL_FW_INI_MAX_REGION_ID 64 #define IWL_FW_INI_MAX_NAME 32 /** * struct iwl_fw_ini_region_cfg -- cgit v1.2.3 From 15e28c78c3864cd7694bc7fca5142ff1f3f8d0e7 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 26 Nov 2018 13:24:55 +0200 Subject: iwlwifi: mvm: support new format for the beacon notification The firmware is changing the format of the beacon notification to remove the dependency on the Tx response format. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/tx.h | 18 ++++++++++-- drivers/net/wireless/intel/iwlwifi/fw/file.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 35 +++++++++++++++-------- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 ++++ 4 files changed, 48 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h index 358bdf051e83..8511e735c374 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h @@ -847,19 +847,33 @@ struct iwl_beacon_notif { } __packed; /** - * struct iwl_extended_beacon_notif - notifies about beacon transmission + * struct iwl_extended_beacon_notif_v5 - notifies about beacon transmission * @beacon_notify_hdr: tx response command associated with the beacon * @tsf: last beacon tsf * @ibss_mgr_status: whether IBSS is manager * @gp2: last beacon time in gp2 */ -struct iwl_extended_beacon_notif { +struct iwl_extended_beacon_notif_v5 { struct iwl_mvm_tx_resp beacon_notify_hdr; __le64 tsf; __le32 ibss_mgr_status; __le32 gp2; } __packed; /* BEACON_NTFY_API_S_VER_5 */ +/** + * struct iwl_extended_beacon_notif - notifies about beacon transmission + * @status: the status of the Tx response of the beacon + * @tsf: last beacon tsf + * @ibss_mgr_status: whether IBSS is manager + * @gp2: last beacon time in gp2 + */ +struct iwl_extended_beacon_notif { + __le32 status; + __le64 tsf; + __le32 ibss_mgr_status; + __le32 gp2; +} __packed; /* BEACON_NTFY_API_S_VER_6_ */ + /** * enum iwl_dump_control - dump (flush) control flags * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index db392cfc2bd4..a6dd27fbe4aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -263,6 +263,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; * @IWL_UCODE_TLV_API_FRAG_EBS: This ucode supports fragmented EBS * @IWL_UCODE_TLV_API_REDUCE_TX_POWER: This ucode supports v5 of * the REDUCE_TX_POWER_CMD. + * @IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF: This ucode supports the short + * version of the beacon notification. * * @NUM_IWL_UCODE_TLV_API: number of bits used */ @@ -287,6 +289,7 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2 = (__force iwl_ucode_tlv_api_t)42, IWL_UCODE_TLV_API_FRAG_EBS = (__force iwl_ucode_tlv_api_t)44, IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45, + IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46, NUM_IWL_UCODE_TLV_API #ifdef __CHECKER__ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 768a87e0a1c3..c1eb07c08827 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1330,7 +1330,7 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_extended_beacon_notif *beacon = (void *)pkt->data; - struct iwl_mvm_tx_resp *beacon_notify_hdr; + struct iwl_extended_beacon_notif_v5 *beacon_v5 = (void *)pkt->data; struct ieee80211_vif *csa_vif; struct ieee80211_vif *tx_blocked_vif; struct agg_tx_status *agg_status; @@ -1338,18 +1338,29 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, lockdep_assert_held(&mvm->mutex); - beacon_notify_hdr = &beacon->beacon_notify_hdr; mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2); - mvm->ibss_manager = beacon->ibss_mgr_status != 0; - - agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr); - status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK; - IWL_DEBUG_RX(mvm, - "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n", - status, beacon_notify_hdr->failure_frame, - le64_to_cpu(beacon->tsf), - mvm->ap_last_beacon_gp2, - le32_to_cpu(beacon_notify_hdr->initial_rate)); + + if (!iwl_mvm_is_short_beacon_notif_supported(mvm)) { + struct iwl_mvm_tx_resp *beacon_notify_hdr = + &beacon_v5->beacon_notify_hdr; + + mvm->ibss_manager = beacon_v5->ibss_mgr_status != 0; + agg_status = iwl_mvm_get_agg_status(mvm, beacon_notify_hdr); + status = le16_to_cpu(agg_status->status) & TX_STATUS_MSK; + IWL_DEBUG_RX(mvm, + "beacon status %#x retries:%d tsf:0x%016llX gp2:0x%X rate:%d\n", + status, beacon_notify_hdr->failure_frame, + le64_to_cpu(beacon->tsf), + mvm->ap_last_beacon_gp2, + le32_to_cpu(beacon_notify_hdr->initial_rate)); + } else { + mvm->ibss_manager = beacon->ibss_mgr_status != 0; + status = le32_to_cpu(beacon->status) & TX_STATUS_MSK; + IWL_DEBUG_RX(mvm, + "beacon status %#x tsf:0x%016llX gp2:0x%X\n", + status, le64_to_cpu(beacon->tsf), + mvm->ap_last_beacon_gp2); + } csa_vif = rcu_dereference_protected(mvm->csa_vif, lockdep_is_held(&mvm->mutex)); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 12e9ecc3ee27..f7176020139d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1311,6 +1311,12 @@ static inline bool iwl_mvm_is_frag_ebs_supported(struct iwl_mvm *mvm) return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_FRAG_EBS); } +static inline bool iwl_mvm_is_short_beacon_notif_supported(struct iwl_mvm *mvm) +{ + return fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF); +} + static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm) { /* For now we only use this mode to differentiate between -- cgit v1.2.3 From 6032c062723ce5a23eccb7d2bf8c0a2985424f27 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 30 Nov 2018 19:24:26 +0800 Subject: iwlwifi: mvm: remove duplicated include from ops.c Remove duplicated include. Signed-off-by: YueHaibing Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index a2719a75249a..de288962773e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -82,7 +82,6 @@ #include "fw/api/scan.h" #include "time-event.h" #include "fw-api.h" -#include "fw/api/scan.h" #include "fw/acpi.h" #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" -- cgit v1.2.3 From 700b3799b398d00320f40ef1a40d3fe341f98678 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 12 Nov 2018 13:27:51 +0200 Subject: iwlwifi: Fix pre operational dumping flows There are several dumping flows in the driver in case of a fail prior to operational. In some cases we get 2 dumps while in others we get none. Fix this by uniting the different flows. Add a different dump type to driver triggered dumps in case we want a dump but did not got assert, and make all dumping go through iwl_fw_dbg_collect_desc to avoid multiple dumps. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 89 +++++++++++++--------- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 5 +- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 3 + drivers/net/wireless/intel/iwlwifi/fw/init.c | 3 + drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 13 ++++ drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 6 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 9 +-- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 + 8 files changed, 81 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 0edc5bcdfb82..f8cf12804aee 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1365,44 +1365,6 @@ const struct iwl_fw_dump_desc iwl_dump_desc_assert = { }; IWL_EXPORT_SYMBOL(iwl_dump_desc_assert); -void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt) -{ - IWL_INFO(fwrt, "error dump due to fw assert\n"); - fwrt->dump.desc = &iwl_dump_desc_assert; - iwl_fw_error_dump(fwrt); -} -IWL_EXPORT_SYMBOL(iwl_fw_assert_error_dump); - -void iwl_fw_alive_timeout_dump(struct iwl_fw_runtime *fwrt) -{ - struct iwl_fw_dump_desc *iwl_dump_desc_alive_timeout; - - if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) - return; - - iwl_dump_desc_alive_timeout = - kmalloc(sizeof(*iwl_dump_desc_alive_timeout), GFP_KERNEL); - if (!iwl_dump_desc_alive_timeout) - return; - - iwl_dump_desc_alive_timeout->trig_desc.type = - cpu_to_le32(FW_DBG_TRIGGER_ALIVE_TIMEOUT); - iwl_dump_desc_alive_timeout->len = 0; - - if (WARN_ON(fwrt->dump.desc)) - iwl_fw_free_dump_desc(fwrt); - - IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n", - FW_DBG_TRIGGER_ALIVE_TIMEOUT); - - /* set STATUS_FW_ERROR to collect all memory regions. */ - set_bit(STATUS_FW_ERROR, &fwrt->trans->status); - - fwrt->dump.desc = iwl_dump_desc_alive_timeout; - iwl_fw_error_dump(fwrt); -} -IWL_EXPORT_SYMBOL(iwl_fw_alive_timeout_dump); - int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, const struct iwl_fw_dump_desc *desc, bool monitor_only, @@ -1442,6 +1404,33 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, } IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect_desc); +int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, + enum iwl_fw_dbg_trigger trig_type) +{ + int ret; + struct iwl_fw_dump_desc *iwl_dump_error_desc = + kmalloc(sizeof(*iwl_dump_error_desc), GFP_KERNEL); + + if (!iwl_dump_error_desc) + return -ENOMEM; + + iwl_dump_error_desc->trig_desc.type = cpu_to_le32(trig_type); + iwl_dump_error_desc->len = 0; + + ret = iwl_fw_dbg_collect_desc(fwrt, iwl_dump_error_desc, false, 0); + if (ret) { + kfree(iwl_dump_error_desc); + } else { + set_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status); + + /* trigger nmi to halt the fw */ + iwl_force_nmi(fwrt->trans); + } + + return ret; +} +IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect); + int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, enum iwl_fw_dbg_trigger trig, const char *str, size_t len, @@ -1893,3 +1882,27 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, _iwl_fw_dbg_apply_point(fwrt, data, apply_point, true); } IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point); + +void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt) +{ + /* if the wait event timeout elapses instead of wake up then + * the driver did not receive NMI interrupt and can not assume the FW + * is halted + */ + int ret = wait_event_timeout(fwrt->trans->fw_halt_waitq, + !test_bit(STATUS_FW_WAIT_DUMP, + &fwrt->trans->status), + msecs_to_jiffies(2000)); + if (!ret) { + /* failed to receive NMI interrupt, assuming the FW is stuck */ + set_bit(STATUS_FW_ERROR, &fwrt->trans->status); + + clear_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status); + } + + /* Assuming the op mode mutex is held at this point */ + iwl_fw_dbg_collect_sync(fwrt); + + iwl_trans_stop_device(fwrt->trans); +} +IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 36e0f40dab3b..2fa7a19e02b6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -112,6 +112,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, const struct iwl_fw_dump_desc *desc, bool monitor_only, unsigned int delay); +int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, + enum iwl_fw_dbg_trigger trig_type); int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, enum iwl_fw_dbg_trigger trig, const char *str, size_t len, @@ -434,10 +436,9 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {} #endif /* CONFIG_IWLWIFI_DEBUGFS */ -void iwl_fw_assert_error_dump(struct iwl_fw_runtime *fwrt); -void iwl_fw_alive_timeout_dump(struct iwl_fw_runtime *fwrt); void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt); void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, enum iwl_fw_ini_apply_point apply_point); +void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt); #endif /* __iwl_fw_dbg_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index d06707f3a2a4..e1c6aa61ab90 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -356,6 +356,8 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data) * @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when * the firmware sends a tx reply. * @FW_DBG_TRIGGER_ALIVE_TIMEOUT: trigger log collection if alive flow timeouts + * @FW_DBG_TRIGGER_DRIVER: trigger log collection upon a flow failure + * in the driver. */ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_INVALID = 0, @@ -374,6 +376,7 @@ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_TDLS, FW_DBG_TRIGGER_TX_STATUS, FW_DBG_TRIGGER_ALIVE_TIMEOUT, + FW_DBG_TRIGGER_DRIVER, /* must be last */ FW_DBG_TRIGGER_MAX, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index 2efac307909e..7adf4e4e841a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -6,6 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -26,6 +27,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -74,6 +76,7 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, fwrt->ops_ctx = ops_ctx; INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk); iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir); + init_waitqueue_head(&fwrt->trans->fw_halt_waitq); } IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index a7009cd4232d..d79025d663df 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -8,6 +8,7 @@ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -330,6 +332,7 @@ enum iwl_d3_status { * are sent * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent * @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation + * @STATUS_FW_WAIT_DUMP: if set, wait until cleared before collecting dump */ enum iwl_trans_status { STATUS_SYNC_HCMD_ACTIVE, @@ -342,6 +345,7 @@ enum iwl_trans_status { STATUS_TRANS_GOING_IDLE, STATUS_TRANS_IDLE, STATUS_TRANS_DEAD, + STATUS_FW_WAIT_DUMP, }; static inline int @@ -796,6 +800,11 @@ struct iwl_trans { bool suspending; bool dbg_rec_on; + u32 lmac_error_event_table[2]; + u32 umac_error_event_table; + unsigned int error_event_table_tlv_status; + wait_queue_head_t fw_halt_waitq; + /* pointer to trans specific struct */ /*Ensure that this pointer will always be aligned to sizeof pointer */ char trans_specific[0] __aligned(sizeof(void *)); @@ -1202,6 +1211,10 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans) /* prevent double restarts due to the same erroneous FW */ if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) iwl_op_mode_nic_error(trans->op_mode); + + if (test_and_clear_bit(STATUS_FW_WAIT_DUMP, &trans->status)) + wake_up(&trans->fw_halt_waitq); + } /***************************************************** diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 25c8cea1180e..d8ae9561a9b0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -332,7 +332,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, struct iwl_trans *trans = mvm->trans; if (ret == -ETIMEDOUT) - iwl_fw_alive_timeout_dump(&mvm->fwrt); + iwl_fw_dbg_error_collect(&mvm->fwrt, + FW_DBG_TRIGGER_ALIVE_TIMEOUT); if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) IWL_ERR(mvm, @@ -408,7 +409,6 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); if (ret) { IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); - iwl_fw_assert_error_dump(&mvm->fwrt); goto error; } @@ -1053,7 +1053,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ret = iwl_mvm_load_rt_fw(mvm); if (ret) { IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); - iwl_fw_assert_error_dump(&mvm->fwrt); + iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER); goto error; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f7176020139d..ee61f4a00c5e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -2013,15 +2013,12 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) &mvm->status)) iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert, false, 0); - /* calling this function without using dump_start/end since at this - * point we already hold the op mode mutex - */ - iwl_fw_dbg_collect_sync(&mvm->fwrt); + iwl_fw_cancel_timestamp(&mvm->fwrt); - iwl_free_fw_paging(&mvm->fwrt); clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); + iwl_fwrt_stop_device(&mvm->fwrt); + iwl_free_fw_paging(&mvm->fwrt); iwl_fw_dump_conf_clear(&mvm->fwrt); - iwl_trans_stop_device(mvm->trans); } /* Re-configure the SCD for a queue that has already been configured */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index de288962773e..ad816007e546 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -817,6 +817,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mutex_lock(&mvm->mutex); iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE); err = iwl_run_init_mvm_ucode(mvm, true); + if (err) + iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER); if (!iwlmvm_mod_params.init_dbg || !err) iwl_mvm_stop_device(mvm); iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE); -- cgit v1.2.3 From d7febc2e61f91eaa810f1682909928d16f4c6adc Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 29 Nov 2018 17:55:55 +0200 Subject: iwlwifi: dbg_ini: update ini structs meta doc Align the documentation of the structs with the latest version in the FW. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index b2ab675b3cf8..4926950d432a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -70,7 +70,7 @@ struct iwl_fw_ini_header { __le32 tlv_version; __le32 apply_point; u8 data[]; -} __packed; /* FW_INI_HEADER_TLV_S */ +} __packed; /* FW_DEBUG_TLV_HEADER_S */ /** * struct iwl_fw_ini_allocation_tlv - (IWL_FW_INI_TLV_TYPE_BUFFER_ALLOCATION) @@ -92,7 +92,7 @@ struct iwl_fw_ini_allocation_tlv { __le32 size; __le32 max_fragments; __le32 min_frag_size; -} __packed; /* FW_INI_BUFFER_ALLOCATION_TLV_S_VER_1 */ +} __packed; /* FW_DEBUG_TLV_BUFFER_ALLOCATION_TLV_S_VER_1 */ /** * struct iwl_fw_ini_hcmd (IWL_FW_INI_TLV_TYPE_HCMD) @@ -108,7 +108,7 @@ struct iwl_fw_ini_hcmd { u8 group; __le16 padding; u8 data[0]; -} __packed; /* FW_INI_HCMD_S */ +} __packed; /* FW_DEBUG_TLV_HCMD_DATA_S */ /** * struct iwl_fw_ini_hcmd_tlv @@ -118,7 +118,7 @@ struct iwl_fw_ini_hcmd { struct iwl_fw_ini_hcmd_tlv { struct iwl_fw_ini_header header; struct iwl_fw_ini_hcmd hcmd; -} __packed; /* FW_INI_HCMD_TLV_S_VER_1 */ +} __packed; /* FW_DEBUG_TLV_HCMD_S_VER_1 */ /* * struct iwl_fw_ini_debug_flow_tlv (IWL_FW_INI_TLV_TYPE_DEBUG_FLOW) @@ -129,7 +129,7 @@ struct iwl_fw_ini_hcmd_tlv { struct iwl_fw_ini_debug_flow_tlv { struct iwl_fw_ini_header header; __le32 debug_flow_cfg; -} __packed; /* FW_INI_DEBUG_FLOW_TLV_S_VER_1 */ +} __packed; /* FW_DEBUG_TLV_FLOW_TLV_S_VER_1 */ #define IWL_FW_INI_MAX_REGION_ID 64 #define IWL_FW_INI_MAX_NAME 32 @@ -176,7 +176,7 @@ struct iwl_fw_ini_region_tlv { * struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG) * Region sections define IDs and triggers that use those IDs TLV * - * @trigger_id: enum &iwl_fw_ini_tigger_id + * @trigger_id: enum &iwl_fw_ini_trigger_id * @ignore_default: override FW TLV with binary TLV * @dump_delay: delay from trigger fire to dump, in usec * @occurrences: max amount of times to be fired @@ -322,7 +322,7 @@ enum iwl_fw_ini_apply_point { IWL_FW_INI_APPLY_MISSED_BEACONS, IWL_FW_INI_APPLY_SCAN_COMPLETE, IWL_FW_INI_APPLY_NUM, -}; /* FW_INI_APPLY_POINT_E_VER_1 */ +}; /* FW_DEBUG_TLV_APPLY_POINT_E_VER_1 */ /** * enum iwl_fw_ini_allocation_id @@ -342,7 +342,7 @@ enum iwl_fw_ini_allocation_id { IWL_FW_INI_ALLOCATION_ID_SDFX, IWL_FW_INI_ALLOCATION_ID_FW_DUMP, IWL_FW_INI_ALLOCATION_ID_USER_DEFINED, -}; /* FW_INI_ALLOCATION_ID_E_VER_1 */ +}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */ /** * enum iwl_fw_ini_buffer_location @@ -354,7 +354,7 @@ enum iwl_fw_ini_buffer_location { IWL_FW_INI_LOCATION_INVALID, IWL_FW_INI_LOCATION_SRAM_PATH, IWL_FW_INI_LOCATION_DRAM_PATH, -}; /* FW_INI_BUFFER_LOCATION_E_VER_1 */ +}; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */ /** * enum iwl_fw_ini_debug_flow @@ -366,7 +366,7 @@ enum iwl_fw_ini_debug_flow { IWL_FW_INI_DEBUG_INVALID, IWL_FW_INI_DEBUG_DBTR_FLOW, IWL_FW_INI_DEBUG_TB2DTF_FLOW, -}; /* FW_INI_DEBUG_FLOW_E_VER_1 */ +}; /* FW_DEBUG_TLV_FLOW_E_VER_1 */ /** * enum iwl_fw_ini_region_type @@ -398,6 +398,6 @@ enum iwl_fw_ini_region_type { IWL_FW_INI_REGION_PAGING, IWL_FW_INI_REGION_CSR, IWL_FW_INI_REGION_NUM -}; /* FW_INI_REGION_TYPE_E_VER_1*/ +}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */ #endif -- cgit v1.2.3 From 999ced14c783e94f286c72484a01f9947ee94790 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 4 Dec 2018 23:13:15 +0200 Subject: iwlwifi: dvm: fix some fall through warnings Some case statements were missing a comment about falling through or had more text than the compiler can recognize. Fix that. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/dvm/rx.c | 6 ++++-- drivers/net/wireless/intel/iwlwifi/dvm/scan.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c index 6f17a5e24e82..e224b23f0ba8 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rx.c @@ -2,6 +2,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * Portions of this file are derived from the ipw3945 project, as well * as portionhelp of the ieee80211 subsystem header files. @@ -592,7 +593,7 @@ static int iwlagn_set_decrypted_flag(struct iwl_priv *priv, if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == RX_RES_STATUS_BAD_KEY_TTAK) break; - + /* fall through */ case RX_RES_STATUS_SEC_TYPE_WEP: if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == RX_RES_STATUS_BAD_ICV_MIC) { @@ -601,6 +602,7 @@ static int iwlagn_set_decrypted_flag(struct iwl_priv *priv, IWL_DEBUG_RX(priv, "Packet destroyed\n"); return -1; } + /* fall through */ case RX_RES_STATUS_SEC_TYPE_CCMP: if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == RX_RES_STATUS_DECRYPT_OK) { @@ -729,7 +731,7 @@ static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; break; } - /* fall through if TTAK OK */ + /* fall through */ default: if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c index 8d7aafb4d9e9..f190f7beb3a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/scan.c @@ -3,6 +3,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -418,7 +419,7 @@ static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time) limit = (limits[1] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; limit /= 2; dwell_time = min(limit, dwell_time); - /* fall through to limit further */ + /* fall through */ case 1: limit = (limits[0] * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; limit /= n_active; -- cgit v1.2.3 From 244726ec9e1965c3263807c7c22bcdd1f6870e96 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 4 Dec 2018 23:23:49 +0200 Subject: iwlwifi: mvm: add fall through comments where needed Some switch-cases were missing a fall through comment, so the compiler may warn. Fix that by adding the comments where needed. In other cases there was more text in the comment, which the compiler doesn't recognize, so either remove the extra text or move it to a separate comment line as appropriate. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/led.c | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 1 + drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c | 1 + drivers/net/wireless/intel/iwlwifi/mvm/rx.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 6 +++--- 6 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c index 9bb1de1cad64..4348bb00e761 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,6 +29,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -113,6 +115,7 @@ int iwl_mvm_leds_init(struct iwl_mvm *mvm) switch (mode) { case IWL_LED_BLINK: IWL_ERR(mvm, "Blink led mode not supported, used default\n"); + /* fall through */ case IWL_LED_DEFAULT: case IWL_LED_RF_STATE: mode = IWL_LED_RF_STATE; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 8837d7667f36..4e676a6936c1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3901,6 +3901,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, mvmvif->ap_ibss_active = true; break; } + /* fall through */ case NL80211_IFTYPE_ADHOC: /* * The AP binding flow is handled as part of the start_ap flow diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c index f369173db11c..86e40bae57e3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c @@ -109,6 +109,7 @@ u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef) return PHY_VHT_CTRL_POS_4_ABOVE; default: WARN(1, "Invalid channel definition"); + /* fall through */ case 0: /* * The FW is expected to check the control channel position only diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 235ab26ca429..fbd3014e8b82 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -222,7 +222,7 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm, !(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK)) return 0; *crypt_len = IEEE80211_TKIP_IV_LEN; - /* fall through if TTAK OK */ + /* fall through */ case RX_MPDU_RES_STATUS_SEC_WEP_ENC: if (!(rx_pkt_status & RX_MPDU_RES_STATUS_ICV_OK)) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 2c56f73d688e..b5ff3325c1d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -310,7 +310,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, stats->flag |= RX_FLAG_MMIC_ERROR; *crypt_len = IEEE80211_TKIP_IV_LEN; - /* fall through if TTAK OK */ + /* fall through */ case IWL_RX_MPDU_STATUS_SEC_WEP: if (!(status & IWL_RX_MPDU_STATUS_ICV_OK)) return -1; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index af8156ba8084..853bf679dc26 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1616,10 +1616,10 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type) if (mvm->scan_status & IWL_MVM_SCAN_SCHED_MASK) return iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true); - - /* fall through, something is wrong if no scan was - * running but we ran out of scans. + /* Something is wrong if no scan was running but we + * ran out of scans. */ + /* fall through */ default: WARN_ON(1); break; -- cgit v1.2.3 From 28916a165aa7e0ceddedabf722808881ba6a3b03 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 3 Dec 2018 20:13:27 +0200 Subject: iwlwifi: mvm: fix AP mode in WEP Recently we started to send the WEP keys to the firmware so that we could use hardware Tx encryption also on newer devices that require the keys to be installed in the firmware for encryption (as opposed to older devices that can get the key in the Tx command for each Tx). When we implemented that, we forgot to remove the key when we remove a station leading to a situation where a station that connects and disconnects a lot of times exhausts the key database inside the firmware. A fix was made for that, but we always removed the same key: mvmvif->ap_wep_key which means that we removed the same key entry in the firmware. This can make sense since in WEP, the key is the same for all the stations, but the internal implementation of iwl_mvm_set_sta_key and iwl_mvm_remove_sta_key assumes that each station uses a different key in the firmware's key database. So now we got to the situation where we have a single ieee80211_key_conf instance that means, a single ieee80211_key_conf.hw_key_idx index for several stations and hence for several keys. ieee80211_key_conf.hw_key_idx is set to 0 when the first station associates, and then it is overwritten to 1 when the second station associates which is a buggy of course. This led to the following message upon the removal of the second station: iwlwifi 0000:00:03.0: offset 1 not used in fw key table. WARNING: CPU: 2 PID: 27883 at net/mac80211/sta_info.c:1122 __sta_info_destroy_part2+0x16b/0x180 [mac80211] RIP: 0010:__sta_info_destroy_part2+0x16b/0x180 [mac80211] Call Trace: __sta_info_destroy+0x2a/0x40 [mac80211] sta_info_destroy_addr_bss+0x38/0x60 [mac80211] ieee80211_del_station+0x1d/0x30 [mac80211] nl80211_del_station+0xe0/0x1f0 [cfg80211] Fix this by copying the ieee80211_key_conf structure for each and every station. This is the easiest way to properly remove the keys with the right index. Another solution would have been to allow several stations to use the same key offset in the firmware. That would require to change the way we track keys in iwlmvm and not really worth it. Also, maintain correctly fw_key_table when we add a key for the multicast station. Remove the key when we remove the multicast station. Signed-off-by: Emmanuel Grumbach Fixes: 337bfc9881a2 ("iwlwifi: mvm: set wep key for all stations in soft ap mode") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 30 +++-- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 132 +++++++++++++--------- drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 3 + 3 files changed, 102 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 4e676a6936c1..92605aaca937 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3078,6 +3078,24 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ret = iwl_mvm_update_sta(mvm, vif, sta); } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { + /* if wep is used, need to set the key for the station now */ + if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) { + mvm_sta->wep_key = + kmemdup(mvmvif->ap_wep_key, + sizeof(*mvmvif->ap_wep_key) + + mvmvif->ap_wep_key->keylen, + GFP_KERNEL); + if (!mvm_sta->wep_key) { + ret = -ENOMEM; + goto out_unlock; + } + + ret = iwl_mvm_set_sta_key(mvm, vif, sta, + mvm_sta->wep_key, + STA_KEY_IDX_INVALID); + } else { + ret = 0; + } /* we don't support TDLS during DCM */ if (iwl_mvm_phy_ctx_count(mvm) > 1) @@ -3092,14 +3110,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, true); - - /* if wep is used, need to set the key for the station now */ - if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) - ret = iwl_mvm_set_sta_key(mvm, vif, sta, - mvmvif->ap_wep_key, - STA_KEY_IDX_INVALID); - else - ret = 0; } else if (old_state == IEEE80211_STA_AUTHORIZED && new_state == IEEE80211_STA_ASSOC) { /* disable beacon filtering */ @@ -3127,10 +3137,12 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, /* Remove STA key if this is an AP using WEP */ if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) { int rm_ret = iwl_mvm_remove_sta_key(mvm, vif, sta, - mvmvif->ap_wep_key); + mvm_sta->wep_key); if (!ret) ret = rm_ret; + kfree(mvm_sta->wep_key); + mvm_sta->wep_key = NULL; } } else { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index a102a16a15f6..3ea39bb533e8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2337,11 +2337,13 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) if (mvmvif->ap_wep_key) { u8 key_offset = iwl_mvm_set_fw_key_idx(mvm); + __set_bit(key_offset, mvm->fw_key_table); + if (key_offset == STA_KEY_IDX_INVALID) return -ENOSPC; ret = iwl_mvm_send_sta_key(mvm, mvmvif->mcast_sta.sta_id, - mvmvif->ap_wep_key, 1, 0, NULL, 0, + mvmvif->ap_wep_key, true, 0, NULL, 0, key_offset, 0); if (ret) return ret; @@ -2350,6 +2352,59 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) return 0; } +static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, + struct ieee80211_key_conf *keyconf, + bool mcast) +{ + union { + struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1; + struct iwl_mvm_add_sta_key_cmd cmd; + } u = {}; + bool new_api = fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_TKIP_MIC_KEYS); + __le16 key_flags; + int ret, size; + u32 status; + + /* This is a valid situation for GTK removal */ + if (sta_id == IWL_MVM_INVALID_STA) + return 0; + + key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & + STA_KEY_FLG_KEYID_MSK); + key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP); + key_flags |= cpu_to_le16(STA_KEY_NOT_VALID); + + if (mcast) + key_flags |= cpu_to_le16(STA_KEY_MULTICAST); + + /* + * The fields assigned here are in the same location at the start + * of the command, so we can do this union trick. + */ + u.cmd.common.key_flags = key_flags; + u.cmd.common.key_offset = keyconf->hw_key_idx; + u.cmd.common.sta_id = sta_id; + + size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1); + + status = ADD_STA_SUCCESS; + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd, + &status); + + switch (status) { + case ADD_STA_SUCCESS: + IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n"); + break; + default: + ret = -EIO; + IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n"); + break; + } + + return ret; +} + /* * Send the FW a request to remove the station from it's internal data * structures, and in addition remove it from the local data structure. @@ -2365,6 +2420,28 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0); + if (mvmvif->ap_wep_key) { + int i; + + if (!__test_and_clear_bit(mvmvif->ap_wep_key->hw_key_idx, + mvm->fw_key_table)) { + IWL_ERR(mvm, "offset %d not used in fw key table.\n", + mvmvif->ap_wep_key->hw_key_idx); + return -ENOENT; + } + + /* track which key was deleted last */ + for (i = 0; i < STA_KEY_MAX_NUM; i++) { + if (mvm->fw_key_deleted[i] < U8_MAX) + mvm->fw_key_deleted[i]++; + } + mvm->fw_key_deleted[mvmvif->ap_wep_key->hw_key_idx] = 0; + ret = __iwl_mvm_remove_sta_key(mvm, mvmvif->mcast_sta.sta_id, + mvmvif->ap_wep_key, true); + if (ret) + return ret; + } + ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); if (ret) IWL_WARN(mvm, "Failed sending remove station\n"); @@ -3396,59 +3473,6 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm, return ret; } -static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, - struct ieee80211_key_conf *keyconf, - bool mcast) -{ - union { - struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1; - struct iwl_mvm_add_sta_key_cmd cmd; - } u = {}; - bool new_api = fw_has_api(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_API_TKIP_MIC_KEYS); - __le16 key_flags; - int ret, size; - u32 status; - - /* This is a valid situation for GTK removal */ - if (sta_id == IWL_MVM_INVALID_STA) - return 0; - - key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & - STA_KEY_FLG_KEYID_MSK); - key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP); - key_flags |= cpu_to_le16(STA_KEY_NOT_VALID); - - if (mcast) - key_flags |= cpu_to_le16(STA_KEY_MULTICAST); - - /* - * The fields assigned here are in the same location at the start - * of the command, so we can do this union trick. - */ - u.cmd.common.key_flags = key_flags; - u.cmd.common.key_offset = keyconf->hw_key_idx; - u.cmd.common.sta_id = sta_id; - - size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1); - - status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd, - &status); - - switch (status) { - case ADD_STA_SUCCESS: - IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n"); - break; - default: - ret = -EIO; - IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n"); - break; - } - - return ret; -} - int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 0614296244b3..79700c7310a1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -394,6 +394,7 @@ struct iwl_mvm_rxq_dup_data { * the BA window. To be used for UAPSD only. * @ptk_pn: per-queue PTK PN data structures * @dup_data: per queue duplicate packet detection data + * @wep_key: used in AP mode. Is a duplicate of the WEP key. * @deferred_traffic_tid_map: indication bitmap of deferred traffic per-TID * @tx_ant: the index of the antenna to use for data tx to this station. Only * used during connection establishment (e.g. for the 4 way handshake @@ -425,6 +426,8 @@ struct iwl_mvm_sta { struct iwl_mvm_key_pn __rcu *ptk_pn[4]; struct iwl_mvm_rxq_dup_data *dup_data; + struct ieee80211_key_conf *wep_key; + u8 reserved_queue; /* Temporary, until the new TLC will control the Tx protection */ -- cgit v1.2.3 From 679bff239f51388a61a3cb4a512bc3a1d6e66d74 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 6 Dec 2018 15:02:11 +0200 Subject: iwlwifi: mvm: limit AMSDU size to 8K Typically, when not in HE mode, we will not perform well with AMSDUs bigger than 8K. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 09866f50857a..2d7a089d93a3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -1757,7 +1757,12 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta, else mvmsta->amsdu_enabled = 0xFFFF; - mvmsta->max_amsdu_len = sta->max_amsdu_len; + if (mvmsta->vif->bss_conf.he_support && + !iwlwifi_mod_params.disable_11ax) + mvmsta->max_amsdu_len = sta->max_amsdu_len; + else + mvmsta->max_amsdu_len = min_t(int, sta->max_amsdu_len, 8500); + sta->max_rc_amsdu_len = mvmsta->max_amsdu_len; for (i = 0; i < IWL_MAX_TID_COUNT; i++) { -- cgit v1.2.3 From f992c61d59fb2eb1a234890ef92f378a47ebe20b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Dec 2018 12:04:31 +0100 Subject: iwlwifi: mvm: remove redundant condition In iwl_mvm_sta_alloc_queue_tvqm(), we know that we have a station, so no need to check it. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 3ea39bb533e8..27839c10d5e3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -791,11 +791,9 @@ static int iwl_mvm_sta_alloc_queue_tvqm(struct iwl_mvm *mvm, if (queue < 0) return queue; - if (sta) { - mvmtxq->txq_id = queue; - mvm->tvqm_info[queue].txq_tid = tid; - mvm->tvqm_info[queue].sta_id = mvmsta->sta_id; - } + mvmtxq->txq_id = queue; + mvm->tvqm_info[queue].txq_tid = tid; + mvm->tvqm_info[queue].sta_id = mvmsta->sta_id; IWL_DEBUG_TX_QUEUES(mvm, "Allocated queue is %d\n", queue); -- cgit v1.2.3 From f4056d713cede3d3f1f574e9c36613c6a1a4e347 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Sun, 9 Dec 2018 11:20:39 +0200 Subject: iwlwifi: mvm: add tlc command name to output Instead of having the command appear as "UNKNOWN" in the dmesg, add the name to it. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index ad816007e546..8a16388c3a0b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -445,6 +445,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), HCMD_NAME(STA_HE_CTXT_CMD), HCMD_NAME(RFH_QUEUE_CONFIG_CMD), + HCMD_NAME(TLC_MNG_CONFIG_CMD), HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD), HCMD_NAME(STA_PM_NOTIF), HCMD_NAME(MU_GROUP_MGMT_NOTIF), -- cgit v1.2.3 From 9394662ab5e92ef1fcfe108ea4f4d98efa99d84a Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Sun, 9 Dec 2018 12:24:24 +0200 Subject: iwlwifi: mvm: config mac ctxt to HE before TLC If we have a station connecting HE, make sure that the MAC ctxt is updated with indication of this before setting the TLC rates via the TLC manager command. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 3 +-- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index c1eb07c08827..83711b555036 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -706,8 +706,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p) cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); - if (vif->bss_conf.assoc && vif->bss_conf.he_support && - !iwlwifi_mod_params.disable_11ax) { + if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) { cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); if (vif->bss_conf.twt_requester) ctxt_sta->data_policy |= cpu_to_le32(TWT_SUPPORTED); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 92605aaca937..fc251cc47b7f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3066,11 +3066,15 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, } else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) { if (vif->type == NL80211_IFTYPE_AP) { + vif->bss_conf.he_support = sta->he_cap.has_he; mvmvif->ap_assoc_sta_count++; iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id); + } else if (vif->type == NL80211_IFTYPE_STATION) { + vif->bss_conf.he_support = sta->he_cap.has_he; + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); } iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, -- cgit v1.2.3 From 138d320a95ce4ecef13e6b3f3b3a8a21af5c6e1d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 6 Dec 2018 11:30:37 +0100 Subject: iwlwifi: dvm: use %u for sscanf() into unsigned variable Use %u instead of using %d which looks signed but then won't get signed output if using an unsigned variable. It doesn't matter much, but be consistent. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index 3d2e44a642de..e64cdafc5623 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c @@ -3,6 +3,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -2238,7 +2239,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, buf_size = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; - if (sscanf(buf, "%d", &event_log_flag) != 1) + if (sscanf(buf, "%u", &event_log_flag) != 1) return -EFAULT; if (event_log_flag == 1) iwl_dump_nic_event_log(priv, true, NULL); -- cgit v1.2.3 From 0ec7bfb26aff91ae60ac8a893fee755287291a55 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 20 Nov 2018 13:29:29 +0200 Subject: iwlwifi: dbg_ini: remove redundant dram buffer allocation There are several flows in that can cause redundant allocation. In case the driver reaches the maximum amount of blocks allowed, it allocates the buffer and only then checks if it reached the maximum amount of blocks and return without freeing the buffer, causing a memory leak. Solve this by moving the check of the amount of buffers being used before the allocation. In case there was an assert, the apply points are being reused, causing that for each assert, the driver allocates a new redundant buffer. Solve this by adding a new is_alloc field to indicate if the driver already allocated memory for the requested buffer. Also, split iwl_fw_dbg_buffer_allocation function into iwl_fw_dbg_buffer_allocation and iwl_fw_dbg_buffer_apply to increase the clearity of the flow. Signed-off-by: Shahar S Matityahu Fixes: d47902f9f71d ("iwlwifi: dbg: add apply point logic") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 89 ++++++++++++++---------- drivers/net/wireless/intel/iwlwifi/fw/img.h | 19 +++-- drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 2 +- drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 23 +++++- 4 files changed, 85 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index f8cf12804aee..5feae549d316 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1131,7 +1131,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs))) continue; - reg = fwrt->dump.active_regs[reg_id].reg; + reg = fwrt->dump.active_regs[reg_id]; if (WARN(!reg, "Unassigned region %d\n", reg_id)) continue; @@ -1197,7 +1197,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, if (reg_id >= ARRAY_SIZE(fwrt->dump.active_regs)) continue; - reg = fwrt->dump.active_regs[reg_id].reg; + reg = fwrt->dump.active_regs[reg_id]; /* Don't warn, get_trigger_len already warned */ if (!reg) continue; @@ -1667,27 +1667,13 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt) IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data); static void -iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_allocation_tlv *alloc) +iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size) { struct iwl_trans *trans = fwrt->trans; - struct iwl_ldbg_config_cmd ldbg_cmd = { - .type = cpu_to_le32(BUFFER_ALLOCATION), - }; - struct iwl_buffer_allocation_cmd *cmd = &ldbg_cmd.buffer_allocation; - struct iwl_host_cmd hcmd = { - .id = LDBG_CONFIG_CMD, - .flags = CMD_ASYNC, - .data[0] = &ldbg_cmd, - .len[0] = sizeof(ldbg_cmd), - }; void *virtual_addr = NULL; - u32 size = le32_to_cpu(alloc->size); dma_addr_t phys_addr; - if (!trans->num_blocks && - le32_to_cpu(alloc->buffer_location) != - IWL_FW_INI_LOCATION_DRAM_PATH) + if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon))) return; virtual_addr = @@ -1699,25 +1685,52 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, if (!virtual_addr) IWL_ERR(fwrt, "Failed to allocate debug memory\n"); - if (WARN_ON_ONCE(trans->num_blocks == ARRAY_SIZE(trans->fw_mon))) - return; - trans->fw_mon[trans->num_blocks].block = virtual_addr; trans->fw_mon[trans->num_blocks].physical = phys_addr; trans->fw_mon[trans->num_blocks].size = size; trans->num_blocks++; IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size); +} + +static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_allocation_data *alloc) +{ + struct iwl_trans *trans = fwrt->trans; + struct iwl_ldbg_config_cmd ldbg_cmd = { + .type = cpu_to_le32(BUFFER_ALLOCATION), + }; + struct iwl_buffer_allocation_cmd *cmd = &ldbg_cmd.buffer_allocation; + struct iwl_host_cmd hcmd = { + .id = LDBG_CONFIG_CMD, + .flags = CMD_ASYNC, + .data[0] = &ldbg_cmd, + .len[0] = sizeof(ldbg_cmd), + }; + int block_idx = trans->num_blocks; + + if (le32_to_cpu(alloc->tlv.buffer_location) != + IWL_FW_INI_LOCATION_DRAM_PATH) + return; + + if (!alloc->is_alloc) { + iwl_fw_dbg_buffer_allocation(fwrt, + le32_to_cpu(alloc->tlv.size)); + if (block_idx == trans->num_blocks) + return; + alloc->is_alloc = 1; + } /* First block is assigned via registers / context info */ if (trans->num_blocks == 1) return; cmd->num_frags = cpu_to_le32(1); - cmd->fragments[0].address = cpu_to_le64(phys_addr); - cmd->fragments[0].size = alloc->size; - cmd->allocation_id = alloc->allocation_id; - cmd->buffer_location = alloc->buffer_location; + cmd->fragments[0].address = + cpu_to_le64(trans->fw_mon[block_idx].physical); + cmd->fragments[0].size = alloc->tlv.size; + cmd->allocation_id = alloc->tlv.allocation_id; + cmd->buffer_location = alloc->tlv.buffer_location; iwl_trans_send_cmd(trans, &hcmd); } @@ -1746,9 +1759,8 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, int i, size = le32_to_cpu(tlv->num_regions); for (i = 0; i < size; i++) { - struct iwl_fw_ini_region_cfg *reg = iter; + struct iwl_fw_ini_region_cfg *reg = iter, **active; int id = le32_to_cpu(reg->region_id); - struct iwl_fw_ini_active_regs *active; if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), "Invalid region id %d for apply point %d\n", id, pnt)) @@ -1756,17 +1768,14 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, active = &fwrt->dump.active_regs[id]; - if (ext && active->apply_point == pnt) - IWL_WARN(fwrt->trans, - "External region TLV overrides FW default %x\n", - id); + if (*active) + IWL_WARN(fwrt->trans, "region TLV %d override\n", id); IWL_DEBUG_FW(fwrt, "%s: apply point %d, activating region ID %d\n", __func__, pnt, id); - active->reg = reg; - active->apply_point = pnt; + *active = reg; if (le32_to_cpu(reg->region_type) != IWL_FW_INI_REGION_DRAM_BUFFER) @@ -1842,9 +1851,13 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, u32 type = le32_to_cpu(tlv->type); switch (type) { - case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: - iwl_fw_dbg_buffer_allocation(fwrt, ini_tlv); + case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: { + struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv; + + iwl_fw_dbg_buffer_apply(fwrt, ini_tlv); + iter += sizeof(buf_alloc->is_alloc); break; + } case IWL_UCODE_TLV_TYPE_HCMD: if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) { IWL_ERR(fwrt, @@ -1875,6 +1888,12 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, enum iwl_fw_ini_apply_point apply_point) { void *data = &fwrt->trans->apply_points[apply_point]; + int i; + + if (apply_point == IWL_FW_INI_APPLY_EARLY) { + for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++) + fwrt->dump.active_regs[i] = NULL; + } _iwl_fw_dbg_apply_point(fwrt, data, apply_point, false); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 12333167ea23..23f982be800f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -222,6 +222,15 @@ struct iwl_fw_dbg { u32 dump_mask; }; +/** + * @tlv: the buffer allocation tlv + * @is_alloc: indicates if the buffer was already allocated + */ +struct iwl_fw_ini_allocation_data { + struct iwl_fw_ini_allocation_tlv tlv; + u32 is_alloc; +} __packed; + /** * struct iwl_fw_ini_active_triggers * @active: is this trigger active @@ -236,16 +245,6 @@ struct iwl_fw_ini_active_triggers { struct iwl_fw_ini_trigger *conf_ext; }; -/** - * struct iwl_fw_ini_active_regs - * @reg: active region from TLV - * @apply_point: apply point where it became active - */ -struct iwl_fw_ini_active_regs { - struct iwl_fw_ini_region_cfg *reg; - enum iwl_fw_ini_apply_point apply_point; -}; - /** * struct iwl_fw - variables associated with the firmware * diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 9ff04ffba3fa..52af848f2eb3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -139,7 +139,7 @@ struct iwl_fw_runtime { /* ts of the beginning of a non-collect fw dbg data period */ unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM - 1]; u32 *d3_debug_data; - struct iwl_fw_ini_active_regs active_regs[IWL_FW_INI_MAX_REGION_ID]; + struct iwl_fw_ini_region_cfg *active_regs[IWL_FW_INI_MAX_REGION_ID]; struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM]; u32 lmac_err_id[MAX_NUM_LMAC]; u32 umac_err_id; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 43d815cb3ce9..5798f434f68f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -71,6 +71,7 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, u32 apply_point = le32_to_cpu(header->apply_point); int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv); + int offset_size = copy_size; if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM, "Invalid apply point id %d\n", apply_point)) @@ -81,17 +82,25 @@ void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv, else data = &trans->apply_points[apply_point]; + /* add room for is_alloc field in &iwl_fw_ini_allocation_data struct */ + if (le32_to_cpu(tlv->type) == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) { + struct iwl_fw_ini_allocation_data *buf_alloc = + (void *)tlv->data; + + offset_size += sizeof(buf_alloc->is_alloc); + } + /* * Make sure we still have room to copy this TLV. Offset points to the * location the last copy ended. */ - if (WARN_ONCE(data->offset + copy_size > data->size, + if (WARN_ONCE(data->offset + offset_size > data->size, "Not enough memory for apply point %d\n", apply_point)) return; memcpy(data->data + data->offset, (void *)tlv, copy_size); - data->offset += copy_size; + data->offset += offset_size; } void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, @@ -129,6 +138,16 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM)) continue; + /* add room for is_alloc field in &iwl_fw_ini_allocation_data + * struct + */ + if (tlv_type == IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION) { + struct iwl_fw_ini_allocation_data *buf_alloc = + (void *)tlv->data; + + size[apply] += sizeof(buf_alloc->is_alloc); + } + size[apply] += sizeof(*tlv) + tlv_len; } -- cgit v1.2.3 From 74cf15cb69c0beb6cdaae3ff43f5231232a1f1b0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 3 Dec 2018 15:59:40 +0100 Subject: iwlwifi: mvm: add HE TB PPDU SIG-A BW to radiotap Expose the trigger-based PPDU SIG-A bandwidth to radiotap in the newly defined bits thereof. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 21 +++++++++++++++------ include/net/ieee80211_radiotap.h | 6 ++++++ 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index b5ff3325c1d3..d2728fe6a041 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -960,6 +960,7 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data, * the TSF/timers are not be transmitted in HE-MU. */ u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK); + u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK; u8 offs = 0; rx_status->bw = RATE_INFO_BW_HE_RU; @@ -1002,19 +1003,27 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data, he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC); - if (he_mu) { #define CHECK_BW(bw) \ BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_ ## bw ## MHZ != \ + RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS); \ + BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_ ## bw ## MHZ != \ RATE_MCS_CHAN_WIDTH_##bw >> RATE_MCS_CHAN_WIDTH_POS) - CHECK_BW(20); - CHECK_BW(40); - CHECK_BW(80); - CHECK_BW(160); + CHECK_BW(20); + CHECK_BW(40); + CHECK_BW(80); + CHECK_BW(160); + + if (he_mu) he_mu->flags2 |= le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, rate_n_flags), IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW); - } + else if (he_type == RATE_MCS_HE_TYPE_TRIG) + he->data6 |= + cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) | + le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK, + rate_n_flags), + IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW); } static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 8014153bdd49..38c48bb80439 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h @@ -291,6 +291,12 @@ enum ieee80211_radiotap_he_bits { IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f, IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010, + IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN = 0x0020, + IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW = 0x00c0, + IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_20MHZ = 0, + IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_40MHZ = 1, + IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_80MHZ = 2, + IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_160MHZ = 3, IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00, IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000, }; -- cgit v1.2.3 From 45108c5d6870f3ccdf0e84518593572eddfd5ad0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Dec 2018 09:04:55 +0100 Subject: iwlwifi: move config structs to C file Even if they're static const, there's no need to duplicate the structs every time they're included and used. Move them to an appropriate C file instead. Also remove useless parentheses along the way. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 31 ++---------------------- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 32 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index ff942532fac3..f1e493380713 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -445,35 +445,8 @@ struct iwl_cfg { u32 d3_debug_data_length; }; -static const struct iwl_csr_params iwl_csr_v1 = { - .flag_mac_clock_ready = 0, - .flag_val_mac_access_en = 0, - .flag_init_done = 2, - .flag_mac_access_req = 3, - .flag_sw_reset = 7, - .flag_master_dis = 8, - .flag_stop_master = 9, - .addr_sw_reset = (CSR_BASE + 0x020), - .mac_addr0_otp = 0x380, - .mac_addr1_otp = 0x384, - .mac_addr0_strap = 0x388, - .mac_addr1_strap = 0x38C -}; - -static const struct iwl_csr_params iwl_csr_v2 = { - .flag_init_done = 6, - .flag_mac_clock_ready = 20, - .flag_val_mac_access_en = 20, - .flag_mac_access_req = 21, - .flag_master_dis = 28, - .flag_stop_master = 29, - .flag_sw_reset = 31, - .addr_sw_reset = (CSR_BASE + 0x024), - .mac_addr0_otp = 0x30, - .mac_addr1_otp = 0x34, - .mac_addr0_strap = 0x38, - .mac_addr1_strap = 0x3C -}; +extern const struct iwl_csr_params iwl_csr_v1; +extern const struct iwl_csr_params iwl_csr_v2; /* * This list declares the config structures for all devices. diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index ffd1e649bfa0..d62eb2d9389a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -7,6 +7,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 - 2016 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -28,6 +29,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 - 2016 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,6 +70,36 @@ #include "iwl-prph.h" #include "iwl-fh.h" +const struct iwl_csr_params iwl_csr_v1 = { + .flag_mac_clock_ready = 0, + .flag_val_mac_access_en = 0, + .flag_init_done = 2, + .flag_mac_access_req = 3, + .flag_sw_reset = 7, + .flag_master_dis = 8, + .flag_stop_master = 9, + .addr_sw_reset = CSR_BASE + 0x020, + .mac_addr0_otp = 0x380, + .mac_addr1_otp = 0x384, + .mac_addr0_strap = 0x388, + .mac_addr1_strap = 0x38C +}; + +const struct iwl_csr_params iwl_csr_v2 = { + .flag_init_done = 6, + .flag_mac_clock_ready = 20, + .flag_val_mac_access_en = 20, + .flag_mac_access_req = 21, + .flag_master_dis = 28, + .flag_stop_master = 29, + .flag_sw_reset = 31, + .addr_sw_reset = CSR_BASE + 0x024, + .mac_addr0_otp = 0x30, + .mac_addr1_otp = 0x34, + .mac_addr0_strap = 0x38, + .mac_addr1_strap = 0x3C +}; + void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) { trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); -- cgit v1.2.3 From 32a378539a37428903637904a815e79eecd5b8be Mon Sep 17 00:00:00 2001 From: Naftali Goldstein Date: Mon, 10 Dec 2018 08:50:01 +0200 Subject: iwlwifi: mvm: add description to second BAD_COMMAND assert number Depending on exactly what happens in the FW, an invalid host-command could result in either assert 0x38 or 0x39. Add 0x39 to the assert-name table. Signed-off-by: Naftali Goldstein Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 211c4638d690..92f61e8a6284 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -294,6 +294,7 @@ static const struct { { "SYSASSERT", 0x35 }, { "UCODE_VERSION_MISMATCH", 0x37 }, { "BAD_COMMAND", 0x38 }, + { "BAD_COMMAND", 0x39 }, { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, { "FATAL_ERROR", 0x3D }, { "NMI_TRM_HW_ERR", 0x46 }, -- cgit v1.2.3 From 3619b088a87905a28d51b10172ff1e923c692cd7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Dec 2018 10:36:29 +0100 Subject: iwlwifi: mvm: don't hide HE radiotap data in SKB Hiding the HE radiotap data for further processing of the SKB just caused another bug when adding the L-SIG data. Simply stop doing this and adjust the skb->data pointer accordingly when we need to get the 802.11 header. While at it, also verify and fix the data alignment, we need to add 2 bytes padding with the vendor data to ensure the whole length of all radiotap headers is a multiple of 4. Signed-off-by: Johannes Berg Fixes: 6721039d5b8a ("iwlwifi: mvm: add L-SIG length to radiotap") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 47 ++++++++++++++++++++------- 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index d2728fe6a041..957d99932e8b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -66,11 +66,37 @@ #include "mvm.h" #include "fw-api.h" +static void *iwl_mvm_skb_get_hdr(struct sk_buff *skb) +{ + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + u8 *data = skb->data; + + /* Alignment concerns */ + BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he) % 4); + BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) % 4); + BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_lsig) % 4); + BUILD_BUG_ON(sizeof(struct ieee80211_vendor_radiotap) % 4); + + if (rx_status->flag & RX_FLAG_RADIOTAP_HE) + data += sizeof(struct ieee80211_radiotap_he); + if (rx_status->flag & RX_FLAG_RADIOTAP_HE_MU) + data += sizeof(struct ieee80211_radiotap_he_mu); + if (rx_status->flag & RX_FLAG_RADIOTAP_LSIG) + data += sizeof(struct ieee80211_radiotap_lsig); + if (rx_status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) { + struct ieee80211_vendor_radiotap *radiotap = (void *)data; + + data += sizeof(*radiotap) + radiotap->len + radiotap->pad; + } + + return data; +} + static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, int queue, struct ieee80211_sta *sta) { struct iwl_mvm_sta *mvmsta; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb); struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb); struct iwl_mvm_key_pn *ptk_pn; int res; @@ -197,12 +223,15 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, { struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); struct ieee80211_vendor_radiotap *radiotap; - int size = sizeof(*radiotap) + sizeof(__le16); + const int size = sizeof(*radiotap) + sizeof(__le16); if (!mvm->cur_aid) return; - radiotap = skb_put(skb, size); + /* ensure alignment */ + BUILD_BUG_ON((size + 2) % 4); + + radiotap = skb_put(skb, size + 2); radiotap->align = 1; /* Intel OUI */ radiotap->oui[0] = 0xf6; @@ -212,10 +241,12 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm, radiotap->subns = 1; radiotap->present = 0x1; radiotap->len = size - sizeof(*radiotap); - radiotap->pad = 0; + radiotap->pad = 2; /* fill the data now */ memcpy(radiotap->data, &mvm->cur_aid, sizeof(mvm->cur_aid)); + /* and clear the padding */ + memset(radiotap->data + sizeof(__le16), 0, radiotap->pad); rx_status->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA; } @@ -663,7 +694,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, struct sk_buff *skb, struct iwl_rx_mpdu_desc *desc) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb); struct iwl_mvm_sta *mvm_sta; struct iwl_mvm_baid_data *baid_data; struct iwl_mvm_reorder_buffer *buffer; @@ -1174,22 +1205,16 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb, .flags2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN | IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), }; - unsigned int radiotap_len = 0; he = skb_put_data(skb, &known, sizeof(known)); - radiotap_len += sizeof(known); rx_status->flag |= RX_FLAG_RADIOTAP_HE; if (phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU || phy_data->info_type == IWL_RX_PHY_INFO_TYPE_HE_MU_EXT) { he_mu = skb_put_data(skb, &mu_known, sizeof(mu_known)); - radiotap_len += sizeof(mu_known); rx_status->flag |= RX_FLAG_RADIOTAP_HE_MU; } - /* temporarily hide the radiotap data */ - __skb_pull(skb, radiotap_len); - /* report the AMPDU-EOF bit on single frames */ if (!queue && !(phy_info & IWL_RX_MPDU_PHY_AMPDU)) { rx_status->flag |= RX_FLAG_AMPDU_DETAILS; -- cgit v1.2.3 From 537ea3bb744ebd3cad188aa179a01d07bfb5c6dd Mon Sep 17 00:00:00 2001 From: Avigail Grinstein Date: Sun, 28 Oct 2018 17:16:44 +0200 Subject: iwlwifi: mvm: support absolute thresholds in bf configuration Update iwl_beacon_filter_cmd to support BEACON_FILTER_CONFIG_API_S_VER_4. Currently driver configs them to be zero (i.e. disable them, so no change is applied). Signed-off-by: Avigail Grinstein Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/power.h | 11 ++++++++++- drivers/net/wireless/intel/iwlwifi/fw/file.h | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/power.c | 20 +++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 286a22da232d..5844898ee92c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -470,6 +470,13 @@ struct iwl_geo_tx_power_profiles_resp { * @ba_escape_timer: Fully receive and parse beacon if no beacons were passed * for a longer period of time then this escape-timeout. Units: Beacons. * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. + * @bf_threshold_absolute_low: See below. + * @bf_threshold_absolute_high: Send Beacon to driver if Energy value calculated + * for this beacon crossed this absolute threshold. For the 'Increase' + * direction the bf_energy_absolute_low[i] is used. For the 'Decrease' + * direction the bf_energy_absolute_high[i] is used. Zero value means + * that this specific threshold is ignored for beacon filtering, and + * beacon will not be forced to be sent to driver due to this setting. */ struct iwl_beacon_filter_cmd { __le32 bf_energy_delta; @@ -483,7 +490,9 @@ struct iwl_beacon_filter_cmd { __le32 bf_escape_timer; __le32 ba_escape_timer; __le32 ba_enable_beacon_abort; -} __packed; + __le32 bf_threshold_absolute_low[2]; + __le32 bf_threshold_absolute_high[2]; +} __packed; /* BEACON_FILTER_CONFIG_API_S_VER_4 */ /* Beacon filtering and beacon abort */ #define IWL_BF_ENERGY_DELTA_DEFAULT 5 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index a6dd27fbe4aa..8c6ce4142204 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -265,6 +265,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; * the REDUCE_TX_POWER_CMD. * @IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF: This ucode supports the short * version of the beacon notification. + * @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of + * BEACON_FILTER_CONFIG_API_S_VER_4. * * @NUM_IWL_UCODE_TLV_API: number of bits used */ @@ -290,6 +292,7 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_FRAG_EBS = (__force iwl_ucode_tlv_api_t)44, IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45, IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46, + IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47, NUM_IWL_UCODE_TLV_API #ifdef __CHECKER__ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 5a0a28fd762d..df9f1d6cdf78 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -79,6 +81,8 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, struct iwl_beacon_filter_cmd *cmd, u32 flags) { + u16 len; + IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", le32_to_cpu(cmd->ba_enable_beacon_abort)); IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", @@ -101,9 +105,23 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, le32_to_cpu(cmd->bf_temp_fast_filter)); IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n", le32_to_cpu(cmd->bf_temp_slow_filter)); + IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_low is: %d, %d\n", + le32_to_cpu(cmd->bf_threshold_absolute_low[0]), + le32_to_cpu(cmd->bf_threshold_absolute_low[1])); + + IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_high is: %d, %d\n", + le32_to_cpu(cmd->bf_threshold_absolute_high[0]), + le32_to_cpu(cmd->bf_threshold_absolute_high[1])); + + if (fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_BEACON_FILTER_V4)) + len = sizeof(struct iwl_beacon_filter_cmd); + else + len = offsetof(struct iwl_beacon_filter_cmd, + bf_threshold_absolute_low); return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, flags, - sizeof(struct iwl_beacon_filter_cmd), cmd); + len, cmd); } static -- cgit v1.2.3 From 608dce95db10b8ee1a26dbce3f60204bb69812a5 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 12 Dec 2018 09:45:11 +0200 Subject: iwlwifi: mvm: fix RSS config command The hash mask is a bitmap, so we should use BIT() on the enum values. Signed-off-by: Sara Sharon Fixes: 43413a975d06 ("iwlwifi: mvm: support rss queues configuration command") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index d8ae9561a9b0..134dab2d774a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -105,12 +105,12 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) int i; struct iwl_rss_config_cmd cmd = { .flags = cpu_to_le32(IWL_RSS_ENABLE), - .hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP | - IWL_RSS_HASH_TYPE_IPV4_UDP | - IWL_RSS_HASH_TYPE_IPV4_PAYLOAD | - IWL_RSS_HASH_TYPE_IPV6_TCP | - IWL_RSS_HASH_TYPE_IPV6_UDP | - IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, + .hash_mask = BIT(IWL_RSS_HASH_TYPE_IPV4_TCP) | + BIT(IWL_RSS_HASH_TYPE_IPV4_UDP) | + BIT(IWL_RSS_HASH_TYPE_IPV4_PAYLOAD) | + BIT(IWL_RSS_HASH_TYPE_IPV6_TCP) | + BIT(IWL_RSS_HASH_TYPE_IPV6_UDP) | + BIT(IWL_RSS_HASH_TYPE_IPV6_PAYLOAD), }; if (mvm->trans->num_rx_queues == 1) -- cgit v1.2.3 From 9deb52c68fb5419875745e3f1c78836a331b5e6b Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 5 Dec 2018 14:02:53 +0200 Subject: iwlwifi: dbg_ini: align struct iwl_fw_ini_region_cfg to the FW New fields were added to struct iwl_fw_ini_region_cfg. add those field and apply the changes the result from this change offset field is used to differentiate between the different LMACs and any memory access to the region addresses should be base_addr + offset. A fifo struct is to hold the meta data needed for fifo regions Also move range_data_size and num_of_ranges into a struct under the union to be aligned to the struct in the FW. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 40 +++++++++++++++++---- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 41 ++++++++++++++-------- 2 files changed, 60 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index 4926950d432a..75e23c426be8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -133,6 +133,33 @@ struct iwl_fw_ini_debug_flow_tlv { #define IWL_FW_INI_MAX_REGION_ID 64 #define IWL_FW_INI_MAX_NAME 32 + +/** + * struct iwl_fw_ini_region_cfg_internal - meta data of internal memory region + * @num_of_range: the amount of ranges in the region + * @range_data_size: size of the data to read per range, in bytes. + */ +struct iwl_fw_ini_region_cfg_internal { + __le32 num_of_ranges; + __le32 range_data_size; +} __packed; /* FW_DEBUG_TLV_REGION_NIC_INTERNAL_RANGES_S */ + +/** + * struct iwl_fw_ini_region_cfg_fifos - meta data of fifos region + * @lmac1_id: bit map of lmac1 fifos to include in the region. + * @lmac2_id: bit map of lmac2 fifos to include in the region. + * @num_of_registers: number of prph registers in the region, each register is + * 4 bytes size. + * @header_only: none zero value indicates that this region does not include + * fifo data and includes only the given registers. + */ +struct iwl_fw_ini_region_cfg_fifos { + __le32 lmac1_id; + __le32 lmac2_id; + __le32 num_of_registers; + __le32 header_only; +} __packed; /* FW_DEBUG_TLV_REGION_FIFOS_S */ + /** * struct iwl_fw_ini_region_cfg * @region_id: ID of this dump configuration @@ -140,11 +167,11 @@ struct iwl_fw_ini_debug_flow_tlv { * @num_regions: amount of regions in the address array. * @name_len: name length * @name: file name to use for this region - * @num_of_range: the amount of ranges in the region. + * @internal: used in case the region uses internal memory. * @allocation_id: For DRAM type field substitutes for allocation_id - * @range_data_size: size of the data to read per range, in bytes. - * @start_addr: array of addresses. for type IWL_FW_INI_REGION_DRAM_BUFFER, - * 1 entry. For any other case, num_of_ranges entries. + * @fifos: used in case of fifos region. + * @offset: offset to use for each memory base address + * @start_addr: array of addresses. */ struct iwl_fw_ini_region_cfg { __le32 region_id; @@ -152,10 +179,11 @@ struct iwl_fw_ini_region_cfg { __le32 name_len; u8 name[IWL_FW_INI_MAX_NAME]; union { - __le32 num_of_ranges; + struct iwl_fw_ini_region_cfg_internal internal; __le32 allocation_id; + struct iwl_fw_ini_region_cfg_fifos fifos; }; - __le32 range_data_size; + __le32 offset; __le32 start_addr[]; } __packed; /* FW_DEBUG_TLV_REGION_CONFIG_S */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 5feae549d316..9bcce27c6bcf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1068,7 +1068,7 @@ static void iwl_dump_prph_ini(struct iwl_trans *trans, { struct iwl_fw_error_dump_prph *prph; unsigned long flags; - u32 i, size = le32_to_cpu(reg->num_of_ranges); + u32 i, size = le32_to_cpu(reg->internal.num_of_ranges); IWL_DEBUG_INFO(trans, "WRT PRPH dump\n"); @@ -1077,8 +1077,9 @@ static void iwl_dump_prph_ini(struct iwl_trans *trans, for (i = 0; i < size; i++) { (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); - (*data)->len = cpu_to_le32(le32_to_cpu(reg->range_data_size) + - sizeof(*prph)); + (*data)->len = + cpu_to_le32(le32_to_cpu(reg->internal.range_data_size) + + sizeof(*prph)); prph = (void *)(*data)->data; prph->prph_start = reg->start_addr[i]; prph->data[0] = cpu_to_le32(iwl_read_prph_no_grab(trans, @@ -1092,8 +1093,8 @@ static void iwl_dump_csr_ini(struct iwl_trans *trans, struct iwl_fw_error_dump_data **data, struct iwl_fw_ini_region_cfg *reg) { - int i, num = le32_to_cpu(reg->num_of_ranges); - u32 size = le32_to_cpu(reg->range_data_size); + int i, num = le32_to_cpu(reg->internal.num_of_ranges); + u32 size = le32_to_cpu(reg->internal.range_data_size); IWL_DEBUG_INFO(trans, "WRT CSR dump\n"); @@ -1136,13 +1137,13 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, continue; type = le32_to_cpu(reg->region_type); - num_entries = le32_to_cpu(reg->num_of_ranges); + num_entries = le32_to_cpu(reg->internal.num_of_ranges); switch (type) { case IWL_FW_INI_REGION_DEVICE_MEMORY: size += hdr_len + sizeof(struct iwl_fw_error_dump_named_mem) + - le32_to_cpu(reg->range_data_size); + le32_to_cpu(reg->internal.range_data_size); break; case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: @@ -1168,7 +1169,8 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, break; case IWL_FW_INI_REGION_CSR: size += num_entries * - (hdr_len + le32_to_cpu(reg->range_data_size)); + (hdr_len + + le32_to_cpu(reg->internal.range_data_size)); break; case IWL_FW_INI_REGION_DRAM_BUFFER: /* Transport takes care of DRAM dumping */ @@ -1204,15 +1206,20 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, type = le32_to_cpu(reg->region_type); switch (type) { - case IWL_FW_INI_REGION_DEVICE_MEMORY: - if (WARN_ON(le32_to_cpu(reg->num_of_ranges) > 1)) + case IWL_FW_INI_REGION_DEVICE_MEMORY: { + u32 num_of_ranges = + le32_to_cpu(reg->internal.num_of_ranges); + u32 range_data_size = + le32_to_cpu(reg->internal.range_data_size); + + if (WARN_ON(num_of_ranges) > 1) continue; - iwl_fw_dump_named_mem(fwrt, data, - le32_to_cpu(reg->range_data_size), + iwl_fw_dump_named_mem(fwrt, data, range_data_size, le32_to_cpu(reg->start_addr[0]), reg->name, le32_to_cpu(reg->name_len)); break; + } case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: @@ -1761,6 +1768,7 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, for (i = 0; i < size; i++) { struct iwl_fw_ini_region_cfg *reg = iter, **active; int id = le32_to_cpu(reg->region_id); + u32 type = le32_to_cpu(reg->region_type); if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), "Invalid region id %d for apply point %d\n", id, pnt)) @@ -1777,9 +1785,12 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, *active = reg; - if (le32_to_cpu(reg->region_type) != - IWL_FW_INI_REGION_DRAM_BUFFER) - iter += le32_to_cpu(reg->num_of_ranges) * + if (type == IWL_FW_INI_REGION_TXF || + type == IWL_FW_INI_REGION_RXF) + iter += le32_to_cpu(reg->fifos.num_of_registers) * + sizeof(__le32); + else if (type != IWL_FW_INI_REGION_DRAM_BUFFER) + iter += le32_to_cpu(reg->internal.num_of_ranges) * sizeof(__le32); iter += sizeof(*reg); -- cgit v1.2.3 From 8d534e96b5000a20e80f91c2026e6671c7a0c921 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 3 Dec 2018 09:19:25 +0200 Subject: iwlwifi: dbg_ini: create new dump flow and implement prph dump Create a skeleton to unite all memory dumps in ini mode. Implement prph dump with the new skeleton. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 164 ++++++++++++++++----- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 4 + drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 34 +++++ 3 files changed, 163 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 9bcce27c6bcf..7fd7604751ef 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1062,33 +1062,6 @@ out: return dump_file; } -static void iwl_dump_prph_ini(struct iwl_trans *trans, - struct iwl_fw_error_dump_data **data, - struct iwl_fw_ini_region_cfg *reg) -{ - struct iwl_fw_error_dump_prph *prph; - unsigned long flags; - u32 i, size = le32_to_cpu(reg->internal.num_of_ranges); - - IWL_DEBUG_INFO(trans, "WRT PRPH dump\n"); - - if (!iwl_trans_grab_nic_access(trans, &flags)) - return; - - for (i = 0; i < size; i++) { - (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); - (*data)->len = - cpu_to_le32(le32_to_cpu(reg->internal.range_data_size) + - sizeof(*prph)); - prph = (void *)(*data)->data; - prph->prph_start = reg->start_addr[i]; - prph->data[0] = cpu_to_le32(iwl_read_prph_no_grab(trans, - le32_to_cpu(prph->prph_start))); - *data = iwl_fw_error_next_data(*data); - } - iwl_trans_release_nic_access(trans, &flags); -} - static void iwl_dump_csr_ini(struct iwl_trans *trans, struct iwl_fw_error_dump_data **data, struct iwl_fw_ini_region_cfg *reg) @@ -1114,20 +1087,131 @@ static void iwl_dump_csr_ini(struct iwl_trans *trans, } } +static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_error_dump_range *range, + struct iwl_fw_ini_region_cfg *reg, + int idx) +{ + __le32 *val = range->data; + u32 addr, prph_val, offset = le32_to_cpu(reg->offset); + int i; + + range->start_addr = reg->start_addr[idx]; + range->range_data_size = reg->internal.range_data_size; + for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { + addr = le32_to_cpu(range->start_addr) + i; + prph_val = iwl_read_prph(fwrt->trans, addr + offset); + if (prph_val == 0x5a5a5a5a) + return -1; + *val++ = cpu_to_le32(prph_val); + } + return le32_to_cpu(range->range_data_size); +} + +static struct iwl_fw_ini_error_dump_range +*iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data) +{ + struct iwl_fw_ini_error_dump *dump = data; + + return dump->ranges; +} + +static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return le32_to_cpu(reg->internal.num_of_ranges) * + le32_to_cpu(reg->internal.range_data_size); +} + +static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return le32_to_cpu(reg->internal.num_of_ranges); +} + +/** + * struct iwl_dump_ini_mem_ops - ini memory dump operations + * @get_num_of_ranges: returns the number of memory ranges in the region. + * @get_size: returns the size of the region data without headers. + * @fill_mem_hdr: fills region type specific headers and returns the first + * range or NULL if failed to fill headers. + * @fill_range: copies a given memory range into the dump. + * Returns the size of the range or -1 otherwise. + */ +struct iwl_dump_ini_mem_ops { + u32 (*get_num_of_ranges)(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg); + u32 (*get_size)(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg); + struct iwl_fw_ini_error_dump_range * + (*fill_mem_hdr)(struct iwl_fw_runtime *fwrt, void *data); + int (*fill_range)(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_error_dump_range *range, + struct iwl_fw_ini_region_cfg *reg, int idx); +}; + +/** + * iwl_dump_ini_mem - copy a memory region into the dump + * @fwrt: fw runtime struct. + * @data: dump memory data. + * @reg: region to copy to the dump. + */ +static void +iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, + enum iwl_fw_ini_region_type type, + struct iwl_fw_error_dump_data **data, + struct iwl_fw_ini_region_cfg *reg, + struct iwl_dump_ini_mem_ops *ops) +{ + struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data; + struct iwl_fw_ini_error_dump_range *range; + u32 num_of_ranges, i; + + if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size || + !ops->fill_mem_hdr || !ops->fill_range)) + return; + + num_of_ranges = ops->get_num_of_ranges(fwrt, reg); + + (*data)->type = cpu_to_le32(type | INI_DUMP_BIT); + (*data)->len = cpu_to_le32(sizeof(*header) + num_of_ranges * + sizeof(*range) + ops->get_size(fwrt, reg)); + + header->num_of_ranges = cpu_to_le32(num_of_ranges); + header->name_len = cpu_to_le32(min_t(int, IWL_FW_INI_MAX_NAME, + le32_to_cpu(reg->name_len))); + memcpy(header->name, reg->name, le32_to_cpu(header->name_len)); + + range = ops->fill_mem_hdr(fwrt, header); + if (!range) + return; + + for (i = 0; i < num_of_ranges; i++) { + int range_data_size = ops->fill_range(fwrt, range, reg, i); + + if (range_data_size < 0) { + IWL_ERR(fwrt, "Failed to dump region type %d\n", type); + return; + } + range = ((void *)range) + sizeof(*range) + range_data_size; + } + *data = iwl_fw_error_next_data(*data); +} + static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_trigger *trigger) { - int i, num, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data); + int i, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data); + u32 dump_header_len = sizeof(struct iwl_fw_ini_error_dump); + u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range); if (!trigger || !trigger->num_regions) return 0; - num = le32_to_cpu(trigger->num_regions); - for (i = 0; i < num; i++) { + for (i = 0; i < le32_to_cpu(trigger->num_regions); i++) { u32 reg_id = le32_to_cpu(trigger->data[i]); struct iwl_fw_ini_region_cfg *reg; enum iwl_fw_ini_region_type type; - u32 num_entries; if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs))) continue; @@ -1137,8 +1221,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, continue; type = le32_to_cpu(reg->region_type); - num_entries = le32_to_cpu(reg->internal.num_of_ranges); - switch (type) { case IWL_FW_INI_REGION_DEVICE_MEMORY: size += hdr_len + @@ -1148,10 +1230,9 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: - size += num_entries * - (hdr_len + - sizeof(struct iwl_fw_error_dump_prph) + - sizeof(u32)); + size += hdr_len + dump_header_len + range_header_len * + iwl_dump_ini_mem_ranges(fwrt, reg) + + iwl_dump_ini_mem_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_TXF: size += iwl_fw_txf_len(fwrt, &fwrt->smem_cfg); @@ -1168,7 +1249,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, PAGING_BLOCK_SIZE); break; case IWL_FW_INI_REGION_CSR: - size += num_entries * + size += le32_to_cpu(reg->internal.num_of_ranges) * (hdr_len + le32_to_cpu(reg->internal.range_data_size)); break; @@ -1195,6 +1276,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, u32 reg_id = le32_to_cpu(trigger->data[i]); enum iwl_fw_ini_region_type type; struct iwl_fw_ini_region_cfg *reg; + struct iwl_dump_ini_mem_ops ops; if (reg_id >= ARRAY_SIZE(fwrt->dump.active_regs)) continue; @@ -1223,7 +1305,11 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: - iwl_dump_prph_ini(fwrt->trans, data, reg); + ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; + ops.get_size = iwl_dump_ini_mem_get_size; + ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; + ops.fill_range = iwl_dump_ini_prph_iter; + iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; case IWL_FW_INI_REGION_DRAM_BUFFER: *dump_mask |= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 2fa7a19e02b6..a6133b5f9e83 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -441,4 +441,8 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, enum iwl_fw_ini_apply_point apply_point); void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt); + +/* This bit is used to differentiate the legacy dump from the ini dump */ +#define INI_DUMP_BIT BIT(31) + #endif /* __iwl_fw_dbg_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index e1c6aa61ab90..fb2ff29762e2 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -290,6 +290,40 @@ struct iwl_fw_error_dump_named_mem { u8 data[]; }; +/** + * struct iwl_fw_ini_error_dump_range - range of memory + * @start_addr: the start address of this range + * @range_data_size: the size of this range, in bytes + * @data: the actual memory + */ +struct iwl_fw_ini_error_dump_range { + __le32 start_addr; + __le32 range_data_size; + __le32 data[]; +} __packed; + +/** + * struct iwl_fw_ini_error_dump_header - ini region dump header + * @num_of_ranges: number of ranges in this region + * @name_len: number of bytes allocated to the name string of this region + * @name: name of the region + */ +struct iwl_fw_ini_error_dump_header { + __le32 num_of_ranges; + __le32 name_len; + u8 name[IWL_FW_INI_MAX_NAME]; +}; + +/** + * struct iwl_fw_ini_error_dump - ini region dump + * @header: the header of this region + * @ranges: the memory ranges of this this region + */ +struct iwl_fw_ini_error_dump { + struct iwl_fw_ini_error_dump_header header; + struct iwl_fw_ini_error_dump_range ranges[]; +} __packed; + /** * struct iwl_fw_error_dump_rb - content of an Receive Buffer * @index: the index of the Receive Buffer in the Rx queue -- cgit v1.2.3 From f4f907aa73e0b6389fb92b1c611048838f83c24d Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 3 Dec 2018 12:13:31 +0200 Subject: iwlwifi: dbg_ini: implement csr memory dump Implement csr memory dump in the new dump mechanism. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 56 +++++++++++++---------------- 1 file changed, 25 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 7fd7604751ef..e34b287a5405 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1062,31 +1062,6 @@ out: return dump_file; } -static void iwl_dump_csr_ini(struct iwl_trans *trans, - struct iwl_fw_error_dump_data **data, - struct iwl_fw_ini_region_cfg *reg) -{ - int i, num = le32_to_cpu(reg->internal.num_of_ranges); - u32 size = le32_to_cpu(reg->internal.range_data_size); - - IWL_DEBUG_INFO(trans, "WRT CSR dump\n"); - - for (i = 0; i < num; i++) { - u32 add = le32_to_cpu(reg->start_addr[i]); - __le32 *val; - int j; - - (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR); - (*data)->len = cpu_to_le32(size); - val = (void *)(*data)->data; - - for (j = 0; j < size; j += 4) - *val++ = cpu_to_le32(iwl_trans_read32(trans, j + add)); - - *data = iwl_fw_error_next_data(*data); - } -} - static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_error_dump_range *range, struct iwl_fw_ini_region_cfg *reg, @@ -1108,6 +1083,25 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, return le32_to_cpu(range->range_data_size); } +static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_error_dump_range *range, + struct iwl_fw_ini_region_cfg *reg, + int idx) +{ + __le32 *val = range->data; + u32 addr, offset = le32_to_cpu(reg->offset); + int i; + + range->start_addr = reg->start_addr[idx]; + range->range_data_size = reg->internal.range_data_size; + for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { + addr = le32_to_cpu(range->start_addr) + i; + *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, + addr + offset)); + } + return le32_to_cpu(range->range_data_size); +} + static struct iwl_fw_ini_error_dump_range *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data) { @@ -1230,6 +1224,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: + case IWL_FW_INI_REGION_CSR: size += hdr_len + dump_header_len + range_header_len * iwl_dump_ini_mem_ranges(fwrt, reg) + iwl_dump_ini_mem_get_size(fwrt, reg); @@ -1248,11 +1243,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, sizeof(struct iwl_fw_error_dump_paging) + PAGING_BLOCK_SIZE); break; - case IWL_FW_INI_REGION_CSR: - size += le32_to_cpu(reg->internal.num_of_ranges) * - (hdr_len + - le32_to_cpu(reg->internal.range_data_size)); - break; case IWL_FW_INI_REGION_DRAM_BUFFER: /* Transport takes care of DRAM dumping */ case IWL_FW_INI_REGION_INTERNAL_BUFFER: @@ -1327,7 +1317,11 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, iwl_fw_dump_rxf(fwrt, data); break; case IWL_FW_INI_REGION_CSR: - iwl_dump_csr_ini(fwrt->trans, data, reg); + ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; + ops.get_size = iwl_dump_ini_mem_get_size; + ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; + ops.fill_range = iwl_dump_ini_csr_iter; + iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; case IWL_FW_INI_REGION_DRAM_IMR: case IWL_FW_INI_REGION_INTERNAL_BUFFER: -- cgit v1.2.3 From 6e9f8f9924393fc12827a1a9362a34bb53b8e64f Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 3 Dec 2018 13:40:24 +0200 Subject: iwlwifi: dbg_ini: implement device internal memory dump Implement device internal memory dump in the new dump mechanism. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 60 ++++++++-------------- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 16 ------ 2 files changed, 21 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index e34b287a5405..edad8175c2a3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -707,28 +707,6 @@ static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt, IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type); } -static void iwl_fw_dump_named_mem(struct iwl_fw_runtime *fwrt, - struct iwl_fw_error_dump_data **dump_data, - u32 len, u32 ofs, u8 *name, u8 name_len) -{ - struct iwl_fw_error_dump_named_mem *dump_mem; - - if (!len) - return; - - (*dump_data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); - (*dump_data)->len = cpu_to_le32(len + sizeof(*dump_mem)); - dump_mem = (void *)(*dump_data)->data; - dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_NAMED_MEM); - dump_mem->offset = cpu_to_le32(ofs); - dump_mem->name_len = name_len; - memcpy(dump_mem->name, name, name_len); - iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len); - *dump_data = iwl_fw_error_next_data(*dump_data); - - IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type); -} - #define ADD_LEN(len, item_len, const_len) \ do {size_t item = item_len; len += (!!item) * const_len + item; } \ while (0) @@ -1102,6 +1080,21 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt, return le32_to_cpu(range->range_data_size); } +static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_error_dump_range *range, + struct iwl_fw_ini_region_cfg *reg, + int idx) +{ + u32 addr = le32_to_cpu(range->start_addr); + u32 offset = le32_to_cpu(reg->offset); + + range->start_addr = reg->start_addr[idx]; + range->range_data_size = reg->internal.range_data_size; + iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data, + le32_to_cpu(reg->internal.range_data_size)); + return le32_to_cpu(range->range_data_size); +} + static struct iwl_fw_ini_error_dump_range *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data) { @@ -1217,10 +1210,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, type = le32_to_cpu(reg->region_type); switch (type) { case IWL_FW_INI_REGION_DEVICE_MEMORY: - size += hdr_len + - sizeof(struct iwl_fw_error_dump_named_mem) + - le32_to_cpu(reg->internal.range_data_size); - break; case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: @@ -1278,20 +1267,13 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, type = le32_to_cpu(reg->region_type); switch (type) { - case IWL_FW_INI_REGION_DEVICE_MEMORY: { - u32 num_of_ranges = - le32_to_cpu(reg->internal.num_of_ranges); - u32 range_data_size = - le32_to_cpu(reg->internal.range_data_size); - - if (WARN_ON(num_of_ranges) > 1) - continue; - iwl_fw_dump_named_mem(fwrt, data, range_data_size, - le32_to_cpu(reg->start_addr[0]), - reg->name, - le32_to_cpu(reg->name_len)); + case IWL_FW_INI_REGION_DEVICE_MEMORY: + ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; + ops.get_size = iwl_dump_ini_mem_get_size; + ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; + ops.fill_range = iwl_dump_ini_dev_mem_iter; + iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; - } case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index fb2ff29762e2..42e0c4c93c82 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -274,22 +274,6 @@ struct iwl_fw_error_dump_mem { u8 data[]; }; -/** - * struct iwl_fw_error_dump_named_mem - chunk of memory - * @type: &enum iwl_fw_error_dump_mem_type - * @offset: the offset from which the memory was read - * @name_len: name length - * @name: file name - * @data: the content of the memory - */ -struct iwl_fw_error_dump_named_mem { - __le32 type; - __le32 offset; - u8 name_len; - u8 name[32]; - u8 data[]; -}; - /** * struct iwl_fw_ini_error_dump_range - range of memory * @start_addr: the start address of this range -- cgit v1.2.3 From 505a00c071132689611d66cb61625282df9bee12 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 5 Dec 2018 10:08:19 +0200 Subject: iwlwifi: dbg_ini: implement paging memory dump Implement paging memory dump in the new dump mechanism. To support this change, moved iwl_self_init_dram strcut from trans_pcie to trans so that it will accessible via fw_runtime. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 114 ++++++++++++++++++--- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 15 +++ .../net/wireless/intel/iwlwifi/pcie/ctxt-info.c | 6 +- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 18 +--- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 10 +- 5 files changed, 125 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index edad8175c2a3..390401300fcf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1095,6 +1095,43 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, return le32_to_cpu(range->range_data_size); } +static int +iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_error_dump_range *range, + struct iwl_fw_ini_region_cfg *reg, + int idx) +{ + u32 page_size = fwrt->trans->init_dram.paging[idx].size; + + range->start_addr = cpu_to_le32(idx); + range->range_data_size = cpu_to_le32(page_size); + memcpy(range->data, fwrt->trans->init_dram.paging[idx].block, + page_size); + return le32_to_cpu(range->range_data_size); +} + +static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_error_dump_range *range, + struct iwl_fw_ini_region_cfg *reg, + int idx) +{ + /* increase idx by 1 since the pages are from 1 to + * fwrt->num_of_paging_blk + 1 + */ + struct page *page = fwrt->fw_paging_db[++idx].fw_paging_block; + dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys; + u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size; + + range->start_addr = cpu_to_le32(idx); + range->range_data_size = cpu_to_le32(page_size); + dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size, + DMA_BIDIRECTIONAL); + memcpy(range->data, page_address(page), page_size); + dma_sync_single_for_device(fwrt->trans->dev, addr, page_size, + DMA_BIDIRECTIONAL); + return le32_to_cpu(range->range_data_size); +} + static struct iwl_fw_ini_error_dump_range *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data) { @@ -1110,12 +1147,46 @@ static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt, le32_to_cpu(reg->internal.range_data_size); } +static u32 iwl_dump_ini_paging_gen2_get_size(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + int i; + u32 size = 0; + + for (i = 0; i < fwrt->trans->init_dram.paging_cnt; i++) + size += fwrt->trans->init_dram.paging[i].size; + return size; +} + +static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + int i; + u32 size = 0; + + for (i = 1; i <= fwrt->num_of_paging_blk; i++) + size += fwrt->fw_paging_db[i].fw_paging_size; + return size; +} + static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { return le32_to_cpu(reg->internal.num_of_ranges); } +static u32 iwl_dump_ini_paging_gen2_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return fwrt->trans->init_dram.paging_cnt; +} + +static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return fwrt->num_of_paging_blk; +} + /** * struct iwl_dump_ini_mem_ops - ini memory dump operations * @get_num_of_ranges: returns the number of memory ranges in the region. @@ -1224,14 +1295,21 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_RXF: size += iwl_fw_rxf_len(fwrt, &fwrt->smem_cfg); break; - case IWL_FW_INI_REGION_PAGING: - if (!iwl_fw_dbg_is_paging_enabled(fwrt)) - break; - size += fwrt->num_of_paging_blk * - (hdr_len + - sizeof(struct iwl_fw_error_dump_paging) + - PAGING_BLOCK_SIZE); + case IWL_FW_INI_REGION_PAGING: { + size += hdr_len + dump_header_len; + if (iwl_fw_dbg_is_paging_enabled(fwrt)) { + size += range_header_len * + iwl_dump_ini_paging_ranges(fwrt, reg) + + iwl_dump_ini_paging_get_size(fwrt, reg); + } else { + size += range_header_len * + iwl_dump_ini_paging_gen2_ranges(fwrt, + reg) + + iwl_dump_ini_paging_gen2_get_size(fwrt, + reg); + } break; + } case IWL_FW_INI_REGION_DRAM_BUFFER: /* Transport takes care of DRAM dumping */ case IWL_FW_INI_REGION_INTERNAL_BUFFER: @@ -1286,12 +1364,24 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_DRAM_BUFFER: *dump_mask |= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR); break; - case IWL_FW_INI_REGION_PAGING: - if (iwl_fw_dbg_is_paging_enabled(fwrt)) - iwl_dump_paging(fwrt, data); - else - *dump_mask |= BIT(IWL_FW_ERROR_DUMP_PAGING); + case IWL_FW_INI_REGION_PAGING: { + ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; + if (iwl_fw_dbg_is_paging_enabled(fwrt)) { + ops.get_num_of_ranges = + iwl_dump_ini_paging_ranges; + ops.get_size = iwl_dump_ini_paging_get_size; + ops.fill_range = iwl_dump_ini_paging_iter; + } else { + ops.get_num_of_ranges = + iwl_dump_ini_paging_gen2_ranges; + ops.get_size = + iwl_dump_ini_paging_gen2_get_size; + ops.fill_range = iwl_dump_ini_paging_gen2_iter; + } + + iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; + } case IWL_FW_INI_REGION_TXF: iwl_fw_dump_txf(fwrt, data); break; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index d79025d663df..36d0addb79e8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -700,6 +700,20 @@ struct iwl_dram_data { int size; }; +/** + * struct iwl_self_init_dram - dram data used by self init process + * @fw: lmac and umac dram data + * @fw_cnt: total number of items in array + * @paging: paging dram data + * @paging_cnt: total number of items in array + */ +struct iwl_self_init_dram { + struct iwl_dram_data *fw; + int fw_cnt; + struct iwl_dram_data *paging; + int paging_cnt; +}; + /** * struct iwl_trans - transport common data * @@ -794,6 +808,7 @@ struct iwl_trans { u8 dbg_n_dest_reg; int num_blocks; struct iwl_dram_data fw_mon[IWL_FW_INI_APPLY_NUM]; + struct iwl_self_init_dram init_dram; enum iwl_plat_pm_mode system_pm_mode; enum iwl_plat_pm_mode runtime_pm_mode; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index 7f4aaa810ea1..9274e317cc77 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -59,8 +59,7 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_self_init_dram *dram = &trans_pcie->init_dram; + struct iwl_self_init_dram *dram = &trans->init_dram; int i; if (!dram->paging) { @@ -83,8 +82,7 @@ int iwl_pcie_init_fw_sec(struct iwl_trans *trans, const struct fw_img *fw, struct iwl_context_info_dram *ctxt_dram) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_self_init_dram *dram = &trans_pcie->init_dram; + struct iwl_self_init_dram *dram = &trans->init_dram; int i, ret, lmac_cnt, umac_cnt, paging_cnt; if (WARN(dram->paging, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 0d16bcc3141f..ee38ae3b0d30 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -453,20 +453,6 @@ enum iwl_image_response_code { IWL_IMAGE_RESP_FAIL = 2, }; -/** - * struct iwl_self_init_dram - dram data used by self init process - * @fw: lmac and umac dram data - * @fw_cnt: total number of items in array - * @paging: paging dram data - * @paging_cnt: total number of items in array - */ -struct iwl_self_init_dram { - struct iwl_dram_data *fw; - int fw_cnt; - struct iwl_dram_data *paging; - int paging_cnt; -}; - /** * struct cont_rec: continuous recording data structure * @prev_wr_ptr: the last address that was read in monitor_data @@ -554,7 +540,6 @@ struct iwl_trans_pcie { dma_addr_t prph_info_dma_addr; dma_addr_t prph_scratch_dma_addr; dma_addr_t iml_dma_addr; - struct iwl_self_init_dram init_dram; struct iwl_trans *trans; struct net_device napi_dev; @@ -813,8 +798,7 @@ static inline int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans, static inline void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_self_init_dram *dram = &trans_pcie->init_dram; + struct iwl_self_init_dram *dram = &trans->init_dram; int i; if (!dram->fw) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index f26664b0f0f8..ac82c891595c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3220,10 +3220,10 @@ static struct iwl_trans_dump_data /* Paged memory for gen2 HW */ if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) - for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) + for (i = 0; i < trans->init_dram.paging_cnt; i++) len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_paging) + - trans_pcie->init_dram.paging[i].size; + trans->init_dram.paging[i].size; dump_data = vzalloc(len); if (!dump_data) @@ -3275,16 +3275,16 @@ static struct iwl_trans_dump_data /* Paged memory for gen2 HW */ if (trans->cfg->gen2 && dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) { - for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) { + for (i = 0; i < trans->init_dram.paging_cnt; i++) { struct iwl_fw_error_dump_paging *paging; - u32 page_len = trans_pcie->init_dram.paging[i].size; + u32 page_len = trans->init_dram.paging[i].size; data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); data->len = cpu_to_le32(sizeof(*paging) + page_len); paging = (void *)data->data; paging->index = cpu_to_le32(i); memcpy(paging->data, - trans_pcie->init_dram.paging[i].block, page_len); + trans->init_dram.paging[i].block, page_len); data = iwl_fw_error_next_data(data); len += sizeof(*data) + sizeof(*paging) + page_len; -- cgit v1.2.3 From b8a7547d77782ba1d403f2417be9453a3a256e14 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 5 Dec 2018 08:48:26 +0200 Subject: iwlwifi: fix send hcmd timeout recovery flow Both iwl_trans_fw_error and iwl_force_nmi initiate async recovery flow. Calling them both is redundant and causing a race. Solve this by removing the call to iwl_trans_fw_error. Signed-off-by: Shahar S Matityahu Fixes: cfadc3ffccd5 ("iwlwifi: pcie: stop the firmware when we restart it") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 3 +++ drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 25 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 8 +++---- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 8 +++---- 5 files changed, 35 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 36d0addb79e8..ef23c6aafb5c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -688,6 +688,9 @@ enum iwl_plat_pm_mode { */ #define IWL_TRANS_IDLE_TIMEOUT 2000 +/* Max time to wait for nmi interrupt */ +#define IWL_TRANS_NMI_TIMEOUT (HZ / 4) + /** * struct iwl_dram_data * @physical: page phy pointer diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index ee38ae3b0d30..9e1bcafad786 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -1036,6 +1036,7 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans) void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state); void iwl_trans_pcie_dump_regs(struct iwl_trans *trans); +void iwl_trans_sync_nmi(struct iwl_trans *trans); #ifdef CONFIG_IWLWIFI_DEBUGFS int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index ac82c891595c..0b29b2ebb23d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3650,3 +3650,28 @@ out_no_pci: iwl_trans_free(trans); return ERR_PTR(ret); } + +void iwl_trans_sync_nmi(struct iwl_trans *trans) +{ + unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT; + + iwl_disable_interrupts(trans); + iwl_force_nmi(trans); + while (time_after(timeout, jiffies)) { + u32 inta_hw = iwl_read32(trans, + CSR_MSIX_HW_INT_CAUSES_AD); + + /* Error detected by uCode */ + if (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) { + /* Clear causes register */ + iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD, + inta_hw & + MSIX_HW_INT_CAUSES_REG_SW_ERR); + break; + } + + mdelay(1); + } + iwl_enable_interrupts(trans); + iwl_trans_fw_error(trans); +} diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index f3d2e8fe920b..88530d9f4a54 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -965,9 +965,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans, cmd_str); ret = -ETIMEDOUT; - iwl_force_nmi(trans); - iwl_trans_fw_error(trans); - + iwl_trans_sync_nmi(trans); goto cancel; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 07395502f419..28a371814387 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -8,7 +8,7 @@ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1942,9 +1942,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, iwl_get_cmd_string(trans, cmd->id)); ret = -ETIMEDOUT; - iwl_force_nmi(trans); - iwl_trans_fw_error(trans); - + iwl_trans_sync_nmi(trans); goto cancel; } -- cgit v1.2.3 From c96b5eec2105ccb6a956c8da6bb6deb670ebaf43 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Dec 2018 09:27:47 +0100 Subject: iwlwifi: refactor NIC init sequence The typical sequence of setting INIT_DONE and then waiting for clock stabilisation is going to need a new workarounds, so first of all refactor it. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/iwl-eeprom-read.c | 47 ++++++--------- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 30 ++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-io.h | 5 ++ drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 18 +----- .../net/wireless/intel/iwlwifi/pcie/trans-gen2.c | 21 +------ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 67 +++------------------- 6 files changed, 66 insertions(+), 122 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c index a6db6a814257..82e87192119e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c @@ -193,34 +193,25 @@ static int iwl_init_otp_access(struct iwl_trans *trans) { int ret; - /* Enable 40MHz radio clock */ - iwl_write32(trans, CSR_GP_CNTRL, - iwl_read32(trans, CSR_GP_CNTRL) | - BIT(trans->cfg->csr->flag_init_done)); - - /* wait for clock to be ready */ - ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_mac_clock_ready), - BIT(trans->cfg->csr->flag_mac_clock_ready), - 25000); - if (ret < 0) { - IWL_ERR(trans, "Time out access OTP\n"); - } else { - iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); - udelay(5); - iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); - - /* - * CSR auto clock gate disable bit - - * this is only applicable for HW with OTP shadow RAM - */ - if (trans->cfg->base_params->shadow_ram_support) - iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); - } - return ret; + ret = iwl_finish_nic_init(trans); + if (ret) + return ret; + + iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_RESET_REQ); + udelay(5); + iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_RESET_REQ); + + /* + * CSR auto clock gate disable bit - + * this is only applicable for HW with OTP shadow RAM + */ + if (trans->cfg->base_params->shadow_ram_support) + iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, + CSR_RESET_LINK_PWR_MGMT_DISABLED); + + return 0; } static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index d62eb2d9389a..4ea5883f9175 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -488,3 +488,33 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf) return 0; } + +int iwl_finish_nic_init(struct iwl_trans *trans) +{ + int err; + + /* + * Set "initialization complete" bit to move adapter from + * D0U* --> D0A* (powered-up active) state. + */ + iwl_set_bit(trans, CSR_GP_CNTRL, + BIT(trans->cfg->csr->flag_init_done)); + + if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) + udelay(2); + + /* + * Wait for clock stabilization; once stabilized, access to + * device-internal resources is supported, e.g. iwl_write_prph() + * and accesses to uCode SRAM. + */ + err = iwl_poll_bit(trans, CSR_GP_CNTRL, + BIT(trans->cfg->csr->flag_mac_clock_ready), + BIT(trans->cfg->csr->flag_mac_clock_ready), + 25000); + if (err < 0) + IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); + + return err < 0 ? err : 0; +} +IWL_EXPORT_SYMBOL(iwl_finish_nic_init); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index 61477e58352d..bf1100837d72 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -5,6 +5,8 @@ * * GPL LICENSE SUMMARY * + * Copyright (C) 2018 Intel Corporation + * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. @@ -23,6 +25,7 @@ * * BSD LICENSE * + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -96,6 +99,8 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs, void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask); void iwl_force_nmi(struct iwl_trans *trans); +int iwl_finish_nic_init(struct iwl_trans *trans); + /* Error handling */ int iwl_dump_fh(struct iwl_trans *trans, char **buf); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 92f61e8a6284..4a18997fb48a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -523,23 +523,9 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num) /* reset the device */ iwl_trans_sw_reset(trans); - /* set INIT_DONE flag */ - iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_init_done)); - - /* and wait for clock stabilization */ - if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) - udelay(2); - - err = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_mac_clock_ready), - BIT(trans->cfg->csr->flag_mac_clock_ready), - 25000); - if (err < 0) { - IWL_DEBUG_INFO(trans, - "Failed to reset the card for the dump\n"); + err = iwl_finish_nic_init(trans); + if (err) return; - } } iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 77f3610e5ca9..e2d64378c932 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -92,26 +92,9 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans) iwl_pcie_apm_config(trans); - /* - * Set "initialization complete" bit to move adapter from - * D0U* --> D0A* (powered-up active) state. - */ - iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_init_done)); - - /* - * Wait for clock stabilization; once stabilized, access to - * device-internal resources is supported, e.g. iwl_write_prph() - * and accesses to uCode SRAM. - */ - ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_mac_clock_ready), - BIT(trans->cfg->csr->flag_mac_clock_ready), - 25000); - if (ret < 0) { - IWL_DEBUG_INFO(trans, "Failed to init the card\n"); + ret = iwl_finish_nic_init(trans); + if (ret) return ret; - } set_bit(STATUS_DEVICE_ENABLED, &trans->status); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 0b29b2ebb23d..375d8f25b886 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -364,26 +364,9 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans) if (trans->cfg->base_params->pll_cfg) iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); - /* - * Set "initialization complete" bit to move adapter from - * D0U* --> D0A* (powered-up active) state. - */ - iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_init_done)); - - /* - * Wait for clock stabilization; once stabilized, access to - * device-internal resources is supported, e.g. iwl_write_prph() - * and accesses to uCode SRAM. - */ - ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_mac_clock_ready), - BIT(trans->cfg->csr->flag_mac_clock_ready), - 25000); - if (ret < 0) { - IWL_ERR(trans, "Failed to init the card\n"); + ret = iwl_finish_nic_init(trans); + if (ret) return ret; - } if (trans->cfg->host_interrupt_operation_mode) { /* @@ -453,23 +436,8 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) iwl_trans_pcie_sw_reset(trans); - /* - * Set "initialization complete" bit to move adapter from - * D0U* --> D0A* (powered-up active) state. - */ - iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_init_done)); - - /* - * Wait for clock stabilization; once stabilized, access to - * device-internal resources is possible. - */ - ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_mac_clock_ready), - BIT(trans->cfg->csr->flag_mac_clock_ready), - 25000); - if (WARN_ON(ret < 0)) { - IWL_ERR(trans, "Access time out - failed to enable LP XTAL\n"); + ret = iwl_finish_nic_init(trans); + if (WARN_ON(ret)) { /* Release XTAL ON request */ __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_XTAL_ON); @@ -1558,20 +1526,10 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, iwl_set_bit(trans, CSR_GP_CNTRL, BIT(trans->cfg->csr->flag_mac_access_req)); - iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_init_done)); - if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) - udelay(2); - - ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_mac_clock_ready), - BIT(trans->cfg->csr->flag_mac_clock_ready), - 25000); - if (ret < 0) { - IWL_ERR(trans, "Failed to resume the device (mac ready)\n"); + ret = iwl_finish_nic_init(trans); + if (ret) return ret; - } /* * Reconfigure IVAR table in case of MSIX or reset ict table in @@ -3521,18 +3479,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, * in-order to recognize C step driver should read chip version * id located at the AUX bus MISC address space. */ - iwl_set_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_init_done)); - udelay(2); - - ret = iwl_poll_bit(trans, CSR_GP_CNTRL, - BIT(trans->cfg->csr->flag_mac_clock_ready), - BIT(trans->cfg->csr->flag_mac_clock_ready), - 25000); - if (ret < 0) { - IWL_DEBUG_INFO(trans, "Failed to wake up the nic\n"); + ret = iwl_finish_nic_init(trans); + if (ret) goto out_no_pci; - } if (iwl_trans_grab_nic_access(trans, &flags)) { u32 hw_step; -- cgit v1.2.3 From dbf592f3d14fb7d532cb7c820b1065cf33e02aaa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 11 Dec 2018 21:20:43 +0100 Subject: iwlwifi: mvm: fix RFH config command with >=10 CPUs If we have >=10 (logical) CPUs, our command size exceeds the internal buffer size and the command fails; fix that by using IWL_HCMD_DFL_NOCOPY for the command that's allocated anyway. While at it, also fix the leak of cmd, and use struct_size() to calculate its size. Signed-off-by: Johannes Berg Fixes: 8edbfaa19835 ("iwlwifi: mvm: configure multi RX queue") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 134dab2d774a..8140b193cc05 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -127,13 +127,17 @@ static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) static int iwl_configure_rxq(struct iwl_mvm *mvm) { - int i, num_queues, size; + int i, num_queues, size, ret; struct iwl_rfh_queue_config *cmd; + struct iwl_host_cmd hcmd = { + .id = WIDE_ID(DATA_PATH_GROUP, RFH_QUEUE_CONFIG_CMD), + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; /* Do not configure default queue, it is configured via context info */ num_queues = mvm->trans->num_rx_queues - 1; - size = sizeof(*cmd) + num_queues * sizeof(struct iwl_rfh_queue_data); + size = struct_size(cmd, data, num_queues); cmd = kzalloc(size, GFP_KERNEL); if (!cmd) @@ -154,10 +158,14 @@ static int iwl_configure_rxq(struct iwl_mvm *mvm) cmd->data[i].fr_bd_wid = cpu_to_le32(data.fr_bd_wid); } - return iwl_mvm_send_cmd_pdu(mvm, - WIDE_ID(DATA_PATH_GROUP, - RFH_QUEUE_CONFIG_CMD), - 0, size, cmd); + hcmd.data[0] = cmd; + hcmd.len[0] = size; + + ret = iwl_mvm_send_cmd(mvm, &hcmd); + + kfree(cmd); + + return ret; } static int iwl_mvm_send_dqa_cmd(struct iwl_mvm *mvm) -- cgit v1.2.3 From b998fbbd531fe33d9dd50fd37056f48b4257113d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Dec 2018 09:36:58 +0100 Subject: iwlwifi: implement BISR HW workaround for 22260 devices There's a small hardware bug in 22260 devices which thus require a few more delays during initialization. Implement this workaround. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 3 +++ drivers/net/wireless/intel/iwlwifi/iwl-config.h | 4 +++- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index c547288d32aa..28d8c3477371 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -220,6 +220,7 @@ const struct iwl_cfg iwl22260_2ax_cfg = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .bisr_workaround = 1, }; const struct iwl_cfg killer1650x_2ax_cfg = { @@ -232,6 +233,7 @@ const struct iwl_cfg killer1650x_2ax_cfg = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .bisr_workaround = 1, }; const struct iwl_cfg killer1650w_2ax_cfg = { @@ -244,6 +246,7 @@ const struct iwl_cfg killer1650w_2ax_cfg = { * HT size; mac80211 would otherwise pick the HE max (256) by default. */ .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, + .bisr_workaround = 1, }; /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index f1e493380713..5e713730165a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -379,6 +379,7 @@ struct iwl_csr_params { * @nvm_type: see &enum iwl_nvm_type * @d3_debug_data_base_addr: base address where D3 debug data is stored * @d3_debug_data_length: length of the D3 debug data + * @bisr_workaround: BISR hardware workaround (for 22260 series devices) * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -428,7 +429,8 @@ struct iwl_cfg { use_tfh:1, gen2:1, cdb:1, - dbgc_supported:1; + dbgc_supported:1, + bisr_workaround:1; u8 valid_tx_ant; u8 valid_rx_ant; u8 non_shared_ant; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index 4ea5883f9175..bf171edad53a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -493,6 +493,11 @@ int iwl_finish_nic_init(struct iwl_trans *trans) { int err; + if (trans->cfg->bisr_workaround) { + /* ensure the TOP FSM isn't still in previous reset */ + mdelay(2); + } + /* * Set "initialization complete" bit to move adapter from * D0U* --> D0A* (powered-up active) state. @@ -515,6 +520,11 @@ int iwl_finish_nic_init(struct iwl_trans *trans) if (err < 0) IWL_DEBUG_INFO(trans, "Failed to wake NIC\n"); + if (trans->cfg->bisr_workaround) { + /* ensure BISR shift has finished */ + udelay(200); + } + return err < 0 ? err : 0; } IWL_EXPORT_SYMBOL(iwl_finish_nic_init); -- cgit v1.2.3 From 5b9030cee1bedba934adb5c7ae708e510dddd0f0 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Mon, 3 Sep 2018 22:07:02 +0530 Subject: ath10k: Set DMA address mask to 35 bit for WCN3990 WCN3990 is a 37-bit target but can address memory range only upto 35 bits. The 36th bit is used to control the smmu/iommu translation and the 37th bit is used by the internal bus masters to access the wifi subsystem internal SRAM. With the DMA mask set to 37i-bit, the host driver can get 37-bit dma address, which leads to incorrect address access in the target. Hence the host driver can used addresses upto 35-bit for WCN3990. Fix the dma mask for wcn3990 to 35-bit, instead of 37-bit. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Tested-by: Bjorn Andersson Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 75 ++++++++++++++++++++++++++------ drivers/net/wireless/ath/ath10k/ce.h | 14 ++++-- drivers/net/wireless/ath/ath10k/htt_tx.c | 2 +- drivers/net/wireless/ath/ath10k/hw.c | 10 +++-- drivers/net/wireless/ath/ath10k/hw.h | 6 ++- drivers/net/wireless/ath/ath10k/snoc.c | 2 +- 6 files changed, 84 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index f6d3ecbdd3a3..a3d0d68a7b53 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -228,11 +228,31 @@ ath10k_ce_shadow_dest_ring_write_index_set(struct ath10k *ar, } static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar, - u32 ce_ctrl_addr, - unsigned int addr) + u32 ce_id, + u64 addr) +{ + struct ath10k_ce *ce = ath10k_ce_priv(ar); + struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; + u32 ce_ctrl_addr = ath10k_ce_base_address(ar, ce_id); + u32 addr_lo = lower_32_bits(addr); + + ath10k_ce_write32(ar, ce_ctrl_addr + + ar->hw_ce_regs->sr_base_addr_lo, addr_lo); + + if (ce_state->ops->ce_set_src_ring_base_addr_hi) { + ce_state->ops->ce_set_src_ring_base_addr_hi(ar, ce_ctrl_addr, + addr); + } +} + +static void ath10k_ce_set_src_ring_base_addr_hi(struct ath10k *ar, + u32 ce_ctrl_addr, + u64 addr) { + u32 addr_hi = upper_32_bits(addr) & CE_DESC_ADDR_HI_MASK; + ath10k_ce_write32(ar, ce_ctrl_addr + - ar->hw_ce_regs->sr_base_addr, addr); + ar->hw_ce_regs->sr_base_addr_hi, addr_hi); } static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar, @@ -313,11 +333,36 @@ static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, } static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar, - u32 ce_ctrl_addr, - u32 addr) + u32 ce_id, + u64 addr) { + struct ath10k_ce *ce = ath10k_ce_priv(ar); + struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; + u32 ce_ctrl_addr = ath10k_ce_base_address(ar, ce_id); + u32 addr_lo = lower_32_bits(addr); + + ath10k_ce_write32(ar, ce_ctrl_addr + + ar->hw_ce_regs->dr_base_addr_lo, addr_lo); + + if (ce_state->ops->ce_set_dest_ring_base_addr_hi) { + ce_state->ops->ce_set_dest_ring_base_addr_hi(ar, ce_ctrl_addr, + addr); + } +} + +static void ath10k_ce_set_dest_ring_base_addr_hi(struct ath10k *ar, + u32 ce_ctrl_addr, + u64 addr) +{ + u32 addr_hi = upper_32_bits(addr) & CE_DESC_ADDR_HI_MASK; + u32 reg_value; + + reg_value = ath10k_ce_read32(ar, ce_ctrl_addr + + ar->hw_ce_regs->dr_base_addr_hi); + reg_value &= ~CE_DESC_ADDR_HI_MASK; + reg_value |= addr_hi; ath10k_ce_write32(ar, ce_ctrl_addr + - ar->hw_ce_regs->dr_base_addr, addr); + ar->hw_ce_regs->dr_base_addr_hi, reg_value); } static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar, @@ -563,7 +608,7 @@ static int _ath10k_ce_send_nolock_64(struct ath10k_ce_pipe *ce_state, addr = (__le32 *)&sdesc.addr; - flags |= upper_32_bits(buffer) & CE_DESC_FLAGS_GET_MASK; + flags |= upper_32_bits(buffer) & CE_DESC_ADDR_HI_MASK; addr[0] = __cpu_to_le32(buffer); addr[1] = __cpu_to_le32(flags); if (flags & CE_SEND_FLAG_GATHER) @@ -731,7 +776,7 @@ static int __ath10k_ce_rx_post_buf_64(struct ath10k_ce_pipe *pipe, return -ENOSPC; desc->addr = __cpu_to_le64(paddr); - desc->addr &= __cpu_to_le64(CE_DESC_37BIT_ADDR_MASK); + desc->addr &= __cpu_to_le64(CE_DESC_ADDR_MASK); desc->nbytes = 0; @@ -1346,7 +1391,7 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, ath10k_ce_src_ring_write_index_get(ar, ctrl_addr); src_ring->write_index &= src_ring->nentries_mask; - ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, + ath10k_ce_src_ring_base_addr_set(ar, ce_id, src_ring->base_addr_ce_space); ath10k_ce_src_ring_size_set(ar, ctrl_addr, nentries); ath10k_ce_src_ring_dmax_set(ar, ctrl_addr, attr->src_sz_max); @@ -1385,7 +1430,7 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr); dest_ring->write_index &= dest_ring->nentries_mask; - ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, + ath10k_ce_dest_ring_base_addr_set(ar, ce_id, dest_ring->base_addr_ce_space); ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries); ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0); @@ -1661,7 +1706,7 @@ static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id) { u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id); - ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr, 0); + ath10k_ce_src_ring_base_addr_set(ar, ce_id, 0); ath10k_ce_src_ring_size_set(ar, ctrl_addr, 0); ath10k_ce_src_ring_dmax_set(ar, ctrl_addr, 0); ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, 0); @@ -1671,7 +1716,7 @@ static void ath10k_ce_deinit_dest_ring(struct ath10k *ar, unsigned int ce_id) { u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id); - ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, 0); + ath10k_ce_dest_ring_base_addr_set(ar, ce_id, 0); ath10k_ce_dest_ring_size_set(ar, ctrl_addr, 0); ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, 0); } @@ -1803,6 +1848,8 @@ static const struct ath10k_ce_ops ce_ops = { .ce_extract_desc_data = ath10k_ce_extract_desc_data, .ce_free_pipe = _ath10k_ce_free_pipe, .ce_send_nolock = _ath10k_ce_send_nolock, + .ce_set_src_ring_base_addr_hi = NULL, + .ce_set_dest_ring_base_addr_hi = NULL, }; static const struct ath10k_ce_ops ce_64_ops = { @@ -1815,6 +1862,8 @@ static const struct ath10k_ce_ops ce_64_ops = { .ce_extract_desc_data = ath10k_ce_extract_desc_data_64, .ce_free_pipe = _ath10k_ce_free_pipe_64, .ce_send_nolock = _ath10k_ce_send_nolock_64, + .ce_set_src_ring_base_addr_hi = ath10k_ce_set_src_ring_base_addr_hi, + .ce_set_dest_ring_base_addr_hi = ath10k_ce_set_dest_ring_base_addr_hi, }; static void ath10k_ce_set_ops(struct ath10k *ar, @@ -1910,7 +1959,7 @@ void ath10k_ce_alloc_rri(struct ath10k *ar) lower_32_bits(ce->paddr_rri)); ath10k_ce_write32(ar, ar->hw_ce_regs->ce_rri_high, (upper_32_bits(ce->paddr_rri) & - CE_DESC_FLAGS_GET_MASK)); + CE_DESC_ADDR_HI_MASK)); for (i = 0; i < CE_COUNT; i++) { ctrl1_regs = ar->hw_ce_regs->ctrl1_regs->addr; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index ead9987c3259..c44a52e8a6af 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -39,8 +39,8 @@ struct ath10k_ce_pipe; #define CE_DESC_FLAGS_BYTE_SWAP (1 << 1) #define CE_WCN3990_DESC_FLAGS_GATHER BIT(31) -#define CE_DESC_FLAGS_GET_MASK GENMASK(4, 0) -#define CE_DESC_37BIT_ADDR_MASK GENMASK_ULL(37, 0) +#define CE_DESC_ADDR_MASK GENMASK_ULL(34, 0) +#define CE_DESC_ADDR_HI_MASK GENMASK(4, 0) /* Following desc flags are used in QCA99X0 */ #define CE_DESC_FLAGS_HOST_INT_DIS (1 << 2) @@ -104,7 +104,7 @@ struct ath10k_ce_ring { /* Host address space */ void *base_addr_owner_space_unaligned; /* CE address space */ - u32 base_addr_ce_space_unaligned; + dma_addr_t base_addr_ce_space_unaligned; /* * Actual start of descriptors. @@ -115,7 +115,7 @@ struct ath10k_ce_ring { void *base_addr_owner_space; /* CE address space */ - u32 base_addr_ce_space; + dma_addr_t base_addr_ce_space; char *shadow_base_unaligned; struct ce_desc *shadow_base; @@ -334,6 +334,12 @@ struct ath10k_ce_ops { void *per_transfer_context, dma_addr_t buffer, u32 nbytes, u32 transfer_id, u32 flags); + void (*ce_set_src_ring_base_addr_hi)(struct ath10k *ar, + u32 ce_ctrl_addr, + u64 addr); + void (*ce_set_dest_ring_base_addr_hi)(struct ath10k *ar, + u32 ce_ctrl_addr, + u64 addr); }; static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index ad05ab714c9b..f811f96c8882 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -1498,7 +1498,7 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt, u16 msdu_id, flags1 = 0; u16 freq = 0; dma_addr_t frags_paddr = 0; - u32 txbuf_paddr; + dma_addr_t txbuf_paddr; struct htt_msdu_ext_desc_64 *ext_desc = NULL; struct htt_msdu_ext_desc_64 *ext_desc_t = NULL; diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 61ecf931ba4d..48886b6b9056 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -318,9 +318,11 @@ static struct ath10k_hw_ce_ctrl1_upd wcn3990_ctrl1_upd = { }; const struct ath10k_hw_ce_regs wcn3990_ce_regs = { - .sr_base_addr = 0x00000000, + .sr_base_addr_lo = 0x00000000, + .sr_base_addr_hi = 0x00000004, .sr_size_addr = 0x00000008, - .dr_base_addr = 0x0000000c, + .dr_base_addr_lo = 0x0000000c, + .dr_base_addr_hi = 0x00000010, .dr_size_addr = 0x00000014, .misc_ie_addr = 0x00000034, .sr_wr_index_addr = 0x0000003c, @@ -464,9 +466,9 @@ static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = { }; const struct ath10k_hw_ce_regs qcax_ce_regs = { - .sr_base_addr = 0x00000000, + .sr_base_addr_lo = 0x00000000, .sr_size_addr = 0x00000004, - .dr_base_addr = 0x00000008, + .dr_base_addr_lo = 0x00000008, .dr_size_addr = 0x0000000c, .ce_cmd_addr = 0x00000018, .misc_ie_addr = 0x00000034, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index e50a8dc5b093..f03114740040 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -353,9 +353,11 @@ struct ath10k_hw_ce_ctrl1_upd { }; struct ath10k_hw_ce_regs { - u32 sr_base_addr; + u32 sr_base_addr_lo; + u32 sr_base_addr_hi; u32 sr_size_addr; - u32 dr_base_addr; + u32 dr_base_addr_lo; + u32 dr_base_addr_hi; u32 dr_size_addr; u32 ce_cmd_addr; u32 misc_ie_addr; diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 54efe6be8f1d..0032bc5dd934 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -66,7 +66,7 @@ static void ath10k_snoc_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state); static const struct ath10k_snoc_drv_priv drv_priv = { .hw_rev = ATH10K_HW_WCN3990, - .dma_mask = DMA_BIT_MASK(37), + .dma_mask = DMA_BIT_MASK(35), .msa_size = 0x100000, }; -- cgit v1.2.3 From 1a86be476cfa3e53ff1e0f7ddcbe427770c6e767 Mon Sep 17 00:00:00 2001 From: Yu Wang Date: Tue, 15 Jan 2019 14:31:07 +0800 Subject: ath10k: fix S5 power consumption issue for QCA9377 After system entering S5 (shut down but system still providing power to QCA9377) on Ubuntu platform, power consumption of QCA9377 is 69mA, which is too high. The root cause is pci_soft_reset is not set for QCA9377 during pci probe. To fix this issue, set 'pci_soft_reset' to 'th10k_pci_warm_reset', and then the power consumption drops to a normal value(10mA). Verified on Dell Ubuntu platform with firmware: WLAN.TF.1.0-00002-QCATFSWPZ-5 Signed-off-by: Yu Wang Signed-off-by: Yu Wang Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 01b4edb00e9e..0a4ce98ae69c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3554,7 +3554,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, case QCA9377_1_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA9377; pci_ps = true; - pci_soft_reset = NULL; + pci_soft_reset = ath10k_pci_warm_reset; pci_hard_reset = ath10k_pci_qca6174_chip_reset; targ_cpu_to_ce_addr = ath10k_pci_qca6174_targ_cpu_to_ce_addr; break; -- cgit v1.2.3 From 5cbb117477501df2f8b3a384b042b08cd7174c92 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Wed, 16 Jan 2019 16:59:42 +0530 Subject: ath10k: Add support for extended HTT aggr msg support HTT aggr message parameter in HL2.0 fw are different in comparison to legacy fw version. Fill correct HTT aggr msg parameter for targets using HL2.0 firmware. Signed-off-by: Govind Singh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.c | 2 +- drivers/net/wireless/ath/ath10k/htt.h | 11 +++++++ drivers/net/wireless/ath/ath10k/htt_tx.c | 49 ++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 21a67f82f037..55c716499830 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -268,7 +268,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt) return status; } - status = ath10k_htt_h2t_aggr_cfg_msg(htt, + status = htt->tx_ops->htt_h2t_aggr_cfg_msg(htt, htt->max_num_ampdu, htt->max_num_amsdu); if (status) { diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index a76f7c9e2199..f5fa86f6efad 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -357,6 +357,13 @@ struct htt_aggr_conf { u8 max_num_amsdu_subframes; } __packed; +struct htt_aggr_conf_v2 { + u8 max_num_ampdu_subframes; + /* amsdu_subframes is limited by 0x1F mask */ + u8 max_num_amsdu_subframes; + u8 reserved; +} __packed; + #define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32 struct htt_mgmt_tx_desc_qca99x0 { __le32 rate; @@ -1650,6 +1657,7 @@ struct htt_cmd { struct htt_stats_req stats_req; struct htt_oob_sync_req oob_sync_req; struct htt_aggr_conf aggr_conf; + struct htt_aggr_conf_v2 aggr_conf_v2; struct htt_frag_desc_bank_cfg32 frag_desc_bank_cfg32; struct htt_frag_desc_bank_cfg64 frag_desc_bank_cfg64; struct htt_tx_fetch_resp tx_fetch_resp; @@ -1890,6 +1898,9 @@ struct ath10k_htt_tx_ops { struct sk_buff *msdu); int (*htt_alloc_txbuff)(struct ath10k_htt *htt); void (*htt_free_txbuff)(struct ath10k_htt *htt); + int (*htt_h2t_aggr_cfg_msg)(struct ath10k_htt *htt, + u8 max_subfrms_ampdu, + u8 max_subfrms_amsdu); }; static inline int ath10k_htt_send_rx_ring_cfg(struct ath10k_htt *htt) diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index f811f96c8882..7b89d950c26d 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -1035,6 +1035,53 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, return 0; } +static int ath10k_htt_h2t_aggr_cfg_msg_v2(struct ath10k_htt *htt, + u8 max_subfrms_ampdu, + u8 max_subfrms_amsdu) +{ + struct ath10k *ar = htt->ar; + struct htt_aggr_conf_v2 *aggr_conf; + struct sk_buff *skb; + struct htt_cmd *cmd; + int len; + int ret; + + /* Firmware defaults are: amsdu = 3 and ampdu = 64 */ + + if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64) + return -EINVAL; + + if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31) + return -EINVAL; + + len = sizeof(cmd->hdr); + len += sizeof(cmd->aggr_conf_v2); + + skb = ath10k_htc_alloc_skb(ar, len); + if (!skb) + return -ENOMEM; + + skb_put(skb, len); + cmd = (struct htt_cmd *)skb->data; + cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG; + + aggr_conf = &cmd->aggr_conf_v2; + aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu; + aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu; + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d", + aggr_conf->max_num_amsdu_subframes, + aggr_conf->max_num_ampdu_subframes); + + ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); + if (ret) { + dev_kfree_skb_any(skb); + return ret; + } + + return 0; +} + int ath10k_htt_tx_fetch_resp(struct ath10k *ar, __le32 token, __le16 fetch_seq_num, @@ -1692,6 +1739,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_32 = { .htt_tx = ath10k_htt_tx_32, .htt_alloc_txbuff = ath10k_htt_tx_alloc_cont_txbuf_32, .htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_32, + .htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg, }; static const struct ath10k_htt_tx_ops htt_tx_ops_64 = { @@ -1702,6 +1750,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_64 = { .htt_tx = ath10k_htt_tx_64, .htt_alloc_txbuff = ath10k_htt_tx_alloc_cont_txbuf_64, .htt_free_txbuff = ath10k_htt_tx_free_cont_txbuf_64, + .htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_v2, }; static const struct ath10k_htt_tx_ops htt_tx_ops_hl = { -- cgit v1.2.3 From 4b6e9f3fe1d8af03ddbd484d5ea30344e5115d5f Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 15 Jan 2019 16:02:23 -0800 Subject: ath9k: eeprom: Use scnprintf instead of snprintf Change snprintf to scnprintf. There are generally two cases where using snprintf causes problems. 1) Uses of size += snprintf(buf, SIZE - size, fmt, ...) In this case, if snprintf would have written more characters than what the buffer size (SIZE) is, then size will end up larger than SIZE. In later uses of snprintf, SIZE - size will result in a negative number, leading to problems. Note that size might already be too large by using size = snprintf before the code reaches a case of size += snprintf. 2) If size is ultimately used as a length parameter for a copy back to user space, then it will potentially allow for a buffer overflow and information disclosure when size is greater than SIZE. When the size is used to index the buffer directly, we can have memory corruption. This also means when size = snprintf... is used, it may also cause problems since size may become large. Copying to userspace is mitigated by the HARDENED_USERCOPY kernel configuration. The solution to these issues is to use scnprintf which returns the number of characters actually written to the buffer, so the size variable will never exceed SIZE. Cc: Willy Tarreau Cc: Silvio Cesare Signed-off-by: Kees Cook Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index f019a20e5a1f..2b29bf4730f6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3457,9 +3457,9 @@ static u32 ar9003_dump_cal_data(struct ath_hw *ah, char *buf, u32 len, u32 size, if (!((pBase->txrxMask >> i) & 1)) continue; - len += snprintf(buf + len, size - len, "Chain %d\n", i); + len += scnprintf(buf + len, size - len, "Chain %d\n", i); - len += snprintf(buf + len, size - len, + len += scnprintf(buf + len, size - len, "Freq\t ref\tvolt\ttemp\tnf_cal\tnf_pow\trx_temp\n"); for (j = 0; j < cal_pier_nr; j++) { @@ -3471,10 +3471,10 @@ static u32 ar9003_dump_cal_data(struct ath_hw *ah, char *buf, u32 len, u32 size, freq = 4800 + eep->calFreqPier5G[j] * 5; } - len += snprintf(buf + len, size - len, + len += scnprintf(buf + len, size - len, "%d\t", freq); - len += snprintf(buf + len, size - len, + len += scnprintf(buf + len, size - len, "%d\t%d\t%d\t%d\t%d\t%d\n", cal_pier->refPower, cal_pier->voltMeas, @@ -3505,12 +3505,12 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, len += scnprintf(buf + len, size - len, "Calibration data\n"); len = ar9003_dump_cal_data(ah, buf, len, size, true); - len += snprintf(buf + len, size - len, + len += scnprintf(buf + len, size - len, "%20s :\n", "5GHz modal Header"); len = ar9003_dump_modal_eeprom(buf, len, size, &eep->modalHeader5G); - len += snprintf(buf + len, size - len, "Calibration data\n"); + len += scnprintf(buf + len, size - len, "Calibration data\n"); len = ar9003_dump_cal_data(ah, buf, len, size, false); goto out; -- cgit v1.2.3 From 2c2ab5af7d1470d7ba56525cc0c3eebe5ee2bad0 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 4 Feb 2019 21:05:55 +0300 Subject: sh_eth: rename sh_eth_cpu_data::hw_checksum Commit 62e04b7e0e3c ("sh_eth: rename 'sh_eth_cpu_data::hw_crc'") renamed the field to 'hw_checksum' for the Ether DMAC "intelligent checksum", however some Ether MACs implement a simpler checksumming scheme, so that name now seems misleading. Rename that field to 'csmr' as the "intelligent checksum" is always controlled by the CSMR register. Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 14 +++++++------- drivers/net/ethernet/renesas/sh_eth.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index f27a0dc8c563..ee4839983896 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -555,7 +555,7 @@ static int sh_eth_soft_reset_gether(struct net_device *ndev) sh_eth_write(ndev, 0, RDFFR); /* Reset HW CRC register */ - if (mdp->cd->hw_checksum) + if (mdp->cd->csmr) sh_eth_write(ndev, 0, CSMR); /* Select MII mode */ @@ -619,7 +619,7 @@ static struct sh_eth_cpu_data r7s72100_data = { .no_trimd = 1, .no_ade = 1, .xdfar_rw = 1, - .hw_checksum = 1, + .csmr = 1, .tsu = 1, .no_tx_cntrs = 1, }; @@ -668,7 +668,7 @@ static struct sh_eth_cpu_data r8a7740_data = { .no_trimd = 1, .no_ade = 1, .xdfar_rw = 1, - .hw_checksum = 1, + .csmr = 1, .tsu = 1, .select_mii = 1, .magic = 1, @@ -793,7 +793,7 @@ static struct sh_eth_cpu_data r8a77980_data = { .no_trimd = 1, .no_ade = 1, .xdfar_rw = 1, - .hw_checksum = 1, + .csmr = 1, .select_mii = 1, .magic = 1, .cexcr = 1, @@ -1045,7 +1045,7 @@ static struct sh_eth_cpu_data sh7734_data = { .no_ade = 1, .xdfar_rw = 1, .tsu = 1, - .hw_checksum = 1, + .csmr = 1, .select_mii = 1, .magic = 1, .cexcr = 1, @@ -1633,7 +1633,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) * the RFS bits are from bit 25 to bit 16. So, the * driver needs right shifting by 16. */ - if (mdp->cd->hw_checksum) + if (mdp->cd->csmr) desc_status >>= 16; skb = mdp->rx_skbuff[entry]; @@ -2173,7 +2173,7 @@ static size_t __sh_eth_get_regs(struct net_device *ndev, u32 *buf) add_reg(MAFCR); if (cd->rtrate) add_reg(RTRATE); - if (cd->hw_checksum) + if (cd->csmr) add_reg(CSMR); if (cd->select_mii) add_reg(RMII_MII); diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 0c18650bbfe6..46d2fdf9d456 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -499,7 +499,7 @@ struct sh_eth_cpu_data { unsigned no_ade:1; /* E-DMAC DOES NOT have ADE bit in EESR */ unsigned no_xdfar:1; /* E-DMAC DOES NOT have RDFAR/TDFAR */ unsigned xdfar_rw:1; /* E-DMAC has writeable RDFAR/TDFAR */ - unsigned hw_checksum:1; /* E-DMAC has CSMR */ + unsigned csmr:1; /* E-DMAC has CSMR */ unsigned select_mii:1; /* EtherC has RMII_MII (MII select register) */ unsigned rmiimode:1; /* EtherC has RMIIMODE register */ unsigned rtrate:1; /* EtherC has RTRATE register */ -- cgit v1.2.3 From f8e022db50564705e9e957a729a955f396a71093 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 4 Feb 2019 21:06:52 +0300 Subject: sh_eth: RX checksum offload support Add support for the RX checksum offload. This is enabled by default and may be disabled and re-enabled using 'ethtool': # ethtool -K eth0 rx off # ethtool -K eth0 rx on Some Ether MACs provide a simple checksumming scheme which appears to be completely compatible with CHECKSUM_COMPLETE: sum of all packet data after the L2 header is appended to packet data; this may be trivially read by the driver and used to update the skb accordingly. The same checksumming scheme is implemented in the EtherAVB MACs and now supported by the 'ravb' driver. In terms of performance, throughput is close to gigabit line rate with the RX checksum offload both enabled and disabled. The 'perf' output, however, appears to indicate that significantly less time is spent in do_csum() -- this is as expected. Test results with RX checksum offload enabled: ~/netperf-2.2pl4# perf record -a ./netperf -t TCP_MAERTS -H 192.168.2.4 TCP MAERTS TEST to 192.168.2.4 Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 131072 16384 16384 10.01 933.93 [ perf record: Woken up 8 times to write data ] [ perf record: Captured and wrote 1.955 MB perf.data (41940 samples) ] ~/netperf-2.2pl4# perf report Samples: 41K of event 'cycles:ppp', Event count (approx.): 9915302763 Overhead Command Shared Object Symbol 9.44% netperf [kernel.kallsyms] [k] __arch_copy_to_user 7.75% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irq 6.31% swapper [kernel.kallsyms] [k] default_idle_call 5.89% swapper [kernel.kallsyms] [k] arch_cpu_idle 4.37% swapper [kernel.kallsyms] [k] tick_nohz_idle_exit 4.02% netperf [kernel.kallsyms] [k] _raw_spin_unlock_irq 2.52% netperf [kernel.kallsyms] [k] preempt_count_sub 1.81% netperf [kernel.kallsyms] [k] tcp_recvmsg 1.80% netperf [kernel.kallsyms] [k] _raw_spin_unlock_irqres 1.78% netperf [kernel.kallsyms] [k] preempt_count_add 1.36% netperf [kernel.kallsyms] [k] __tcp_transmit_skb 1.20% netperf [kernel.kallsyms] [k] __local_bh_enable_ip 1.10% netperf [kernel.kallsyms] [k] sh_eth_start_xmit Test results with RX checksum offload disabled: ~/netperf-2.2pl4# perf record -a ./netperf -t TCP_MAERTS -H 192.168.2.4 TCP MAERTS TEST to 192.168.2.4 Recv Send Send Socket Socket Message Elapsed Size Size Size Time Throughput bytes bytes bytes secs. 10^6bits/sec 131072 16384 16384 10.01 932.04 [ perf record: Woken up 14 times to write data ] [ perf record: Captured and wrote 3.642 MB perf.data (78817 samples) ] ~/netperf-2.2pl4# perf report Samples: 78K of event 'cycles:ppp', Event count (approx.): 18091442796 Overhead Command Shared Object Symbol 7.00% swapper [kernel.kallsyms] [k] do_csum 3.94% swapper [kernel.kallsyms] [k] sh_eth_poll 3.83% ksoftirqd/0 [kernel.kallsyms] [k] do_csum 3.23% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irq 2.87% netperf [kernel.kallsyms] [k] __arch_copy_to_user 2.86% swapper [kernel.kallsyms] [k] arch_cpu_idle 2.13% swapper [kernel.kallsyms] [k] default_idle_call 2.12% ksoftirqd/0 [kernel.kallsyms] [k] sh_eth_poll 2.02% swapper [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore 1.84% swapper [kernel.kallsyms] [k] __softirqentry_text_start 1.64% swapper [kernel.kallsyms] [k] tick_nohz_idle_exit 1.53% netperf [kernel.kallsyms] [k] _raw_spin_unlock_irq 1.32% netperf [kernel.kallsyms] [k] preempt_count_sub 1.27% swapper [kernel.kallsyms] [k] __pi___inval_dcache_area 1.22% swapper [kernel.kallsyms] [k] check_preemption_disabled 1.01% ksoftirqd/0 [kernel.kallsyms] [k] _raw_spin_unlock_irqrestore The above results collected on the R-Car V3H Starter Kit board. Based on the commit 4d86d3818627 ("ravb: RX checksum offload")... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 60 +++++++++++++++++++++++++++++++++-- drivers/net/ethernet/renesas/sh_eth.h | 1 + 2 files changed, 59 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index ee4839983896..4e3456bb37bb 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1532,8 +1532,9 @@ static int sh_eth_dev_init(struct net_device *ndev) mdp->irq_enabled = true; sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); - /* PAUSE Prohibition */ + /* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */ sh_eth_write(ndev, ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | + (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) | ECMR_TE | ECMR_RE, ECMR); if (mdp->cd->set_rate) @@ -1592,6 +1593,19 @@ static void sh_eth_dev_exit(struct net_device *ndev) update_mac_address(ndev); } +static void sh_eth_rx_csum(struct sk_buff *skb) +{ + u8 *hw_csum; + + /* The hardware checksum is 2 bytes appended to packet data */ + if (unlikely(skb->len < sizeof(__sum16))) + return; + hw_csum = skb_tail_pointer(skb) - sizeof(__sum16); + skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum)); + skb->ip_summed = CHECKSUM_COMPLETE; + skb_trim(skb, skb->len - sizeof(__sum16)); +} + /* Packet receive function */ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) { @@ -1666,6 +1680,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) DMA_FROM_DEVICE); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); + if (ndev->features & NETIF_F_RXCSUM) + sh_eth_rx_csum(skb); netif_receive_skb(skb); ndev->stats.rx_packets++; ndev->stats.rx_bytes += pkt_len; @@ -2921,6 +2937,39 @@ static void sh_eth_set_rx_mode(struct net_device *ndev) spin_unlock_irqrestore(&mdp->lock, flags); } +static void sh_eth_set_rx_csum(struct net_device *ndev, bool enable) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + unsigned long flags; + + spin_lock_irqsave(&mdp->lock, flags); + + /* Disable TX and RX */ + sh_eth_rcv_snd_disable(ndev); + + /* Modify RX Checksum setting */ + sh_eth_modify(ndev, ECMR, ECMR_RCSC, enable ? ECMR_RCSC : 0); + + /* Enable TX and RX */ + sh_eth_rcv_snd_enable(ndev); + + spin_unlock_irqrestore(&mdp->lock, flags); +} + +static int sh_eth_set_features(struct net_device *ndev, + netdev_features_t features) +{ + netdev_features_t changed = ndev->features ^ features; + struct sh_eth_private *mdp = netdev_priv(ndev); + + if (changed & NETIF_F_RXCSUM && mdp->cd->rx_csum) + sh_eth_set_rx_csum(ndev, features & NETIF_F_RXCSUM); + + ndev->features = features; + + return 0; +} + static int sh_eth_get_vtag_index(struct sh_eth_private *mdp) { if (!mdp->port) @@ -3102,6 +3151,7 @@ static const struct net_device_ops sh_eth_netdev_ops = { .ndo_change_mtu = sh_eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, + .ndo_set_features = sh_eth_set_features, }; static const struct net_device_ops sh_eth_netdev_ops_tsu = { @@ -3117,6 +3167,7 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = { .ndo_change_mtu = sh_eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, + .ndo_set_features = sh_eth_set_features, }; #ifdef CONFIG_OF @@ -3245,6 +3296,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev) ndev->max_mtu = 2000 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); ndev->min_mtu = ETH_MIN_MTU; + if (mdp->cd->rx_csum) { + ndev->features = NETIF_F_RXCSUM; + ndev->hw_features = NETIF_F_RXCSUM; + } + /* set function */ if (mdp->cd->tsu) ndev->netdev_ops = &sh_eth_netdev_ops_tsu; @@ -3294,7 +3350,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev) goto out_release; } mdp->port = port; - ndev->features = NETIF_F_HW_VLAN_CTAG_FILTER; + ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; /* Need to init only the first port of the two sharing a TSU */ if (port == 0) { diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 46d2fdf9d456..850726301e1c 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -500,6 +500,7 @@ struct sh_eth_cpu_data { unsigned no_xdfar:1; /* E-DMAC DOES NOT have RDFAR/TDFAR */ unsigned xdfar_rw:1; /* E-DMAC has writeable RDFAR/TDFAR */ unsigned csmr:1; /* E-DMAC has CSMR */ + unsigned rx_csum:1; /* EtherC has ECMR.RCSC */ unsigned select_mii:1; /* EtherC has RMII_MII (MII select register) */ unsigned rmiimode:1; /* EtherC has RMIIMODE register */ unsigned rtrate:1; /* EtherC has RTRATE register */ -- cgit v1.2.3 From 48132cd0c6317701421df3232a77c0a642292859 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 4 Feb 2019 21:07:53 +0300 Subject: sh_eth: offload RX checksum on R7S72100 The RZ/A1H (R7S721000) SoC manual describes the Ether MAC's RX checksum offload the same way as it's implemented in the EtherAVB MACs... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 4e3456bb37bb..00cbca124302 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -620,6 +620,7 @@ static struct sh_eth_cpu_data r7s72100_data = { .no_ade = 1, .xdfar_rw = 1, .csmr = 1, + .rx_csum = 1, .tsu = 1, .no_tx_cntrs = 1, }; -- cgit v1.2.3 From 040c16fd5974a947bcfb2fe2e66fe4f42eeef08a Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 4 Feb 2019 21:08:54 +0300 Subject: sh_eth: offload RX checksum on R8A7740 The R-Mobile A1 (R8A7740) SoC manual describes the Ether MAC's RX checksum offload the same way as it's implemented in the EtherAVB MAC... Signed-off-by: Sergei Shtylyov Tested-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 00cbca124302..b96f25230f2e 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -670,6 +670,7 @@ static struct sh_eth_cpu_data r8a7740_data = { .no_ade = 1, .xdfar_rw = 1, .csmr = 1, + .rx_csum = 1, .tsu = 1, .select_mii = 1, .magic = 1, -- cgit v1.2.3 From 0da843adeefb4953a1a73a24d5a8dfbbffcd9a47 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 4 Feb 2019 21:10:32 +0300 Subject: sh_eth: offload RX checksum on R8A77980 The R-Car V3H (R8A77980) SoC manual describes the Ether MAC's RX checksum offload the same way as it's implemented in the EtherAVB MAC... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index b96f25230f2e..8733afe764b4 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -796,6 +796,7 @@ static struct sh_eth_cpu_data r8a77980_data = { .no_ade = 1, .xdfar_rw = 1, .csmr = 1, + .rx_csum = 1, .select_mii = 1, .magic = 1, .cexcr = 1, -- cgit v1.2.3 From 06240e1b526d426acfe7b21e673da49e12f5a225 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 4 Feb 2019 21:11:32 +0300 Subject: sh_eth: offload RX checksum on SH7734 The SH7734 SoC manual describes the Ether MAC's RX checksum offload the same way as it's implemented in the EtherAVB MACs... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 8733afe764b4..104a7dd9d5ea 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1049,6 +1049,7 @@ static struct sh_eth_cpu_data sh7734_data = { .xdfar_rw = 1, .tsu = 1, .csmr = 1, + .rx_csum = 1, .select_mii = 1, .magic = 1, .cexcr = 1, -- cgit v1.2.3 From 997feb11b83bd1c3b0100587a773629cabb83ce2 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 4 Feb 2019 21:12:39 +0300 Subject: sh_eth: offload RX checksum on SH7763 The SH7763 SoC manual describes the Ether MAC's RX checksum offload the same way as it's implemented in the EtherAVB MACs... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 104a7dd9d5ea..339b2eae2100 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1092,6 +1092,7 @@ static struct sh_eth_cpu_data sh7763_data = { .irq_flags = IRQF_SHARED, .magic = 1, .cexcr = 1, + .rx_csum = 1, .dual_port = 1, }; -- cgit v1.2.3 From fc9c5a4a5a570571fa5a0d472ad7a637ceda6b7e Mon Sep 17 00:00:00 2001 From: Tonghao Zhang Date: Tue, 29 Jan 2019 13:23:24 -0800 Subject: net/mlx5: Fix code style issue in mlx driver Add the tab before '}' and keep the code style consistent. Signed-off-by: Tonghao Zhang Reviewed-by: Or Gerlitz Acked-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index b2df7c3749fb..b354f3ee94c5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -619,7 +619,8 @@ static struct mlx5_flow_group *alloc_flow_group(struct mlx5_flow_steering *steer if (ret) { kmem_cache_free(steering->fgs_cache, fg); return ERR_PTR(ret); -} + } + ida_init(&fg->fte_allocator); fg->mask.match_criteria_enable = match_criteria_enable; memcpy(&fg->mask.match_criteria, match_criteria, -- cgit v1.2.3 From 5468e82f7034f0ae175a3ce075441356099bdaa3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 4 Feb 2019 11:26:18 +0100 Subject: net: phy: fixed-phy: Drop GPIO from fixed_phy_add() All users of the fixed_phy_add() pass -1 as GPIO number to the fixed phy driver, and all users of fixed_phy_register() pass -1 as GPIO number as well, except for the device tree MDIO bus. Any new users should create a proper device and pass the GPIO as a descriptor associated with the device so delete the GPIO argument from the calls and drop the code looking requesting a GPIO in fixed_phy_add(). In fixed phy_register(), investigate the "fixed-link" node and pick the GPIO descriptor from "link-gpios" if this property exists. Move the corresponding code out of of_mdio.c as the fixed phy code anyways requires OF to be in use. Tested-by: Andrew Lunn Signed-off-by: Linus Walleij Signed-off-by: David S. Miller --- .../networking/device_drivers/stmicro/stmmac.txt | 2 +- arch/m68k/coldfire/m5272.c | 2 +- arch/mips/ar7/platform.c | 4 +- arch/mips/bcm47xx/setup.c | 2 +- drivers/net/dsa/dsa_loop.c | 2 +- drivers/net/ethernet/broadcom/bgmac.c | 2 +- drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +- drivers/net/phy/fixed_phy.c | 82 ++++++++++++++++------ drivers/net/usb/lan78xx.c | 3 +- drivers/of/of_mdio.c | 9 +-- include/linux/phy_fixed.h | 8 +-- 11 files changed, 72 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/device_drivers/stmicro/stmmac.txt b/Documentation/networking/device_drivers/stmicro/stmmac.txt index 2bb07078f535..1ae979fd90d2 100644 --- a/Documentation/networking/device_drivers/stmicro/stmmac.txt +++ b/Documentation/networking/device_drivers/stmicro/stmmac.txt @@ -267,7 +267,7 @@ static struct fixed_phy_status stmmac0_fixed_phy_status = { During the board's device_init we can configure the first MAC for fixed_link by calling: - fixed_phy_add(PHY_POLL, 1, &stmmac0_fixed_phy_status, -1); + fixed_phy_add(PHY_POLL, 1, &stmmac0_fixed_phy_status); and the second one, with a real PHY device attached to the bus, by using the stmmac_mdio_bus_data structure (to provide the id, the reset procedure etc). diff --git a/arch/m68k/coldfire/m5272.c b/arch/m68k/coldfire/m5272.c index ad1185c68df7..6b3ab583c698 100644 --- a/arch/m68k/coldfire/m5272.c +++ b/arch/m68k/coldfire/m5272.c @@ -127,7 +127,7 @@ static struct fixed_phy_status nettel_fixed_phy_status __initdata = { static int __init init_BSP(void) { m5272_uarts_init(); - fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status, -1); + fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status); return 0; } diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index f09262e0a72f..10ff07b7721e 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -683,7 +683,7 @@ static int __init ar7_register_devices(void) if (ar7_has_high_cpmac()) { res = fixed_phy_add(PHY_POLL, cpmac_high.id, - &fixed_phy_status, -1); + &fixed_phy_status); if (!res) { cpmac_get_mac(1, cpmac_high_data.dev_addr); @@ -696,7 +696,7 @@ static int __init ar7_register_devices(void) } else cpmac_low_data.phy_mask = 0xffffffff; - res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status, -1); + res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status); if (!res) { cpmac_get_mac(0, cpmac_low_data.dev_addr); res = platform_device_register(&cpmac_low); diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index fe3773539eff..82627c264964 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -274,7 +274,7 @@ static int __init bcm47xx_register_bus_complete(void) bcm47xx_leds_register(); bcm47xx_workarounds(); - fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status, -1); + fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status); return 0; } device_initcall(bcm47xx_register_bus_complete); diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c index 816f34d64736..17482ae09aa5 100644 --- a/drivers/net/dsa/dsa_loop.c +++ b/drivers/net/dsa/dsa_loop.c @@ -343,7 +343,7 @@ static int __init dsa_loop_init(void) unsigned int i; for (i = 0; i < NUM_FIXED_PHYS; i++) - phydevs[i] = fixed_phy_register(PHY_POLL, &status, -1, NULL); + phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL); return mdio_driver_register(&dsa_loop_drv); } diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 2d3a44c40221..4632dd5dbad1 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -1446,7 +1446,7 @@ int bgmac_phy_connect_direct(struct bgmac *bgmac) struct phy_device *phy_dev; int err; - phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL); + phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, NULL); if (!phy_dev || IS_ERR(phy_dev)) { dev_err(bgmac->dev, "Failed to register fixed PHY device\n"); return -ENODEV; diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index aceb9b7b55bd..51880d83131a 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -525,7 +525,7 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv) .asym_pause = 0, }; - phydev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL); + phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL); if (!phydev || IS_ERR(phydev)) { dev_err(kdev, "failed to register fixed PHY device\n"); return -ENODEV; diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index 47a8cb574c45..f136a23c1a35 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -38,7 +38,7 @@ struct fixed_phy { bool no_carrier; int (*link_update)(struct net_device *, struct fixed_phy_status *); struct list_head node; - int link_gpio; + struct gpio_desc *link_gpiod; }; static struct platform_device *pdev; @@ -67,8 +67,8 @@ EXPORT_SYMBOL_GPL(fixed_phy_change_carrier); static void fixed_phy_update(struct fixed_phy *fp) { - if (!fp->no_carrier && gpio_is_valid(fp->link_gpio)) - fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); + if (!fp->no_carrier && fp->link_gpiod) + fp->status.link = !!gpiod_get_value_cansleep(fp->link_gpiod); } static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) @@ -133,9 +133,9 @@ int fixed_phy_set_link_update(struct phy_device *phydev, } EXPORT_SYMBOL_GPL(fixed_phy_set_link_update); -int fixed_phy_add(unsigned int irq, int phy_addr, - struct fixed_phy_status *status, - int link_gpio) +static int fixed_phy_add_gpiod(unsigned int irq, int phy_addr, + struct fixed_phy_status *status, + struct gpio_desc *gpiod) { int ret; struct fixed_mdio_bus *fmb = &platform_fmb; @@ -156,24 +156,19 @@ int fixed_phy_add(unsigned int irq, int phy_addr, fp->addr = phy_addr; fp->status = *status; - fp->link_gpio = link_gpio; - - if (gpio_is_valid(fp->link_gpio)) { - ret = gpio_request_one(fp->link_gpio, GPIOF_DIR_IN, - "fixed-link-gpio-link"); - if (ret) - goto err_regs; - } + fp->link_gpiod = gpiod; fixed_phy_update(fp); list_add_tail(&fp->node, &fmb->phys); return 0; +} -err_regs: - kfree(fp); - return ret; +int fixed_phy_add(unsigned int irq, int phy_addr, + struct fixed_phy_status *status) { + + return fixed_phy_add_gpiod(irq, phy_addr, status, NULL); } EXPORT_SYMBOL_GPL(fixed_phy_add); @@ -187,8 +182,8 @@ static void fixed_phy_del(int phy_addr) list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { if (fp->addr == phy_addr) { list_del(&fp->node); - if (gpio_is_valid(fp->link_gpio)) - gpio_free(fp->link_gpio); + if (fp->link_gpiod) + gpiod_put(fp->link_gpiod); kfree(fp); ida_simple_remove(&phy_fixed_ida, phy_addr); return; @@ -196,12 +191,50 @@ static void fixed_phy_del(int phy_addr) } } +#ifdef CONFIG_OF_GPIO +static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np) +{ + struct device_node *fixed_link_node; + struct gpio_desc *gpiod; + + if (!np) + return NULL; + + fixed_link_node = of_get_child_by_name(np, "fixed-link"); + if (!fixed_link_node) + return NULL; + + /* + * As the fixed link is just a device tree node without any + * Linux device associated with it, we simply have obtain + * the GPIO descriptor from the device tree like this. + */ + gpiod = gpiod_get_from_of_node(fixed_link_node, "link-gpios", 0, + GPIOD_IN, "mdio"); + of_node_put(fixed_link_node); + if (IS_ERR(gpiod)) { + if (PTR_ERR(gpiod) == -EPROBE_DEFER) + return gpiod; + pr_err("error getting GPIO for fixed link %pOF, proceed without\n", + fixed_link_node); + gpiod = NULL; + } + + return gpiod; +} +#else +static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np) +{ + return NULL; +} +#endif + struct phy_device *fixed_phy_register(unsigned int irq, struct fixed_phy_status *status, - int link_gpio, struct device_node *np) { struct fixed_mdio_bus *fmb = &platform_fmb; + struct gpio_desc *gpiod = NULL; struct phy_device *phy; int phy_addr; int ret; @@ -209,12 +242,17 @@ struct phy_device *fixed_phy_register(unsigned int irq, if (!fmb->mii_bus || fmb->mii_bus->state != MDIOBUS_REGISTERED) return ERR_PTR(-EPROBE_DEFER); + /* Check if we have a GPIO associated with this fixed phy */ + gpiod = fixed_phy_get_gpiod(np); + if (IS_ERR(gpiod)) + return ERR_CAST(gpiod); + /* Get the next available PHY address, up to PHY_MAX_ADDR */ phy_addr = ida_simple_get(&phy_fixed_ida, 0, PHY_MAX_ADDR, GFP_KERNEL); if (phy_addr < 0) return ERR_PTR(phy_addr); - ret = fixed_phy_add(irq, phy_addr, status, link_gpio); + ret = fixed_phy_add_gpiod(irq, phy_addr, status, gpiod); if (ret < 0) { ida_simple_remove(&phy_fixed_ida, phy_addr); return ERR_PTR(ret); diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index e96bc0c6140f..3d92ea6fcc02 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2051,8 +2051,7 @@ static struct phy_device *lan7801_phy_init(struct lan78xx_net *dev) phydev = phy_find_first(dev->mdiobus); if (!phydev) { netdev_dbg(dev->net, "PHY Not Found!! Registering Fixed PHY\n"); - phydev = fixed_phy_register(PHY_POLL, &fphy_status, -1, - NULL); + phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL); if (IS_ERR(phydev)) { netdev_err(dev->net, "No PHY/fixed_PHY found\n"); return NULL; diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index 5ad1342f5682..de6157357e26 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -463,7 +462,6 @@ int of_phy_register_fixed_link(struct device_node *np) struct device_node *fixed_link_node; u32 fixed_link_prop[5]; const char *managed; - int link_gpio = -1; if (of_property_read_string(np, "managed", &managed) == 0 && strcmp(managed, "in-band-status") == 0) { @@ -485,11 +483,7 @@ int of_phy_register_fixed_link(struct device_node *np) status.pause = of_property_read_bool(fixed_link_node, "pause"); status.asym_pause = of_property_read_bool(fixed_link_node, "asym-pause"); - link_gpio = of_get_named_gpio_flags(fixed_link_node, - "link-gpios", 0, NULL); of_node_put(fixed_link_node); - if (link_gpio == -EPROBE_DEFER) - return -EPROBE_DEFER; goto register_phy; } @@ -508,8 +502,7 @@ int of_phy_register_fixed_link(struct device_node *np) return -ENODEV; register_phy: - return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, link_gpio, - np)); + return PTR_ERR_OR_ZERO(fixed_phy_register(PHY_POLL, &status, np)); } EXPORT_SYMBOL(of_phy_register_fixed_link); diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h index 9525567b1951..c78fc203db43 100644 --- a/include/linux/phy_fixed.h +++ b/include/linux/phy_fixed.h @@ -15,11 +15,9 @@ struct device_node; #if IS_ENABLED(CONFIG_FIXED_PHY) extern int fixed_phy_change_carrier(struct net_device *dev, bool new_carrier); extern int fixed_phy_add(unsigned int irq, int phy_id, - struct fixed_phy_status *status, - int link_gpio); + struct fixed_phy_status *status); extern struct phy_device *fixed_phy_register(unsigned int irq, struct fixed_phy_status *status, - int link_gpio, struct device_node *np); extern void fixed_phy_unregister(struct phy_device *phydev); extern int fixed_phy_set_link_update(struct phy_device *phydev, @@ -27,14 +25,12 @@ extern int fixed_phy_set_link_update(struct phy_device *phydev, struct fixed_phy_status *)); #else static inline int fixed_phy_add(unsigned int irq, int phy_id, - struct fixed_phy_status *status, - int link_gpio) + struct fixed_phy_status *status) { return -ENODEV; } static inline struct phy_device *fixed_phy_register(unsigned int irq, struct fixed_phy_status *status, - int gpio_link, struct device_node *np) { return ERR_PTR(-ENODEV); -- cgit v1.2.3 From dd648818dad3ad5ab5151c7f5ca0bb55a0bf71de Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Mon, 4 Feb 2019 09:30:38 -0800 Subject: net: nixge: Make mdio child node optional Make MDIO child optional and only instantiate the MDIO bus if the child is actually present. There are currently no (in-tree) users of this binding; all (out-of-tree) users use overlays that get shipped together with the FPGA images that contain the IP. This will significantly increase maintainabilty of future revisions of this IP. Reviewed-by: Andrew Lunn Signed-off-by: Moritz Fischer Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/nixge.txt | 27 ++++++++++++++++++++++--- drivers/net/ethernet/ni/nixge.c | 19 +++++++++++------ 2 files changed, 37 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/net/nixge.txt b/Documentation/devicetree/bindings/net/nixge.txt index 44a7358b4399..bb2929f9c64f 100644 --- a/Documentation/devicetree/bindings/net/nixge.txt +++ b/Documentation/devicetree/bindings/net/nixge.txt @@ -16,6 +16,9 @@ Required properties: - nvmem-cells: Phandle of nvmem cell containing the MAC address - nvmem-cell-names: Should be "address" +Optional properties: +- mdio subnode to indicate presence of MDIO controller + Examples (10G generic PHY): nixge0: ethernet@40000000 { compatible = "ni,xge-enet-3.00"; @@ -33,8 +36,26 @@ Examples (10G generic PHY): phy-mode = "xgmii"; phy-handle = <ðernet_phy1>; - ethernet_phy1: ethernet-phy@4 { - compatible = "ethernet-phy-ieee802.3-c45"; - reg = <4>; + mdio { + ethernet_phy1: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <4>; + }; }; }; + +Examples (10G generic PHY, no MDIO): + nixge0: ethernet@40000000 { + compatible = "ni,xge-enet-2.00"; + reg = <0x40000000 0x6000>; + + nvmem-cells = <ð1_addr>; + nvmem-cell-names = "address"; + + interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>, <0 30 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "rx", "tx"; + interrupt-parent = <&intc>; + + phy-mode = "xgmii"; + phy-handle = <ðernet_phy1>; + }; diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index 73a98bd2fcd2..c8dd1e4c759d 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -1284,6 +1284,7 @@ static int nixge_probe(struct platform_device *pdev) { struct nixge_priv *priv; struct net_device *ndev; + struct device_node *mn; const u8 *mac_addr; int err; @@ -1335,10 +1336,14 @@ static int nixge_probe(struct platform_device *pdev) priv->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; priv->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; - err = nixge_mdio_setup(priv, pdev->dev.of_node); - if (err) { - netdev_err(ndev, "error registering mdio bus"); - goto free_netdev; + mn = of_get_child_by_name(pdev->dev.of_node, "mdio"); + if (mn) { + err = nixge_mdio_setup(priv, mn); + of_node_put(mn); + if (err) { + netdev_err(ndev, "error registering mdio bus"); + goto free_netdev; + } } priv->phy_mode = of_get_phy_mode(pdev->dev.of_node); @@ -1364,7 +1369,8 @@ static int nixge_probe(struct platform_device *pdev) return 0; unregister_mdio: - mdiobus_unregister(priv->mii_bus); + if (priv->mii_bus) + mdiobus_unregister(priv->mii_bus); free_netdev: free_netdev(ndev); @@ -1379,7 +1385,8 @@ static int nixge_remove(struct platform_device *pdev) unregister_netdev(ndev); - mdiobus_unregister(priv->mii_bus); + if (priv->mii_bus) + mdiobus_unregister(priv->mii_bus); free_netdev(ndev); -- cgit v1.2.3 From 8dc0ae90ad02b368ffdbee7a3509750dcd3c1b13 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Mon, 4 Feb 2019 09:30:39 -0800 Subject: net: nixge: Add support for fixed-link configurations Add support for fixed-link configurations to nixge driver. Signed-off-by: Moritz Fischer Signed-off-by: David S. Miller --- drivers/net/ethernet/ni/nixge.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index c8dd1e4c759d..96f7a9818294 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -1282,9 +1282,9 @@ static int nixge_of_get_resources(struct platform_device *pdev) static int nixge_probe(struct platform_device *pdev) { + struct device_node *mn, *phy_node; struct nixge_priv *priv; struct net_device *ndev; - struct device_node *mn; const u8 *mac_addr; int err; @@ -1353,21 +1353,30 @@ static int nixge_probe(struct platform_device *pdev) goto unregister_mdio; } - priv->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); - if (!priv->phy_node) { - netdev_err(ndev, "not find \"phy-handle\" property\n"); - err = -EINVAL; - goto unregister_mdio; + phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); + if (!phy_node && of_phy_is_fixed_link(pdev->dev.of_node)) { + err = of_phy_register_fixed_link(pdev->dev.of_node); + if (err < 0) { + netdev_err(ndev, "broken fixed-link specification\n"); + goto unregister_mdio; + } + phy_node = of_node_get(pdev->dev.of_node); } + priv->phy_node = phy_node; err = register_netdev(priv->ndev); if (err) { netdev_err(ndev, "register_netdev() error (%i)\n", err); - goto unregister_mdio; + goto free_phy; } return 0; +free_phy: + if (of_phy_is_fixed_link(pdev->dev.of_node)) + of_phy_deregister_fixed_link(pdev->dev.of_node); + of_node_put(phy_node); + unregister_mdio: if (priv->mii_bus) mdiobus_unregister(priv->mii_bus); @@ -1385,6 +1394,10 @@ static int nixge_remove(struct platform_device *pdev) unregister_netdev(ndev); + if (of_phy_is_fixed_link(pdev->dev.of_node)) + of_phy_deregister_fixed_link(pdev->dev.of_node); + of_node_put(priv->phy_node); + if (priv->mii_bus) mdiobus_unregister(priv->mii_bus); -- cgit v1.2.3 From 4a4cec7257908d3482a22d43f3a9f229d4592f5c Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 4 Feb 2019 23:35:54 +0000 Subject: net: marvell: mvpp2: use phy_interface_mode_is_8023z() helper Use the phy_interface_mode_is_8023z() helper for detecting interface modes that use 802.3z serial encoding. This is equivalent to testing for both 1000base-X and 2500base-X. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 38 ++++++++++--------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 16066c2d5b3a..1b82202f8c17 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1090,9 +1090,8 @@ static void mvpp22_gop_unmask_irq(struct mvpp2_port *port) u32 val; if (phy_interface_mode_is_rgmii(port->phy_interface) || - port->phy_interface == PHY_INTERFACE_MODE_SGMII || - port->phy_interface == PHY_INTERFACE_MODE_1000BASEX || - port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + phy_interface_mode_is_8023z(port->phy_interface) || + port->phy_interface == PHY_INTERFACE_MODE_SGMII) { /* Enable the GMAC link status irq for this port */ val = readl(port->base + MVPP22_GMAC_INT_SUM_MASK); val |= MVPP22_GMAC_INT_SUM_MASK_LINK_STAT; @@ -1122,9 +1121,8 @@ static void mvpp22_gop_mask_irq(struct mvpp2_port *port) } if (phy_interface_mode_is_rgmii(port->phy_interface) || - port->phy_interface == PHY_INTERFACE_MODE_SGMII || - port->phy_interface == PHY_INTERFACE_MODE_1000BASEX || - port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + phy_interface_mode_is_8023z(port->phy_interface) || + port->phy_interface == PHY_INTERFACE_MODE_SGMII) { val = readl(port->base + MVPP22_GMAC_INT_SUM_MASK); val &= ~MVPP22_GMAC_INT_SUM_MASK_LINK_STAT; writel(val, port->base + MVPP22_GMAC_INT_SUM_MASK); @@ -1136,9 +1134,8 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port) u32 val; if (phy_interface_mode_is_rgmii(port->phy_interface) || - port->phy_interface == PHY_INTERFACE_MODE_SGMII || - port->phy_interface == PHY_INTERFACE_MODE_1000BASEX || - port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + phy_interface_mode_is_8023z(port->phy_interface) || + port->phy_interface == PHY_INTERFACE_MODE_SGMII) { val = readl(port->base + MVPP22_GMAC_INT_MASK); val |= MVPP22_GMAC_INT_MASK_LINK_STAT; writel(val, port->base + MVPP22_GMAC_INT_MASK); @@ -1244,9 +1241,8 @@ static void mvpp2_port_loopback_set(struct mvpp2_port *port, else val &= ~MVPP2_GMAC_GMII_LB_EN_MASK; - if (port->phy_interface == PHY_INTERFACE_MODE_SGMII || - port->phy_interface == PHY_INTERFACE_MODE_1000BASEX || - port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) + if (phy_interface_mode_is_8023z(port->phy_interface) || + port->phy_interface == PHY_INTERFACE_MODE_SGMII) val |= MVPP2_GMAC_PCS_LB_EN_MASK; else val &= ~MVPP2_GMAC_PCS_LB_EN_MASK; @@ -2472,9 +2468,8 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id) link = true; } } else if (phy_interface_mode_is_rgmii(port->phy_interface) || - port->phy_interface == PHY_INTERFACE_MODE_SGMII || - port->phy_interface == PHY_INTERFACE_MODE_1000BASEX || - port->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + phy_interface_mode_is_8023z(port->phy_interface) || + port->phy_interface == PHY_INTERFACE_MODE_SGMII) { val = readl(port->base + MVPP22_GMAC_INT_STAT); if (val & MVPP22_GMAC_INT_STAT_LINK) { event = true; @@ -4566,8 +4561,7 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, ctrl0 &= ~MVPP2_GMAC_PORT_TYPE_MASK; ctrl2 &= ~(MVPP2_GMAC_PORT_RESET_MASK | MVPP2_GMAC_PCS_ENABLE_MASK); - if (state->interface == PHY_INTERFACE_MODE_1000BASEX || - state->interface == PHY_INTERFACE_MODE_2500BASEX) { + if (phy_interface_mode_is_8023z(state->interface)) { /* 1000BaseX and 2500BaseX ports cannot negotiate speed nor can * they negotiate duplex: they are always operating with a fixed * speed of 1000/2500Mbps in full duplex, so force 1000/2500 @@ -4587,9 +4581,8 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, if (phylink_test(state->advertising, Asym_Pause)) an |= MVPP2_GMAC_FC_ADV_ASM_EN; - if (state->interface == PHY_INTERFACE_MODE_SGMII || - state->interface == PHY_INTERFACE_MODE_1000BASEX || - state->interface == PHY_INTERFACE_MODE_2500BASEX) { + if (phy_interface_mode_is_8023z(state->interface) || + state->interface == PHY_INTERFACE_MODE_SGMII) { an |= MVPP2_GMAC_IN_BAND_AUTONEG; ctrl2 |= MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PCS_ENABLE_MASK; @@ -4650,9 +4643,8 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, if (state->interface == PHY_INTERFACE_MODE_10GKR) mvpp2_xlg_config(port, mode, state); else if (phy_interface_mode_is_rgmii(state->interface) || - state->interface == PHY_INTERFACE_MODE_SGMII || - state->interface == PHY_INTERFACE_MODE_1000BASEX || - state->interface == PHY_INTERFACE_MODE_2500BASEX) + phy_interface_mode_is_8023z(state->interface) || + state->interface == PHY_INTERFACE_MODE_SGMII) mvpp2_gmac_config(port, mode, state); if (port->priv->hw_version == MVPP21 && port->flags & MVPP2_F_LOOPBACK) -- cgit v1.2.3 From bf2fa12593c2bb77c7ab84254ac69af429d6719b Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 4 Feb 2019 23:35:59 +0000 Subject: net: marvell: mvpp2: fix lack of link interrupts Sven Auhagen reports that if he changes a SFP+ module for a SFP module on the Macchiatobin Single Shot, the link does not come back up. For Sven, it is as easy as: - Insert a SFP+ module connected, and use ping6 to verify link is up. - Remove SFP+ module - Insert SFP 1000base-X module use ping6 to verify link is up: Link up event did not trigger and the link is down but that doesn't show the problem for me. Locally, this has been reproduced by: - Boot with no modules. - Insert SFP+ module, confirm link is up. - Replace module with 25000base-X module. Confirm link is up. - Set remote end down, link is reported as dropped at both ends. - Set remote end up, link is reported up at remote end, but not local end due to lack of link interrupt. Fix this by setting up both GMAC and XLG interrupts for port 0, but only unmasking the appropriate interrupt according to the current mode set in the mac_config() method. However, only do the mask/unmask dance when we are really changing the link mode to avoid missing any link interrupts. Tested-by: Sven Auhagen Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 1b82202f8c17..5c0c26fd8363 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1133,7 +1133,8 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port) { u32 val; - if (phy_interface_mode_is_rgmii(port->phy_interface) || + if (port->phylink || + phy_interface_mode_is_rgmii(port->phy_interface) || phy_interface_mode_is_8023z(port->phy_interface) || port->phy_interface == PHY_INTERFACE_MODE_SGMII) { val = readl(port->base + MVPP22_GMAC_INT_MASK); @@ -4620,6 +4621,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, const struct phylink_link_state *state) { struct mvpp2_port *port = netdev_priv(dev); + bool change_interface = port->phy_interface != state->interface; /* Check for invalid configuration */ if (state->interface == PHY_INTERFACE_MODE_10GKR && port->gop_id != 0) { @@ -4629,14 +4631,16 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, /* Make sure the port is disabled when reconfiguring the mode */ mvpp2_port_disable(port); + if (change_interface) { + mvpp22_gop_mask_irq(port); - if (port->priv->hw_version == MVPP22 && - port->phy_interface != state->interface) { - port->phy_interface = state->interface; + if (port->priv->hw_version == MVPP22) { + port->phy_interface = state->interface; - /* Reconfigure the serdes lanes */ - phy_power_off(port->comphy); - mvpp22_mode_reconfigure(port); + /* Reconfigure the serdes lanes */ + phy_power_off(port->comphy); + mvpp22_mode_reconfigure(port); + } } /* mac (re)configuration */ @@ -4650,6 +4654,9 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, if (port->priv->hw_version == MVPP21 && port->flags & MVPP2_F_LOOPBACK) mvpp2_port_loopback_set(port, state); + if (change_interface) + mvpp22_gop_unmask_irq(port); + mvpp2_port_enable(port); } -- cgit v1.2.3 From 341203e78943236d4a8e4ca58d6a236195f0652e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 Feb 2019 01:16:31 +0200 Subject: mac80211_hwsim: Support boottime in scan results This makes the age information for cfg80211 scan results more accurate and fixes issues with wpa_supplicant dropping "old" scan results (e.g., "wlan0: Own scan request started a scan in 0.000456 seconds") that looked like would have been received before a scan started due to the inaccuracy of the default timing mechanism for calculating the BSS entry age. This makes hwsim test cases significantly more robust to run. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 320edcac4699..87be2b18063a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1273,10 +1273,12 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, * probably doesn't really matter. */ if (ieee80211_is_beacon(hdr->frame_control) || - ieee80211_is_probe_resp(hdr->frame_control)) + ieee80211_is_probe_resp(hdr->frame_control)) { + rx_status.boottime_ns = ktime_get_boot_ns(); now = data->abs_bcn_ts; - else + } else { now = mac80211_hwsim_get_tsf_raw(); + } /* Copy skb to all enabled radios that are on the current frequency */ spin_lock(&hwsim_radio_lock); -- cgit v1.2.3 From 59f58708c5047289589cbf6ee95146b76cf57d1e Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Tue, 11 Dec 2018 15:59:37 +0800 Subject: e1000e: Exclude device from suspend direct complete optimization e1000e sets different WoL settings in system suspend callback and runtime suspend callback. The suspend direct complete optimization leaves e1000e in runtime suspended state with wrong WoL setting during system suspend. To fix this, we need to disable suspend direct complete optimization to let e1000e always use suspend callback to set correct WoL during system suspend. Signed-off-by: Kai-Heng Feng Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/netdev.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 189f231075c2..e19e53d97ac5 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -7351,6 +7351,8 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) e1000_print_device_info(adapter); + dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_NEVER_SKIP); + if (pci_dev_run_wake(pdev)) pm_runtime_put_noidle(&pdev->dev); -- cgit v1.2.3 From 803cc52323e0c863d3f08740b8c156593a5ca1e9 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Tue, 11 Dec 2018 18:55:41 +0200 Subject: igc: Remove unreachable code from igc_phy.c file Address community comment. Remove the unreachable code leads to the static checker warning. PHY functionality will be added later per demand. Reported by Dan Carpenter. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_phy.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igc/igc_phy.c b/drivers/net/ethernet/intel/igc/igc_phy.c index 38e43e6fc1c7..4c8f96a9a148 100644 --- a/drivers/net/ethernet/intel/igc/igc_phy.c +++ b/drivers/net/ethernet/intel/igc/igc_phy.c @@ -152,7 +152,6 @@ void igc_power_down_phy_copper(struct igc_hw *hw) s32 igc_check_downshift(struct igc_hw *hw) { struct igc_phy_info *phy = &hw->phy; - u16 phy_data, offset, mask; s32 ret_val; switch (phy->type) { @@ -161,15 +160,8 @@ s32 igc_check_downshift(struct igc_hw *hw) /* speed downshift not supported */ phy->speed_downgraded = false; ret_val = 0; - goto out; } - ret_val = phy->ops.read_reg(hw, offset, &phy_data); - - if (!ret_val) - phy->speed_downgraded = (phy_data & mask) ? true : false; - -out: return ret_val; } -- cgit v1.2.3 From a8890c38abb2f1706672cafb4094d3726430b335 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Tue, 18 Dec 2018 11:29:54 +0200 Subject: igc: Fix code redundancy Remove redundant igc_check_for_link_base code and replace it with an igc_check_for_copper_link method. Fix duplication of IGC_ADVTXD_PAYLEN_SHIFT mask declaration. Remove obsolete IGC_SCVPC register definition. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_base.c | 20 ++------------------ drivers/net/ethernet/intel/igc/igc_base.h | 3 --- drivers/net/ethernet/intel/igc/igc_regs.h | 1 - 3 files changed, 2 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c index df40af759542..19ff987922d2 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.c +++ b/drivers/net/ethernet/intel/igc/igc_base.c @@ -53,22 +53,6 @@ out: return ret_val; } -/** - * igc_check_for_link_base - Check for link - * @hw: pointer to the HW structure - * - * If sgmii is enabled, then use the pcs register to determine link, otherwise - * use the generic interface for determining link. - */ -static s32 igc_check_for_link_base(struct igc_hw *hw) -{ - s32 ret_val = 0; - - ret_val = igc_check_for_copper_link(hw); - - return ret_val; -} - /** * igc_reset_hw_base - Reset hardware * @hw: pointer to the HW structure @@ -265,7 +249,7 @@ static s32 igc_init_phy_params_base(struct igc_hw *hw) if (ret_val) return ret_val; - igc_check_for_link_base(hw); + igc_check_for_copper_link(hw); /* Verify phy id and set remaining function pointers */ switch (phy->id) { @@ -512,7 +496,7 @@ void igc_rx_fifo_flush_base(struct igc_hw *hw) static struct igc_mac_operations igc_mac_ops_base = { .init_hw = igc_init_hw_base, - .check_for_link = igc_check_for_link_base, + .check_for_link = igc_check_for_copper_link, .rar_set = igc_rar_set, .read_mac_addr = igc_read_mac_addr_base, .get_speed_and_duplex = igc_get_link_up_info_base, diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h index 35588fa7b8c5..a5d3f57274a8 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.h +++ b/drivers/net/ethernet/intel/igc/igc_base.h @@ -90,9 +90,6 @@ union igc_adv_rx_desc { } wb; /* writeback */ }; -/* Adv Transmit Descriptor Config Masks */ -#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ - /* Additional Transmit Descriptor Control definitions */ #define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */ diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h index a1bd3216c906..f8c835283377 100644 --- a/drivers/net/ethernet/intel/igc/igc_regs.h +++ b/drivers/net/ethernet/intel/igc/igc_regs.h @@ -188,7 +188,6 @@ #define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ #define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ #define IGC_LENERRS 0x04138 /* Length Errors Count */ -#define IGC_SCVPC 0x04228 /* SerDes/SGMII Code Violation Pkt Count */ #define IGC_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */ /* Management registers */ -- cgit v1.2.3 From 2242281d6998af1b3cbf216904f4a6c78530ad3b Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 2 Jan 2019 20:20:33 +0100 Subject: ixgbe: remove magic constant in ixgbe_reset_hw_82599() ixgbe_reset_hw_82599() resets the value of hw->mac.num_rar_entries to pre-defined value of 128. Let's get rid of that hardcoded literal, and use IXGBE_82599_RAR_ENTRIES instead, the same way the normal initialization path does. Signed-off-by: Jiri Kosina Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 1e49716f52bc..109f8de5a1c2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -1048,7 +1048,7 @@ mac_reset_top: * clear the multicast table. Also reset num_rar_entries to 128, * since we modify this value when programming the SAN MAC address. */ - hw->mac.num_rar_entries = 128; + hw->mac.num_rar_entries = IXGBE_82599_RAR_ENTRIES; hw->mac.ops.init_rx_addrs(hw); /* Store the permanent SAN mac address */ -- cgit v1.2.3 From ea888b03e3d784fc6617e032a1c01a2d1a04d164 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 3 Jan 2019 16:49:02 -0800 Subject: fm10k: TRIVIAL cleanup of extra spacing in function comment The function comment for fm10k_iov_msg_msix_pf has an extra space in a sentence, which is unnecessary. Signed-off-by: Jacob Keller Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 8f0a99b6a537..cb4d02629b86 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1148,7 +1148,7 @@ static void fm10k_iov_update_stats_pf(struct fm10k_hw *hw, * @results: Pointer array to message, results[0] is pointer to message * @mbx: Pointer to mailbox information structure * - * This function is a default handler for MSI-X requests from the VF. The + * This function is a default handler for MSI-X requests from the VF. The * assumption is that in this case it is acceptable to just directly * hand off the message from the VF to the underlying shared code. **/ -- cgit v1.2.3 From 979eff22c9f49b1882e417bdb750488f80302611 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 3 Jan 2019 17:17:03 -0800 Subject: e1000e: fix a missing check for return value The change is based on the issue found by Kangjie Lu where we not checking the return value of a register read/write which could result in a NULL pointer dereference if the read/write fails. Since we are only trying to disable the far-end loopback, if the read and write of register fails, we do not want to bail out of the function. We just want to log that it failed to disable and continue on. CC: Sasha Neftin CC: Kangjie Lu Signed-off-by: Jeff Kirsher Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/80003es2lan.c | 33 +++++++++++++++++-------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e1000e/80003es2lan.c b/drivers/net/ethernet/intel/e1000e/80003es2lan.c index 257bd59bc9c6..f86d55657959 100644 --- a/drivers/net/ethernet/intel/e1000e/80003es2lan.c +++ b/drivers/net/ethernet/intel/e1000e/80003es2lan.c @@ -696,11 +696,16 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) ret_val = e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data); - if (ret_val) - return ret_val; - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); + if (!ret_val) { + kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_INBAND_PARAM, + kum_reg_data); + if (ret_val) + e_dbg("Error disabling far-end loopback\n"); + } else { + e_dbg("Error disabling far-end loopback\n"); + } ret_val = e1000e_get_auto_rd_done(hw); if (ret_val) @@ -754,11 +759,19 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) return ret_val; /* Disable IBIST slave mode (far-end loopback) */ - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); + ret_val = + e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, + &kum_reg_data); + if (!ret_val) { + kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; + ret_val = e1000_write_kmrn_reg_80003es2lan(hw, + E1000_KMRNCTRLSTA_INBAND_PARAM, + kum_reg_data); + if (ret_val) + e_dbg("Error disabling far-end loopback\n"); + } else { + e_dbg("Error disabling far-end loopback\n"); + } /* Set the transmit descriptor write-back policy */ reg_data = er32(TXDCTL(0)); -- cgit v1.2.3 From 55fdbeaa2db8b271db767240fba24a60bd232528 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Mon, 7 Jan 2019 16:40:17 +0200 Subject: igc: Remove unused code Remove unused igc_adv_data_desc definition from igc_base.h file. Descriptors definition will be added per demand. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_base.h | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igc/igc_base.h b/drivers/net/ethernet/intel/igc/igc_base.h index a5d3f57274a8..76d4991d7284 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.h +++ b/drivers/net/ethernet/intel/igc/igc_base.h @@ -36,28 +36,6 @@ union igc_adv_tx_desc { #define IGC_RAR_ENTRIES 16 -struct igc_adv_data_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - u32 data; - struct { - u32 datalen:16; /* Data buffer length */ - u32 rsvd:4; - u32 dtyp:4; /* Descriptor type */ - u32 dcmd:8; /* Descriptor command */ - } config; - } lower; - union { - u32 data; - struct { - u32 status:4; /* Descriptor status */ - u32 idx:4; - u32 popts:6; /* Packet Options */ - u32 paylen:18; /* Payload length */ - } options; - } upper; -}; - /* Receive Descriptor - Advanced */ union igc_adv_rx_desc { struct { -- cgit v1.2.3 From 439c71f7d2ca07cb5bc3ee0686f1e8a3de45b9cd Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Sun, 13 Jan 2019 11:22:31 +0200 Subject: igc: Remove unneeded code Remove the 'igc_get_link_up_info_base method' from igc_base.c file. Use the 'igc_get_speed_and_duplex_copper' method directly and reduce the code redundancy. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_base.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c index 19ff987922d2..a31ec1682090 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.c +++ b/drivers/net/ethernet/intel/igc/igc_base.c @@ -333,26 +333,6 @@ static void igc_release_phy_base(struct igc_hw *hw) hw->mac.ops.release_swfw_sync(hw, mask); } -/** - * igc_get_link_up_info_base - Get link speed/duplex info - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * This is a wrapper function, if using the serial gigabit media independent - * interface, use PCS to retrieve the link speed and duplex information. - * Otherwise, use the generic function to get the link speed and duplex info. - */ -static s32 igc_get_link_up_info_base(struct igc_hw *hw, u16 *speed, - u16 *duplex) -{ - s32 ret_val; - - ret_val = igc_get_speed_and_duplex_copper(hw, speed, duplex); - - return ret_val; -} - /** * igc_init_hw_base - Initialize hardware * @hw: pointer to the HW structure @@ -499,7 +479,7 @@ static struct igc_mac_operations igc_mac_ops_base = { .check_for_link = igc_check_for_copper_link, .rar_set = igc_rar_set, .read_mac_addr = igc_read_mac_addr_base, - .get_speed_and_duplex = igc_get_link_up_info_base, + .get_speed_and_duplex = igc_get_speed_and_duplex_copper, }; static const struct igc_phy_operations igc_phy_ops_base = { -- cgit v1.2.3 From 0f9e980bf5ee1a97e2e401c846b2af989eb21c61 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Mon, 14 Jan 2019 16:29:30 +0300 Subject: e1000e: fix cyclic resets at link up with active tx I'm seeing series of e1000e resets (sometimes endless) at system boot if something generates tx traffic at this time. In my case this is netconsole who sends message "e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames" from e1000e itself. As result e1000_watchdog_task sees used tx buffer while carrier is off and start this reset cycle again. [ 17.794359] e1000e: eth1 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None [ 17.794714] IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready [ 22.936455] e1000e 0000:02:00.0 eth1: changing MTU from 1500 to 9000 [ 23.033336] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 26.102364] e1000e: eth1 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None [ 27.174495] 8021q: 802.1Q VLAN Support v1.8 [ 27.174513] 8021q: adding VLAN 0 to HW filter on device eth1 [ 30.671724] cgroup: cgroup: disabling cgroup2 socket matching due to net_prio or net_cls activation [ 30.898564] netpoll: netconsole: local port 6666 [ 30.898566] netpoll: netconsole: local IPv6 address 2a02:6b8:0:80b:beae:c5ff:fe28:23f8 [ 30.898567] netpoll: netconsole: interface 'eth1' [ 30.898568] netpoll: netconsole: remote port 6666 [ 30.898568] netpoll: netconsole: remote IPv6 address 2a02:6b8:b000:605c:e61d:2dff:fe03:3790 [ 30.898569] netpoll: netconsole: remote ethernet address b0:a8:6e:f4:ff:c0 [ 30.917747] console [netcon0] enabled [ 30.917749] netconsole: network logging started [ 31.453353] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 34.185730] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 34.321840] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 34.465822] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 34.597423] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 34.745417] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 34.877356] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 35.005441] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 35.157376] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 35.289362] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 35.417441] e1000e 0000:02:00.0: Some CPU C-states have been disabled in order to enable jumbo frames [ 37.790342] e1000e: eth1 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None This patch flushes tx buffers only once when carrier is off rather than at each watchdog iteration. Signed-off-by: Konstantin Khlebnikov Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/netdev.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index e19e53d97ac5..736fa51878f8 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5309,8 +5309,13 @@ static void e1000_watchdog_task(struct work_struct *work) /* 8000ES2LAN requires a Rx packet buffer work-around * on link down event; reset the controller to flush * the Rx packet buffer. + * + * If the link is lost the controller stops DMA, but + * if there is queued Tx work it cannot be done. So + * reset the controller to flush the Tx packet buffers. */ - if (adapter->flags & FLAG_RX_NEEDS_RESTART) + if ((adapter->flags & FLAG_RX_NEEDS_RESTART) || + e1000_desc_unused(tx_ring) + 1 < tx_ring->count) adapter->flags |= FLAG_RESTART_NOW; else pm_schedule_suspend(netdev->dev.parent, @@ -5333,14 +5338,6 @@ link_up: adapter->gotc_old = adapter->stats.gotc; spin_unlock(&adapter->stats64_lock); - /* If the link is lost the controller stops DMA, but - * if there is queued Tx work it cannot be done. So - * reset the controller to flush the Tx packet buffers. - */ - if (!netif_carrier_ok(netdev) && - (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) - adapter->flags |= FLAG_RESTART_NOW; - /* If reset is necessary, do it outside of interrupt context. */ if (adapter->flags & FLAG_RESTART_NOW) { schedule_work(&adapter->reset_task); -- cgit v1.2.3 From 109f599663b9d24f0045b1f4f576896c136942ec Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Tue, 15 Jan 2019 15:21:09 +0200 Subject: igc: Remove the 'igc_read_mac_addr_base' method Remove the redundant 'igc_read_mac_addr_base' method and use the 'igc_read_mac_addr' method directly instead. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_base.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c index a31ec1682090..51a667c16dea 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.c +++ b/drivers/net/ethernet/intel/igc/igc_base.c @@ -371,19 +371,6 @@ static s32 igc_init_hw_base(struct igc_hw *hw) return ret_val; } -/** - * igc_read_mac_addr_base - Read device MAC address - * @hw: pointer to the HW structure - */ -static s32 igc_read_mac_addr_base(struct igc_hw *hw) -{ - s32 ret_val = 0; - - ret_val = igc_read_mac_addr(hw); - - return ret_val; -} - /** * igc_power_down_phy_copper_base - Remove link during PHY power down * @hw: pointer to the HW structure @@ -478,7 +465,7 @@ static struct igc_mac_operations igc_mac_ops_base = { .init_hw = igc_init_hw_base, .check_for_link = igc_check_for_copper_link, .rar_set = igc_rar_set, - .read_mac_addr = igc_read_mac_addr_base, + .read_mac_addr = igc_read_mac_addr, .get_speed_and_duplex = igc_get_speed_and_duplex_copper, }; -- cgit v1.2.3 From 200a1a1a7e91eee978c76238f6ef526e3071a81c Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Tue, 15 Jan 2019 15:21:18 +0200 Subject: igc: Remove the 'igc_get_phy_id_base' method Remove the redundant 'igc_get_phy_id_base' method and use the 'igc_get_phy_id' method directly instead. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/igc_base.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c index 51a667c16dea..fe9a9666c70f 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.c +++ b/drivers/net/ethernet/intel/igc/igc_base.c @@ -107,22 +107,6 @@ static s32 igc_reset_hw_base(struct igc_hw *hw) return ret_val; } -/** - * igc_get_phy_id_base - Retrieve PHY addr and id - * @hw: pointer to the HW structure - * - * Retrieves the PHY address and ID for both PHY's which do and do not use - * sgmi interface. - */ -static s32 igc_get_phy_id_base(struct igc_hw *hw) -{ - s32 ret_val = 0; - - ret_val = igc_get_phy_id(hw); - - return ret_val; -} - /** * igc_init_nvm_params_base - Init NVM func ptrs. * @hw: pointer to the HW structure @@ -245,7 +229,7 @@ static s32 igc_init_phy_params_base(struct igc_hw *hw) goto out; } - ret_val = igc_get_phy_id_base(hw); + ret_val = igc_get_phy_id(hw); if (ret_val) return ret_val; -- cgit v1.2.3 From a865d22d593ff1310665d582e08ec78b3632cca8 Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Wed, 23 Jan 2019 14:56:30 -0800 Subject: igb: Bump version number With recent changes, need to bump the driver version to reflect the changes. Signed-off-by: Todd Fujinaka Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index dfa357b1a9d6..d35cc9697e2d 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -39,7 +39,7 @@ #include "igb.h" #define MAJ 5 -#define MIN 4 +#define MIN 6 #define BUILD 0 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \ __stringify(BUILD) "-k" -- cgit v1.2.3 From 8c5ad0dae93c9931dc32b9f4a98e73922c6ab2e0 Mon Sep 17 00:00:00 2001 From: Sasha Neftin Date: Wed, 30 Jan 2019 19:13:14 +0200 Subject: igc: Add ethtool support This patch adds basic ethtool support to the device to allow for configuration. Signed-off-by: Sasha Neftin Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igc/Makefile | 3 +- drivers/net/ethernet/intel/igc/igc.h | 34 +- drivers/net/ethernet/intel/igc/igc_base.c | 1 + drivers/net/ethernet/intel/igc/igc_defines.h | 4 + drivers/net/ethernet/intel/igc/igc_ethtool.c | 1032 ++++++++++++++++++++++++++ drivers/net/ethernet/intel/igc/igc_hw.h | 1 + drivers/net/ethernet/intel/igc/igc_main.c | 109 ++- drivers/net/ethernet/intel/igc/igc_regs.h | 3 + 8 files changed, 1169 insertions(+), 18 deletions(-) create mode 100644 drivers/net/ethernet/intel/igc/igc_ethtool.c (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igc/Makefile b/drivers/net/ethernet/intel/igc/Makefile index 4387f6ba8e67..88c6f88baac5 100644 --- a/drivers/net/ethernet/intel/igc/Makefile +++ b/drivers/net/ethernet/intel/igc/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_IGC) += igc.o -igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o +igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \ +igc_ethtool.o diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index b1039dd3dd13..80faccc34cda 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -13,19 +13,43 @@ #include "igc_hw.h" -/* main */ +/* forward declaration */ +void igc_set_ethtool_ops(struct net_device *); + +struct igc_adapter; +struct igc_ring; + +void igc_up(struct igc_adapter *adapter); +void igc_down(struct igc_adapter *adapter); +int igc_setup_tx_resources(struct igc_ring *ring); +int igc_setup_rx_resources(struct igc_ring *ring); +void igc_free_tx_resources(struct igc_ring *ring); +void igc_free_rx_resources(struct igc_ring *ring); +unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter); +void igc_set_flag_queue_pairs(struct igc_adapter *adapter, + const u32 max_rss_queues); +int igc_reinit_queues(struct igc_adapter *adapter); +bool igc_has_link(struct igc_adapter *adapter); +void igc_reset(struct igc_adapter *adapter); +int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx); + extern char igc_driver_name[]; extern char igc_driver_version[]; +#define IGC_REGS_LEN 740 +#define IGC_RETA_SIZE 128 + /* Interrupt defines */ #define IGC_START_ITR 648 /* ~6000 ints/sec */ #define IGC_FLAG_HAS_MSI BIT(0) -#define IGC_FLAG_QUEUE_PAIRS BIT(4) +#define IGC_FLAG_QUEUE_PAIRS BIT(3) +#define IGC_FLAG_DMAC BIT(4) #define IGC_FLAG_NEED_LINK_UPDATE BIT(9) #define IGC_FLAG_MEDIA_RESET BIT(10) #define IGC_FLAG_MAS_ENABLE BIT(12) #define IGC_FLAG_HAS_MSIX BIT(13) #define IGC_FLAG_VLAN_PROMISC BIT(15) +#define IGC_FLAG_RX_LEGACY BIT(16) #define IGC_START_ITR 648 /* ~6000 ints/sec */ #define IGC_4K_ITR 980 @@ -60,6 +84,7 @@ extern char igc_driver_version[]; #define IGC_RXBUFFER_2048 2048 #define IGC_RXBUFFER_3072 3072 +#define AUTO_ALL_MODES 0 #define IGC_RX_HDR_LEN IGC_RXBUFFER_256 /* RX and TX descriptor control thresholds. @@ -340,6 +365,8 @@ struct igc_adapter { struct igc_mac_addr *mac_table; + u8 rss_indir_tbl[IGC_RETA_SIZE]; + unsigned long link_check_timeout; struct igc_info ei; }; @@ -418,6 +445,9 @@ static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data) return 0; } +/* forward declaration */ +void igc_reinit_locked(struct igc_adapter *); + #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring)) #define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS) diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c index fe9a9666c70f..51a8b8769c67 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.c +++ b/drivers/net/ethernet/intel/igc/igc_base.c @@ -131,6 +131,7 @@ static s32 igc_init_nvm_params_base(struct igc_hw *hw) if (size > 15) size = 15; + nvm->type = igc_nvm_eeprom_spi; nvm->word_size = BIT(size); nvm->opcode_bits = 8; nvm->delay_usec = 1; diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 8740754ea1fd..7d1bdcd1225a 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -4,6 +4,10 @@ #ifndef _IGC_DEFINES_H_ #define _IGC_DEFINES_H_ +/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ +#define REQ_TX_DESCRIPTOR_MULTIPLE 8 +#define REQ_RX_DESCRIPTOR_MULTIPLE 8 + #define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ /* PCI Bus Info */ diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c new file mode 100644 index 000000000000..eff37a6c0afa --- /dev/null +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -0,0 +1,1032 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018 Intel Corporation */ + +/* ethtool support for igc */ +#include + +#include "igc.h" + +static const char igc_priv_flags_strings[][ETH_GSTRING_LEN] = { +#define IGC_PRIV_FLAGS_LEGACY_RX BIT(0) + "legacy-rx", +}; + +#define IGC_PRIV_FLAGS_STR_LEN ARRAY_SIZE(igc_priv_flags_strings) + +static void igc_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + strlcpy(drvinfo->driver, igc_driver_name, sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, igc_driver_version, sizeof(drvinfo->version)); + + /* add fw_version here */ + strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), + sizeof(drvinfo->bus_info)); + + drvinfo->n_priv_flags = IGC_PRIV_FLAGS_STR_LEN; +} + +static int igc_get_regs_len(struct net_device *netdev) +{ + return IGC_REGS_LEN * sizeof(u32); +} + +static void igc_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + u32 *regs_buff = p; + u8 i; + + memset(p, 0, IGC_REGS_LEN * sizeof(u32)); + + regs->version = (1u << 24) | (hw->revision_id << 16) | hw->device_id; + + /* General Registers */ + regs_buff[0] = rd32(IGC_CTRL); + regs_buff[1] = rd32(IGC_STATUS); + regs_buff[2] = rd32(IGC_CTRL_EXT); + regs_buff[3] = rd32(IGC_MDIC); + regs_buff[4] = rd32(IGC_CONNSW); + + /* NVM Register */ + regs_buff[5] = rd32(IGC_EECD); + + /* Interrupt */ + /* Reading EICS for EICR because they read the + * same but EICS does not clear on read + */ + regs_buff[6] = rd32(IGC_EICS); + regs_buff[7] = rd32(IGC_EICS); + regs_buff[8] = rd32(IGC_EIMS); + regs_buff[9] = rd32(IGC_EIMC); + regs_buff[10] = rd32(IGC_EIAC); + regs_buff[11] = rd32(IGC_EIAM); + /* Reading ICS for ICR because they read the + * same but ICS does not clear on read + */ + regs_buff[12] = rd32(IGC_ICS); + regs_buff[13] = rd32(IGC_ICS); + regs_buff[14] = rd32(IGC_IMS); + regs_buff[15] = rd32(IGC_IMC); + regs_buff[16] = rd32(IGC_IAC); + regs_buff[17] = rd32(IGC_IAM); + + /* Flow Control */ + regs_buff[18] = rd32(IGC_FCAL); + regs_buff[19] = rd32(IGC_FCAH); + regs_buff[20] = rd32(IGC_FCTTV); + regs_buff[21] = rd32(IGC_FCRTL); + regs_buff[22] = rd32(IGC_FCRTH); + regs_buff[23] = rd32(IGC_FCRTV); + + /* Receive */ + regs_buff[24] = rd32(IGC_RCTL); + regs_buff[25] = rd32(IGC_RXCSUM); + regs_buff[26] = rd32(IGC_RLPML); + regs_buff[27] = rd32(IGC_RFCTL); + + /* Transmit */ + regs_buff[28] = rd32(IGC_TCTL); + regs_buff[29] = rd32(IGC_TIPG); + + /* Wake Up */ + + /* MAC */ + + /* Statistics */ + regs_buff[30] = adapter->stats.crcerrs; + regs_buff[31] = adapter->stats.algnerrc; + regs_buff[32] = adapter->stats.symerrs; + regs_buff[33] = adapter->stats.rxerrc; + regs_buff[34] = adapter->stats.mpc; + regs_buff[35] = adapter->stats.scc; + regs_buff[36] = adapter->stats.ecol; + regs_buff[37] = adapter->stats.mcc; + regs_buff[38] = adapter->stats.latecol; + regs_buff[39] = adapter->stats.colc; + regs_buff[40] = adapter->stats.dc; + regs_buff[41] = adapter->stats.tncrs; + regs_buff[42] = adapter->stats.sec; + regs_buff[43] = adapter->stats.htdpmc; + regs_buff[44] = adapter->stats.rlec; + regs_buff[45] = adapter->stats.xonrxc; + regs_buff[46] = adapter->stats.xontxc; + regs_buff[47] = adapter->stats.xoffrxc; + regs_buff[48] = adapter->stats.xofftxc; + regs_buff[49] = adapter->stats.fcruc; + regs_buff[50] = adapter->stats.prc64; + regs_buff[51] = adapter->stats.prc127; + regs_buff[52] = adapter->stats.prc255; + regs_buff[53] = adapter->stats.prc511; + regs_buff[54] = adapter->stats.prc1023; + regs_buff[55] = adapter->stats.prc1522; + regs_buff[56] = adapter->stats.gprc; + regs_buff[57] = adapter->stats.bprc; + regs_buff[58] = adapter->stats.mprc; + regs_buff[59] = adapter->stats.gptc; + regs_buff[60] = adapter->stats.gorc; + regs_buff[61] = adapter->stats.gotc; + regs_buff[62] = adapter->stats.rnbc; + regs_buff[63] = adapter->stats.ruc; + regs_buff[64] = adapter->stats.rfc; + regs_buff[65] = adapter->stats.roc; + regs_buff[66] = adapter->stats.rjc; + regs_buff[67] = adapter->stats.mgprc; + regs_buff[68] = adapter->stats.mgpdc; + regs_buff[69] = adapter->stats.mgptc; + regs_buff[70] = adapter->stats.tor; + regs_buff[71] = adapter->stats.tot; + regs_buff[72] = adapter->stats.tpr; + regs_buff[73] = adapter->stats.tpt; + regs_buff[74] = adapter->stats.ptc64; + regs_buff[75] = adapter->stats.ptc127; + regs_buff[76] = adapter->stats.ptc255; + regs_buff[77] = adapter->stats.ptc511; + regs_buff[78] = adapter->stats.ptc1023; + regs_buff[79] = adapter->stats.ptc1522; + regs_buff[80] = adapter->stats.mptc; + regs_buff[81] = adapter->stats.bptc; + regs_buff[82] = adapter->stats.tsctc; + regs_buff[83] = adapter->stats.iac; + regs_buff[84] = adapter->stats.rpthc; + regs_buff[85] = adapter->stats.hgptc; + regs_buff[86] = adapter->stats.hgorc; + regs_buff[87] = adapter->stats.hgotc; + regs_buff[88] = adapter->stats.lenerrs; + regs_buff[89] = adapter->stats.scvpc; + regs_buff[90] = adapter->stats.hrmpc; + + for (i = 0; i < 4; i++) + regs_buff[91 + i] = rd32(IGC_SRRCTL(i)); + for (i = 0; i < 4; i++) + regs_buff[95 + i] = rd32(IGC_PSRTYPE(i)); + for (i = 0; i < 4; i++) + regs_buff[99 + i] = rd32(IGC_RDBAL(i)); + for (i = 0; i < 4; i++) + regs_buff[103 + i] = rd32(IGC_RDBAH(i)); + for (i = 0; i < 4; i++) + regs_buff[107 + i] = rd32(IGC_RDLEN(i)); + for (i = 0; i < 4; i++) + regs_buff[111 + i] = rd32(IGC_RDH(i)); + for (i = 0; i < 4; i++) + regs_buff[115 + i] = rd32(IGC_RDT(i)); + for (i = 0; i < 4; i++) + regs_buff[119 + i] = rd32(IGC_RXDCTL(i)); + + for (i = 0; i < 10; i++) + regs_buff[123 + i] = rd32(IGC_EITR(i)); + for (i = 0; i < 16; i++) + regs_buff[139 + i] = rd32(IGC_RAL(i)); + for (i = 0; i < 16; i++) + regs_buff[145 + i] = rd32(IGC_RAH(i)); + + for (i = 0; i < 4; i++) + regs_buff[149 + i] = rd32(IGC_TDBAL(i)); + for (i = 0; i < 4; i++) + regs_buff[152 + i] = rd32(IGC_TDBAH(i)); + for (i = 0; i < 4; i++) + regs_buff[156 + i] = rd32(IGC_TDLEN(i)); + for (i = 0; i < 4; i++) + regs_buff[160 + i] = rd32(IGC_TDH(i)); + for (i = 0; i < 4; i++) + regs_buff[164 + i] = rd32(IGC_TDT(i)); + for (i = 0; i < 4; i++) + regs_buff[168 + i] = rd32(IGC_TXDCTL(i)); +} + +static u32 igc_get_msglevel(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + return adapter->msg_enable; +} + +static void igc_set_msglevel(struct net_device *netdev, u32 data) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + adapter->msg_enable = data; +} + +static int igc_nway_reset(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + if (netif_running(netdev)) + igc_reinit_locked(adapter); + return 0; +} + +static u32 igc_get_link(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_mac_info *mac = &adapter->hw.mac; + + /* If the link is not reported up to netdev, interrupts are disabled, + * and so the physical link state may have changed since we last + * looked. Set get_link_status to make sure that the true link + * state is interrogated, rather than pulling a cached and possibly + * stale link state from the driver. + */ + if (!netif_carrier_ok(netdev)) + mac->get_link_status = 1; + + return igc_has_link(adapter); +} + +static int igc_get_eeprom_len(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + return adapter->hw.nvm.word_size * 2; +} + +static int igc_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + int first_word, last_word; + u16 *eeprom_buff; + int ret_val = 0; + u16 i; + + if (eeprom->len == 0) + return -EINVAL; + + eeprom->magic = hw->vendor_id | (hw->device_id << 16); + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + + eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16), + GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + if (hw->nvm.type == igc_nvm_eeprom_spi) { + ret_val = hw->nvm.ops.read(hw, first_word, + last_word - first_word + 1, + eeprom_buff); + } else { + for (i = 0; i < last_word - first_word + 1; i++) { + ret_val = hw->nvm.ops.read(hw, first_word + i, 1, + &eeprom_buff[i]); + if (ret_val) + break; + } + } + + /* Device's eeprom is always little-endian, word addressable */ + for (i = 0; i < last_word - first_word + 1; i++) + le16_to_cpus(&eeprom_buff[i]); + + memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), + eeprom->len); + kfree(eeprom_buff); + + return ret_val; +} + +static int igc_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + int max_len, first_word, last_word, ret_val = 0; + u16 *eeprom_buff; + void *ptr; + u16 i; + + if (eeprom->len == 0) + return -EOPNOTSUPP; + + if (hw->mac.type >= igc_i225 && + !igc_get_flash_presence_i225(hw)) { + return -EOPNOTSUPP; + } + + if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) + return -EFAULT; + + max_len = hw->nvm.word_size * 2; + + first_word = eeprom->offset >> 1; + last_word = (eeprom->offset + eeprom->len - 1) >> 1; + eeprom_buff = kmalloc(max_len, GFP_KERNEL); + if (!eeprom_buff) + return -ENOMEM; + + ptr = (void *)eeprom_buff; + + if (eeprom->offset & 1) { + /* need read/modify/write of first changed EEPROM word + * only the second byte of the word is being modified + */ + ret_val = hw->nvm.ops.read(hw, first_word, 1, + &eeprom_buff[0]); + ptr++; + } + if (((eeprom->offset + eeprom->len) & 1) && ret_val == 0) { + /* need read/modify/write of last changed EEPROM word + * only the first byte of the word is being modified + */ + ret_val = hw->nvm.ops.read(hw, last_word, 1, + &eeprom_buff[last_word - first_word]); + } + + /* Device's eeprom is always little-endian, word addressable */ + for (i = 0; i < last_word - first_word + 1; i++) + le16_to_cpus(&eeprom_buff[i]); + + memcpy(ptr, bytes, eeprom->len); + + for (i = 0; i < last_word - first_word + 1; i++) + eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); + + ret_val = hw->nvm.ops.write(hw, first_word, + last_word - first_word + 1, eeprom_buff); + + /* Update the checksum if nvm write succeeded */ + if (ret_val == 0) + hw->nvm.ops.update(hw); + + /* check if need: igc_set_fw_version(adapter); */ + kfree(eeprom_buff); + return ret_val; +} + +static void igc_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + ring->rx_max_pending = IGC_MAX_RXD; + ring->tx_max_pending = IGC_MAX_TXD; + ring->rx_pending = adapter->rx_ring_count; + ring->tx_pending = adapter->tx_ring_count; +} + +static int igc_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_ring *temp_ring; + u16 new_rx_count, new_tx_count; + int i, err = 0; + + if (ring->rx_mini_pending || ring->rx_jumbo_pending) + return -EINVAL; + + new_rx_count = min_t(u32, ring->rx_pending, IGC_MAX_RXD); + new_rx_count = max_t(u16, new_rx_count, IGC_MIN_RXD); + new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); + + new_tx_count = min_t(u32, ring->tx_pending, IGC_MAX_TXD); + new_tx_count = max_t(u16, new_tx_count, IGC_MIN_TXD); + new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); + + if (new_tx_count == adapter->tx_ring_count && + new_rx_count == adapter->rx_ring_count) { + /* nothing to do */ + return 0; + } + + while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + + if (!netif_running(adapter->netdev)) { + for (i = 0; i < adapter->num_tx_queues; i++) + adapter->tx_ring[i]->count = new_tx_count; + for (i = 0; i < adapter->num_rx_queues; i++) + adapter->rx_ring[i]->count = new_rx_count; + adapter->tx_ring_count = new_tx_count; + adapter->rx_ring_count = new_rx_count; + goto clear_reset; + } + + if (adapter->num_tx_queues > adapter->num_rx_queues) + temp_ring = vmalloc(array_size(sizeof(struct igc_ring), + adapter->num_tx_queues)); + else + temp_ring = vmalloc(array_size(sizeof(struct igc_ring), + adapter->num_rx_queues)); + + if (!temp_ring) { + err = -ENOMEM; + goto clear_reset; + } + + igc_down(adapter); + + /* We can't just free everything and then setup again, + * because the ISRs in MSI-X mode get passed pointers + * to the Tx and Rx ring structs. + */ + if (new_tx_count != adapter->tx_ring_count) { + for (i = 0; i < adapter->num_tx_queues; i++) { + memcpy(&temp_ring[i], adapter->tx_ring[i], + sizeof(struct igc_ring)); + + temp_ring[i].count = new_tx_count; + err = igc_setup_tx_resources(&temp_ring[i]); + if (err) { + while (i) { + i--; + igc_free_tx_resources(&temp_ring[i]); + } + goto err_setup; + } + } + + for (i = 0; i < adapter->num_tx_queues; i++) { + igc_free_tx_resources(adapter->tx_ring[i]); + + memcpy(adapter->tx_ring[i], &temp_ring[i], + sizeof(struct igc_ring)); + } + + adapter->tx_ring_count = new_tx_count; + } + + if (new_rx_count != adapter->rx_ring_count) { + for (i = 0; i < adapter->num_rx_queues; i++) { + memcpy(&temp_ring[i], adapter->rx_ring[i], + sizeof(struct igc_ring)); + + temp_ring[i].count = new_rx_count; + err = igc_setup_rx_resources(&temp_ring[i]); + if (err) { + while (i) { + i--; + igc_free_rx_resources(&temp_ring[i]); + } + goto err_setup; + } + } + + for (i = 0; i < adapter->num_rx_queues; i++) { + igc_free_rx_resources(adapter->rx_ring[i]); + + memcpy(adapter->rx_ring[i], &temp_ring[i], + sizeof(struct igc_ring)); + } + + adapter->rx_ring_count = new_rx_count; + } +err_setup: + igc_up(adapter); + vfree(temp_ring); +clear_reset: + clear_bit(__IGC_RESETTING, &adapter->state); + return err; +} + +static void igc_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + + pause->autoneg = + (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + + if (hw->fc.current_mode == igc_fc_rx_pause) { + pause->rx_pause = 1; + } else if (hw->fc.current_mode == igc_fc_tx_pause) { + pause->tx_pause = 1; + } else if (hw->fc.current_mode == igc_fc_full) { + pause->rx_pause = 1; + pause->tx_pause = 1; + } +} + +static int igc_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + int retval = 0; + + adapter->fc_autoneg = pause->autoneg; + + while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + + if (adapter->fc_autoneg == AUTONEG_ENABLE) { + hw->fc.requested_mode = igc_fc_default; + if (netif_running(adapter->netdev)) { + igc_down(adapter); + igc_up(adapter); + } else { + igc_reset(adapter); + } + } else { + if (pause->rx_pause && pause->tx_pause) + hw->fc.requested_mode = igc_fc_full; + else if (pause->rx_pause && !pause->tx_pause) + hw->fc.requested_mode = igc_fc_rx_pause; + else if (!pause->rx_pause && pause->tx_pause) + hw->fc.requested_mode = igc_fc_tx_pause; + else if (!pause->rx_pause && !pause->tx_pause) + hw->fc.requested_mode = igc_fc_none; + + hw->fc.current_mode = hw->fc.requested_mode; + + retval = ((hw->phy.media_type == igc_media_type_copper) ? + igc_force_mac_fc(hw) : igc_setup_link(hw)); + } + + clear_bit(__IGC_RESETTING, &adapter->state); + return retval; +} + +static int igc_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + if (adapter->rx_itr_setting <= 3) + ec->rx_coalesce_usecs = adapter->rx_itr_setting; + else + ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2; + + if (!(adapter->flags & IGC_FLAG_QUEUE_PAIRS)) { + if (adapter->tx_itr_setting <= 3) + ec->tx_coalesce_usecs = adapter->tx_itr_setting; + else + ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2; + } + + return 0; +} + +static int igc_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + int i; + + if (ec->rx_max_coalesced_frames || + ec->rx_coalesce_usecs_irq || + ec->rx_max_coalesced_frames_irq || + ec->tx_max_coalesced_frames || + ec->tx_coalesce_usecs_irq || + ec->stats_block_coalesce_usecs || + ec->use_adaptive_rx_coalesce || + ec->use_adaptive_tx_coalesce || + ec->pkt_rate_low || + ec->rx_coalesce_usecs_low || + ec->rx_max_coalesced_frames_low || + ec->tx_coalesce_usecs_low || + ec->tx_max_coalesced_frames_low || + ec->pkt_rate_high || + ec->rx_coalesce_usecs_high || + ec->rx_max_coalesced_frames_high || + ec->tx_coalesce_usecs_high || + ec->tx_max_coalesced_frames_high || + ec->rate_sample_interval) + return -ENOTSUPP; + + if (ec->rx_coalesce_usecs > IGC_MAX_ITR_USECS || + (ec->rx_coalesce_usecs > 3 && + ec->rx_coalesce_usecs < IGC_MIN_ITR_USECS) || + ec->rx_coalesce_usecs == 2) + return -EINVAL; + + if (ec->tx_coalesce_usecs > IGC_MAX_ITR_USECS || + (ec->tx_coalesce_usecs > 3 && + ec->tx_coalesce_usecs < IGC_MIN_ITR_USECS) || + ec->tx_coalesce_usecs == 2) + return -EINVAL; + + if ((adapter->flags & IGC_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs) + return -EINVAL; + + /* If ITR is disabled, disable DMAC */ + if (ec->rx_coalesce_usecs == 0) { + if (adapter->flags & IGC_FLAG_DMAC) + adapter->flags &= ~IGC_FLAG_DMAC; + } + + /* convert to rate of irq's per second */ + if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) + adapter->rx_itr_setting = ec->rx_coalesce_usecs; + else + adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2; + + /* convert to rate of irq's per second */ + if (adapter->flags & IGC_FLAG_QUEUE_PAIRS) + adapter->tx_itr_setting = adapter->rx_itr_setting; + else if (ec->tx_coalesce_usecs && ec->tx_coalesce_usecs <= 3) + adapter->tx_itr_setting = ec->tx_coalesce_usecs; + else + adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2; + + for (i = 0; i < adapter->num_q_vectors; i++) { + struct igc_q_vector *q_vector = adapter->q_vector[i]; + + q_vector->tx.work_limit = adapter->tx_work_limit; + if (q_vector->rx.ring) + q_vector->itr_val = adapter->rx_itr_setting; + else + q_vector->itr_val = adapter->tx_itr_setting; + if (q_vector->itr_val && q_vector->itr_val <= 3) + q_vector->itr_val = IGC_START_ITR; + q_vector->set_itr = 1; + } + + return 0; +} + +void igc_write_rss_indir_tbl(struct igc_adapter *adapter) +{ + struct igc_hw *hw = &adapter->hw; + u32 reg = IGC_RETA(0); + u32 shift = 0; + int i = 0; + + while (i < IGC_RETA_SIZE) { + u32 val = 0; + int j; + + for (j = 3; j >= 0; j--) { + val <<= 8; + val |= adapter->rss_indir_tbl[i + j]; + } + + wr32(reg, val << shift); + reg += 4; + i += 4; + } +} + +static u32 igc_get_rxfh_indir_size(struct net_device *netdev) +{ + return IGC_RETA_SIZE; +} + +static int igc_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + int i; + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + if (!indir) + return 0; + for (i = 0; i < IGC_RETA_SIZE; i++) + indir[i] = adapter->rss_indir_tbl[i]; + + return 0; +} + +static int igc_set_rxfh(struct net_device *netdev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + u32 num_queues; + int i; + + /* We do not allow change in unsupported parameters */ + if (key || + (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)) + return -EOPNOTSUPP; + if (!indir) + return 0; + + num_queues = adapter->rss_queues; + + /* Verify user input. */ + for (i = 0; i < IGC_RETA_SIZE; i++) + if (indir[i] >= num_queues) + return -EINVAL; + + for (i = 0; i < IGC_RETA_SIZE; i++) + adapter->rss_indir_tbl[i] = indir[i]; + + igc_write_rss_indir_tbl(adapter); + + return 0; +} + +static unsigned int igc_max_channels(struct igc_adapter *adapter) +{ + return igc_get_max_rss_queues(adapter); +} + +static void igc_get_channels(struct net_device *netdev, + struct ethtool_channels *ch) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + /* Report maximum channels */ + ch->max_combined = igc_max_channels(adapter); + + /* Report info for other vector */ + if (adapter->flags & IGC_FLAG_HAS_MSIX) { + ch->max_other = NON_Q_VECTORS; + ch->other_count = NON_Q_VECTORS; + } + + ch->combined_count = adapter->rss_queues; +} + +static int igc_set_channels(struct net_device *netdev, + struct ethtool_channels *ch) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + unsigned int count = ch->combined_count; + unsigned int max_combined = 0; + + /* Verify they are not requesting separate vectors */ + if (!count || ch->rx_count || ch->tx_count) + return -EINVAL; + + /* Verify other_count is valid and has not been changed */ + if (ch->other_count != NON_Q_VECTORS) + return -EINVAL; + + /* Verify the number of channels doesn't exceed hw limits */ + max_combined = igc_max_channels(adapter); + if (count > max_combined) + return -EINVAL; + + if (count != adapter->rss_queues) { + adapter->rss_queues = count; + igc_set_flag_queue_pairs(adapter, max_combined); + + /* Hardware has to reinitialize queues and interrupts to + * match the new configuration. + */ + return igc_reinit_queues(adapter); + } + + return 0; +} + +static u32 igc_get_priv_flags(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + u32 priv_flags = 0; + + if (adapter->flags & IGC_FLAG_RX_LEGACY) + priv_flags |= IGC_PRIV_FLAGS_LEGACY_RX; + + return priv_flags; +} + +static int igc_set_priv_flags(struct net_device *netdev, u32 priv_flags) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + unsigned int flags = adapter->flags; + + flags &= ~IGC_FLAG_RX_LEGACY; + if (priv_flags & IGC_PRIV_FLAGS_LEGACY_RX) + flags |= IGC_FLAG_RX_LEGACY; + + if (flags != adapter->flags) { + adapter->flags = flags; + + /* reset interface to repopulate queues */ + if (netif_running(netdev)) + igc_reinit_locked(adapter); + } + + return 0; +} + +static int igc_ethtool_begin(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + pm_runtime_get_sync(&adapter->pdev->dev); + return 0; +} + +static void igc_ethtool_complete(struct net_device *netdev) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + + pm_runtime_put(&adapter->pdev->dev); +} + +static int igc_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + u32 status; + u32 speed; + + ethtool_link_ksettings_zero_link_mode(cmd, supported); + ethtool_link_ksettings_zero_link_mode(cmd, advertising); + + /* supported link modes */ + ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, 2500baseT_Full); + + /* twisted pair */ + cmd->base.port = PORT_TP; + cmd->base.phy_address = hw->phy.addr; + + /* advertising link modes */ + ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, 2500baseT_Full); + + /* set autoneg settings */ + if (hw->mac.autoneg == 1) { + ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Autoneg); + } + + switch (hw->fc.requested_mode) { + case igc_fc_full: + ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); + break; + case igc_fc_rx_pause: + ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Asym_Pause); + break; + case igc_fc_tx_pause: + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Asym_Pause); + break; + default: + ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + Asym_Pause); + } + + status = rd32(IGC_STATUS); + + if (status & IGC_STATUS_LU) { + if (status & IGC_STATUS_SPEED_1000) { + /* For I225, STATUS will indicate 1G speed in both + * 1 Gbps and 2.5 Gbps link modes. + * An additional bit is used + * to differentiate between 1 Gbps and 2.5 Gbps. + */ + if (hw->mac.type == igc_i225 && + (status & IGC_STATUS_SPEED_2500)) { + speed = SPEED_2500; + hw_dbg("2500 Mbs, "); + } else { + speed = SPEED_1000; + hw_dbg("1000 Mbs, "); + } + } else if (status & IGC_STATUS_SPEED_100) { + speed = SPEED_100; + hw_dbg("100 Mbs, "); + } else { + speed = SPEED_10; + hw_dbg("10 Mbs, "); + } + if ((status & IGC_STATUS_FD) || + hw->phy.media_type != igc_media_type_copper) + cmd->base.duplex = DUPLEX_FULL; + else + cmd->base.duplex = DUPLEX_HALF; + } else { + speed = SPEED_UNKNOWN; + cmd->base.duplex = DUPLEX_UNKNOWN; + } + cmd->base.speed = speed; + if (hw->mac.autoneg) + cmd->base.autoneg = AUTONEG_ENABLE; + else + cmd->base.autoneg = AUTONEG_DISABLE; + + /* MDI-X => 2; MDI =>1; Invalid =>0 */ + if (hw->phy.media_type == igc_media_type_copper) + cmd->base.eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : + ETH_TP_MDI; + else + cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; + + if (hw->phy.mdix == AUTO_ALL_MODES) + cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; + else + cmd->base.eth_tp_mdix_ctrl = hw->phy.mdix; + + return 0; +} + +static int igc_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_hw *hw = &adapter->hw; + u32 advertising; + + /* When adapter in resetting mode, autoneg/speed/duplex + * cannot be changed + */ + if (igc_check_reset_block(hw)) { + dev_err(&adapter->pdev->dev, + "Cannot change link characteristics when reset is active.\n"); + return -EINVAL; + } + + /* MDI setting is only allowed when autoneg enabled because + * some hardware doesn't allow MDI setting when speed or + * duplex is forced. + */ + if (cmd->base.eth_tp_mdix_ctrl) { + if (cmd->base.eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO && + cmd->base.autoneg != AUTONEG_ENABLE) { + dev_err(&adapter->pdev->dev, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); + return -EINVAL; + } + } + + while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) + usleep_range(1000, 2000); + + ethtool_convert_link_mode_to_legacy_u32(&advertising, + cmd->link_modes.advertising); + + if (cmd->base.autoneg == AUTONEG_ENABLE) { + hw->mac.autoneg = 1; + hw->phy.autoneg_advertised = advertising; + if (adapter->fc_autoneg) + hw->fc.requested_mode = igc_fc_default; + } else { + /* calling this overrides forced MDI setting */ + dev_info(&adapter->pdev->dev, + "Force mode currently not supported\n"); + } + + /* MDI-X => 2; MDI => 1; Auto => 3 */ + if (cmd->base.eth_tp_mdix_ctrl) { + /* fix up the value for auto (3 => 0) as zero is mapped + * internally to auto + */ + if (cmd->base.eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) + hw->phy.mdix = AUTO_ALL_MODES; + else + hw->phy.mdix = cmd->base.eth_tp_mdix_ctrl; + } + + /* reset the link */ + if (netif_running(adapter->netdev)) { + igc_down(adapter); + igc_up(adapter); + } else { + igc_reset(adapter); + } + + clear_bit(__IGC_RESETTING, &adapter->state); + + return 0; +} + +static const struct ethtool_ops igc_ethtool_ops = { + .get_drvinfo = igc_get_drvinfo, + .get_regs_len = igc_get_regs_len, + .get_regs = igc_get_regs, + .get_msglevel = igc_get_msglevel, + .set_msglevel = igc_set_msglevel, + .nway_reset = igc_nway_reset, + .get_link = igc_get_link, + .get_eeprom_len = igc_get_eeprom_len, + .get_eeprom = igc_get_eeprom, + .set_eeprom = igc_set_eeprom, + .get_ringparam = igc_get_ringparam, + .set_ringparam = igc_set_ringparam, + .get_pauseparam = igc_get_pauseparam, + .set_pauseparam = igc_set_pauseparam, + .get_coalesce = igc_get_coalesce, + .set_coalesce = igc_set_coalesce, + .get_rxfh_indir_size = igc_get_rxfh_indir_size, + .get_rxfh = igc_get_rxfh, + .set_rxfh = igc_set_rxfh, + .get_channels = igc_get_channels, + .set_channels = igc_set_channels, + .get_priv_flags = igc_get_priv_flags, + .set_priv_flags = igc_set_priv_flags, + .begin = igc_ethtool_begin, + .complete = igc_ethtool_complete, + .get_link_ksettings = igc_get_link_ksettings, + .set_link_ksettings = igc_set_link_ksettings, +}; + +void igc_set_ethtool_ops(struct net_device *netdev) +{ + netdev->ethtool_ops = &igc_ethtool_ops; +} diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h index c50414f48f0d..7c88b7bd4799 100644 --- a/drivers/net/ethernet/intel/igc/igc_hw.h +++ b/drivers/net/ethernet/intel/igc/igc_hw.h @@ -55,6 +55,7 @@ enum igc_media_type { enum igc_nvm_type { igc_nvm_unknown = 0, + igc_nvm_eeprom_spi, igc_nvm_flash_hw, igc_nvm_invm, }; diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index f20183037fb2..11c75433fe22 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -12,6 +12,8 @@ #define DRV_VERSION "0.0.1-k" #define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) + static int debug = -1; MODULE_AUTHOR("Intel Corporation, "); @@ -66,7 +68,7 @@ enum latency_range { latency_invalid = 255 }; -static void igc_reset(struct igc_adapter *adapter) +void igc_reset(struct igc_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct igc_hw *hw = &adapter->hw; @@ -150,7 +152,7 @@ static void igc_get_hw_control(struct igc_adapter *adapter) * * Free all transmit software resources */ -static void igc_free_tx_resources(struct igc_ring *tx_ring) +void igc_free_tx_resources(struct igc_ring *tx_ring) { igc_clean_tx_ring(tx_ring); @@ -261,7 +263,7 @@ static void igc_clean_all_tx_rings(struct igc_adapter *adapter) * * Return 0 on success, negative on failure */ -static int igc_setup_tx_resources(struct igc_ring *tx_ring) +int igc_setup_tx_resources(struct igc_ring *tx_ring) { struct device *dev = tx_ring->dev; int size = 0; @@ -381,7 +383,7 @@ static void igc_clean_all_rx_rings(struct igc_adapter *adapter) * * Free all receive software resources */ -static void igc_free_rx_resources(struct igc_ring *rx_ring) +void igc_free_rx_resources(struct igc_ring *rx_ring) { igc_clean_rx_ring(rx_ring); @@ -418,7 +420,7 @@ static void igc_free_all_rx_resources(struct igc_adapter *adapter) * * Returns 0 on success, negative on failure */ -static int igc_setup_rx_resources(struct igc_ring *rx_ring) +int igc_setup_rx_resources(struct igc_ring *rx_ring) { struct device *dev = rx_ring->dev; int size, desc_len; @@ -1703,7 +1705,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) * igc_up - Open the interface and prepare it to handle traffic * @adapter: board private structure */ -static void igc_up(struct igc_adapter *adapter) +void igc_up(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; int i = 0; @@ -1748,7 +1750,7 @@ static void igc_nfc_filter_exit(struct igc_adapter *adapter) * igc_down - Close the interface * @adapter: board private structure */ -static void igc_down(struct igc_adapter *adapter) +void igc_down(struct igc_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct igc_hw *hw = &adapter->hw; @@ -1810,7 +1812,7 @@ static void igc_down(struct igc_adapter *adapter) igc_clean_all_rx_rings(adapter); } -static void igc_reinit_locked(struct igc_adapter *adapter) +void igc_reinit_locked(struct igc_adapter *adapter) { WARN_ON(in_interrupt()); while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) @@ -1922,7 +1924,7 @@ static void igc_configure(struct igc_adapter *adapter) /** * igc_rar_set_index - Sync RAL[index] and RAH[index] registers with MAC table - * @adapter: Pointer to adapter structure + * @adapter: address of board private structure * @index: Index of the RAR entry which need to be synced with MAC table */ static void igc_rar_set_index(struct igc_adapter *adapter, u32 index) @@ -2298,7 +2300,7 @@ static void igc_update_phy_info(struct timer_list *t) * igc_has_link - check shared code for link and determine up/down * @adapter: pointer to driver private info */ -static bool igc_has_link(struct igc_adapter *adapter) +bool igc_has_link(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; bool link_active = false; @@ -3501,6 +3503,57 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg) return value; } +int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx) +{ + struct pci_dev *pdev = adapter->pdev; + struct igc_mac_info *mac = &adapter->hw.mac; + + mac->autoneg = 0; + + /* Make sure dplx is at most 1 bit and lsb of speed is not set + * for the switch() below to work + */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + + switch (spd + dplx) { + case SPEED_10 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_10_HALF; + break; + case SPEED_10 + DUPLEX_FULL: + mac->forced_speed_duplex = ADVERTISE_10_FULL; + break; + case SPEED_100 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_100_HALF; + break; + case SPEED_100 + DUPLEX_FULL: + mac->forced_speed_duplex = ADVERTISE_100_FULL; + break; + case SPEED_1000 + DUPLEX_FULL: + mac->autoneg = 1; + adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; + break; + case SPEED_1000 + DUPLEX_HALF: /* not supported */ + goto err_inval; + case SPEED_2500 + DUPLEX_FULL: + mac->autoneg = 1; + adapter->hw.phy.autoneg_advertised = ADVERTISE_2500_FULL; + break; + case SPEED_2500 + DUPLEX_HALF: /* not supported */ + default: + goto err_inval; + } + + /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ + adapter->hw.phy.mdix = AUTO_ALL_MODES; + + return 0; + +err_inval: + dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; +} + /** * igc_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -3568,7 +3621,7 @@ static int igc_probe(struct pci_dev *pdev, hw = &adapter->hw; hw->back = adapter; adapter->port_num = hw->bus.func; - adapter->msg_enable = GENMASK(debug - 1, 0); + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); err = pci_save_state(pdev); if (err) @@ -3584,7 +3637,7 @@ static int igc_probe(struct pci_dev *pdev, hw->hw_addr = adapter->io_addr; netdev->netdev_ops = &igc_netdev_ops; - + igc_set_ethtool_ops(netdev); netdev->watchdog_timeo = 5 * HZ; netdev->mem_start = pci_resource_start(pdev, 0); @@ -3744,8 +3797,8 @@ static struct pci_driver igc_driver = { .remove = igc_remove, }; -static void igc_set_flag_queue_pairs(struct igc_adapter *adapter, - const u32 max_rss_queues) +void igc_set_flag_queue_pairs(struct igc_adapter *adapter, + const u32 max_rss_queues) { /* Determine if we need to pair queues. */ /* If rss_queues > half of max_rss_queues, pair the queues in @@ -3757,7 +3810,7 @@ static void igc_set_flag_queue_pairs(struct igc_adapter *adapter, adapter->flags &= ~IGC_FLAG_QUEUE_PAIRS; } -static unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter) +unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter) { unsigned int max_rss_queues; @@ -3836,6 +3889,32 @@ static int igc_sw_init(struct igc_adapter *adapter) return 0; } +/** + * igc_reinit_queues - return error + * @adapter: pointer to adapter structure + */ +int igc_reinit_queues(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + int err = 0; + + if (netif_running(netdev)) + igc_close(netdev); + + igc_reset_interrupt_capability(adapter); + + if (igc_init_interrupt_scheme(adapter, true)) { + dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + + if (netif_running(netdev)) + err = igc_open(netdev); + + return err; +} + /** * igc_get_hw_dev - return device * @hw: pointer to hardware structure diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h index f8c835283377..5afe7a8d3faf 100644 --- a/drivers/net/ethernet/intel/igc/igc_regs.h +++ b/drivers/net/ethernet/intel/igc/igc_regs.h @@ -80,6 +80,9 @@ /* MSI-X Table Register Descriptions */ #define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */ +/* Redirection Table - RW Array */ +#define IGC_RETA(_i) (0x05C00 + ((_i) * 4)) + /* Receive Register Descriptions */ #define IGC_RCTL 0x00100 /* Rx Control - RW */ #define IGC_SRRCTL(_n) (0x0C00C + ((_n) * 0x40)) -- cgit v1.2.3 From 1878f0dcbff0cd07f62602deb160a44d69a8f146 Mon Sep 17 00:00:00 2001 From: Nikita Yushchenko Date: Wed, 6 Feb 2019 07:36:40 +0100 Subject: net: phy: provide full set of accessor functions to MMD registers This adds full set of locked and unlocked accessor functions to read and write PHY MMD registers and/or bitfields. Set of functions exactly matches what is already available for PHY legacy registers. Signed-off-by: Nikita Yushchenko Signed-off-by: Andrew Lunn Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-core.c | 116 ++++++++++++++++++++++++++++++++++----- include/linux/phy.h | 134 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 214 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index 909b3344babf..7d6aad287f84 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -414,15 +414,15 @@ static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad, } /** - * phy_read_mmd - Convenience function for reading a register + * __phy_read_mmd - Convenience function for reading a register * from an MMD on a given PHY. * @phydev: The phy_device struct * @devad: The MMD to read from (0..31) * @regnum: The register on the MMD to read (0..65535) * - * Same rules as for phy_read(); + * Same rules as for __phy_read(); */ -int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) +int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) { int val; @@ -434,33 +434,52 @@ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) } else if (phydev->is_c45) { u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff); - val = mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr); + val = __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr); } else { struct mii_bus *bus = phydev->mdio.bus; int phy_addr = phydev->mdio.addr; - mutex_lock(&bus->mdio_lock); mmd_phy_indirect(bus, phy_addr, devad, regnum); /* Read the content of the MMD's selected register */ val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA); - mutex_unlock(&bus->mdio_lock); } return val; } +EXPORT_SYMBOL(__phy_read_mmd); + +/** + * phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * + * Same rules as for phy_read(); + */ +int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum) +{ + int ret; + + mutex_lock(&phydev->mdio.bus->mdio_lock); + ret = __phy_read_mmd(phydev, devad, regnum); + mutex_unlock(&phydev->mdio.bus->mdio_lock); + + return ret; +} EXPORT_SYMBOL(phy_read_mmd); /** - * phy_write_mmd - Convenience function for writing a register + * __phy_write_mmd - Convenience function for writing a register * on an MMD on a given PHY. * @phydev: The phy_device struct * @devad: The MMD to read from * @regnum: The register on the MMD to read * @val: value to write to @regnum * - * Same rules as for phy_write(); + * Same rules as for __phy_write(); */ -int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) +int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) { int ret; @@ -472,23 +491,43 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) } else if (phydev->is_c45) { u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff); - ret = mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, - addr, val); + ret = __mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, + addr, val); } else { struct mii_bus *bus = phydev->mdio.bus; int phy_addr = phydev->mdio.addr; - mutex_lock(&bus->mdio_lock); mmd_phy_indirect(bus, phy_addr, devad, regnum); /* Write the data into MMD's selected register */ __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val); - mutex_unlock(&bus->mdio_lock); ret = 0; } return ret; } +EXPORT_SYMBOL(__phy_write_mmd); + +/** + * phy_write_mmd - Convenience function for writing a register + * on an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @val: value to write to @regnum + * + * Same rules as for phy_write(); + */ +int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) +{ + int ret; + + mutex_lock(&phydev->mdio.bus->mdio_lock); + ret = __phy_write_mmd(phydev, devad, regnum, val); + mutex_unlock(&phydev->mdio.bus->mdio_lock); + + return ret; +} EXPORT_SYMBOL(phy_write_mmd); /** @@ -538,6 +577,57 @@ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) } EXPORT_SYMBOL_GPL(phy_modify); +/** + * __phy_modify_mmd - Convenience function for modifying a register on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * Unlocked helper function which allows a MMD register to be modified as + * new register value = (old register value & ~mask) | set + */ +int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) +{ + int ret; + + ret = __phy_read_mmd(phydev, devad, regnum); + if (ret < 0) + return ret; + + ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set); + + return ret < 0 ? ret : 0; +} +EXPORT_SYMBOL_GPL(__phy_modify_mmd); + +/** + * phy_modify_mmd - Convenience function for modifying a register on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) +{ + int ret; + + mutex_lock(&phydev->mdio.bus->mdio_lock); + ret = __phy_modify_mmd(phydev, devad, regnum, mask, set); + mutex_unlock(&phydev->mdio.bus->mdio_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_modify_mmd); + static int __phy_read_page(struct phy_device *phydev) { return phydev->drv->read_page(phydev); diff --git a/include/linux/phy.h b/include/linux/phy.h index 70f83d0d7469..237dd035858a 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -692,17 +692,6 @@ static inline bool phy_is_started(struct phy_device *phydev) void phy_resolve_aneg_linkmode(struct phy_device *phydev); -/** - * phy_read_mmd - Convenience function for reading a register - * from an MMD on a given PHY. - * @phydev: The phy_device struct - * @devad: The MMD to read from - * @regnum: The register on the MMD to read - * - * Same rules as for phy_read(); - */ -int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum); - /** * phy_read - Convenience function for reading a given PHY register * @phydev: the phy_device struct @@ -758,9 +747,60 @@ static inline int __phy_write(struct phy_device *phydev, u32 regnum, u16 val) val); } +/** + * phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * + * Same rules as for phy_read(); + */ +int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum); + +/** + * __phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * + * Same rules as for __phy_read(); + */ +int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum); + +/** + * phy_write_mmd - Convenience function for writing a register + * on an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to write to + * @regnum: The register on the MMD to read + * @val: value to write to @regnum + * + * Same rules as for phy_write(); + */ +int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); + +/** + * __phy_write_mmd - Convenience function for writing a register + * on an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to write to + * @regnum: The register on the MMD to read + * @val: value to write to @regnum + * + * Same rules as for __phy_write(); + */ +int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); + int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set); int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set); +int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set); +int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set); + /** * __phy_set_bits - Convenience function for setting bits in a PHY register * @phydev: the phy_device struct @@ -810,6 +850,66 @@ static inline int phy_clear_bits(struct phy_device *phydev, u32 regnum, u16 val) return phy_modify(phydev, regnum, val, 0); } +/** + * __phy_set_bits_mmd - Convenience function for setting bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to set + * + * The caller must have taken the MDIO bus lock. + */ +static inline int __phy_set_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + return __phy_modify_mmd(phydev, devad, regnum, 0, val); +} + +/** + * __phy_clear_bits_mmd - Convenience function for clearing bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to clear + * + * The caller must have taken the MDIO bus lock. + */ +static inline int __phy_clear_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + return __phy_modify_mmd(phydev, devad, regnum, val, 0); +} + +/** + * phy_set_bits_mmd - Convenience function for setting bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to set + */ +static inline int phy_set_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + return phy_modify_mmd(phydev, devad, regnum, 0, val); +} + +/** + * phy_clear_bits_mmd - Convenience function for clearing bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to clear + */ +static inline int phy_clear_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + return phy_modify_mmd(phydev, devad, regnum, val, 0); +} + /** * phy_interrupt_is_valid - Convenience function for testing a given PHY irq * @phydev: the phy_device struct @@ -886,18 +986,6 @@ static inline bool phy_is_pseudo_fixed_link(struct phy_device *phydev) return phydev->is_pseudo_fixed_link; } -/** - * phy_write_mmd - Convenience function for writing a register - * on an MMD on a given PHY. - * @phydev: The phy_device struct - * @devad: The MMD to read from - * @regnum: The register on the MMD to read - * @val: value to write to @regnum - * - * Same rules as for phy_write(); - */ -int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); - int phy_save_page(struct phy_device *phydev); int phy_select_page(struct phy_device *phydev, int page); int phy_restore_page(struct phy_device *phydev, int oldpage, int ret); -- cgit v1.2.3 From b52c018ddccfed4fded59546c502ddb1ea8c7ba1 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 6 Feb 2019 07:38:43 +0100 Subject: net: phy: make use of new MMD accessors Make use of the new MMD accessors. v2: - fix SoB Signed-off-by: Andrew Lunn Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/dp83867.c | 47 ++++++++++++++++---------------------------- drivers/net/phy/dp83tc811.c | 15 ++++---------- drivers/net/phy/marvell10g.c | 38 ++++++++++------------------------- drivers/net/phy/phy-c45.c | 21 ++++---------------- drivers/net/phy/phy.c | 11 +++-------- 5 files changed, 38 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 8a8d9f606b3e..fc09c5c1a4de 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -127,17 +127,13 @@ static int dp83867_config_port_mirroring(struct phy_device *phydev) { struct dp83867_private *dp83867 = (struct dp83867_private *)phydev->priv; - u16 val; - - val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4); if (dp83867->port_mirroring == DP83867_PORT_MIRROING_EN) - val |= DP83867_CFG4_PORT_MIRROR_EN; + phy_set_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, + DP83867_CFG4_PORT_MIRROR_EN); else - val &= ~DP83867_CFG4_PORT_MIRROR_EN; - - phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val); - + phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, + DP83867_CFG4_PORT_MIRROR_EN); return 0; } @@ -222,11 +218,9 @@ static int dp83867_config_init(struct phy_device *phydev) } /* RX_DV/RX_CTRL strapped in mode 1 or mode 2 workaround */ - if (dp83867->rxctrl_strap_quirk) { - val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4); - val &= ~BIT(7); - phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val); - } + if (dp83867->rxctrl_strap_quirk) + phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, + BIT(7)); if (phy_interface_is_rgmii(phydev)) { val = phy_read(phydev, MII_DP83867_PHYCTRL); @@ -275,17 +269,11 @@ static int dp83867_config_init(struct phy_device *phydev) phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIIDCTL, delay); - if (dp83867->io_impedance >= 0) { - val = phy_read_mmd(phydev, DP83867_DEVADDR, - DP83867_IO_MUX_CFG); - - val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; - val |= dp83867->io_impedance & - DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL; - - phy_write_mmd(phydev, DP83867_DEVADDR, - DP83867_IO_MUX_CFG, val); - } + if (dp83867->io_impedance >= 0) + phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG, + DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL, + dp83867->io_impedance & + DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL); } /* Enable Interrupt output INT_OE in CFG3 register */ @@ -299,12 +287,11 @@ static int dp83867_config_init(struct phy_device *phydev) dp83867_config_port_mirroring(phydev); /* Clock output selection if muxing property is set */ - if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) { - val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG); - val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK; - val |= (dp83867->clk_output_sel << DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT); - phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG, val); - } + if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) + phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG, + DP83867_IO_MUX_CFG_CLK_O_SEL_MASK, + dp83867->clk_output_sel << + DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT); return 0; } diff --git a/drivers/net/phy/dp83tc811.c b/drivers/net/phy/dp83tc811.c index da13356999e5..e9704af1d239 100644 --- a/drivers/net/phy/dp83tc811.c +++ b/drivers/net/phy/dp83tc811.c @@ -144,11 +144,8 @@ static int dp83811_set_wol(struct phy_device *phydev, phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG, value); } else { - value = phy_read_mmd(phydev, DP83811_DEVADDR, - MII_DP83811_WOL_CFG); - value &= ~DP83811_WOL_EN; - phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG, - value); + phy_clear_bits_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG, + DP83811_WOL_EN); } return 0; @@ -328,14 +325,10 @@ static int dp83811_suspend(struct phy_device *phydev) static int dp83811_resume(struct phy_device *phydev) { - int value; - genphy_resume(phydev); - value = phy_read_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG); - - phy_write_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG, value | - DP83811_WOL_CLR_INDICATION); + phy_set_bits_mmd(phydev, DP83811_DEVADDR, MII_DP83811_WOL_CFG, + DP83811_WOL_CLR_INDICATION); return 0; } diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 38cfc923a88a..5531f9cabc63 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -58,24 +58,6 @@ struct mv3310_priv { char *hwmon_name; }; -static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg, - u16 mask, u16 bits) -{ - int old, val, ret; - - old = phy_read_mmd(phydev, devad, reg); - if (old < 0) - return old; - - val = (old & ~mask) | (bits & mask); - if (val == old) - return 0; - - ret = phy_write_mmd(phydev, devad, reg, val); - - return ret < 0 ? ret : 1; -} - #ifdef CONFIG_HWMON static umode_t mv3310_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, @@ -159,8 +141,8 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable) return ret; val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE; - ret = mv3310_modify(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL, - MV_V2_TEMP_CTRL_MASK, val); + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL, + MV_V2_TEMP_CTRL_MASK, val); return ret < 0 ? ret : 0; } @@ -363,18 +345,18 @@ static int mv3310_config_aneg(struct phy_device *phydev) linkmode_and(phydev->advertising, phydev->advertising, phydev->supported); - ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_100BASE4 | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, - linkmode_adv_to_mii_adv_t(phydev->advertising)); + ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_100BASE4 | + ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, + linkmode_adv_to_mii_adv_t(phydev->advertising)); if (ret < 0) return ret; if (ret > 0) changed = true; reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); - ret = mv3310_modify(phydev, MDIO_MMD_AN, MV_AN_CTRL1000, - ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg); + ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MV_AN_CTRL1000, + ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg); if (ret < 0) return ret; if (ret > 0) @@ -387,8 +369,8 @@ static int mv3310_config_aneg(struct phy_device *phydev) else reg = 0; - ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV10G, reg); + ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV10G, reg); if (ret < 0) return ret; if (ret > 0) diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 03af927fa5ad..519866679c91 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -75,15 +75,9 @@ EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced); */ int genphy_c45_an_disable_aneg(struct phy_device *phydev) { - int val; - - val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); - if (val < 0) - return val; - - val &= ~(MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART); - return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val); + return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, + MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART); } EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg); @@ -97,15 +91,8 @@ EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg); */ int genphy_c45_restart_aneg(struct phy_device *phydev) { - int val; - - val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); - if (val < 0) - return val; - - val |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART; - - return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val); + return phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, + MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART); } EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index d12aa512b7f5..89ead29cec68 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1060,17 +1060,12 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable) if (!phy_check_valid(phydev->speed, phydev->duplex, common)) goto eee_exit_err; - if (clk_stop_enable) { + if (clk_stop_enable) /* Configure the PHY to stop receiving xMII * clock while it is signaling LPI. */ - int val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1); - if (val < 0) - return val; - - val |= MDIO_PCS_CTRL1_CLKSTOP_EN; - phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, val); - } + phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1, + MDIO_PCS_CTRL1_CLKSTOP_EN); return 0; /* EEE supported */ } -- cgit v1.2.3 From 8f2566225ae2d62d532bb1810ed74fa4bbc5bbdb Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 2 Feb 2019 12:50:43 +0100 Subject: flow_offload: add flow_rule and flow_match structures and use them This patch wraps the dissector key and mask - that flower uses to represent the matching side - around the flow_match structure. To avoid a follow up patch that would edit the same LoCs in the drivers, this patch also wraps this new flow match structure around the flow rule object. This new structure will also contain the flow actions in follow up patches. This introduces two new interfaces: bool flow_rule_match_key(rule, dissector_id) that returns true if a given matching key is set on, and: flow_rule_match_XYZ(rule, &match); To fetch the matching side XYZ into the match container structure, to retrieve the key and the mask with one single call. Signed-off-by: Pablo Neira Ayuso Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 174 ++++----- .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 194 ++++------ drivers/net/ethernet/intel/i40e/i40e_main.c | 178 ++++----- drivers/net/ethernet/intel/iavf/iavf_main.c | 195 ++++------ drivers/net/ethernet/intel/igb/igb_main.c | 64 ++-- .../net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 68 ++-- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 376 ++++++++----------- .../net/ethernet/mellanox/mlxsw/spectrum_flower.c | 202 +++++----- drivers/net/ethernet/netronome/nfp/flower/action.c | 11 +- drivers/net/ethernet/netronome/nfp/flower/match.c | 417 +++++++++++---------- .../net/ethernet/netronome/nfp/flower/offload.c | 149 +++----- drivers/net/ethernet/qlogic/qede/qede_filter.c | 85 ++--- include/net/flow_offload.h | 115 ++++++ include/net/pkt_cls.h | 11 +- net/core/Makefile | 2 +- net/core/flow_offload.c | 143 +++++++ net/sched/cls_flower.c | 47 ++- 17 files changed, 1209 insertions(+), 1222 deletions(-) create mode 100644 include/net/flow_offload.h create mode 100644 net/core/flow_offload.c (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c index c683b5e96b1d..90a2170c5138 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c @@ -177,18 +177,12 @@ static int bnxt_tc_parse_actions(struct bnxt *bp, return 0; } -#define GET_KEY(flow_cmd, key_type) \ - skb_flow_dissector_target((flow_cmd)->dissector, key_type,\ - (flow_cmd)->key) -#define GET_MASK(flow_cmd, key_type) \ - skb_flow_dissector_target((flow_cmd)->dissector, key_type,\ - (flow_cmd)->mask) - static int bnxt_tc_parse_flow(struct bnxt *bp, struct tc_cls_flower_offload *tc_flow_cmd, struct bnxt_tc_flow *flow) { - struct flow_dissector *dissector = tc_flow_cmd->dissector; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(tc_flow_cmd); + struct flow_dissector *dissector = rule->match.dissector; /* KEY_CONTROL and KEY_BASIC are needed for forming a meaningful key */ if ((dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) == 0 || @@ -198,140 +192,120 @@ static int bnxt_tc_parse_flow(struct bnxt *bp, return -EOPNOTSUPP; } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_BASIC); - struct flow_dissector_key_basic *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_BASIC); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; - flow->l2_key.ether_type = key->n_proto; - flow->l2_mask.ether_type = mask->n_proto; + flow_rule_match_basic(rule, &match); + flow->l2_key.ether_type = match.key->n_proto; + flow->l2_mask.ether_type = match.mask->n_proto; - if (key->n_proto == htons(ETH_P_IP) || - key->n_proto == htons(ETH_P_IPV6)) { - flow->l4_key.ip_proto = key->ip_proto; - flow->l4_mask.ip_proto = mask->ip_proto; + if (match.key->n_proto == htons(ETH_P_IP) || + match.key->n_proto == htons(ETH_P_IPV6)) { + flow->l4_key.ip_proto = match.key->ip_proto; + flow->l4_mask.ip_proto = match.mask->ip_proto; } } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - struct flow_dissector_key_eth_addrs *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ETH_ADDRS); - struct flow_dissector_key_eth_addrs *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_ETH_ADDRS); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; + flow_rule_match_eth_addrs(rule, &match); flow->flags |= BNXT_TC_FLOW_FLAGS_ETH_ADDRS; - ether_addr_copy(flow->l2_key.dmac, key->dst); - ether_addr_copy(flow->l2_mask.dmac, mask->dst); - ether_addr_copy(flow->l2_key.smac, key->src); - ether_addr_copy(flow->l2_mask.smac, mask->src); + ether_addr_copy(flow->l2_key.dmac, match.key->dst); + ether_addr_copy(flow->l2_mask.dmac, match.mask->dst); + ether_addr_copy(flow->l2_key.smac, match.key->src); + ether_addr_copy(flow->l2_mask.smac, match.mask->src); } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_dissector_key_vlan *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_VLAN); - struct flow_dissector_key_vlan *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_VLAN); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; + flow_rule_match_vlan(rule, &match); flow->l2_key.inner_vlan_tci = - cpu_to_be16(VLAN_TCI(key->vlan_id, key->vlan_priority)); + cpu_to_be16(VLAN_TCI(match.key->vlan_id, + match.key->vlan_priority)); flow->l2_mask.inner_vlan_tci = - cpu_to_be16((VLAN_TCI(mask->vlan_id, mask->vlan_priority))); + cpu_to_be16((VLAN_TCI(match.mask->vlan_id, + match.mask->vlan_priority))); flow->l2_key.inner_vlan_tpid = htons(ETH_P_8021Q); flow->l2_mask.inner_vlan_tpid = htons(0xffff); flow->l2_key.num_vlans = 1; } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { - struct flow_dissector_key_ipv4_addrs *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_IPV4_ADDRS); - struct flow_dissector_key_ipv4_addrs *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_IPV4_ADDRS); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { + struct flow_match_ipv4_addrs match; + flow_rule_match_ipv4_addrs(rule, &match); flow->flags |= BNXT_TC_FLOW_FLAGS_IPV4_ADDRS; - flow->l3_key.ipv4.daddr.s_addr = key->dst; - flow->l3_mask.ipv4.daddr.s_addr = mask->dst; - flow->l3_key.ipv4.saddr.s_addr = key->src; - flow->l3_mask.ipv4.saddr.s_addr = mask->src; - } else if (dissector_uses_key(dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { - struct flow_dissector_key_ipv6_addrs *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_IPV6_ADDRS); - struct flow_dissector_key_ipv6_addrs *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_IPV6_ADDRS); - + flow->l3_key.ipv4.daddr.s_addr = match.key->dst; + flow->l3_mask.ipv4.daddr.s_addr = match.mask->dst; + flow->l3_key.ipv4.saddr.s_addr = match.key->src; + flow->l3_mask.ipv4.saddr.s_addr = match.mask->src; + } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { + struct flow_match_ipv6_addrs match; + + flow_rule_match_ipv6_addrs(rule, &match); flow->flags |= BNXT_TC_FLOW_FLAGS_IPV6_ADDRS; - flow->l3_key.ipv6.daddr = key->dst; - flow->l3_mask.ipv6.daddr = mask->dst; - flow->l3_key.ipv6.saddr = key->src; - flow->l3_mask.ipv6.saddr = mask->src; + flow->l3_key.ipv6.daddr = match.key->dst; + flow->l3_mask.ipv6.daddr = match.mask->dst; + flow->l3_key.ipv6.saddr = match.key->src; + flow->l3_mask.ipv6.saddr = match.mask->src; } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_PORTS)) { - struct flow_dissector_key_ports *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_PORTS); - struct flow_dissector_key_ports *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_PORTS); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports match; + flow_rule_match_ports(rule, &match); flow->flags |= BNXT_TC_FLOW_FLAGS_PORTS; - flow->l4_key.ports.dport = key->dst; - flow->l4_mask.ports.dport = mask->dst; - flow->l4_key.ports.sport = key->src; - flow->l4_mask.ports.sport = mask->src; + flow->l4_key.ports.dport = match.key->dst; + flow->l4_mask.ports.dport = match.mask->dst; + flow->l4_key.ports.sport = match.key->src; + flow->l4_mask.ports.sport = match.mask->src; } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ICMP)) { - struct flow_dissector_key_icmp *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ICMP); - struct flow_dissector_key_icmp *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_ICMP); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) { + struct flow_match_icmp match; + flow_rule_match_icmp(rule, &match); flow->flags |= BNXT_TC_FLOW_FLAGS_ICMP; - flow->l4_key.icmp.type = key->type; - flow->l4_key.icmp.code = key->code; - flow->l4_mask.icmp.type = mask->type; - flow->l4_mask.icmp.code = mask->code; + flow->l4_key.icmp.type = match.key->type; + flow->l4_key.icmp.code = match.key->code; + flow->l4_mask.icmp.type = match.mask->type; + flow->l4_mask.icmp.code = match.mask->code; } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) { - struct flow_dissector_key_ipv4_addrs *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS); - struct flow_dissector_key_ipv4_addrs *mask = - GET_MASK(tc_flow_cmd, - FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) { + struct flow_match_ipv4_addrs match; + flow_rule_match_enc_ipv4_addrs(rule, &match); flow->flags |= BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS; - flow->tun_key.u.ipv4.dst = key->dst; - flow->tun_mask.u.ipv4.dst = mask->dst; - flow->tun_key.u.ipv4.src = key->src; - flow->tun_mask.u.ipv4.src = mask->src; - } else if (dissector_uses_key(dissector, + flow->tun_key.u.ipv4.dst = match.key->dst; + flow->tun_mask.u.ipv4.dst = match.mask->dst; + flow->tun_key.u.ipv4.src = match.key->src; + flow->tun_mask.u.ipv4.src = match.mask->src; + } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) { return -EOPNOTSUPP; } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) { - struct flow_dissector_key_keyid *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_KEYID); - struct flow_dissector_key_keyid *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_KEYID); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { + struct flow_match_enc_keyid match; + flow_rule_match_enc_keyid(rule, &match); flow->flags |= BNXT_TC_FLOW_FLAGS_TUNL_ID; - flow->tun_key.tun_id = key32_to_tunnel_id(key->keyid); - flow->tun_mask.tun_id = key32_to_tunnel_id(mask->keyid); + flow->tun_key.tun_id = key32_to_tunnel_id(match.key->keyid); + flow->tun_mask.tun_id = key32_to_tunnel_id(match.mask->keyid); } - if (dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) { - struct flow_dissector_key_ports *key = - GET_KEY(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_PORTS); - struct flow_dissector_key_ports *mask = - GET_MASK(tc_flow_cmd, FLOW_DISSECTOR_KEY_ENC_PORTS); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS)) { + struct flow_match_ports match; + flow_rule_match_enc_ports(rule, &match); flow->flags |= BNXT_TC_FLOW_FLAGS_TUNL_PORTS; - flow->tun_key.tp_dst = key->dst; - flow->tun_mask.tp_dst = mask->dst; - flow->tun_key.tp_src = key->src; - flow->tun_mask.tp_src = mask->src; + flow->tun_key.tp_dst = match.key->dst; + flow->tun_mask.tp_dst = match.mask->dst; + flow->tun_key.tp_src = match.key->src; + flow->tun_mask.tp_src = match.mask->src; } return bnxt_tc_parse_actions(bp, &flow->actions, tc_flow_cmd->exts); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c index c116f96956fe..39c5af5dad3d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c @@ -83,28 +83,23 @@ static void cxgb4_process_flow_match(struct net_device *dev, struct tc_cls_flower_offload *cls, struct ch_filter_specification *fs) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(cls); u16 addr_type = 0; - if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { - struct flow_dissector_key_control *key = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_CONTROL, - cls->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control match; - addr_type = key->addr_type; + flow_rule_match_control(rule, &match); + addr_type = match.key->addr_type; } - if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_BASIC, - cls->key); - struct flow_dissector_key_basic *mask = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_BASIC, - cls->mask); - u16 ethtype_key = ntohs(key->n_proto); - u16 ethtype_mask = ntohs(mask->n_proto); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; + u16 ethtype_key, ethtype_mask; + + flow_rule_match_basic(rule, &match); + ethtype_key = ntohs(match.key->n_proto); + ethtype_mask = ntohs(match.mask->n_proto); if (ethtype_key == ETH_P_ALL) { ethtype_key = 0; @@ -116,115 +111,89 @@ static void cxgb4_process_flow_match(struct net_device *dev, fs->val.ethtype = ethtype_key; fs->mask.ethtype = ethtype_mask; - fs->val.proto = key->ip_proto; - fs->mask.proto = mask->ip_proto; + fs->val.proto = match.key->ip_proto; + fs->mask.proto = match.mask->ip_proto; } if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { - struct flow_dissector_key_ipv4_addrs *key = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - cls->key); - struct flow_dissector_key_ipv4_addrs *mask = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - cls->mask); + struct flow_match_ipv4_addrs match; + + flow_rule_match_ipv4_addrs(rule, &match); fs->type = 0; - memcpy(&fs->val.lip[0], &key->dst, sizeof(key->dst)); - memcpy(&fs->val.fip[0], &key->src, sizeof(key->src)); - memcpy(&fs->mask.lip[0], &mask->dst, sizeof(mask->dst)); - memcpy(&fs->mask.fip[0], &mask->src, sizeof(mask->src)); + memcpy(&fs->val.lip[0], &match.key->dst, sizeof(match.key->dst)); + memcpy(&fs->val.fip[0], &match.key->src, sizeof(match.key->src)); + memcpy(&fs->mask.lip[0], &match.mask->dst, sizeof(match.mask->dst)); + memcpy(&fs->mask.fip[0], &match.mask->src, sizeof(match.mask->src)); /* also initialize nat_lip/fip to same values */ - memcpy(&fs->nat_lip[0], &key->dst, sizeof(key->dst)); - memcpy(&fs->nat_fip[0], &key->src, sizeof(key->src)); - + memcpy(&fs->nat_lip[0], &match.key->dst, sizeof(match.key->dst)); + memcpy(&fs->nat_fip[0], &match.key->src, sizeof(match.key->src)); } if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { - struct flow_dissector_key_ipv6_addrs *key = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - cls->key); - struct flow_dissector_key_ipv6_addrs *mask = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - cls->mask); + struct flow_match_ipv6_addrs match; + flow_rule_match_ipv6_addrs(rule, &match); fs->type = 1; - memcpy(&fs->val.lip[0], key->dst.s6_addr, sizeof(key->dst)); - memcpy(&fs->val.fip[0], key->src.s6_addr, sizeof(key->src)); - memcpy(&fs->mask.lip[0], mask->dst.s6_addr, sizeof(mask->dst)); - memcpy(&fs->mask.fip[0], mask->src.s6_addr, sizeof(mask->src)); + memcpy(&fs->val.lip[0], match.key->dst.s6_addr, + sizeof(match.key->dst)); + memcpy(&fs->val.fip[0], match.key->src.s6_addr, + sizeof(match.key->src)); + memcpy(&fs->mask.lip[0], match.mask->dst.s6_addr, + sizeof(match.mask->dst)); + memcpy(&fs->mask.fip[0], match.mask->src.s6_addr, + sizeof(match.mask->src)); /* also initialize nat_lip/fip to same values */ - memcpy(&fs->nat_lip[0], key->dst.s6_addr, sizeof(key->dst)); - memcpy(&fs->nat_fip[0], key->src.s6_addr, sizeof(key->src)); + memcpy(&fs->nat_lip[0], match.key->dst.s6_addr, + sizeof(match.key->dst)); + memcpy(&fs->nat_fip[0], match.key->src.s6_addr, + sizeof(match.key->src)); } - if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_PORTS)) { - struct flow_dissector_key_ports *key, *mask; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports match; - key = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_PORTS, - cls->key); - mask = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_PORTS, - cls->mask); - fs->val.lport = cpu_to_be16(key->dst); - fs->mask.lport = cpu_to_be16(mask->dst); - fs->val.fport = cpu_to_be16(key->src); - fs->mask.fport = cpu_to_be16(mask->src); + flow_rule_match_ports(rule, &match); + fs->val.lport = cpu_to_be16(match.key->dst); + fs->mask.lport = cpu_to_be16(match.mask->dst); + fs->val.fport = cpu_to_be16(match.key->src); + fs->mask.fport = cpu_to_be16(match.mask->src); /* also initialize nat_lport/fport to same values */ - fs->nat_lport = cpu_to_be16(key->dst); - fs->nat_fport = cpu_to_be16(key->src); + fs->nat_lport = cpu_to_be16(match.key->dst); + fs->nat_fport = cpu_to_be16(match.key->src); } - if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_IP)) { - struct flow_dissector_key_ip *key, *mask; - - key = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_IP, - cls->key); - mask = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_IP, - cls->mask); - fs->val.tos = key->tos; - fs->mask.tos = mask->tos; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { + struct flow_match_ip match; + + flow_rule_match_ip(rule, &match); + fs->val.tos = match.key->tos; + fs->mask.tos = match.mask->tos; } - if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) { - struct flow_dissector_key_keyid *key, *mask; - - key = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - cls->key); - mask = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - cls->mask); - fs->val.vni = be32_to_cpu(key->keyid); - fs->mask.vni = be32_to_cpu(mask->keyid); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { + struct flow_match_enc_keyid match; + + flow_rule_match_enc_keyid(rule, &match); + fs->val.vni = be32_to_cpu(match.key->keyid); + fs->mask.vni = be32_to_cpu(match.mask->keyid); if (fs->mask.vni) { fs->val.encap_vld = 1; fs->mask.encap_vld = 1; } } - if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_dissector_key_vlan *key, *mask; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; u16 vlan_tci, vlan_tci_mask; - key = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_VLAN, - cls->key); - mask = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_VLAN, - cls->mask); - vlan_tci = key->vlan_id | (key->vlan_priority << - VLAN_PRIO_SHIFT); - vlan_tci_mask = mask->vlan_id | (mask->vlan_priority << - VLAN_PRIO_SHIFT); + flow_rule_match_vlan(rule, &match); + vlan_tci = match.key->vlan_id | (match.key->vlan_priority << + VLAN_PRIO_SHIFT); + vlan_tci_mask = match.mask->vlan_id | (match.mask->vlan_priority << + VLAN_PRIO_SHIFT); fs->val.ivlan = vlan_tci; fs->mask.ivlan = vlan_tci_mask; @@ -255,10 +224,12 @@ static void cxgb4_process_flow_match(struct net_device *dev, static int cxgb4_validate_flow_match(struct net_device *dev, struct tc_cls_flower_offload *cls) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(cls); + struct flow_dissector *dissector = rule->match.dissector; u16 ethtype_mask = 0; u16 ethtype_key = 0; - if (cls->dissector->used_keys & + if (dissector->used_keys & ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | BIT(FLOW_DISSECTOR_KEY_BASIC) | BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | @@ -268,36 +239,29 @@ static int cxgb4_validate_flow_match(struct net_device *dev, BIT(FLOW_DISSECTOR_KEY_VLAN) | BIT(FLOW_DISSECTOR_KEY_IP))) { netdev_warn(dev, "Unsupported key used: 0x%x\n", - cls->dissector->used_keys); + dissector->used_keys); return -EOPNOTSUPP; } - if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_BASIC, - cls->key); - struct flow_dissector_key_basic *mask = - skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_BASIC, - cls->mask); - ethtype_key = ntohs(key->n_proto); - ethtype_mask = ntohs(mask->n_proto); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; + + flow_rule_match_basic(rule, &match); + ethtype_key = ntohs(match.key->n_proto); + ethtype_mask = ntohs(match.mask->n_proto); } - if (dissector_uses_key(cls->dissector, FLOW_DISSECTOR_KEY_IP)) { + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { u16 eth_ip_type = ethtype_key & ethtype_mask; - struct flow_dissector_key_ip *mask; + struct flow_match_ip match; if (eth_ip_type != ETH_P_IP && eth_ip_type != ETH_P_IPV6) { netdev_err(dev, "IP Key supported only with IPv4/v6"); return -EINVAL; } - mask = skb_flow_dissector_target(cls->dissector, - FLOW_DISSECTOR_KEY_IP, - cls->mask); - if (mask->ttl) { + flow_rule_match_ip(rule, &match); + if (match.mask->ttl) { netdev_warn(dev, "ttl match unsupported for offload"); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5c6731b97059..44856a84738d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7169,11 +7169,13 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, struct tc_cls_flower_offload *f, struct i40e_cloud_filter *filter) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_dissector *dissector = rule->match.dissector; u16 n_proto_mask = 0, n_proto_key = 0, addr_type = 0; struct i40e_pf *pf = vsi->back; u8 field_flags = 0; - if (f->dissector->used_keys & + if (dissector->used_keys & ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | BIT(FLOW_DISSECTOR_KEY_BASIC) | BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | @@ -7183,143 +7185,109 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, BIT(FLOW_DISSECTOR_KEY_PORTS) | BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) { dev_err(&pf->pdev->dev, "Unsupported key used: 0x%x\n", - f->dissector->used_keys); + dissector->used_keys); return -EOPNOTSUPP; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) { - struct flow_dissector_key_keyid *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - f->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { + struct flow_match_enc_keyid match; - struct flow_dissector_key_keyid *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - f->mask); - - if (mask->keyid != 0) + flow_rule_match_enc_keyid(rule, &match); + if (match.mask->keyid != 0) field_flags |= I40E_CLOUD_FIELD_TEN_ID; - filter->tenant_id = be32_to_cpu(key->keyid); + filter->tenant_id = be32_to_cpu(match.key->keyid); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->key); - - struct flow_dissector_key_basic *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; - n_proto_key = ntohs(key->n_proto); - n_proto_mask = ntohs(mask->n_proto); + flow_rule_match_basic(rule, &match); + n_proto_key = ntohs(match.key->n_proto); + n_proto_mask = ntohs(match.mask->n_proto); if (n_proto_key == ETH_P_ALL) { n_proto_key = 0; n_proto_mask = 0; } filter->n_proto = n_proto_key & n_proto_mask; - filter->ip_proto = key->ip_proto; + filter->ip_proto = match.key->ip_proto; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - struct flow_dissector_key_eth_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; - struct flow_dissector_key_eth_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->mask); + flow_rule_match_eth_addrs(rule, &match); /* use is_broadcast and is_zero to check for all 0xf or 0 */ - if (!is_zero_ether_addr(mask->dst)) { - if (is_broadcast_ether_addr(mask->dst)) { + if (!is_zero_ether_addr(match.mask->dst)) { + if (is_broadcast_ether_addr(match.mask->dst)) { field_flags |= I40E_CLOUD_FIELD_OMAC; } else { dev_err(&pf->pdev->dev, "Bad ether dest mask %pM\n", - mask->dst); + match.mask->dst); return I40E_ERR_CONFIG; } } - if (!is_zero_ether_addr(mask->src)) { - if (is_broadcast_ether_addr(mask->src)) { + if (!is_zero_ether_addr(match.mask->src)) { + if (is_broadcast_ether_addr(match.mask->src)) { field_flags |= I40E_CLOUD_FIELD_IMAC; } else { dev_err(&pf->pdev->dev, "Bad ether src mask %pM\n", - mask->src); + match.mask->src); return I40E_ERR_CONFIG; } } - ether_addr_copy(filter->dst_mac, key->dst); - ether_addr_copy(filter->src_mac, key->src); + ether_addr_copy(filter->dst_mac, match.key->dst); + ether_addr_copy(filter->src_mac, match.key->src); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_dissector_key_vlan *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->key); - struct flow_dissector_key_vlan *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; - if (mask->vlan_id) { - if (mask->vlan_id == VLAN_VID_MASK) { + flow_rule_match_vlan(rule, &match); + if (match.mask->vlan_id) { + if (match.mask->vlan_id == VLAN_VID_MASK) { field_flags |= I40E_CLOUD_FIELD_IVLAN; } else { dev_err(&pf->pdev->dev, "Bad vlan mask 0x%04x\n", - mask->vlan_id); + match.mask->vlan_id); return I40E_ERR_CONFIG; } } - filter->vlan_id = cpu_to_be16(key->vlan_id); + filter->vlan_id = cpu_to_be16(match.key->vlan_id); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { - struct flow_dissector_key_control *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_CONTROL, - f->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control match; - addr_type = key->addr_type; + flow_rule_match_control(rule, &match); + addr_type = match.key->addr_type; } if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { - struct flow_dissector_key_ipv4_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->key); - struct flow_dissector_key_ipv4_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->mask); - - if (mask->dst) { - if (mask->dst == cpu_to_be32(0xffffffff)) { + struct flow_match_ipv4_addrs match; + + flow_rule_match_ipv4_addrs(rule, &match); + if (match.mask->dst) { + if (match.mask->dst == cpu_to_be32(0xffffffff)) { field_flags |= I40E_CLOUD_FIELD_IIP; } else { dev_err(&pf->pdev->dev, "Bad ip dst mask %pI4b\n", - &mask->dst); + &match.mask->dst); return I40E_ERR_CONFIG; } } - if (mask->src) { - if (mask->src == cpu_to_be32(0xffffffff)) { + if (match.mask->src) { + if (match.mask->src == cpu_to_be32(0xffffffff)) { field_flags |= I40E_CLOUD_FIELD_IIP; } else { dev_err(&pf->pdev->dev, "Bad ip src mask %pI4b\n", - &mask->src); + &match.mask->src); return I40E_ERR_CONFIG; } } @@ -7328,70 +7296,60 @@ static int i40e_parse_cls_flower(struct i40e_vsi *vsi, dev_err(&pf->pdev->dev, "Tenant id not allowed for ip filter\n"); return I40E_ERR_CONFIG; } - filter->dst_ipv4 = key->dst; - filter->src_ipv4 = key->src; + filter->dst_ipv4 = match.key->dst; + filter->src_ipv4 = match.key->src; } if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { - struct flow_dissector_key_ipv6_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->key); - struct flow_dissector_key_ipv6_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->mask); + struct flow_match_ipv6_addrs match; + + flow_rule_match_ipv6_addrs(rule, &match); /* src and dest IPV6 address should not be LOOPBACK * (0:0:0:0:0:0:0:1), which can be represented as ::1 */ - if (ipv6_addr_loopback(&key->dst) || - ipv6_addr_loopback(&key->src)) { + if (ipv6_addr_loopback(&match.key->dst) || + ipv6_addr_loopback(&match.key->src)) { dev_err(&pf->pdev->dev, "Bad ipv6, addr is LOOPBACK\n"); return I40E_ERR_CONFIG; } - if (!ipv6_addr_any(&mask->dst) || !ipv6_addr_any(&mask->src)) + if (!ipv6_addr_any(&match.mask->dst) || + !ipv6_addr_any(&match.mask->src)) field_flags |= I40E_CLOUD_FIELD_IIP; - memcpy(&filter->src_ipv6, &key->src.s6_addr32, + memcpy(&filter->src_ipv6, &match.key->src.s6_addr32, sizeof(filter->src_ipv6)); - memcpy(&filter->dst_ipv6, &key->dst.s6_addr32, + memcpy(&filter->dst_ipv6, &match.key->dst.s6_addr32, sizeof(filter->dst_ipv6)); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) { - struct flow_dissector_key_ports *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->key); - struct flow_dissector_key_ports *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports match; - if (mask->src) { - if (mask->src == cpu_to_be16(0xffff)) { + flow_rule_match_ports(rule, &match); + if (match.mask->src) { + if (match.mask->src == cpu_to_be16(0xffff)) { field_flags |= I40E_CLOUD_FIELD_IIP; } else { dev_err(&pf->pdev->dev, "Bad src port mask 0x%04x\n", - be16_to_cpu(mask->src)); + be16_to_cpu(match.mask->src)); return I40E_ERR_CONFIG; } } - if (mask->dst) { - if (mask->dst == cpu_to_be16(0xffff)) { + if (match.mask->dst) { + if (match.mask->dst == cpu_to_be16(0xffff)) { field_flags |= I40E_CLOUD_FIELD_IIP; } else { dev_err(&pf->pdev->dev, "Bad dst port mask 0x%04x\n", - be16_to_cpu(mask->dst)); + be16_to_cpu(match.mask->dst)); return I40E_ERR_CONFIG; } } - filter->dst_port = key->dst; - filter->src_port = key->src; + filter->dst_port = match.key->dst; + filter->src_port = match.key->src; switch (filter->ip_proto) { case IPPROTO_TCP: diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 9f2b7b7adf6b..4569d69a2b55 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -2439,6 +2439,8 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter, struct tc_cls_flower_offload *f, struct iavf_cloud_filter *filter) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_dissector *dissector = rule->match.dissector; u16 n_proto_mask = 0; u16 n_proto_key = 0; u8 field_flags = 0; @@ -2447,7 +2449,7 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter, int i = 0; struct virtchnl_filter *vf = &filter->f; - if (f->dissector->used_keys & + if (dissector->used_keys & ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | BIT(FLOW_DISSECTOR_KEY_BASIC) | BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | @@ -2457,32 +2459,24 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter, BIT(FLOW_DISSECTOR_KEY_PORTS) | BIT(FLOW_DISSECTOR_KEY_ENC_KEYID))) { dev_err(&adapter->pdev->dev, "Unsupported key used: 0x%x\n", - f->dissector->used_keys); + dissector->used_keys); return -EOPNOTSUPP; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) { - struct flow_dissector_key_keyid *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { + struct flow_match_enc_keyid match; - if (mask->keyid != 0) + flow_rule_match_enc_keyid(rule, &match); + if (match.mask->keyid != 0) field_flags |= IAVF_CLOUD_FIELD_TEN_ID; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; - struct flow_dissector_key_basic *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->mask); - n_proto_key = ntohs(key->n_proto); - n_proto_mask = ntohs(mask->n_proto); + flow_rule_match_basic(rule, &match); + n_proto_key = ntohs(match.key->n_proto); + n_proto_mask = ntohs(match.mask->n_proto); if (n_proto_key == ETH_P_ALL) { n_proto_key = 0; @@ -2496,122 +2490,103 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter, vf->flow_type = VIRTCHNL_TCP_V6_FLOW; } - if (key->ip_proto != IPPROTO_TCP) { + if (match.key->ip_proto != IPPROTO_TCP) { dev_info(&adapter->pdev->dev, "Only TCP transport is supported\n"); return -EINVAL; } } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - struct flow_dissector_key_eth_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; + + flow_rule_match_eth_addrs(rule, &match); - struct flow_dissector_key_eth_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->mask); /* use is_broadcast and is_zero to check for all 0xf or 0 */ - if (!is_zero_ether_addr(mask->dst)) { - if (is_broadcast_ether_addr(mask->dst)) { + if (!is_zero_ether_addr(match.mask->dst)) { + if (is_broadcast_ether_addr(match.mask->dst)) { field_flags |= IAVF_CLOUD_FIELD_OMAC; } else { dev_err(&adapter->pdev->dev, "Bad ether dest mask %pM\n", - mask->dst); + match.mask->dst); return I40E_ERR_CONFIG; } } - if (!is_zero_ether_addr(mask->src)) { - if (is_broadcast_ether_addr(mask->src)) { + if (!is_zero_ether_addr(match.mask->src)) { + if (is_broadcast_ether_addr(match.mask->src)) { field_flags |= IAVF_CLOUD_FIELD_IMAC; } else { dev_err(&adapter->pdev->dev, "Bad ether src mask %pM\n", - mask->src); + match.mask->src); return I40E_ERR_CONFIG; } } - if (!is_zero_ether_addr(key->dst)) - if (is_valid_ether_addr(key->dst) || - is_multicast_ether_addr(key->dst)) { + if (!is_zero_ether_addr(match.key->dst)) + if (is_valid_ether_addr(match.key->dst) || + is_multicast_ether_addr(match.key->dst)) { /* set the mask if a valid dst_mac address */ for (i = 0; i < ETH_ALEN; i++) vf->mask.tcp_spec.dst_mac[i] |= 0xff; ether_addr_copy(vf->data.tcp_spec.dst_mac, - key->dst); + match.key->dst); } - if (!is_zero_ether_addr(key->src)) - if (is_valid_ether_addr(key->src) || - is_multicast_ether_addr(key->src)) { + if (!is_zero_ether_addr(match.key->src)) + if (is_valid_ether_addr(match.key->src) || + is_multicast_ether_addr(match.key->src)) { /* set the mask if a valid dst_mac address */ for (i = 0; i < ETH_ALEN; i++) vf->mask.tcp_spec.src_mac[i] |= 0xff; ether_addr_copy(vf->data.tcp_spec.src_mac, - key->src); + match.key->src); } } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_dissector_key_vlan *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->key); - struct flow_dissector_key_vlan *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; - if (mask->vlan_id) { - if (mask->vlan_id == VLAN_VID_MASK) { + flow_rule_match_vlan(rule, &match); + if (match.mask->vlan_id) { + if (match.mask->vlan_id == VLAN_VID_MASK) { field_flags |= IAVF_CLOUD_FIELD_IVLAN; } else { dev_err(&adapter->pdev->dev, "Bad vlan mask %u\n", - mask->vlan_id); + match.mask->vlan_id); return I40E_ERR_CONFIG; } } vf->mask.tcp_spec.vlan_id |= cpu_to_be16(0xffff); - vf->data.tcp_spec.vlan_id = cpu_to_be16(key->vlan_id); + vf->data.tcp_spec.vlan_id = cpu_to_be16(match.key->vlan_id); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { - struct flow_dissector_key_control *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_CONTROL, - f->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control match; - addr_type = key->addr_type; + flow_rule_match_control(rule, &match); + addr_type = match.key->addr_type; } if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { - struct flow_dissector_key_ipv4_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->key); - struct flow_dissector_key_ipv4_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->mask); - - if (mask->dst) { - if (mask->dst == cpu_to_be32(0xffffffff)) { + struct flow_match_ipv4_addrs match; + + flow_rule_match_ipv4_addrs(rule, &match); + if (match.mask->dst) { + if (match.mask->dst == cpu_to_be32(0xffffffff)) { field_flags |= IAVF_CLOUD_FIELD_IIP; } else { dev_err(&adapter->pdev->dev, "Bad ip dst mask 0x%08x\n", - be32_to_cpu(mask->dst)); + be32_to_cpu(match.mask->dst)); return I40E_ERR_CONFIG; } } - if (mask->src) { - if (mask->src == cpu_to_be32(0xffffffff)) { + if (match.mask->src) { + if (match.mask->src == cpu_to_be32(0xffffffff)) { field_flags |= IAVF_CLOUD_FIELD_IIP; } else { dev_err(&adapter->pdev->dev, "Bad ip src mask 0x%08x\n", - be32_to_cpu(mask->dst)); + be32_to_cpu(match.mask->dst)); return I40E_ERR_CONFIG; } } @@ -2620,28 +2595,23 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter, dev_info(&adapter->pdev->dev, "Tenant id not allowed for ip filter\n"); return I40E_ERR_CONFIG; } - if (key->dst) { + if (match.key->dst) { vf->mask.tcp_spec.dst_ip[0] |= cpu_to_be32(0xffffffff); - vf->data.tcp_spec.dst_ip[0] = key->dst; + vf->data.tcp_spec.dst_ip[0] = match.key->dst; } - if (key->src) { + if (match.key->src) { vf->mask.tcp_spec.src_ip[0] |= cpu_to_be32(0xffffffff); - vf->data.tcp_spec.src_ip[0] = key->src; + vf->data.tcp_spec.src_ip[0] = match.key->src; } } if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { - struct flow_dissector_key_ipv6_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->key); - struct flow_dissector_key_ipv6_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->mask); + struct flow_match_ipv6_addrs match; + + flow_rule_match_ipv6_addrs(rule, &match); /* validate mask, make sure it is not IPV6_ADDR_ANY */ - if (ipv6_addr_any(&mask->dst)) { + if (ipv6_addr_any(&match.mask->dst)) { dev_err(&adapter->pdev->dev, "Bad ipv6 dst mask 0x%02x\n", IPV6_ADDR_ANY); return I40E_ERR_CONFIG; @@ -2650,61 +2620,56 @@ static int iavf_parse_cls_flower(struct iavf_adapter *adapter, /* src and dest IPv6 address should not be LOOPBACK * (0:0:0:0:0:0:0:1) which can be represented as ::1 */ - if (ipv6_addr_loopback(&key->dst) || - ipv6_addr_loopback(&key->src)) { + if (ipv6_addr_loopback(&match.key->dst) || + ipv6_addr_loopback(&match.key->src)) { dev_err(&adapter->pdev->dev, "ipv6 addr should not be loopback\n"); return I40E_ERR_CONFIG; } - if (!ipv6_addr_any(&mask->dst) || !ipv6_addr_any(&mask->src)) + if (!ipv6_addr_any(&match.mask->dst) || + !ipv6_addr_any(&match.mask->src)) field_flags |= IAVF_CLOUD_FIELD_IIP; for (i = 0; i < 4; i++) vf->mask.tcp_spec.dst_ip[i] |= cpu_to_be32(0xffffffff); - memcpy(&vf->data.tcp_spec.dst_ip, &key->dst.s6_addr32, + memcpy(&vf->data.tcp_spec.dst_ip, &match.key->dst.s6_addr32, sizeof(vf->data.tcp_spec.dst_ip)); for (i = 0; i < 4; i++) vf->mask.tcp_spec.src_ip[i] |= cpu_to_be32(0xffffffff); - memcpy(&vf->data.tcp_spec.src_ip, &key->src.s6_addr32, + memcpy(&vf->data.tcp_spec.src_ip, &match.key->src.s6_addr32, sizeof(vf->data.tcp_spec.src_ip)); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) { - struct flow_dissector_key_ports *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->key); - struct flow_dissector_key_ports *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->mask); - - if (mask->src) { - if (mask->src == cpu_to_be16(0xffff)) { + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports match; + + flow_rule_match_ports(rule, &match); + if (match.mask->src) { + if (match.mask->src == cpu_to_be16(0xffff)) { field_flags |= IAVF_CLOUD_FIELD_IIP; } else { dev_err(&adapter->pdev->dev, "Bad src port mask %u\n", - be16_to_cpu(mask->src)); + be16_to_cpu(match.mask->src)); return I40E_ERR_CONFIG; } } - if (mask->dst) { - if (mask->dst == cpu_to_be16(0xffff)) { + if (match.mask->dst) { + if (match.mask->dst == cpu_to_be16(0xffff)) { field_flags |= IAVF_CLOUD_FIELD_IIP; } else { dev_err(&adapter->pdev->dev, "Bad dst port mask %u\n", - be16_to_cpu(mask->dst)); + be16_to_cpu(match.mask->dst)); return I40E_ERR_CONFIG; } } - if (key->dst) { + if (match.key->dst) { vf->mask.tcp_spec.dst_port |= cpu_to_be16(0xffff); - vf->data.tcp_spec.dst_port = key->dst; + vf->data.tcp_spec.dst_port = match.key->dst; } - if (key->src) { + if (match.key->src) { vf->mask.tcp_spec.src_port |= cpu_to_be16(0xffff); - vf->data.tcp_spec.src_port = key->src; + vf->data.tcp_spec.src_port = match.key->src; } } vf->field_flags = field_flags; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index d35cc9697e2d..6d812e96572d 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2581,9 +2581,11 @@ static int igb_parse_cls_flower(struct igb_adapter *adapter, int traffic_class, struct igb_nfc_filter *input) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_dissector *dissector = rule->match.dissector; struct netlink_ext_ack *extack = f->common.extack; - if (f->dissector->used_keys & + if (dissector->used_keys & ~(BIT(FLOW_DISSECTOR_KEY_BASIC) | BIT(FLOW_DISSECTOR_KEY_CONTROL) | BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | @@ -2593,78 +2595,60 @@ static int igb_parse_cls_flower(struct igb_adapter *adapter, return -EOPNOTSUPP; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - struct flow_dissector_key_eth_addrs *key, *mask; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->mask); - - if (!is_zero_ether_addr(mask->dst)) { - if (!is_broadcast_ether_addr(mask->dst)) { + flow_rule_match_eth_addrs(rule, &match); + if (!is_zero_ether_addr(match.mask->dst)) { + if (!is_broadcast_ether_addr(match.mask->dst)) { NL_SET_ERR_MSG_MOD(extack, "Only full masks are supported for destination MAC address"); return -EINVAL; } input->filter.match_flags |= IGB_FILTER_FLAG_DST_MAC_ADDR; - ether_addr_copy(input->filter.dst_addr, key->dst); + ether_addr_copy(input->filter.dst_addr, match.key->dst); } - if (!is_zero_ether_addr(mask->src)) { - if (!is_broadcast_ether_addr(mask->src)) { + if (!is_zero_ether_addr(match.mask->src)) { + if (!is_broadcast_ether_addr(match.mask->src)) { NL_SET_ERR_MSG_MOD(extack, "Only full masks are supported for source MAC address"); return -EINVAL; } input->filter.match_flags |= IGB_FILTER_FLAG_SRC_MAC_ADDR; - ether_addr_copy(input->filter.src_addr, key->src); + ether_addr_copy(input->filter.src_addr, match.key->src); } } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key, *mask; - - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; - if (mask->n_proto) { - if (mask->n_proto != ETHER_TYPE_FULL_MASK) { + flow_rule_match_basic(rule, &match); + if (match.mask->n_proto) { + if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) { NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for EtherType filter"); return -EINVAL; } input->filter.match_flags |= IGB_FILTER_FLAG_ETHER_TYPE; - input->filter.etype = key->n_proto; + input->filter.etype = match.key->n_proto; } } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_dissector_key_vlan *key, *mask; - - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; - if (mask->vlan_priority) { - if (mask->vlan_priority != VLAN_PRIO_FULL_MASK) { + flow_rule_match_vlan(rule, &match); + if (match.mask->vlan_priority) { + if (match.mask->vlan_priority != VLAN_PRIO_FULL_MASK) { NL_SET_ERR_MSG_MOD(extack, "Only full mask is supported for VLAN priority"); return -EINVAL; } input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI; - input->filter.vlan_tci = key->vlan_priority; + input->filter.vlan_tci = match.key->vlan_priority; } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index 046948ead152..47bb4eb894c2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -496,25 +496,21 @@ static int mlx5e_tc_tun_parse_vxlan(struct mlx5e_priv *priv, void *headers_c, void *headers_v) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); struct netlink_ext_ack *extack = f->common.extack; - struct flow_dissector_key_ports *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_PORTS, - f->key); - struct flow_dissector_key_ports *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_PORTS, - f->mask); void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); + struct flow_match_ports enc_ports; + + flow_rule_match_enc_ports(rule, &enc_ports); /* Full udp dst port must be given */ - if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS) || - memchr_inv(&mask->dst, 0xff, sizeof(mask->dst))) { + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS) || + memchr_inv(&enc_ports.mask->dst, 0xff, sizeof(enc_ports.mask->dst))) { NL_SET_ERR_MSG_MOD(extack, "VXLAN decap filter must include enc_dst_port condition"); netdev_warn(priv->netdev, @@ -523,12 +519,12 @@ static int mlx5e_tc_tun_parse_vxlan(struct mlx5e_priv *priv, } /* udp dst port must be knonwn as a VXLAN port */ - if (!mlx5_vxlan_lookup_port(priv->mdev->vxlan, be16_to_cpu(key->dst))) { + if (!mlx5_vxlan_lookup_port(priv->mdev->vxlan, be16_to_cpu(enc_ports.key->dst))) { NL_SET_ERR_MSG_MOD(extack, "Matched UDP port is not registered as a VXLAN port"); netdev_warn(priv->netdev, "UDP port %d is not registered as a VXLAN port\n", - be16_to_cpu(key->dst)); + be16_to_cpu(enc_ports.key->dst)); return -EOPNOTSUPP; } @@ -536,26 +532,26 @@ static int mlx5e_tc_tun_parse_vxlan(struct mlx5e_priv *priv, MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_UDP); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport, ntohs(mask->dst)); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, ntohs(key->dst)); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport, + ntohs(enc_ports.mask->dst)); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, + ntohs(enc_ports.key->dst)); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport, ntohs(mask->src)); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport, ntohs(key->src)); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport, + ntohs(enc_ports.mask->src)); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport, + ntohs(enc_ports.key->src)); /* match on VNI */ - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) { - struct flow_dissector_key_keyid *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - f->key); - struct flow_dissector_key_keyid *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { + struct flow_match_enc_keyid enc_keyid; + + flow_rule_match_enc_keyid(rule, &enc_keyid); + MLX5_SET(fte_match_set_misc, misc_c, vxlan_vni, - be32_to_cpu(mask->keyid)); + be32_to_cpu(enc_keyid.mask->keyid)); MLX5_SET(fte_match_set_misc, misc_v, vxlan_vni, - be32_to_cpu(key->keyid)); + be32_to_cpu(enc_keyid.key->keyid)); } return 0; } @@ -570,6 +566,7 @@ static int mlx5e_tc_tun_parse_gretap(struct mlx5e_priv *priv, misc_parameters); void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); if (!MLX5_CAP_ESW(priv->mdev, nvgre_encap_decap)) { NL_SET_ERR_MSG_MOD(f->common.extack, @@ -587,21 +584,14 @@ static int mlx5e_tc_tun_parse_gretap(struct mlx5e_priv *priv, MLX5_SET(fte_match_set_misc, misc_v, gre_protocol, ETH_P_TEB); /* gre key */ - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) { - struct flow_dissector_key_keyid *mask = NULL; - struct flow_dissector_key_keyid *key = NULL; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { + struct flow_match_enc_keyid enc_keyid; - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - f->mask); + flow_rule_match_enc_keyid(rule, &enc_keyid); MLX5_SET(fte_match_set_misc, misc_c, - gre_key.key, be32_to_cpu(mask->keyid)); - - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - f->key); + gre_key.key, be32_to_cpu(enc_keyid.mask->keyid)); MLX5_SET(fte_match_set_misc, misc_v, - gre_key.key, be32_to_cpu(key->keyid)); + gre_key.key, be32_to_cpu(enc_keyid.key->keyid)); } return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 74159d39dd66..cd289ce0582d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1309,12 +1309,9 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv, outer_headers); void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); - - struct flow_dissector_key_control *enc_control = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_CONTROL, - f->key); - int err = 0; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_match_control enc_control; + int err; err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f, headers_c, headers_v); @@ -1324,79 +1321,70 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv, return err; } - if (enc_control->addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { - struct flow_dissector_key_ipv4_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, - f->key); - struct flow_dissector_key_ipv4_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, - f->mask); + flow_rule_match_enc_control(rule, &enc_control); + + if (enc_control.key->addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { + struct flow_match_ipv4_addrs match; + + flow_rule_match_enc_ipv4_addrs(rule, &match); MLX5_SET(fte_match_set_lyr_2_4, headers_c, src_ipv4_src_ipv6.ipv4_layout.ipv4, - ntohl(mask->src)); + ntohl(match.mask->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, src_ipv4_src_ipv6.ipv4_layout.ipv4, - ntohl(key->src)); + ntohl(match.key->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_c, dst_ipv4_dst_ipv6.ipv4_layout.ipv4, - ntohl(mask->dst)); + ntohl(match.mask->dst)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, dst_ipv4_dst_ipv6.ipv4_layout.ipv4, - ntohl(key->dst)); + ntohl(match.key->dst)); MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP); - } else if (enc_control->addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { - struct flow_dissector_key_ipv6_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, - f->key); - struct flow_dissector_key_ipv6_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, - f->mask); + } else if (enc_control.key->addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { + struct flow_match_ipv6_addrs match; + flow_rule_match_enc_ipv6_addrs(rule, &match); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, src_ipv4_src_ipv6.ipv6_layout.ipv6), - &mask->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); + &match.mask->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, src_ipv4_src_ipv6.ipv6_layout.ipv6), - &key->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); + &match.key->src, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, dst_ipv4_dst_ipv6.ipv6_layout.ipv6), - &mask->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); + &match.mask->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dst_ipv4_dst_ipv6.ipv6_layout.ipv6), - &key->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); + &match.key->dst, MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6)); MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IPV6); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_IP)) { - struct flow_dissector_key_ip *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_IP, - f->key); - struct flow_dissector_key_ip *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_IP, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) { + struct flow_match_ip match; - MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, mask->tos & 0x3); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, key->tos & 0x3); + flow_rule_match_enc_ip(rule, &match); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, + match.mask->tos & 0x3); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, + match.key->tos & 0x3); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, mask->tos >> 2); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, key->tos >> 2); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, + match.mask->tos >> 2); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, + match.key->tos >> 2); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, mask->ttl); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, key->ttl); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, + match.mask->ttl); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, + match.key->ttl); - if (mask->ttl && + if (match.mask->ttl && !MLX5_CAP_ESW_FLOWTABLE_FDB (priv->mdev, ft_field_support.outer_ipv4_ttl)) { @@ -1437,12 +1425,14 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, misc_parameters); void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_dissector *dissector = rule->match.dissector; u16 addr_type = 0; u8 ip_proto = 0; *match_level = MLX5_MATCH_NONE; - if (f->dissector->used_keys & + if (dissector->used_keys & ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | BIT(FLOW_DISSECTOR_KEY_BASIC) | BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | @@ -1461,20 +1451,18 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, BIT(FLOW_DISSECTOR_KEY_ENC_IP))) { NL_SET_ERR_MSG_MOD(extack, "Unsupported key"); netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n", - f->dissector->used_keys); + dissector->used_keys); return -EOPNOTSUPP; } - if ((dissector_uses_key(f->dissector, - FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) || - dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID) || - dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) && - dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_CONTROL)) { - struct flow_dissector_key_control *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ENC_CONTROL, - f->key); - switch (key->addr_type) { + if ((flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) || + flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID) || + flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS)) && + flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL)) { + struct flow_match_control match; + + flow_rule_match_enc_control(rule, &match); + switch (match.key->addr_type) { case FLOW_DISSECTOR_KEY_IPV4_ADDRS: case FLOW_DISSECTOR_KEY_IPV6_ADDRS: if (parse_tunnel_attr(priv, spec, f, filter_dev)) @@ -1493,35 +1481,27 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, inner_headers); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->key); - struct flow_dissector_key_basic *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; + + flow_rule_match_basic(rule, &match); MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype, - ntohs(mask->n_proto)); + ntohs(match.mask->n_proto)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, - ntohs(key->n_proto)); + ntohs(match.key->n_proto)); - if (mask->n_proto) + if (match.mask->n_proto) *match_level = MLX5_MATCH_L2; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_dissector_key_vlan *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->key); - struct flow_dissector_key_vlan *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->mask); - if (mask->vlan_id || mask->vlan_priority || mask->vlan_tpid) { - if (key->vlan_tpid == htons(ETH_P_8021AD)) { + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; + + flow_rule_match_vlan(rule, &match); + if (match.mask->vlan_id || + match.mask->vlan_priority || + match.mask->vlan_tpid) { + if (match.key->vlan_tpid == htons(ETH_P_8021AD)) { MLX5_SET(fte_match_set_lyr_2_4, headers_c, svlan_tag, 1); MLX5_SET(fte_match_set_lyr_2_4, headers_v, @@ -1533,11 +1513,15 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, cvlan_tag, 1); } - MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid, mask->vlan_id); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, key->vlan_id); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid, + match.mask->vlan_id); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, + match.key->vlan_id); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, mask->vlan_priority); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, key->vlan_priority); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, + match.mask->vlan_priority); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, + match.key->vlan_priority); *match_level = MLX5_MATCH_L2; } @@ -1547,17 +1531,14 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, *match_level = MLX5_MATCH_L2; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CVLAN)) { - struct flow_dissector_key_vlan *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_CVLAN, - f->key); - struct flow_dissector_key_vlan *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_CVLAN, - f->mask); - if (mask->vlan_id || mask->vlan_priority || mask->vlan_tpid) { - if (key->vlan_tpid == htons(ETH_P_8021AD)) { + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) { + struct flow_match_vlan match; + + flow_rule_match_vlan(rule, &match); + if (match.mask->vlan_id || + match.mask->vlan_priority || + match.mask->vlan_tpid) { + if (match.key->vlan_tpid == htons(ETH_P_8021AD)) { MLX5_SET(fte_match_set_misc, misc_c, outer_second_svlan_tag, 1); MLX5_SET(fte_match_set_misc, misc_v, @@ -1570,69 +1551,58 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, } MLX5_SET(fte_match_set_misc, misc_c, outer_second_vid, - mask->vlan_id); + match.mask->vlan_id); MLX5_SET(fte_match_set_misc, misc_v, outer_second_vid, - key->vlan_id); + match.key->vlan_id); MLX5_SET(fte_match_set_misc, misc_c, outer_second_prio, - mask->vlan_priority); + match.mask->vlan_priority); MLX5_SET(fte_match_set_misc, misc_v, outer_second_prio, - key->vlan_priority); + match.key->vlan_priority); *match_level = MLX5_MATCH_L2; } } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - struct flow_dissector_key_eth_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->key); - struct flow_dissector_key_eth_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; + flow_rule_match_eth_addrs(rule, &match); ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, dmac_47_16), - mask->dst); + match.mask->dst); ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dmac_47_16), - key->dst); + match.key->dst); ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, smac_47_16), - mask->src); + match.mask->src); ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, smac_47_16), - key->src); + match.key->src); - if (!is_zero_ether_addr(mask->src) || !is_zero_ether_addr(mask->dst)) + if (!is_zero_ether_addr(match.mask->src) || + !is_zero_ether_addr(match.mask->dst)) *match_level = MLX5_MATCH_L2; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { - struct flow_dissector_key_control *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_CONTROL, - f->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control match; - struct flow_dissector_key_control *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_CONTROL, - f->mask); - addr_type = key->addr_type; + flow_rule_match_control(rule, &match); + addr_type = match.key->addr_type; /* the HW doesn't support frag first/later */ - if (mask->flags & FLOW_DIS_FIRST_FRAG) + if (match.mask->flags & FLOW_DIS_FIRST_FRAG) return -EOPNOTSUPP; - if (mask->flags & FLOW_DIS_IS_FRAGMENT) { + if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) { MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1); MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, - key->flags & FLOW_DIS_IS_FRAGMENT); + match.key->flags & FLOW_DIS_IS_FRAGMENT); /* the HW doesn't need L3 inline to match on frag=no */ - if (!(key->flags & FLOW_DIS_IS_FRAGMENT)) + if (!(match.key->flags & FLOW_DIS_IS_FRAGMENT)) *match_level = MLX5_MATCH_L2; /* *** L2 attributes parsing up to here *** */ else @@ -1640,102 +1610,85 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, } } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->key); - struct flow_dissector_key_basic *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->mask); - ip_proto = key->ip_proto; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; + + flow_rule_match_basic(rule, &match); + ip_proto = match.key->ip_proto; MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol, - mask->ip_proto); + match.mask->ip_proto); MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, - key->ip_proto); + match.key->ip_proto); - if (mask->ip_proto) + if (match.mask->ip_proto) *match_level = MLX5_MATCH_L3; } if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { - struct flow_dissector_key_ipv4_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->key); - struct flow_dissector_key_ipv4_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->mask); + struct flow_match_ipv4_addrs match; + flow_rule_match_ipv4_addrs(rule, &match); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, src_ipv4_src_ipv6.ipv4_layout.ipv4), - &mask->src, sizeof(mask->src)); + &match.mask->src, sizeof(match.mask->src)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, src_ipv4_src_ipv6.ipv4_layout.ipv4), - &key->src, sizeof(key->src)); + &match.key->src, sizeof(match.key->src)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, dst_ipv4_dst_ipv6.ipv4_layout.ipv4), - &mask->dst, sizeof(mask->dst)); + &match.mask->dst, sizeof(match.mask->dst)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dst_ipv4_dst_ipv6.ipv4_layout.ipv4), - &key->dst, sizeof(key->dst)); + &match.key->dst, sizeof(match.key->dst)); - if (mask->src || mask->dst) + if (match.mask->src || match.mask->dst) *match_level = MLX5_MATCH_L3; } if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { - struct flow_dissector_key_ipv6_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->key); - struct flow_dissector_key_ipv6_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->mask); + struct flow_match_ipv6_addrs match; + flow_rule_match_ipv6_addrs(rule, &match); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, src_ipv4_src_ipv6.ipv6_layout.ipv6), - &mask->src, sizeof(mask->src)); + &match.mask->src, sizeof(match.mask->src)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, src_ipv4_src_ipv6.ipv6_layout.ipv6), - &key->src, sizeof(key->src)); + &match.key->src, sizeof(match.key->src)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, dst_ipv4_dst_ipv6.ipv6_layout.ipv6), - &mask->dst, sizeof(mask->dst)); + &match.mask->dst, sizeof(match.mask->dst)); memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, dst_ipv4_dst_ipv6.ipv6_layout.ipv6), - &key->dst, sizeof(key->dst)); + &match.key->dst, sizeof(match.key->dst)); - if (ipv6_addr_type(&mask->src) != IPV6_ADDR_ANY || - ipv6_addr_type(&mask->dst) != IPV6_ADDR_ANY) + if (ipv6_addr_type(&match.mask->src) != IPV6_ADDR_ANY || + ipv6_addr_type(&match.mask->dst) != IPV6_ADDR_ANY) *match_level = MLX5_MATCH_L3; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) { - struct flow_dissector_key_ip *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IP, - f->key); - struct flow_dissector_key_ip *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IP, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { + struct flow_match_ip match; - MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, mask->tos & 0x3); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, key->tos & 0x3); + flow_rule_match_ip(rule, &match); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, + match.mask->tos & 0x3); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, + match.key->tos & 0x3); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, mask->tos >> 2); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, key->tos >> 2); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, + match.mask->tos >> 2); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, + match.key->tos >> 2); - MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, mask->ttl); - MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, key->ttl); + MLX5_SET(fte_match_set_lyr_2_4, headers_c, ttl_hoplimit, + match.mask->ttl); + MLX5_SET(fte_match_set_lyr_2_4, headers_v, ttl_hoplimit, + match.key->ttl); - if (mask->ttl && + if (match.mask->ttl && !MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, ft_field_support.outer_ipv4_ttl)) { NL_SET_ERR_MSG_MOD(extack, @@ -1743,44 +1696,39 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, return -EOPNOTSUPP; } - if (mask->tos || mask->ttl) + if (match.mask->tos || match.mask->ttl) *match_level = MLX5_MATCH_L3; } /* *** L3 attributes parsing up to here *** */ - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) { - struct flow_dissector_key_ports *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->key); - struct flow_dissector_key_ports *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports match; + + flow_rule_match_ports(rule, &match); switch (ip_proto) { case IPPROTO_TCP: MLX5_SET(fte_match_set_lyr_2_4, headers_c, - tcp_sport, ntohs(mask->src)); + tcp_sport, ntohs(match.mask->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, - tcp_sport, ntohs(key->src)); + tcp_sport, ntohs(match.key->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_c, - tcp_dport, ntohs(mask->dst)); + tcp_dport, ntohs(match.mask->dst)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, - tcp_dport, ntohs(key->dst)); + tcp_dport, ntohs(match.key->dst)); break; case IPPROTO_UDP: MLX5_SET(fte_match_set_lyr_2_4, headers_c, - udp_sport, ntohs(mask->src)); + udp_sport, ntohs(match.mask->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, - udp_sport, ntohs(key->src)); + udp_sport, ntohs(match.key->src)); MLX5_SET(fte_match_set_lyr_2_4, headers_c, - udp_dport, ntohs(mask->dst)); + udp_dport, ntohs(match.mask->dst)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, - udp_dport, ntohs(key->dst)); + udp_dport, ntohs(match.key->dst)); break; default: NL_SET_ERR_MSG_MOD(extack, @@ -1790,26 +1738,20 @@ static int __parse_cls_flower(struct mlx5e_priv *priv, return -EINVAL; } - if (mask->src || mask->dst) + if (match.mask->src || match.mask->dst) *match_level = MLX5_MATCH_L4; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) { - struct flow_dissector_key_tcp *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_TCP, - f->key); - struct flow_dissector_key_tcp *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_TCP, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) { + struct flow_match_tcp match; + flow_rule_match_tcp(rule, &match); MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags, - ntohs(mask->flags)); + ntohs(match.mask->flags)); MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags, - ntohs(key->flags)); + ntohs(match.key->flags)); - if (mask->flags) + if (match.mask->flags) *match_level = MLX5_MATCH_L4; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index ff072358d950..a20379e29e02 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -113,59 +113,49 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei, struct tc_cls_flower_offload *f) { - struct flow_dissector_key_ipv4_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->key); - struct flow_dissector_key_ipv4_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->mask); + struct flow_match_ipv4_addrs match; + + flow_rule_match_ipv4_addrs(f->rule, &match); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31, - (char *) &key->src, - (char *) &mask->src, 4); + (char *) &match.key->src, + (char *) &match.mask->src, 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31, - (char *) &key->dst, - (char *) &mask->dst, 4); + (char *) &match.key->dst, + (char *) &match.mask->dst, 4); } static void mlxsw_sp_flower_parse_ipv6(struct mlxsw_sp_acl_rule_info *rulei, struct tc_cls_flower_offload *f) { - struct flow_dissector_key_ipv6_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->key); - struct flow_dissector_key_ipv6_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->mask); + struct flow_match_ipv6_addrs match; + + flow_rule_match_ipv6_addrs(f->rule, &match); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_96_127, - &key->src.s6_addr[0x0], - &mask->src.s6_addr[0x0], 4); + &match.key->src.s6_addr[0x0], + &match.mask->src.s6_addr[0x0], 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_64_95, - &key->src.s6_addr[0x4], - &mask->src.s6_addr[0x4], 4); + &match.key->src.s6_addr[0x4], + &match.mask->src.s6_addr[0x4], 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_32_63, - &key->src.s6_addr[0x8], - &mask->src.s6_addr[0x8], 4); + &match.key->src.s6_addr[0x8], + &match.mask->src.s6_addr[0x8], 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31, - &key->src.s6_addr[0xC], - &mask->src.s6_addr[0xC], 4); + &match.key->src.s6_addr[0xC], + &match.mask->src.s6_addr[0xC], 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_96_127, - &key->dst.s6_addr[0x0], - &mask->dst.s6_addr[0x0], 4); + &match.key->dst.s6_addr[0x0], + &match.mask->dst.s6_addr[0x0], 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_64_95, - &key->dst.s6_addr[0x4], - &mask->dst.s6_addr[0x4], 4); + &match.key->dst.s6_addr[0x4], + &match.mask->dst.s6_addr[0x4], 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_32_63, - &key->dst.s6_addr[0x8], - &mask->dst.s6_addr[0x8], 4); + &match.key->dst.s6_addr[0x8], + &match.mask->dst.s6_addr[0x8], 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31, - &key->dst.s6_addr[0xC], - &mask->dst.s6_addr[0xC], 4); + &match.key->dst.s6_addr[0xC], + &match.mask->dst.s6_addr[0xC], 4); } static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp, @@ -173,9 +163,10 @@ static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp, struct tc_cls_flower_offload *f, u8 ip_proto) { - struct flow_dissector_key_ports *key, *mask; + const struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_match_ports match; - if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) return 0; if (ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) { @@ -184,16 +175,13 @@ static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp, return -EINVAL; } - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->mask); + flow_rule_match_ports(rule, &match); mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_DST_L4_PORT, - ntohs(key->dst), ntohs(mask->dst)); + ntohs(match.key->dst), + ntohs(match.mask->dst)); mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_SRC_L4_PORT, - ntohs(key->src), ntohs(mask->src)); + ntohs(match.key->src), + ntohs(match.mask->src)); return 0; } @@ -202,9 +190,10 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, struct tc_cls_flower_offload *f, u8 ip_proto) { - struct flow_dissector_key_tcp *key, *mask; + const struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_match_tcp match; - if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) return 0; if (ip_proto != IPPROTO_TCP) { @@ -213,14 +202,11 @@ static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp, return -EINVAL; } - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_TCP, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_TCP, - f->mask); + flow_rule_match_tcp(rule, &match); + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_TCP_FLAGS, - ntohs(key->flags), ntohs(mask->flags)); + ntohs(match.key->flags), + ntohs(match.mask->flags)); return 0; } @@ -229,9 +215,10 @@ static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp, struct tc_cls_flower_offload *f, u16 n_proto) { - struct flow_dissector_key_ip *key, *mask; + const struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_match_ip match; - if (!dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) return 0; if (n_proto != ETH_P_IP && n_proto != ETH_P_IPV6) { @@ -240,20 +227,18 @@ static int mlxsw_sp_flower_parse_ip(struct mlxsw_sp *mlxsw_sp, return -EINVAL; } - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IP, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IP, - f->mask); + flow_rule_match_ip(rule, &match); + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_TTL_, - key->ttl, mask->ttl); + match.key->ttl, match.mask->ttl); mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_ECN, - key->tos & 0x3, mask->tos & 0x3); + match.key->tos & 0x3, + match.mask->tos & 0x3); mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_DSCP, - key->tos >> 6, mask->tos >> 6); + match.key->tos >> 6, + match.mask->tos >> 6); return 0; } @@ -263,13 +248,15 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, struct tc_cls_flower_offload *f) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_dissector *dissector = rule->match.dissector; u16 n_proto_mask = 0; u16 n_proto_key = 0; u16 addr_type = 0; u8 ip_proto = 0; int err; - if (f->dissector->used_keys & + if (dissector->used_keys & ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | BIT(FLOW_DISSECTOR_KEY_BASIC) | BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) | @@ -286,25 +273,19 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_acl_rulei_priority(rulei, f->common.prio); - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { - struct flow_dissector_key_control *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_CONTROL, - f->key); - addr_type = key->addr_type; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control match; + + flow_rule_match_control(rule, &match); + addr_type = match.key->addr_type; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->key); - struct flow_dissector_key_basic *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->mask); - n_proto_key = ntohs(key->n_proto); - n_proto_mask = ntohs(mask->n_proto); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; + + flow_rule_match_basic(rule, &match); + n_proto_key = ntohs(match.key->n_proto); + n_proto_mask = ntohs(match.mask->n_proto); if (n_proto_key == ETH_P_ALL) { n_proto_key = 0; @@ -314,60 +295,53 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, MLXSW_AFK_ELEMENT_ETHERTYPE, n_proto_key, n_proto_mask); - ip_proto = key->ip_proto; + ip_proto = match.key->ip_proto; mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_IP_PROTO, - key->ip_proto, mask->ip_proto); + match.key->ip_proto, + match.mask->ip_proto); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - struct flow_dissector_key_eth_addrs *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->key); - struct flow_dissector_key_eth_addrs *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; + flow_rule_match_eth_addrs(rule, &match); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DMAC_32_47, - key->dst, mask->dst, 2); + match.key->dst, + match.mask->dst, 2); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DMAC_0_31, - key->dst + 2, mask->dst + 2, 4); + match.key->dst + 2, + match.mask->dst + 2, 4); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SMAC_32_47, - key->src, mask->src, 2); + match.key->src, + match.mask->src, 2); mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SMAC_0_31, - key->src + 2, mask->src + 2, 4); + match.key->src + 2, + match.mask->src + 2, 4); } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_dissector_key_vlan *key = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->key); - struct flow_dissector_key_vlan *mask = - skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_VLAN, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; + flow_rule_match_vlan(rule, &match); if (mlxsw_sp_acl_block_is_egress_bound(block)) { NL_SET_ERR_MSG_MOD(f->common.extack, "vlan_id key is not supported on egress"); return -EOPNOTSUPP; } - if (mask->vlan_id != 0) + if (match.mask->vlan_id != 0) mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VID, - key->vlan_id, - mask->vlan_id); - if (mask->vlan_priority != 0) + match.key->vlan_id, + match.mask->vlan_id); + if (match.mask->vlan_priority != 0) mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_PCP, - key->vlan_priority, - mask->vlan_priority); + match.key->vlan_priority, + match.mask->vlan_priority); } if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index 8d54b36afee8..43192640bdd1 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -587,6 +587,7 @@ static int nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow, char *nfp_action, int *a_len, u32 *csum_updated) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); struct nfp_fl_set_ipv6_addr set_ip6_dst, set_ip6_src; struct nfp_fl_set_ipv6_tc_hl_fl set_ip6_tc_hl_fl; struct nfp_fl_set_ip4_ttl_tos set_ip_ttl_tos; @@ -643,13 +644,11 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow, return err; } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *basic; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; - basic = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_BASIC, - flow->key); - ip_proto = basic->ip_proto; + flow_rule_match_basic(rule, &match); + ip_proto = match.key->ip_proto; } if (set_eth.head.len_lw) { diff --git a/drivers/net/ethernet/netronome/nfp/flower/match.c b/drivers/net/ethernet/netronome/nfp/flower/match.c index c04a0d6b0184..1279fa5da9e1 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/match.c +++ b/drivers/net/ethernet/netronome/nfp/flower/match.c @@ -8,31 +8,41 @@ #include "main.h" static void -nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *frame, - struct tc_cls_flower_offload *flow, u8 key_type, - bool mask_version) +nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *ext, + struct nfp_flower_meta_tci *msk, + struct tc_cls_flower_offload *flow, u8 key_type) { - struct fl_flow_key *target = mask_version ? flow->mask : flow->key; - struct flow_dissector_key_vlan *flow_vlan; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); u16 tmp_tci; - memset(frame, 0, sizeof(struct nfp_flower_meta_tci)); + memset(ext, 0, sizeof(struct nfp_flower_meta_tci)); + memset(msk, 0, sizeof(struct nfp_flower_meta_tci)); + /* Populate the metadata frame. */ - frame->nfp_flow_key_layer = key_type; - frame->mask_id = ~0; + ext->nfp_flow_key_layer = key_type; + ext->mask_id = ~0; + + msk->nfp_flow_key_layer = key_type; + msk->mask_id = ~0; - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_VLAN)) { - flow_vlan = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_VLAN, - target); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan match; + + flow_rule_match_vlan(rule, &match); /* Populate the tci field. */ - if (flow_vlan->vlan_id || flow_vlan->vlan_priority) { + if (match.key->vlan_id || match.key->vlan_priority) { + tmp_tci = FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO, + match.key->vlan_priority) | + FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID, + match.key->vlan_id) | + NFP_FLOWER_MASK_VLAN_CFI; + ext->tci = cpu_to_be16(tmp_tci); tmp_tci = FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO, - flow_vlan->vlan_priority) | + match.mask->vlan_priority) | FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID, - flow_vlan->vlan_id) | + match.mask->vlan_id) | NFP_FLOWER_MASK_VLAN_CFI; - frame->tci = cpu_to_be16(tmp_tci); + msk->tci = cpu_to_be16(tmp_tci); } } } @@ -64,231 +74,244 @@ nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port, } static void -nfp_flower_compile_mac(struct nfp_flower_mac_mpls *frame, - struct tc_cls_flower_offload *flow, - bool mask_version) +nfp_flower_compile_mac(struct nfp_flower_mac_mpls *ext, + struct nfp_flower_mac_mpls *msk, + struct tc_cls_flower_offload *flow) { - struct fl_flow_key *target = mask_version ? flow->mask : flow->key; - struct flow_dissector_key_eth_addrs *addr; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); - memset(frame, 0, sizeof(struct nfp_flower_mac_mpls)); + memset(ext, 0, sizeof(struct nfp_flower_mac_mpls)); + memset(msk, 0, sizeof(struct nfp_flower_mac_mpls)); - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { - addr = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ETH_ADDRS, - target); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { + struct flow_match_eth_addrs match; + + flow_rule_match_eth_addrs(rule, &match); /* Populate mac frame. */ - ether_addr_copy(frame->mac_dst, &addr->dst[0]); - ether_addr_copy(frame->mac_src, &addr->src[0]); + ether_addr_copy(ext->mac_dst, &match.key->dst[0]); + ether_addr_copy(ext->mac_src, &match.key->src[0]); + ether_addr_copy(msk->mac_dst, &match.mask->dst[0]); + ether_addr_copy(msk->mac_src, &match.mask->src[0]); } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_MPLS)) { - struct flow_dissector_key_mpls *mpls; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) { + struct flow_match_mpls match; u32 t_mpls; - mpls = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_MPLS, - target); - - t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, mpls->mpls_label) | - FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, mpls->mpls_tc) | - FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, mpls->mpls_bos) | + flow_rule_match_mpls(rule, &match); + t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, match.key->mpls_label) | + FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, match.key->mpls_tc) | + FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, match.key->mpls_bos) | NFP_FLOWER_MASK_MPLS_Q; - - frame->mpls_lse = cpu_to_be32(t_mpls); - } else if (dissector_uses_key(flow->dissector, - FLOW_DISSECTOR_KEY_BASIC)) { + ext->mpls_lse = cpu_to_be32(t_mpls); + t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, match.mask->mpls_label) | + FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, match.mask->mpls_tc) | + FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, match.mask->mpls_bos) | + NFP_FLOWER_MASK_MPLS_Q; + msk->mpls_lse = cpu_to_be32(t_mpls); + } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { /* Check for mpls ether type and set NFP_FLOWER_MASK_MPLS_Q * bit, which indicates an mpls ether type but without any * mpls fields. */ - struct flow_dissector_key_basic *key_basic; - - key_basic = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_BASIC, - flow->key); - if (key_basic->n_proto == cpu_to_be16(ETH_P_MPLS_UC) || - key_basic->n_proto == cpu_to_be16(ETH_P_MPLS_MC)) - frame->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q); + struct flow_match_basic match; + + flow_rule_match_basic(rule, &match); + if (match.key->n_proto == cpu_to_be16(ETH_P_MPLS_UC) || + match.key->n_proto == cpu_to_be16(ETH_P_MPLS_MC)) { + ext->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q); + msk->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q); + } } } static void -nfp_flower_compile_tport(struct nfp_flower_tp_ports *frame, - struct tc_cls_flower_offload *flow, - bool mask_version) +nfp_flower_compile_tport(struct nfp_flower_tp_ports *ext, + struct nfp_flower_tp_ports *msk, + struct tc_cls_flower_offload *flow) { - struct fl_flow_key *target = mask_version ? flow->mask : flow->key; - struct flow_dissector_key_ports *tp; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); - memset(frame, 0, sizeof(struct nfp_flower_tp_ports)); + memset(ext, 0, sizeof(struct nfp_flower_tp_ports)); + memset(msk, 0, sizeof(struct nfp_flower_tp_ports)); - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_PORTS)) { - tp = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_PORTS, - target); - frame->port_src = tp->src; - frame->port_dst = tp->dst; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports match; + + flow_rule_match_ports(rule, &match); + ext->port_src = match.key->src; + ext->port_dst = match.key->dst; + msk->port_src = match.mask->src; + msk->port_dst = match.mask->dst; } } static void -nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *frame, - struct tc_cls_flower_offload *flow, - bool mask_version) +nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext, + struct nfp_flower_ip_ext *msk, + struct tc_cls_flower_offload *flow) { - struct fl_flow_key *target = mask_version ? flow->mask : flow->key; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *basic; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; - basic = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_BASIC, - target); - frame->proto = basic->ip_proto; + flow_rule_match_basic(rule, &match); + ext->proto = match.key->ip_proto; + msk->proto = match.mask->ip_proto; } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_IP)) { - struct flow_dissector_key_ip *flow_ip; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { + struct flow_match_ip match; - flow_ip = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_IP, - target); - frame->tos = flow_ip->tos; - frame->ttl = flow_ip->ttl; + flow_rule_match_ip(rule, &match); + ext->tos = match.key->tos; + ext->ttl = match.key->ttl; + msk->tos = match.mask->tos; + msk->ttl = match.mask->ttl; } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_TCP)) { - struct flow_dissector_key_tcp *tcp; - u32 tcp_flags; - - tcp = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_TCP, target); - tcp_flags = be16_to_cpu(tcp->flags); - - if (tcp_flags & TCPHDR_FIN) - frame->flags |= NFP_FL_TCP_FLAG_FIN; - if (tcp_flags & TCPHDR_SYN) - frame->flags |= NFP_FL_TCP_FLAG_SYN; - if (tcp_flags & TCPHDR_RST) - frame->flags |= NFP_FL_TCP_FLAG_RST; - if (tcp_flags & TCPHDR_PSH) - frame->flags |= NFP_FL_TCP_FLAG_PSH; - if (tcp_flags & TCPHDR_URG) - frame->flags |= NFP_FL_TCP_FLAG_URG; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) { + struct flow_match_tcp match; + u16 tcp_flags; + + flow_rule_match_tcp(rule, &match); + tcp_flags = be16_to_cpu(match.key->flags); + + if (tcp_flags & TCPHDR_FIN) { + ext->flags |= NFP_FL_TCP_FLAG_FIN; + msk->flags |= NFP_FL_TCP_FLAG_FIN; + } + if (tcp_flags & TCPHDR_SYN) { + ext->flags |= NFP_FL_TCP_FLAG_SYN; + msk->flags |= NFP_FL_TCP_FLAG_SYN; + } + if (tcp_flags & TCPHDR_RST) { + ext->flags |= NFP_FL_TCP_FLAG_RST; + msk->flags |= NFP_FL_TCP_FLAG_RST; + } + if (tcp_flags & TCPHDR_PSH) { + ext->flags |= NFP_FL_TCP_FLAG_PSH; + msk->flags |= NFP_FL_TCP_FLAG_PSH; + } + if (tcp_flags & TCPHDR_URG) { + ext->flags |= NFP_FL_TCP_FLAG_URG; + msk->flags |= NFP_FL_TCP_FLAG_URG; + } } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { - struct flow_dissector_key_control *key; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control match; - key = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_CONTROL, - target); - if (key->flags & FLOW_DIS_IS_FRAGMENT) - frame->flags |= NFP_FL_IP_FRAGMENTED; - if (key->flags & FLOW_DIS_FIRST_FRAG) - frame->flags |= NFP_FL_IP_FRAG_FIRST; + flow_rule_match_control(rule, &match); + if (match.key->flags & FLOW_DIS_IS_FRAGMENT) { + ext->flags |= NFP_FL_IP_FRAGMENTED; + msk->flags |= NFP_FL_IP_FRAGMENTED; + } + if (match.key->flags & FLOW_DIS_FIRST_FRAG) { + ext->flags |= NFP_FL_IP_FRAG_FIRST; + msk->flags |= NFP_FL_IP_FRAG_FIRST; + } } } static void -nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *frame, - struct tc_cls_flower_offload *flow, - bool mask_version) +nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext, + struct nfp_flower_ipv4 *msk, + struct tc_cls_flower_offload *flow) { - struct fl_flow_key *target = mask_version ? flow->mask : flow->key; - struct flow_dissector_key_ipv4_addrs *addr; - - memset(frame, 0, sizeof(struct nfp_flower_ipv4)); - - if (dissector_uses_key(flow->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { - addr = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - target); - frame->ipv4_src = addr->src; - frame->ipv4_dst = addr->dst; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); + struct flow_match_ipv4_addrs match; + + memset(ext, 0, sizeof(struct nfp_flower_ipv4)); + memset(msk, 0, sizeof(struct nfp_flower_ipv4)); + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { + flow_rule_match_ipv4_addrs(rule, &match); + ext->ipv4_src = match.key->src; + ext->ipv4_dst = match.key->dst; + msk->ipv4_src = match.mask->src; + msk->ipv4_dst = match.mask->dst; } - nfp_flower_compile_ip_ext(&frame->ip_ext, flow, mask_version); + nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, flow); } static void -nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *frame, - struct tc_cls_flower_offload *flow, - bool mask_version) +nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *ext, + struct nfp_flower_ipv6 *msk, + struct tc_cls_flower_offload *flow) { - struct fl_flow_key *target = mask_version ? flow->mask : flow->key; - struct flow_dissector_key_ipv6_addrs *addr; - - memset(frame, 0, sizeof(struct nfp_flower_ipv6)); - - if (dissector_uses_key(flow->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { - addr = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - target); - frame->ipv6_src = addr->src; - frame->ipv6_dst = addr->dst; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); + + memset(ext, 0, sizeof(struct nfp_flower_ipv6)); + memset(msk, 0, sizeof(struct nfp_flower_ipv6)); + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { + struct flow_match_ipv6_addrs match; + + flow_rule_match_ipv6_addrs(rule, &match); + ext->ipv6_src = match.key->src; + ext->ipv6_dst = match.key->dst; + msk->ipv6_src = match.mask->src; + msk->ipv6_dst = match.mask->dst; } - nfp_flower_compile_ip_ext(&frame->ip_ext, flow, mask_version); + nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, flow); } static int -nfp_flower_compile_geneve_opt(void *key_buf, struct tc_cls_flower_offload *flow, - bool mask_version) +nfp_flower_compile_geneve_opt(void *ext, void *msk, + struct tc_cls_flower_offload *flow) { - struct fl_flow_key *target = mask_version ? flow->mask : flow->key; - struct flow_dissector_key_enc_opts *opts; + struct flow_match_enc_opts match; - opts = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_OPTS, - target); - memcpy(key_buf, opts->data, opts->len); + flow_rule_match_enc_opts(flow->rule, &match); + memcpy(ext, match.key->data, match.key->len); + memcpy(msk, match.mask->data, match.mask->len); return 0; } static void -nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *frame, - struct tc_cls_flower_offload *flow, - bool mask_version) +nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *ext, + struct nfp_flower_ipv4_udp_tun *msk, + struct tc_cls_flower_offload *flow) { - struct fl_flow_key *target = mask_version ? flow->mask : flow->key; - struct flow_dissector_key_ipv4_addrs *tun_ips; - struct flow_dissector_key_keyid *vni; - struct flow_dissector_key_ip *ip; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); - memset(frame, 0, sizeof(struct nfp_flower_ipv4_udp_tun)); + memset(ext, 0, sizeof(struct nfp_flower_ipv4_udp_tun)); + memset(msk, 0, sizeof(struct nfp_flower_ipv4_udp_tun)); - if (dissector_uses_key(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID)) { + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) { + struct flow_match_enc_keyid match; u32 temp_vni; - vni = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_KEYID, - target); - temp_vni = be32_to_cpu(vni->keyid) << NFP_FL_TUN_VNI_OFFSET; - frame->tun_id = cpu_to_be32(temp_vni); + flow_rule_match_enc_keyid(rule, &match); + temp_vni = be32_to_cpu(match.key->keyid) << NFP_FL_TUN_VNI_OFFSET; + ext->tun_id = cpu_to_be32(temp_vni); + temp_vni = be32_to_cpu(match.mask->keyid) << NFP_FL_TUN_VNI_OFFSET; + msk->tun_id = cpu_to_be32(temp_vni); } - if (dissector_uses_key(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) { - tun_ips = - skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, - target); - frame->ip_src = tun_ips->src; - frame->ip_dst = tun_ips->dst; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) { + struct flow_match_ipv4_addrs match; + + flow_rule_match_enc_ipv4_addrs(rule, &match); + ext->ip_src = match.key->src; + ext->ip_dst = match.key->dst; + msk->ip_src = match.mask->src; + msk->ip_dst = match.mask->dst; } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_ENC_IP)) { - ip = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_IP, - target); - frame->tos = ip->tos; - frame->ttl = ip->ttl; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) { + struct flow_match_ip match; + + flow_rule_match_enc_ip(rule, &match); + ext->tos = match.key->tos; + ext->ttl = match.key->ttl; + msk->tos = match.mask->tos; + msk->ttl = match.mask->ttl; } } @@ -313,12 +336,9 @@ int nfp_flower_compile_flow_match(struct nfp_app *app, ext = nfp_flow->unmasked_data; msk = nfp_flow->mask_data; - /* Populate Exact Metadata. */ nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)ext, - flow, key_ls->key_layer, false); - /* Populate Mask Metadata. */ - nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)msk, - flow, key_ls->key_layer, true); + (struct nfp_flower_meta_tci *)msk, + flow, key_ls->key_layer); ext += sizeof(struct nfp_flower_meta_tci); msk += sizeof(struct nfp_flower_meta_tci); @@ -348,45 +368,33 @@ int nfp_flower_compile_flow_match(struct nfp_app *app, msk += sizeof(struct nfp_flower_in_port); if (NFP_FLOWER_LAYER_MAC & key_ls->key_layer) { - /* Populate Exact MAC Data. */ nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)ext, - flow, false); - /* Populate Mask MAC Data. */ - nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)msk, - flow, true); + (struct nfp_flower_mac_mpls *)msk, + flow); ext += sizeof(struct nfp_flower_mac_mpls); msk += sizeof(struct nfp_flower_mac_mpls); } if (NFP_FLOWER_LAYER_TP & key_ls->key_layer) { - /* Populate Exact TP Data. */ nfp_flower_compile_tport((struct nfp_flower_tp_ports *)ext, - flow, false); - /* Populate Mask TP Data. */ - nfp_flower_compile_tport((struct nfp_flower_tp_ports *)msk, - flow, true); + (struct nfp_flower_tp_ports *)msk, + flow); ext += sizeof(struct nfp_flower_tp_ports); msk += sizeof(struct nfp_flower_tp_ports); } if (NFP_FLOWER_LAYER_IPV4 & key_ls->key_layer) { - /* Populate Exact IPv4 Data. */ nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)ext, - flow, false); - /* Populate Mask IPv4 Data. */ - nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)msk, - flow, true); + (struct nfp_flower_ipv4 *)msk, + flow); ext += sizeof(struct nfp_flower_ipv4); msk += sizeof(struct nfp_flower_ipv4); } if (NFP_FLOWER_LAYER_IPV6 & key_ls->key_layer) { - /* Populate Exact IPv4 Data. */ nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)ext, - flow, false); - /* Populate Mask IPv4 Data. */ - nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)msk, - flow, true); + (struct nfp_flower_ipv6 *)msk, + flow); ext += sizeof(struct nfp_flower_ipv6); msk += sizeof(struct nfp_flower_ipv6); } @@ -395,10 +403,7 @@ int nfp_flower_compile_flow_match(struct nfp_app *app, key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE) { __be32 tun_dst; - /* Populate Exact VXLAN Data. */ - nfp_flower_compile_ipv4_udp_tun((void *)ext, flow, false); - /* Populate Mask VXLAN Data. */ - nfp_flower_compile_ipv4_udp_tun((void *)msk, flow, true); + nfp_flower_compile_ipv4_udp_tun((void *)ext, (void *)msk, flow); tun_dst = ((struct nfp_flower_ipv4_udp_tun *)ext)->ip_dst; ext += sizeof(struct nfp_flower_ipv4_udp_tun); msk += sizeof(struct nfp_flower_ipv4_udp_tun); @@ -410,11 +415,7 @@ int nfp_flower_compile_flow_match(struct nfp_app *app, nfp_tunnel_add_ipv4_off(app, tun_dst); if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE_OP) { - err = nfp_flower_compile_geneve_opt(ext, flow, false); - if (err) - return err; - - err = nfp_flower_compile_geneve_opt(msk, flow, true); + err = nfp_flower_compile_geneve_opt(ext, msk, flow); if (err) return err; } diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 2cdbf29ecbe7..74f7ff292052 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -102,23 +102,22 @@ nfp_flower_xmit_flow(struct nfp_app *app, struct nfp_fl_payload *nfp_flow, static bool nfp_flower_check_higher_than_mac(struct tc_cls_flower_offload *f) { - return dissector_uses_key(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS) || - dissector_uses_key(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS) || - dissector_uses_key(f->dissector, - FLOW_DISSECTOR_KEY_PORTS) || - dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ICMP); + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + + return flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) || + flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) || + flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS) || + flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP); } static int -nfp_flower_calc_opt_layer(struct flow_dissector_key_enc_opts *enc_opts, +nfp_flower_calc_opt_layer(struct flow_match_enc_opts *enc_opts, u32 *key_layer_two, int *key_size) { - if (enc_opts->len > NFP_FL_MAX_GENEVE_OPT_KEY) + if (enc_opts->key->len > NFP_FL_MAX_GENEVE_OPT_KEY) return -EOPNOTSUPP; - if (enc_opts->len > 0) { + if (enc_opts->key->len > 0) { *key_layer_two |= NFP_FLOWER_LAYER2_GENEVE_OP; *key_size += sizeof(struct nfp_flower_geneve_options); } @@ -133,20 +132,21 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, struct tc_cls_flower_offload *flow, enum nfp_flower_tun_type *tun_type) { - struct flow_dissector_key_basic *mask_basic = NULL; - struct flow_dissector_key_basic *key_basic = NULL; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); + struct flow_dissector *dissector = rule->match.dissector; + struct flow_match_basic basic = { NULL, NULL}; struct nfp_flower_priv *priv = app->priv; u32 key_layer_two; u8 key_layer; int key_size; int err; - if (flow->dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR) + if (dissector->used_keys & ~NFP_FLOWER_WHITELIST_DISSECTOR) return -EOPNOTSUPP; /* If any tun dissector is used then the required set must be used. */ - if (flow->dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR && - (flow->dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R) + if (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR && + (dissector->used_keys & NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R) != NFP_FLOWER_WHITELIST_TUN_DISSECTOR_R) return -EOPNOTSUPP; @@ -155,76 +155,53 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, key_size = sizeof(struct nfp_flower_meta_tci) + sizeof(struct nfp_flower_in_port); - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS) || - dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_MPLS)) { + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS) || + flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) { key_layer |= NFP_FLOWER_LAYER_MAC; key_size += sizeof(struct nfp_flower_mac_mpls); } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_VLAN)) { - struct flow_dissector_key_vlan *flow_vlan; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + struct flow_match_vlan vlan; - flow_vlan = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_VLAN, - flow->mask); + flow_rule_match_vlan(rule, &vlan); if (!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_PCP) && - flow_vlan->vlan_priority) + vlan.key->vlan_priority) return -EOPNOTSUPP; } - if (dissector_uses_key(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_CONTROL)) { - struct flow_dissector_key_ipv4_addrs *mask_ipv4 = NULL; - struct flow_dissector_key_ports *mask_enc_ports = NULL; - struct flow_dissector_key_enc_opts *enc_op = NULL; - struct flow_dissector_key_ports *enc_ports = NULL; - struct flow_dissector_key_control *mask_enc_ctl = - skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_CONTROL, - flow->mask); - struct flow_dissector_key_control *enc_ctl = - skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_CONTROL, - flow->key); - - if (mask_enc_ctl->addr_type != 0xffff || - enc_ctl->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS) + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL)) { + struct flow_match_enc_opts enc_op = { NULL, NULL }; + struct flow_match_ipv4_addrs ipv4_addrs; + struct flow_match_control enc_ctl; + struct flow_match_ports enc_ports; + + flow_rule_match_enc_control(rule, &enc_ctl); + + if (enc_ctl.mask->addr_type != 0xffff || + enc_ctl.key->addr_type != FLOW_DISSECTOR_KEY_IPV4_ADDRS) return -EOPNOTSUPP; /* These fields are already verified as used. */ - mask_ipv4 = - skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, - flow->mask); - if (mask_ipv4->dst != cpu_to_be32(~0)) + flow_rule_match_enc_ipv4_addrs(rule, &ipv4_addrs); + if (ipv4_addrs.mask->dst != cpu_to_be32(~0)) return -EOPNOTSUPP; - mask_enc_ports = - skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_PORTS, - flow->mask); - enc_ports = - skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_PORTS, - flow->key); - if (mask_enc_ports->dst != cpu_to_be16(~0)) + flow_rule_match_enc_ports(rule, &enc_ports); + if (enc_ports.mask->dst != cpu_to_be16(~0)) return -EOPNOTSUPP; - if (dissector_uses_key(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_OPTS)) { - enc_op = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_ENC_OPTS, - flow->key); - } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_OPTS)) + flow_rule_match_enc_opts(rule, &enc_op); - switch (enc_ports->dst) { + switch (enc_ports.key->dst) { case htons(NFP_FL_VXLAN_PORT): *tun_type = NFP_FL_TUNNEL_VXLAN; key_layer |= NFP_FLOWER_LAYER_VXLAN; key_size += sizeof(struct nfp_flower_ipv4_udp_tun); - if (enc_op) + if (enc_op.key) return -EOPNOTSUPP; break; case htons(NFP_FL_GENEVE_PORT): @@ -236,11 +213,11 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, key_layer_two |= NFP_FLOWER_LAYER2_GENEVE; key_size += sizeof(struct nfp_flower_ipv4_udp_tun); - if (!enc_op) + if (!enc_op.key) break; if (!(priv->flower_ext_feats & NFP_FL_FEATS_GENEVE_OPT)) return -EOPNOTSUPP; - err = nfp_flower_calc_opt_layer(enc_op, &key_layer_two, + err = nfp_flower_calc_opt_layer(&enc_op, &key_layer_two, &key_size); if (err) return err; @@ -254,19 +231,12 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, return -EOPNOTSUPP; } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - mask_basic = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_BASIC, - flow->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) + flow_rule_match_basic(rule, &basic); - key_basic = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_BASIC, - flow->key); - } - - if (mask_basic && mask_basic->n_proto) { + if (basic.mask && basic.mask->n_proto) { /* Ethernet type is present in the key. */ - switch (key_basic->n_proto) { + switch (basic.key->n_proto) { case cpu_to_be16(ETH_P_IP): key_layer |= NFP_FLOWER_LAYER_IPV4; key_size += sizeof(struct nfp_flower_ipv4); @@ -305,9 +275,9 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, } } - if (mask_basic && mask_basic->ip_proto) { + if (basic.mask && basic.mask->ip_proto) { /* Ethernet type is present in the key. */ - switch (key_basic->ip_proto) { + switch (basic.key->ip_proto) { case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_SCTP: @@ -324,14 +294,12 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, } } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_TCP)) { - struct flow_dissector_key_tcp *tcp; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) { + struct flow_match_tcp tcp; u32 tcp_flags; - tcp = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_TCP, - flow->key); - tcp_flags = be16_to_cpu(tcp->flags); + flow_rule_match_tcp(rule, &tcp); + tcp_flags = be16_to_cpu(tcp.key->flags); if (tcp_flags & ~NFP_FLOWER_SUPPORTED_TCPFLAGS) return -EOPNOTSUPP; @@ -347,12 +315,12 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, * space, thus we need to ensure we include a IPv4/IPv6 key * layer if we have not done so already. */ - if (!key_basic) + if (!basic.key) return -EOPNOTSUPP; if (!(key_layer & NFP_FLOWER_LAYER_IPV4) && !(key_layer & NFP_FLOWER_LAYER_IPV6)) { - switch (key_basic->n_proto) { + switch (basic.key->n_proto) { case cpu_to_be16(ETH_P_IP): key_layer |= NFP_FLOWER_LAYER_IPV4; key_size += sizeof(struct nfp_flower_ipv4); @@ -369,14 +337,11 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, } } - if (dissector_uses_key(flow->dissector, FLOW_DISSECTOR_KEY_CONTROL)) { - struct flow_dissector_key_control *key_ctl; - - key_ctl = skb_flow_dissector_target(flow->dissector, - FLOW_DISSECTOR_KEY_CONTROL, - flow->key); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { + struct flow_match_control ctl; - if (key_ctl->flags & ~NFP_FLOWER_SUPPORTED_CTLFLAGS) + flow_rule_match_control(rule, &ctl); + if (ctl.key->flags & ~NFP_FLOWER_SUPPORTED_CTLFLAGS) return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index b16ce7d93caf..81d5b9304229 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -2033,24 +2033,20 @@ qede_tc_parse_ports(struct qede_dev *edev, struct tc_cls_flower_offload *f, struct qede_arfs_tuple *t) { - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) { - struct flow_dissector_key_ports *key, *mask; - - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_PORTS, - f->mask); - - if ((key->src && mask->src != U16_MAX) || - (key->dst && mask->dst != U16_MAX)) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { + struct flow_match_ports match; + + flow_rule_match_ports(rule, &match); + if ((match.key->src && match.mask->src != U16_MAX) || + (match.key->dst && match.mask->dst != U16_MAX)) { DP_NOTICE(edev, "Do not support ports masks\n"); return -EINVAL; } - t->src_port = key->src; - t->dst_port = key->dst; + t->src_port = match.key->src; + t->dst_port = match.key->dst; } return 0; @@ -2061,32 +2057,27 @@ qede_tc_parse_v6_common(struct qede_dev *edev, struct tc_cls_flower_offload *f, struct qede_arfs_tuple *t) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); struct in6_addr zero_addr, addr; memset(&zero_addr, 0, sizeof(addr)); memset(&addr, 0xff, sizeof(addr)); - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { - struct flow_dissector_key_ipv6_addrs *key, *mask; - - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV6_ADDRS, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { + struct flow_match_ipv6_addrs match; - if ((memcmp(&key->src, &zero_addr, sizeof(addr)) && - memcmp(&mask->src, &addr, sizeof(addr))) || - (memcmp(&key->dst, &zero_addr, sizeof(addr)) && - memcmp(&mask->dst, &addr, sizeof(addr)))) { + flow_rule_match_ipv6_addrs(rule, &match); + if ((memcmp(&match.key->src, &zero_addr, sizeof(addr)) && + memcmp(&match.mask->src, &addr, sizeof(addr))) || + (memcmp(&match.key->dst, &zero_addr, sizeof(addr)) && + memcmp(&match.mask->dst, &addr, sizeof(addr)))) { DP_NOTICE(edev, "Do not support IPv6 address prefix/mask\n"); return -EINVAL; } - memcpy(&t->src_ipv6, &key->src, sizeof(addr)); - memcpy(&t->dst_ipv6, &key->dst, sizeof(addr)); + memcpy(&t->src_ipv6, &match.key->src, sizeof(addr)); + memcpy(&t->dst_ipv6, &match.key->dst, sizeof(addr)); } if (qede_tc_parse_ports(edev, f, t)) @@ -2100,24 +2091,20 @@ qede_tc_parse_v4_common(struct qede_dev *edev, struct tc_cls_flower_offload *f, struct qede_arfs_tuple *t) { - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { - struct flow_dissector_key_ipv4_addrs *key, *mask; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->key); - mask = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_IPV4_ADDRS, - f->mask); + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { + struct flow_match_ipv4_addrs match; - if ((key->src && mask->src != U32_MAX) || - (key->dst && mask->dst != U32_MAX)) { + flow_rule_match_ipv4_addrs(rule, &match); + if ((match.key->src && match.mask->src != U32_MAX) || + (match.key->dst && match.mask->dst != U32_MAX)) { DP_NOTICE(edev, "Do not support ipv4 prefix/masks\n"); return -EINVAL; } - t->src_ipv4 = key->src; - t->dst_ipv4 = key->dst; + t->src_ipv4 = match.key->src; + t->dst_ipv4 = match.key->dst; } if (qede_tc_parse_ports(edev, f, t)) @@ -2175,19 +2162,21 @@ qede_parse_flower_attr(struct qede_dev *edev, __be16 proto, struct tc_cls_flower_offload *f, struct qede_arfs_tuple *tuple) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); + struct flow_dissector *dissector = rule->match.dissector; int rc = -EINVAL; u8 ip_proto = 0; memset(tuple, 0, sizeof(*tuple)); - if (f->dissector->used_keys & + if (dissector->used_keys & ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | BIT(FLOW_DISSECTOR_KEY_BASIC) | BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | BIT(FLOW_DISSECTOR_KEY_PORTS))) { DP_NOTICE(edev, "Unsupported key set:0x%x\n", - f->dissector->used_keys); + dissector->used_keys); return -EOPNOTSUPP; } @@ -2197,13 +2186,11 @@ qede_parse_flower_attr(struct qede_dev *edev, __be16 proto, return -EPROTONOSUPPORT; } - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { - struct flow_dissector_key_basic *key; + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { + struct flow_match_basic match; - key = skb_flow_dissector_target(f->dissector, - FLOW_DISSECTOR_KEY_BASIC, - f->key); - ip_proto = key->ip_proto; + flow_rule_match_basic(rule, &match); + ip_proto = match.key->ip_proto; } if (ip_proto == IPPROTO_TCP && proto == htons(ETH_P_IP)) diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h new file mode 100644 index 000000000000..461c66595763 --- /dev/null +++ b/include/net/flow_offload.h @@ -0,0 +1,115 @@ +#ifndef _NET_FLOW_OFFLOAD_H +#define _NET_FLOW_OFFLOAD_H + +#include + +struct flow_match { + struct flow_dissector *dissector; + void *mask; + void *key; +}; + +struct flow_match_basic { + struct flow_dissector_key_basic *key, *mask; +}; + +struct flow_match_control { + struct flow_dissector_key_control *key, *mask; +}; + +struct flow_match_eth_addrs { + struct flow_dissector_key_eth_addrs *key, *mask; +}; + +struct flow_match_vlan { + struct flow_dissector_key_vlan *key, *mask; +}; + +struct flow_match_ipv4_addrs { + struct flow_dissector_key_ipv4_addrs *key, *mask; +}; + +struct flow_match_ipv6_addrs { + struct flow_dissector_key_ipv6_addrs *key, *mask; +}; + +struct flow_match_ip { + struct flow_dissector_key_ip *key, *mask; +}; + +struct flow_match_ports { + struct flow_dissector_key_ports *key, *mask; +}; + +struct flow_match_icmp { + struct flow_dissector_key_icmp *key, *mask; +}; + +struct flow_match_tcp { + struct flow_dissector_key_tcp *key, *mask; +}; + +struct flow_match_mpls { + struct flow_dissector_key_mpls *key, *mask; +}; + +struct flow_match_enc_keyid { + struct flow_dissector_key_keyid *key, *mask; +}; + +struct flow_match_enc_opts { + struct flow_dissector_key_enc_opts *key, *mask; +}; + +struct flow_rule; + +void flow_rule_match_basic(const struct flow_rule *rule, + struct flow_match_basic *out); +void flow_rule_match_control(const struct flow_rule *rule, + struct flow_match_control *out); +void flow_rule_match_eth_addrs(const struct flow_rule *rule, + struct flow_match_eth_addrs *out); +void flow_rule_match_vlan(const struct flow_rule *rule, + struct flow_match_vlan *out); +void flow_rule_match_ipv4_addrs(const struct flow_rule *rule, + struct flow_match_ipv4_addrs *out); +void flow_rule_match_ipv6_addrs(const struct flow_rule *rule, + struct flow_match_ipv6_addrs *out); +void flow_rule_match_ip(const struct flow_rule *rule, + struct flow_match_ip *out); +void flow_rule_match_ports(const struct flow_rule *rule, + struct flow_match_ports *out); +void flow_rule_match_tcp(const struct flow_rule *rule, + struct flow_match_tcp *out); +void flow_rule_match_icmp(const struct flow_rule *rule, + struct flow_match_icmp *out); +void flow_rule_match_mpls(const struct flow_rule *rule, + struct flow_match_mpls *out); +void flow_rule_match_enc_control(const struct flow_rule *rule, + struct flow_match_control *out); +void flow_rule_match_enc_ipv4_addrs(const struct flow_rule *rule, + struct flow_match_ipv4_addrs *out); +void flow_rule_match_enc_ipv6_addrs(const struct flow_rule *rule, + struct flow_match_ipv6_addrs *out); +void flow_rule_match_enc_ip(const struct flow_rule *rule, + struct flow_match_ip *out); +void flow_rule_match_enc_ports(const struct flow_rule *rule, + struct flow_match_ports *out); +void flow_rule_match_enc_keyid(const struct flow_rule *rule, + struct flow_match_enc_keyid *out); +void flow_rule_match_enc_opts(const struct flow_rule *rule, + struct flow_match_enc_opts *out); + +struct flow_rule { + struct flow_match match; +}; + +struct flow_rule *flow_rule_alloc(void); + +static inline bool flow_rule_match_key(const struct flow_rule *rule, + enum flow_dissector_key_id key) +{ + return dissector_uses_key(rule->match.dissector, key); +} + +#endif /* _NET_FLOW_OFFLOAD_H */ diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 40965fbbcd31..04b64523cc32 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -6,6 +6,7 @@ #include #include #include +#include /* TC action not accessible from user space */ #define TC_ACT_REINSERT (TC_ACT_VALUE_MAX + 1) @@ -760,13 +761,17 @@ struct tc_cls_flower_offload { struct tc_cls_common_offload common; enum tc_fl_command command; unsigned long cookie; - struct flow_dissector *dissector; - struct fl_flow_key *mask; - struct fl_flow_key *key; + struct flow_rule *rule; struct tcf_exts *exts; u32 classid; }; +static inline struct flow_rule * +tc_cls_flower_offload_flow_rule(struct tc_cls_flower_offload *tc_flow_cmd) +{ + return tc_flow_cmd->rule; +} + enum tc_matchall_command { TC_CLSMATCHALL_REPLACE, TC_CLSMATCHALL_DESTROY, diff --git a/net/core/Makefile b/net/core/Makefile index fccd31e0e7f7..f97d6254e564 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \ - fib_notifier.o xdp.o + fib_notifier.o xdp.o flow_offload.o obj-y += net-sysfs.o obj-$(CONFIG_PAGE_POOL) += page_pool.o diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c new file mode 100644 index 000000000000..2fbf6903d2f6 --- /dev/null +++ b/net/core/flow_offload.c @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include +#include + +struct flow_rule *flow_rule_alloc(void) +{ + return kzalloc(sizeof(struct flow_rule), GFP_KERNEL); +} +EXPORT_SYMBOL(flow_rule_alloc); + +#define FLOW_DISSECTOR_MATCH(__rule, __type, __out) \ + const struct flow_match *__m = &(__rule)->match; \ + struct flow_dissector *__d = (__m)->dissector; \ + \ + (__out)->key = skb_flow_dissector_target(__d, __type, (__m)->key); \ + (__out)->mask = skb_flow_dissector_target(__d, __type, (__m)->mask); \ + +void flow_rule_match_basic(const struct flow_rule *rule, + struct flow_match_basic *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_BASIC, out); +} +EXPORT_SYMBOL(flow_rule_match_basic); + +void flow_rule_match_control(const struct flow_rule *rule, + struct flow_match_control *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_CONTROL, out); +} +EXPORT_SYMBOL(flow_rule_match_control); + +void flow_rule_match_eth_addrs(const struct flow_rule *rule, + struct flow_match_eth_addrs *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS, out); +} +EXPORT_SYMBOL(flow_rule_match_eth_addrs); + +void flow_rule_match_vlan(const struct flow_rule *rule, + struct flow_match_vlan *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_VLAN, out); +} +EXPORT_SYMBOL(flow_rule_match_vlan); + +void flow_rule_match_ipv4_addrs(const struct flow_rule *rule, + struct flow_match_ipv4_addrs *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS, out); +} +EXPORT_SYMBOL(flow_rule_match_ipv4_addrs); + +void flow_rule_match_ipv6_addrs(const struct flow_rule *rule, + struct flow_match_ipv6_addrs *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS, out); +} +EXPORT_SYMBOL(flow_rule_match_ipv6_addrs); + +void flow_rule_match_ip(const struct flow_rule *rule, + struct flow_match_ip *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IP, out); +} +EXPORT_SYMBOL(flow_rule_match_ip); + +void flow_rule_match_ports(const struct flow_rule *rule, + struct flow_match_ports *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_PORTS, out); +} +EXPORT_SYMBOL(flow_rule_match_ports); + +void flow_rule_match_tcp(const struct flow_rule *rule, + struct flow_match_tcp *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_TCP, out); +} +EXPORT_SYMBOL(flow_rule_match_tcp); + +void flow_rule_match_icmp(const struct flow_rule *rule, + struct flow_match_icmp *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ICMP, out); +} +EXPORT_SYMBOL(flow_rule_match_icmp); + +void flow_rule_match_mpls(const struct flow_rule *rule, + struct flow_match_mpls *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_MPLS, out); +} +EXPORT_SYMBOL(flow_rule_match_mpls); + +void flow_rule_match_enc_control(const struct flow_rule *rule, + struct flow_match_control *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL, out); +} +EXPORT_SYMBOL(flow_rule_match_enc_control); + +void flow_rule_match_enc_ipv4_addrs(const struct flow_rule *rule, + struct flow_match_ipv4_addrs *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, out); +} +EXPORT_SYMBOL(flow_rule_match_enc_ipv4_addrs); + +void flow_rule_match_enc_ipv6_addrs(const struct flow_rule *rule, + struct flow_match_ipv6_addrs *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, out); +} +EXPORT_SYMBOL(flow_rule_match_enc_ipv6_addrs); + +void flow_rule_match_enc_ip(const struct flow_rule *rule, + struct flow_match_ip *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IP, out); +} +EXPORT_SYMBOL(flow_rule_match_enc_ip); + +void flow_rule_match_enc_ports(const struct flow_rule *rule, + struct flow_match_ports *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_PORTS, out); +} +EXPORT_SYMBOL(flow_rule_match_enc_ports); + +void flow_rule_match_enc_keyid(const struct flow_rule *rule, + struct flow_match_enc_keyid *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_KEYID, out); +} +EXPORT_SYMBOL(flow_rule_match_enc_keyid); + +void flow_rule_match_enc_opts(const struct flow_rule *rule, + struct flow_match_enc_opts *out) +{ + FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_OPTS, out); +} +EXPORT_SYMBOL(flow_rule_match_enc_opts); diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index f6aa57fbbbaf..aaffea0b66e9 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -381,16 +381,22 @@ static int fl_hw_replace_filter(struct tcf_proto *tp, bool skip_sw = tc_skip_sw(f->flags); int err; + cls_flower.rule = flow_rule_alloc(); + if (!cls_flower.rule) + return -ENOMEM; + tc_cls_common_offload_init(&cls_flower.common, tp, f->flags, extack); cls_flower.command = TC_CLSFLOWER_REPLACE; cls_flower.cookie = (unsigned long) f; - cls_flower.dissector = &f->mask->dissector; - cls_flower.mask = &f->mask->key; - cls_flower.key = &f->mkey; + cls_flower.rule->match.dissector = &f->mask->dissector; + cls_flower.rule->match.mask = &f->mask->key; + cls_flower.rule->match.key = &f->mkey; cls_flower.exts = &f->exts; cls_flower.classid = f->res.classid; err = tc_setup_cb_call(block, TC_SETUP_CLSFLOWER, &cls_flower, skip_sw); + kfree(cls_flower.rule); + if (err < 0) { fl_hw_destroy_filter(tp, f, NULL); return err; @@ -1463,18 +1469,24 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, if (tc_skip_hw(f->flags)) continue; + cls_flower.rule = flow_rule_alloc(); + if (!cls_flower.rule) + return -ENOMEM; + tc_cls_common_offload_init(&cls_flower.common, tp, f->flags, extack); cls_flower.command = add ? TC_CLSFLOWER_REPLACE : TC_CLSFLOWER_DESTROY; cls_flower.cookie = (unsigned long)f; - cls_flower.dissector = &mask->dissector; - cls_flower.mask = &mask->key; - cls_flower.key = &f->mkey; + cls_flower.rule->match.dissector = &mask->dissector; + cls_flower.rule->match.mask = &mask->key; + cls_flower.rule->match.key = &f->mkey; cls_flower.exts = &f->exts; cls_flower.classid = f->res.classid; err = cb(TC_SETUP_CLSFLOWER, &cls_flower, cb_priv); + kfree(cls_flower.rule); + if (err) { if (add && tc_skip_sw(f->flags)) return err; @@ -1489,25 +1501,32 @@ static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, return 0; } -static void fl_hw_create_tmplt(struct tcf_chain *chain, - struct fl_flow_tmplt *tmplt) +static int fl_hw_create_tmplt(struct tcf_chain *chain, + struct fl_flow_tmplt *tmplt) { struct tc_cls_flower_offload cls_flower = {}; struct tcf_block *block = chain->block; struct tcf_exts dummy_exts = { 0, }; + cls_flower.rule = flow_rule_alloc(); + if (!cls_flower.rule) + return -ENOMEM; + cls_flower.common.chain_index = chain->index; cls_flower.command = TC_CLSFLOWER_TMPLT_CREATE; cls_flower.cookie = (unsigned long) tmplt; - cls_flower.dissector = &tmplt->dissector; - cls_flower.mask = &tmplt->mask; - cls_flower.key = &tmplt->dummy_key; + cls_flower.rule->match.dissector = &tmplt->dissector; + cls_flower.rule->match.mask = &tmplt->mask; + cls_flower.rule->match.key = &tmplt->dummy_key; cls_flower.exts = &dummy_exts; /* We don't care if driver (any of them) fails to handle this * call. It serves just as a hint for it. */ tc_setup_cb_call(block, TC_SETUP_CLSFLOWER, &cls_flower, false); + kfree(cls_flower.rule); + + return 0; } static void fl_hw_destroy_tmplt(struct tcf_chain *chain, @@ -1551,12 +1570,14 @@ static void *fl_tmplt_create(struct net *net, struct tcf_chain *chain, err = fl_set_key(net, tb, &tmplt->dummy_key, &tmplt->mask, extack); if (err) goto errout_tmplt; - kfree(tb); fl_init_dissector(&tmplt->dissector, &tmplt->mask); - fl_hw_create_tmplt(chain, tmplt); + err = fl_hw_create_tmplt(chain, tmplt); + if (err) + goto errout_tmplt; + kfree(tb); return tmplt; errout_tmplt: -- cgit v1.2.3 From c500c86b0c75da167b59ee82f78e394fd10cb792 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 2 Feb 2019 12:50:44 +0100 Subject: net/mlx5e: support for two independent packet edit actions This patch adds pedit_headers_action structure to store the result of parsing tc pedit actions. Then, it calls alloc_tc_pedit_action() to populate the mlx5e hardware intermediate representation once all actions have been parsed. This patch comes in preparation for the new flow_action infrastructure, where each packet mangling comes in an separated action, ie. not packed as in tc pedit. Signed-off-by: Pablo Neira Ayuso Acked-by: Jiri Pirko Acked-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 81 ++++++++++++++++++------- 1 file changed, 59 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index cd289ce0582d..1c8e8da166bd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1804,6 +1804,12 @@ struct pedit_headers { struct udphdr udp; }; +struct pedit_headers_action { + struct pedit_headers vals; + struct pedit_headers masks; + u32 pedits; +}; + static int pedit_header_offsets[] = { [TCA_PEDIT_KEY_EX_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth), [TCA_PEDIT_KEY_EX_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4), @@ -1815,16 +1821,15 @@ static int pedit_header_offsets[] = { #define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype]) static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset, - struct pedit_headers *masks, - struct pedit_headers *vals) + struct pedit_headers_action *hdrs) { u32 *curr_pmask, *curr_pval; if (hdr_type >= __PEDIT_HDR_TYPE_MAX) goto out_err; - curr_pmask = (u32 *)(pedit_header(masks, hdr_type) + offset); - curr_pval = (u32 *)(pedit_header(vals, hdr_type) + offset); + curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset); + curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset); if (*curr_pmask & mask) /* disallow acting twice on the same location */ goto out_err; @@ -1880,8 +1885,7 @@ static struct mlx5_fields fields[] = { * max from the SW pedit action. On success, it says how many HW actions were * actually parsed. */ -static int offload_pedit_fields(struct pedit_headers *masks, - struct pedit_headers *vals, +static int offload_pedit_fields(struct pedit_headers_action *hdrs, struct mlx5e_tc_flow_parse_attr *parse_attr, struct netlink_ext_ack *extack) { @@ -1896,10 +1900,10 @@ static int offload_pedit_fields(struct pedit_headers *masks, __be16 mask_be16; void *action; - set_masks = &masks[TCA_PEDIT_KEY_EX_CMD_SET]; - add_masks = &masks[TCA_PEDIT_KEY_EX_CMD_ADD]; - set_vals = &vals[TCA_PEDIT_KEY_EX_CMD_SET]; - add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD]; + set_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].masks; + add_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].masks; + set_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].vals; + add_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].vals; action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto); action = parse_attr->mod_hdr_actions; @@ -1995,12 +1999,14 @@ static int offload_pedit_fields(struct pedit_headers *masks, } static int alloc_mod_hdr_actions(struct mlx5e_priv *priv, - const struct tc_action *a, int namespace, + struct pedit_headers_action *hdrs, + int namespace, struct mlx5e_tc_flow_parse_attr *parse_attr) { int nkeys, action_size, max_actions; - nkeys = tcf_pedit_nkeys(a); + nkeys = hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits + + hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits; action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto); if (namespace == MLX5_FLOW_NAMESPACE_FDB) /* FDB offloading */ @@ -2024,18 +2030,15 @@ static const struct pedit_headers zero_masks = {}; static int parse_tc_pedit_action(struct mlx5e_priv *priv, const struct tc_action *a, int namespace, struct mlx5e_tc_flow_parse_attr *parse_attr, + struct pedit_headers_action *hdrs, struct netlink_ext_ack *extack) { - struct pedit_headers masks[__PEDIT_CMD_MAX], vals[__PEDIT_CMD_MAX], *cmd_masks; int nkeys, i, err = -EOPNOTSUPP; u32 mask, val, offset; u8 cmd, htype; nkeys = tcf_pedit_nkeys(a); - memset(masks, 0, sizeof(struct pedit_headers) * __PEDIT_CMD_MAX); - memset(vals, 0, sizeof(struct pedit_headers) * __PEDIT_CMD_MAX); - for (i = 0; i < nkeys; i++) { htype = tcf_pedit_htype(a, i); cmd = tcf_pedit_cmd(a, i); @@ -2056,21 +2059,37 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv, val = tcf_pedit_val(a, i); offset = tcf_pedit_offset(a, i); - err = set_pedit_val(htype, ~mask, val, offset, &masks[cmd], &vals[cmd]); + err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd]); if (err) goto out_err; + + hdrs[cmd].pedits++; } - err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr); + return 0; +out_err: + return err; +} + +static int alloc_tc_pedit_action(struct mlx5e_priv *priv, int namespace, + struct mlx5e_tc_flow_parse_attr *parse_attr, + struct pedit_headers_action *hdrs, + struct netlink_ext_ack *extack) +{ + struct pedit_headers *cmd_masks; + int err; + u8 cmd; + + err = alloc_mod_hdr_actions(priv, hdrs, namespace, parse_attr); if (err) goto out_err; - err = offload_pedit_fields(masks, vals, parse_attr, extack); + err = offload_pedit_fields(hdrs, parse_attr, extack); if (err < 0) goto out_dealloc_parsed_actions; for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) { - cmd_masks = &masks[cmd]; + cmd_masks = &hdrs[cmd].masks; if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) { NL_SET_ERR_MSG_MOD(extack, "attempt to offload an unsupported field"); @@ -2211,6 +2230,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack) { + struct pedit_headers_action hdrs[__PEDIT_CMD_MAX] = {}; struct mlx5_nic_flow_attr *attr = flow->nic_attr; const struct tc_action *a; u32 action = 0; @@ -2232,7 +2252,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, if (is_tcf_pedit(a)) { err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_KERNEL, - parse_attr, extack); + parse_attr, hdrs, extack); if (err) return err; @@ -2286,6 +2306,14 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, return -EINVAL; } + if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits || + hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) { + err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL, + parse_attr, hdrs, extack); + if (err) + return err; + } + attr->action = action; if (!actions_match_supported(priv, exts, parse_attr, flow, extack)) return -EOPNOTSUPP; @@ -2446,6 +2474,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack) { + struct pedit_headers_action hdrs[__PEDIT_CMD_MAX] = {}; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr *attr = flow->esw_attr; struct mlx5e_rep_priv *rpriv = priv->ppriv; @@ -2470,7 +2499,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, if (is_tcf_pedit(a)) { err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB, - parse_attr, extack); + parse_attr, hdrs, extack); if (err) return err; @@ -2605,6 +2634,14 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, return -EINVAL; } + if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits || + hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].pedits) { + err = alloc_tc_pedit_action(priv, MLX5_FLOW_NAMESPACE_KERNEL, + parse_attr, hdrs, extack); + if (err) + return err; + } + attr->action = action; if (!actions_match_supported(priv, exts, parse_attr, flow, extack)) return -EOPNOTSUPP; -- cgit v1.2.3 From 3b1903ef97c080a80ead3a6a2305f55108e08269 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 2 Feb 2019 12:50:47 +0100 Subject: flow_offload: add statistics retrieval infrastructure and use it This patch provides the flow_stats structure that acts as container for tc_cls_flower_offload, then we can use to restore the statistics on the existing TC actions. Hence, tcf_exts_stats_update() is not used from drivers anymore. Signed-off-by: Pablo Neira Ayuso Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 4 ++-- drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 6 +++--- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 2 +- drivers/net/ethernet/netronome/nfp/flower/offload.c | 5 ++--- include/net/flow_offload.h | 14 ++++++++++++++ include/net/pkt_cls.h | 1 + net/sched/cls_flower.c | 4 ++++ 8 files changed, 28 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c index 90a2170c5138..6a87434b7173 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c @@ -1396,8 +1396,8 @@ static int bnxt_tc_get_flow_stats(struct bnxt *bp, lastused = flow->lastused; spin_unlock(&flow->stats_lock); - tcf_exts_stats_update(tc_flow_cmd->exts, stats.bytes, stats.packets, - lastused); + flow_stats_update(&tc_flow_cmd->stats, stats.bytes, stats.packets, + lastused); return 0; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c index 39c5af5dad3d..8a2d66ee1d7b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c @@ -807,9 +807,9 @@ int cxgb4_tc_flower_stats(struct net_device *dev, if (ofld_stats->packet_count != packets) { if (ofld_stats->prev_packet_count != packets) ofld_stats->last_used = jiffies; - tcf_exts_stats_update(cls->exts, bytes - ofld_stats->byte_count, - packets - ofld_stats->packet_count, - ofld_stats->last_used); + flow_stats_update(&cls->stats, bytes - ofld_stats->byte_count, + packets - ofld_stats->packet_count, + ofld_stats->last_used); ofld_stats->packet_count = packets; ofld_stats->byte_count = bytes; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 1c8e8da166bd..c4c6bbcafc68 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3071,7 +3071,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); out: - tcf_exts_stats_update(f->exts, bytes, packets, lastuse); + flow_stats_update(&f->stats, bytes, packets, lastuse); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index a20379e29e02..c090ecb62041 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -460,7 +460,7 @@ int mlxsw_sp_flower_stats(struct mlxsw_sp *mlxsw_sp, if (err) goto err_rule_get_stats; - tcf_exts_stats_update(f->exts, bytes, packets, lastuse); + flow_stats_update(&f->stats, bytes, packets, lastuse); mlxsw_sp_acl_ruleset_put(mlxsw_sp, ruleset); return 0; diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 74f7ff292052..fe1469d201af 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -554,9 +554,8 @@ nfp_flower_get_stats(struct nfp_app *app, struct net_device *netdev, ctx_id = be32_to_cpu(nfp_flow->meta.host_ctx_id); spin_lock_bh(&priv->stats_lock); - tcf_exts_stats_update(flow->exts, priv->stats[ctx_id].bytes, - priv->stats[ctx_id].pkts, - priv->stats[ctx_id].used); + flow_stats_update(&flow->stats, priv->stats[ctx_id].bytes, + priv->stats[ctx_id].pkts, priv->stats[ctx_id].used); priv->stats[ctx_id].pkts = 0; priv->stats[ctx_id].bytes = 0; diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index dabc819b6cc9..f9ce39992dbd 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -179,4 +179,18 @@ static inline bool flow_rule_match_key(const struct flow_rule *rule, return dissector_uses_key(rule->match.dissector, key); } +struct flow_stats { + u64 pkts; + u64 bytes; + u64 lastused; +}; + +static inline void flow_stats_update(struct flow_stats *flow_stats, + u64 bytes, u64 pkts, u64 lastused) +{ + flow_stats->pkts = pkts; + flow_stats->bytes = bytes; + flow_stats->lastused = lastused; +} + #endif /* _NET_FLOW_OFFLOAD_H */ diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index c470c100b926..bea1b1c3ea9b 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -765,6 +765,7 @@ struct tc_cls_flower_offload { enum tc_fl_command command; unsigned long cookie; struct flow_rule *rule; + struct flow_stats stats; struct tcf_exts *exts; u32 classid; }; diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 48c54ef52a98..8ec85056aa0d 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -429,6 +429,10 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f) cls_flower.classid = f->res.classid; tc_setup_cb_call(block, TC_SETUP_CLSFLOWER, &cls_flower, false); + + tcf_exts_stats_update(&f->exts, cls_flower.stats.bytes, + cls_flower.stats.pkts, + cls_flower.stats.lastused); } static bool __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f, -- cgit v1.2.3 From 738678817573ce45698e1bb13222f2e53622c555 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 2 Feb 2019 12:50:48 +0100 Subject: drivers: net: use flow action infrastructure This patch updates drivers to use the new flow action infrastructure. Signed-off-by: Pablo Neira Ayuso Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 74 +++--- .../net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c | 250 +++++++++---------- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 265 ++++++++++----------- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 2 +- .../net/ethernet/mellanox/mlxsw/spectrum_flower.c | 54 +++-- drivers/net/ethernet/netronome/nfp/flower/action.c | 187 ++++++++------- drivers/net/ethernet/qlogic/qede/qede_filter.c | 12 +- 7 files changed, 418 insertions(+), 426 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c index 6a87434b7173..7a1fdad1aea6 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c @@ -61,9 +61,9 @@ static u16 bnxt_flow_get_dst_fid(struct bnxt *pf_bp, struct net_device *dev) static int bnxt_tc_parse_redir(struct bnxt *bp, struct bnxt_tc_actions *actions, - const struct tc_action *tc_act) + const struct flow_action_entry *act) { - struct net_device *dev = tcf_mirred_dev(tc_act); + struct net_device *dev = act->dev; if (!dev) { netdev_info(bp->dev, "no dev in mirred action"); @@ -77,16 +77,16 @@ static int bnxt_tc_parse_redir(struct bnxt *bp, static int bnxt_tc_parse_vlan(struct bnxt *bp, struct bnxt_tc_actions *actions, - const struct tc_action *tc_act) + const struct flow_action_entry *act) { - switch (tcf_vlan_action(tc_act)) { - case TCA_VLAN_ACT_POP: + switch (act->id) { + case FLOW_ACTION_VLAN_POP: actions->flags |= BNXT_TC_ACTION_FLAG_POP_VLAN; break; - case TCA_VLAN_ACT_PUSH: + case FLOW_ACTION_VLAN_PUSH: actions->flags |= BNXT_TC_ACTION_FLAG_PUSH_VLAN; - actions->push_vlan_tci = htons(tcf_vlan_push_vid(tc_act)); - actions->push_vlan_tpid = tcf_vlan_push_proto(tc_act); + actions->push_vlan_tci = htons(act->vlan.vid); + actions->push_vlan_tpid = act->vlan.proto; break; default: return -EOPNOTSUPP; @@ -96,10 +96,10 @@ static int bnxt_tc_parse_vlan(struct bnxt *bp, static int bnxt_tc_parse_tunnel_set(struct bnxt *bp, struct bnxt_tc_actions *actions, - const struct tc_action *tc_act) + const struct flow_action_entry *act) { - struct ip_tunnel_info *tun_info = tcf_tunnel_info(tc_act); - struct ip_tunnel_key *tun_key = &tun_info->key; + const struct ip_tunnel_info *tun_info = act->tunnel; + const struct ip_tunnel_key *tun_key = &tun_info->key; if (ip_tunnel_info_af(tun_info) != AF_INET) { netdev_info(bp->dev, "only IPv4 tunnel-encap is supported"); @@ -113,51 +113,43 @@ static int bnxt_tc_parse_tunnel_set(struct bnxt *bp, static int bnxt_tc_parse_actions(struct bnxt *bp, struct bnxt_tc_actions *actions, - struct tcf_exts *tc_exts) + struct flow_action *flow_action) { - const struct tc_action *tc_act; + struct flow_action_entry *act; int i, rc; - if (!tcf_exts_has_actions(tc_exts)) { + if (!flow_action_has_entries(flow_action)) { netdev_info(bp->dev, "no actions"); return -EINVAL; } - tcf_exts_for_each_action(i, tc_act, tc_exts) { - /* Drop action */ - if (is_tcf_gact_shot(tc_act)) { + flow_action_for_each(i, act, flow_action) { + switch (act->id) { + case FLOW_ACTION_DROP: actions->flags |= BNXT_TC_ACTION_FLAG_DROP; return 0; /* don't bother with other actions */ - } - - /* Redirect action */ - if (is_tcf_mirred_egress_redirect(tc_act)) { - rc = bnxt_tc_parse_redir(bp, actions, tc_act); + case FLOW_ACTION_REDIRECT: + rc = bnxt_tc_parse_redir(bp, actions, act); if (rc) return rc; - continue; - } - - /* Push/pop VLAN */ - if (is_tcf_vlan(tc_act)) { - rc = bnxt_tc_parse_vlan(bp, actions, tc_act); + break; + case FLOW_ACTION_VLAN_POP: + case FLOW_ACTION_VLAN_PUSH: + case FLOW_ACTION_VLAN_MANGLE: + rc = bnxt_tc_parse_vlan(bp, actions, act); if (rc) return rc; - continue; - } - - /* Tunnel encap */ - if (is_tcf_tunnel_set(tc_act)) { - rc = bnxt_tc_parse_tunnel_set(bp, actions, tc_act); + break; + case FLOW_ACTION_TUNNEL_ENCAP: + rc = bnxt_tc_parse_tunnel_set(bp, actions, act); if (rc) return rc; - continue; - } - - /* Tunnel decap */ - if (is_tcf_tunnel_release(tc_act)) { + break; + case FLOW_ACTION_TUNNEL_DECAP: actions->flags |= BNXT_TC_ACTION_FLAG_TUNNEL_DECAP; - continue; + break; + default: + break; } } @@ -308,7 +300,7 @@ static int bnxt_tc_parse_flow(struct bnxt *bp, flow->tun_mask.tp_src = match.mask->src; } - return bnxt_tc_parse_actions(bp, &flow->actions, tc_flow_cmd->exts); + return bnxt_tc_parse_actions(bp, &flow->actions, &rule->action); } static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c index 8a2d66ee1d7b..82a8d1970060 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c @@ -292,7 +292,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val, u32 mask, u32 offset, u8 htype) { switch (htype) { - case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH: + case FLOW_ACT_MANGLE_HDR_TYPE_ETH: switch (offset) { case PEDIT_ETH_DMAC_31_0: fs->newdmac = 1; @@ -310,7 +310,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val, offload_pedit(fs, val, mask, ETH_SMAC_47_16); } break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4: + case FLOW_ACT_MANGLE_HDR_TYPE_IP4: switch (offset) { case PEDIT_IP4_SRC: offload_pedit(fs, val, mask, IP4_SRC); @@ -320,7 +320,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val, } fs->nat_mode = NAT_MODE_ALL; break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6: + case FLOW_ACT_MANGLE_HDR_TYPE_IP6: switch (offset) { case PEDIT_IP6_SRC_31_0: offload_pedit(fs, val, mask, IP6_SRC_31_0); @@ -348,7 +348,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val, } fs->nat_mode = NAT_MODE_ALL; break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP: + case FLOW_ACT_MANGLE_HDR_TYPE_TCP: switch (offset) { case PEDIT_TCP_SPORT_DPORT: if (~mask & PEDIT_TCP_UDP_SPORT_MASK) @@ -361,7 +361,7 @@ static void process_pedit_field(struct ch_filter_specification *fs, u32 val, } fs->nat_mode = NAT_MODE_ALL; break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP: + case FLOW_ACT_MANGLE_HDR_TYPE_UDP: switch (offset) { case PEDIT_UDP_SPORT_DPORT: if (~mask & PEDIT_TCP_UDP_SPORT_MASK) @@ -380,56 +380,63 @@ static void cxgb4_process_flow_actions(struct net_device *in, struct tc_cls_flower_offload *cls, struct ch_filter_specification *fs) { - const struct tc_action *a; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(cls); + struct flow_action_entry *act; int i; - tcf_exts_for_each_action(i, a, cls->exts) { - if (is_tcf_gact_ok(a)) { + flow_action_for_each(i, act, &rule->action) { + switch (act->id) { + case FLOW_ACTION_ACCEPT: fs->action = FILTER_PASS; - } else if (is_tcf_gact_shot(a)) { + break; + case FLOW_ACTION_DROP: fs->action = FILTER_DROP; - } else if (is_tcf_mirred_egress_redirect(a)) { - struct net_device *out = tcf_mirred_dev(a); + break; + case FLOW_ACTION_REDIRECT: { + struct net_device *out = act->dev; struct port_info *pi = netdev_priv(out); fs->action = FILTER_SWITCH; fs->eport = pi->port_id; - } else if (is_tcf_vlan(a)) { - u32 vlan_action = tcf_vlan_action(a); - u8 prio = tcf_vlan_push_prio(a); - u16 vid = tcf_vlan_push_vid(a); + } + break; + case FLOW_ACTION_VLAN_POP: + case FLOW_ACTION_VLAN_PUSH: + case FLOW_ACTION_VLAN_MANGLE: { + u8 prio = act->vlan.prio; + u16 vid = act->vlan.vid; u16 vlan_tci = (prio << VLAN_PRIO_SHIFT) | vid; - - switch (vlan_action) { - case TCA_VLAN_ACT_POP: + switch (act->id) { + case FLOW_ACTION_VLAN_POP: fs->newvlan |= VLAN_REMOVE; break; - case TCA_VLAN_ACT_PUSH: + case FLOW_ACTION_VLAN_PUSH: fs->newvlan |= VLAN_INSERT; fs->vlan = vlan_tci; break; - case TCA_VLAN_ACT_MODIFY: + case FLOW_ACTION_VLAN_MANGLE: fs->newvlan |= VLAN_REWRITE; fs->vlan = vlan_tci; break; default: break; } - } else if (is_tcf_pedit(a)) { + } + break; + case FLOW_ACTION_MANGLE: { u32 mask, val, offset; - int nkeys, i; u8 htype; - nkeys = tcf_pedit_nkeys(a); - for (i = 0; i < nkeys; i++) { - htype = tcf_pedit_htype(a, i); - mask = tcf_pedit_mask(a, i); - val = tcf_pedit_val(a, i); - offset = tcf_pedit_offset(a, i); + htype = act->mangle.htype; + mask = act->mangle.mask; + val = act->mangle.val; + offset = act->mangle.offset; - process_pedit_field(fs, val, mask, offset, - htype); + process_pedit_field(fs, val, mask, offset, htype); } + break; + default: + break; } } } @@ -448,101 +455,89 @@ static bool valid_l4_mask(u32 mask) } static bool valid_pedit_action(struct net_device *dev, - const struct tc_action *a) + const struct flow_action_entry *act) { u32 mask, offset; - u8 cmd, htype; - int nkeys, i; - - nkeys = tcf_pedit_nkeys(a); - for (i = 0; i < nkeys; i++) { - htype = tcf_pedit_htype(a, i); - cmd = tcf_pedit_cmd(a, i); - mask = tcf_pedit_mask(a, i); - offset = tcf_pedit_offset(a, i); - - if (cmd != TCA_PEDIT_KEY_EX_CMD_SET) { - netdev_err(dev, "%s: Unsupported pedit cmd\n", + u8 htype; + + htype = act->mangle.htype; + mask = act->mangle.mask; + offset = act->mangle.offset; + + switch (htype) { + case FLOW_ACT_MANGLE_HDR_TYPE_ETH: + switch (offset) { + case PEDIT_ETH_DMAC_31_0: + case PEDIT_ETH_DMAC_47_32_SMAC_15_0: + case PEDIT_ETH_SMAC_47_16: + break; + default: + netdev_err(dev, "%s: Unsupported pedit field\n", __func__); return false; } - - switch (htype) { - case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH: - switch (offset) { - case PEDIT_ETH_DMAC_31_0: - case PEDIT_ETH_DMAC_47_32_SMAC_15_0: - case PEDIT_ETH_SMAC_47_16: - break; - default: - netdev_err(dev, "%s: Unsupported pedit field\n", - __func__); - return false; - } - break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4: - switch (offset) { - case PEDIT_IP4_SRC: - case PEDIT_IP4_DST: - break; - default: - netdev_err(dev, "%s: Unsupported pedit field\n", - __func__); - return false; - } + break; + case FLOW_ACT_MANGLE_HDR_TYPE_IP4: + switch (offset) { + case PEDIT_IP4_SRC: + case PEDIT_IP4_DST: break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6: - switch (offset) { - case PEDIT_IP6_SRC_31_0: - case PEDIT_IP6_SRC_63_32: - case PEDIT_IP6_SRC_95_64: - case PEDIT_IP6_SRC_127_96: - case PEDIT_IP6_DST_31_0: - case PEDIT_IP6_DST_63_32: - case PEDIT_IP6_DST_95_64: - case PEDIT_IP6_DST_127_96: - break; - default: - netdev_err(dev, "%s: Unsupported pedit field\n", - __func__); - return false; - } + default: + netdev_err(dev, "%s: Unsupported pedit field\n", + __func__); + return false; + } + break; + case FLOW_ACT_MANGLE_HDR_TYPE_IP6: + switch (offset) { + case PEDIT_IP6_SRC_31_0: + case PEDIT_IP6_SRC_63_32: + case PEDIT_IP6_SRC_95_64: + case PEDIT_IP6_SRC_127_96: + case PEDIT_IP6_DST_31_0: + case PEDIT_IP6_DST_63_32: + case PEDIT_IP6_DST_95_64: + case PEDIT_IP6_DST_127_96: break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP: - switch (offset) { - case PEDIT_TCP_SPORT_DPORT: - if (!valid_l4_mask(~mask)) { - netdev_err(dev, "%s: Unsupported mask for TCP L4 ports\n", - __func__); - return false; - } - break; - default: - netdev_err(dev, "%s: Unsupported pedit field\n", + default: + netdev_err(dev, "%s: Unsupported pedit field\n", + __func__); + return false; + } + break; + case FLOW_ACT_MANGLE_HDR_TYPE_TCP: + switch (offset) { + case PEDIT_TCP_SPORT_DPORT: + if (!valid_l4_mask(~mask)) { + netdev_err(dev, "%s: Unsupported mask for TCP L4 ports\n", __func__); return false; } break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP: - switch (offset) { - case PEDIT_UDP_SPORT_DPORT: - if (!valid_l4_mask(~mask)) { - netdev_err(dev, "%s: Unsupported mask for UDP L4 ports\n", - __func__); - return false; - } - break; - default: - netdev_err(dev, "%s: Unsupported pedit field\n", + default: + netdev_err(dev, "%s: Unsupported pedit field\n", + __func__); + return false; + } + break; + case FLOW_ACT_MANGLE_HDR_TYPE_UDP: + switch (offset) { + case PEDIT_UDP_SPORT_DPORT: + if (!valid_l4_mask(~mask)) { + netdev_err(dev, "%s: Unsupported mask for UDP L4 ports\n", __func__); return false; } break; default: - netdev_err(dev, "%s: Unsupported pedit type\n", + netdev_err(dev, "%s: Unsupported pedit field\n", __func__); return false; } + break; + default: + netdev_err(dev, "%s: Unsupported pedit type\n", __func__); + return false; } return true; } @@ -550,24 +545,26 @@ static bool valid_pedit_action(struct net_device *dev, static int cxgb4_validate_flow_actions(struct net_device *dev, struct tc_cls_flower_offload *cls) { - const struct tc_action *a; + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(cls); + struct flow_action_entry *act; bool act_redir = false; bool act_pedit = false; bool act_vlan = false; int i; - tcf_exts_for_each_action(i, a, cls->exts) { - if (is_tcf_gact_ok(a)) { - /* Do nothing */ - } else if (is_tcf_gact_shot(a)) { + flow_action_for_each(i, act, &rule->action) { + switch (act->id) { + case FLOW_ACTION_ACCEPT: + case FLOW_ACTION_DROP: /* Do nothing */ - } else if (is_tcf_mirred_egress_redirect(a)) { + break; + case FLOW_ACTION_REDIRECT: { struct adapter *adap = netdev2adap(dev); struct net_device *n_dev, *target_dev; unsigned int i; bool found = false; - target_dev = tcf_mirred_dev(a); + target_dev = act->dev; for_each_port(adap, i) { n_dev = adap->port[i]; if (target_dev == n_dev) { @@ -585,15 +582,18 @@ static int cxgb4_validate_flow_actions(struct net_device *dev, return -EINVAL; } act_redir = true; - } else if (is_tcf_vlan(a)) { - u16 proto = be16_to_cpu(tcf_vlan_push_proto(a)); - u32 vlan_action = tcf_vlan_action(a); + } + break; + case FLOW_ACTION_VLAN_POP: + case FLOW_ACTION_VLAN_PUSH: + case FLOW_ACTION_VLAN_MANGLE: { + u16 proto = be16_to_cpu(act->vlan.proto); - switch (vlan_action) { - case TCA_VLAN_ACT_POP: + switch (act->id) { + case FLOW_ACTION_VLAN_POP: break; - case TCA_VLAN_ACT_PUSH: - case TCA_VLAN_ACT_MODIFY: + case FLOW_ACTION_VLAN_PUSH: + case FLOW_ACTION_VLAN_MANGLE: if (proto != ETH_P_8021Q) { netdev_err(dev, "%s: Unsupported vlan proto\n", __func__); @@ -606,13 +606,17 @@ static int cxgb4_validate_flow_actions(struct net_device *dev, return -EOPNOTSUPP; } act_vlan = true; - } else if (is_tcf_pedit(a)) { - bool pedit_valid = valid_pedit_action(dev, a); + } + break; + case FLOW_ACTION_MANGLE: { + bool pedit_valid = valid_pedit_action(dev, act); if (!pedit_valid) return -EOPNOTSUPP; act_pedit = true; - } else { + } + break; + default: netdev_err(dev, "%s: Unsupported action\n", __func__); return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index c4c6bbcafc68..83522c926d7c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1811,11 +1811,11 @@ struct pedit_headers_action { }; static int pedit_header_offsets[] = { - [TCA_PEDIT_KEY_EX_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth), - [TCA_PEDIT_KEY_EX_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4), - [TCA_PEDIT_KEY_EX_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6), - [TCA_PEDIT_KEY_EX_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp), - [TCA_PEDIT_KEY_EX_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp), + [FLOW_ACT_MANGLE_HDR_TYPE_ETH] = offsetof(struct pedit_headers, eth), + [FLOW_ACT_MANGLE_HDR_TYPE_IP4] = offsetof(struct pedit_headers, ip4), + [FLOW_ACT_MANGLE_HDR_TYPE_IP6] = offsetof(struct pedit_headers, ip6), + [FLOW_ACT_MANGLE_HDR_TYPE_TCP] = offsetof(struct pedit_headers, tcp), + [FLOW_ACT_MANGLE_HDR_TYPE_UDP] = offsetof(struct pedit_headers, udp), }; #define pedit_header(_ph, _htype) ((void *)(_ph) + pedit_header_offsets[_htype]) @@ -1825,7 +1825,7 @@ static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset, { u32 *curr_pmask, *curr_pval; - if (hdr_type >= __PEDIT_HDR_TYPE_MAX) + if (hdr_type >= 2) goto out_err; curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset); @@ -1900,10 +1900,10 @@ static int offload_pedit_fields(struct pedit_headers_action *hdrs, __be16 mask_be16; void *action; - set_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].masks; - add_masks = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].masks; - set_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_SET].vals; - add_vals = &hdrs[TCA_PEDIT_KEY_EX_CMD_ADD].vals; + set_masks = &hdrs[0].masks; + add_masks = &hdrs[1].masks; + set_vals = &hdrs[0].vals; + add_vals = &hdrs[1].vals; action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto); action = parse_attr->mod_hdr_actions; @@ -2028,43 +2028,33 @@ static int alloc_mod_hdr_actions(struct mlx5e_priv *priv, static const struct pedit_headers zero_masks = {}; static int parse_tc_pedit_action(struct mlx5e_priv *priv, - const struct tc_action *a, int namespace, + const struct flow_action_entry *act, int namespace, struct mlx5e_tc_flow_parse_attr *parse_attr, struct pedit_headers_action *hdrs, struct netlink_ext_ack *extack) { - int nkeys, i, err = -EOPNOTSUPP; + u8 cmd = (act->id == FLOW_ACTION_MANGLE) ? 0 : 1; + int err = -EOPNOTSUPP; u32 mask, val, offset; - u8 cmd, htype; + u8 htype; - nkeys = tcf_pedit_nkeys(a); + htype = act->mangle.htype; + err = -EOPNOTSUPP; /* can't be all optimistic */ - for (i = 0; i < nkeys; i++) { - htype = tcf_pedit_htype(a, i); - cmd = tcf_pedit_cmd(a, i); - err = -EOPNOTSUPP; /* can't be all optimistic */ - - if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK) { - NL_SET_ERR_MSG_MOD(extack, - "legacy pedit isn't offloaded"); - goto out_err; - } - - if (cmd != TCA_PEDIT_KEY_EX_CMD_SET && cmd != TCA_PEDIT_KEY_EX_CMD_ADD) { - NL_SET_ERR_MSG_MOD(extack, "pedit cmd isn't offloaded"); - goto out_err; - } + if (htype == FLOW_ACT_MANGLE_UNSPEC) { + NL_SET_ERR_MSG_MOD(extack, "legacy pedit isn't offloaded"); + goto out_err; + } - mask = tcf_pedit_mask(a, i); - val = tcf_pedit_val(a, i); - offset = tcf_pedit_offset(a, i); + mask = act->mangle.mask; + val = act->mangle.val; + offset = act->mangle.offset; - err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd]); - if (err) - goto out_err; + err = set_pedit_val(htype, ~mask, val, offset, &hdrs[cmd]); + if (err) + goto out_err; - hdrs[cmd].pedits++; - } + hdrs[cmd].pedits++; return 0; out_err: @@ -2139,15 +2129,15 @@ static bool csum_offload_supported(struct mlx5e_priv *priv, } static bool modify_header_match_supported(struct mlx5_flow_spec *spec, - struct tcf_exts *exts, + struct flow_action *flow_action, struct netlink_ext_ack *extack) { - const struct tc_action *a; + const struct flow_action_entry *act; bool modify_ip_header; u8 htype, ip_proto; void *headers_v; u16 ethertype; - int nkeys, i; + int i; headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype); @@ -2157,20 +2147,16 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec, goto out_ok; modify_ip_header = false; - tcf_exts_for_each_action(i, a, exts) { - int k; - - if (!is_tcf_pedit(a)) + flow_action_for_each(i, act, flow_action) { + if (act->id != FLOW_ACTION_MANGLE && + act->id != FLOW_ACTION_ADD) continue; - nkeys = tcf_pedit_nkeys(a); - for (k = 0; k < nkeys; k++) { - htype = tcf_pedit_htype(a, k); - if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 || - htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP6) { - modify_ip_header = true; - break; - } + htype = act->mangle.htype; + if (htype == FLOW_ACT_MANGLE_HDR_TYPE_IP4 || + htype == FLOW_ACT_MANGLE_HDR_TYPE_IP6) { + modify_ip_header = true; + break; } } @@ -2188,7 +2174,7 @@ out_ok: } static bool actions_match_supported(struct mlx5e_priv *priv, - struct tcf_exts *exts, + struct flow_action *flow_action, struct mlx5e_tc_flow_parse_attr *parse_attr, struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack) @@ -2205,7 +2191,8 @@ static bool actions_match_supported(struct mlx5e_priv *priv, return false; if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) - return modify_header_match_supported(&parse_attr->spec, exts, + return modify_header_match_supported(&parse_attr->spec, + flow_action, extack); return true; @@ -2225,53 +2212,50 @@ static bool same_hw_devs(struct mlx5e_priv *priv, struct mlx5e_priv *peer_priv) return (fsystem_guid == psystem_guid); } -static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, +static int parse_tc_nic_actions(struct mlx5e_priv *priv, + struct flow_action *flow_action, struct mlx5e_tc_flow_parse_attr *parse_attr, struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack) { - struct pedit_headers_action hdrs[__PEDIT_CMD_MAX] = {}; struct mlx5_nic_flow_attr *attr = flow->nic_attr; - const struct tc_action *a; + struct pedit_headers_action hdrs[2] = {}; + const struct flow_action_entry *act; u32 action = 0; int err, i; - if (!tcf_exts_has_actions(exts)) + if (!flow_action_has_entries(flow_action)) return -EINVAL; attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG; - tcf_exts_for_each_action(i, a, exts) { - if (is_tcf_gact_shot(a)) { + flow_action_for_each(i, act, flow_action) { + switch (act->id) { + case FLOW_ACTION_DROP: action |= MLX5_FLOW_CONTEXT_ACTION_DROP; if (MLX5_CAP_FLOWTABLE(priv->mdev, flow_table_properties_nic_receive.flow_counter)) action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; - continue; - } - - if (is_tcf_pedit(a)) { - err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_KERNEL, + break; + case FLOW_ACTION_MANGLE: + case FLOW_ACTION_ADD: + err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_KERNEL, parse_attr, hdrs, extack); if (err) return err; action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR | MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; - continue; - } - - if (is_tcf_csum(a)) { + break; + case FLOW_ACTION_CSUM: if (csum_offload_supported(priv, action, - tcf_csum_update_flags(a), + act->csum_flags, extack)) - continue; + break; return -EOPNOTSUPP; - } - - if (is_tcf_mirred_egress_redirect(a)) { - struct net_device *peer_dev = tcf_mirred_dev(a); + case FLOW_ACTION_REDIRECT: { + struct net_device *peer_dev = act->dev; if (priv->netdev->netdev_ops == peer_dev->netdev_ops && same_hw_devs(priv, netdev_priv(peer_dev))) { @@ -2286,11 +2270,10 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, peer_dev->name); return -EINVAL; } - continue; - } - - if (is_tcf_skbedit_mark(a)) { - u32 mark = tcf_skbedit_mark(a); + } + break; + case FLOW_ACTION_MARK: { + u32 mark = act->mark; if (mark & ~MLX5E_TC_FLOW_ID_MASK) { NL_SET_ERR_MSG_MOD(extack, @@ -2300,10 +2283,11 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, attr->flow_tag = mark; action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; - continue; + } + break; + default: + return -EINVAL; } - - return -EINVAL; } if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits || @@ -2315,7 +2299,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, } attr->action = action; - if (!actions_match_supported(priv, exts, parse_attr, flow, extack)) + if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack)) return -EOPNOTSUPP; return 0; @@ -2420,7 +2404,7 @@ out_err: } static int parse_tc_vlan_action(struct mlx5e_priv *priv, - const struct tc_action *a, + const struct flow_action_entry *act, struct mlx5_esw_flow_attr *attr, u32 *action) { @@ -2429,7 +2413,8 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv, if (vlan_idx >= MLX5_FS_VLAN_DEPTH) return -EOPNOTSUPP; - if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) { + switch (act->id) { + case FLOW_ACTION_VLAN_POP: if (vlan_idx) { if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, MLX5_FS_VLAN_DEPTH)) @@ -2439,10 +2424,11 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv, } else { *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP; } - } else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) { - attr->vlan_vid[vlan_idx] = tcf_vlan_push_vid(a); - attr->vlan_prio[vlan_idx] = tcf_vlan_push_prio(a); - attr->vlan_proto[vlan_idx] = tcf_vlan_push_proto(a); + break; + case FLOW_ACTION_VLAN_PUSH: + attr->vlan_vid[vlan_idx] = act->vlan.vid; + attr->vlan_prio[vlan_idx] = act->vlan.prio; + attr->vlan_proto[vlan_idx] = act->vlan.proto; if (!attr->vlan_proto[vlan_idx]) attr->vlan_proto[vlan_idx] = htons(ETH_P_8021Q); @@ -2454,13 +2440,15 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv, *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2; } else { if (!mlx5_eswitch_vlan_actions_supported(priv->mdev, 1) && - (tcf_vlan_push_proto(a) != htons(ETH_P_8021Q) || - tcf_vlan_push_prio(a))) + (act->vlan.proto != htons(ETH_P_8021Q) || + act->vlan.prio)) return -EOPNOTSUPP; *action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; } - } else { /* action is TCA_VLAN_ACT_MODIFY */ + break; + default: + /* action is FLOW_ACT_VLAN_MANGLE */ return -EOPNOTSUPP; } @@ -2469,59 +2457,56 @@ static int parse_tc_vlan_action(struct mlx5e_priv *priv, return 0; } -static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, +static int parse_tc_fdb_actions(struct mlx5e_priv *priv, + struct flow_action *flow_action, struct mlx5e_tc_flow_parse_attr *parse_attr, struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack) { - struct pedit_headers_action hdrs[__PEDIT_CMD_MAX] = {}; + struct pedit_headers_action hdrs[2] = {}; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr *attr = flow->esw_attr; struct mlx5e_rep_priv *rpriv = priv->ppriv; - struct ip_tunnel_info *info = NULL; - const struct tc_action *a; + const struct ip_tunnel_info *info = NULL; + const struct flow_action_entry *act; bool encap = false; u32 action = 0; int err, i; - if (!tcf_exts_has_actions(exts)) + if (!flow_action_has_entries(flow_action)) return -EINVAL; attr->in_rep = rpriv->rep; attr->in_mdev = priv->mdev; - tcf_exts_for_each_action(i, a, exts) { - if (is_tcf_gact_shot(a)) { + flow_action_for_each(i, act, flow_action) { + switch (act->id) { + case FLOW_ACTION_DROP: action |= MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; - continue; - } - - if (is_tcf_pedit(a)) { - err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB, + break; + case FLOW_ACTION_MANGLE: + case FLOW_ACTION_ADD: + err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_FDB, parse_attr, hdrs, extack); if (err) return err; action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; attr->split_count = attr->out_count; - continue; - } - - if (is_tcf_csum(a)) { + break; + case FLOW_ACTION_CSUM: if (csum_offload_supported(priv, action, - tcf_csum_update_flags(a), - extack)) - continue; + act->csum_flags, extack)) + break; return -EOPNOTSUPP; - } - - if (is_tcf_mirred_egress_redirect(a) || is_tcf_mirred_egress_mirror(a)) { + case FLOW_ACTION_REDIRECT: + case FLOW_ACTION_MIRRED: { struct mlx5e_priv *out_priv; struct net_device *out_dev; - out_dev = tcf_mirred_dev(a); + out_dev = act->dev; if (!out_dev) { /* out_dev is NULL when filters with * non-existing mirred device are replayed to @@ -2586,35 +2571,29 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, priv->netdev->name, out_dev->name); return -EINVAL; } - continue; - } - - if (is_tcf_tunnel_set(a)) { - info = tcf_tunnel_info(a); + } + break; + case FLOW_ACTION_TUNNEL_ENCAP: + info = act->tunnel; if (info) encap = true; else return -EOPNOTSUPP; - continue; - } - - if (is_tcf_vlan(a)) { - err = parse_tc_vlan_action(priv, a, attr, &action); + break; + case FLOW_ACTION_VLAN_PUSH: + case FLOW_ACTION_VLAN_POP: + err = parse_tc_vlan_action(priv, act, attr, &action); if (err) return err; attr->split_count = attr->out_count; - continue; - } - - if (is_tcf_tunnel_release(a)) { + break; + case FLOW_ACTION_TUNNEL_DECAP: action |= MLX5_FLOW_CONTEXT_ACTION_DECAP; - continue; - } - - if (is_tcf_gact_goto_chain(a)) { - u32 dest_chain = tcf_gact_goto_chain_index(a); + break; + case FLOW_ACTION_GOTO: { + u32 dest_chain = act->chain_index; u32 max_chain = mlx5_eswitch_get_chain_range(esw); if (dest_chain <= attr->chain) { @@ -2627,11 +2606,11 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, } action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; attr->dest_chain = dest_chain; - - continue; + break; + } + default: + return -EINVAL; } - - return -EINVAL; } if (hdrs[TCA_PEDIT_KEY_EX_CMD_SET].pedits || @@ -2643,7 +2622,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, } attr->action = action; - if (!actions_match_supported(priv, exts, parse_attr, flow, extack)) + if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack)) return -EOPNOTSUPP; if (attr->dest_chain) { @@ -2754,6 +2733,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct mlx5_eswitch_rep *in_rep, struct mlx5_core_dev *in_mdev) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); struct netlink_ext_ack *extack = f->common.extack; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5e_tc_flow_parse_attr *parse_attr; @@ -2775,7 +2755,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, flow->esw_attr->chain = f->common.chain_index; flow->esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16; - err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow, extack); + err = parse_tc_fdb_actions(priv, &rule->action, parse_attr, flow, extack); if (err) goto err_free; @@ -2891,6 +2871,7 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv, struct net_device *filter_dev, struct mlx5e_tc_flow **__flow) { + struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); struct netlink_ext_ack *extack = f->common.extack; struct mlx5e_tc_flow_parse_attr *parse_attr; struct mlx5e_tc_flow *flow; @@ -2913,7 +2894,7 @@ mlx5e_add_nic_flow(struct mlx5e_priv *priv, if (err) goto err_free; - err = parse_tc_nic_actions(priv, f->exts, parse_attr, flow, extack); + err = parse_tc_nic_actions(priv, &rule->action, parse_attr, flow, extack); if (err) goto err_free; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index a69e3462b65e..2649d128a57c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -588,7 +588,7 @@ int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp, { u8 ethertype; - if (action == TCA_VLAN_ACT_MODIFY) { + if (action == FLOW_ACTION_VLAN_MANGLE) { switch (proto) { case ETH_P_8021Q: ethertype = 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index c090ecb62041..9af9f5c1b25c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -17,13 +17,13 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_block *block, struct mlxsw_sp_acl_rule_info *rulei, - struct tcf_exts *exts, + struct flow_action *flow_action, struct netlink_ext_ack *extack) { - const struct tc_action *a; + const struct flow_action_entry *act; int err, i; - if (!tcf_exts_has_actions(exts)) + if (!flow_action_has_entries(flow_action)) return 0; /* Count action is inserted first */ @@ -31,27 +31,31 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, if (err) return err; - tcf_exts_for_each_action(i, a, exts) { - if (is_tcf_gact_ok(a)) { + flow_action_for_each(i, act, flow_action) { + switch (act->id) { + case FLOW_ACTION_ACCEPT: err = mlxsw_sp_acl_rulei_act_terminate(rulei); if (err) { NL_SET_ERR_MSG_MOD(extack, "Cannot append terminate action"); return err; } - } else if (is_tcf_gact_shot(a)) { + break; + case FLOW_ACTION_DROP: err = mlxsw_sp_acl_rulei_act_drop(rulei); if (err) { NL_SET_ERR_MSG_MOD(extack, "Cannot append drop action"); return err; } - } else if (is_tcf_gact_trap(a)) { + break; + case FLOW_ACTION_TRAP: err = mlxsw_sp_acl_rulei_act_trap(rulei); if (err) { NL_SET_ERR_MSG_MOD(extack, "Cannot append trap action"); return err; } - } else if (is_tcf_gact_goto_chain(a)) { - u32 chain_index = tcf_gact_goto_chain_index(a); + break; + case FLOW_ACTION_GOTO: { + u32 chain_index = act->chain_index; struct mlxsw_sp_acl_ruleset *ruleset; u16 group_id; @@ -67,7 +71,9 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, NL_SET_ERR_MSG_MOD(extack, "Cannot append jump action"); return err; } - } else if (is_tcf_mirred_egress_redirect(a)) { + } + break; + case FLOW_ACTION_REDIRECT: { struct net_device *out_dev; struct mlxsw_sp_fid *fid; u16 fid_index; @@ -79,29 +85,34 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, if (err) return err; - out_dev = tcf_mirred_dev(a); + out_dev = act->dev; err = mlxsw_sp_acl_rulei_act_fwd(mlxsw_sp, rulei, out_dev, extack); if (err) return err; - } else if (is_tcf_mirred_egress_mirror(a)) { - struct net_device *out_dev = tcf_mirred_dev(a); + } + break; + case FLOW_ACTION_MIRRED: { + struct net_device *out_dev = act->dev; err = mlxsw_sp_acl_rulei_act_mirror(mlxsw_sp, rulei, block, out_dev, extack); if (err) return err; - } else if (is_tcf_vlan(a)) { - u16 proto = be16_to_cpu(tcf_vlan_push_proto(a)); - u32 action = tcf_vlan_action(a); - u8 prio = tcf_vlan_push_prio(a); - u16 vid = tcf_vlan_push_vid(a); + } + break; + case FLOW_ACTION_VLAN_PUSH: + case FLOW_ACTION_VLAN_POP: { + u16 proto = be16_to_cpu(act->vlan.proto); + u8 prio = act->vlan.prio; + u16 vid = act->vlan.vid; return mlxsw_sp_acl_rulei_act_vlan(mlxsw_sp, rulei, - action, vid, + act->id, vid, proto, prio, extack); - } else { + } + default: NL_SET_ERR_MSG_MOD(extack, "Unsupported action"); dev_err(mlxsw_sp->bus_info->dev, "Unsupported action\n"); return -EOPNOTSUPP; @@ -361,7 +372,8 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp, if (err) return err; - return mlxsw_sp_flower_parse_actions(mlxsw_sp, block, rulei, f->exts, + return mlxsw_sp_flower_parse_actions(mlxsw_sp, block, rulei, + &f->rule->action, f->common.extack); } diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index 43192640bdd1..6b1d56b021ac 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -37,7 +37,7 @@ static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan) static void nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan, - const struct tc_action *action) + const struct flow_action_entry *act) { size_t act_size = sizeof(struct nfp_fl_push_vlan); u16 tmp_push_vlan_tci; @@ -45,17 +45,17 @@ nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan, push_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_VLAN; push_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ; push_vlan->reserved = 0; - push_vlan->vlan_tpid = tcf_vlan_push_proto(action); + push_vlan->vlan_tpid = act->vlan.proto; tmp_push_vlan_tci = - FIELD_PREP(NFP_FL_PUSH_VLAN_PRIO, tcf_vlan_push_prio(action)) | - FIELD_PREP(NFP_FL_PUSH_VLAN_VID, tcf_vlan_push_vid(action)) | + FIELD_PREP(NFP_FL_PUSH_VLAN_PRIO, act->vlan.prio) | + FIELD_PREP(NFP_FL_PUSH_VLAN_VID, act->vlan.vid) | NFP_FL_PUSH_VLAN_CFI; push_vlan->vlan_tci = cpu_to_be16(tmp_push_vlan_tci); } static int -nfp_fl_pre_lag(struct nfp_app *app, const struct tc_action *action, +nfp_fl_pre_lag(struct nfp_app *app, const struct flow_action_entry *act, struct nfp_fl_payload *nfp_flow, int act_len) { size_t act_size = sizeof(struct nfp_fl_pre_lag); @@ -63,7 +63,7 @@ nfp_fl_pre_lag(struct nfp_app *app, const struct tc_action *action, struct net_device *out_dev; int err; - out_dev = tcf_mirred_dev(action); + out_dev = act->dev; if (!out_dev || !netif_is_lag_master(out_dev)) return 0; @@ -92,7 +92,8 @@ nfp_fl_pre_lag(struct nfp_app *app, const struct tc_action *action, static int nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output, - const struct tc_action *action, struct nfp_fl_payload *nfp_flow, + const struct flow_action_entry *act, + struct nfp_fl_payload *nfp_flow, bool last, struct net_device *in_dev, enum nfp_flower_tun_type tun_type, int *tun_out_cnt) { @@ -104,7 +105,7 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output, output->head.jump_id = NFP_FL_ACTION_OPCODE_OUTPUT; output->head.len_lw = act_size >> NFP_FL_LW_SIZ; - out_dev = tcf_mirred_dev(action); + out_dev = act->dev; if (!out_dev) return -EOPNOTSUPP; @@ -155,9 +156,9 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output, static enum nfp_flower_tun_type nfp_fl_get_tun_from_act_l4_port(struct nfp_app *app, - const struct tc_action *action) + const struct flow_action_entry *act) { - struct ip_tunnel_info *tun = tcf_tunnel_info(action); + const struct ip_tunnel_info *tun = act->tunnel; struct nfp_flower_priv *priv = app->priv; switch (tun->key.tp_dst) { @@ -195,9 +196,9 @@ static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len) static int nfp_fl_push_geneve_options(struct nfp_fl_payload *nfp_fl, int *list_len, - const struct tc_action *action) + const struct flow_action_entry *act) { - struct ip_tunnel_info *ip_tun = tcf_tunnel_info(action); + struct ip_tunnel_info *ip_tun = (struct ip_tunnel_info *)act->tunnel; int opt_len, opt_cnt, act_start, tot_push_len; u8 *src = ip_tunnel_info_opts(ip_tun); @@ -259,13 +260,13 @@ nfp_fl_push_geneve_options(struct nfp_fl_payload *nfp_fl, int *list_len, static int nfp_fl_set_ipv4_udp_tun(struct nfp_app *app, struct nfp_fl_set_ipv4_udp_tun *set_tun, - const struct tc_action *action, + const struct flow_action_entry *act, struct nfp_fl_pre_tunnel *pre_tun, enum nfp_flower_tun_type tun_type, struct net_device *netdev) { size_t act_size = sizeof(struct nfp_fl_set_ipv4_udp_tun); - struct ip_tunnel_info *ip_tun = tcf_tunnel_info(action); + const struct ip_tunnel_info *ip_tun = act->tunnel; struct nfp_flower_priv *priv = app->priv; u32 tmp_set_ip_tun_type_index = 0; /* Currently support one pre-tunnel so index is always 0. */ @@ -345,7 +346,7 @@ static void nfp_fl_set_helper32(u32 value, u32 mask, u8 *p_exact, u8 *p_mask) } static int -nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off, +nfp_fl_set_eth(const struct flow_action_entry *act, int idx, u32 off, struct nfp_fl_set_eth *set_eth) { u32 exact, mask; @@ -353,8 +354,8 @@ nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off, if (off + 4 > ETH_ALEN * 2) return -EOPNOTSUPP; - mask = ~tcf_pedit_mask(action, idx); - exact = tcf_pedit_val(action, idx); + mask = ~act->mangle.mask; + exact = act->mangle.val; if (exact & ~mask) return -EOPNOTSUPP; @@ -376,7 +377,7 @@ struct ipv4_ttl_word { }; static int -nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off, +nfp_fl_set_ip4(const struct flow_action_entry *act, int idx, u32 off, struct nfp_fl_set_ip4_addrs *set_ip_addr, struct nfp_fl_set_ip4_ttl_tos *set_ip_ttl_tos) { @@ -387,8 +388,8 @@ nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off, __be32 exact, mask; /* We are expecting tcf_pedit to return a big endian value */ - mask = (__force __be32)~tcf_pedit_mask(action, idx); - exact = (__force __be32)tcf_pedit_val(action, idx); + mask = (__force __be32)~act->mangle.mask; + exact = (__force __be32)act->mangle.val; if (exact & ~mask) return -EOPNOTSUPP; @@ -505,7 +506,7 @@ nfp_fl_set_ip6_hop_limit_flow_label(u32 off, __be32 exact, __be32 mask, } static int -nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off, +nfp_fl_set_ip6(const struct flow_action_entry *act, int idx, u32 off, struct nfp_fl_set_ipv6_addr *ip_dst, struct nfp_fl_set_ipv6_addr *ip_src, struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl) @@ -515,8 +516,8 @@ nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off, u8 word; /* We are expecting tcf_pedit to return a big endian value */ - mask = (__force __be32)~tcf_pedit_mask(action, idx); - exact = (__force __be32)tcf_pedit_val(action, idx); + mask = (__force __be32)~act->mangle.mask; + exact = (__force __be32)act->mangle.val; if (exact & ~mask) return -EOPNOTSUPP; @@ -541,7 +542,7 @@ nfp_fl_set_ip6(const struct tc_action *action, int idx, u32 off, } static int -nfp_fl_set_tport(const struct tc_action *action, int idx, u32 off, +nfp_fl_set_tport(const struct flow_action_entry *act, int idx, u32 off, struct nfp_fl_set_tport *set_tport, int opcode) { u32 exact, mask; @@ -549,8 +550,8 @@ nfp_fl_set_tport(const struct tc_action *action, int idx, u32 off, if (off) return -EOPNOTSUPP; - mask = ~tcf_pedit_mask(action, idx); - exact = tcf_pedit_val(action, idx); + mask = ~act->mangle.mask; + exact = act->mangle.val; if (exact & ~mask) return -EOPNOTSUPP; @@ -584,7 +585,8 @@ static u32 nfp_fl_csum_l4_to_flag(u8 ip_proto) } static int -nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow, +nfp_fl_pedit(const struct flow_action_entry *act, + struct tc_cls_flower_offload *flow, char *nfp_action, int *a_len, u32 *csum_updated) { struct flow_rule *rule = tc_cls_flower_offload_flow_rule(flow); @@ -592,13 +594,13 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow, struct nfp_fl_set_ipv6_tc_hl_fl set_ip6_tc_hl_fl; struct nfp_fl_set_ip4_ttl_tos set_ip_ttl_tos; struct nfp_fl_set_ip4_addrs set_ip_addr; + enum flow_action_mangle_base htype; struct nfp_fl_set_tport set_tport; struct nfp_fl_set_eth set_eth; - enum pedit_header_type htype; - int idx, nkeys, err; size_t act_size = 0; - u32 offset, cmd; u8 ip_proto = 0; + int idx, err; + u32 offset; memset(&set_ip6_tc_hl_fl, 0, sizeof(set_ip6_tc_hl_fl)); memset(&set_ip_ttl_tos, 0, sizeof(set_ip_ttl_tos)); @@ -607,42 +609,35 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow, memset(&set_ip_addr, 0, sizeof(set_ip_addr)); memset(&set_tport, 0, sizeof(set_tport)); memset(&set_eth, 0, sizeof(set_eth)); - nkeys = tcf_pedit_nkeys(action); - for (idx = 0; idx < nkeys; idx++) { - cmd = tcf_pedit_cmd(action, idx); - htype = tcf_pedit_htype(action, idx); - offset = tcf_pedit_offset(action, idx); + htype = act->mangle.htype; + offset = act->mangle.offset; - if (cmd != TCA_PEDIT_KEY_EX_CMD_SET) - return -EOPNOTSUPP; - - switch (htype) { - case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH: - err = nfp_fl_set_eth(action, idx, offset, &set_eth); - break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4: - err = nfp_fl_set_ip4(action, idx, offset, &set_ip_addr, - &set_ip_ttl_tos); - break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6: - err = nfp_fl_set_ip6(action, idx, offset, &set_ip6_dst, - &set_ip6_src, &set_ip6_tc_hl_fl); - break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP: - err = nfp_fl_set_tport(action, idx, offset, &set_tport, - NFP_FL_ACTION_OPCODE_SET_TCP); - break; - case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP: - err = nfp_fl_set_tport(action, idx, offset, &set_tport, - NFP_FL_ACTION_OPCODE_SET_UDP); - break; - default: - return -EOPNOTSUPP; - } - if (err) - return err; + switch (htype) { + case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH: + err = nfp_fl_set_eth(act, idx, offset, &set_eth); + break; + case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4: + err = nfp_fl_set_ip4(act, idx, offset, &set_ip_addr, + &set_ip_ttl_tos); + break; + case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6: + err = nfp_fl_set_ip6(act, idx, offset, &set_ip6_dst, + &set_ip6_src, &set_ip6_tc_hl_fl); + break; + case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP: + err = nfp_fl_set_tport(act, idx, offset, &set_tport, + NFP_FL_ACTION_OPCODE_SET_TCP); + break; + case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP: + err = nfp_fl_set_tport(act, idx, offset, &set_tport, + NFP_FL_ACTION_OPCODE_SET_UDP); + break; + default: + return -EOPNOTSUPP; } + if (err) + return err; if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { struct flow_match_basic match; @@ -732,7 +727,7 @@ nfp_fl_pedit(const struct tc_action *action, struct tc_cls_flower_offload *flow, } static int -nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a, +nfp_flower_output_action(struct nfp_app *app, const struct flow_action_entry *act, struct nfp_fl_payload *nfp_fl, int *a_len, struct net_device *netdev, bool last, enum nfp_flower_tun_type *tun_type, int *tun_out_cnt, @@ -752,7 +747,7 @@ nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a, return -EOPNOTSUPP; output = (struct nfp_fl_output *)&nfp_fl->action_data[*a_len]; - err = nfp_fl_output(app, output, a, nfp_fl, last, netdev, *tun_type, + err = nfp_fl_output(app, output, act, nfp_fl, last, netdev, *tun_type, tun_out_cnt); if (err) return err; @@ -763,7 +758,7 @@ nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a, /* nfp_fl_pre_lag returns -err or size of prelag action added. * This will be 0 if it is not egressing to a lag dev. */ - prelag_size = nfp_fl_pre_lag(app, a, nfp_fl, *a_len); + prelag_size = nfp_fl_pre_lag(app, act, nfp_fl, *a_len); if (prelag_size < 0) return prelag_size; else if (prelag_size > 0 && (!last || *out_cnt)) @@ -777,7 +772,7 @@ nfp_flower_output_action(struct nfp_app *app, const struct tc_action *a, } static int -nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a, +nfp_flower_loop_action(struct nfp_app *app, const struct flow_action_entry *act, struct tc_cls_flower_offload *flow, struct nfp_fl_payload *nfp_fl, int *a_len, struct net_device *netdev, @@ -790,23 +785,25 @@ nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a, struct nfp_fl_pop_vlan *pop_v; int err; - if (is_tcf_gact_shot(a)) { + switch (act->id) { + case FLOW_ACTION_DROP: nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_DROP); - } else if (is_tcf_mirred_egress_redirect(a)) { - err = nfp_flower_output_action(app, a, nfp_fl, a_len, netdev, + break; + case FLOW_ACTION_REDIRECT: + err = nfp_flower_output_action(app, act, nfp_fl, a_len, netdev, true, tun_type, tun_out_cnt, out_cnt, csum_updated); if (err) return err; - - } else if (is_tcf_mirred_egress_mirror(a)) { - err = nfp_flower_output_action(app, a, nfp_fl, a_len, netdev, + break; + case FLOW_ACTION_MIRRED: + err = nfp_flower_output_action(app, act, nfp_fl, a_len, netdev, false, tun_type, tun_out_cnt, out_cnt, csum_updated); if (err) return err; - - } else if (is_tcf_vlan(a) && tcf_vlan_action(a) == TCA_VLAN_ACT_POP) { + break; + case FLOW_ACTION_VLAN_POP: if (*a_len + sizeof(struct nfp_fl_pop_vlan) > NFP_FL_MAX_A_SIZ) return -EOPNOTSUPP; @@ -815,19 +812,21 @@ nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a, nfp_fl_pop_vlan(pop_v); *a_len += sizeof(struct nfp_fl_pop_vlan); - } else if (is_tcf_vlan(a) && tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) { + break; + case FLOW_ACTION_VLAN_PUSH: if (*a_len + sizeof(struct nfp_fl_push_vlan) > NFP_FL_MAX_A_SIZ) return -EOPNOTSUPP; psh_v = (struct nfp_fl_push_vlan *)&nfp_fl->action_data[*a_len]; nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); - nfp_fl_push_vlan(psh_v, a); + nfp_fl_push_vlan(psh_v, act); *a_len += sizeof(struct nfp_fl_push_vlan); - } else if (is_tcf_tunnel_set(a)) { - struct ip_tunnel_info *ip_tun = tcf_tunnel_info(a); + break; + case FLOW_ACTION_TUNNEL_ENCAP: { + const struct ip_tunnel_info *ip_tun = act->tunnel; - *tun_type = nfp_fl_get_tun_from_act_l4_port(app, a); + *tun_type = nfp_fl_get_tun_from_act_l4_port(app, act); if (*tun_type == NFP_FL_TUNNEL_NONE) return -EOPNOTSUPP; @@ -846,32 +845,36 @@ nfp_flower_loop_action(struct nfp_app *app, const struct tc_action *a, nfp_fl->meta.shortcut = cpu_to_be32(NFP_FL_SC_ACT_NULL); *a_len += sizeof(struct nfp_fl_pre_tunnel); - err = nfp_fl_push_geneve_options(nfp_fl, a_len, a); + err = nfp_fl_push_geneve_options(nfp_fl, a_len, act); if (err) return err; set_tun = (void *)&nfp_fl->action_data[*a_len]; - err = nfp_fl_set_ipv4_udp_tun(app, set_tun, a, pre_tun, + err = nfp_fl_set_ipv4_udp_tun(app, set_tun, act, pre_tun, *tun_type, netdev); if (err) return err; *a_len += sizeof(struct nfp_fl_set_ipv4_udp_tun); - } else if (is_tcf_tunnel_release(a)) { + } + break; + case FLOW_ACTION_TUNNEL_DECAP: /* Tunnel decap is handled by default so accept action. */ return 0; - } else if (is_tcf_pedit(a)) { - if (nfp_fl_pedit(a, flow, &nfp_fl->action_data[*a_len], + case FLOW_ACTION_MANGLE: + if (nfp_fl_pedit(act, flow, &nfp_fl->action_data[*a_len], a_len, csum_updated)) return -EOPNOTSUPP; - } else if (is_tcf_csum(a)) { + break; + case FLOW_ACTION_CSUM: /* csum action requests recalc of something we have not fixed */ - if (tcf_csum_update_flags(a) & ~*csum_updated) + if (act->csum_flags & ~*csum_updated) return -EOPNOTSUPP; /* If we will correctly fix the csum we can remove it from the * csum update list. Which will later be used to check support. */ - *csum_updated &= ~tcf_csum_update_flags(a); - } else { + *csum_updated &= ~act->csum_flags; + break; + default: /* Currently we do not handle any other actions. */ return -EOPNOTSUPP; } @@ -886,7 +889,7 @@ int nfp_flower_compile_action(struct nfp_app *app, { int act_len, act_cnt, err, tun_out_cnt, out_cnt, i; enum nfp_flower_tun_type tun_type; - const struct tc_action *a; + struct flow_action_entry *act; u32 csum_updated = 0; memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ); @@ -897,8 +900,8 @@ int nfp_flower_compile_action(struct nfp_app *app, tun_out_cnt = 0; out_cnt = 0; - tcf_exts_for_each_action(i, a, flow->exts) { - err = nfp_flower_loop_action(app, a, flow, nfp_flow, &act_len, + flow_action_for_each(i, act, &flow->rule->action) { + err = nfp_flower_loop_action(app, act, flow, nfp_flow, &act_len, netdev, &tun_type, &tun_out_cnt, &out_cnt, &csum_updated); if (err) diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index 81d5b9304229..833c9ec58a6e 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -2004,21 +2004,21 @@ unlock: } static int qede_parse_actions(struct qede_dev *edev, - struct tcf_exts *exts) + struct flow_action *flow_action) { + const struct flow_action_entry *act; int rc = -EINVAL, num_act = 0, i; - const struct tc_action *a; bool is_drop = false; - if (!tcf_exts_has_actions(exts)) { + if (!flow_action_has_entries(flow_action)) { DP_NOTICE(edev, "No tc actions received\n"); return rc; } - tcf_exts_for_each_action(i, a, exts) { + flow_action_for_each(i, act, flow_action) { num_act++; - if (is_tcf_gact_shot(a)) + if (act->id == FLOW_ACTION_DROP) is_drop = true; } @@ -2235,7 +2235,7 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto, } /* parse tc actions and get the vf_id */ - if (qede_parse_actions(edev, f->exts)) + if (qede_parse_actions(edev, &f->rule->action)) goto unlock; if (qede_flow_find_fltr(edev, &t)) { -- cgit v1.2.3 From e4f7ef54cbd8c8fd808e176c7feb8b614f0034fe Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 2 Feb 2019 12:50:52 +0100 Subject: dsa: bcm_sf2: use flow_rule infrastructure Update this driver to use the flow_rule infrastructure, hence we can use the same code to populate hardware IR from ethtool_rx_flow and the cls_flower interfaces. Signed-off-by: Pablo Neira Ayuso Acked-by: Jiri Pirko Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2_cfp.c | 102 +++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c index e14663ab6dbc..6d8059dc77b7 100644 --- a/drivers/net/dsa/bcm_sf2_cfp.c +++ b/drivers/net/dsa/bcm_sf2_cfp.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "bcm_sf2.h" #include "bcm_sf2_regs.h" @@ -257,7 +258,8 @@ static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv, } static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv, - struct ethtool_tcpip4_spec *v4_spec, + struct flow_dissector_key_ipv4_addrs *addrs, + struct flow_dissector_key_ports *ports, unsigned int slice_num, bool mask) { @@ -278,7 +280,7 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv, * UDF_n_A6 [23:8] * UDF_n_A5 [7:0] */ - reg = be16_to_cpu(v4_spec->pdst) >> 8; + reg = be16_to_cpu(ports->dst) >> 8; if (mask) offset = CORE_CFP_MASK_PORT(3); else @@ -289,9 +291,9 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv, * UDF_n_A4 [23:8] * UDF_n_A3 [7:0] */ - reg = (be16_to_cpu(v4_spec->pdst) & 0xff) << 24 | - (u32)be16_to_cpu(v4_spec->psrc) << 8 | - (be32_to_cpu(v4_spec->ip4dst) & 0x0000ff00) >> 8; + reg = (be16_to_cpu(ports->dst) & 0xff) << 24 | + (u32)be16_to_cpu(ports->src) << 8 | + (be32_to_cpu(addrs->dst) & 0x0000ff00) >> 8; if (mask) offset = CORE_CFP_MASK_PORT(2); else @@ -302,9 +304,9 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv, * UDF_n_A2 [23:8] * UDF_n_A1 [7:0] */ - reg = (u32)(be32_to_cpu(v4_spec->ip4dst) & 0xff) << 24 | - (u32)(be32_to_cpu(v4_spec->ip4dst) >> 16) << 8 | - (be32_to_cpu(v4_spec->ip4src) & 0x0000ff00) >> 8; + reg = (u32)(be32_to_cpu(addrs->dst) & 0xff) << 24 | + (u32)(be32_to_cpu(addrs->dst) >> 16) << 8 | + (be32_to_cpu(addrs->src) & 0x0000ff00) >> 8; if (mask) offset = CORE_CFP_MASK_PORT(1); else @@ -317,8 +319,8 @@ static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv, * Slice ID [3:2] * Slice valid [1:0] */ - reg = (u32)(be32_to_cpu(v4_spec->ip4src) & 0xff) << 24 | - (u32)(be32_to_cpu(v4_spec->ip4src) >> 16) << 8 | + reg = (u32)(be32_to_cpu(addrs->src) & 0xff) << 24 | + (u32)(be32_to_cpu(addrs->src) >> 16) << 8 | SLICE_NUM(slice_num) | SLICE_VALID; if (mask) offset = CORE_CFP_MASK_PORT(0); @@ -332,9 +334,13 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, unsigned int queue_num, struct ethtool_rx_flow_spec *fs) { - struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec; + struct ethtool_rx_flow_spec_input input = {}; const struct cfp_udf_layout *layout; unsigned int slice_num, rule_index; + struct ethtool_rx_flow_rule *flow; + struct flow_match_ipv4_addrs ipv4; + struct flow_match_ports ports; + struct flow_match_ip ip; u8 ip_proto, ip_frag; u8 num_udf; u32 reg; @@ -343,13 +349,9 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, switch (fs->flow_type & ~FLOW_EXT) { case TCP_V4_FLOW: ip_proto = IPPROTO_TCP; - v4_spec = &fs->h_u.tcp_ip4_spec; - v4_m_spec = &fs->m_u.tcp_ip4_spec; break; case UDP_V4_FLOW: ip_proto = IPPROTO_UDP; - v4_spec = &fs->h_u.udp_ip4_spec; - v4_m_spec = &fs->m_u.udp_ip4_spec; break; default: return -EINVAL; @@ -367,11 +369,22 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, if (rule_index > bcm_sf2_cfp_rule_size(priv)) return -ENOSPC; + input.fs = fs; + flow = ethtool_rx_flow_rule_create(&input); + if (IS_ERR(flow)) + return PTR_ERR(flow); + + flow_rule_match_ipv4_addrs(flow->rule, &ipv4); + flow_rule_match_ports(flow->rule, &ports); + flow_rule_match_ip(flow->rule, &ip); + layout = &udf_tcpip4_layout; /* We only use one UDF slice for now */ slice_num = bcm_sf2_get_slice_number(layout, 0); - if (slice_num == UDF_NUM_SLICES) - return -EINVAL; + if (slice_num == UDF_NUM_SLICES) { + ret = -EINVAL; + goto out_err_flow_rule; + } num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices); @@ -398,7 +411,7 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, * Reserved [1] * UDF_Valid[8] [0] */ - core_writel(priv, v4_spec->tos << IPTOS_SHIFT | + core_writel(priv, ip.key->tos << IPTOS_SHIFT | ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT | udf_upper_bits(num_udf), CORE_CFP_DATA_PORT(6)); @@ -417,8 +430,8 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5)); /* Program the match and the mask */ - bcm_sf2_cfp_slice_ipv4(priv, v4_spec, slice_num, false); - bcm_sf2_cfp_slice_ipv4(priv, v4_m_spec, SLICE_NUM_MASK, true); + bcm_sf2_cfp_slice_ipv4(priv, ipv4.key, ports.key, slice_num, false); + bcm_sf2_cfp_slice_ipv4(priv, ipv4.mask, ports.mask, SLICE_NUM_MASK, true); /* Insert into TCAM now */ bcm_sf2_cfp_rule_addr_set(priv, rule_index); @@ -426,14 +439,14 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL); if (ret) { pr_err("TCAM entry at addr %d failed\n", rule_index); - return ret; + goto out_err_flow_rule; } /* Insert into Action and policer RAMs now */ ret = bcm_sf2_cfp_act_pol_set(priv, rule_index, port_num, queue_num, true); if (ret) - return ret; + goto out_err_flow_rule; /* Turn on CFP for this rule now */ reg = core_readl(priv, CORE_CFP_CTL_REG); @@ -446,6 +459,10 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, fs->location = rule_index; return 0; + +out_err_flow_rule: + ethtool_rx_flow_rule_destroy(flow); + return ret; } static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv, @@ -582,8 +599,12 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, struct ethtool_rx_flow_spec *fs) { struct ethtool_tcpip6_spec *v6_spec, *v6_m_spec; + struct ethtool_rx_flow_spec_input input = {}; unsigned int slice_num, rule_index[2]; const struct cfp_udf_layout *layout; + struct ethtool_rx_flow_rule *flow; + struct flow_match_ipv6_addrs ipv6; + struct flow_match_ports ports; u8 ip_proto, ip_frag; int ret = 0; u8 num_udf; @@ -645,6 +666,15 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, goto out_err; } + input.fs = fs; + flow = ethtool_rx_flow_rule_create(&input); + if (IS_ERR(flow)) { + ret = PTR_ERR(flow); + goto out_err; + } + flow_rule_match_ipv6_addrs(flow->rule, &ipv6); + flow_rule_match_ports(flow->rule, &ports); + /* Apply the UDF layout for this filter */ bcm_sf2_cfp_udf_set(priv, layout, slice_num); @@ -688,10 +718,10 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5)); /* Slice the IPv6 source address and port */ - bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6src, v6_spec->psrc, - slice_num, false); - bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6src, v6_m_spec->psrc, - SLICE_NUM_MASK, true); + bcm_sf2_cfp_slice_ipv6(priv, ipv6.key->src.in6_u.u6_addr32, + ports.key->src, slice_num, false); + bcm_sf2_cfp_slice_ipv6(priv, ipv6.mask->src.in6_u.u6_addr32, + ports.mask->src, SLICE_NUM_MASK, true); /* Insert into TCAM now because we need to insert a second rule */ bcm_sf2_cfp_rule_addr_set(priv, rule_index[0]); @@ -699,20 +729,20 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL); if (ret) { pr_err("TCAM entry at addr %d failed\n", rule_index[0]); - goto out_err; + goto out_err_flow_rule; } /* Insert into Action and policer RAMs now */ ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port_num, queue_num, false); if (ret) - goto out_err; + goto out_err_flow_rule; /* Now deal with the second slice to chain this rule */ slice_num = bcm_sf2_get_slice_number(layout, slice_num + 1); if (slice_num == UDF_NUM_SLICES) { ret = -EINVAL; - goto out_err; + goto out_err_flow_rule; } num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices); @@ -748,10 +778,10 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, /* Mask all */ core_writel(priv, 0, CORE_CFP_MASK_PORT(5)); - bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6dst, v6_spec->pdst, slice_num, - false); - bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6dst, v6_m_spec->pdst, - SLICE_NUM_MASK, true); + bcm_sf2_cfp_slice_ipv6(priv, ipv6.key->dst.in6_u.u6_addr32, + ports.key->dst, slice_num, false); + bcm_sf2_cfp_slice_ipv6(priv, ipv6.mask->dst.in6_u.u6_addr32, + ports.key->dst, SLICE_NUM_MASK, true); /* Insert into TCAM now */ bcm_sf2_cfp_rule_addr_set(priv, rule_index[1]); @@ -759,7 +789,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL); if (ret) { pr_err("TCAM entry at addr %d failed\n", rule_index[1]); - goto out_err; + goto out_err_flow_rule; } /* Insert into Action and policer RAMs now, set chain ID to @@ -768,7 +798,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port_num, queue_num, true); if (ret) - goto out_err; + goto out_err_flow_rule; /* Turn on CFP for this rule now */ reg = core_readl(priv, CORE_CFP_CTL_REG); @@ -784,6 +814,8 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, return ret; +out_err_flow_rule: + ethtool_rx_flow_rule_destroy(flow); out_err: clear_bit(rule_index[1], priv->cfp.used); return ret; -- cgit v1.2.3 From 5bdf4120ae9b661b017266beeabdf4b8814b97fe Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 2 Feb 2019 12:50:53 +0100 Subject: qede: place ethtool_rx_flow_spec after code after TC flower codebase This is a preparation patch to reuse the existing TC flower codebase from ethtool_rx_flow_spec. This patch is merely moving the core ethtool_rx_flow_spec parser after tc flower offload driver code so we can skip a few forward function declarations in the follow up patch. Signed-off-by: Pablo Neira Ayuso Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede_filter.c | 264 ++++++++++++------------- 1 file changed, 132 insertions(+), 132 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index 833c9ec58a6e..ed77950f6cf9 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -1791,72 +1791,6 @@ static int qede_flow_spec_to_tuple_udpv6(struct qede_dev *edev, return 0; } -static int qede_flow_spec_to_tuple(struct qede_dev *edev, - struct qede_arfs_tuple *t, - struct ethtool_rx_flow_spec *fs) -{ - memset(t, 0, sizeof(*t)); - - if (qede_flow_spec_validate_unused(edev, fs)) - return -EOPNOTSUPP; - - switch ((fs->flow_type & ~FLOW_EXT)) { - case TCP_V4_FLOW: - return qede_flow_spec_to_tuple_tcpv4(edev, t, fs); - case UDP_V4_FLOW: - return qede_flow_spec_to_tuple_udpv4(edev, t, fs); - case TCP_V6_FLOW: - return qede_flow_spec_to_tuple_tcpv6(edev, t, fs); - case UDP_V6_FLOW: - return qede_flow_spec_to_tuple_udpv6(edev, t, fs); - default: - DP_VERBOSE(edev, NETIF_MSG_IFUP, - "Can't support flow of type %08x\n", fs->flow_type); - return -EOPNOTSUPP; - } - - return 0; -} - -static int qede_flow_spec_validate(struct qede_dev *edev, - struct ethtool_rx_flow_spec *fs, - struct qede_arfs_tuple *t) -{ - if (fs->location >= QEDE_RFS_MAX_FLTR) { - DP_INFO(edev, "Location out-of-bounds\n"); - return -EINVAL; - } - - /* Check location isn't already in use */ - if (test_bit(fs->location, edev->arfs->arfs_fltr_bmap)) { - DP_INFO(edev, "Location already in use\n"); - return -EINVAL; - } - - /* Check if the filtering-mode could support the filter */ - if (edev->arfs->filter_count && - edev->arfs->mode != t->mode) { - DP_INFO(edev, - "flow_spec would require filtering mode %08x, but %08x is configured\n", - t->mode, edev->arfs->filter_count); - return -EINVAL; - } - - /* If drop requested then no need to validate other data */ - if (fs->ring_cookie == RX_CLS_FLOW_DISC) - return 0; - - if (ethtool_get_flow_spec_ring_vf(fs->ring_cookie)) - return 0; - - if (fs->ring_cookie >= QEDE_RSS_COUNT(edev)) { - DP_INFO(edev, "Queue out-of-bounds\n"); - return -EINVAL; - } - - return 0; -} - /* Must be called while qede lock is held */ static struct qede_arfs_fltr_node * qede_flow_find_fltr(struct qede_dev *edev, struct qede_arfs_tuple *t) @@ -1896,72 +1830,6 @@ static void qede_flow_set_destination(struct qede_dev *edev, "Configuring N-tuple for VF 0x%02x\n", n->vfid - 1); } -int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info) -{ - struct ethtool_rx_flow_spec *fsp = &info->fs; - struct qede_arfs_fltr_node *n; - struct qede_arfs_tuple t; - int min_hlen, rc; - - __qede_lock(edev); - - if (!edev->arfs) { - rc = -EPERM; - goto unlock; - } - - /* Translate the flow specification into something fittign our DB */ - rc = qede_flow_spec_to_tuple(edev, &t, fsp); - if (rc) - goto unlock; - - /* Make sure location is valid and filter isn't already set */ - rc = qede_flow_spec_validate(edev, fsp, &t); - if (rc) - goto unlock; - - if (qede_flow_find_fltr(edev, &t)) { - rc = -EINVAL; - goto unlock; - } - - n = kzalloc(sizeof(*n), GFP_KERNEL); - if (!n) { - rc = -ENOMEM; - goto unlock; - } - - min_hlen = qede_flow_get_min_header_size(&t); - n->data = kzalloc(min_hlen, GFP_KERNEL); - if (!n->data) { - kfree(n); - rc = -ENOMEM; - goto unlock; - } - - n->sw_id = fsp->location; - set_bit(n->sw_id, edev->arfs->arfs_fltr_bmap); - n->buf_len = min_hlen; - - memcpy(&n->tuple, &t, sizeof(n->tuple)); - - qede_flow_set_destination(edev, n, fsp); - - /* Build a minimal header according to the flow */ - n->tuple.build_hdr(&n->tuple, n->data); - - rc = qede_enqueue_fltr_and_config_searcher(edev, n, 0); - if (rc) - goto unlock; - - qede_configure_arfs_fltr(edev, n, n->rxq_id, true); - rc = qede_poll_arfs_filter_config(edev, n); -unlock: - __qede_unlock(edev); - - return rc; -} - int qede_delete_flow_filter(struct qede_dev *edev, u64 cookie) { struct qede_arfs_fltr_node *fltr = NULL; @@ -2277,3 +2145,135 @@ unlock: __qede_unlock(edev); return rc; } + +static int qede_flow_spec_validate(struct qede_dev *edev, + struct ethtool_rx_flow_spec *fs, + struct qede_arfs_tuple *t) +{ + if (fs->location >= QEDE_RFS_MAX_FLTR) { + DP_INFO(edev, "Location out-of-bounds\n"); + return -EINVAL; + } + + /* Check location isn't already in use */ + if (test_bit(fs->location, edev->arfs->arfs_fltr_bmap)) { + DP_INFO(edev, "Location already in use\n"); + return -EINVAL; + } + + /* Check if the filtering-mode could support the filter */ + if (edev->arfs->filter_count && + edev->arfs->mode != t->mode) { + DP_INFO(edev, + "flow_spec would require filtering mode %08x, but %08x is configured\n", + t->mode, edev->arfs->filter_count); + return -EINVAL; + } + + /* If drop requested then no need to validate other data */ + if (fs->ring_cookie == RX_CLS_FLOW_DISC) + return 0; + + if (ethtool_get_flow_spec_ring_vf(fs->ring_cookie)) + return 0; + + if (fs->ring_cookie >= QEDE_RSS_COUNT(edev)) { + DP_INFO(edev, "Queue out-of-bounds\n"); + return -EINVAL; + } + + return 0; +} + +static int qede_flow_spec_to_tuple(struct qede_dev *edev, + struct qede_arfs_tuple *t, + struct ethtool_rx_flow_spec *fs) +{ + memset(t, 0, sizeof(*t)); + + if (qede_flow_spec_validate_unused(edev, fs)) + return -EOPNOTSUPP; + + switch ((fs->flow_type & ~FLOW_EXT)) { + case TCP_V4_FLOW: + return qede_flow_spec_to_tuple_tcpv4(edev, t, fs); + case UDP_V4_FLOW: + return qede_flow_spec_to_tuple_udpv4(edev, t, fs); + case TCP_V6_FLOW: + return qede_flow_spec_to_tuple_tcpv6(edev, t, fs); + case UDP_V6_FLOW: + return qede_flow_spec_to_tuple_udpv6(edev, t, fs); + default: + DP_VERBOSE(edev, NETIF_MSG_IFUP, + "Can't support flow of type %08x\n", fs->flow_type); + return -EOPNOTSUPP; + } + + return 0; +} + +int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info) +{ + struct ethtool_rx_flow_spec *fsp = &info->fs; + struct qede_arfs_fltr_node *n; + struct qede_arfs_tuple t; + int min_hlen, rc; + + __qede_lock(edev); + + if (!edev->arfs) { + rc = -EPERM; + goto unlock; + } + + /* Translate the flow specification into something fittign our DB */ + rc = qede_flow_spec_to_tuple(edev, &t, fsp); + if (rc) + goto unlock; + + /* Make sure location is valid and filter isn't already set */ + rc = qede_flow_spec_validate(edev, fsp, &t); + if (rc) + goto unlock; + + if (qede_flow_find_fltr(edev, &t)) { + rc = -EINVAL; + goto unlock; + } + + n = kzalloc(sizeof(*n), GFP_KERNEL); + if (!n) { + rc = -ENOMEM; + goto unlock; + } + + min_hlen = qede_flow_get_min_header_size(&t); + n->data = kzalloc(min_hlen, GFP_KERNEL); + if (!n->data) { + kfree(n); + rc = -ENOMEM; + goto unlock; + } + + n->sw_id = fsp->location; + set_bit(n->sw_id, edev->arfs->arfs_fltr_bmap); + n->buf_len = min_hlen; + + memcpy(&n->tuple, &t, sizeof(n->tuple)); + + qede_flow_set_destination(edev, n, fsp); + + /* Build a minimal header according to the flow */ + n->tuple.build_hdr(&n->tuple, n->data); + + rc = qede_enqueue_fltr_and_config_searcher(edev, n, 0); + if (rc) + goto unlock; + + qede_configure_arfs_fltr(edev, n, n->rxq_id, true); + rc = qede_poll_arfs_filter_config(edev, n); +unlock: + __qede_unlock(edev); + + return rc; +} -- cgit v1.2.3 From 37c5d3efd7f801091d1470d7682be474e0ea2bd0 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 2 Feb 2019 12:50:54 +0100 Subject: qede: use ethtool_rx_flow_rule() to remove duplicated parser code The qede driver supports for ethtool_rx_flow_spec and flower, both codebases look very similar. This patch uses the ethtool_rx_flow_rule() infrastructure to remove the duplicated ethtool_rx_flow_spec parser and consolidate ACL offload support around the flow_rule infrastructure. Furthermore, more code can be consolidated by merging qede_add_cls_rule() and qede_add_tc_flower_fltr(), these two functions also look very similar. This driver currently provides simple ACL support, such as 5-tuple matching, drop policy and queue to CPU. Drivers that support more features can benefit from this infrastructure to save even more redundant codebase. Signed-off-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede_filter.c | 279 +++++++------------------ 1 file changed, 76 insertions(+), 203 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c index ed77950f6cf9..add922b93d2c 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_filter.c +++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c @@ -1665,132 +1665,6 @@ static int qede_set_v6_tuple_to_profile(struct qede_dev *edev, return 0; } -static int qede_flow_spec_to_tuple_ipv4_common(struct qede_dev *edev, - struct qede_arfs_tuple *t, - struct ethtool_rx_flow_spec *fs) -{ - if ((fs->h_u.tcp_ip4_spec.ip4src & - fs->m_u.tcp_ip4_spec.ip4src) != fs->h_u.tcp_ip4_spec.ip4src) { - DP_INFO(edev, "Don't support IP-masks\n"); - return -EOPNOTSUPP; - } - - if ((fs->h_u.tcp_ip4_spec.ip4dst & - fs->m_u.tcp_ip4_spec.ip4dst) != fs->h_u.tcp_ip4_spec.ip4dst) { - DP_INFO(edev, "Don't support IP-masks\n"); - return -EOPNOTSUPP; - } - - if ((fs->h_u.tcp_ip4_spec.psrc & - fs->m_u.tcp_ip4_spec.psrc) != fs->h_u.tcp_ip4_spec.psrc) { - DP_INFO(edev, "Don't support port-masks\n"); - return -EOPNOTSUPP; - } - - if ((fs->h_u.tcp_ip4_spec.pdst & - fs->m_u.tcp_ip4_spec.pdst) != fs->h_u.tcp_ip4_spec.pdst) { - DP_INFO(edev, "Don't support port-masks\n"); - return -EOPNOTSUPP; - } - - if (fs->h_u.tcp_ip4_spec.tos) { - DP_INFO(edev, "Don't support tos\n"); - return -EOPNOTSUPP; - } - - t->eth_proto = htons(ETH_P_IP); - t->src_ipv4 = fs->h_u.tcp_ip4_spec.ip4src; - t->dst_ipv4 = fs->h_u.tcp_ip4_spec.ip4dst; - t->src_port = fs->h_u.tcp_ip4_spec.psrc; - t->dst_port = fs->h_u.tcp_ip4_spec.pdst; - - return qede_set_v4_tuple_to_profile(edev, t); -} - -static int qede_flow_spec_to_tuple_tcpv4(struct qede_dev *edev, - struct qede_arfs_tuple *t, - struct ethtool_rx_flow_spec *fs) -{ - t->ip_proto = IPPROTO_TCP; - - if (qede_flow_spec_to_tuple_ipv4_common(edev, t, fs)) - return -EINVAL; - - return 0; -} - -static int qede_flow_spec_to_tuple_udpv4(struct qede_dev *edev, - struct qede_arfs_tuple *t, - struct ethtool_rx_flow_spec *fs) -{ - t->ip_proto = IPPROTO_UDP; - - if (qede_flow_spec_to_tuple_ipv4_common(edev, t, fs)) - return -EINVAL; - - return 0; -} - -static int qede_flow_spec_to_tuple_ipv6_common(struct qede_dev *edev, - struct qede_arfs_tuple *t, - struct ethtool_rx_flow_spec *fs) -{ - struct in6_addr zero_addr; - - memset(&zero_addr, 0, sizeof(zero_addr)); - - if ((fs->h_u.tcp_ip6_spec.psrc & - fs->m_u.tcp_ip6_spec.psrc) != fs->h_u.tcp_ip6_spec.psrc) { - DP_INFO(edev, "Don't support port-masks\n"); - return -EOPNOTSUPP; - } - - if ((fs->h_u.tcp_ip6_spec.pdst & - fs->m_u.tcp_ip6_spec.pdst) != fs->h_u.tcp_ip6_spec.pdst) { - DP_INFO(edev, "Don't support port-masks\n"); - return -EOPNOTSUPP; - } - - if (fs->h_u.tcp_ip6_spec.tclass) { - DP_INFO(edev, "Don't support tclass\n"); - return -EOPNOTSUPP; - } - - t->eth_proto = htons(ETH_P_IPV6); - memcpy(&t->src_ipv6, &fs->h_u.tcp_ip6_spec.ip6src, - sizeof(struct in6_addr)); - memcpy(&t->dst_ipv6, &fs->h_u.tcp_ip6_spec.ip6dst, - sizeof(struct in6_addr)); - t->src_port = fs->h_u.tcp_ip6_spec.psrc; - t->dst_port = fs->h_u.tcp_ip6_spec.pdst; - - return qede_set_v6_tuple_to_profile(edev, t, &zero_addr); -} - -static int qede_flow_spec_to_tuple_tcpv6(struct qede_dev *edev, - struct qede_arfs_tuple *t, - struct ethtool_rx_flow_spec *fs) -{ - t->ip_proto = IPPROTO_TCP; - - if (qede_flow_spec_to_tuple_ipv6_common(edev, t, fs)) - return -EINVAL; - - return 0; -} - -static int qede_flow_spec_to_tuple_udpv6(struct qede_dev *edev, - struct qede_arfs_tuple *t, - struct ethtool_rx_flow_spec *fs) -{ - t->ip_proto = IPPROTO_UDP; - - if (qede_flow_spec_to_tuple_ipv6_common(edev, t, fs)) - return -EINVAL; - - return 0; -} - /* Must be called while qede lock is held */ static struct qede_arfs_fltr_node * qede_flow_find_fltr(struct qede_dev *edev, struct qede_arfs_tuple *t) @@ -1875,34 +1749,38 @@ static int qede_parse_actions(struct qede_dev *edev, struct flow_action *flow_action) { const struct flow_action_entry *act; - int rc = -EINVAL, num_act = 0, i; - bool is_drop = false; + int i; if (!flow_action_has_entries(flow_action)) { - DP_NOTICE(edev, "No tc actions received\n"); - return rc; + DP_NOTICE(edev, "No actions received\n"); + return -EINVAL; } flow_action_for_each(i, act, flow_action) { - num_act++; + switch (act->id) { + case FLOW_ACTION_DROP: + break; + case FLOW_ACTION_QUEUE: + if (act->queue.vf) + break; - if (act->id == FLOW_ACTION_DROP) - is_drop = true; + if (act->queue.index >= QEDE_RSS_COUNT(edev)) { + DP_INFO(edev, "Queue out-of-bounds\n"); + return -EINVAL; + } + break; + default: + return -EINVAL; + } } - if (num_act == 1 && is_drop) - return 0; - - return rc; + return 0; } static int -qede_tc_parse_ports(struct qede_dev *edev, - struct tc_cls_flower_offload *f, - struct qede_arfs_tuple *t) +qede_flow_parse_ports(struct qede_dev *edev, struct flow_rule *rule, + struct qede_arfs_tuple *t) { - struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); - if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { struct flow_match_ports match; @@ -1921,11 +1799,9 @@ qede_tc_parse_ports(struct qede_dev *edev, } static int -qede_tc_parse_v6_common(struct qede_dev *edev, - struct tc_cls_flower_offload *f, - struct qede_arfs_tuple *t) +qede_flow_parse_v6_common(struct qede_dev *edev, struct flow_rule *rule, + struct qede_arfs_tuple *t) { - struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); struct in6_addr zero_addr, addr; memset(&zero_addr, 0, sizeof(addr)); @@ -1948,19 +1824,16 @@ qede_tc_parse_v6_common(struct qede_dev *edev, memcpy(&t->dst_ipv6, &match.key->dst, sizeof(addr)); } - if (qede_tc_parse_ports(edev, f, t)) + if (qede_flow_parse_ports(edev, rule, t)) return -EINVAL; return qede_set_v6_tuple_to_profile(edev, t, &zero_addr); } static int -qede_tc_parse_v4_common(struct qede_dev *edev, - struct tc_cls_flower_offload *f, +qede_flow_parse_v4_common(struct qede_dev *edev, struct flow_rule *rule, struct qede_arfs_tuple *t) { - struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); - if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { struct flow_match_ipv4_addrs match; @@ -1975,62 +1848,56 @@ qede_tc_parse_v4_common(struct qede_dev *edev, t->dst_ipv4 = match.key->dst; } - if (qede_tc_parse_ports(edev, f, t)) + if (qede_flow_parse_ports(edev, rule, t)) return -EINVAL; return qede_set_v4_tuple_to_profile(edev, t); } static int -qede_tc_parse_tcp_v6(struct qede_dev *edev, - struct tc_cls_flower_offload *f, +qede_flow_parse_tcp_v6(struct qede_dev *edev, struct flow_rule *rule, struct qede_arfs_tuple *tuple) { tuple->ip_proto = IPPROTO_TCP; tuple->eth_proto = htons(ETH_P_IPV6); - return qede_tc_parse_v6_common(edev, f, tuple); + return qede_flow_parse_v6_common(edev, rule, tuple); } static int -qede_tc_parse_tcp_v4(struct qede_dev *edev, - struct tc_cls_flower_offload *f, +qede_flow_parse_tcp_v4(struct qede_dev *edev, struct flow_rule *rule, struct qede_arfs_tuple *tuple) { tuple->ip_proto = IPPROTO_TCP; tuple->eth_proto = htons(ETH_P_IP); - return qede_tc_parse_v4_common(edev, f, tuple); + return qede_flow_parse_v4_common(edev, rule, tuple); } static int -qede_tc_parse_udp_v6(struct qede_dev *edev, - struct tc_cls_flower_offload *f, +qede_flow_parse_udp_v6(struct qede_dev *edev, struct flow_rule *rule, struct qede_arfs_tuple *tuple) { tuple->ip_proto = IPPROTO_UDP; tuple->eth_proto = htons(ETH_P_IPV6); - return qede_tc_parse_v6_common(edev, f, tuple); + return qede_flow_parse_v6_common(edev, rule, tuple); } static int -qede_tc_parse_udp_v4(struct qede_dev *edev, - struct tc_cls_flower_offload *f, +qede_flow_parse_udp_v4(struct qede_dev *edev, struct flow_rule *rule, struct qede_arfs_tuple *tuple) { tuple->ip_proto = IPPROTO_UDP; tuple->eth_proto = htons(ETH_P_IP); - return qede_tc_parse_v4_common(edev, f, tuple); + return qede_flow_parse_v4_common(edev, rule, tuple); } static int -qede_parse_flower_attr(struct qede_dev *edev, __be16 proto, - struct tc_cls_flower_offload *f, - struct qede_arfs_tuple *tuple) +qede_parse_flow_attr(struct qede_dev *edev, __be16 proto, + struct flow_rule *rule, struct qede_arfs_tuple *tuple) { - struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); struct flow_dissector *dissector = rule->match.dissector; int rc = -EINVAL; u8 ip_proto = 0; @@ -2062,15 +1929,15 @@ qede_parse_flower_attr(struct qede_dev *edev, __be16 proto, } if (ip_proto == IPPROTO_TCP && proto == htons(ETH_P_IP)) - rc = qede_tc_parse_tcp_v4(edev, f, tuple); + rc = qede_flow_parse_tcp_v4(edev, rule, tuple); else if (ip_proto == IPPROTO_TCP && proto == htons(ETH_P_IPV6)) - rc = qede_tc_parse_tcp_v6(edev, f, tuple); + rc = qede_flow_parse_tcp_v6(edev, rule, tuple); else if (ip_proto == IPPROTO_UDP && proto == htons(ETH_P_IP)) - rc = qede_tc_parse_udp_v4(edev, f, tuple); + rc = qede_flow_parse_udp_v4(edev, rule, tuple); else if (ip_proto == IPPROTO_UDP && proto == htons(ETH_P_IPV6)) - rc = qede_tc_parse_udp_v6(edev, f, tuple); + rc = qede_flow_parse_udp_v6(edev, rule, tuple); else - DP_NOTICE(edev, "Invalid tc protocol request\n"); + DP_NOTICE(edev, "Invalid protocol request\n"); return rc; } @@ -2090,7 +1957,7 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto, } /* parse flower attribute and prepare filter */ - if (qede_parse_flower_attr(edev, proto, f, &t)) + if (qede_parse_flow_attr(edev, proto, f->rule, &t)) goto unlock; /* Validate profile mode and number of filters */ @@ -2147,16 +2014,17 @@ unlock: } static int qede_flow_spec_validate(struct qede_dev *edev, - struct ethtool_rx_flow_spec *fs, - struct qede_arfs_tuple *t) + struct flow_action *flow_action, + struct qede_arfs_tuple *t, + __u32 location) { - if (fs->location >= QEDE_RFS_MAX_FLTR) { + if (location >= QEDE_RFS_MAX_FLTR) { DP_INFO(edev, "Location out-of-bounds\n"); return -EINVAL; } /* Check location isn't already in use */ - if (test_bit(fs->location, edev->arfs->arfs_fltr_bmap)) { + if (test_bit(location, edev->arfs->arfs_fltr_bmap)) { DP_INFO(edev, "Location already in use\n"); return -EINVAL; } @@ -2170,46 +2038,56 @@ static int qede_flow_spec_validate(struct qede_dev *edev, return -EINVAL; } - /* If drop requested then no need to validate other data */ - if (fs->ring_cookie == RX_CLS_FLOW_DISC) - return 0; - - if (ethtool_get_flow_spec_ring_vf(fs->ring_cookie)) - return 0; - - if (fs->ring_cookie >= QEDE_RSS_COUNT(edev)) { - DP_INFO(edev, "Queue out-of-bounds\n"); + if (qede_parse_actions(edev, flow_action)) return -EINVAL; - } return 0; } -static int qede_flow_spec_to_tuple(struct qede_dev *edev, - struct qede_arfs_tuple *t, - struct ethtool_rx_flow_spec *fs) +static int qede_flow_spec_to_rule(struct qede_dev *edev, + struct qede_arfs_tuple *t, + struct ethtool_rx_flow_spec *fs) { - memset(t, 0, sizeof(*t)); + struct ethtool_rx_flow_spec_input input = {}; + struct ethtool_rx_flow_rule *flow; + __be16 proto; + int err = 0; if (qede_flow_spec_validate_unused(edev, fs)) return -EOPNOTSUPP; switch ((fs->flow_type & ~FLOW_EXT)) { case TCP_V4_FLOW: - return qede_flow_spec_to_tuple_tcpv4(edev, t, fs); case UDP_V4_FLOW: - return qede_flow_spec_to_tuple_udpv4(edev, t, fs); + proto = htons(ETH_P_IP); + break; case TCP_V6_FLOW: - return qede_flow_spec_to_tuple_tcpv6(edev, t, fs); case UDP_V6_FLOW: - return qede_flow_spec_to_tuple_udpv6(edev, t, fs); + proto = htons(ETH_P_IPV6); + break; default: DP_VERBOSE(edev, NETIF_MSG_IFUP, "Can't support flow of type %08x\n", fs->flow_type); return -EOPNOTSUPP; } - return 0; + input.fs = fs; + flow = ethtool_rx_flow_rule_create(&input); + if (IS_ERR(flow)) + return PTR_ERR(flow); + + if (qede_parse_flow_attr(edev, proto, flow->rule, t)) { + err = -EINVAL; + goto err_out; + } + + /* Make sure location is valid and filter isn't already set */ + err = qede_flow_spec_validate(edev, &flow->rule->action, t, + fs->location); +err_out: + ethtool_rx_flow_rule_destroy(flow); + return err; + } int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info) @@ -2227,12 +2105,7 @@ int qede_add_cls_rule(struct qede_dev *edev, struct ethtool_rxnfc *info) } /* Translate the flow specification into something fittign our DB */ - rc = qede_flow_spec_to_tuple(edev, &t, fsp); - if (rc) - goto unlock; - - /* Make sure location is valid and filter isn't already set */ - rc = qede_flow_spec_validate(edev, fsp, &t); + rc = qede_flow_spec_to_rule(edev, &t, fsp); if (rc) goto unlock; -- cgit v1.2.3 From 27c874867c4e92278cc78f3c27574fb92d7f1578 Mon Sep 17 00:00:00 2001 From: Ioana Ciocoi Radulescu Date: Mon, 4 Feb 2019 17:00:35 +0000 Subject: dpaa2-eth: Use a single page per Rx buffer Instead of allocating page fragments via the network stack, use the page allocator directly. For now, we consume one page for each Rx buffer. With the new memory model we are free to consider adding more XDP support. Performance decreases slightly in some IP forwarding cases. No visible effect on termination traffic. The driver memory footprint increases as a result of this change, but it is still small enough to not really matter. Another side effect is that now Rx buffer alignment requirements are naturally satisfied without any additional actions needed. Remove alignment related code, except in the buffer layout information conveyed to MC, as hardware still needs to know the alignment value we guarantee. Signed-off-by: Ioana Ciornei Signed-off-by: Ioana Radulescu Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 61 +++++++++++++----------- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 21 +++----- 2 files changed, 38 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 04925c731f0b..6e58de628e5e 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -86,16 +86,16 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv, for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) { addr = dpaa2_sg_get_addr(&sgt[i]); sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr); - dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, - DMA_BIDIRECTIONAL); + dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE, + DMA_BIDIRECTIONAL); - skb_free_frag(sg_vaddr); + free_pages((unsigned long)sg_vaddr, 0); if (dpaa2_sg_is_final(&sgt[i])) break; } free_buf: - skb_free_frag(vaddr); + free_pages((unsigned long)vaddr, 0); } /* Build a linear skb based on a single-buffer frame descriptor */ @@ -109,7 +109,7 @@ static struct sk_buff *build_linear_skb(struct dpaa2_eth_channel *ch, ch->buf_count--; - skb = build_skb(fd_vaddr, DPAA2_ETH_SKB_SIZE); + skb = build_skb(fd_vaddr, DPAA2_ETH_RX_BUF_RAW_SIZE); if (unlikely(!skb)) return NULL; @@ -144,19 +144,19 @@ static struct sk_buff *build_frag_skb(struct dpaa2_eth_priv *priv, /* Get the address and length from the S/G entry */ sg_addr = dpaa2_sg_get_addr(sge); sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr); - dma_unmap_single(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE, - DMA_BIDIRECTIONAL); + dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE, + DMA_BIDIRECTIONAL); sg_length = dpaa2_sg_get_len(sge); if (i == 0) { /* We build the skb around the first data buffer */ - skb = build_skb(sg_vaddr, DPAA2_ETH_SKB_SIZE); + skb = build_skb(sg_vaddr, DPAA2_ETH_RX_BUF_RAW_SIZE); if (unlikely(!skb)) { /* Free the first SG entry now, since we already * unmapped it and obtained the virtual address */ - skb_free_frag(sg_vaddr); + free_pages((unsigned long)sg_vaddr, 0); /* We still need to subtract the buffers used * by this FD from our software counter @@ -211,9 +211,9 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count) for (i = 0; i < count; i++) { vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]); - dma_unmap_single(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE, - DMA_BIDIRECTIONAL); - skb_free_frag(vaddr); + dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE, + DMA_BIDIRECTIONAL); + free_pages((unsigned long)vaddr, 0); } } @@ -378,16 +378,16 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv, return; } - dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, - DMA_BIDIRECTIONAL); + dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE, + DMA_BIDIRECTIONAL); skb = build_linear_skb(ch, fd, vaddr); } else if (fd_format == dpaa2_fd_sg) { WARN_ON(priv->xdp_prog); - dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, - DMA_BIDIRECTIONAL); + dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE, + DMA_BIDIRECTIONAL); skb = build_frag_skb(priv, ch, buf_data); - skb_free_frag(vaddr); + free_pages((unsigned long)vaddr, 0); percpu_extras->rx_sg_frames++; percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd); } else { @@ -903,7 +903,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv, { struct device *dev = priv->net_dev->dev.parent; u64 buf_array[DPAA2_ETH_BUFS_PER_CMD]; - void *buf; + struct page *page; dma_addr_t addr; int i, err; @@ -911,14 +911,16 @@ static int add_bufs(struct dpaa2_eth_priv *priv, /* Allocate buffer visible to WRIOP + skb shared info + * alignment padding */ - buf = napi_alloc_frag(dpaa2_eth_buf_raw_size(priv)); - if (unlikely(!buf)) + /* allocate one page for each Rx buffer. WRIOP sees + * the entire page except for a tailroom reserved for + * skb shared info + */ + page = dev_alloc_pages(0); + if (!page) goto err_alloc; - buf = PTR_ALIGN(buf, priv->rx_buf_align); - - addr = dma_map_single(dev, buf, DPAA2_ETH_RX_BUF_SIZE, - DMA_BIDIRECTIONAL); + addr = dma_map_page(dev, page, 0, DPAA2_ETH_RX_BUF_SIZE, + DMA_BIDIRECTIONAL); if (unlikely(dma_mapping_error(dev, addr))) goto err_map; @@ -926,7 +928,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv, /* tracing point */ trace_dpaa2_eth_buf_seed(priv->net_dev, - buf, dpaa2_eth_buf_raw_size(priv), + page, DPAA2_ETH_RX_BUF_RAW_SIZE, addr, DPAA2_ETH_RX_BUF_SIZE, bpid); } @@ -948,7 +950,7 @@ release_bufs: return i; err_map: - skb_free_frag(buf); + __free_pages(page, 0); err_alloc: /* If we managed to allocate at least some buffers, * release them to hardware @@ -2134,6 +2136,7 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv) { struct device *dev = priv->net_dev->dev.parent; struct dpni_buffer_layout buf_layout = {0}; + u16 rx_buf_align; int err; /* We need to check for WRIOP version 1.0.0, but depending on the MC @@ -2142,9 +2145,9 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv) */ if (priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(0, 0, 0) || priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(1, 0, 0)) - priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1; + rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1; else - priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN; + rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN; /* tx buffer */ buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE; @@ -2184,7 +2187,7 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv) /* rx buffer */ buf_layout.pass_frame_status = true; buf_layout.pass_parser_result = true; - buf_layout.data_align = priv->rx_buf_align; + buf_layout.data_align = rx_buf_align; buf_layout.data_head_room = dpaa2_eth_rx_head_room(priv); buf_layout.private_data_size = 0; buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h index 31fe486ec25f..da3d039cc9bf 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h @@ -63,9 +63,11 @@ /* Hardware requires alignment for ingress/egress buffer addresses */ #define DPAA2_ETH_TX_BUF_ALIGN 64 -#define DPAA2_ETH_RX_BUF_SIZE 2048 -#define DPAA2_ETH_SKB_SIZE \ - (DPAA2_ETH_RX_BUF_SIZE + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) +#define DPAA2_ETH_RX_BUF_RAW_SIZE PAGE_SIZE +#define DPAA2_ETH_RX_BUF_TAILROOM \ + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +#define DPAA2_ETH_RX_BUF_SIZE \ + (DPAA2_ETH_RX_BUF_RAW_SIZE - DPAA2_ETH_RX_BUF_TAILROOM) /* Hardware annotation area in RX/TX buffers */ #define DPAA2_ETH_RX_HWA_SIZE 64 @@ -343,7 +345,6 @@ struct dpaa2_eth_priv { bool rx_tstamp; /* Rx timestamping enabled */ u16 tx_qdid; - u16 rx_buf_align; struct fsl_mc_io *mc_io; /* Cores which have an affine DPIO/DPCON. * This is the cpu set on which Rx and Tx conf frames are processed @@ -418,15 +419,6 @@ enum dpaa2_eth_rx_dist { DPAA2_ETH_RX_DIST_CLS }; -/* Hardware only sees DPAA2_ETH_RX_BUF_SIZE, but the skb built around - * the buffer also needs space for its shared info struct, and we need - * to allocate enough to accommodate hardware alignment restrictions - */ -static inline unsigned int dpaa2_eth_buf_raw_size(struct dpaa2_eth_priv *priv) -{ - return DPAA2_ETH_SKB_SIZE + priv->rx_buf_align; -} - static inline unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv, struct sk_buff *skb) @@ -451,8 +443,7 @@ unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv, */ static inline unsigned int dpaa2_eth_rx_head_room(struct dpaa2_eth_priv *priv) { - return priv->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN - - DPAA2_ETH_RX_HWA_SIZE; + return priv->tx_data_offset - DPAA2_ETH_RX_HWA_SIZE; } int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags); -- cgit v1.2.3 From 0723a3aec0ade2d4223800ad26323a9c5369c0a0 Mon Sep 17 00:00:00 2001 From: Ioana Ciocoi Radulescu Date: Mon, 4 Feb 2019 17:00:35 +0000 Subject: dpaa2-eth: Use napi_consume_skb() While in NAPI context, free skbs by calling napi_consume_skb() instead of dev_kfree_skb(), to take advantage of the bulk freeing mechanism. Signed-off-by: Ioana Radulescu Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 6e58de628e5e..3bc54374968a 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -657,7 +657,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv, * dpaa2_eth_tx(). */ static void free_tx_fd(const struct dpaa2_eth_priv *priv, - const struct dpaa2_fd *fd) + const struct dpaa2_fd *fd, bool in_napi) { struct device *dev = priv->net_dev->dev.parent; dma_addr_t fd_addr; @@ -712,7 +712,7 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv, skb_free_frag(skbh); /* Move on with skb release */ - dev_kfree_skb(skb); + napi_consume_skb(skb, in_napi); } static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) @@ -795,7 +795,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) if (unlikely(err < 0)) { percpu_stats->tx_errors++; /* Clean up everything, including freeing the skb */ - free_tx_fd(priv, &fd); + free_tx_fd(priv, &fd, false); } else { fd_len = dpaa2_fd_get_len(&fd); percpu_stats->tx_packets++; @@ -837,7 +837,7 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv, /* Check frame errors in the FD field */ fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK; - free_tx_fd(priv, fd); + free_tx_fd(priv, fd, true); if (likely(!fd_errors)) return; -- cgit v1.2.3 From 1fa0f68c9255092c862f9280072ab0b947773b02 Mon Sep 17 00:00:00 2001 From: Ioana Ciocoi Radulescu Date: Mon, 4 Feb 2019 17:00:36 +0000 Subject: dpaa2-eth: Use FQ-based DPIO enqueue API Starting with MC10.14.0, dpaa2_io_service_enqueue_fq() API is functional. Since there are a number of cases where it offers better performance compared to the currently used enqueue function, switch to it for firmware versions that support it. Signed-off-by: Ioana Radulescu Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 41 ++++++++++++++++++++---- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 4 +++ 2 files changed, 39 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 3bc54374968a..87777b09f5e0 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -264,9 +264,7 @@ static int xdp_enqueue(struct dpaa2_eth_priv *priv, struct dpaa2_fd *fd, fq = &priv->fq[queue_id]; for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { - err = dpaa2_io_service_enqueue_qd(fq->channel->dpio, - priv->tx_qdid, 0, - fq->tx_qdbin, fd); + err = priv->enqueue(priv, fq, fd, 0); if (err != -EBUSY) break; } @@ -785,9 +783,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) queue_mapping = skb_get_queue_mapping(skb); fq = &priv->fq[queue_mapping]; for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { - err = dpaa2_io_service_enqueue_qd(fq->channel->dpio, - priv->tx_qdid, 0, - fq->tx_qdbin, &fd); + err = priv->enqueue(priv, fq, &fd, 0); if (err != -EBUSY) break; } @@ -2205,6 +2201,36 @@ static int set_buffer_layout(struct dpaa2_eth_priv *priv) return 0; } +#define DPNI_ENQUEUE_FQID_VER_MAJOR 7 +#define DPNI_ENQUEUE_FQID_VER_MINOR 9 + +static inline int dpaa2_eth_enqueue_qd(struct dpaa2_eth_priv *priv, + struct dpaa2_eth_fq *fq, + struct dpaa2_fd *fd, u8 prio) +{ + return dpaa2_io_service_enqueue_qd(fq->channel->dpio, + priv->tx_qdid, prio, + fq->tx_qdbin, fd); +} + +static inline int dpaa2_eth_enqueue_fq(struct dpaa2_eth_priv *priv, + struct dpaa2_eth_fq *fq, + struct dpaa2_fd *fd, + u8 prio __always_unused) +{ + return dpaa2_io_service_enqueue_fq(fq->channel->dpio, + fq->tx_fqid, fd); +} + +static void set_enqueue_mode(struct dpaa2_eth_priv *priv) +{ + if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_ENQUEUE_FQID_VER_MAJOR, + DPNI_ENQUEUE_FQID_VER_MINOR) < 0) + priv->enqueue = dpaa2_eth_enqueue_qd; + else + priv->enqueue = dpaa2_eth_enqueue_fq; +} + /* Configure the DPNI object this interface is associated with */ static int setup_dpni(struct fsl_mc_device *ls_dev) { @@ -2258,6 +2284,8 @@ static int setup_dpni(struct fsl_mc_device *ls_dev) if (err) goto close; + set_enqueue_mode(priv); + priv->cls_rules = devm_kzalloc(dev, sizeof(struct dpaa2_eth_cls_rule) * dpaa2_eth_fs_count(priv), GFP_KERNEL); if (!priv->cls_rules) @@ -2342,6 +2370,7 @@ static int setup_tx_flow(struct dpaa2_eth_priv *priv, } fq->tx_qdbin = qid.qdbin; + fq->tx_fqid = qid.fqid; err = dpni_get_queue(priv->mc_io, 0, priv->mc_token, DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid, diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h index da3d039cc9bf..3e29dece51e4 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h @@ -276,6 +276,7 @@ struct dpaa2_eth_priv; struct dpaa2_eth_fq { u32 fqid; u32 tx_qdbin; + u32 tx_fqid; u16 flowid; int target_cpu; u32 dq_frames; @@ -328,6 +329,9 @@ struct dpaa2_eth_priv { u8 num_fqs; struct dpaa2_eth_fq fq[DPAA2_ETH_MAX_QUEUES]; + int (*enqueue)(struct dpaa2_eth_priv *priv, + struct dpaa2_eth_fq *fq, + struct dpaa2_fd *fd, u8 prio); u8 num_channels; struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS]; -- cgit v1.2.3 From 20fb0572826b8dca465ad97b0b7eddd78bafb7ae Mon Sep 17 00:00:00 2001 From: Ioana Ciocoi Radulescu Date: Mon, 4 Feb 2019 17:00:37 +0000 Subject: dpaa2-eth: Update buffer pool refill threshold Add more buffers to the Rx buffer pool as soon as 7 of them get consumed, instead of waiting for their number to drop below a fixed threshold. 7 is the number of buffers that can be released in the pool via a single DPIO command. Signed-off-by: Ioana Radulescu Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h index 3e29dece51e4..9510928b7cca 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h @@ -53,7 +53,8 @@ */ #define DPAA2_ETH_MAX_FRAMES_PER_QUEUE (DPAA2_ETH_TAILDROP_THRESH / 64) #define DPAA2_ETH_NUM_BUFS (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256) -#define DPAA2_ETH_REFILL_THRESH DPAA2_ETH_MAX_FRAMES_PER_QUEUE +#define DPAA2_ETH_REFILL_THRESH \ + (DPAA2_ETH_NUM_BUFS - DPAA2_ETH_BUFS_PER_CMD) /* Maximum number of buffers that can be acquired/released through a single * QBMan command -- cgit v1.2.3 From d32d02a5489b327e700deac32ecab4669bff1109 Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Mon, 4 Feb 2019 18:47:46 +0000 Subject: mlxsw: core: Trace EMAD errors Trace EMAD errors returned from HW. Signed-off-by: Nir Dotan Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index ddedf8ab5b64..4f6fa515394e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1460,13 +1460,17 @@ static int mlxsw_reg_trans_wait(struct mlxsw_reg_trans *trans) if (trans->retries) dev_warn(mlxsw_core->bus_info->dev, "EMAD retries (%d/%d) (tid=%llx)\n", trans->retries, MLXSW_EMAD_MAX_RETRY, trans->tid); - if (err) + if (err) { dev_err(mlxsw_core->bus_info->dev, "EMAD reg access failed (tid=%llx,reg_id=%x(%s),type=%s,status=%x(%s))\n", trans->tid, trans->reg->id, mlxsw_reg_id_str(trans->reg->id), mlxsw_core_reg_access_type_str(trans->type), trans->emad_status, mlxsw_emad_op_tlv_status_str(trans->emad_status)); + trace_devlink_hwerr(priv_to_devlink(mlxsw_core), + trans->emad_status, + mlxsw_emad_op_tlv_status_str(trans->emad_status)); + } list_del(&trans->bulk_list); kfree_rcu(trans, rcu); -- cgit v1.2.3 From 04c7788c2bb3542e5c8c9d7175193e4d925edf20 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 6 Feb 2019 13:30:17 +0100 Subject: r8169: Load MAC address from device tree if present If the system was booted using a device tree and if the device tree contains a MAC address, use it instead of reading one from the EEPROM. This is useful in situations where the EEPROM isn't properly programmed or where the firmware wants to override the existing MAC address. Signed-off-by: Thierry Reding Reviewed-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e8a112149a62..501891be7c56 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -7110,6 +7110,21 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags); } +static void rtl_read_mac_address(struct rtl8169_private *tp, + u8 mac_addr[ETH_ALEN]) +{ + /* Get MAC address */ + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38: + case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: + *(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC); + *(u16 *)&mac_addr[4] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC); + break; + default: + break; + } +} + DECLARE_RTL_COND(rtl_link_list_ready_cond) { return RTL_R8(tp, MCU) & LINK_LIST_RDY; @@ -7301,6 +7316,7 @@ static int rtl_get_ether_clk(struct rtl8169_private *tp) static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; + u8 mac_addr[ETH_ALEN] __aligned(4) = {}; struct rtl8169_private *tp; struct net_device *dev; int chipset, region, i; @@ -7403,20 +7419,14 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) u64_stats_init(&tp->rx_stats.syncp); u64_stats_init(&tp->tx_stats.syncp); - /* Get MAC address */ - switch (tp->mac_version) { - u8 mac_addr[ETH_ALEN] __aligned(4); - case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: - *(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC); - *(u16 *)&mac_addr[4] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC); + /* get MAC address */ + rc = eth_platform_get_mac_address(&pdev->dev, mac_addr); + if (rc) + rtl_read_mac_address(tp, mac_addr); + + if (is_valid_ether_addr(mac_addr)) + rtl_rar_set(tp, mac_addr); - if (is_valid_ether_addr(mac_addr)) - rtl_rar_set(tp, mac_addr); - break; - default: - break; - } for (i = 0; i < ETH_ALEN; i++) dev->dev_addr[i] = RTL_R8(tp, MAC0 + i); -- cgit v1.2.3 From deedf1feb255c7a390309f615e50de37cb82fb61 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 6 Feb 2019 13:30:18 +0100 Subject: r8169: Avoid pointer aliasing Read MAC address 32-bit at a time and manually extract the individual bytes. This avoids pointer aliasing and gives the compiler a better chance of optimizing the operation. Suggested-by: Andrew Lunn Signed-off-by: Thierry Reding Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 501891be7c56..1dd72137fd53 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -7113,12 +7113,21 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) static void rtl_read_mac_address(struct rtl8169_private *tp, u8 mac_addr[ETH_ALEN]) { + u32 value; + /* Get MAC address */ switch (tp->mac_version) { case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38: case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: - *(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC); - *(u16 *)&mac_addr[4] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC); + value = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC); + mac_addr[0] = (value >> 0) & 0xff; + mac_addr[1] = (value >> 8) & 0xff; + mac_addr[2] = (value >> 16) & 0xff; + mac_addr[3] = (value >> 24) & 0xff; + + value = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC); + mac_addr[4] = (value >> 0) & 0xff; + mac_addr[5] = (value >> 8) & 0xff; break; default: break; @@ -7316,7 +7325,8 @@ static int rtl_get_ether_clk(struct rtl8169_private *tp) static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - u8 mac_addr[ETH_ALEN] __aligned(4) = {}; + /* align to u16 for is_valid_ether_addr() */ + u8 mac_addr[ETH_ALEN] __aligned(2) = {}; struct rtl8169_private *tp; struct net_device *dev; int chipset, region, i; -- cgit v1.2.3 From 249f62b6edad70d5eba43caf09526ee035336e0a Mon Sep 17 00:00:00 2001 From: Vishal Kulkarni Date: Wed, 6 Feb 2019 18:27:13 +0530 Subject: cxgb4: Add new T6 PCI device ids 0x608b Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h index bf7325f6d553..0c5373462ced 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h @@ -218,6 +218,7 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN CH_PCI_ID_TABLE_FENTRY(0x6088), /* Custom T62100-CR */ CH_PCI_ID_TABLE_FENTRY(0x6089), /* Custom T62100-KR */ CH_PCI_ID_TABLE_FENTRY(0x608a), /* Custom T62100-CR */ + CH_PCI_ID_TABLE_FENTRY(0x608b), /* Custom T6225-CR */ CH_PCI_DEVICE_ID_TABLE_DEFINE_END; #endif /* __T4_PCI_ID_TBL_H__ */ -- cgit v1.2.3 From 47b98039fb6e1b3fc7b04a86a9c8ed5bbf604103 Mon Sep 17 00:00:00 2001 From: Vishal Kulkarni Date: Wed, 6 Feb 2019 18:31:36 +0530 Subject: cxgb4: Update 1.22.9.0 as the latest firmware supported. Change t4fw_version.h to update latest firmware version number to 1.22.9.0. Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h index a844296135b4..9125ddd89dd1 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h @@ -36,8 +36,8 @@ #define __T4FW_VERSION_H__ #define T4FW_VERSION_MAJOR 0x01 -#define T4FW_VERSION_MINOR 0x14 -#define T4FW_VERSION_MICRO 0x08 +#define T4FW_VERSION_MINOR 0x16 +#define T4FW_VERSION_MICRO 0x09 #define T4FW_VERSION_BUILD 0x00 #define T4FW_MIN_VERSION_MAJOR 0x01 @@ -45,8 +45,8 @@ #define T4FW_MIN_VERSION_MICRO 0x00 #define T5FW_VERSION_MAJOR 0x01 -#define T5FW_VERSION_MINOR 0x14 -#define T5FW_VERSION_MICRO 0x08 +#define T5FW_VERSION_MINOR 0x16 +#define T5FW_VERSION_MICRO 0x09 #define T5FW_VERSION_BUILD 0x00 #define T5FW_MIN_VERSION_MAJOR 0x00 @@ -54,8 +54,8 @@ #define T5FW_MIN_VERSION_MICRO 0x00 #define T6FW_VERSION_MAJOR 0x01 -#define T6FW_VERSION_MINOR 0x14 -#define T6FW_VERSION_MICRO 0x08 +#define T6FW_VERSION_MINOR 0x16 +#define T6FW_VERSION_MICRO 0x09 #define T6FW_VERSION_BUILD 0x00 #define T6FW_MIN_VERSION_MAJOR 0x00 -- cgit v1.2.3 From 52d5254a2d045bba2a744042319c64e1fe41b5c8 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:36 -0800 Subject: bnxt: Implement ndo_get_port_parent_id() BNXT only supports SWITCHDEV_ATTR_ID_PORT_PARENT_ID, which makes it a great candidate to be converted to use the ndo_get_port_parent_id() NDO instead of implementing switchdev_port_attr_get(). The conversion is straight forward here since the PF and VF code use the same getter. Since bnxt makes uses of switchdev_port_same_parent_id() convert it to use netdev_port_same_parent_id(). Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 28 ++++++++------------------- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 4 ++-- drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 12 ++++-------- 4 files changed, 15 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 6a512871176b..1c2987c3d708 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -9981,8 +9981,11 @@ static int bnxt_get_phys_port_name(struct net_device *dev, char *buf, return 0; } -int bnxt_port_attr_get(struct bnxt *bp, struct switchdev_attr *attr) +int bnxt_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) { + struct bnxt *bp = netdev_priv(dev); + if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV) return -EOPNOTSUPP; @@ -9990,27 +9993,12 @@ int bnxt_port_attr_get(struct bnxt *bp, struct switchdev_attr *attr) if (!BNXT_PF(bp)) return -EOPNOTSUPP; - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = sizeof(bp->switch_id); - memcpy(attr->u.ppid.id, bp->switch_id, attr->u.ppid.id_len); - break; - default: - return -EOPNOTSUPP; - } - return 0; -} + ppid->id_len = sizeof(bp->switch_id); + memcpy(ppid->id, bp->switch_id, ppid->id_len); -static int bnxt_swdev_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return bnxt_port_attr_get(netdev_priv(dev), attr); + return 0; } -static const struct switchdev_ops bnxt_switchdev_ops = { - .switchdev_port_attr_get = bnxt_swdev_port_attr_get -}; - static const struct net_device_ops bnxt_netdev_ops = { .ndo_open = bnxt_open, .ndo_start_xmit = bnxt_start_xmit, @@ -10042,6 +10030,7 @@ static const struct net_device_ops bnxt_netdev_ops = { .ndo_bpf = bnxt_xdp, .ndo_bridge_getlink = bnxt_bridge_getlink, .ndo_bridge_setlink = bnxt_bridge_setlink, + .ndo_get_port_parent_id = bnxt_get_port_parent_id, .ndo_get_phys_port_name = bnxt_get_phys_port_name }; @@ -10400,7 +10389,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->netdev_ops = &bnxt_netdev_ops; dev->watchdog_timeo = BNXT_TX_TIMEOUT; dev->ethtool_ops = &bnxt_ethtool_ops; - SWITCHDEV_SET_OPS(dev, &bnxt_switchdev_ops); pci_set_drvdata(pdev, dev); rc = bnxt_alloc_hwrm_resources(bp); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 5c886a700bcc..17554d4be651 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -1795,7 +1794,8 @@ int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs, int bnxt_setup_mq_tc(struct net_device *dev, u8 tc); int bnxt_get_max_rings(struct bnxt *, int *, int *, bool); int bnxt_restore_pf_fw_resources(struct bnxt *bp); -int bnxt_port_attr_get(struct bnxt *bp, struct switchdev_attr *attr); +int bnxt_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid); void bnxt_dim_work(struct work_struct *work); int bnxt_hwrm_set_ring_coal(struct bnxt *bp, struct bnxt_napi *bnapi); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c index 7a1fdad1aea6..61a3457ed71b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c @@ -45,7 +45,7 @@ static u16 bnxt_flow_get_dst_fid(struct bnxt *pf_bp, struct net_device *dev) struct bnxt *bp; /* check if dev belongs to the same switch */ - if (!switchdev_port_same_parent_id(pf_bp->dev, dev)) { + if (!netdev_port_same_parent_id(pf_bp->dev, dev)) { netdev_info(pf_bp->dev, "dev(ifindex=%d) not on same switch", dev->ifindex); return BNXT_FID_INVALID; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c index 9a25c05aa571..2bdd2da9aac7 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c @@ -237,21 +237,17 @@ static void bnxt_vf_rep_get_drvinfo(struct net_device *dev, strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); } -static int bnxt_vf_rep_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) +static int bnxt_vf_rep_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) { struct bnxt_vf_rep *vf_rep = netdev_priv(dev); /* as only PORT_PARENT_ID is supported currently use common code * between PF and VF-rep for now. */ - return bnxt_port_attr_get(vf_rep->bp, attr); + return bnxt_get_port_parent_id(vf_rep->bp->dev, ppid); } -static const struct switchdev_ops bnxt_vf_rep_switchdev_ops = { - .switchdev_port_attr_get = bnxt_vf_rep_port_attr_get -}; - static const struct ethtool_ops bnxt_vf_rep_ethtool_ops = { .get_drvinfo = bnxt_vf_rep_get_drvinfo }; @@ -262,6 +258,7 @@ static const struct net_device_ops bnxt_vf_rep_netdev_ops = { .ndo_start_xmit = bnxt_vf_rep_xmit, .ndo_get_stats64 = bnxt_vf_rep_get_stats64, .ndo_setup_tc = bnxt_vf_rep_setup_tc, + .ndo_get_port_parent_id = bnxt_vf_rep_get_port_parent_id, .ndo_get_phys_port_name = bnxt_vf_rep_get_phys_port_name }; @@ -392,7 +389,6 @@ static void bnxt_vf_rep_netdev_init(struct bnxt *bp, struct bnxt_vf_rep *vf_rep, dev->netdev_ops = &bnxt_vf_rep_netdev_ops; dev->ethtool_ops = &bnxt_vf_rep_ethtool_ops; - SWITCHDEV_SET_OPS(dev, &bnxt_vf_rep_switchdev_ops); /* Just inherit all the featues of the parent PF as the VF-R * uses the RX/TX rings of the parent PF */ -- cgit v1.2.3 From c4bf24508e1f51cdcd5b810077e3cbcf21f4302c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:37 -0800 Subject: liquidio: Implement ndo_get_port_parent_id() Liquidio only supports SWITCHDEV_ATTR_ID_PORT_PARENT_ID, which makes it a great candidate to be converted to use the ndo_get_port_parent_id() NDO instead of implementing switchdev_port_attr_get(). Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/liquidio/lio_main.c | 22 +++++--------------- drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c | 25 +++++++---------------- 2 files changed, 12 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index 3d24133e5e49..e97e6754ee09 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "liquidio_common.h" #include "octeon_droq.h" #include "octeon_iq.h" @@ -3184,7 +3183,8 @@ static const struct devlink_ops liquidio_devlink_ops = { }; static int -lio_pf_switchdev_attr_get(struct net_device *dev, struct switchdev_attr *attr) +liquidio_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) { struct lio *lio = GET_LIO(dev); struct octeon_device *oct = lio->oct_dev; @@ -3192,24 +3192,12 @@ lio_pf_switchdev_attr_get(struct net_device *dev, struct switchdev_attr *attr) if (oct->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV) return -EOPNOTSUPP; - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = ETH_ALEN; - ether_addr_copy(attr->u.ppid.id, - (void *)&lio->linfo.hw_addr + 2); - break; - - default: - return -EOPNOTSUPP; - } + ppid->id_len = ETH_ALEN; + ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2); return 0; } -static const struct switchdev_ops lio_pf_switchdev_ops = { - .switchdev_port_attr_get = lio_pf_switchdev_attr_get, -}; - static int liquidio_get_vf_stats(struct net_device *netdev, int vfidx, struct ifla_vf_stats *vf_stats) { @@ -3259,6 +3247,7 @@ static const struct net_device_ops lionetdevops = { .ndo_set_vf_trust = liquidio_set_vf_trust, .ndo_set_vf_link_state = liquidio_set_vf_link_state, .ndo_get_vf_stats = liquidio_get_vf_stats, + .ndo_get_port_parent_id = liquidio_get_port_parent_id, }; /** \brief Entry point for the liquidio module @@ -3534,7 +3523,6 @@ static int setup_nic_devices(struct octeon_device *octeon_dev) * netdev tasks. */ netdev->netdev_ops = &lionetdevops; - SWITCHDEV_SET_OPS(netdev, &lio_pf_switchdev_ops); retval = netif_set_real_num_rx_queues(netdev, num_oqueues); if (retval) { diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c index de61060721c4..f3f2e71431ac 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c @@ -25,7 +25,6 @@ #include "octeon_nic.h" #include "octeon_main.h" #include "octeon_network.h" -#include #include "lio_vf_rep.h" static int lio_vf_rep_open(struct net_device *ndev); @@ -38,6 +37,8 @@ static int lio_vf_rep_phys_port_name(struct net_device *dev, static void lio_vf_rep_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64); static int lio_vf_rep_change_mtu(struct net_device *ndev, int new_mtu); +static int lio_vf_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid); static const struct net_device_ops lio_vf_rep_ndev_ops = { .ndo_open = lio_vf_rep_open, @@ -47,6 +48,7 @@ static const struct net_device_ops lio_vf_rep_ndev_ops = { .ndo_get_phys_port_name = lio_vf_rep_phys_port_name, .ndo_get_stats64 = lio_vf_rep_get_stats64, .ndo_change_mtu = lio_vf_rep_change_mtu, + .ndo_get_port_parent_id = lio_vf_get_port_parent_id, }; static int @@ -443,31 +445,19 @@ xmit_failed: return NETDEV_TX_OK; } -static int -lio_vf_rep_attr_get(struct net_device *dev, struct switchdev_attr *attr) +static int lio_vf_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) { struct lio_vf_rep_desc *vf_rep = netdev_priv(dev); struct net_device *parent_ndev = vf_rep->parent_ndev; struct lio *lio = GET_LIO(parent_ndev); - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = ETH_ALEN; - ether_addr_copy(attr->u.ppid.id, - (void *)&lio->linfo.hw_addr + 2); - break; - - default: - return -EOPNOTSUPP; - } + ppid->id_len = ETH_ALEN; + ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2); return 0; } -static const struct switchdev_ops lio_vf_rep_switchdev_ops = { - .switchdev_port_attr_get = lio_vf_rep_attr_get, -}; - static void lio_vf_rep_fetch_stats(struct work_struct *work) { @@ -524,7 +514,6 @@ lio_vf_rep_create(struct octeon_device *oct) ndev->min_mtu = LIO_MIN_MTU_SIZE; ndev->max_mtu = LIO_MAX_MTU_SIZE; ndev->netdev_ops = &lio_vf_rep_ndev_ops; - SWITCHDEV_SET_OPS(ndev, &lio_vf_rep_switchdev_ops); vf_rep = netdev_priv(ndev); memset(vf_rep, 0, sizeof(*vf_rep)); -- cgit v1.2.3 From 6dcfa2343802b1550530f3ba284cb0179cf2efc8 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:38 -0800 Subject: net/mlx5e: Implement ndo_get_port_parent_id() mlx5e only supports SWITCHDEV_ATTR_ID_PORT_PARENT_ID, which makes it a great candidate to be converted to use the ndo_get_port_parent_id() NDO instead of implementing switchdev_port_attr_get(). Since mlx5e makes use of switchdev_port_parent_id() convert it to use netdev_port_same_parent_id(). Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 31 ++++++++-------------- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 5 ++-- 3 files changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index 47bb4eb894c2..9e71f4d41b82 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -25,7 +25,7 @@ static int get_route_and_out_devs(struct mlx5e_priv *priv, /* if the egress device isn't on the same HW e-switch or * it's a LAG device, use the uplink */ - if (!switchdev_port_same_parent_id(priv->netdev, dev) || + if (!netdev_port_same_parent_id(priv->netdev, dev) || dst_is_lag_dev) { *route_dev = uplink_dev; *out_dev = *route_dev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 5d2e0c2f6624..0b1988b330f3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -381,7 +381,8 @@ static const struct ethtool_ops mlx5e_uplink_rep_ethtool_ops = { .set_pauseparam = mlx5e_uplink_rep_set_pauseparam, }; -static int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr) +static int mlx5e_rep_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) { struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; @@ -398,20 +399,14 @@ static int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr) uplink_priv = netdev_priv(uplink_dev); } - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = ETH_ALEN; - if (uplink_upper && mlx5_lag_is_sriov(uplink_priv->mdev)) { - ether_addr_copy(attr->u.ppid.id, uplink_upper->dev_addr); - } else { - struct mlx5e_rep_priv *rpriv = priv->ppriv; - struct mlx5_eswitch_rep *rep = rpriv->rep; + ppid->id_len = ETH_ALEN; + if (uplink_upper && mlx5_lag_is_sriov(uplink_priv->mdev)) { + ether_addr_copy(ppid->id, uplink_upper->dev_addr); + } else { + struct mlx5e_rep_priv *rpriv = priv->ppriv; + struct mlx5_eswitch_rep *rep = rpriv->rep; - ether_addr_copy(attr->u.ppid.id, rep->hw_id); - } - break; - default: - return -EOPNOTSUPP; + ether_addr_copy(ppid->id, rep->hw_id); } return 0; @@ -1284,10 +1279,6 @@ static int mlx5e_uplink_rep_set_vf_vlan(struct net_device *dev, int vf, u16 vlan return 0; } -static const struct switchdev_ops mlx5e_rep_switchdev_ops = { - .switchdev_port_attr_get = mlx5e_attr_get, -}; - static const struct net_device_ops mlx5e_netdev_ops_vf_rep = { .ndo_open = mlx5e_vf_rep_open, .ndo_stop = mlx5e_vf_rep_close, @@ -1298,6 +1289,7 @@ static const struct net_device_ops mlx5e_netdev_ops_vf_rep = { .ndo_has_offload_stats = mlx5e_rep_has_offload_stats, .ndo_get_offload_stats = mlx5e_rep_get_offload_stats, .ndo_change_mtu = mlx5e_vf_rep_change_mtu, + .ndo_get_port_parent_id = mlx5e_rep_get_port_parent_id, }; static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = { @@ -1319,6 +1311,7 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = { .ndo_get_vf_config = mlx5e_get_vf_config, .ndo_get_vf_stats = mlx5e_get_vf_stats, .ndo_set_vf_vlan = mlx5e_uplink_rep_set_vf_vlan, + .ndo_get_port_parent_id = mlx5e_rep_get_port_parent_id, }; bool mlx5e_eswitch_rep(struct net_device *netdev) @@ -1393,8 +1386,6 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev) netdev->watchdog_timeo = 15 * HZ; - netdev->switchdev_ops = &mlx5e_rep_switchdev_ops; - netdev->features |= NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL; netdev->hw_features |= NETIF_F_HW_TC; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 83522c926d7c..85c5dd7fc2c7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -2525,8 +2524,8 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_COUNT; - if (switchdev_port_same_parent_id(priv->netdev, - out_dev) || + if (netdev_port_same_parent_id(priv->netdev, + out_dev) || is_merged_eswitch_dev(priv, out_dev)) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH); -- cgit v1.2.3 From 25ba8605147689462c750eb9f2e53f6b88bd953a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:39 -0800 Subject: mlxsw: Implement ndo_get_port_parent_id() mlxsw implements SWITCHDEV_ATTR_ID_PORT_PARENT_ID and we want to get rid of switchdev_ops eventually, ease that migration by implementing a ndo_get_port_parent_id() function which returns what switchdev_port_attr_get() would do. Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 13 ++++++++ .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 5 --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 37 ++++++++-------------- 3 files changed, 26 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index a88169738b4a..8dd808b7f931 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1700,6 +1700,18 @@ static int mlxsw_sp_set_features(struct net_device *dev, mlxsw_sp_feature_hw_tc); } +static int mlxsw_sp_port_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + + ppid->id_len = sizeof(mlxsw_sp->base_mac); + memcpy(&ppid->id, &mlxsw_sp->base_mac, ppid->id_len); + + return 0; +} + static const struct net_device_ops mlxsw_sp_port_netdev_ops = { .ndo_open = mlxsw_sp_port_open, .ndo_stop = mlxsw_sp_port_stop, @@ -1715,6 +1727,7 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = { .ndo_vlan_rx_kill_vid = mlxsw_sp_port_kill_vid, .ndo_get_phys_port_name = mlxsw_sp_port_get_phys_port_name, .ndo_set_features = mlxsw_sp_set_features, + .ndo_get_port_parent_id = mlxsw_sp_port_get_port_parent_id, }; static void mlxsw_sp_port_get_drvinfo(struct net_device *dev, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index a4a9fe992193..95e37de3e48f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -451,11 +451,6 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev, struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = sizeof(mlxsw_sp->base_mac); - memcpy(&attr->u.ppid.id, &mlxsw_sp->base_mac, - attr->u.ppid.id_len); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: mlxsw_sp_port_bridge_flags_get(mlxsw_sp->bridge, attr->orig_dev, &attr->u.brport_flags); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 2d4f213e154d..533fe6235b7c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "pci.h" #include "core.h" @@ -390,6 +389,18 @@ static int mlxsw_sx_port_get_phys_port_name(struct net_device *dev, char *name, name, len); } +static int mlxsw_sx_port_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) +{ + struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); + struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; + + ppid->id_len = sizeof(mlxsw_sx->hw_id); + memcpy(&ppid->id, &mlxsw_sx->hw_id, ppid->id_len); + + return 0; +} + static const struct net_device_ops mlxsw_sx_port_netdev_ops = { .ndo_open = mlxsw_sx_port_open, .ndo_stop = mlxsw_sx_port_stop, @@ -397,6 +408,7 @@ static const struct net_device_ops mlxsw_sx_port_netdev_ops = { .ndo_change_mtu = mlxsw_sx_port_change_mtu, .ndo_get_stats64 = mlxsw_sx_port_get_stats64, .ndo_get_phys_port_name = mlxsw_sx_port_get_phys_port_name, + .ndo_get_port_parent_id = mlxsw_sx_port_get_port_parent_id, }; static void mlxsw_sx_port_get_drvinfo(struct net_device *dev, @@ -901,28 +913,6 @@ static const struct ethtool_ops mlxsw_sx_port_ethtool_ops = { .set_link_ksettings = mlxsw_sx_port_set_link_ksettings, }; -static int mlxsw_sx_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); - struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = sizeof(mlxsw_sx->hw_id); - memcpy(&attr->u.ppid.id, &mlxsw_sx->hw_id, attr->u.ppid.id_len); - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static const struct switchdev_ops mlxsw_sx_port_switchdev_ops = { - .switchdev_port_attr_get = mlxsw_sx_port_attr_get, -}; - static int mlxsw_sx_hw_id_get(struct mlxsw_sx *mlxsw_sx) { char spad_pl[MLXSW_REG_SPAD_LEN] = {0}; @@ -1034,7 +1024,6 @@ static int __mlxsw_sx_port_eth_create(struct mlxsw_sx *mlxsw_sx, u8 local_port, dev->netdev_ops = &mlxsw_sx_port_netdev_ops; dev->ethtool_ops = &mlxsw_sx_port_ethtool_ops; - dev->switchdev_ops = &mlxsw_sx_port_switchdev_ops; err = mlxsw_sx_port_dev_addr_get(mlxsw_sx_port); if (err) { -- cgit v1.2.3 From 751302c35ea0ae5aac9918e85199eb9f56a5afac Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:40 -0800 Subject: mscc: ocelot: Implement ndo_get_port_parent_id() Ocelot only supports SWITCHDEV_ATTR_ID_PORT_PARENT_ID as a valid switchdev attribute getter, convert it to use ndo_get_port_parent_id() and get rid of the switchdev_ops::switchdev_port_attr_get altogether. Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index c6a575eb0ff5..195306d05bcd 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -916,6 +916,18 @@ static int ocelot_set_features(struct net_device *dev, return 0; } +static int ocelot_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) +{ + struct ocelot_port *ocelot_port = netdev_priv(dev); + struct ocelot *ocelot = ocelot_port->ocelot; + + ppid->id_len = sizeof(ocelot->base_mac); + memcpy(&ppid->id, &ocelot->base_mac, ppid->id_len); + + return 0; +} + static const struct net_device_ops ocelot_port_netdev_ops = { .ndo_open = ocelot_port_open, .ndo_stop = ocelot_port_stop, @@ -930,6 +942,7 @@ static const struct net_device_ops ocelot_port_netdev_ops = { .ndo_vlan_rx_add_vid = ocelot_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = ocelot_vlan_rx_kill_vid, .ndo_set_features = ocelot_set_features, + .ndo_get_port_parent_id = ocelot_get_port_parent_id, }; static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data) @@ -1013,25 +1026,6 @@ static const struct ethtool_ops ocelot_ethtool_ops = { .set_link_ksettings = phy_ethtool_set_link_ksettings, }; -static int ocelot_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - struct ocelot_port *ocelot_port = netdev_priv(dev); - struct ocelot *ocelot = ocelot_port->ocelot; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = sizeof(ocelot->base_mac); - memcpy(&attr->u.ppid.id, &ocelot->base_mac, - attr->u.ppid.id_len); - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port, struct switchdev_trans *trans, u8 state) @@ -1331,7 +1325,6 @@ static int ocelot_port_obj_del(struct net_device *dev, } static const struct switchdev_ops ocelot_port_switchdev_ops = { - .switchdev_port_attr_get = ocelot_port_attr_get, .switchdev_port_attr_set = ocelot_port_attr_set, }; -- cgit v1.2.3 From a5084bb71fa4cc2a70a3a5775ccd0447dbcb32f3 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:41 -0800 Subject: nfp: Implement ndo_get_port_parent_id() NFP only supports SWITCHDEV_ATTR_ID_PORT_PARENT_ID, which makes it a great candidate to be converted to use the ndo_get_port_parent_id() NDO instead of implementing switchdev_port_attr_get(). Since NFP uses switchdev_port_same_parent_id() convert it to use netdev_port_same_parent_id(). Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/action.c | 3 +-- .../net/ethernet/netronome/nfp/nfp_net_common.c | 4 +--- drivers/net/ethernet/netronome/nfp/nfp_net_repr.c | 4 +--- drivers/net/ethernet/netronome/nfp/nfp_port.c | 22 +++++----------------- drivers/net/ethernet/netronome/nfp/nfp_port.h | 4 +++- 5 files changed, 11 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index 6b1d56b021ac..583e97c99e68 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -138,7 +137,7 @@ nfp_fl_output(struct nfp_app *app, struct nfp_fl_output *output, if (nfp_netdev_is_nfp_repr(in_dev)) { /* Confirm ingress and egress are on same device. */ - if (!switchdev_port_same_parent_id(in_dev, out_dev)) + if (!netdev_port_same_parent_id(in_dev, out_dev)) return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 7d2d4241498f..776f6c07701b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -36,7 +36,6 @@ #include #include -#include #include #include "nfpcore/nfp_nsp.h" @@ -3531,6 +3530,7 @@ const struct net_device_ops nfp_net_netdev_ops = { .ndo_udp_tunnel_add = nfp_net_add_vxlan_port, .ndo_udp_tunnel_del = nfp_net_del_vxlan_port, .ndo_bpf = nfp_net_xdp, + .ndo_get_port_parent_id = nfp_port_get_port_parent_id, }; /** @@ -3815,8 +3815,6 @@ static void nfp_net_netdev_init(struct nfp_net *nn) netdev->netdev_ops = &nfp_net_netdev_ops; netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000); - SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops); - /* MTU range: 68 - hw-specific max */ netdev->min_mtu = ETH_MIN_MTU; netdev->max_mtu = nn->max_mtu; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c index 69d7aebda09b..62839807e21e 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c @@ -5,7 +5,6 @@ #include #include #include -#include #include "nfpcore/nfp_cpp.h" #include "nfpcore/nfp_nsp.h" @@ -273,6 +272,7 @@ const struct net_device_ops nfp_repr_netdev_ops = { .ndo_fix_features = nfp_repr_fix_features, .ndo_set_features = nfp_port_set_features, .ndo_set_mac_address = eth_mac_addr, + .ndo_get_port_parent_id = nfp_port_get_port_parent_id, }; void @@ -336,8 +336,6 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev, netdev->max_mtu = pf_netdev->max_mtu; - SWITCHDEV_SET_OPS(netdev, &nfp_port_switchdev_ops); - /* Set features the lower device can support with representors */ if (repr_cap & NFP_NET_CFG_CTRL_LIVE_ADDR) netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c index 86bc149ca231..7e90880fa46b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_port.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c @@ -31,34 +31,22 @@ struct nfp_port *nfp_port_from_netdev(struct net_device *netdev) return NULL; } -static int -nfp_port_attr_get(struct net_device *netdev, struct switchdev_attr *attr) +int nfp_port_get_port_parent_id(struct net_device *netdev, + struct netdev_phys_item_id *ppid) { struct nfp_port *port; + const u8 *serial; port = nfp_port_from_netdev(netdev); if (!port) return -EOPNOTSUPP; - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: { - const u8 *serial; - /* N.B: attr->u.ppid.id is binary data */ - attr->u.ppid.id_len = nfp_cpp_serial(port->app->cpp, &serial); - memcpy(&attr->u.ppid.id, serial, attr->u.ppid.id_len); - break; - } - default: - return -EOPNOTSUPP; - } + ppid->id_len = nfp_cpp_serial(port->app->cpp, &serial); + memcpy(&ppid->id, serial, ppid->id_len); return 0; } -const struct switchdev_ops nfp_port_switchdev_ops = { - .switchdev_port_attr_get = nfp_port_attr_get, -}; - int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type, void *type_data) { diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.h b/drivers/net/ethernet/netronome/nfp/nfp_port.h index b2479a2a49e5..90ae053f5c07 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_port.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_port.h @@ -7,6 +7,7 @@ #include struct net_device; +struct netdev_phys_item_id; struct nfp_app; struct nfp_pf; struct nfp_port; @@ -90,7 +91,6 @@ struct nfp_port { }; extern const struct ethtool_ops nfp_port_ethtool_ops; -extern const struct switchdev_ops nfp_port_switchdev_ops; __printf(2, 3) u8 *nfp_pr_et(u8 *data, const char *fmt, ...); @@ -106,6 +106,8 @@ int nfp_port_set_features(struct net_device *netdev, netdev_features_t features); struct nfp_port *nfp_port_from_netdev(struct net_device *netdev); +int nfp_port_get_port_parent_id(struct net_device *netdev, + struct netdev_phys_item_id *ppid); struct nfp_port * nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id); struct nfp_eth_table_port *__nfp_port_get_eth_port(struct nfp_port *port); -- cgit v1.2.3 From 7026b8a6fbe1061863a25495d4dc1fa115c8708e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:42 -0800 Subject: rocker: Implement ndo_get_port_parent_id() mlxsw implements SWITCHDEV_ATTR_ID_PORT_PARENT_ID and we want to get rid of switchdev_ops eventually, ease that migration by implementing a ndo_get_port_parent_id() function which returns what switchdev_port_attr_get() would do. Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker_main.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 62a205eba9f7..66f72f8c46e5 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2026,6 +2026,18 @@ static void rocker_port_neigh_destroy(struct net_device *dev, err); } +static int rocker_port_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) +{ + const struct rocker_port *rocker_port = netdev_priv(dev); + const struct rocker *rocker = rocker_port->rocker; + + ppid->id_len = sizeof(rocker->hw.id); + memcpy(&ppid->id, &rocker->hw.id, ppid->id_len); + + return 0; +} + static const struct net_device_ops rocker_port_netdev_ops = { .ndo_open = rocker_port_open, .ndo_stop = rocker_port_stop, @@ -2035,6 +2047,7 @@ static const struct net_device_ops rocker_port_netdev_ops = { .ndo_get_phys_port_name = rocker_port_get_phys_port_name, .ndo_change_proto_down = rocker_port_change_proto_down, .ndo_neigh_destroy = rocker_port_neigh_destroy, + .ndo_get_port_parent_id = rocker_port_get_port_parent_id, }; /******************** @@ -2045,14 +2058,9 @@ static int rocker_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { const struct rocker_port *rocker_port = netdev_priv(dev); - const struct rocker *rocker = rocker_port->rocker; int err = 0; switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = sizeof(rocker->hw.id); - memcpy(&attr->u.ppid.id, &rocker->hw.id, attr->u.ppid.id_len); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = rocker_world_port_attr_bridge_flags_get(rocker_port, &attr->u.brport_flags); -- cgit v1.2.3 From e58df56c8564b701491236381fc1e75202952736 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:43 -0800 Subject: netdevsim: Implement ndo_get_port_parent_id() netdevsim only supports SWITCHDEV_ATTR_ID_PORT_PARENT_ID, which makes it a great candidate to be converted to use the ndo_get_port_parent_id() NDO instead of implementing switchdev_port_attr_get(). Acked-by: Jiri Pirko Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/netdevsim/netdev.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 8d8e2b3f263e..75a50b59cb8f 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -22,7 +22,6 @@ #include #include #include -#include #include "netdevsim.h" @@ -148,26 +147,16 @@ static struct device_type nsim_dev_type = { .release = nsim_dev_release, }; -static int -nsim_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) +static int nsim_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) { struct netdevsim *ns = netdev_priv(dev); - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = sizeof(ns->sdev->switch_id); - memcpy(&attr->u.ppid.id, &ns->sdev->switch_id, - attr->u.ppid.id_len); - return 0; - default: - return -EOPNOTSUPP; - } + ppid->id_len = sizeof(ns->sdev->switch_id); + memcpy(&ppid->id, &ns->sdev->switch_id, ppid->id_len); + return 0; } -static const struct switchdev_ops nsim_switchdev_ops = { - .switchdev_port_attr_get = nsim_port_attr_get, -}; - static int nsim_init(struct net_device *dev) { char sdev_ddir_name[10], sdev_link_name[32]; @@ -214,7 +203,6 @@ static int nsim_init(struct net_device *dev) goto err_bpf_uninit; SET_NETDEV_DEV(dev, &ns->dev); - SWITCHDEV_SET_OPS(dev, &nsim_switchdev_ops); err = nsim_devlink_setup(ns); if (err) @@ -493,6 +481,7 @@ static const struct net_device_ops nsim_netdev_ops = { .ndo_setup_tc = nsim_setup_tc, .ndo_set_features = nsim_set_features, .ndo_bpf = nsim_bpf, + .ndo_get_port_parent_id = nsim_get_port_parent_id, }; static void nsim_setup(struct net_device *dev) -- cgit v1.2.3 From 7870a7bd570bc1bd43622c7c6828931d3ea98b8c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 09:45:44 -0800 Subject: staging: fsl-dpaa2: ethsw: Implement ndo_get_port_parent_id() ethsw implements SWITCHDEV_ATTR_ID_PORT_PARENT_ID and we want to get rid of switchdev_ops eventually, ease that migration by implementing a ndo_get_port_parent_id() function which returns what switchdev_port_attr_get() would do. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index daabaceeea52..e559f4c25cf7 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -505,6 +505,17 @@ static netdev_tx_t port_dropframe(struct sk_buff *skb, return NETDEV_TX_OK; } +static int swdev_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) +{ + struct ethsw_port_priv *port_priv = netdev_priv(dev); + + ppid->id_len = 1; + ppid->id[0] = port_priv->ethsw_data->dev_id; + + return 0; +} + static const struct net_device_ops ethsw_port_ops = { .ndo_open = port_open, .ndo_stop = port_stop, @@ -515,6 +526,7 @@ static const struct net_device_ops ethsw_port_ops = { .ndo_get_offload_stats = port_get_offload_stats, .ndo_start_xmit = port_dropframe, + .ndo_get_port_parent_id = swdev_get_port_parent_id, }; static void ethsw_links_state_update(struct ethsw_core *ethsw) @@ -634,10 +646,6 @@ static int swdev_port_attr_get(struct net_device *netdev, struct ethsw_port_priv *port_priv = netdev_priv(netdev); switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = 1; - attr->u.ppid.id[0] = port_priv->ethsw_data->dev_id; - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: attr->u.brport_flags = (port_priv->ethsw_data->learning ? BR_LEARNING : 0) | -- cgit v1.2.3 From 2810c3b252b902979fd7fe074123101cfc313fae Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 6 Feb 2019 19:42:01 +0000 Subject: mlxsw: spectrum_router: Offload blackhole routes Create a new FIB entry type for blackhole routes and set it in case the type of the notified route is 'RTN_BLACKHOLE'. Program such routes with a discard action and mark them as offloaded since the device is dropping the packets instead of the kernel. Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 230e1f6e192b..6754061d9b72 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -364,6 +364,7 @@ enum mlxsw_sp_fib_entry_type { MLXSW_SP_FIB_ENTRY_TYPE_REMOTE, MLXSW_SP_FIB_ENTRY_TYPE_LOCAL, MLXSW_SP_FIB_ENTRY_TYPE_TRAP, + MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE, /* This is a special case of local delivery, where a packet should be * decapsulated on reception. Note that there is no corresponding ENCAP, @@ -3928,6 +3929,7 @@ mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry) return !!nh_group->adj_index_valid; case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL: return !!nh_group->nh_rif; + case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE: case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP: return true; @@ -3963,6 +3965,7 @@ mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry) int i; if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL || + fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE || fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP || fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP) { nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD; @@ -4004,7 +4007,8 @@ mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry) fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry, common); - if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL) { + if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL || + fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE) { list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6, list)->rt->fib6_nh.nh_flags |= RTNH_F_OFFLOAD; return; @@ -4172,6 +4176,19 @@ static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); } +static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_fib_entry *fib_entry, + enum mlxsw_reg_ralue_op op) +{ + enum mlxsw_reg_ralue_trap_action trap_action; + char ralue_pl[MLXSW_REG_RALUE_LEN]; + + trap_action = MLXSW_REG_RALUE_TRAP_ACTION_DISCARD_ERROR; + mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op); + mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, 0, 0); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); +} + static int mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib_entry *fib_entry, @@ -4211,6 +4228,8 @@ static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp, return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op); case MLXSW_SP_FIB_ENTRY_TYPE_TRAP: return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op); + case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE: + return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, fib_entry, op); case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP: return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp, fib_entry, op); @@ -4279,8 +4298,10 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp, case RTN_BROADCAST: fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP; return 0; + case RTN_BLACKHOLE: + fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE; + return 0; case RTN_UNREACHABLE: /* fall through */ - case RTN_BLACKHOLE: /* fall through */ case RTN_PROHIBIT: /* Packets hitting these routes need to be trapped, but * can do so with a lower priority than packets directed @@ -5229,6 +5250,8 @@ static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp, */ if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP; + else if (rt->fib6_type == RTN_BLACKHOLE) + fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE; else if (rt->fib6_flags & RTF_REJECT) fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL; else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt)) -- cgit v1.2.3 From bcd3d9d9246f35c62c5d652d20569a76dbdf4bd1 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 5 Feb 2019 12:07:28 +0100 Subject: net: dsa: mv88e6xxx: Prevent suspend to RAM On one hand, the mv88e6xxx driver has a work queue called in loop which will attempt register accesses after MDIO bus suspension, that entirely freezes the platform during suspend. On the other hand, the DSA core is not ready yet to support suspend to RAM operation because so far there is no way to recover reliably the switch configuration. To avoid the kernel to freeze when suspending with a switch driven by the mv88e6xxx driver, we choose to prevent the driver suspension and in the same way, the whole platform. Signed-off-by: Miquel Raynal Reviewed-by: Andrew Lunn Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8dca2c949e73..669a7f13fdce 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4764,6 +4764,21 @@ static const void *pdata_device_get_match_data(struct device *dev) return NULL; } +/* There is no suspend to RAM support at DSA level yet, the switch configuration + * would be lost after a power cycle so prevent it to be suspended. + */ +static int __maybe_unused mv88e6xxx_suspend(struct device *dev) +{ + return -EOPNOTSUPP; +} + +static int __maybe_unused mv88e6xxx_resume(struct device *dev) +{ + return 0; +} + +static SIMPLE_DEV_PM_OPS(mv88e6xxx_pm_ops, mv88e6xxx_suspend, mv88e6xxx_resume); + static int mv88e6xxx_probe(struct mdio_device *mdiodev) { struct dsa_mv88e6xxx_pdata *pdata = mdiodev->dev.platform_data; @@ -4948,6 +4963,7 @@ static struct mdio_driver mv88e6xxx_driver = { .mdiodrv.driver = { .name = "mv88e6085", .of_match_table = mv88e6xxx_of_match, + .pm = &mv88e6xxx_pm_ops, }, }; -- cgit v1.2.3 From 7d8e249f393a1aca30bde876e932401d2c78bc9f Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Tue, 5 Feb 2019 14:15:20 +0200 Subject: net: stmmac: fix ptp timestamping on Rx on gmac4 The current driver only enables Pdelay_Req and Pdelay_Resp when HWTSTAMP_FILTER_PTP_V2_EVENT, HWTSTAMP_FILTER_PTP_V1_L4_EVENT or HWTSTAMP_FILTER_PTP_V2_L4_EVENT is requested. This results in ptp sync on slave mode to report 'received SYNC without timestamp' when using ptp4l. Although the hardware can support Sync, Pdelay_Req and Pdelay_resp by setting bit14 annd bits 17/16 to 01 this leaves Delay_Req timestamps out. Fix this by enabling all event and general messages timestamps. This includes SYNC, Follow_Up, Delay_Req, Delay_Resp, Pdelay_Req, Pdelay_Resp and Pdelay_Resp_Follow_Up messages. Signed-off-by: Ilias Apalodimas Acked-by: Jose Abreu Tested-by: Alexandre TORGUE Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 25 ++++++++--------------- drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 9 ++++++-- 2 files changed, 16 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 517555bcfa44..effff171d250 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -597,12 +597,13 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: /* PTP v1, UDP, any kind of event packet */ config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; - /* take time stamp for all event messages */ - if (xmac) - snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; - else - snap_type_sel = PTP_TCR_SNAPTYPSEL_1; - + /* 'xmac' hardware can support Sync, Pdelay_Req and + * Pdelay_resp by setting bit14 and bits17/16 to 01 + * This leaves Delay_Req timestamps out. + * Enable all events *and* general purpose message + * timestamping + */ + snap_type_sel = PTP_TCR_SNAPTYPSEL_1; ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; break; @@ -633,10 +634,7 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; ptp_v2 = PTP_TCR_TSVER2ENA; /* take time stamp for all event messages */ - if (xmac) - snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; - else - snap_type_sel = PTP_TCR_SNAPTYPSEL_1; + snap_type_sel = PTP_TCR_SNAPTYPSEL_1; ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; @@ -669,12 +667,7 @@ static int stmmac_hwtstamp_set(struct net_device *dev, struct ifreq *ifr) /* PTP v2/802.AS1 any layer, any kind of event packet */ config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; ptp_v2 = PTP_TCR_TSVER2ENA; - /* take time stamp for all event messages */ - if (xmac) - snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1; - else - snap_type_sel = PTP_TCR_SNAPTYPSEL_1; - + snap_type_sel = PTP_TCR_SNAPTYPSEL_1; ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; ptp_over_ethernet = PTP_TCR_TSIPENA; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h index ecccf895fd7e..e852821289cf 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h @@ -59,9 +59,14 @@ #define PTP_TCR_TSEVNTENA BIT(14) /* Enable Snapshot for Messages Relevant to Master */ #define PTP_TCR_TSMSTRENA BIT(15) -/* Select PTP packets for Taking Snapshots */ +/* Select PTP packets for Taking Snapshots + * On gmac4 specifically: + * Enable SYNC, Pdelay_Req, Pdelay_Resp when TSEVNTENA is enabled. + * or + * Enable SYNC, Follow_Up, Delay_Req, Delay_Resp, Pdelay_Req, Pdelay_Resp, + * Pdelay_Resp_Follow_Up if TSEVNTENA is disabled + */ #define PTP_TCR_SNAPTYPSEL_1 BIT(16) -#define PTP_GMAC4_TCR_SNAPTYPSEL_1 GENMASK(17, 16) /* Enable MAC address for PTP Frame Filtering */ #define PTP_TCR_TSENMACADDR BIT(18) -- cgit v1.2.3 From a6e11f6bbd29a92d1357c2f3033a70fb1b767432 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Tue, 5 Feb 2019 20:41:37 +0100 Subject: net: phy: improve genphy_c45_read_link Let's make genphy_c45_read_link behave the same as genphy_update_link and set phydev->link in the function directly. This allows to simplify the callers. In addition don't check further devices once we detect that at least one device reports link as down. v2: - remove an unused variable Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 2 -- drivers/net/phy/phy-c45.c | 15 ++++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 5531f9cabc63..296a537cdfcb 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -457,8 +457,6 @@ static int mv3310_read_status(struct phy_device *phydev) if (val < 0) return val; - phydev->link = val > 0 ? 1 : 0; - val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); if (val < 0) return val; diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 519866679c91..c92d0fb7ec4f 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -121,7 +121,7 @@ EXPORT_SYMBOL_GPL(genphy_c45_aneg_done); * @mmd_mask: MMDs to read status from * * Read the link status from the specified MMDs, and if they all indicate - * that the link is up, return positive. If an error is encountered, + * that the link is up, set phydev->link to 1. If an error is encountered, * a negative errno will be returned, otherwise zero. */ int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask) @@ -129,7 +129,7 @@ int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask) int val, devad; bool link = true; - while (mmd_mask) { + while (mmd_mask && link) { devad = __ffs(mmd_mask); mmd_mask &= ~BIT(devad); @@ -145,7 +145,9 @@ int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask) link = false; } - return link; + phydev->link = link; + + return 0; } EXPORT_SYMBOL_GPL(genphy_c45_read_link); @@ -265,7 +267,6 @@ EXPORT_SYMBOL_GPL(gen10g_config_aneg); int gen10g_read_status(struct phy_device *phydev) { u32 mmd_mask = phydev->c45_ids.devices_in_package; - int ret; /* For now just lie and say it's 10G all the time */ phydev->speed = SPEED_10000; @@ -274,11 +275,7 @@ int gen10g_read_status(struct phy_device *phydev) /* Avoid reading the vendor MMDs */ mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2)); - ret = genphy_c45_read_link(phydev, mmd_mask); - - phydev->link = ret > 0 ? 1 : 0; - - return 0; + return genphy_c45_read_link(phydev, mmd_mask); } EXPORT_SYMBOL_GPL(gen10g_read_status); -- cgit v1.2.3 From 22087d659212d2401f4caa602fd57160ff1e6222 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 5 Feb 2019 22:20:09 +0100 Subject: net: emac: remove IBM_EMAC_RX_SKB_HEADROOM The EMAC driver had a custom IBM_EMAC_RX_SKB_HEADROOM Kconfig option that reserved additional skb headroom for RX. This patch removes the option and migrates the code to use napi_alloc_skb() and netdev_alloc_skb_ip_align() in its place. Signed-off-by: Christian Lamparter Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/emac/Kconfig | 12 ------- drivers/net/ethernet/ibm/emac/core.c | 64 ++++++++++++++++++++++++----------- drivers/net/ethernet/ibm/emac/core.h | 10 ++---- 3 files changed, 47 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/ibm/emac/Kconfig b/drivers/net/ethernet/ibm/emac/Kconfig index 90d49191beb3..eacf7e141fdc 100644 --- a/drivers/net/ethernet/ibm/emac/Kconfig +++ b/drivers/net/ethernet/ibm/emac/Kconfig @@ -28,18 +28,6 @@ config IBM_EMAC_RX_COPY_THRESHOLD depends on IBM_EMAC default "256" -config IBM_EMAC_RX_SKB_HEADROOM - int "Additional RX skb headroom (bytes)" - depends on IBM_EMAC - default "0" - help - Additional receive skb headroom. Note, that driver - will always reserve at least 2 bytes to make IP header - aligned, so usually there is no need to add any additional - headroom. - - If unsure, set to 0. - config IBM_EMAC_DEBUG bool "Debugging" depends on IBM_EMAC diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 209255495bc9..3c2a5759844a 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -1071,7 +1071,9 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu) /* Second pass, allocate new skbs */ for (i = 0; i < NUM_RX_BUFF; ++i) { - struct sk_buff *skb = alloc_skb(rx_skb_size, GFP_ATOMIC); + struct sk_buff *skb; + + skb = netdev_alloc_skb_ip_align(dev->ndev, rx_skb_size); if (!skb) { ret = -ENOMEM; goto oom; @@ -1080,10 +1082,10 @@ static int emac_resize_rx_ring(struct emac_instance *dev, int new_mtu) BUG_ON(!dev->rx_skb[i]); dev_kfree_skb(dev->rx_skb[i]); - skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2); dev->rx_desc[i].data_ptr = - dma_map_single(&dev->ofdev->dev, skb->data - 2, rx_sync_size, - DMA_FROM_DEVICE) + 2; + dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN, + rx_sync_size, DMA_FROM_DEVICE) + + NET_IP_ALIGN; dev->rx_skb[i] = skb; } skip: @@ -1174,20 +1176,18 @@ static void emac_clean_rx_ring(struct emac_instance *dev) } } -static inline int emac_alloc_rx_skb(struct emac_instance *dev, int slot, - gfp_t flags) +static int +__emac_prepare_rx_skb(struct sk_buff *skb, struct emac_instance *dev, int slot) { - struct sk_buff *skb = alloc_skb(dev->rx_skb_size, flags); if (unlikely(!skb)) return -ENOMEM; dev->rx_skb[slot] = skb; dev->rx_desc[slot].data_len = 0; - skb_reserve(skb, EMAC_RX_SKB_HEADROOM + 2); dev->rx_desc[slot].data_ptr = - dma_map_single(&dev->ofdev->dev, skb->data - 2, dev->rx_sync_size, - DMA_FROM_DEVICE) + 2; + dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN, + dev->rx_sync_size, DMA_FROM_DEVICE) + NET_IP_ALIGN; wmb(); dev->rx_desc[slot].ctrl = MAL_RX_CTRL_EMPTY | (slot == (NUM_RX_BUFF - 1) ? MAL_RX_CTRL_WRAP : 0); @@ -1195,6 +1195,27 @@ static inline int emac_alloc_rx_skb(struct emac_instance *dev, int slot, return 0; } +static int +emac_alloc_rx_skb(struct emac_instance *dev, int slot) +{ + struct sk_buff *skb; + + skb = __netdev_alloc_skb_ip_align(dev->ndev, dev->rx_skb_size, + GFP_KERNEL); + + return __emac_prepare_rx_skb(skb, dev, slot); +} + +static int +emac_alloc_rx_skb_napi(struct emac_instance *dev, int slot) +{ + struct sk_buff *skb; + + skb = napi_alloc_skb(&dev->mal->napi, dev->rx_skb_size); + + return __emac_prepare_rx_skb(skb, dev, slot); +} + static void emac_print_link_status(struct emac_instance *dev) { if (netif_carrier_ok(dev->ndev)) @@ -1225,7 +1246,7 @@ static int emac_open(struct net_device *ndev) /* Allocate RX ring */ for (i = 0; i < NUM_RX_BUFF; ++i) - if (emac_alloc_rx_skb(dev, i, GFP_KERNEL)) { + if (emac_alloc_rx_skb(dev, i)) { printk(KERN_ERR "%s: failed to allocate RX ring\n", ndev->name); goto oom; @@ -1660,8 +1681,9 @@ static inline void emac_recycle_rx_skb(struct emac_instance *dev, int slot, DBG2(dev, "recycle %d %d" NL, slot, len); if (len) - dma_map_single(&dev->ofdev->dev, skb->data - 2, - EMAC_DMA_ALIGN(len + 2), DMA_FROM_DEVICE); + dma_map_single(&dev->ofdev->dev, skb->data - NET_IP_ALIGN, + SKB_DATA_ALIGN(len + NET_IP_ALIGN), + DMA_FROM_DEVICE); dev->rx_desc[slot].data_len = 0; wmb(); @@ -1713,7 +1735,7 @@ static inline int emac_rx_sg_append(struct emac_instance *dev, int slot) int len = dev->rx_desc[slot].data_len; int tot_len = dev->rx_sg_skb->len + len; - if (unlikely(tot_len + 2 > dev->rx_skb_size)) { + if (unlikely(tot_len + NET_IP_ALIGN > dev->rx_skb_size)) { ++dev->estats.rx_dropped_mtu; dev_kfree_skb(dev->rx_sg_skb); dev->rx_sg_skb = NULL; @@ -1769,16 +1791,18 @@ static int emac_poll_rx(void *param, int budget) } if (len && len < EMAC_RX_COPY_THRESH) { - struct sk_buff *copy_skb = - alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, GFP_ATOMIC); + struct sk_buff *copy_skb; + + copy_skb = napi_alloc_skb(&dev->mal->napi, len); if (unlikely(!copy_skb)) goto oom; - skb_reserve(copy_skb, EMAC_RX_SKB_HEADROOM + 2); - memcpy(copy_skb->data - 2, skb->data - 2, len + 2); + memcpy(copy_skb->data - NET_IP_ALIGN, + skb->data - NET_IP_ALIGN, + len + NET_IP_ALIGN); emac_recycle_rx_skb(dev, slot, len); skb = copy_skb; - } else if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC))) + } else if (unlikely(emac_alloc_rx_skb_napi(dev, slot))) goto oom; skb_put(skb, len); @@ -1799,7 +1823,7 @@ static int emac_poll_rx(void *param, int budget) sg: if (ctrl & MAL_RX_CTRL_FIRST) { BUG_ON(dev->rx_sg_skb); - if (unlikely(emac_alloc_rx_skb(dev, slot, GFP_ATOMIC))) { + if (unlikely(emac_alloc_rx_skb_napi(dev, slot))) { DBG(dev, "rx OOM %d" NL, slot); ++dev->estats.rx_dropped_oom; emac_recycle_rx_skb(dev, slot, 0); diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index 84caa4a3fc52..187689cd8212 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -68,22 +68,18 @@ static inline int emac_rx_size(int mtu) return mal_rx_size(ETH_DATA_LEN + EMAC_MTU_OVERHEAD); } -#define EMAC_DMA_ALIGN(x) ALIGN((x), dma_get_cache_alignment()) - -#define EMAC_RX_SKB_HEADROOM \ - EMAC_DMA_ALIGN(CONFIG_IBM_EMAC_RX_SKB_HEADROOM) - /* Size of RX skb for the given MTU */ static inline int emac_rx_skb_size(int mtu) { int size = max(mtu + EMAC_MTU_OVERHEAD, emac_rx_size(mtu)); - return EMAC_DMA_ALIGN(size + 2) + EMAC_RX_SKB_HEADROOM; + + return SKB_DATA_ALIGN(size + NET_IP_ALIGN) + NET_SKB_PAD; } /* RX DMA sync size */ static inline int emac_rx_sync_size(int mtu) { - return EMAC_DMA_ALIGN(emac_rx_size(mtu) + 2); + return SKB_DATA_ALIGN(emac_rx_size(mtu) + NET_IP_ALIGN); } /* Driver statistcs is split into two parts to make it more cache friendly: -- cgit v1.2.3 From 768ec4c012ac8b32d8062e599f105f57a6f4c01b Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Mon, 4 Feb 2019 17:25:55 +0530 Subject: ath10k: update HOST capability qmi message HOST capability interface data structures are updated in HL3.1 fw version. Update the qmi host capability members for compatibility across different firmware versions. Since this change breaks backward compatibility with HL2.0 fw, HL2.0 fw upgrade to WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1 or later version is required. Testing: Tested on QCS404 platform(WCN3990 HW). Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1, WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1 Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c | 229 ++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h | 34 +++- 2 files changed, 257 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c index ba79c2e4aed6..4102f7b0b5c3 100644 --- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c +++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c @@ -1763,14 +1763,239 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = { daemon_support_valid), }, { - .data_type = QMI_UNSIGNED_1_BYTE, + .data_type = QMI_UNSIGNED_4_BYTE, .elem_len = 1, - .elem_size = sizeof(u8), + .elem_size = sizeof(u32), .array_type = NO_ARRAY, .tlv_type = 0x10, .offset = offsetof(struct wlfw_host_cap_req_msg_v01, daemon_support), }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + wake_msi_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + wake_msi), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios_valid), + }, + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios_len), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = QMI_WLFW_MAX_NUM_GPIO_V01, + .elem_size = sizeof(u32), + .array_type = VAR_LEN_ARRAY, + .tlv_type = 0x12, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + gpios), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + nm_modem_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x13, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + nm_modem), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x14, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x15, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + bdf_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + m3_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_filesys_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_filesys_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_cache_support_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_cache_support), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_done_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1A, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + cal_done), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_bucket_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x1B, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_bucket), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_cfg_mode_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + mem_cfg_mode), + }, {} }; diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h index c5e3870b8871..ff668f5d8afd 100644 --- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h +++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h @@ -553,12 +553,38 @@ struct wlfw_mac_addr_resp_msg_v01 { #define WLFW_MAC_ADDR_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct qmi_elem_info wlfw_mac_addr_resp_msg_v01_ei[]; +#define QMI_WLFW_MAX_NUM_GPIO_V01 32 struct wlfw_host_cap_req_msg_v01 { u8 daemon_support_valid; - u8 daemon_support; -}; - -#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 4 + u32 daemon_support; + u8 wake_msi_valid; + u32 wake_msi; + u8 gpios_valid; + u32 gpios_len; + u32 gpios[QMI_WLFW_MAX_NUM_GPIO_V01]; + u8 nm_modem_valid; + u8 nm_modem; + u8 bdf_support_valid; + u8 bdf_support; + u8 bdf_cache_support_valid; + u8 bdf_cache_support; + u8 m3_support_valid; + u8 m3_support; + u8 m3_cache_support_valid; + u8 m3_cache_support; + u8 cal_filesys_support_valid; + u8 cal_filesys_support; + u8 cal_cache_support_valid; + u8 cal_cache_support; + u8 cal_done_valid; + u8 cal_done; + u8 mem_bucket_valid; + u32 mem_bucket; + u8 mem_cfg_mode_valid; + u8 mem_cfg_mode; +}; + +#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189 extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[]; struct wlfw_host_cap_resp_msg_v01 { -- cgit v1.2.3 From cc123fac978f468e419b7bbd2e153e54196254de Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Fri, 25 Jan 2019 09:40:01 +0530 Subject: ath10k: Handle bundled tx completion for management frames WCN3990 supports sending tx completion for multiple management frames bundled together in a single event. Add support to handle the bundled tx completion event for WCN3990. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi-ops.h | 13 +++++++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 63 +++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi-tlv.h | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 23 +++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 7 ++++ 5 files changed, 107 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 04663076d27a..e92d00a6a2a1 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -33,6 +33,9 @@ struct wmi_ops { struct wmi_mgmt_rx_ev_arg *arg); int (*pull_mgmt_tx_compl)(struct ath10k *ar, struct sk_buff *skb, struct wmi_tlv_mgmt_tx_compl_ev_arg *arg); + int (*pull_mgmt_tx_bundle_compl)( + struct ath10k *ar, struct sk_buff *skb, + struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg); int (*pull_ch_info)(struct ath10k *ar, struct sk_buff *skb, struct wmi_ch_info_ev_arg *arg); int (*pull_vdev_start)(struct ath10k *ar, struct sk_buff *skb, @@ -279,6 +282,16 @@ ath10k_wmi_pull_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb, return ar->wmi.ops->pull_mgmt_tx_compl(ar, skb, arg); } +static inline int +ath10k_wmi_pull_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb, + struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg) +{ + if (!ar->wmi.ops->pull_mgmt_tx_bundle_compl) + return -EOPNOTSUPP; + + return ar->wmi.ops->pull_mgmt_tx_bundle_compl(ar, skb, arg); +} + static inline int ath10k_wmi_pull_mgmt_rx(struct ath10k *ar, struct sk_buff *skb, struct wmi_mgmt_rx_ev_arg *arg) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 892bd8c30dd9..e85d6be1fb90 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -620,6 +620,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) case WMI_TLV_MGMT_TX_COMPLETION_EVENTID: ath10k_wmi_event_mgmt_tx_compl(ar, skb); break; + case WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID: + ath10k_wmi_event_mgmt_tx_bundle_compl(ar, skb); + break; default: ath10k_dbg(ar, ATH10K_DBG_WMI, "Unknown eventid: %d\n", id); break; @@ -686,6 +689,65 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb, return 0; } +struct wmi_tlv_tx_bundle_compl_parse { + const __le32 *num_reports; + const __le32 *desc_ids; + const __le32 *status; + bool desc_ids_done; + bool status_done; +}; + +static int +ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len, + const void *ptr, void *data) +{ + struct wmi_tlv_tx_bundle_compl_parse *bundle_tx_compl = data; + + switch (tag) { + case WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_BUNDLE_EVENT: + bundle_tx_compl->num_reports = ptr; + break; + case WMI_TLV_TAG_ARRAY_UINT32: + if (!bundle_tx_compl->desc_ids_done) { + bundle_tx_compl->desc_ids_done = true; + bundle_tx_compl->desc_ids = ptr; + } else if (!bundle_tx_compl->status_done) { + bundle_tx_compl->status_done = true; + bundle_tx_compl->status = ptr; + } + break; + default: + break; + } + return 0; +} + +static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev( + struct ath10k *ar, struct sk_buff *skb, + struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg) +{ + struct wmi_tlv_tx_bundle_compl_parse bundle_tx_compl = { }; + int ret; + + ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len, + ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse, + &bundle_tx_compl); + if (ret) { + ath10k_warn(ar, "failed to parse tlv: %d\n", ret); + return ret; + } + + if (!bundle_tx_compl.num_reports || !bundle_tx_compl.desc_ids || + !bundle_tx_compl.status) + return -EPROTO; + + arg->num_reports = *bundle_tx_compl.num_reports; + arg->desc_ids = bundle_tx_compl.desc_ids; + arg->status = bundle_tx_compl.status; + + return 0; +} + static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb, struct wmi_mgmt_rx_ev_arg *arg) @@ -4093,6 +4155,7 @@ static const struct wmi_ops wmi_tlv_ops = { .pull_scan = ath10k_wmi_tlv_op_pull_scan_ev, .pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev, .pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev, + .pull_mgmt_tx_bundle_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev, .pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev, .pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev, .pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev, diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index e07e9907e355..5941961bec9c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -321,6 +321,7 @@ enum wmi_tlv_event_id { WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID, WMI_TLV_OFFLOAD_PROB_RESP_TX_STATUS_EVENTID, WMI_TLV_MGMT_TX_COMPLETION_EVENTID, + WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID, WMI_TLV_TX_DELBA_COMPLETE_EVENTID = WMI_TLV_EV(WMI_TLV_GRP_BA_NEG), WMI_TLV_TX_ADDBA_COMPLETE_EVENTID, WMI_TLV_BA_RSP_SSN_EVENTID, diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index ba837403e266..971ff364d8b1 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2383,6 +2383,29 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb) return 0; } +int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb) +{ + struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg arg; + u32 num_reports; + int i, ret; + + ret = ath10k_wmi_pull_mgmt_tx_bundle_compl(ar, skb, &arg); + if (ret) { + ath10k_warn(ar, "failed to parse bundle mgmt compl event: %d\n", ret); + return ret; + } + + num_reports = __le32_to_cpu(arg.num_reports); + + for (i = 0; i < num_reports; i++) + wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_ids[i]), + __le32_to_cpu(arg.status[i])); + + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n"); + + return 0; +} + int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) { struct wmi_mgmt_rx_ev_arg arg = {}; diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 2034ccc7cc72..ac04077c4e69 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -6688,6 +6688,12 @@ struct wmi_tlv_mgmt_tx_compl_ev_arg { __le32 pdev_id; }; +struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg { + __le32 num_reports; + const __le32 *desc_ids; + const __le32 *status; +}; + struct wmi_mgmt_rx_ev_arg { __le32 channel; __le32 snr; @@ -7244,6 +7250,7 @@ int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg); int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb); int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb); int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb); +int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb); void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb); void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb); int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb); -- cgit v1.2.3 From 543271334483f23f8118f5b1bae919134010714f Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Fri, 25 Jan 2019 09:40:02 +0530 Subject: ath10k: Enable bundle tx compl for management frames in WCN3990 WCN3990 sends tx completion of multiple management frames bundled together in a single event, if the host driver exposes the support to handle this bundled tx completion event. This reduces the number of WMI events which are sent to the host driver by the target. Set the BUNDLE_TX_COMPL flag in the host capability flags when host sends the wmi init command, to indicate the host capability to handle bundled tx completion for management frames. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 +- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index e85d6be1fb90..e6f62bb252ec 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1688,7 +1688,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) cfg->num_ocb_vdevs = __cpu_to_le32(0); cfg->num_ocb_channels = __cpu_to_le32(0); cfg->num_ocb_schedules = __cpu_to_le32(0); - cfg->host_capab = __cpu_to_le32(0); + cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL); ath10k_wmi_put_host_mem_chunks(ar, chunks); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 5941961bec9c..298d917f72cd 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1593,6 +1593,8 @@ struct chan_info_params { u32 mac_clk_mhz; }; +#define WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL BIT(9) + struct wmi_tlv_mgmt_tx_compl_ev { __le32 desc_id; __le32 status; -- cgit v1.2.3 From 6e8a8991e2103dcb6a9cff28f460390e8e360848 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Fri, 25 Jan 2019 09:51:06 +0530 Subject: ath10k: fix dma unmap direction for management frames The management frames transmitted are dma mapped with direction TO_DEVICE, but incorrectly mapped with direction FROM_DEVICE during tx complete and error cases. Fix the direction of dma during dma unmap of the transmitted management frames. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Fixes: 38a1390e02b7 ("ath10k: dma unmap mgmt tx buffer if wmi cmd send fails") Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 4 ++-- drivers/net/wireless/ath/ath10k/wmi.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index e49b36752ba2..8c6c5152d416 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -3863,7 +3863,7 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) ath10k_warn(ar, "failed to transmit management frame by ref via WMI: %d\n", ret); dma_unmap_single(ar->dev, paddr, skb->len, - DMA_FROM_DEVICE); + DMA_TO_DEVICE); ieee80211_free_txskb(ar->hw, skb); } } else { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 971ff364d8b1..6509febc07cd 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -2346,7 +2346,7 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id, msdu = pkt_addr->vaddr; dma_unmap_single(ar->dev, pkt_addr->paddr, - msdu->len, DMA_FROM_DEVICE); + msdu->len, DMA_TO_DEVICE); info = IEEE80211_SKB_CB(msdu); if (status) -- cgit v1.2.3 From cdb78e5af49105917ba5694bc616d12b0a4f85f3 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Tue, 29 Jan 2019 14:56:07 +0530 Subject: ath10k: fix hw-restart crash inject mode for WCN3990 The hw-restart crash inject mode is a special mode, where there is no crash generated in the firmware, but instead the driver restarts the firmware. In order to restart WCN3990 firmware, the driver needs to send qmi_wlan_disable message followed by the qmi_wlan_enable message to the WCN3990 firmware. Currently the qmi_wlan_disable message is not sent to the WCN3990 firmware when hw-restart crash is injected, which causes the firmware to crash when the driver sends qmi_wlan_enable message during ath10k_restart. Send qmi_wlan_disable to the WCN3990 firmware when the hw-restart crash is injected via debugfs. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/snoc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 0032bc5dd934..38d850bde089 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1000,7 +1000,16 @@ static int ath10k_snoc_wlan_enable(struct ath10k *ar) static void ath10k_snoc_wlan_disable(struct ath10k *ar) { - if (!test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + + /* If both ATH10K_FLAG_CRASH_FLUSH and ATH10K_SNOC_FLAG_RECOVERY + * flags are not set, it means that the driver has restarted + * due to a crash inject via debugfs. In this case, the driver + * needs to restart the firmware and hence send qmi wlan disable, + * during the driver restart sequence. + */ + if (!test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags) || + !test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags)) ath10k_qmi_wlan_disable(ar); } -- cgit v1.2.3 From 40194e3b36bfd9e3972001f17c0171348d372c3d Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Tue, 29 Jan 2019 20:03:12 +0800 Subject: ath10k: change swap mail box check after htc ready The swap box flag of firmware is not set before htc ready, then it will not set swap box flag in ath10k driver, and it will let swap box setting not same between firmware and ath10k driver, then it will trigger firmware assert failure. Check the flag and set swap box after htc ready will fix the firmware assert failure. Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00005-QCARMSWP-1. Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 6 ++++++ drivers/net/wireless/ath/ath10k/hif.h | 9 ++++++++ drivers/net/wireless/ath/ath10k/sdio.c | 38 ++++++++++++++++++++-------------- 3 files changed, 38 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 399b501f3c3c..23e88fb6dfd9 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2556,6 +2556,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, goto err_hif_stop; } + status = ath10k_hif_swap_mailbox(ar); + if (status) { + ath10k_err(ar, "failed to swap mailbox: %d\n", status); + goto err_hif_stop; + } + if (mode == ATH10K_FIRMWARE_MODE_NORMAL) { status = ath10k_htt_connect(&ar->htt); if (status) { diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 1a59ea0068c2..5f7f1e08866f 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -59,6 +59,8 @@ struct ath10k_hif_ops { */ void (*stop)(struct ath10k *ar); + int (*swap_mailbox)(struct ath10k *ar); + int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id, u8 *ul_pipe, u8 *dl_pipe); @@ -139,6 +141,13 @@ static inline void ath10k_hif_stop(struct ath10k *ar) return ar->hif.ops->stop(ar); } +static inline int ath10k_hif_swap_mailbox(struct ath10k *ar) +{ + if (ar->hif.ops->swap_mailbox) + return ar->hif.ops->swap_mailbox(ar); + return 0; +} + static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, u8 *ul_pipe, u8 *dl_pipe) diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 983ecfef1d28..334a147901e4 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -1615,12 +1615,33 @@ static int ath10k_sdio_hif_diag_write_mem(struct ath10k *ar, u32 address, return 0; } +static int ath10k_sdio_hif_swap_mailbox(struct ath10k *ar) +{ + struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar); + u32 addr, val; + int ret = 0; + + addr = host_interest_item_address(HI_ITEM(hi_acs_flags)); + + ret = ath10k_sdio_hif_diag_read32(ar, addr, &val); + if (ret) { + ath10k_warn(ar, "unable to read hi_acs_flags : %d\n", ret); + return ret; + } + + if (val & HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK) { + ath10k_dbg(ar, ATH10K_DBG_SDIO, + "sdio mailbox swap service enabled\n"); + ar_sdio->swap_mbox = true; + } + return 0; +} + /* HIF start/stop */ static int ath10k_sdio_hif_start(struct ath10k *ar) { struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar); - u32 addr, val; int ret; /* Sleep 20 ms before HIF interrupts are disabled. @@ -1654,20 +1675,6 @@ static int ath10k_sdio_hif_start(struct ath10k *ar) if (ret) ath10k_warn(ar, "failed to enable sdio interrupts: %d\n", ret); - addr = host_interest_item_address(HI_ITEM(hi_acs_flags)); - - ret = ath10k_sdio_hif_diag_read32(ar, addr, &val); - if (ret) { - ath10k_warn(ar, "unable to read hi_acs_flags address: %d\n", ret); - return ret; - } - - if (val & HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK) { - ath10k_dbg(ar, ATH10K_DBG_SDIO, - "sdio mailbox swap service enabled\n"); - ar_sdio->swap_mbox = true; - } - /* Enable sleep and then disable it again */ ret = ath10k_sdio_hif_set_mbox_sleep(ar, true); if (ret) @@ -1898,6 +1905,7 @@ static const struct ath10k_hif_ops ath10k_sdio_hif_ops = { .exchange_bmi_msg = ath10k_sdio_bmi_exchange_msg, .start = ath10k_sdio_hif_start, .stop = ath10k_sdio_hif_stop, + .swap_mailbox = ath10k_sdio_hif_swap_mailbox, .map_service_to_pipe = ath10k_sdio_hif_map_service_to_pipe, .get_default_pipe = ath10k_sdio_hif_get_default_pipe, .send_complete_check = ath10k_sdio_hif_send_complete_check, -- cgit v1.2.3 From ea69598408147eabab23ebedbb5d0492381f0d18 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 29 Jan 2019 15:14:48 -0800 Subject: ath10k: sdio: add .owner field sdio_register_driver() doesn't do this for us, unlike (for example) platform_driver_register(). This is important for helping track module-to-device relationships. Signed-off-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/sdio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 334a147901e4..f3b2e148e6ce 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -2096,7 +2096,10 @@ static struct sdio_driver ath10k_sdio_driver = { .id_table = ath10k_sdio_devices, .probe = ath10k_sdio_probe, .remove = ath10k_sdio_remove, - .drv.pm = ATH10K_SDIO_PM_OPS, + .drv = { + .owner = THIS_MODULE, + .pm = ATH10K_SDIO_PM_OPS, + }, }; static int __init ath10k_sdio_init(void) -- cgit v1.2.3 From f9a4b7f45ff595e33c98d652e852854818fddad7 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 30 Jan 2019 11:09:00 +0800 Subject: ath10k: snoc: remove set but not used variable 'ar_snoc' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/ath/ath10k/snoc.c: In function 'ath10k_snoc_tx_pipe_cleanup': drivers/net/wireless/ath/ath10k/snoc.c:681:22: warning: variable 'ar_snoc' set but not used [-Wunused-but-set-variable] Signed-off-by: YueHaibing Reviewed-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/snoc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 38d850bde089..097211daaa46 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -875,13 +875,11 @@ static void ath10k_snoc_tx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe) { struct ath10k_ce_pipe *ce_pipe; struct ath10k_ce_ring *ce_ring; - struct ath10k_snoc *ar_snoc; struct sk_buff *skb; struct ath10k *ar; int i; ar = snoc_pipe->hif_ce_state; - ar_snoc = ath10k_snoc_priv(ar); ce_pipe = snoc_pipe->ce_hdl; ce_ring = ce_pipe->src_ring; -- cgit v1.2.3 From 0b38b4b44516add3d1e3062a08fdcf1856476a00 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 31 Jan 2019 14:15:56 +0100 Subject: ath10k: do not return invalid pointers as a *dentry When calling debugfs functions, they can now return error values if something went wrong. If that happens, return a NULL as a *dentry to the relay core instead of passing it an illegal pointer. The relay core should be able to handle an illegal pointer, but add this check to be safe. Cc: Kalle Valo Cc: ath10k@lists.infradead.org Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/spectral.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c index 653b6d013207..4a7fa3e4e99f 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.c +++ b/drivers/net/wireless/ath/ath10k/spectral.c @@ -494,6 +494,9 @@ static struct dentry *create_buf_file_handler(const char *filename, buf_file = debugfs_create_file(filename, mode, parent, buf, &relay_file_operations); + if (IS_ERR(buf_file)) + return NULL; + *is_global = 1; return buf_file; } -- cgit v1.2.3 From a73dbce3a6f41f07672956e44725f20b0b79053a Mon Sep 17 00:00:00 2001 From: Alagu Sankar Date: Fri, 1 Feb 2019 10:17:09 +0800 Subject: ath10k: reduce transmit msdu count Reduce the transmit MSDU count for SDIO, to match with the descriptors as used by the firmware. This also acts as a high watermark level for transmit. Too many packets to the firmware results in transmit overflow interrupt. It only affect SDIO chip, it will not cause functionaly changes to other hardware. Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00005-QCARMSWP-1. Signed-off-by: Alagu Sankar Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 6 +++++- drivers/net/wireless/ath/ath10k/hw.h | 1 + drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 23e88fb6dfd9..753f5764d25c 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2309,7 +2309,11 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->max_num_stations = TARGET_TLV_NUM_STATIONS; ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS; ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS; - ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; + if (ar->hif.bus == ATH10K_BUS_SDIO) + ar->htt.max_num_pending_tx = + TARGET_TLV_NUM_MSDU_DESC_HL; + else + ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS; ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV | WMI_STAT_PEER; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index f03114740040..f9ffed53f2c4 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -736,6 +736,7 @@ ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw, #define TARGET_TLV_NUM_TDLS_VDEVS 1 #define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2) #define TARGET_TLV_NUM_MSDU_DESC (1024 + 32) +#define TARGET_TLV_NUM_MSDU_DESC_HL 64 #define TARGET_TLV_NUM_WOW_PATTERNS 22 #define TARGET_TLV_MGMT_NUM_MSDU_DESC (50) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index e6f62bb252ec..90617e1a074c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1673,7 +1673,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0); cfg->vow_config = __cpu_to_le32(0); cfg->gtk_offload_max_vdev = __cpu_to_le32(2); - cfg->num_msdu_desc = __cpu_to_le32(TARGET_TLV_NUM_MSDU_DESC); + cfg->num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx); cfg->max_frag_entries = __cpu_to_le32(2); cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS); cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20); -- cgit v1.2.3 From ff488d0ef1c224561d4ec7479de920738aa11e55 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Fri, 1 Feb 2019 11:04:22 +0530 Subject: ath10k: add a condition to fill the LDPC capability correctly The firmware advertises the LDPC support information for HT in HT capability info in the wmi service ready event. To provide granularity, firmware now advertises WMI_HT_CAP_RX_LDPC and WMI_HT_CAP_TX_LDPC separately. To support LDPC, host should also check for WMI_HT_CAP_RX_LDPC and WMI_HT_CAP_TX_LDPC in HT capabilities. Add a condition to existing logic in host to know whether firmware supports LDPC or not. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1, WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1 Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 3 ++- drivers/net/wireless/ath/ath10k/wmi.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 8c6c5152d416..a1bb70e073f6 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4549,7 +4549,8 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) ht_cap.cap |= stbc; } - if (ar->ht_cap_info & WMI_HT_CAP_LDPC) + if (ar->ht_cap_info & WMI_HT_CAP_LDPC || (ar->ht_cap_info & + WMI_HT_CAP_RX_LDPC && (ar->ht_cap_info & WMI_HT_CAP_TX_LDPC))) ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index ac04077c4e69..86348418a278 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -2075,6 +2075,8 @@ enum wmi_channel_change_cause { #define WMI_HT_CAP_MPDU_DENSITY 0x0700 /* MPDU Density */ #define WMI_HT_CAP_MPDU_DENSITY_MASK_SHIFT 8 #define WMI_HT_CAP_HT40_SGI 0x0800 +#define WMI_HT_CAP_RX_LDPC 0x1000 /* LDPC RX support */ +#define WMI_HT_CAP_TX_LDPC 0x2000 /* LDPC TX support */ #define WMI_HT_CAP_DEFAULT_ALL (WMI_HT_CAP_ENABLED | \ WMI_HT_CAP_HT20_SGI | \ -- cgit v1.2.3 From 056550291d983a1b0a36b4f018a46ca7d12eb75c Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Fri, 1 Feb 2019 11:06:30 +0530 Subject: ath10k: fill tx_duration for each peer in Tx stats per STA Firmware sends the tx_duration for each in HTT_T2H_MSG_TYPE_PEER_STATS msg. Fill the tx_duration sent by firmware in the tx stats information per STA. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1, WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1 Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index f42bac204ef8..89d84dc73a44 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2975,6 +2975,8 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, STATS_OP_FMT(RETRY).rate_table[0][idx] += pstats->retry_bytes; STATS_OP_FMT(RETRY).rate_table[1][idx] += pstats->retry_pkts; } + + tx_stats->tx_duration += pstats->duration; } static void @@ -3141,6 +3143,7 @@ static void ath10k_htt_fetch_peer_stats(struct ath10k *ar, p_tx_stats->succ_pkts = __le16_to_cpu(tx_stats->succ_pkts); p_tx_stats->retry_pkts = __le16_to_cpu(tx_stats->retry_pkts); p_tx_stats->failed_pkts = __le16_to_cpu(tx_stats->failed_pkts); + p_tx_stats->duration = __le16_to_cpu(tx_stats->tx_duration); ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats); } -- cgit v1.2.3 From cd98625b3e3fd53b92323f781c0a80c039c23fbb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 31 Jan 2019 14:16:25 +0100 Subject: ath9k: do not return invalid pointers as a *dentry When calling debugfs functions, they can now return error values if something went wrong. If that happens, return a NULL as a *dentry to the relay core instead of passing it an illegal pointer. The relay core should be able to handle an illegal pointer, but add this check to be safe. Cc: Kalle Valo Cc: QCA ath9k Development Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/common-spectral.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index 6aa3ec024ffa..21191955a7c1 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c @@ -1039,6 +1039,9 @@ static struct dentry *create_buf_file_handler(const char *filename, buf_file = debugfs_create_file(filename, mode, parent, buf, &relay_file_operations); + if (IS_ERR(buf_file)) + return NULL; + *is_global = 1; return buf_file; } -- cgit v1.2.3 From b789f333d7acaddb1d6d56c9c64416bbcbbc723a Mon Sep 17 00:00:00 2001 From: Zhiwei Jiang Date: Wed, 23 Jan 2019 00:30:33 +0800 Subject: ath: move spin_lock_bh to spin_lock in tasklet as you are already in a tasklet, it is unnecessary to call spin_lock_bh, because softirq already disable BH. Signed-off-by: Zhiwei Jiang Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 799010ed04e0..4e8e80ac8341 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -574,12 +574,12 @@ void ath9k_tx_failed_tasklet(unsigned long data) { struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; - spin_lock_bh(&priv->tx.tx_lock); + spin_lock(&priv->tx.tx_lock); if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { - spin_unlock_bh(&priv->tx.tx_lock); + spin_unlock(&priv->tx.tx_lock); return; } - spin_unlock_bh(&priv->tx.tx_lock); + spin_unlock(&priv->tx.tx_lock); ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); } -- cgit v1.2.3 From 62a2c1355c15940eb7223fda514b60dc18e46a3f Mon Sep 17 00:00:00 2001 From: Oever Gonzalez Date: Sat, 26 Jan 2019 17:30:19 +0100 Subject: ath: regd: add extra US coutry codes This patch adds several country codes to the regd.h and regd_common.h files in order to support devices like the Linksys EA6350v3, whose country codes are not present in the original list. Without this patch, all devices whose manufacturer programmed any of these code in their EEPROM will not work. The values for CTRY_UNITED_STATES2 and CTRY_UNITED_STATES3 were taken from a post by Sven Eckelmann : Signed-off-by: Oever Gonzalez Signed-off-by: Christian Lamparter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/regd.h | 2 ++ drivers/net/wireless/ath/regd_common.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index d73e45e26547..75ddaefdd049 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -185,7 +185,9 @@ enum CountryCode { CTRY_UKRAINE = 804, CTRY_UNITED_KINGDOM = 826, CTRY_UNITED_STATES = 840, + CTRY_UNITED_STATES2 = 841, CTRY_UNITED_STATES_FCC49 = 842, + CTRY_UNITED_STATES3 = 843, CTRY_URUGUAY = 858, CTRY_UZBEKISTAN = 860, CTRY_VENEZUELA = 862, diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 4021e37a225a..c4bd26e65949 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -483,6 +483,8 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_UAE, NULL1_WORLD, "AE"}, {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, + {CTRY_UNITED_STATES2, FCC3_FCCA, "US"}, + {CTRY_UNITED_STATES3, FCC3_FCCA, "US"}, /* This "PS" is for US public safety actually... to support this we * would need to assign new special alpha2 to CRDA db as with the world * regdomain and use another alpha2 */ -- cgit v1.2.3 From 8f289805616e81f7c1690931aa8a586c76f4fa88 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Wed, 6 Feb 2019 21:45:29 -0800 Subject: net: phy: fixed_phy: Fix fixed_phy not checking GPIO Fix fixed_phy not checking GPIO if no link_update callback is registered. In the original version all users registered a link_update callback so the issue was masked. Fixes: a5597008dbc2 ("phy: fixed_phy: Add gpio to determine link up/down.") Reviewed-by: Andrew Lunn Signed-off-by: Moritz Fischer Signed-off-by: David S. Miller --- drivers/net/phy/fixed_phy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index f136a23c1a35..d810f914aaa4 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -85,11 +85,11 @@ static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) s = read_seqcount_begin(&fp->seqcount); fp->status.link = !fp->no_carrier; /* Issue callback if user registered it. */ - if (fp->link_update) { + if (fp->link_update) fp->link_update(fp->phydev->attached_dev, &fp->status); - fixed_phy_update(fp); - } + /* Check the GPIO for change in status */ + fixed_phy_update(fp); state = fp->status; } while (read_seqcount_retry(&fp->seqcount, s)); -- cgit v1.2.3 From de8650a820715ea619b687b4a315794593be1d59 Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 7 Feb 2019 11:36:40 +0200 Subject: net/mlx5e: Add tx reporter support Add mlx5e tx reporter to devlink health reporters. This reporter will be responsible for diagnosing, reporting and recovering of tx errors. This patch declares the TX reporter operations and creates it using the devlink health API. Currently, this reporter supports reporting and recovering from send error CQE only. In addition, it adds diagnose information for the open SQs. For a local SQ recover (due to driver error report), in case of SQ recover failure, the recover operation will be considered as a failure. For a full tx recover, an attempt to close and open the channels will be done. If this one passed successfully, it will be considered as a successful recover. The SQ recover from error CQE flow is not a new feature in the driver, this patch re-organize the functions and adapt them for the devlink health API. For this purpose, move code from en_main.c to a new file named reporter_tx.c. Diagnose output: $devlink health diagnose pci/0000:00:09.0 reporter tx -j -p { "SQs": [ { "sqn": 138, "HW state": 1, "stopped": false },{ "sqn": 142, "HW state": 1, "stopped": false } ] } $devlink health diagnose pci/0000:00:09.0 reporter tx SQs: sqn: 138 HW state: 1 stopped: false sqn: 142 HW state: 1 stopped: false Signed-off-by: Eran Ben Elisha Reviewed-by: Moshe Shemesh Acked-by: Saeed Mahameed Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en.h | 18 +- .../net/ethernet/mellanox/mlx5/core/en/reporter.h | 14 ++ .../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 259 +++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 136 ++--------- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 5 +- 6 files changed, 306 insertions(+), 128 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 9de9abacf7f6..6bb2a860b15b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -22,7 +22,7 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \ # mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ en_tx.o en_rx.o en_dim.o en_txrx.o en/xdp.o en_stats.o \ - en_selftest.o en/port.o en/monitor_stats.o + en_selftest.o en/port.o en/monitor_stats.o en/reporter_tx.o # # Netdev extra diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 6dd74ef69389..66e510b16243 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -387,10 +387,7 @@ struct mlx5e_txqsq { struct mlx5e_channel *channel; int txq_ix; u32 rate_limit; - struct mlx5e_txqsq_recover { - struct work_struct recover_work; - u64 last_recover; - } recover; + struct work_struct recover_work; } ____cacheline_aligned_in_smp; struct mlx5e_dma_info { @@ -683,6 +680,13 @@ struct mlx5e_rss_params { u8 hfunc; }; +struct mlx5e_modify_sq_param { + int curr_state; + int next_state; + int rl_update; + int rl_index; +}; + struct mlx5e_priv { /* priv data path fields - start */ struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC]; @@ -738,6 +742,7 @@ struct mlx5e_priv { #ifdef CONFIG_MLX5_EN_TLS struct mlx5e_tls *tls; #endif + struct devlink_health_reporter *tx_reporter; }; struct mlx5e_profile { @@ -868,6 +873,11 @@ void mlx5e_set_rq_type(struct mlx5_core_dev *mdev, struct mlx5e_params *params); void mlx5e_init_rq_type_params(struct mlx5_core_dev *mdev, struct mlx5e_params *params); +int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, + struct mlx5e_modify_sq_param *p); +void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq); +void mlx5e_tx_disable_queue(struct netdev_queue *txq); + static inline bool mlx5e_tunnel_inner_ft_supported(struct mlx5_core_dev *mdev) { return (MLX5_CAP_ETH(mdev, tunnel_stateless_gre) && diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h new file mode 100644 index 000000000000..1c90059db5f8 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef __MLX5E_EN_REPORTER_H +#define __MLX5E_EN_REPORTER_H + +#include +#include "en.h" + +int mlx5e_tx_reporter_create(struct mlx5e_priv *priv); +void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv); +void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq); + +#endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c new file mode 100644 index 000000000000..35568e4820de --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#include +#include "reporter.h" +#include "lib/eq.h" + +#define MLX5E_TX_REPORTER_PER_SQ_MAX_LEN 256 + +struct mlx5e_tx_err_ctx { + int (*recover)(struct mlx5e_txqsq *sq); + struct mlx5e_txqsq *sq; +}; + +static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) +{ + unsigned long exp_time = jiffies + msecs_to_jiffies(2000); + + while (time_before(jiffies, exp_time)) { + if (sq->cc == sq->pc) + return 0; + + msleep(20); + } + + netdev_err(sq->channel->netdev, + "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n", + sq->sqn, sq->cc, sq->pc); + + return -ETIMEDOUT; +} + +static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq) +{ + WARN_ONCE(sq->cc != sq->pc, + "SQ 0x%x: cc (0x%x) != pc (0x%x)\n", + sq->sqn, sq->cc, sq->pc); + sq->cc = 0; + sq->dma_fifo_cc = 0; + sq->pc = 0; +} + +static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state) +{ + struct mlx5_core_dev *mdev = sq->channel->mdev; + struct net_device *dev = sq->channel->netdev; + struct mlx5e_modify_sq_param msp = {0}; + int err; + + msp.curr_state = curr_state; + msp.next_state = MLX5_SQC_STATE_RST; + + err = mlx5e_modify_sq(mdev, sq->sqn, &msp); + if (err) { + netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn); + return err; + } + + memset(&msp, 0, sizeof(msp)); + msp.curr_state = MLX5_SQC_STATE_RST; + msp.next_state = MLX5_SQC_STATE_RDY; + + err = mlx5e_modify_sq(mdev, sq->sqn, &msp); + if (err) { + netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn); + return err; + } + + return 0; +} + +static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq) +{ + struct mlx5_core_dev *mdev = sq->channel->mdev; + struct net_device *dev = sq->channel->netdev; + u8 state; + int err; + + if (!test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) + return 0; + + err = mlx5_core_query_sq_state(mdev, sq->sqn, &state); + if (err) { + netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n", + sq->sqn, err); + return err; + } + + if (state != MLX5_SQC_STATE_ERR) { + netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn); + return -EINVAL; + } + + mlx5e_tx_disable_queue(sq->txq); + + err = mlx5e_wait_for_sq_flush(sq); + if (err) + return err; + + /* At this point, no new packets will arrive from the stack as TXQ is + * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all + * pending WQEs. SQ can safely reset the SQ. + */ + + err = mlx5e_sq_to_ready(sq, state); + if (err) + return err; + + mlx5e_reset_txqsq_cc_pc(sq); + sq->stats->recover++; + mlx5e_activate_txqsq(sq); + + return 0; +} + +void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq) +{ + char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN]; + struct mlx5e_tx_err_ctx err_ctx = {0}; + + err_ctx.sq = sq; + err_ctx.recover = mlx5e_tx_reporter_err_cqe_recover; + sprintf(err_str, "ERR CQE on SQ: 0x%x", sq->sqn); + + devlink_health_report(sq->channel->priv->tx_reporter, err_str, + &err_ctx); +} + +/* state lock cannot be grabbed within this function. + * It can cause a dead lock or a read-after-free. + */ +int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_tx_err_ctx *err_ctx) +{ + return err_ctx->recover(err_ctx->sq); +} + +static int mlx5e_tx_reporter_recover_all(struct mlx5e_priv *priv) +{ + int err; + + rtnl_lock(); + mutex_lock(&priv->state_lock); + mlx5e_close_locked(priv->netdev); + err = mlx5e_open_locked(priv->netdev); + mutex_unlock(&priv->state_lock); + rtnl_unlock(); + + return err; +} + +static int mlx5e_tx_reporter_recover(struct devlink_health_reporter *reporter, + void *context) +{ + struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); + struct mlx5e_tx_err_ctx *err_ctx = context; + + return err_ctx ? mlx5e_tx_reporter_recover_from_ctx(err_ctx) : + mlx5e_tx_reporter_recover_all(priv); +} + +static int +mlx5e_tx_reporter_build_diagnose_output(struct devlink_fmsg *fmsg, + u32 sqn, u8 state, bool stopped) +{ + int err; + + err = devlink_fmsg_obj_nest_start(fmsg); + if (err) + return err; + + err = devlink_fmsg_u32_pair_put(fmsg, "sqn", sqn); + if (err) + return err; + + err = devlink_fmsg_u8_pair_put(fmsg, "HW state", state); + if (err) + return err; + + err = devlink_fmsg_bool_pair_put(fmsg, "stopped", stopped); + if (err) + return err; + + err = devlink_fmsg_obj_nest_end(fmsg); + if (err) + return err; + + return 0; +} + +static int mlx5e_tx_reporter_diagnose(struct devlink_health_reporter *reporter, + struct devlink_fmsg *fmsg) +{ + struct mlx5e_priv *priv = devlink_health_reporter_priv(reporter); + int i, err = 0; + + mutex_lock(&priv->state_lock); + + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) + goto unlock; + + err = devlink_fmsg_arr_pair_nest_start(fmsg, "SQs"); + if (err) + goto unlock; + + for (i = 0; i < priv->channels.num * priv->channels.params.num_tc; + i++) { + struct mlx5e_txqsq *sq = priv->txq2sq[i]; + u8 state; + + err = mlx5_core_query_sq_state(priv->mdev, sq->sqn, &state); + if (err) + break; + + err = mlx5e_tx_reporter_build_diagnose_output(fmsg, sq->sqn, + state, + netif_xmit_stopped(sq->txq)); + if (err) + break; + } + err = devlink_fmsg_arr_pair_nest_end(fmsg); + if (err) + goto unlock; + +unlock: + mutex_unlock(&priv->state_lock); + return err; +} + +static const struct devlink_health_reporter_ops mlx5_tx_reporter_ops = { + .name = "tx", + .recover = mlx5e_tx_reporter_recover, + .diagnose = mlx5e_tx_reporter_diagnose, +}; + +#define MLX5_REPORTER_TX_GRACEFUL_PERIOD 500 + +int mlx5e_tx_reporter_create(struct mlx5e_priv *priv) +{ + struct mlx5_core_dev *mdev = priv->mdev; + struct devlink *devlink = priv_to_devlink(mdev); + + priv->tx_reporter = + devlink_health_reporter_create(devlink, &mlx5_tx_reporter_ops, + MLX5_REPORTER_TX_GRACEFUL_PERIOD, + true, priv); + if (IS_ERR_OR_NULL(priv->tx_reporter)) + netdev_warn(priv->netdev, + "Failed to create tx reporter, err = %ld\n", + PTR_ERR(priv->tx_reporter)); + return PTR_ERR_OR_ZERO(priv->tx_reporter); +} + +void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv) +{ + if (IS_ERR_OR_NULL(priv->tx_reporter)) + return; + + devlink_health_reporter_destroy(priv->tx_reporter); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 099d307e6f25..93e1f037b019 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -51,6 +51,7 @@ #include "en/xdp.h" #include "lib/eq.h" #include "en/monitor_stats.h" +#include "en/reporter.h" struct mlx5e_rq_param { u32 rqc[MLX5_ST_SZ_DW(rqc)]; @@ -1159,7 +1160,7 @@ static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa) return 0; } -static void mlx5e_sq_recover(struct work_struct *work); +static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work); static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, int txq_ix, struct mlx5e_params *params, @@ -1181,7 +1182,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c, sq->uar_map = mdev->mlx5e_res.bfreg.map; sq->min_inline_mode = params->tx_min_inline_mode; sq->stats = &c->priv->channel_stats[c->ix].sq[tc]; - INIT_WORK(&sq->recover.recover_work, mlx5e_sq_recover); + INIT_WORK(&sq->recover_work, mlx5e_tx_err_cqe_work); if (MLX5_IPSEC_DEV(c->priv->mdev)) set_bit(MLX5E_SQ_STATE_IPSEC, &sq->state); if (mlx5_accel_is_tls_device(c->priv->mdev)) @@ -1269,15 +1270,8 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev, return err; } -struct mlx5e_modify_sq_param { - int curr_state; - int next_state; - bool rl_update; - int rl_index; -}; - -static int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, - struct mlx5e_modify_sq_param *p) +int mlx5e_modify_sq(struct mlx5_core_dev *mdev, u32 sqn, + struct mlx5e_modify_sq_param *p) { void *in; void *sqc; @@ -1375,17 +1369,7 @@ err_free_txqsq: return err; } -static void mlx5e_reset_txqsq_cc_pc(struct mlx5e_txqsq *sq) -{ - WARN_ONCE(sq->cc != sq->pc, - "SQ 0x%x: cc (0x%x) != pc (0x%x)\n", - sq->sqn, sq->cc, sq->pc); - sq->cc = 0; - sq->dma_fifo_cc = 0; - sq->pc = 0; -} - -static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) +void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) { sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix); clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state); @@ -1394,7 +1378,7 @@ static void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq) netif_tx_start_queue(sq->txq); } -static inline void netif_tx_disable_queue(struct netdev_queue *txq) +void mlx5e_tx_disable_queue(struct netdev_queue *txq) { __netif_tx_lock_bh(txq); netif_tx_stop_queue(txq); @@ -1410,7 +1394,7 @@ static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq) /* prevent netif_tx_wake_queue */ napi_synchronize(&c->napi); - netif_tx_disable_queue(sq->txq); + mlx5e_tx_disable_queue(sq->txq); /* last doorbell out, godspeed .. */ if (mlx5e_wqc_has_room_for(wq, sq->cc, sq->pc, 1)) { @@ -1430,6 +1414,7 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq) struct mlx5_rate_limit rl = {0}; cancel_work_sync(&sq->dim.work); + cancel_work_sync(&sq->recover_work); mlx5e_destroy_sq(mdev, sq->sqn); if (sq->rate_limit) { rl.rate = sq->rate_limit; @@ -1439,105 +1424,12 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq) mlx5e_free_txqsq(sq); } -static int mlx5e_wait_for_sq_flush(struct mlx5e_txqsq *sq) -{ - unsigned long exp_time = jiffies + msecs_to_jiffies(2000); - - while (time_before(jiffies, exp_time)) { - if (sq->cc == sq->pc) - return 0; - - msleep(20); - } - - netdev_err(sq->channel->netdev, - "Wait for SQ 0x%x flush timeout (sq cc = 0x%x, sq pc = 0x%x)\n", - sq->sqn, sq->cc, sq->pc); - - return -ETIMEDOUT; -} - -static int mlx5e_sq_to_ready(struct mlx5e_txqsq *sq, int curr_state) +static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work) { - struct mlx5_core_dev *mdev = sq->channel->mdev; - struct net_device *dev = sq->channel->netdev; - struct mlx5e_modify_sq_param msp = {0}; - int err; - - msp.curr_state = curr_state; - msp.next_state = MLX5_SQC_STATE_RST; - - err = mlx5e_modify_sq(mdev, sq->sqn, &msp); - if (err) { - netdev_err(dev, "Failed to move sq 0x%x to reset\n", sq->sqn); - return err; - } - - memset(&msp, 0, sizeof(msp)); - msp.curr_state = MLX5_SQC_STATE_RST; - msp.next_state = MLX5_SQC_STATE_RDY; - - err = mlx5e_modify_sq(mdev, sq->sqn, &msp); - if (err) { - netdev_err(dev, "Failed to move sq 0x%x to ready\n", sq->sqn); - return err; - } - - return 0; -} - -static void mlx5e_sq_recover(struct work_struct *work) -{ - struct mlx5e_txqsq_recover *recover = - container_of(work, struct mlx5e_txqsq_recover, - recover_work); - struct mlx5e_txqsq *sq = container_of(recover, struct mlx5e_txqsq, - recover); - struct mlx5_core_dev *mdev = sq->channel->mdev; - struct net_device *dev = sq->channel->netdev; - u8 state; - int err; - - err = mlx5_core_query_sq_state(mdev, sq->sqn, &state); - if (err) { - netdev_err(dev, "Failed to query SQ 0x%x state. err = %d\n", - sq->sqn, err); - return; - } - - if (state != MLX5_RQC_STATE_ERR) { - netdev_err(dev, "SQ 0x%x not in ERROR state\n", sq->sqn); - return; - } - - netif_tx_disable_queue(sq->txq); - - if (mlx5e_wait_for_sq_flush(sq)) - return; - - /* If the interval between two consecutive recovers per SQ is too - * short, don't recover to avoid infinite loop of ERR_CQE -> recover. - * If we reached this state, there is probably a bug that needs to be - * fixed. let's keep the queue close and let tx timeout cleanup. - */ - if (jiffies_to_msecs(jiffies - recover->last_recover) < - MLX5E_SQ_RECOVER_MIN_INTERVAL) { - netdev_err(dev, "Recover SQ 0x%x canceled, too many error CQEs\n", - sq->sqn); - return; - } - - /* At this point, no new packets will arrive from the stack as TXQ is - * marked with QUEUE_STATE_DRV_XOFF. In addition, NAPI cleared all - * pending WQEs. SQ can safely reset the SQ. - */ - if (mlx5e_sq_to_ready(sq, state)) - return; + struct mlx5e_txqsq *sq = container_of(recover_work, struct mlx5e_txqsq, + recover_work); - mlx5e_reset_txqsq_cc_pc(sq); - sq->stats->recover++; - recover->last_recover = jiffies; - mlx5e_activate_txqsq(sq); + mlx5e_tx_reporter_err_cqe(sq); } static int mlx5e_open_icosq(struct mlx5e_channel *c, @@ -3236,6 +3128,7 @@ static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv) { int tc; + mlx5e_tx_reporter_destroy(priv); for (tc = 0; tc < priv->profile->max_tc; tc++) mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]); } @@ -4953,6 +4846,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv) #ifdef CONFIG_MLX5_CORE_EN_DCB mlx5e_dcbnl_initialize(priv); #endif + mlx5e_tx_reporter_create(priv); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 598ad7e4d5c9..189211295e48 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -513,8 +513,9 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) &sq->state)) { mlx5e_dump_error_cqe(sq, (struct mlx5_err_cqe *)cqe); - queue_work(cq->channel->priv->wq, - &sq->recover.recover_work); + if (!IS_ERR_OR_NULL(cq->channel->priv->tx_reporter)) + queue_work(cq->channel->priv->wq, + &sq->recover_work); } stats->cqe_err++; } -- cgit v1.2.3 From 7d91126b1aea9eea7fdc9f5cd9e315002f33768d Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 7 Feb 2019 11:36:41 +0200 Subject: net/mlx5e: Add tx timeout support for mlx5e tx reporter With this patch, ndo_tx_timeout callback will be redirected to the tx reporter in order to detect a tx timeout error and report it to the devlink health. (The watchdog detects tx timeouts, but the driver verify the issue still exists before launching any recover method). In addition, recover from tx timeout in case of lost interrupt was added to the tx reporter recover method. The tx timeout recover from lost interrupt is not a new feature in the driver, this patch re-organize the functionality and move it to the tx reporter recovery flow. tx timeout example: (with auto_recover set to false, if set to true, the manual recover and diagnose sections are irrelevant) $cat /sys/kernel/debug/tracing/trace ... devlink_health_report: bus_name=pci dev_name=0000:00:09.0 driver_name=mlx5_core reporter_name=tx: TX timeout on queue: 0, SQ: 0x8a, CQ: 0x35, SQ Cons: 0x2 SQ Prod: 0x2, usecs since last trans: 14912000 $devlink health show pci/0000:00:09.0: name tx state healthy #err 1 #recover 0 last_dump_ts N/A parameters: grace_period 500 auto_recover false $devlink health diagnose pci/0000:00:09.0 reporter tx -j -p { "SQs": [ { "sqn": 138, "HW state": 1, "stopped": true },{ "sqn": 142, "HW state": 1, "stopped": false } ] } $devlink health diagnose pci/0000:00:09.0 reporter tx SQs: sqn: 138 HW state: 1 stopped: true sqn: 142 HW state: 1 stopped: false $devlink health recover pci/0000:00:09 reporter tx $devlink health show pci/0000:00:09.0: name tx state healthy #err 1 #recover 1 last_dump_ts N/A parameters: grace_period 500 auto_recover false Signed-off-by: Eran Ben Elisha Reviewed-by: Moshe Shemesh Acked-by: Saeed Mahameed Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/en/reporter.h | 1 + .../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 38 ++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 53 +++++++--------------- 3 files changed, 55 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h index 1c90059db5f8..e78e92753d73 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter.h @@ -10,5 +10,6 @@ int mlx5e_tx_reporter_create(struct mlx5e_priv *priv); void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv); void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq); +int mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq); #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 35568e4820de..0aebfb377cf0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -126,6 +126,44 @@ void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq) &err_ctx); } +static int mlx5e_tx_reporter_timeout_recover(struct mlx5e_txqsq *sq) +{ + struct mlx5_eq_comp *eq = sq->cq.mcq.eq; + u32 eqe_count; + int ret; + + netdev_err(sq->channel->netdev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n", + eq->core.eqn, eq->core.cons_index, eq->core.irqn); + + eqe_count = mlx5_eq_poll_irq_disabled(eq); + ret = eqe_count ? true : false; + if (!eqe_count) { + clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); + return ret; + } + + netdev_err(sq->channel->netdev, "Recover %d eqes on EQ 0x%x\n", + eqe_count, eq->core.eqn); + sq->channel->stats->eq_rearm++; + return ret; +} + +int mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq) +{ + char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN]; + struct mlx5e_tx_err_ctx err_ctx; + + err_ctx.sq = sq; + err_ctx.recover = mlx5e_tx_reporter_timeout_recover; + sprintf(err_str, + "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n", + sq->channel->ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc, + jiffies_to_usecs(jiffies - sq->txq->trans_start)); + + return devlink_health_report(sq->channel->priv->tx_reporter, err_str, + &err_ctx); +} + /* state lock cannot be grabbed within this function. * It can cause a dead lock or a read-after-free. */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 93e1f037b019..d81ebba7c04e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4116,31 +4116,13 @@ netdev_features_t mlx5e_features_check(struct sk_buff *skb, return features; } -static bool mlx5e_tx_timeout_eq_recover(struct net_device *dev, - struct mlx5e_txqsq *sq) -{ - struct mlx5_eq_comp *eq = sq->cq.mcq.eq; - u32 eqe_count; - - netdev_err(dev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n", - eq->core.eqn, eq->core.cons_index, eq->core.irqn); - - eqe_count = mlx5_eq_poll_irq_disabled(eq); - if (!eqe_count) - return false; - - netdev_err(dev, "Recover %d eqes on EQ 0x%x\n", eqe_count, eq->core.eqn); - sq->channel->stats->eq_rearm++; - return true; -} - static void mlx5e_tx_timeout_work(struct work_struct *work) { struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv, tx_timeout_work); - struct net_device *dev = priv->netdev; - bool reopen_channels = false; - int i, err; + bool report_failed = false; + int err; + int i; rtnl_lock(); mutex_lock(&priv->state_lock); @@ -4149,31 +4131,22 @@ static void mlx5e_tx_timeout_work(struct work_struct *work) goto unlock; for (i = 0; i < priv->channels.num * priv->channels.params.num_tc; i++) { - struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, i); + struct netdev_queue *dev_queue = + netdev_get_tx_queue(priv->netdev, i); struct mlx5e_txqsq *sq = priv->txq2sq[i]; if (!netif_xmit_stopped(dev_queue)) continue; - netdev_err(dev, - "TX timeout on queue: %d, SQ: 0x%x, CQ: 0x%x, SQ Cons: 0x%x SQ Prod: 0x%x, usecs since last trans: %u\n", - i, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc, - jiffies_to_usecs(jiffies - dev_queue->trans_start)); - - /* If we recover a lost interrupt, most likely TX timeout will - * be resolved, skip reopening channels - */ - if (!mlx5e_tx_timeout_eq_recover(dev, sq)) { - clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); - reopen_channels = true; - } + if (mlx5e_tx_reporter_timeout(sq)) + report_failed = true; } - if (!reopen_channels) + if (!report_failed) goto unlock; - mlx5e_close_locked(dev); - err = mlx5e_open_locked(dev); + mlx5e_close_locked(priv->netdev); + err = mlx5e_open_locked(priv->netdev); if (err) netdev_err(priv->netdev, "mlx5e_open_locked failed recovering from a tx_timeout, err(%d).\n", @@ -4189,6 +4162,12 @@ static void mlx5e_tx_timeout(struct net_device *dev) struct mlx5e_priv *priv = netdev_priv(dev); netdev_err(dev, "TX timeout detected\n"); + + if (IS_ERR_OR_NULL(priv->tx_reporter)) { + netdev_err_once(priv->netdev, "tx timeout will not be handled, no valid tx reporter\n"); + return; + } + queue_work(priv->wq, &priv->tx_timeout_work); } -- cgit v1.2.3 From fc4aa1ca1628d31d1e2770b96a3bd8e25eef118d Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Thu, 7 Feb 2019 12:18:02 +0000 Subject: net: vxlan: Free a leaked vetoed multicast rdst When an rdst is rejected by a driver, the current code removes it from the remote list, but neglects to free it. This is triggered by tools/testing/selftests/drivers/net/mlxsw/vxlan_fdb_veto.sh and shows as the following kmemleak trace: unreferenced object 0xffff88817fa3d888 (size 96): comm "softirq", pid 0, jiffies 4372702718 (age 165.252s) hex dump (first 32 bytes): 02 00 00 00 c6 33 64 03 80 f5 a2 61 81 88 ff ff .....3d....a.... 06 df 71 ae ff ff ff ff 0c 00 00 00 04 d2 6a 6b ..q...........jk backtrace: [<00000000296b27ac>] kmem_cache_alloc_trace+0x1ae/0x370 [<0000000075c86dc6>] vxlan_fdb_append.part.12+0x62/0x3b0 [vxlan] [<00000000e0414b63>] vxlan_fdb_update+0xc61/0x1020 [vxlan] [<00000000f330c4bd>] vxlan_fdb_add+0x2e8/0x3d0 [vxlan] [<0000000008f81c2c>] rtnl_fdb_add+0x4c2/0xa10 [<00000000bdc4b270>] rtnetlink_rcv_msg+0x6dd/0x970 [<000000006701f2ce>] netlink_rcv_skb+0x290/0x410 [<00000000c08a5487>] rtnetlink_rcv+0x15/0x20 [<00000000d5f54b1e>] netlink_unicast+0x43f/0x5e0 [<00000000db4336bb>] netlink_sendmsg+0x789/0xcd0 [<00000000e1ee26b6>] sock_sendmsg+0xba/0x100 [<00000000ba409802>] ___sys_sendmsg+0x631/0x960 [<000000003c332113>] __sys_sendmsg+0xea/0x180 [<00000000f4139144>] __x64_sys_sendmsg+0x78/0xb0 [<000000006d1ddc59>] do_syscall_64+0x94/0x410 [<00000000c8defa9a>] entry_SYSCALL_64_after_hwframe+0x49/0xbe Move vxlan_dst_free() up and schedule a call thereof to plug this leak. Fixes: 61f46fe8c646 ("vxlan: Allow vetoing of FDB notifications") Signed-off-by: Petr Machata Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index ef45c3c925be..c0cd1c022e77 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -869,6 +869,14 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, call_rcu(&f->rcu, vxlan_fdb_free); } +static void vxlan_dst_free(struct rcu_head *head) +{ + struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu); + + dst_cache_destroy(&rd->dst_cache); + kfree(rd); +} + static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, union vxlan_addr *ip, __u16 state, __u16 flags, @@ -941,8 +949,10 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, err_notify: if ((flags & NLM_F_REPLACE) && rc) *rd = oldrd; - else if ((flags & NLM_F_APPEND) && rc) + else if ((flags & NLM_F_APPEND) && rc) { list_del_rcu(&rd->list); + call_rcu(&rd->rcu, vxlan_dst_free); + } return err; } @@ -1013,14 +1023,6 @@ static int vxlan_fdb_update(struct vxlan_dev *vxlan, } } -static void vxlan_dst_free(struct rcu_head *head) -{ - struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu); - - dst_cache_destroy(&rd->dst_cache); - kfree(rd); -} - static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f, struct vxlan_rdst *rd, bool swdev_notify) { -- cgit v1.2.3 From 14dc100b4411a77a0cb63d049caf184434b18377 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 7 Feb 2019 16:19:10 +0000 Subject: phy: armada38x: add common phy support Add support for the Armada 38x common phy to allow us to change the speed of the Ethernet serdes lane. This driver only supports manipulation of the speed, it does not support configuration of the common phy. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/phy/marvell/Kconfig | 10 ++ drivers/phy/marvell/Makefile | 1 + drivers/phy/marvell/phy-armada38x-comphy.c | 237 +++++++++++++++++++++++++++++ 3 files changed, 248 insertions(+) create mode 100644 drivers/phy/marvell/phy-armada38x-comphy.c (limited to 'drivers') diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig index 6fb4b56e4c14..224ea4e6a46d 100644 --- a/drivers/phy/marvell/Kconfig +++ b/drivers/phy/marvell/Kconfig @@ -21,6 +21,16 @@ config PHY_BERLIN_USB help Enable this to support the USB PHY on Marvell Berlin SoCs. +config PHY_MVEBU_A38X_COMPHY + tristate "Marvell Armada 38x comphy driver" + depends on ARCH_MVEBU || COMPILE_TEST + depends on OF + select GENERIC_PHY + help + This driver allows to control the comphy, an hardware block providing + shared serdes PHYs on Marvell Armada 38x. Its serdes lanes can be + used by various controllers (Ethernet, sata, usb, PCIe...). + config PHY_MVEBU_CP110_COMPHY tristate "Marvell CP110 comphy driver" depends on ARCH_MVEBU || COMPILE_TEST diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile index 3975b144f8ec..59b6c03ef756 100644 --- a/drivers/phy/marvell/Makefile +++ b/drivers/phy/marvell/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o +obj-$(CONFIG_PHY_MVEBU_A38X_COMPHY) += phy-armada38x-comphy.o obj-$(CONFIG_PHY_MVEBU_CP110_COMPHY) += phy-mvebu-cp110-comphy.o obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o diff --git a/drivers/phy/marvell/phy-armada38x-comphy.c b/drivers/phy/marvell/phy-armada38x-comphy.c new file mode 100644 index 000000000000..3e00bc679d4e --- /dev/null +++ b/drivers/phy/marvell/phy-armada38x-comphy.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Russell King, Deep Blue Solutions Ltd. + * + * Partly derived from CP110 comphy driver by Antoine Tenart + * + */ +#include +#include +#include +#include +#include +#include + +#define MAX_A38X_COMPHY 6 +#define MAX_A38X_PORTS 3 + +#define COMPHY_CFG1 0x00 +#define COMPHY_CFG1_GEN_TX(x) ((x) << 26) +#define COMPHY_CFG1_GEN_TX_MSK COMPHY_CFG1_GEN_TX(15) +#define COMPHY_CFG1_GEN_RX(x) ((x) << 22) +#define COMPHY_CFG1_GEN_RX_MSK COMPHY_CFG1_GEN_RX(15) +#define GEN_SGMII_1_25GBPS 6 +#define GEN_SGMII_3_125GBPS 8 + +#define COMPHY_STAT1 0x18 +#define COMPHY_STAT1_PLL_RDY_TX BIT(3) +#define COMPHY_STAT1_PLL_RDY_RX BIT(2) + +#define COMPHY_SELECTOR 0xfc + +struct a38x_comphy; + +struct a38x_comphy_lane { + void __iomem *base; + struct a38x_comphy *priv; + unsigned int n; + + int port; +}; + +struct a38x_comphy { + void __iomem *base; + struct device *dev; + struct a38x_comphy_lane lane[MAX_A38X_COMPHY]; +}; + +static const u8 gbe_mux[MAX_A38X_COMPHY][MAX_A38X_PORTS] = { + { 0, 0, 0 }, + { 4, 5, 0 }, + { 0, 4, 0 }, + { 0, 0, 4 }, + { 0, 3, 0 }, + { 0, 0, 3 }, +}; + +static void a38x_comphy_set_reg(struct a38x_comphy_lane *lane, + unsigned int offset, u32 mask, u32 value) +{ + u32 val; + + val = readl_relaxed(lane->base + offset) & ~mask; + writel(val | value, lane->base + offset); +} + +static void a38x_comphy_set_speed(struct a38x_comphy_lane *lane, + unsigned int gen_tx, unsigned int gen_rx) +{ + a38x_comphy_set_reg(lane, COMPHY_CFG1, + COMPHY_CFG1_GEN_TX_MSK | COMPHY_CFG1_GEN_RX_MSK, + COMPHY_CFG1_GEN_TX(gen_tx) | + COMPHY_CFG1_GEN_RX(gen_rx)); +} + +static int a38x_comphy_poll(struct a38x_comphy_lane *lane, + unsigned int offset, u32 mask, u32 value) +{ + u32 val; + int ret; + + ret = readl_relaxed_poll_timeout_atomic(lane->base + offset, val, + (val & mask) == value, + 1000, 150000); + + if (ret) + dev_err(lane->priv->dev, + "comphy%u: timed out waiting for status\n", lane->n); + + return ret; +} + +/* + * We only support changing the speed for comphys configured for GBE. + * Since that is all we do, we only poll for PLL ready status. + */ +static int a38x_comphy_set_mode(struct phy *phy, enum phy_mode mode, int sub) +{ + struct a38x_comphy_lane *lane = phy_get_drvdata(phy); + unsigned int gen; + + if (mode != PHY_MODE_ETHERNET) + return -EINVAL; + + switch (sub) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + gen = GEN_SGMII_1_25GBPS; + break; + + case PHY_INTERFACE_MODE_2500BASEX: + gen = GEN_SGMII_3_125GBPS; + break; + + default: + return -EINVAL; + } + + a38x_comphy_set_speed(lane, gen, gen); + + return a38x_comphy_poll(lane, COMPHY_STAT1, + COMPHY_STAT1_PLL_RDY_TX | + COMPHY_STAT1_PLL_RDY_RX, + COMPHY_STAT1_PLL_RDY_TX | + COMPHY_STAT1_PLL_RDY_RX); +} + +static const struct phy_ops a38x_comphy_ops = { + .set_mode = a38x_comphy_set_mode, + .owner = THIS_MODULE, +}; + +static struct phy *a38x_comphy_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct a38x_comphy_lane *lane; + struct phy *phy; + u32 val; + + if (WARN_ON(args->args[0] >= MAX_A38X_PORTS)) + return ERR_PTR(-EINVAL); + + phy = of_phy_simple_xlate(dev, args); + if (IS_ERR(phy)) + return phy; + + lane = phy_get_drvdata(phy); + if (lane->port >= 0) + return ERR_PTR(-EBUSY); + + lane->port = args->args[0]; + + val = readl_relaxed(lane->priv->base + COMPHY_SELECTOR); + val = (val >> (4 * lane->n)) & 0xf; + + if (!gbe_mux[lane->n][lane->port] || + val != gbe_mux[lane->n][lane->port]) { + dev_warn(lane->priv->dev, + "comphy%u: not configured for GBE\n", lane->n); + phy = ERR_PTR(-EINVAL); + } + + return phy; +} + +static int a38x_comphy_probe(struct platform_device *pdev) +{ + struct phy_provider *provider; + struct device_node *child; + struct a38x_comphy *priv; + struct resource *res; + void __iomem *base; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->dev = &pdev->dev; + priv->base = base; + + for_each_available_child_of_node(pdev->dev.of_node, child) { + struct phy *phy; + int ret; + u32 val; + + ret = of_property_read_u32(child, "reg", &val); + if (ret < 0) { + dev_err(&pdev->dev, "missing 'reg' property (%d)\n", + ret); + continue; + } + + if (val >= MAX_A38X_COMPHY || priv->lane[val].base) { + dev_err(&pdev->dev, "invalid 'reg' property\n"); + continue; + } + + phy = devm_phy_create(&pdev->dev, child, &a38x_comphy_ops); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + priv->lane[val].base = base + 0x28 * val; + priv->lane[val].priv = priv; + priv->lane[val].n = val; + priv->lane[val].port = -1; + phy_set_drvdata(phy, &priv->lane[val]); + } + + dev_set_drvdata(&pdev->dev, priv); + + provider = devm_of_phy_provider_register(&pdev->dev, a38x_comphy_xlate); + + return PTR_ERR_OR_ZERO(provider); +} + +static const struct of_device_id a38x_comphy_of_match_table[] = { + { .compatible = "marvell,armada-380-comphy" }, + { }, +}; +MODULE_DEVICE_TABLE(of, a38x_comphy_of_match_table); + +static struct platform_driver a38x_comphy_driver = { + .probe = a38x_comphy_probe, + .driver = { + .name = "armada-38x-comphy", + .of_match_table = a38x_comphy_of_match_table, + }, +}; +module_platform_driver(a38x_comphy_driver); + +MODULE_AUTHOR("Russell King "); +MODULE_DESCRIPTION("Common PHY driver for Armada 38x SoCs"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From a10c1c8191e04c21769656c2ca8e1c69a6218954 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 7 Feb 2019 16:19:26 +0000 Subject: net: marvell: neta: add comphy support Add support for the common phy binding, so that we can reconfigure the comphy according to the desired ethernet speed. This will allow us to support 1000base-X and 2500base-X SFPs dynamically on SolidRun Clearfog. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 45 +++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 9d4568eb2297..d134d3538f9b 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -436,6 +437,7 @@ struct mvneta_port { struct device_node *dn; unsigned int tx_csum_limit; struct phylink *phylink; + struct phy *comphy; struct mvneta_bm *bm_priv; struct mvneta_bm_pool *pool_long; @@ -3151,6 +3153,8 @@ static void mvneta_start_dev(struct mvneta_port *pp) { int cpu; + WARN_ON(phy_power_on(pp->comphy)); + mvneta_max_rx_size_set(pp, pp->pkt_size); mvneta_txq_max_tx_size_set(pp, pp->pkt_size); @@ -3213,6 +3217,8 @@ static void mvneta_stop_dev(struct mvneta_port *pp) mvneta_tx_reset(pp); mvneta_rx_reset(pp); + + WARN_ON(phy_power_off(pp->comphy)); } static void mvneta_percpu_enable(void *arg) @@ -3338,6 +3344,7 @@ static int mvneta_set_mac_addr(struct net_device *dev, void *addr) static void mvneta_validate(struct net_device *ndev, unsigned long *supported, struct phylink_link_state *state) { + struct mvneta_port *pp = netdev_priv(ndev); __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; /* We only support QSGMII, SGMII, 802.3z and RGMII modes */ @@ -3358,8 +3365,13 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported, phylink_set(mask, Pause); /* Half-duplex at speeds higher than 100Mbit is unsupported */ - phylink_set(mask, 1000baseT_Full); - phylink_set(mask, 1000baseX_Full); + if (pp->comphy || state->interface != PHY_INTERFACE_MODE_2500BASEX) { + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseX_Full); + } + if (pp->comphy || state->interface == PHY_INTERFACE_MODE_2500BASEX) { + phylink_set(mask, 2500baseX_Full); + } if (!phy_interface_mode_is_8023z(state->interface)) { /* 10M and 100M are only supported in non-802.3z mode */ @@ -3373,6 +3385,11 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported, __ETHTOOL_LINK_MODE_MASK_NBITS); bitmap_and(state->advertising, state->advertising, mask, __ETHTOOL_LINK_MODE_MASK_NBITS); + + /* 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 mvneta_mac_link_state(struct net_device *ndev, @@ -3384,7 +3401,9 @@ static int mvneta_mac_link_state(struct net_device *ndev, gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); if (gmac_stat & MVNETA_GMAC_SPEED_1000) - state->speed = SPEED_1000; + state->speed = + state->interface == PHY_INTERFACE_MODE_2500BASEX ? + SPEED_2500 : SPEED_1000; else if (gmac_stat & MVNETA_GMAC_SPEED_100) state->speed = SPEED_100; else @@ -3499,12 +3518,20 @@ static void mvneta_mac_config(struct net_device *ndev, unsigned int mode, MVNETA_GMAC_FORCE_LINK_DOWN); } + /* When at 2.5G, the link partner can send frames with shortened * preambles. */ if (state->speed == SPEED_2500) new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE; + if (pp->comphy && + (state->interface == PHY_INTERFACE_MODE_SGMII || + state->interface == PHY_INTERFACE_MODE_1000BASEX || + state->interface == PHY_INTERFACE_MODE_2500BASEX)) + WARN_ON(phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, + state->interface)); + if (new_ctrl0 != gmac_ctrl0) mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); if (new_ctrl2 != gmac_ctrl2) @@ -4404,7 +4431,7 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) if (phy_mode == PHY_INTERFACE_MODE_QSGMII) mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO); else if (phy_mode == PHY_INTERFACE_MODE_SGMII || - phy_mode == PHY_INTERFACE_MODE_1000BASEX) + phy_interface_mode_is_8023z(phy_mode)) mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); else if (!phy_interface_mode_is_rgmii(phy_mode)) return -EINVAL; @@ -4421,6 +4448,7 @@ static int mvneta_probe(struct platform_device *pdev) struct mvneta_port *pp; struct net_device *dev; struct phylink *phylink; + struct phy *comphy; const char *dt_mac_addr; char hw_mac_addr[ETH_ALEN]; const char *mac_from; @@ -4446,6 +4474,14 @@ static int mvneta_probe(struct platform_device *pdev) goto err_free_irq; } + comphy = devm_of_phy_get(&pdev->dev, dn, NULL); + if (comphy == ERR_PTR(-EPROBE_DEFER)) { + err = -EPROBE_DEFER; + goto err_free_irq; + } else if (IS_ERR(comphy)) { + comphy = NULL; + } + phylink = phylink_create(dev, pdev->dev.fwnode, phy_mode, &mvneta_phylink_ops); if (IS_ERR(phylink)) { @@ -4462,6 +4498,7 @@ static int mvneta_probe(struct platform_device *pdev) pp = netdev_priv(dev); spin_lock_init(&pp->lock); pp->phylink = phylink; + pp->comphy = comphy; pp->phy_interface = phy_mode; pp->dn = dn; -- cgit v1.2.3 From 71bd106d2567675668e253cba3960e3c4bf2e80e Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Thu, 7 Feb 2019 09:52:10 -0800 Subject: net: fixed-phy: Add fixed_phy_register_with_gpiod() API Add fixed_phy_register_with_gpiod() API. It lets users create a fixed_phy instance that uses a GPIO descriptor which was obtained externally e.g. through platform data. This enables platform devices (non-DT based) to use GPIOs for link status. Signed-off-by: Moritz Fischer Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/fixed_phy.c | 32 +++++++++++++++++++++++++------- include/linux/phy_fixed.h | 15 +++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index d810f914aaa4..b0d1368c3400 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -229,12 +229,12 @@ static struct gpio_desc *fixed_phy_get_gpiod(struct device_node *np) } #endif -struct phy_device *fixed_phy_register(unsigned int irq, - struct fixed_phy_status *status, - struct device_node *np) +static struct phy_device *__fixed_phy_register(unsigned int irq, + struct fixed_phy_status *status, + struct device_node *np, + struct gpio_desc *gpiod) { struct fixed_mdio_bus *fmb = &platform_fmb; - struct gpio_desc *gpiod = NULL; struct phy_device *phy; int phy_addr; int ret; @@ -243,9 +243,11 @@ struct phy_device *fixed_phy_register(unsigned int irq, return ERR_PTR(-EPROBE_DEFER); /* Check if we have a GPIO associated with this fixed phy */ - gpiod = fixed_phy_get_gpiod(np); - if (IS_ERR(gpiod)) - return ERR_CAST(gpiod); + if (!gpiod) { + gpiod = fixed_phy_get_gpiod(np); + if (IS_ERR(gpiod)) + return ERR_CAST(gpiod); + } /* Get the next available PHY address, up to PHY_MAX_ADDR */ phy_addr = ida_simple_get(&phy_fixed_ida, 0, PHY_MAX_ADDR, GFP_KERNEL); @@ -308,8 +310,24 @@ struct phy_device *fixed_phy_register(unsigned int irq, return phy; } + +struct phy_device *fixed_phy_register(unsigned int irq, + struct fixed_phy_status *status, + struct device_node *np) +{ + return __fixed_phy_register(irq, status, np, NULL); +} EXPORT_SYMBOL_GPL(fixed_phy_register); +struct phy_device * +fixed_phy_register_with_gpiod(unsigned int irq, + struct fixed_phy_status *status, + struct gpio_desc *gpiod) +{ + return __fixed_phy_register(irq, status, NULL, gpiod); +} +EXPORT_SYMBOL_GPL(fixed_phy_register_with_gpiod); + void fixed_phy_unregister(struct phy_device *phy) { phy_device_remove(phy); diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h index c78fc203db43..1e5d86ebdaeb 100644 --- a/include/linux/phy_fixed.h +++ b/include/linux/phy_fixed.h @@ -19,6 +19,12 @@ extern int fixed_phy_add(unsigned int irq, int phy_id, extern struct phy_device *fixed_phy_register(unsigned int irq, struct fixed_phy_status *status, struct device_node *np); + +extern struct phy_device * +fixed_phy_register_with_gpiod(unsigned int irq, + struct fixed_phy_status *status, + struct gpio_desc *gpiod); + extern void fixed_phy_unregister(struct phy_device *phydev); extern int fixed_phy_set_link_update(struct phy_device *phydev, int (*link_update)(struct net_device *, @@ -35,6 +41,15 @@ static inline struct phy_device *fixed_phy_register(unsigned int irq, { return ERR_PTR(-ENODEV); } + +static inline struct phy_device * +fixed_phy_register_with_gpiod(unsigned int irq, + struct fixed_phy_status *status, + struct gpio_desc *gpiod) +{ + return ERR_PTR(-ENODEV); +} + static inline void fixed_phy_unregister(struct phy_device *phydev) { } -- cgit v1.2.3 From 998a8a8387ff5f65da456d1fc448dbb926fb5d78 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 7 Feb 2019 21:41:46 +0100 Subject: net: phy: let genphy_c45_read_link manage the devices to check Let genphy_c45_read_link manage the devices to check, this removes overhead from callers. Add C22EXT to the list of excluded devices because it doesn't implement the status register. According to the 802.3 clause 45 spec registers 29.0 - 29.4 are reserved. At the moment we have very few clause 45 PHY drivers, so we are lacking experience whether other drivers will have to exclude further devices, or may need to check PHY XS. If we should figure out that list of devices to check needs to be configurable, I think best will be to add a device list member to struct phy_driver. v2: - adjusted commit message - exclude also device C22EXT from link checking Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 10 +--------- drivers/net/phy/phy-c45.c | 18 ++++++++++-------- include/linux/phy.h | 2 +- include/uapi/linux/mdio.h | 2 ++ 4 files changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 296a537cdfcb..96a79c6c7810 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -428,16 +428,8 @@ static int mv3310_read_10gbr_status(struct phy_device *phydev) static int mv3310_read_status(struct phy_device *phydev) { - u32 mmd_mask = phydev->c45_ids.devices_in_package; int val; - /* The vendor devads do not report link status. Avoid the PHYXS - * instance as there are three, and its status depends on the MAC - * being appropriately configured for the negotiated speed. - */ - mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2) | - BIT(MDIO_MMD_PHYXS)); - phydev->speed = SPEED_UNKNOWN; phydev->duplex = DUPLEX_UNKNOWN; linkmode_zero(phydev->lp_advertising); @@ -453,7 +445,7 @@ static int mv3310_read_status(struct phy_device *phydev) if (val & MDIO_STAT1_LSTATUS) return mv3310_read_10gbr_status(phydev); - val = genphy_c45_read_link(phydev, mmd_mask); + val = genphy_c45_read_link(phydev); if (val < 0) return val; diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index c92d0fb7ec4f..6adfe1f6319e 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -118,17 +118,24 @@ EXPORT_SYMBOL_GPL(genphy_c45_aneg_done); /** * genphy_c45_read_link - read the overall link status from the MMDs * @phydev: target phy_device struct - * @mmd_mask: MMDs to read status from * * Read the link status from the specified MMDs, and if they all indicate * that the link is up, set phydev->link to 1. If an error is encountered, * a negative errno will be returned, otherwise zero. */ -int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask) +int genphy_c45_read_link(struct phy_device *phydev) { + u32 mmd_mask = phydev->c45_ids.devices_in_package; int val, devad; bool link = true; + /* The vendor devads and C22EXT do not report link status. Avoid the + * PHYXS instance as its status may depend on the MAC being + * appropriately configured for the negotiated speed. + */ + mmd_mask &= ~(MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2 | MDIO_DEVS_C22EXT | + MDIO_DEVS_PHYXS); + while (mmd_mask && link) { devad = __ffs(mmd_mask); mmd_mask &= ~BIT(devad); @@ -266,16 +273,11 @@ EXPORT_SYMBOL_GPL(gen10g_config_aneg); int gen10g_read_status(struct phy_device *phydev) { - u32 mmd_mask = phydev->c45_ids.devices_in_package; - /* For now just lie and say it's 10G all the time */ phydev->speed = SPEED_10000; phydev->duplex = DUPLEX_FULL; - /* Avoid reading the vendor MMDs */ - mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2)); - - return genphy_c45_read_link(phydev, mmd_mask); + return genphy_c45_read_link(phydev); } EXPORT_SYMBOL_GPL(gen10g_read_status); diff --git a/include/linux/phy.h b/include/linux/phy.h index 237dd035858a..f41bf651f6a0 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1094,7 +1094,7 @@ int genphy_write_mmd_unsupported(struct phy_device *phdev, int devnum, /* Clause 45 PHY */ int genphy_c45_restart_aneg(struct phy_device *phydev); int genphy_c45_aneg_done(struct phy_device *phydev); -int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask); +int genphy_c45_read_link(struct phy_device *phydev); int genphy_c45_read_lpa(struct phy_device *phydev); int genphy_c45_read_pma(struct phy_device *phydev); int genphy_c45_pma_setup_forced(struct phy_device *phydev); diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h index d435b00d64ad..2e6e309f0847 100644 --- a/include/uapi/linux/mdio.h +++ b/include/uapi/linux/mdio.h @@ -123,6 +123,8 @@ #define MDIO_DEVS_TC MDIO_DEVS_PRESENT(MDIO_MMD_TC) #define MDIO_DEVS_AN MDIO_DEVS_PRESENT(MDIO_MMD_AN) #define MDIO_DEVS_C22EXT MDIO_DEVS_PRESENT(MDIO_MMD_C22EXT) +#define MDIO_DEVS_VEND1 MDIO_DEVS_PRESENT(MDIO_MMD_VEND1) +#define MDIO_DEVS_VEND2 MDIO_DEVS_PRESENT(MDIO_MMD_VEND2) /* Control register 2. */ #define MDIO_PMA_CTRL2_TYPE 0x000f /* PMA/PMD type selection */ -- cgit v1.2.3 From 040bda85b5dff5790f6ebe562e0b6ca09c851440 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Dec 2018 14:10:50 +0200 Subject: mac80211_hwsim: Declare support for Multi-BSSID This can be used to test cfg80211 support for Multi-BSSID scan result parsing. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- drivers/net/wireless/mac80211_hwsim.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 87be2b18063a..e8e359c80ad0 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2801,6 +2801,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ieee80211_hw_set(hw, TDLS_WIDER_BW); if (rctbl) ieee80211_hw_set(hw, SUPPORTS_RC_TABLE); + ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | -- cgit v1.2.3 From 5cc898fbcb352b764f8d51c16e10e2eb0056173d Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 6 Feb 2019 12:28:15 +0100 Subject: brcmfmac: modify __brcmf_err() to take bus as a parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far __brcmf_err() was using pr_err() which didn't allow identifying device that was affected by an error. It's crucial for systems with more than 1 device supported by brcmfmac (a common case for home routers). This change allows passing struct brcmf_bus to the __brcmf_err(). That struct has been agreed to be the most common one. It allows accessing struct device easily & using dev_err() printing helper. Signed-off-by: Rafał Miłecki Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 7 +++++-- drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h | 8 +++++--- drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c | 9 +++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 0ce1d8174e6d..c62009a06617 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -350,7 +350,7 @@ done: } #ifndef CONFIG_BRCM_TRACING -void __brcmf_err(const char *func, const char *fmt, ...) +void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...) { struct va_format vaf; va_list args; @@ -359,7 +359,10 @@ void __brcmf_err(const char *func, const char *fmt, ...) vaf.fmt = fmt; vaf.va = &args; - pr_err("%s: %pV", func, &vaf); + if (bus) + dev_err(bus->dev, "%s: %pV", func, &vaf); + else + pr_err("%s: %pV", func, &vaf); va_end(args); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h index cfed0626bf5a..b499f90d94f6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h @@ -45,8 +45,10 @@ #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -__printf(2, 3) -void __brcmf_err(const char *func, const char *fmt, ...); +struct brcmf_bus; + +__printf(3, 4) +void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...); /* Macro for error messages. When debugging / tracing the driver all error * messages are important to us. */ @@ -55,7 +57,7 @@ void __brcmf_err(const char *func, const char *fmt, ...); if (IS_ENABLED(CONFIG_BRCMDBG) || \ IS_ENABLED(CONFIG_BRCM_TRACING) || \ net_ratelimit()) \ - __brcmf_err(__func__, fmt, ##__VA_ARGS__); \ + __brcmf_err(NULL, __func__, fmt, ##__VA_ARGS__);\ } while (0) #if defined(DEBUG) || defined(CONFIG_BRCM_TRACING) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c index fe6755944b7b..a5c271bff446 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c @@ -14,14 +14,16 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include /* bug in tracepoint.h, it should include this */ #ifndef __CHECKER__ #define CREATE_TRACE_POINTS +#include "bus.h" #include "tracepoint.h" #include "debug.h" -void __brcmf_err(const char *func, const char *fmt, ...) +void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...) { struct va_format vaf = { .fmt = fmt, @@ -30,7 +32,10 @@ void __brcmf_err(const char *func, const char *fmt, ...) va_start(args, fmt); vaf.va = &args; - pr_err("%s: %pV", func, &vaf); + if (bus) + dev_err(bus->dev, "%s: %pV", func, &vaf); + else + pr_err("%s: %pV", func, &vaf); trace_brcmf_err(func, &vaf); va_end(args); } -- cgit v1.2.3 From 8602e62441aba276cafd68034b72162fbc5ca0a6 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 6 Feb 2019 12:28:16 +0100 Subject: brcmfmac: pass bus to the __brcmf_err() in pcie.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables dev_err() usage (instead of pr_err()) in the __brcmf_err(). It makes error messages more meaningful and is important for debugging errors/bugs on systems with multiple brcmfmac supported devices. All bus files should follow & get updated similarly (soon). Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/debug.h | 2 + .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 59 +++++++++++++--------- 2 files changed, 38 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h index b499f90d94f6..c1f260718c8e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h @@ -52,6 +52,7 @@ void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...); /* Macro for error messages. When debugging / tracing the driver all error * messages are important to us. */ +#ifndef brcmf_err #define brcmf_err(fmt, ...) \ do { \ if (IS_ENABLED(CONFIG_BRCMDBG) || \ @@ -59,6 +60,7 @@ void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...); net_ratelimit()) \ __brcmf_err(NULL, __func__, fmt, ##__VA_ARGS__);\ } while (0) +#endif #if defined(DEBUG) || defined(CONFIG_BRCM_TRACING) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 0f69b3fa296e..257f919c52cc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -30,6 +30,15 @@ #include #include +/* Custom brcmf_err() that takes bus arg and passes it further */ +#define brcmf_err(bus, fmt, ...) \ + do { \ + if (IS_ENABLED(CONFIG_BRCMDBG) || \ + IS_ENABLED(CONFIG_BRCM_TRACING) || \ + net_ratelimit()) \ + __brcmf_err(bus, __func__, fmt, ##__VA_ARGS__); \ + } while (0) + #include "debug.h" #include "bus.h" #include "commonring.h" @@ -531,6 +540,7 @@ static void brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid) { const struct pci_dev *pdev = devinfo->pdev; + struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev); struct brcmf_core *core; u32 bar0_win; @@ -548,7 +558,7 @@ brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid) } } } else { - brcmf_err("Unsupported core selected %x\n", coreid); + brcmf_err(bus, "Unsupported core selected %x\n", coreid); } } @@ -848,9 +858,8 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg) static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo) { - struct pci_dev *pdev; - - pdev = devinfo->pdev; + struct pci_dev *pdev = devinfo->pdev; + struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev); brcmf_pcie_intr_disable(devinfo); @@ -861,7 +870,7 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo) brcmf_pcie_isr_thread, IRQF_SHARED, "brcmf_pcie_intr", devinfo)) { pci_disable_msi(pdev); - brcmf_err("Failed to request IRQ %d\n", pdev->irq); + brcmf_err(bus, "Failed to request IRQ %d\n", pdev->irq); return -EIO; } devinfo->irq_allocated = true; @@ -871,15 +880,14 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo) static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo) { - struct pci_dev *pdev; + struct pci_dev *pdev = devinfo->pdev; + struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev); u32 status; u32 count; if (!devinfo->irq_allocated) return; - pdev = devinfo->pdev; - brcmf_pcie_intr_disable(devinfo); free_irq(pdev->irq, devinfo); pci_disable_msi(pdev); @@ -891,7 +899,7 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo) count++; } if (devinfo->in_irq) - brcmf_err("Still in IRQ (processing) !!!\n"); + brcmf_err(bus, "Still in IRQ (processing) !!!\n"); status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status); @@ -1102,6 +1110,7 @@ static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo) static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) { + struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev); struct brcmf_pcie_ringbuf *ring; struct brcmf_pcie_ringbuf *rings; u32 d2h_w_idx_ptr; @@ -1254,7 +1263,7 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) return 0; fail: - brcmf_err("Allocating ring buffers failed\n"); + brcmf_err(bus, "Allocating ring buffers failed\n"); brcmf_pcie_release_ringbuffers(devinfo); return -ENOMEM; } @@ -1277,6 +1286,7 @@ brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo) static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo) { + struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev); u64 address; u32 addr; @@ -1316,7 +1326,7 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo) return 0; fail: - brcmf_err("Allocating scratch buffers failed\n"); + brcmf_err(bus, "Allocating scratch buffers failed\n"); brcmf_pcie_release_scratchbuffers(devinfo); return -ENOMEM; } @@ -1437,6 +1447,7 @@ static int brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo, u32 sharedram_addr) { + struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev); struct brcmf_pcie_shared_info *shared; u32 addr; @@ -1448,7 +1459,8 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo, brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version); if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) || (shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) { - brcmf_err("Unsupported PCIE version %d\n", shared->version); + brcmf_err(bus, "Unsupported PCIE version %d\n", + shared->version); return -EINVAL; } @@ -1490,6 +1502,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, const struct firmware *fw, void *nvram, u32 nvram_len) { + struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev); u32 sharedram_addr; u32 sharedram_addr_written; u32 loop_counter; @@ -1544,7 +1557,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, loop_counter--; } if (sharedram_addr == sharedram_addr_written) { - brcmf_err("FW failed to initialize\n"); + brcmf_err(bus, "FW failed to initialize\n"); return -ENODEV; } brcmf_dbg(PCIE, "Shared RAM addr: 0x%08x\n", sharedram_addr); @@ -1555,16 +1568,15 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo) { - struct pci_dev *pdev; + struct pci_dev *pdev = devinfo->pdev; + struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev); int err; phys_addr_t bar0_addr, bar1_addr; ulong bar1_size; - pdev = devinfo->pdev; - err = pci_enable_device(pdev); if (err) { - brcmf_err("pci_enable_device failed err=%d\n", err); + brcmf_err(bus, "pci_enable_device failed err=%d\n", err); return err; } @@ -1577,7 +1589,7 @@ static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo) /* read Bar-1 mapped memory range */ bar1_size = pci_resource_len(pdev, 2); if ((bar1_size == 0) || (bar1_addr == 0)) { - brcmf_err("BAR1 Not enabled, device size=%ld, addr=%#016llx\n", + brcmf_err(bus, "BAR1 Not enabled, device size=%ld, addr=%#016llx\n", bar1_size, (unsigned long long)bar1_addr); return -EINVAL; } @@ -1586,7 +1598,7 @@ static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo) devinfo->tcm = ioremap_nocache(bar1_addr, bar1_size); if (!devinfo->regs || !devinfo->tcm) { - brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs, + brcmf_err(bus, "ioremap() failed (%p,%p)\n", devinfo->regs, devinfo->tcm); return -EINVAL; } @@ -1873,7 +1885,7 @@ fail_bus: kfree(bus->msgbuf); kfree(bus); fail: - brcmf_err("failed %x:%x\n", pdev->vendor, pdev->device); + brcmf_err(NULL, "failed %x:%x\n", pdev->vendor, pdev->device); brcmf_pcie_release_resource(devinfo); if (devinfo->ci) brcmf_chip_detach(devinfo->ci); @@ -1947,7 +1959,7 @@ static int brcmf_pcie_pm_enter_D3(struct device *dev) wait_event_timeout(devinfo->mbdata_resp_wait, devinfo->mbdata_completed, BRCMF_PCIE_MBDATA_TIMEOUT); if (!devinfo->mbdata_completed) { - brcmf_err("Timeout on response for entering D3 substate\n"); + brcmf_err(bus, "Timeout on response for entering D3 substate\n"); brcmf_bus_change_state(bus, BRCMF_BUS_UP); return -EIO; } @@ -1993,7 +2005,7 @@ cleanup: err = brcmf_pcie_probe(pdev, NULL); if (err) - brcmf_err("probe after resume failed, err=%d\n", err); + brcmf_err(bus, "probe after resume failed, err=%d\n", err); return err; } @@ -2064,7 +2076,8 @@ void brcmf_pcie_register(void) brcmf_dbg(PCIE, "Enter\n"); err = pci_register_driver(&brcmf_pciedrvr); if (err) - brcmf_err("PCIE driver registration failed, err=%d\n", err); + brcmf_err(NULL, "PCIE driver registration failed, err=%d\n", + err); } -- cgit v1.2.3 From 3ef005b82e2ad68107fc5814eaa743d171a6c362 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 16 Jan 2019 07:28:54 +0100 Subject: brcmfmac: add bphy_err() and use it in the cfg80211.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new macro uses wiphy_err() which: 1) Should be the best choice with wiphy already created 2) Uses dev_err() which allows identifying error-affected device Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 497 +++++++++++---------- .../wireless/broadcom/brcm80211/brcmfmac/debug.h | 9 + 2 files changed, 282 insertions(+), 224 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 35301237d435..b5e291ed9496 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -457,6 +457,7 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key, static int send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key) { + struct wiphy *wiphy = ifp->drvr->wiphy; int err; struct brcmf_wsec_key_le key_le; @@ -468,7 +469,7 @@ send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key) sizeof(key_le)); if (err) - brcmf_err("wsec_key error (%d)\n", err); + bphy_err(wiphy, "wsec_key error (%d)\n", err); return err; } @@ -508,6 +509,7 @@ static int brcmf_get_first_free_bsscfgidx(struct brcmf_pub *drvr) static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp) { + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_mbss_ssid_le mbss_ssid_le; int bsscfgidx; int err; @@ -524,7 +526,7 @@ static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp) err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le, sizeof(mbss_ssid_le)); if (err < 0) - brcmf_err("setting ssid failed %d\n", err); + bphy_err(wiphy, "setting ssid failed %d\n", err); return err; } @@ -567,7 +569,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, BRCMF_VIF_EVENT_TIMEOUT); brcmf_cfg80211_arm_vif_event(cfg, NULL); if (!err) { - brcmf_err("timeout occurred\n"); + bphy_err(wiphy, "timeout occurred\n"); err = -EIO; goto fail; } @@ -575,7 +577,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, /* interface created in firmware */ ifp = vif->ifp; if (!ifp) { - brcmf_err("no if pointer provided\n"); + bphy_err(wiphy, "no if pointer provided\n"); err = -ENOENT; goto fail; } @@ -583,7 +585,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1); err = brcmf_net_attach(ifp, true); if (err) { - brcmf_err("Registering netdevice failed\n"); + bphy_err(wiphy, "Registering netdevice failed\n"); free_netdev(ifp->ndev); goto fail; } @@ -620,7 +622,7 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); if (err) { - brcmf_err("iface validation failed: err=%d\n", err); + bphy_err(wiphy, "iface validation failed: err=%d\n", err); return ERR_PTR(err); } switch (type) { @@ -645,8 +647,8 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, } if (IS_ERR(wdev)) - brcmf_err("add iface %s type %d failed: err=%d\n", - name, type, (int)PTR_ERR(wdev)); + bphy_err(wiphy, "add iface %s type %d failed: err=%d\n", name, + type, (int)PTR_ERR(wdev)); else brcmf_cfg80211_update_proto_addr_mode(wdev); @@ -661,12 +663,13 @@ static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc) void brcmf_set_mpc(struct brcmf_if *ifp, int mpc) { + struct wiphy *wiphy = ifp->drvr->wiphy; s32 err = 0; if (check_vif_up(ifp->vif)) { err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc); if (err) { - brcmf_err("fail to set mpc\n"); + bphy_err(wiphy, "fail to set mpc\n"); return; } brcmf_dbg(INFO, "MPC : %d\n", mpc); @@ -677,6 +680,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, bool aborted, bool fw_abort) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_scan_params_le params_le; struct cfg80211_scan_request *scan_request; u64 reqid; @@ -711,7 +715,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, ¶ms_le, sizeof(params_le)); if (err) - brcmf_err("Scan abort failed\n"); + bphy_err(wiphy, "Scan abort failed\n"); } brcmf_scan_config_mpc(ifp, 1); @@ -763,7 +767,7 @@ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy, err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0); if (err) { - brcmf_err("interface_remove failed %d\n", err); + bphy_err(wiphy, "interface_remove failed %d\n", err); goto err_unarm; } @@ -771,7 +775,7 @@ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy, ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL, BRCMF_VIF_EVENT_TIMEOUT); if (!ret) { - brcmf_err("timeout occurred\n"); + bphy_err(wiphy, "timeout occurred\n"); err = -EIO; goto err_unarm; } @@ -873,14 +877,14 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, } err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type); if (err) { - brcmf_err("iface validation failed: err=%d\n", err); + bphy_err(wiphy, "iface validation failed: err=%d\n", err); return err; } switch (type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_WDS: - brcmf_err("type (%d) : currently we do not support this type\n", - type); + bphy_err(wiphy, "type (%d) : currently we do not support this type\n", + type); return -EOPNOTSUPP; case NL80211_IFTYPE_ADHOC: infra = 0; @@ -908,7 +912,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, } else { err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra); if (err) { - brcmf_err("WLC_SET_INFRA error (%d)\n", err); + bphy_err(wiphy, "WLC_SET_INFRA error (%d)\n", err); err = -EAGAIN; goto done; } @@ -999,6 +1003,7 @@ static s32 brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, struct cfg80211_scan_request *request) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + offsetof(struct brcmf_escan_params_le, params_le); struct brcmf_escan_params_le *params; @@ -1030,7 +1035,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, if (err == -EBUSY) brcmf_dbg(INFO, "system busy : escan canceled\n"); else - brcmf_err("error (%d)\n", err); + bphy_err(wiphy, "error (%d)\n", err); } kfree(params); @@ -1076,21 +1081,22 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) return -EIO; if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { - brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); + bphy_err(wiphy, "Scanning already: status (%lu)\n", + cfg->scan_status); return -EAGAIN; } if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) { - brcmf_err("Scanning being aborted: status (%lu)\n", - cfg->scan_status); + bphy_err(wiphy, "Scanning being aborted: status (%lu)\n", + cfg->scan_status); return -EAGAIN; } if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { - brcmf_err("Scanning suppressed: status (%lu)\n", - cfg->scan_status); + bphy_err(wiphy, "Scanning suppressed: status (%lu)\n", + cfg->scan_status); return -EAGAIN; } if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) { - brcmf_err("Connecting: status (%lu)\n", vif->sme_state); + bphy_err(wiphy, "Connecting: status (%lu)\n", vif->sme_state); return -EAGAIN; } @@ -1124,7 +1130,7 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) return 0; scan_out: - brcmf_err("scan error (%d)\n", err); + bphy_err(wiphy, "scan error (%d)\n", err); clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); cfg->scan_request = NULL; return err; @@ -1132,36 +1138,41 @@ scan_out: static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) { + struct brcmf_if *ifp = netdev_priv(ndev); + struct wiphy *wiphy = ifp->drvr->wiphy; s32 err = 0; - err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh", - rts_threshold); + err = brcmf_fil_iovar_int_set(ifp, "rtsthresh", rts_threshold); if (err) - brcmf_err("Error (%d)\n", err); + bphy_err(wiphy, "Error (%d)\n", err); return err; } static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold) { + struct brcmf_if *ifp = netdev_priv(ndev); + struct wiphy *wiphy = ifp->drvr->wiphy; s32 err = 0; - err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh", + err = brcmf_fil_iovar_int_set(ifp, "fragthresh", frag_threshold); if (err) - brcmf_err("Error (%d)\n", err); + bphy_err(wiphy, "Error (%d)\n", err); return err; } static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) { + struct brcmf_if *ifp = netdev_priv(ndev); + struct wiphy *wiphy = ifp->drvr->wiphy; s32 err = 0; u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL); - err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry); + err = brcmf_fil_cmd_int_set(ifp, cmd, retry); if (err) { - brcmf_err("cmd (%d) , error (%d)\n", cmd, err); + bphy_err(wiphy, "cmd (%d) , error (%d)\n", cmd, err); return err; } return err; @@ -1237,6 +1248,7 @@ static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e) static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len) { + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_wsec_pmk_le pmk; int i, err; @@ -1250,8 +1262,8 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len) err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK, &pmk, sizeof(pmk)); if (err < 0) - brcmf_err("failed to change PSK in firmware (len=%u)\n", - pmk_len); + bphy_err(wiphy, "failed to change PSK in firmware (len=%u)\n", + pmk_len); return err; } @@ -1259,6 +1271,7 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len) static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); + struct wiphy *wiphy = cfg_to_wiphy(cfg); s32 err = 0; brcmf_dbg(TRACE, "Enter\n"); @@ -1268,7 +1281,7 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) err = brcmf_fil_cmd_data_set(vif->ifp, BRCMF_C_DISASSOC, NULL, 0); if (err) { - brcmf_err("WLC_DISASSOC failed (%d)\n", err); + bphy_err(wiphy, "WLC_DISASSOC failed (%d)\n", err); } if ((vif->wdev.iftype == NL80211_IFTYPE_STATION) || (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) @@ -1356,7 +1369,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec); if (err) { - brcmf_err("wsec failed (%d)\n", err); + bphy_err(wiphy, "wsec failed (%d)\n", err); goto done; } @@ -1368,7 +1381,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd); if (err) { - brcmf_err("WLC_SET_BCNPRD failed (%d)\n", err); + bphy_err(wiphy, "WLC_SET_BCNPRD failed (%d)\n", err); goto done; } @@ -1413,7 +1426,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL, target_channel); if (err) { - brcmf_err("WLC_SET_CHANNEL failed (%d)\n", err); + bphy_err(wiphy, "WLC_SET_CHANNEL failed (%d)\n", err); goto done; } } else @@ -1425,7 +1438,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, join_params_size); if (err) { - brcmf_err("WLC_SET_SSID failed (%d)\n", err); + bphy_err(wiphy, "WLC_SET_SSID failed (%d)\n", err); goto done; } @@ -1461,6 +1474,8 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) static s32 brcmf_set_wpa_version(struct net_device *ndev, struct cfg80211_connect_params *sme) { + struct brcmf_if *ifp = netdev_priv(ndev); + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); struct brcmf_cfg80211_security *sec; s32 val = 0; @@ -1473,9 +1488,9 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, else val = WPA_AUTH_DISABLED; brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val); - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val); + err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val); if (err) { - brcmf_err("set wpa_auth failed (%d)\n", err); + bphy_err(wiphy, "set wpa_auth failed (%d)\n", err); return err; } sec = &profile->sec; @@ -1486,6 +1501,8 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, static s32 brcmf_set_auth_type(struct net_device *ndev, struct cfg80211_connect_params *sme) { + struct brcmf_if *ifp = netdev_priv(ndev); + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); struct brcmf_cfg80211_security *sec; s32 val = 0; @@ -1506,9 +1523,9 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, break; } - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val); + err = brcmf_fil_bsscfg_int_set(ifp, "auth", val); if (err) { - brcmf_err("set auth failed (%d)\n", err); + bphy_err(wiphy, "set auth failed (%d)\n", err); return err; } sec = &profile->sec; @@ -1520,6 +1537,8 @@ static s32 brcmf_set_wsec_mode(struct net_device *ndev, struct cfg80211_connect_params *sme) { + struct brcmf_if *ifp = netdev_priv(ndev); + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); struct brcmf_cfg80211_security *sec; s32 pval = 0; @@ -1543,8 +1562,8 @@ brcmf_set_wsec_mode(struct net_device *ndev, pval = AES_ENABLED; break; default: - brcmf_err("invalid cipher pairwise (%d)\n", - sme->crypto.ciphers_pairwise[0]); + bphy_err(wiphy, "invalid cipher pairwise (%d)\n", + sme->crypto.ciphers_pairwise[0]); return -EINVAL; } } @@ -1564,8 +1583,8 @@ brcmf_set_wsec_mode(struct net_device *ndev, gval = AES_ENABLED; break; default: - brcmf_err("invalid cipher group (%d)\n", - sme->crypto.cipher_group); + bphy_err(wiphy, "invalid cipher group (%d)\n", + sme->crypto.cipher_group); return -EINVAL; } } @@ -1578,9 +1597,9 @@ brcmf_set_wsec_mode(struct net_device *ndev, pval = AES_ENABLED; wsec = pval | gval; - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", wsec); + err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); if (err) { - brcmf_err("error (%d)\n", err); + bphy_err(wiphy, "error (%d)\n", err); return err; } @@ -1595,6 +1614,7 @@ static s32 brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_if *ifp = netdev_priv(ndev); + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; s32 val; s32 err; @@ -1613,7 +1633,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "wpa_auth", &val); if (err) { - brcmf_err("could not get wpa_auth (%d)\n", err); + bphy_err(wiphy, "could not get wpa_auth (%d)\n", err); return err; } if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { @@ -1627,8 +1647,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA_AUTH_PSK; break; default: - brcmf_err("invalid cipher group (%d)\n", - sme->crypto.cipher_group); + bphy_err(wiphy, "invalid cipher group (%d)\n", + sme->crypto.cipher_group); return -EINVAL; } } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { @@ -1658,8 +1678,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA2_AUTH_PSK | WPA2_AUTH_FT; break; default: - brcmf_err("invalid cipher group (%d)\n", - sme->crypto.cipher_group); + bphy_err(wiphy, "invalid cipher group (%d)\n", + sme->crypto.cipher_group); return -EINVAL; } } @@ -1705,7 +1725,7 @@ skip_mfp_config: brcmf_dbg(CONN, "setting wpa_auth to %d\n", val); err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val); if (err) { - brcmf_err("could not set wpa_auth (%d)\n", err); + bphy_err(wiphy, "could not set wpa_auth (%d)\n", err); return err; } @@ -1716,6 +1736,8 @@ static s32 brcmf_set_sharedkey(struct net_device *ndev, struct cfg80211_connect_params *sme) { + struct brcmf_if *ifp = netdev_priv(ndev); + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); struct brcmf_cfg80211_security *sec; struct brcmf_wsec_key key; @@ -1742,7 +1764,7 @@ brcmf_set_sharedkey(struct net_device *ndev, key.len = (u32) sme->key_len; key.index = (u32) sme->key_idx; if (key.len > sizeof(key.data)) { - brcmf_err("Too long key length (%u)\n", key.len); + bphy_err(wiphy, "Too long key length (%u)\n", key.len); return -EINVAL; } memcpy(key.data, sme->key, key.len); @@ -1755,24 +1777,24 @@ brcmf_set_sharedkey(struct net_device *ndev, key.algo = CRYPTO_ALGO_WEP128; break; default: - brcmf_err("Invalid algorithm (%d)\n", - sme->crypto.ciphers_pairwise[0]); + bphy_err(wiphy, "Invalid algorithm (%d)\n", + sme->crypto.ciphers_pairwise[0]); return -EINVAL; } /* Set the new key/index */ brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n", key.len, key.index, key.algo); brcmf_dbg(CONN, "key \"%s\"\n", key.data); - err = send_key_to_dongle(netdev_priv(ndev), &key); + err = send_key_to_dongle(ifp, &key); if (err) return err; if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { brcmf_dbg(CONN, "set auth_type to shared key\n"); val = WL_AUTH_SHARED_KEY; /* shared key */ - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val); + err = brcmf_fil_bsscfg_int_set(ifp, "auth", val); if (err) - brcmf_err("set auth failed (%d)\n", err); + bphy_err(wiphy, "set auth failed (%d)\n", err); } return err; } @@ -1792,6 +1814,7 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, static void brcmf_set_join_pref(struct brcmf_if *ifp, struct cfg80211_bss_selection *bss_select) { + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_join_pref_params join_pref_params[2]; enum nl80211_band band; int err, i = 0; @@ -1830,7 +1853,7 @@ static void brcmf_set_join_pref(struct brcmf_if *ifp, err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, sizeof(join_pref_params)); if (err) - brcmf_err("Set join_pref error (%d)\n", err); + bphy_err(wiphy, "Set join_pref error (%d)\n", err); } static s32 @@ -1857,7 +1880,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, return -EIO; if (!sme->ssid) { - brcmf_err("Invalid ssid\n"); + bphy_err(wiphy, "Invalid ssid\n"); return -EOPNOTSUPP; } @@ -1886,7 +1909,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); if (err) - brcmf_err("Set Assoc REQ IE Failed\n"); + bphy_err(wiphy, "Set Assoc REQ IE Failed\n"); else brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n"); @@ -1907,32 +1930,32 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_set_wpa_version(ndev, sme); if (err) { - brcmf_err("wl_set_wpa_version failed (%d)\n", err); + bphy_err(wiphy, "wl_set_wpa_version failed (%d)\n", err); goto done; } sme->auth_type = brcmf_war_auth_type(ifp, sme->auth_type); err = brcmf_set_auth_type(ndev, sme); if (err) { - brcmf_err("wl_set_auth_type failed (%d)\n", err); + bphy_err(wiphy, "wl_set_auth_type failed (%d)\n", err); goto done; } err = brcmf_set_wsec_mode(ndev, sme); if (err) { - brcmf_err("wl_set_set_cipher failed (%d)\n", err); + bphy_err(wiphy, "wl_set_set_cipher failed (%d)\n", err); goto done; } err = brcmf_set_key_mgmt(ndev, sme); if (err) { - brcmf_err("wl_set_key_mgmt failed (%d)\n", err); + bphy_err(wiphy, "wl_set_key_mgmt failed (%d)\n", err); goto done; } err = brcmf_set_sharedkey(ndev, sme); if (err) { - brcmf_err("brcmf_set_sharedkey failed (%d)\n", err); + bphy_err(wiphy, "brcmf_set_sharedkey failed (%d)\n", err); goto done; } @@ -1949,7 +1972,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, /* enable firmware supplicant for this interface */ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); if (err < 0) { - brcmf_err("failed to enable fw supplicant\n"); + bphy_err(wiphy, "failed to enable fw supplicant\n"); goto done; } } @@ -2044,7 +2067,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, join_params_size); if (err) - brcmf_err("BRCMF_C_SET_SSID failed (%d)\n", err); + bphy_err(wiphy, "BRCMF_C_SET_SSID failed (%d)\n", err); done: if (err) @@ -2075,7 +2098,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC, &scbval, sizeof(scbval)); if (err) - brcmf_err("error (%d)\n", err); + bphy_err(wiphy, "error (%d)\n", err); brcmf_dbg(TRACE, "Exit\n"); return err; @@ -2102,7 +2125,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, case NL80211_TX_POWER_LIMITED: case NL80211_TX_POWER_FIXED: if (mbm < 0) { - brcmf_err("TX_POWER_FIXED - dbm is negative\n"); + bphy_err(wiphy, "TX_POWER_FIXED - dbm is negative\n"); err = -EINVAL; goto done; } @@ -2112,7 +2135,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, qdbm |= WL_TXPWR_OVERRIDE; break; default: - brcmf_err("Unsupported type %d\n", type); + bphy_err(wiphy, "Unsupported type %d\n", type); err = -EINVAL; goto done; } @@ -2120,11 +2143,11 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, disable = WL_RADIO_SW_DISABLE << 16; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable); if (err) - brcmf_err("WLC_SET_RADIO error (%d)\n", err); + bphy_err(wiphy, "WLC_SET_RADIO error (%d)\n", err); err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm); if (err) - brcmf_err("qtxpower error (%d)\n", err); + bphy_err(wiphy, "qtxpower error (%d)\n", err); done: brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE); @@ -2145,7 +2168,7 @@ brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm); if (err) { - brcmf_err("error (%d)\n", err); + bphy_err(wiphy, "error (%d)\n", err); goto done; } *dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4; @@ -2171,7 +2194,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); if (err) { - brcmf_err("WLC_GET_WSEC error (%d)\n", err); + bphy_err(wiphy, "WLC_GET_WSEC error (%d)\n", err); goto done; } @@ -2181,7 +2204,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_KEY_PRIMARY, index); if (err) - brcmf_err("error (%d)\n", err); + bphy_err(wiphy, "error (%d)\n", err); } done: brcmf_dbg(TRACE, "Exit\n"); @@ -2245,7 +2268,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) { /* we ignore this key index in this case */ - brcmf_err("invalid key index (%d)\n", key_idx); + bphy_err(wiphy, "invalid key index (%d)\n", key_idx); return -EINVAL; } @@ -2254,7 +2277,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, mac_addr); if (params->key_len > sizeof(key->data)) { - brcmf_err("Too long key length (%u)\n", params->key_len); + bphy_err(wiphy, "Too long key length (%u)\n", params->key_len); return -EINVAL; } @@ -2308,7 +2331,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n"); break; default: - brcmf_err("Invalid cipher (0x%x)\n", params->cipher); + bphy_err(wiphy, "Invalid cipher (0x%x)\n", params->cipher); err = -EINVAL; goto done; } @@ -2319,13 +2342,13 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); if (err) { - brcmf_err("get wsec error (%d)\n", err); + bphy_err(wiphy, "get wsec error (%d)\n", err); goto done; } wsec |= val; err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); if (err) { - brcmf_err("set wsec error (%d)\n", err); + bphy_err(wiphy, "set wsec error (%d)\n", err); goto done; } @@ -2356,7 +2379,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); if (err) { - brcmf_err("WLC_GET_WSEC error (%d)\n", err); + bphy_err(wiphy, "WLC_GET_WSEC error (%d)\n", err); /* Ignore this error, may happen during DISASSOC */ err = -EAGAIN; goto done; @@ -2377,7 +2400,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n"); } else { - brcmf_err("Invalid algo (0x%x)\n", wsec); + bphy_err(wiphy, "Invalid algo (0x%x)\n", wsec); err = -EINVAL; goto done; } @@ -2407,6 +2430,7 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, static void brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp) { + struct wiphy *wiphy = ifp->drvr->wiphy; s32 err; u8 key_idx; struct brcmf_wsec_key *key; @@ -2423,18 +2447,18 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp) err = send_key_to_dongle(ifp, key); if (err) { - brcmf_err("Setting WEP key failed (%d)\n", err); + bphy_err(wiphy, "Setting WEP key failed (%d)\n", err); return; } err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); if (err) { - brcmf_err("get wsec error (%d)\n", err); + bphy_err(wiphy, "get wsec error (%d)\n", err); return; } wsec |= WEP_ENABLED; err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); if (err) - brcmf_err("set wsec error (%d)\n", err); + bphy_err(wiphy, "set wsec error (%d)\n", err); } static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si) @@ -2460,6 +2484,7 @@ static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si) static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) { + struct wiphy *wiphy = ifp->drvr->wiphy; struct { __le32 len; struct brcmf_bss_info_le bss_le; @@ -2475,7 +2500,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); if (err) { - brcmf_err("Failed to get bss info (%d)\n", err); + bphy_err(wiphy, "Failed to get bss info (%d)\n", err); goto out_kfree; } si->filled |= BIT_ULL(NL80211_STA_INFO_BSS_PARAM); @@ -2497,6 +2522,7 @@ static s32 brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, struct station_info *sinfo) { + struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_scb_val_le scbval; struct brcmf_pktcnt_le pktcnt; s32 err; @@ -2506,7 +2532,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, /* Get the current tx rate */ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); if (err < 0) { - brcmf_err("BRCMF_C_GET_RATE error (%d)\n", err); + bphy_err(wiphy, "BRCMF_C_GET_RATE error (%d)\n", err); return err; } sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); @@ -2516,7 +2542,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, &scbval, sizeof(scbval)); if (err) { - brcmf_err("BRCMF_C_GET_RSSI error (%d)\n", err); + bphy_err(wiphy, "BRCMF_C_GET_RSSI error (%d)\n", err); return err; } rssi = le32_to_cpu(scbval.val); @@ -2526,7 +2552,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_GET_PKTCNTS, &pktcnt, sizeof(pktcnt)); if (err) { - brcmf_err("BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err); + bphy_err(wiphy, "BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err); return err; } sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS) | @@ -2574,7 +2600,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, &sta_info_le, sizeof(sta_info_le)); if (err < 0) { - brcmf_err("GET STA INFO failed, %d\n", err); + bphy_err(wiphy, "GET STA INFO failed, %d\n", err); goto done; } } @@ -2643,7 +2669,8 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, &scb_val, sizeof(scb_val)); if (err) { - brcmf_err("Could not get rssi (%d)\n", err); + bphy_err(wiphy, "Could not get rssi (%d)\n", + err); goto done; } else { rssi = le32_to_cpu(scb_val.val); @@ -2674,8 +2701,8 @@ brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev, &cfg->assoclist, sizeof(cfg->assoclist)); if (err) { - brcmf_err("BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n", - err); + bphy_err(wiphy, "BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n", + err); cfg->assoclist.count = 0; return -EOPNOTSUPP; } @@ -2723,9 +2750,9 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm); if (err) { if (err == -ENODEV) - brcmf_err("net_device is not ready yet\n"); + bphy_err(wiphy, "net_device is not ready yet\n"); else - brcmf_err("error (%d)\n", err); + bphy_err(wiphy, "error (%d)\n", err); } done: brcmf_dbg(TRACE, "Exit\n"); @@ -2748,7 +2775,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, struct cfg80211_inform_bss bss_data = {}; if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) { - brcmf_err("Bss info is larger than buffer. Discarding\n"); + bphy_err(wiphy, "Bss info is larger than buffer. Discarding\n"); return 0; } @@ -2807,6 +2834,7 @@ next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss) static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_scan_results *bss_list; struct brcmf_bss_info_le *bi = NULL; /* must be initialized */ s32 err = 0; @@ -2815,8 +2843,8 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg) bss_list = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; if (bss_list->count != 0 && bss_list->version != BRCMF_BSS_INFO_VERSION) { - brcmf_err("Version %d != WL_BSS_INFO_VERSION\n", - bss_list->version); + bphy_err(wiphy, "Version %d != WL_BSS_INFO_VERSION\n", + bss_list->version); return -EOPNOTSUPP; } brcmf_dbg(SCAN, "scanned AP count (%d)\n", bss_list->count); @@ -2860,7 +2888,7 @@ static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); if (err) { - brcmf_err("WLC_GET_BSS_INFO failed: %d\n", err); + bphy_err(wiphy, "WLC_GET_BSS_INFO failed: %d\n", err); goto CleanUp; } @@ -2914,6 +2942,7 @@ CleanUp: static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_bss_info_le *bi; const struct brcmf_tlv *tim; u16 beacon_interval; @@ -2930,7 +2959,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX); if (err) { - brcmf_err("Could not get bss info %d\n", err); + bphy_err(wiphy, "Could not get bss info %d\n", err); goto update_bss_info_out; } @@ -2955,7 +2984,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, u32 var; err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var); if (err) { - brcmf_err("wl dtim_assoc failed (%d)\n", err); + bphy_err(wiphy, "wl dtim_assoc failed (%d)\n", err); goto update_bss_info_out; } dtim_period = (u8)var; @@ -2993,9 +3022,10 @@ static void brcmf_escan_timeout(struct timer_list *t) { struct brcmf_cfg80211_info *cfg = from_timer(cfg, t, escan_timeout); + struct wiphy *wiphy = cfg_to_wiphy(cfg); if (cfg->int_escan_map || cfg->scan_request) { - brcmf_err("timer expired\n"); + bphy_err(wiphy, "timer expired\n"); schedule_work(&cfg->escan_timeout_work); } } @@ -3044,6 +3074,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, const struct brcmf_event_msg *e, void *data) { struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + struct wiphy *wiphy = cfg_to_wiphy(cfg); s32 status; struct brcmf_escan_result_le *escan_result_le; u32 escan_buflen; @@ -3060,32 +3091,33 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, goto exit; if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { - brcmf_err("scan not ready, bsscfgidx=%d\n", ifp->bsscfgidx); + bphy_err(wiphy, "scan not ready, bsscfgidx=%d\n", + ifp->bsscfgidx); return -EPERM; } if (status == BRCMF_E_STATUS_PARTIAL) { brcmf_dbg(SCAN, "ESCAN Partial result\n"); if (e->datalen < sizeof(*escan_result_le)) { - brcmf_err("invalid event data length\n"); + bphy_err(wiphy, "invalid event data length\n"); goto exit; } escan_result_le = (struct brcmf_escan_result_le *) data; if (!escan_result_le) { - brcmf_err("Invalid escan result (NULL pointer)\n"); + bphy_err(wiphy, "Invalid escan result (NULL pointer)\n"); goto exit; } escan_buflen = le32_to_cpu(escan_result_le->buflen); if (escan_buflen > BRCMF_ESCAN_BUF_SIZE || escan_buflen > e->datalen || escan_buflen < sizeof(*escan_result_le)) { - brcmf_err("Invalid escan buffer length: %d\n", - escan_buflen); + bphy_err(wiphy, "Invalid escan buffer length: %d\n", + escan_buflen); goto exit; } if (le16_to_cpu(escan_result_le->bss_count) != 1) { - brcmf_err("Invalid bss_count %d: ignoring\n", - escan_result_le->bss_count); + bphy_err(wiphy, "Invalid bss_count %d: ignoring\n", + escan_result_le->bss_count); goto exit; } bss_info_le = &escan_result_le->bss_info_le; @@ -3100,8 +3132,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, bi_length = le32_to_cpu(bss_info_le->length); if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) { - brcmf_err("Ignoring invalid bss_info length: %d\n", - bi_length); + bphy_err(wiphy, "Ignoring invalid bss_info length: %d\n", + bi_length); goto exit; } @@ -3109,7 +3141,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, BIT(NL80211_IFTYPE_ADHOC))) { if (le16_to_cpu(bss_info_le->capability) & WLAN_CAPABILITY_IBSS) { - brcmf_err("Ignoring IBSS result\n"); + bphy_err(wiphy, "Ignoring IBSS result\n"); goto exit; } } @@ -3117,7 +3149,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, list = (struct brcmf_scan_results *) cfg->escan_info.escan_buf; if (bi_length > BRCMF_ESCAN_BUF_SIZE - list->buflen) { - brcmf_err("Buffer is too small: ignoring\n"); + bphy_err(wiphy, "Buffer is too small: ignoring\n"); goto exit; } @@ -3309,14 +3341,14 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE); brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count); if (!result_count) { - brcmf_err("FALSE PNO Event. (pfn_count == 0)\n"); + bphy_err(wiphy, "FALSE PNO Event. (pfn_count == 0)\n"); goto out_err; } netinfo_start = brcmf_get_netinfo_array(pfn_result); datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result); if (datalen < result_count * sizeof(*netinfo)) { - brcmf_err("insufficient event data\n"); + bphy_err(wiphy, "insufficient event data\n"); goto out_err; } @@ -3370,8 +3402,8 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, req->n_match_sets, req->n_ssids); if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { - brcmf_err("Scanning suppressed: status=%lu\n", - cfg->scan_status); + bphy_err(wiphy, "Scanning suppressed: status=%lu\n", + cfg->scan_status); return -EAGAIN; } @@ -3450,6 +3482,7 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, void *data) { struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_pno_scanresults_le *pfn_result; struct brcmf_pno_net_info_le *netinfo; @@ -3468,8 +3501,8 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, } if (le32_to_cpu(pfn_result->count) < 1) { - brcmf_err("Invalid result count, expected 1 (%d)\n", - le32_to_cpu(pfn_result->count)); + bphy_err(wiphy, "Invalid result count, expected 1 (%d)\n", + le32_to_cpu(pfn_result->count)); return -EINVAL; } @@ -3506,7 +3539,7 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp) err = brcmf_fil_iovar_data_get(ifp, "wowl_wakeind", &wake_ind_le, sizeof(wake_ind_le)); if (err) { - brcmf_err("Get wowl_wakeind failed, err = %d\n", err); + bphy_err(wiphy, "Get wowl_wakeind failed, err = %d\n", err); return; } @@ -3547,7 +3580,7 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp) cfg->wowl.nd_data_completed, BRCMF_ND_INFO_TIMEOUT); if (!timeout) - brcmf_err("No result for wowl net detect\n"); + bphy_err(wiphy, "No result for wowl net detect\n"); else wakeup_data.net_detect = cfg->wowl.nd_info; } @@ -3755,7 +3788,7 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, cfg->pmk_list.npmk = cpu_to_le32(npmk); } } else { - brcmf_err("Too many PMKSA entries cached %d\n", npmk); + bphy_err(wiphy, "Too many PMKSA entries cached %d\n", npmk); return -EINVAL; } @@ -3801,7 +3834,7 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, memset(&pmk[i], 0, sizeof(*pmk)); cfg->pmk_list.npmk = cpu_to_le32(npmk - 1); } else { - brcmf_err("Cache entry not found\n"); + bphy_err(wiphy, "Cache entry not found\n"); return -EINVAL; } @@ -3833,19 +3866,20 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) { + struct wiphy *wiphy = ifp->drvr->wiphy; s32 err; s32 wpa_val; /* set auth */ err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0); if (err < 0) { - brcmf_err("auth error %d\n", err); + bphy_err(wiphy, "auth error %d\n", err); return err; } /* set wsec */ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0); if (err < 0) { - brcmf_err("wsec error %d\n", err); + bphy_err(wiphy, "wsec error %d\n", err); return err; } /* set upper-layer auth */ @@ -3855,7 +3889,7 @@ static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) wpa_val = WPA_AUTH_DISABLED; err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_val); if (err < 0) { - brcmf_err("wpa_auth error %d\n", err); + bphy_err(wiphy, "wpa_auth error %d\n", err); return err; } @@ -3875,6 +3909,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, const struct brcmf_vs_tlv *wpa_ie, bool is_rsn_ie) { + struct wiphy *wiphy = ifp->drvr->wiphy; u32 auth = 0; /* d11 open authentication */ u16 count; s32 err = 0; @@ -3905,13 +3940,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, /* check for multicast cipher suite */ if (offset + WPA_IE_MIN_OUI_LEN > len) { err = -EINVAL; - brcmf_err("no multicast cipher suite\n"); + bphy_err(wiphy, "no multicast cipher suite\n"); goto exit; } if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { err = -EINVAL; - brcmf_err("ivalid OUI\n"); + bphy_err(wiphy, "ivalid OUI\n"); goto exit; } offset += TLV_OUI_LEN; @@ -3933,7 +3968,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, break; default: err = -EINVAL; - brcmf_err("Invalid multi cast cipher info\n"); + bphy_err(wiphy, "Invalid multi cast cipher info\n"); goto exit; } @@ -3944,13 +3979,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, /* Check for unicast suite(s) */ if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) { err = -EINVAL; - brcmf_err("no unicast cipher suite\n"); + bphy_err(wiphy, "no unicast cipher suite\n"); goto exit; } for (i = 0; i < count; i++) { if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { err = -EINVAL; - brcmf_err("ivalid OUI\n"); + bphy_err(wiphy, "ivalid OUI\n"); goto exit; } offset += TLV_OUI_LEN; @@ -3968,7 +4003,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, pval |= AES_ENABLED; break; default: - brcmf_err("Invalid unicast security info\n"); + bphy_err(wiphy, "Invalid unicast security info\n"); } offset++; } @@ -3978,13 +4013,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, /* Check for auth key management suite(s) */ if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) { err = -EINVAL; - brcmf_err("no auth key mgmt suite\n"); + bphy_err(wiphy, "no auth key mgmt suite\n"); goto exit; } for (i = 0; i < count; i++) { if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { err = -EINVAL; - brcmf_err("ivalid OUI\n"); + bphy_err(wiphy, "ivalid OUI\n"); goto exit; } offset += TLV_OUI_LEN; @@ -4012,7 +4047,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, wpa_auth |= WPA2_AUTH_1X_SHA256; break; default: - brcmf_err("Invalid key mgmt info\n"); + bphy_err(wiphy, "Invalid key mgmt info\n"); } offset++; } @@ -4054,7 +4089,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable", wme_bss_disable); if (err < 0) { - brcmf_err("wme_bss_disable error %d\n", err); + bphy_err(wiphy, "wme_bss_disable error %d\n", err); goto exit; } @@ -4068,7 +4103,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, &data[offset], WPA_IE_MIN_OUI_LEN); if (err < 0) { - brcmf_err("bip error %d\n", err); + bphy_err(wiphy, "bip error %d\n", err); goto exit; } } @@ -4079,13 +4114,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, /* set auth */ err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth); if (err < 0) { - brcmf_err("auth error %d\n", err); + bphy_err(wiphy, "auth error %d\n", err); goto exit; } /* set wsec */ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); if (err < 0) { - brcmf_err("wsec error %d\n", err); + bphy_err(wiphy, "wsec error %d\n", err); goto exit; } /* Configure MFP, this needs to go after wsec otherwise the wsec command @@ -4094,14 +4129,14 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) { err = brcmf_fil_bsscfg_int_set(ifp, "mfp", mfp); if (err < 0) { - brcmf_err("mfp error %d\n", err); + bphy_err(wiphy, "mfp error %d\n", err); goto exit; } } /* set upper-layer auth */ err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth); if (err < 0) { - brcmf_err("wpa_auth error %d\n", err); + bphy_err(wiphy, "wpa_auth error %d\n", err); goto exit; } @@ -4188,6 +4223,7 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, const u8 *vndr_ie_buf, u32 vndr_ie_len) { struct brcmf_if *ifp; + struct wiphy *wiphy; struct vif_saved_ie *saved_ie; s32 err = 0; u8 *iovar_ie_buf; @@ -4208,6 +4244,7 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, if (!vif) return -ENODEV; ifp = vif->ifp; + wiphy = ifp->drvr->wiphy; saved_ie = &vif->saved_ie; brcmf_dbg(TRACE, "bsscfgidx %d, pktflag : 0x%02X\n", ifp->bsscfgidx, @@ -4239,13 +4276,13 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, break; default: err = -EPERM; - brcmf_err("not suitable type\n"); + bphy_err(wiphy, "not suitable type\n"); goto exit; } if (vndr_ie_len > mgmt_ie_buf_len) { err = -ENOMEM; - brcmf_err("extra IE size too big\n"); + bphy_err(wiphy, "extra IE size too big\n"); goto exit; } @@ -4306,8 +4343,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, /* verify remained buf size before copy data */ if (remained_buf_len < (vndrie_info->vndrie.len + VNDR_IE_VSIE_OFFSET)) { - brcmf_err("no space in mgmt_ie_buf: len left %d", - remained_buf_len); + bphy_err(wiphy, "no space in mgmt_ie_buf: len left %d", + remained_buf_len); break; } remained_buf_len -= (vndrie_info->ie_len + @@ -4338,7 +4375,7 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf, total_ie_buf_len); if (err) - brcmf_err("vndr ie set error : %d\n", err); + bphy_err(wiphy, "vndr ie set error : %d\n", err); } exit: @@ -4366,13 +4403,14 @@ static s32 brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif, struct cfg80211_beacon_data *beacon) { + struct wiphy *wiphy = vif->ifp->drvr->wiphy; s32 err; /* Set Beacon IEs to FW */ err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG, beacon->tail, beacon->tail_len); if (err) { - brcmf_err("Set Beacon IE Failed\n"); + bphy_err(wiphy, "Set Beacon IE Failed\n"); return err; } brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n"); @@ -4382,7 +4420,7 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif, beacon->proberesp_ies, beacon->proberesp_ies_len); if (err) - brcmf_err("Set Probe Resp IE Failed\n"); + bphy_err(wiphy, "Set Probe Resp IE Failed\n"); else brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n"); @@ -4491,7 +4529,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, is_11d); if (err < 0) { - brcmf_err("Regulatory Set Error, %d\n", err); + bphy_err(wiphy, "Regulatory Set Error, %d\n", + err); goto exit; } } @@ -4499,8 +4538,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, settings->beacon_interval); if (err < 0) { - brcmf_err("Beacon Interval Set Error, %d\n", - err); + bphy_err(wiphy, "Beacon Interval Set Error, %d\n", + err); goto exit; } } @@ -4508,7 +4547,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD, settings->dtim_period); if (err < 0) { - brcmf_err("DTIM Interval Set Error, %d\n", err); + bphy_err(wiphy, "DTIM Interval Set Error, %d\n", + err); goto exit; } } @@ -4518,7 +4558,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, !brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB))) { err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); if (err < 0) { - brcmf_err("BRCMF_C_DOWN error %d\n", err); + bphy_err(wiphy, "BRCMF_C_DOWN error %d\n", + err); goto exit; } brcmf_fil_iovar_int_set(ifp, "apsta", 0); @@ -4526,7 +4567,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1); if (err < 0) { - brcmf_err("SET INFRA error %d\n", err); + bphy_err(wiphy, "SET INFRA error %d\n", err); goto exit; } } else if (WARN_ON(supports_11d && (is_11d != ifp->vif->is_11d))) { @@ -4542,7 +4583,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1); if (err < 0) { - brcmf_err("setting AP mode failed %d\n", err); + bphy_err(wiphy, "setting AP mode failed %d\n", + err); goto exit; } if (!mbss) { @@ -4551,14 +4593,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, */ err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec); if (err < 0) { - brcmf_err("Set Channel failed: chspec=%d, %d\n", - chanspec, err); + bphy_err(wiphy, "Set Channel failed: chspec=%d, %d\n", + chanspec, err); goto exit; } } err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); if (err < 0) { - brcmf_err("BRCMF_C_UP error (%d)\n", err); + bphy_err(wiphy, "BRCMF_C_UP error (%d)\n", err); goto exit; } /* On DOWN the firmware removes the WEP keys, reconfigure @@ -4573,14 +4615,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, sizeof(join_params)); if (err < 0) { - brcmf_err("SET SSID error (%d)\n", err); + bphy_err(wiphy, "SET SSID error (%d)\n", err); goto exit; } if (settings->hidden_ssid) { err = brcmf_fil_iovar_int_set(ifp, "closednet", 1); if (err) { - brcmf_err("closednet error (%d)\n", err); + bphy_err(wiphy, "closednet error (%d)\n", err); goto exit; } } @@ -4589,14 +4631,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, } else if (dev_role == NL80211_IFTYPE_P2P_GO) { err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec); if (err < 0) { - brcmf_err("Set Channel failed: chspec=%d, %d\n", - chanspec, err); + bphy_err(wiphy, "Set Channel failed: chspec=%d, %d\n", + chanspec, err); goto exit; } err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le, sizeof(ssid_le)); if (err < 0) { - brcmf_err("setting ssid failed %d\n", err); + bphy_err(wiphy, "setting ssid failed %d\n", err); goto exit; } bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx); @@ -4604,7 +4646,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, sizeof(bss_enable)); if (err < 0) { - brcmf_err("bss_enable config failed %d\n", err); + bphy_err(wiphy, "bss_enable config failed %d\n", err); goto exit; } @@ -4652,13 +4694,13 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, sizeof(join_params)); if (err < 0) - brcmf_err("SET SSID error (%d)\n", err); + bphy_err(wiphy, "SET SSID error (%d)\n", err); err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); if (err < 0) - brcmf_err("BRCMF_C_DOWN error %d\n", err); + bphy_err(wiphy, "BRCMF_C_DOWN error %d\n", err); err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); if (err < 0) - brcmf_err("setting AP mode failed %d\n", err); + bphy_err(wiphy, "setting AP mode failed %d\n", err); if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) brcmf_fil_iovar_int_set(ifp, "mbss", 0); brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, @@ -4666,7 +4708,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) /* Bring device back up so it can be used again */ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); if (err < 0) - brcmf_err("BRCMF_C_UP error %d\n", err); + bphy_err(wiphy, "BRCMF_C_UP error %d\n", err); brcmf_vif_clear_mgmt_ies(ifp->vif); } else { @@ -4675,7 +4717,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, sizeof(bss_enable)); if (err < 0) - brcmf_err("bss_enable config failed %d\n", err); + bphy_err(wiphy, "bss_enable config failed %d\n", err); } brcmf_set_mpc(ifp, 1); brcmf_configure_arp_nd_offload(ifp, true); @@ -4723,7 +4765,8 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scbval)); if (err) - brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); + bphy_err(wiphy, "SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", + err); brcmf_dbg(TRACE, "Exit\n"); return err; @@ -4753,7 +4796,7 @@ brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_DEAUTHORIZE, (void *)mac, ETH_ALEN); if (err < 0) - brcmf_err("Setting SCB (de-)authorize failed, %d\n", err); + bphy_err(wiphy, "Setting SCB (de-)authorize failed, %d\n", err); return err; } @@ -4803,7 +4846,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, mgmt = (const struct ieee80211_mgmt *)buf; if (!ieee80211_is_mgmt(mgmt->frame_control)) { - brcmf_err("Driver only allows MGMT packet type\n"); + bphy_err(wiphy, "Driver only allows MGMT packet type\n"); return -EPERM; } @@ -4834,13 +4877,13 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, GFP_KERNEL); } else if (ieee80211_is_action(mgmt->frame_control)) { if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) { - brcmf_err("invalid action frame length\n"); + bphy_err(wiphy, "invalid action frame length\n"); err = -EINVAL; goto exit; } af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); if (af_params == NULL) { - brcmf_err("unable to allocate frame\n"); + bphy_err(wiphy, "unable to allocate frame\n"); err = -ENOMEM; goto exit; } @@ -4898,7 +4941,7 @@ brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; if (vif == NULL) { - brcmf_err("No p2p device available for probe response\n"); + bphy_err(wiphy, "No p2p device available for probe response\n"); err = -ENODEV; goto exit; } @@ -4926,7 +4969,7 @@ static int brcmf_cfg80211_get_channel(struct wiphy *wiphy, err = brcmf_fil_iovar_int_get(ifp, "chanspec", &chanspec); if (err) { - brcmf_err("chanspec failed (%d)\n", err); + bphy_err(wiphy, "chanspec failed (%d)\n", err); return err; } @@ -5065,7 +5108,7 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, ret = brcmf_fil_iovar_data_set(ifp, "tdls_endpoint", &info, sizeof(info)); if (ret < 0) - brcmf_err("tdls_endpoint iovar failed: ret=%d\n", ret); + bphy_err(wiphy, "tdls_endpoint iovar failed: ret=%d\n", ret); return ret; } @@ -5086,7 +5129,7 @@ brcmf_cfg80211_update_conn_params(struct wiphy *wiphy, err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); if (err) - brcmf_err("Set Assoc REQ IE Failed\n"); + bphy_err(wiphy, "Set Assoc REQ IE Failed\n"); else brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n"); @@ -5112,7 +5155,7 @@ brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev, ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", >k_le, sizeof(gtk_le)); if (ret < 0) - brcmf_err("gtk_key_info iovar failed: ret=%d\n", ret); + bphy_err(wiphy, "gtk_key_info iovar failed: ret=%d\n", ret); return ret; } @@ -5344,6 +5387,7 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_cfg80211_assoc_ielen_le *assoc_info; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); u32 req_len; @@ -5355,7 +5399,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_iovar_data_get(ifp, "assoc_info", cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { - brcmf_err("could not get assoc info (%d)\n", err); + bphy_err(wiphy, "could not get assoc info (%d)\n", err); return err; } assoc_info = @@ -5367,7 +5411,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { - brcmf_err("could not get assoc req (%d)\n", err); + bphy_err(wiphy, "could not get assoc req (%d)\n", err); return err; } conn_info->req_ie_len = req_len; @@ -5383,7 +5427,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { - brcmf_err("could not get assoc resp (%d)\n", err); + bphy_err(wiphy, "could not get assoc resp (%d)\n", err); return err; } conn_info->resp_ie_len = resp_len; @@ -5510,6 +5554,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); static int generation; u32 event = e->event_code; u32 reason = e->reason; @@ -5527,7 +5572,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) && (reason == BRCMF_E_STATUS_SUCCESS)) { if (!data) { - brcmf_err("No IEs present in ASSOC/REASSOC_IND"); + bphy_err(wiphy, "No IEs present in ASSOC/REASSOC_IND\n"); return -EINVAL; } @@ -5819,6 +5864,7 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event) static s32 brcmf_dongle_roam(struct brcmf_if *ifp) { + struct wiphy *wiphy = ifp->drvr->wiphy; s32 err; u32 bcn_timeout; __le32 roamtrigger[2]; @@ -5831,7 +5877,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp) bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON; err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout); if (err) { - brcmf_err("bcn_timeout error (%d)\n", err); + bphy_err(wiphy, "bcn_timeout error (%d)\n", err); goto roam_setup_done; } @@ -5843,7 +5889,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp) err = brcmf_fil_iovar_int_set(ifp, "roam_off", ifp->drvr->settings->roamoff); if (err) { - brcmf_err("roam_off error (%d)\n", err); + bphy_err(wiphy, "roam_off error (%d)\n", err); goto roam_setup_done; } @@ -5852,7 +5898,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp) err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER, (void *)roamtrigger, sizeof(roamtrigger)); if (err) { - brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err); + bphy_err(wiphy, "WLC_SET_ROAM_TRIGGER error (%d)\n", err); goto roam_setup_done; } @@ -5861,7 +5907,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp) err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA, (void *)roam_delta, sizeof(roam_delta)); if (err) { - brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err); + bphy_err(wiphy, "WLC_SET_ROAM_DELTA error (%d)\n", err); goto roam_setup_done; } @@ -5872,25 +5918,26 @@ roam_setup_done: static s32 brcmf_dongle_scantime(struct brcmf_if *ifp) { + struct wiphy *wiphy = ifp->drvr->wiphy; s32 err = 0; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, BRCMF_SCAN_CHANNEL_TIME); if (err) { - brcmf_err("Scan assoc time error (%d)\n", err); + bphy_err(wiphy, "Scan assoc time error (%d)\n", err); goto dongle_scantime_out; } err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, BRCMF_SCAN_UNASSOC_TIME); if (err) { - brcmf_err("Scan unassoc time error (%d)\n", err); + bphy_err(wiphy, "Scan unassoc time error (%d)\n", err); goto dongle_scantime_out; } err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME, BRCMF_SCAN_PASSIVE_TIME); if (err) { - brcmf_err("Scan passive time error (%d)\n", err); + bphy_err(wiphy, "Scan passive time error (%d)\n", err); goto dongle_scantime_out; } @@ -5922,10 +5969,10 @@ static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel, static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap[]) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); struct ieee80211_supported_band *band; struct ieee80211_channel *channel; - struct wiphy *wiphy; struct brcmf_chanspec_list *list; struct brcmu_chan ch; int err; @@ -5944,11 +5991,10 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf, BRCMF_DCMD_MEDLEN); if (err) { - brcmf_err("get chanspecs error (%d)\n", err); + bphy_err(wiphy, "get chanspecs error (%d)\n", err); goto fail_pbuf; } - wiphy = cfg_to_wiphy(cfg); band = wiphy->bands[NL80211_BAND_2GHZ]; if (band) for (i = 0; i < band->n_channels; i++) @@ -5968,7 +6014,8 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, } else if (ch.band == BRCMU_CHAN_BAND_5G) { band = wiphy->bands[NL80211_BAND_5GHZ]; } else { - brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); + bphy_err(wiphy, "Invalid channel Spec. 0x%x.\n", + ch.chspec); continue; } if (!band) @@ -5991,8 +6038,8 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, /* It seems firmware supports some channel we never * considered. Something new in IEEE standard? */ - brcmf_err("Ignoring unexpected firmware channel %d\n", - ch.control_ch_num); + bphy_err(wiphy, "Ignoring unexpected firmware channel %d\n", + ch.control_ch_num); continue; } @@ -6038,6 +6085,7 @@ fail_pbuf: static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); struct ieee80211_supported_band *band; struct brcmf_fil_bwcap_le band_bwcap; @@ -6084,7 +6132,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf, BRCMF_DCMD_MEDLEN); if (err) { - brcmf_err("get chanspecs error (%d)\n", err); + bphy_err(wiphy, "get chanspecs error (%d)\n", err); kfree(pbuf); return err; } @@ -6115,6 +6163,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) { + struct wiphy *wiphy = ifp->drvr->wiphy; u32 band, mimo_bwcap; int err; @@ -6150,7 +6199,7 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT; break; default: - brcmf_err("invalid mimo_bw_cap value\n"); + bphy_err(wiphy, "invalid mimo_bw_cap value\n"); } } @@ -6226,7 +6275,7 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band, static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) { struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); - struct wiphy *wiphy; + struct wiphy *wiphy = cfg_to_wiphy(cfg); u32 nmode = 0; u32 vhtmode = 0; u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT }; @@ -6242,7 +6291,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); if (err) { - brcmf_err("nmode error (%d)\n", err); + bphy_err(wiphy, "nmode error (%d)\n", err); } else { brcmf_get_bwcap(ifp, bw_cap); } @@ -6252,7 +6301,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain); if (err) { - brcmf_err("rxchain error (%d)\n", err); + bphy_err(wiphy, "rxchain error (%d)\n", err); nchain = 1; } else { for (nchain = 0; rxchain; nchain++) @@ -6262,7 +6311,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) err = brcmf_construct_chaninfo(cfg, bw_cap); if (err) { - brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err); + bphy_err(wiphy, "brcmf_construct_chaninfo failed (%d)\n", err); return err; } @@ -6274,7 +6323,6 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) &txbf_bfr_cap); } - wiphy = cfg_to_wiphy(cfg); for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) { band = wiphy->bands[i]; if (band == NULL) @@ -6475,7 +6523,7 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp) wowl = kmemdup(&brcmf_wowlan_support, sizeof(brcmf_wowlan_support), GFP_KERNEL); if (!wowl) { - brcmf_err("only support basic wowlan features\n"); + bphy_err(wiphy, "only support basic wowlan features\n"); wiphy->wowlan = &brcmf_wowlan_support; return; } @@ -6572,7 +6620,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, &bandlist, sizeof(bandlist)); if (err) { - brcmf_err("could not obtain band info: err=%d\n", err); + bphy_err(wiphy, "could not obtain band info: err=%d\n", err); return err; } /* first entry in bandlist is number of bands */ @@ -6621,6 +6669,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) { + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct net_device *ndev; struct wireless_dev *wdev; struct brcmf_if *ifp; @@ -6658,7 +6707,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1); if (err) { - brcmf_err("failed to set frameburst mode\n"); + bphy_err(wiphy, "failed to set frameburst mode\n"); goto default_conf_out; } @@ -6850,8 +6899,8 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, /* ignore non-ISO3166 country codes */ for (i = 0; i < 2; i++) if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { - brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n", - req->alpha2[0], req->alpha2[1]); + bphy_err(wiphy, "not an ISO3166 code (0x%02x 0x%02x)\n", + req->alpha2[0], req->alpha2[1]); return; } @@ -6860,7 +6909,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq)); if (err) { - brcmf_err("Country code iovar returned err = %d\n", err); + bphy_err(wiphy, "Country code iovar returned err = %d\n", err); return; } @@ -6870,7 +6919,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq)); if (err) { - brcmf_err("Firmware rejected country setting\n"); + bphy_err(wiphy, "Firmware rejected country setting\n"); return; } brcmf_setup_wiphybands(cfg); @@ -6916,13 +6965,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, u16 *cap = NULL; if (!ndev) { - brcmf_err("ndev is invalid\n"); + bphy_err(wiphy, "ndev is invalid\n"); return NULL; } cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); if (!cfg) { - brcmf_err("Could not allocate wiphy device\n"); + bphy_err(wiphy, "Could not allocate wiphy device\n"); return NULL; } @@ -6943,7 +6992,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, err = wl_init_priv(cfg); if (err) { - brcmf_err("Failed to init iwm_priv (%d)\n", err); + bphy_err(wiphy, "Failed to init iwm_priv (%d)\n", err); brcmf_free_vif(vif); goto wiphy_out; } @@ -6952,7 +7001,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, /* determine d11 io type before wiphy setup */ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type); if (err) { - brcmf_err("Failed to get D11 version (%d)\n", err); + bphy_err(wiphy, "Failed to get D11 version (%d)\n", err); goto priv_out; } cfg->d11inf.io_type = (u8)io_type; @@ -6986,13 +7035,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, #endif err = wiphy_register(wiphy); if (err < 0) { - brcmf_err("Could not register wiphy device (%d)\n", err); + bphy_err(wiphy, "Could not register wiphy device (%d)\n", err); goto priv_out; } err = brcmf_setup_wiphybands(cfg); if (err) { - brcmf_err("Setting wiphy bands failed (%d)\n", err); + bphy_err(wiphy, "Setting wiphy bands failed (%d)\n", err); goto wiphy_unreg_out; } @@ -7010,24 +7059,24 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, err = brcmf_fweh_activate_events(ifp); if (err) { - brcmf_err("FWEH activation failed (%d)\n", err); + bphy_err(wiphy, "FWEH activation failed (%d)\n", err); goto wiphy_unreg_out; } err = brcmf_p2p_attach(cfg, p2pdev_forced); if (err) { - brcmf_err("P2P initialisation failed (%d)\n", err); + bphy_err(wiphy, "P2P initialisation failed (%d)\n", err); goto wiphy_unreg_out; } err = brcmf_btcoex_attach(cfg); if (err) { - brcmf_err("BT-coex initialisation failed (%d)\n", err); + bphy_err(wiphy, "BT-coex initialisation failed (%d)\n", err); brcmf_p2p_detach(&cfg->p2p); goto wiphy_unreg_out; } err = brcmf_pno_attach(cfg); if (err) { - brcmf_err("PNO initialisation failed (%d)\n", err); + bphy_err(wiphy, "PNO initialisation failed (%d)\n", err); brcmf_btcoex_detach(cfg); brcmf_p2p_detach(&cfg->p2p); goto wiphy_unreg_out; @@ -7047,7 +7096,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, /* (re-) activate FWEH event handling */ err = brcmf_fweh_activate_events(ifp); if (err) { - brcmf_err("FWEH activation failed (%d)\n", err); + bphy_err(wiphy, "FWEH activation failed (%d)\n", err); goto detach; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h index c1f260718c8e..3cf853c84a9e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h @@ -62,6 +62,15 @@ void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...); } while (0) #endif +#define bphy_err(wiphy, fmt, ...) \ + do { \ + if (IS_ENABLED(CONFIG_BRCMDBG) || \ + IS_ENABLED(CONFIG_BRCM_TRACING) || \ + net_ratelimit()) \ + wiphy_err(wiphy, "%s: " fmt, __func__, \ + ##__VA_ARGS__); \ + } while (0) + #if defined(DEBUG) || defined(CONFIG_BRCM_TRACING) /* For debug/tracing purposes treat info messages as errors */ -- cgit v1.2.3 From 2359dd09f9819c7d57d81e05173541f0f9f820c7 Mon Sep 17 00:00:00 2001 From: Matteo Croce Date: Tue, 29 Jan 2019 18:47:17 +0100 Subject: brcmfmac: fix typos Fix spelling mistakes in brcmfmac: "lenght" -> "length". The typos are also in the special comment blocks which translates to documentation. Signed-off-by: Matteo Croce Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | 2 +- drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 2 +- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h | 2 +- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index dcf6e27cc16f..d8085ce579f4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -36,7 +36,7 @@ #define BRCMF_DCMD_MEDLEN 1536 #define BRCMF_DCMD_MAXLEN 8192 -/* IOCTL from host to device are limited in lenght. A device can only handle +/* IOCTL from host to device are limited in length. A device can only handle * ethernet frame size. This limitation is to be applied by protocol layer. */ #define BRCMF_TX_IOCTL_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 14b948917a1a..cf1ddf988476 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -47,7 +47,7 @@ enum nvram_parser_state { * @state: current parser state. * @data: input buffer being parsed. * @nvram: output buffer with parse result. - * @nvram_len: lenght of parse result. + * @nvram_len: length of parse result. * @line: current line. * @column: current column in line. * @pos: byte offset in input buffer. diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h index 816f80ea925b..31f3e8e83a21 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h @@ -266,7 +266,7 @@ struct brcmf_event { * @status: status information. * @reason: reason code. * @auth_type: authentication type. - * @datalen: lenght of event data buffer. + * @datalen: length of event data buffer. * @addr: ether address. * @ifname: interface name. * @ifidx: interface index. diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 76cfaf6999c8..50830c4341a3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -508,7 +508,7 @@ static void brcmf_usb_rx_complete(struct urb *urb) skb = req->skb; req->skb = NULL; - /* zero lenght packets indicate usb "failure". Do not refill */ + /* zero length packets indicate usb "failure". Do not refill */ if (urb->status != 0 || !urb->actual_length) { brcmu_pkt_buf_free_skb(skb); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL); -- cgit v1.2.3 From e665988be29ccea3584528967b432a5cfd801ca4 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 8 Feb 2019 07:42:30 +0100 Subject: brcmfmac: support monitor frames with the hardware/ucode header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far there were two monitor frame formats: 1) 802.11 frames (with frame (sub)type & all addresses) 2) 802.11 frames with the radiotap header Testing the latest FullMAC firmwares for 4366b1/4366c0 resulted in discovering a new format being used. It seems (almost?) identical to the one known from ucode used in SoftMAC devices which is most likely the same codebase anyway. While new firmwares will /announce/ radiotap header support using the "rtap" fw capability string it seems no string was added for the new ucode header format. All above means that: 1) We need new format support when dealing with a received frame 2) A new feature bit & mapping quirks have to be added manually As for now only an empty radiotap is being created. Adding support for extracting some info (band, channel, signal, etc.) is planned for the future. Signed-off-by: Rafał Miłecki Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 55 ++++++++++++++++++++++ .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 4 ++ .../wireless/broadcom/brcm80211/brcmfmac/feature.h | 4 +- 3 files changed, 62 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 860a4372cb56..e772c0845638 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -43,6 +43,36 @@ #define BRCMF_BSSIDX_INVALID -1 +#define RXS_PBPRES BIT(2) + +#define D11_PHY_HDR_LEN 6 + +struct d11rxhdr_le { + __le16 RxFrameSize; + u16 PAD; + __le16 PhyRxStatus_0; + __le16 PhyRxStatus_1; + __le16 PhyRxStatus_2; + __le16 PhyRxStatus_3; + __le16 PhyRxStatus_4; + __le16 PhyRxStatus_5; + __le16 RxStatus1; + __le16 RxStatus2; + __le16 RxTSFTime; + __le16 RxChan; + u8 unknown[12]; +} __packed; + +struct wlc_d11rxhdr { + struct d11rxhdr_le rxhdr; + __le32 tsf_l; + s8 rssi; + s8 rxpwr0; + s8 rxpwr1; + s8 do_rssi_ma; + s8 rxpwr[4]; +} __packed; + char *brcmf_ifname(struct brcmf_if *ifp) { if (!ifp) @@ -409,6 +439,31 @@ void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb) { if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) { /* Do nothing */ + } else if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR)) { + struct wlc_d11rxhdr *wlc_rxhdr = (struct wlc_d11rxhdr *)skb->data; + struct ieee80211_radiotap_header *radiotap; + unsigned int offset; + u16 RxStatus1; + + RxStatus1 = le16_to_cpu(wlc_rxhdr->rxhdr.RxStatus1); + + offset = sizeof(struct wlc_d11rxhdr); + /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU + * subframes + */ + if (RxStatus1 & RXS_PBPRES) + offset += 2; + offset += D11_PHY_HDR_LEN; + + skb_pull(skb, offset); + + /* TODO: use RX header to fill some radiotap data */ + radiotap = skb_push(skb, sizeof(*radiotap)); + memset(radiotap, 0, sizeof(*radiotap)); + radiotap->it_len = cpu_to_le16(sizeof(*radiotap)); + + /* TODO: 4 bytes with receive status? */ + skb->len -= 4; } else { struct ieee80211_radiotap_header *radiotap; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index 4c5a3995dc35..b91b7ecbfedf 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -103,6 +103,10 @@ static const struct brcmf_feat_fwfeat brcmf_feat_fwfeat_map[] = { { "01-6cb8e269", BIT(BRCMF_FEAT_MONITOR) }, /* brcmfmac4366b-pcie.bin from linux-firmware.git commit 52442afee990 */ { "01-c47a91a4", BIT(BRCMF_FEAT_MONITOR) }, + /* brcmfmac4366b-pcie.bin from linux-firmware.git commit 211de1679a68 */ + { "01-801fb449", BIT(BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR) }, + /* brcmfmac4366c-pcie.bin from linux-firmware.git commit 211de1679a68 */ + { "01-d2cbb8fd", BIT(BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR) }, }; static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h index 0b4974df353a..5e88a7f16ad2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h @@ -35,6 +35,7 @@ * FWSUP: Firmware supplicant. * MONITOR: firmware can pass monitor packets to host. * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header + * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header */ #define BRCMF_FEAT_LIST \ BRCMF_FEAT_DEF(MBSS) \ @@ -52,7 +53,8 @@ BRCMF_FEAT_DEF(GSCAN) \ BRCMF_FEAT_DEF(FWSUP) \ BRCMF_FEAT_DEF(MONITOR) \ - BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) + BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \ + BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) /* * Quirks: -- cgit v1.2.3 From 5208fea64e4fbd8a6f180ee915bb8ab247092469 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 28 Jan 2019 16:43:10 +0100 Subject: mwifiex: don't print error message on coex event The BT coex event is not an error condition. Don't print an error message in this case. The same even in sta_event.c prints a message using the debug level already. Signed-off-by: Stefan Agner Reviewed-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/uap_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c index e86217a6b9ca..ca759d9c0253 100644 --- a/drivers/net/wireless/marvell/mwifiex/uap_event.c +++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c @@ -300,7 +300,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) mwifiex_11h_handle_radar_detected(priv, adapter->event_skb); break; case EVENT_BT_COEX_WLAN_PARA_CHANGE: - dev_err(adapter->dev, "EVENT: BT coex wlan param update\n"); + mwifiex_dbg(adapter, EVENT, "event: BT coex wlan param update\n"); mwifiex_bt_coex_wlan_param_update_event(priv, adapter->event_skb); break; -- cgit v1.2.3 From 78f2ef18e185b09a9d9e5b81d0e39f9a3c698157 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 30 Jan 2019 11:15:26 +0800 Subject: rtlwifi: remove set but not used variable 'cmd_seq' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/realtek/rtlwifi/base.c: In function 'rtl_c2h_content_parsing': drivers/net/wireless/realtek/rtlwifi/base.c:2313:13: warning: variable 'cmd_seq' set but not used [-Wunused-but-set-variable] Signed-off-by: YueHaibing Acked-by: Ping-Ke Shih Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/base.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 7aa68fe5d791..137b68ae457e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -2311,11 +2311,10 @@ static void rtl_c2h_content_parsing(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal_ops *hal_ops = rtlpriv->cfg->ops; const struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops; - u8 cmd_id, cmd_seq, cmd_len; + u8 cmd_id, cmd_len; u8 *cmd_buf = NULL; cmd_id = GET_C2H_CMD_ID(skb->data); - cmd_seq = GET_C2H_SEQ(skb->data); cmd_len = skb->len - C2H_DATA_OFFSET; cmd_buf = GET_C2H_DATA_PTR(skb->data); -- cgit v1.2.3 From 6f3a5de16d681f038d1123fcdd832f3aa1d4f5fa Mon Sep 17 00:00:00 2001 From: Siva Rebbagondla Date: Mon, 4 Feb 2019 12:03:25 +0530 Subject: rsi: Add debug support for wowlan wakeup confirmation When a wowlan magic-packet has received to wake up the device, currently driver is not taking care of what kind of packet has received. This patch will add debug support for wakeup reason in driver. Signed-off-by: Siva Rebbagondla Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_mgmt.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 404241424a62..4c2c776fc86d 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -2003,6 +2003,35 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg) return -1; rsi_send_beacon(common); break; + case WOWLAN_WAKEUP_REASON: + rsi_dbg(ERR_ZONE, "\n\nWakeup Type: %x\n", msg[15]); + switch (msg[15]) { + case RSI_UNICAST_MAGIC_PKT: + rsi_dbg(ERR_ZONE, + "*** Wakeup for Unicast magic packet ***\n"); + break; + case RSI_BROADCAST_MAGICPKT: + rsi_dbg(ERR_ZONE, + "*** Wakeup for Broadcast magic packet ***\n"); + break; + case RSI_EAPOL_PKT: + rsi_dbg(ERR_ZONE, + "*** Wakeup for GTK renewal ***\n"); + break; + case RSI_DISCONNECT_PKT: + rsi_dbg(ERR_ZONE, + "*** Wakeup for Disconnect ***\n"); + break; + case RSI_HW_BMISS_PKT: + rsi_dbg(ERR_ZONE, + "*** Wakeup for HW Beacon miss ***\n"); + break; + default: + rsi_dbg(ERR_ZONE, + "##### Un-intentional Wakeup #####\n"); + break; + } + break; case RX_DOT11_MGMT: return rsi_mgmt_pkt_to_core(common, msg, msg_len); default: -- cgit v1.2.3 From cbde979b33fa16e06dadc2c81093699a2bc787db Mon Sep 17 00:00:00 2001 From: Siva Rebbagondla Date: Mon, 4 Feb 2019 12:03:26 +0530 Subject: rsi: add hci detach for hibernation and poweroff As we missed to detach HCI, while entering power off or hibernation, an extra hci interface gets created whenever system is woken up, to avoid this we added hci_detach() in rsi_disconnect(), rsi_freeze(), and rsi_shutdown() functions which are invoked for these tests. This patch fixes the issue Signed-off-by: Siva Rebbagondla Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_sdio.c | 18 ++++++++++++++++++ drivers/net/wireless/rsi/rsi_91x_usb.c | 7 +++++++ 2 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index b412b65eb1f4..9a3bb0da3202 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1132,6 +1132,12 @@ static void rsi_disconnect(struct sdio_func *pfunction) rsi_mac80211_detach(adapter); mdelay(10); + if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 && + adapter->priv->bt_adapter) { + rsi_bt_ops.detach(adapter->priv->bt_adapter); + adapter->priv->bt_adapter = NULL; + } + /* Reset Chip */ rsi_reset_chip(adapter); @@ -1308,6 +1314,12 @@ static int rsi_freeze(struct device *dev) rsi_dbg(ERR_ZONE, "##### Device can not wake up through WLAN\n"); + if (IS_ENABLED(CONFIG_RSI_COEX) && common->coex_mode > 1 && + common->bt_adapter) { + rsi_bt_ops.detach(common->bt_adapter); + common->bt_adapter = NULL; + } + ret = rsi_sdio_disable_interrupts(pfunction); if (sdev->write_fail) @@ -1355,6 +1367,12 @@ static void rsi_shutdown(struct device *dev) if (rsi_config_wowlan(adapter, wowlan)) rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); + if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 && + adapter->priv->bt_adapter) { + rsi_bt_ops.detach(adapter->priv->bt_adapter); + adapter->priv->bt_adapter = NULL; + } + rsi_sdio_disable_interrupts(sdev->pfunction); if (sdev->write_fail) diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index f360690396dd..d31f9cd1ae90 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -816,6 +816,13 @@ static void rsi_disconnect(struct usb_interface *pfunction) return; rsi_mac80211_detach(adapter); + + if (IS_ENABLED(CONFIG_RSI_COEX) && adapter->priv->coex_mode > 1 && + adapter->priv->bt_adapter) { + rsi_bt_ops.detach(adapter->priv->bt_adapter); + adapter->priv->bt_adapter = NULL; + } + rsi_reset_card(adapter); rsi_deinit_usb_interface(adapter); rsi_91x_deinit(adapter); -- cgit v1.2.3 From a63762d0dc3655e8a5c31c89769eb60be4115e17 Mon Sep 17 00:00:00 2001 From: Siva Rebbagondla Date: Mon, 4 Feb 2019 12:03:27 +0530 Subject: rsi: fix wowlan wakeup issue for hibernate(S4) At SDIO restore ieee80211_restart_hw() is getting called to restart all MAC operations. This step is not required. Returning 1 from mac80211_resume() will serve this purpose. Signed-off-by: Siva Rebbagondla Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 8 ++++++-- drivers/net/wireless/rsi/rsi_91x_sdio.c | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index aded1ae4fad5..8d1282f524cf 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -1938,8 +1938,12 @@ static int rsi_mac80211_resume(struct ieee80211_hw *hw) rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__); - if (common->hibernate_resume) - return 0; + if (common->hibernate_resume) { + /* Device need a complete restart of all MAC operations. + * returning 1 will serve this purpose. + */ + return 1; + } mutex_lock(&common->mutex); rsi_send_wowlan_request(common, 0, 0); diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 9a3bb0da3202..449803cca73f 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1396,7 +1396,6 @@ static int rsi_restore(struct device *dev) common->iface_down = true; adapter->sc_nvifs = 0; - ieee80211_restart_hw(adapter->hw); common->wow_flags = 0; common->iface_down = false; -- cgit v1.2.3 From 73f9b25714870c924edd8f6a62c855558e9d09e5 Mon Sep 17 00:00:00 2001 From: Siva Rebbagondla Date: Mon, 4 Feb 2019 12:03:28 +0530 Subject: rsi: resolve power save issue after S4 resume We are redownloading the firmware after S4 restore and observed in stress test that mac80211 sometimes gives power save request after resume which causes the firmware in bad state. mac_ops_resumed flag is added to skip that request until initialisation is done and Keeping power save state is NONE. Signed-off-by: Siva Rebbagondla Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 9 ++++++++- drivers/net/wireless/rsi/rsi_91x_sdio.c | 1 + drivers/net/wireless/rsi/rsi_main.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 8d1282f524cf..7bc8da69bfed 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -239,6 +239,7 @@ static int rsi_mac80211_hw_scan_start(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss = &vif->bss_conf; rsi_dbg(INFO_ZONE, "***** Hardware scan start *****\n"); + common->mac_ops_resumed = false; if (common->fsm_state != FSM_MAC_INIT_DONE) return -ENODEV; @@ -370,6 +371,10 @@ static void rsi_mac80211_tx(struct ieee80211_hw *hw, { struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; + struct ieee80211_hdr *wlh = (struct ieee80211_hdr *)skb->data; + + if (ieee80211_is_auth(wlh->frame_control)) + common->mac_ops_resumed = false; rsi_core_xmit(common, skb); } @@ -677,7 +682,8 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw, } /* Power save parameters */ - if (changed & IEEE80211_CONF_CHANGE_PS) { + if ((changed & IEEE80211_CONF_CHANGE_PS) && + !common->mac_ops_resumed) { struct ieee80211_vif *vif, *sta_vif = NULL; unsigned long flags; int i, set_ps = 1; @@ -1939,6 +1945,7 @@ static int rsi_mac80211_resume(struct ieee80211_hw *hw) rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__); if (common->hibernate_resume) { + common->mac_ops_resumed = true; /* Device need a complete restart of all MAC operations. * returning 1 will serve this purpose. */ diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 449803cca73f..764ad06cf910 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1396,6 +1396,7 @@ static int rsi_restore(struct device *dev) common->iface_down = true; adapter->sc_nvifs = 0; + adapter->ps_state = PS_NONE; common->wow_flags = 0; common->iface_down = false; diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index 4dc0c0123469..35d13f35e9b0 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -311,6 +311,7 @@ struct rsi_common { struct cfg80211_scan_request *hwscan; struct rsi_bgscan_params bgscan; u8 bgscan_en; + u8 mac_ops_resumed; }; struct eepromrw_info { -- cgit v1.2.3 From 38ef8d9016da9dbca48f4ee4395eda35035f2d7c Mon Sep 17 00:00:00 2001 From: Siva Rebbagondla Date: Mon, 4 Feb 2019 12:03:29 +0530 Subject: rsi: fix for wowlan wakeup failure During wowlan regression tests, sometimes radio is not waking up for wowlan packet in coex mode. This is because of power save is enabled by default in case of coex mode greater than one. Hence, disable power save in coex mode to avoid radio loss. Signed-off-by: Siva Rebbagondla Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 7bc8da69bfed..3fd2571cdcb5 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -1901,6 +1901,10 @@ int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan) return 0; } rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers); + + if (common->coex_mode > 1) + rsi_disable_ps(adapter, adapter->vifs[0]); + rsi_send_wowlan_request(common, triggers, 1); /** -- cgit v1.2.3 From 524d6323af5fbc96df5c681a5e338cbb2c089c46 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 5 Feb 2019 09:48:55 +0000 Subject: qtnfmac: enable WPA3 OWE support In the case of OWE, STA should be able to pass DH IEs from AP assoc responses to wpa_s for processing. For this purpose DH IEs are received from firmware in BSS_JOIN events and passed to wireless core and then to wpa_s as additional optional rsp_ies parameter for cfg80211_connect_result. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/event.c | 144 +++++++++++++++++-------- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 1 + 2 files changed, 102 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 3fd1a9217737..944729b74f17 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -150,6 +150,13 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, struct cfg80211_chan_def chandef; struct cfg80211_bss *bss = NULL; u8 *ie = NULL; + size_t payload_len; + u16 tlv_type; + u16 tlv_value_len; + size_t tlv_full_len; + const struct qlink_tlv_hdr *tlv; + const u8 *rsp_ies = NULL; + size_t rsp_ies_len = 0; if (unlikely(len < sizeof(*join_info))) { pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", @@ -167,67 +174,118 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif, pr_debug("VIF%u.%u: BSSID:%pM status:%u\n", vif->mac->macid, vif->vifid, join_info->bssid, status); - if (status == WLAN_STATUS_SUCCESS) { - qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef); - if (!cfg80211_chandef_valid(&chandef)) { - pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n", + if (status != WLAN_STATUS_SUCCESS) + goto done; + + qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef); + if (!cfg80211_chandef_valid(&chandef)) { + pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n", + vif->mac->macid, vif->vifid, + chandef.chan->center_freq, + chandef.center_freq1, + chandef.center_freq2, + chandef.width); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + + bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid, + NULL, 0, IEEE80211_BSS_TYPE_ESS, + IEEE80211_PRIVACY_ANY); + if (!bss) { + pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n", + vif->mac->macid, vif->vifid, + join_info->bssid, chandef.chan->hw_value); + + if (!vif->wdev.ssid_len) { + pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n", + vif->mac->macid, vif->vifid, + join_info->bssid); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + + ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL); + if (!ie) { + pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n", vif->mac->macid, vif->vifid, - chandef.chan->center_freq, - chandef.center_freq1, - chandef.center_freq2, - chandef.width); + join_info->bssid); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; } - bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid, - NULL, 0, IEEE80211_BSS_TYPE_ESS, - IEEE80211_PRIVACY_ANY); + ie[0] = WLAN_EID_SSID; + ie[1] = vif->wdev.ssid_len; + memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len); + + bss = cfg80211_inform_bss(wiphy, chandef.chan, + CFG80211_BSS_FTYPE_UNKNOWN, + join_info->bssid, 0, + WLAN_CAPABILITY_ESS, 100, + ie, 2 + vif->wdev.ssid_len, + 0, GFP_KERNEL); if (!bss) { - pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n", + pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n", vif->mac->macid, vif->vifid, - join_info->bssid, chandef.chan->hw_value); + join_info->bssid); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + } - if (!vif->wdev.ssid_len) { - pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n", - vif->mac->macid, vif->vifid, - join_info->bssid); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto done; - } + payload_len = len - sizeof(*join_info); + tlv = (struct qlink_tlv_hdr *)join_info->ies; + + while (payload_len >= sizeof(struct qlink_tlv_hdr)) { + tlv_type = le16_to_cpu(tlv->type); + tlv_value_len = le16_to_cpu(tlv->len); + tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL); - if (!ie) { - pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n", - vif->mac->macid, vif->vifid, - join_info->bssid); + if (payload_len < tlv_full_len) { + pr_warn("invalid %u TLV\n", tlv_type); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + + if (tlv_type == QTN_TLV_ID_IE_SET) { + const struct qlink_tlv_ie_set *ie_set; + unsigned int ie_len; + + if (payload_len < sizeof(*ie_set)) { + pr_warn("invalid IE_SET TLV\n"); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; } - ie[0] = WLAN_EID_SSID; - ie[1] = vif->wdev.ssid_len; - memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len); - - bss = cfg80211_inform_bss(wiphy, chandef.chan, - CFG80211_BSS_FTYPE_UNKNOWN, - join_info->bssid, 0, - WLAN_CAPABILITY_ESS, 100, - ie, 2 + vif->wdev.ssid_len, - 0, GFP_KERNEL); - if (!bss) { - pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n", - vif->mac->macid, vif->vifid, - join_info->bssid); - status = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto done; + ie_set = (const struct qlink_tlv_ie_set *)tlv; + ie_len = tlv_value_len - + (sizeof(*ie_set) - sizeof(ie_set->hdr)); + + switch (ie_set->type) { + case QLINK_IE_SET_ASSOC_RESP: + if (ie_len) { + rsp_ies = ie_set->ie_data; + rsp_ies_len = ie_len; + } + break; + default: + pr_warn("unexpected IE type: %u\n", + ie_set->type); + break; } } + + payload_len -= tlv_full_len; + tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } + if (payload_len) + pr_warn("VIF%u.%u: unexpected remaining payload: %zu\n", + vif->mac->macid, vif->vifid, payload_len); + done: - cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL, - 0, status, GFP_KERNEL); + cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, rsp_ies, + rsp_ies_len, status, GFP_KERNEL); if (bss) { if (!ether_addr_equal(vif->bssid, join_info->bssid)) ether_addr_copy(vif->bssid, join_info->bssid); diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 27fdb5b01ee3..1f7ced21cb39 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -984,6 +984,7 @@ struct qlink_event_bss_join { struct qlink_chandef chan; u8 bssid[ETH_ALEN]; __le16 status; + u8 ies[0]; } __packed; /** -- cgit v1.2.3 From 47b08e75a669887b19ecaf4e429cf3c19b748500 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 5 Feb 2019 09:48:57 +0000 Subject: qtnfmac: enable WPA3 SAE support In the case of SAE AP, drivers offload authentication to user-space software, e.g. hostapd. For FullMAC drivers the procedure is as follows. If auth_type is SAE and user space indicates external authentication capability, then driver requests authentication offload to user-space software using cfg80211_external_auth_request call. From that point, auth frame exchange is performed transparently for driver: user-space software sends/receives mgmt frames using mgmt_tx/mgmt_frame_register cfg80211 callbacks. As soon as authenitcation is completed, user-space software notifies driver about its status using external_auth cfg80211 callback. Signed-off-by: Sergey Matyukevich Signed-off-by: Kalle Valo --- drivers/net/wireless/quantenna/qtnfmac/cfg80211.c | 40 ++++++++++++++++++++-- drivers/net/wireless/quantenna/qtnfmac/commands.c | 29 ++++++++++++++++ drivers/net/wireless/quantenna/qtnfmac/commands.h | 2 ++ drivers/net/wireless/quantenna/qtnfmac/event.c | 41 +++++++++++++++++++++++ drivers/net/wireless/quantenna/qtnfmac/qlink.h | 35 +++++++++++++++++++ 5 files changed, 145 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 45f4cef7de9c..dcb0991432f4 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -53,9 +53,11 @@ static const u32 qtnf_cipher_suites[] = { static const struct ieee80211_txrx_stypes qtnf_mgmt_stypes[NUM_NL80211_IFTYPES] = { [NL80211_IFTYPE_STATION] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4), + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4), .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4), }, [NL80211_IFTYPE_AP] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4), @@ -636,6 +638,12 @@ qtnf_connect(struct wiphy *wiphy, struct net_device *dev, if (vif->wdev.iftype != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; + if (sme->auth_type == NL80211_AUTHTYPE_SAE && + !(sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) { + pr_err("can not offload authentication to userspace\n"); + return -EOPNOTSUPP; + } + if (sme->bssid) ether_addr_copy(vif->bssid, sme->bssid); else @@ -652,6 +660,30 @@ out: return ret; } +static int +qtnf_external_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_external_auth_params *auth) +{ + struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); + int ret; + + if (vif->wdev.iftype != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + if (!ether_addr_equal(vif->bssid, auth->bssid)) + pr_warn("unexpected bssid: %pM", auth->bssid); + + ret = qtnf_cmd_send_external_auth(vif, auth); + if (ret) { + pr_err("VIF%u.%u: failed to report external auth\n", + vif->mac->macid, vif->vifid); + goto out; + } + +out: + return ret; +} + static int qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) @@ -946,6 +978,7 @@ static struct cfg80211_ops qtn_cfg80211_ops = { .set_default_mgmt_key = qtnf_set_default_mgmt_key, .scan = qtnf_scan, .connect = qtnf_connect, + .external_auth = qtnf_external_auth, .disconnect = qtnf_disconnect, .dump_survey = qtnf_dump_survey, .get_channel = qtnf_get_channel, @@ -1125,6 +1158,9 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac) if (!(hw_info->hw_capab & QLINK_HW_CAPAB_OBSS_SCAN)) wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN; + if (hw_info->hw_capab & QLINK_HW_CAPAB_SAE) + wiphy->features |= NL80211_FEATURE_SAE; + #ifdef CONFIG_PM if (macinfo->wowlan) wiphy->wowlan = macinfo->wowlan; diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 0f48f541de41..85a2a58f4c16 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -2322,6 +2322,35 @@ out: return ret; } +int qtnf_cmd_send_external_auth(struct qtnf_vif *vif, + struct cfg80211_external_auth_params *auth) +{ + struct sk_buff *cmd_skb; + struct qlink_cmd_external_auth *cmd; + int ret; + + cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, + QLINK_CMD_EXTERNAL_AUTH, + sizeof(*cmd)); + if (!cmd_skb) + return -ENOMEM; + + cmd = (struct qlink_cmd_external_auth *)cmd_skb->data; + + ether_addr_copy(cmd->bssid, auth->bssid); + cmd->status = cpu_to_le16(auth->status); + + qtnf_bus_lock(vif->mac->bus); + ret = qtnf_cmd_send(vif->mac->bus, cmd_skb); + if (ret) + goto out; + +out: + qtnf_bus_unlock(vif->mac->bus); + + return ret; +} + int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code) { struct sk_buff *cmd_skb; diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.h b/drivers/net/wireless/quantenna/qtnfmac/commands.h index 96dff643bbc4..64f0b9dc8a14 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.h +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.h @@ -51,6 +51,8 @@ int qtnf_cmd_send_del_sta(struct qtnf_vif *vif, int qtnf_cmd_send_scan(struct qtnf_wmac *mac); int qtnf_cmd_send_connect(struct qtnf_vif *vif, struct cfg80211_connect_params *sme); +int qtnf_cmd_send_external_auth(struct qtnf_vif *vif, + struct cfg80211_external_auth_params *auth); int qtnf_cmd_send_disconnect(struct qtnf_vif *vif, u16 reason_code); int qtnf_cmd_send_updown_intf(struct qtnf_vif *vif, diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 944729b74f17..6c1b886339ac 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -574,6 +574,43 @@ static int qtnf_event_handle_radar(struct qtnf_vif *vif, return 0; } +static int +qtnf_event_handle_external_auth(struct qtnf_vif *vif, + const struct qlink_event_external_auth *ev, + u16 len) +{ + struct cfg80211_external_auth_params auth = {0}; + struct wiphy *wiphy = priv_to_wiphy(vif->mac); + int ret; + + if (len < sizeof(*ev)) { + pr_err("MAC%u: payload is too short\n", vif->mac->macid); + return -EINVAL; + } + + if (!wiphy->registered || !vif->netdev) + return 0; + + if (ev->ssid_len) { + memcpy(auth.ssid.ssid, ev->ssid, ev->ssid_len); + auth.ssid.ssid_len = ev->ssid_len; + } + + auth.key_mgmt_suite = le32_to_cpu(ev->akm_suite); + ether_addr_copy(auth.bssid, ev->bssid); + auth.action = ev->action; + + pr_info("%s: external auth bss=%pM action=%u akm=%u\n", + vif->netdev->name, auth.bssid, auth.action, + auth.key_mgmt_suite); + + ret = cfg80211_external_auth_request(vif->netdev, &auth, GFP_KERNEL); + if (ret) + pr_warn("failed to offload external auth request\n"); + + return ret; +} + static int qtnf_event_parse(struct qtnf_wmac *mac, const struct sk_buff *event_skb) { @@ -632,6 +669,10 @@ static int qtnf_event_parse(struct qtnf_wmac *mac, ret = qtnf_event_handle_radar(vif, (const void *)event, event_len); break; + case QLINK_EVENT_EXTERNAL_AUTH: + ret = qtnf_event_handle_external_auth(vif, (const void *)event, + event_len); + break; default: pr_warn("unknown event type: %x\n", event_id); break; diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index 1f7ced21cb39..7798edcf7980 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -68,6 +68,7 @@ enum qlink_hw_capab { QLINK_HW_CAPAB_PWR_MGMT = BIT(4), QLINK_HW_CAPAB_OBSS_SCAN = BIT(5), QLINK_HW_CAPAB_SCAN_DWELL = BIT(6), + QLINK_HW_CAPAB_SAE = BIT(8), }; enum qlink_iface_type { @@ -250,6 +251,7 @@ enum qlink_cmd_type { QLINK_CMD_DISCONNECT = 0x0061, QLINK_CMD_PM_SET = 0x0062, QLINK_CMD_WOWLAN_SET = 0x0063, + QLINK_CMD_EXTERNAL_AUTH = 0x0066, }; /** @@ -480,6 +482,20 @@ struct qlink_cmd_connect { u8 payload[0]; } __packed; +/** + * struct qlink_cmd_external_auth - data for QLINK_CMD_EXTERNAL_AUTH command + * + * @bssid: BSSID of the BSS to connect to + * @status: authentication status code + * @payload: variable portion of connection request. + */ +struct qlink_cmd_external_auth { + struct qlink_cmd chdr; + u8 bssid[ETH_ALEN]; + __le16 status; + u8 payload[0]; +} __packed; + /** * struct qlink_cmd_disconnect - data for QLINK_CMD_DISCONNECT command * @@ -925,6 +941,7 @@ enum qlink_event_type { QLINK_EVENT_BSS_LEAVE = 0x0027, QLINK_EVENT_FREQ_CHANGE = 0x0028, QLINK_EVENT_RADAR = 0x0029, + QLINK_EVENT_EXTERNAL_AUTH = 0x0030, }; /** @@ -1100,6 +1117,24 @@ struct qlink_event_radar { u8 rsvd[3]; } __packed; +/** + * struct qlink_event_external_auth - data for QLINK_EVENT_EXTERNAL_AUTH event + * + * @ssid: SSID announced by BSS + * @ssid_len: SSID length + * @bssid: BSSID of the BSS to connect to + * @akm_suite: AKM suite for external authentication + * @action: action type/trigger for external authentication + */ +struct qlink_event_external_auth { + struct qlink_event ehdr; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + u8 bssid[ETH_ALEN]; + __le32 akm_suite; + u8 action; +} __packed; + /* QLINK TLVs (Type-Length Values) definitions */ -- cgit v1.2.3 From 34025a1056a3c82b7e16992da9af54d729dd77fe Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 7 Feb 2019 12:11:41 +0000 Subject: rsi: fix indentation issue with a code block There is a block of code that is indented at the wrong level. Fix this with extra tabbing. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 3fd2571cdcb5..2c12f0102328 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -816,15 +816,15 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw, adapter->ps_info.dtim_interval_duration = bss->dtim_period; adapter->ps_info.listen_interval = conf->listen_interval; - /* If U-APSD is updated, send ps parameters to firmware */ - if (bss->assoc) { - if (common->uapsd_bitmap) { - rsi_dbg(INFO_ZONE, "Configuring UAPSD\n"); - rsi_conf_uapsd(adapter, vif); + /* If U-APSD is updated, send ps parameters to firmware */ + if (bss->assoc) { + if (common->uapsd_bitmap) { + rsi_dbg(INFO_ZONE, "Configuring UAPSD\n"); + rsi_conf_uapsd(adapter, vif); + } + } else { + common->uapsd_bitmap = 0; } - } else { - common->uapsd_bitmap = 0; - } } if (changed & BSS_CHANGED_CQM) { -- cgit v1.2.3 From c675e06a98a474f7ad0af32ce467613da818da52 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Fri, 8 Feb 2019 13:55:31 +0100 Subject: ipvlan: decouple l3s mode dependencies from other modes Right now ipvlan has a hard dependency on CONFIG_NETFILTER and otherwise it cannot be built. However, the only ipvlan operation mode that actually depends on netfilter is l3s, everything else is independent of it. Break this hard dependency such that users are able to use ipvlan l3 mode on systems where netfilter is not compiled in. Therefore, this adds a hidden CONFIG_IPVLAN_L3S bool which is defaulting to y when CONFIG_NETFILTER is set in order to retain existing behavior for l3s. All l3s related code is refactored into ipvlan_l3s.c that is compiled in when enabled. Signed-off-by: Daniel Borkmann Cc: Mahesh Bandewar Cc: Florian Westphal Cc: Martynas Pumputis Acked-by: Florian Westphal Signed-off-by: David S. Miller --- drivers/net/Kconfig | 6 +- drivers/net/ipvlan/Makefile | 3 +- drivers/net/ipvlan/ipvlan.h | 37 ++++++- drivers/net/ipvlan/ipvlan_core.c | 105 ++---------------- drivers/net/ipvlan/ipvlan_l3s.c | 227 +++++++++++++++++++++++++++++++++++++++ drivers/net/ipvlan/ipvlan_main.c | 117 +++----------------- 6 files changed, 287 insertions(+), 208 deletions(-) create mode 100644 drivers/net/ipvlan/ipvlan_l3s.c (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index edb1c023a753..7f9727f64f55 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -145,13 +145,15 @@ config MACVTAP To compile this driver as a module, choose M here: the module will be called macvtap. +config IPVLAN_L3S + depends on NETFILTER + def_bool y + select NET_L3_MASTER_DEV config IPVLAN tristate "IP-VLAN support" depends on INET depends on IPV6 || !IPV6 - depends on NETFILTER - select NET_L3_MASTER_DEV ---help--- This allows one to create virtual devices off of a main interface and packets will be delivered based on the dest L3 (IPv6/IPv4 addr) diff --git a/drivers/net/ipvlan/Makefile b/drivers/net/ipvlan/Makefile index 8a2c64dc9641..3ee95367a994 100644 --- a/drivers/net/ipvlan/Makefile +++ b/drivers/net/ipvlan/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_IPVLAN) += ipvlan.o obj-$(CONFIG_IPVTAP) += ipvtap.o -ipvlan-objs := ipvlan_core.o ipvlan_main.o +ipvlan-objs-$(CONFIG_IPVLAN_L3S) += ipvlan_l3s.o +ipvlan-objs := ipvlan_core.o ipvlan_main.o $(ipvlan-objs-y) diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index adb826f55e60..b906d2f6bd04 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -165,10 +165,9 @@ struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, const void *iaddr, bool is_v6); bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6); void ipvlan_ht_addr_del(struct ipvl_addr *addr); -struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb, - u16 proto); -unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state); +struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, + int addr_type, bool use_dest); +void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type); void ipvlan_count_rx(const struct ipvl_dev *ipvlan, unsigned int len, bool success, bool mcast); int ipvlan_link_new(struct net *src_net, struct net_device *dev, @@ -177,6 +176,36 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev, void ipvlan_link_delete(struct net_device *dev, struct list_head *head); void ipvlan_link_setup(struct net_device *dev); int ipvlan_link_register(struct rtnl_link_ops *ops); +#ifdef CONFIG_IPVLAN_L3S +int ipvlan_l3s_register(struct ipvl_port *port); +void ipvlan_l3s_unregister(struct ipvl_port *port); +void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet); +int ipvlan_l3s_init(void); +void ipvlan_l3s_cleanup(void); +#else +static inline int ipvlan_l3s_register(struct ipvl_port *port) +{ + return -ENOTSUPP; +} + +static inline void ipvlan_l3s_unregister(struct ipvl_port *port) +{ +} + +static inline void ipvlan_migrate_l3s_hook(struct net *oldnet, + struct net *newnet) +{ +} + +static inline int ipvlan_l3s_init(void) +{ + return 0; +} + +static inline void ipvlan_l3s_cleanup(void) +{ +} +#endif /* CONFIG_IPVLAN_L3S */ static inline bool netif_is_ipvlan_port(const struct net_device *dev) { diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 1a8132eb2a3e..e0f5bc82b10c 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -138,7 +138,7 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6) return ret; } -static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type) +void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type) { void *lyr3h = NULL; @@ -355,9 +355,8 @@ out: return ret; } -static struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, - void *lyr3h, int addr_type, - bool use_dest) +struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h, + int addr_type, bool use_dest) { struct ipvl_addr *addr = NULL; @@ -647,7 +646,9 @@ int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) case IPVLAN_MODE_L2: return ipvlan_xmit_mode_l2(skb, dev); case IPVLAN_MODE_L3: +#ifdef CONFIG_IPVLAN_L3S case IPVLAN_MODE_L3S: +#endif return ipvlan_xmit_mode_l3(skb, dev); } @@ -743,8 +744,10 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb) return ipvlan_handle_mode_l2(pskb, port); case IPVLAN_MODE_L3: return ipvlan_handle_mode_l3(pskb, port); +#ifdef CONFIG_IPVLAN_L3S case IPVLAN_MODE_L3S: return RX_HANDLER_PASS; +#endif } /* Should not reach here */ @@ -753,97 +756,3 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb) kfree_skb(skb); return RX_HANDLER_CONSUMED; } - -static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb, - struct net_device *dev) -{ - struct ipvl_addr *addr = NULL; - struct ipvl_port *port; - void *lyr3h; - int addr_type; - - if (!dev || !netif_is_ipvlan_port(dev)) - goto out; - - port = ipvlan_port_get_rcu(dev); - if (!port || port->mode != IPVLAN_MODE_L3S) - goto out; - - lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); - if (!lyr3h) - goto out; - - addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); -out: - return addr; -} - -struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb, - u16 proto) -{ - struct ipvl_addr *addr; - struct net_device *sdev; - - addr = ipvlan_skb_to_addr(skb, dev); - if (!addr) - goto out; - - sdev = addr->master->dev; - switch (proto) { - case AF_INET: - { - int err; - struct iphdr *ip4h = ip_hdr(skb); - - err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr, - ip4h->tos, sdev); - if (unlikely(err)) - goto out; - break; - } -#if IS_ENABLED(CONFIG_IPV6) - case AF_INET6: - { - struct dst_entry *dst; - struct ipv6hdr *ip6h = ipv6_hdr(skb); - int flags = RT6_LOOKUP_F_HAS_SADDR; - struct flowi6 fl6 = { - .flowi6_iif = sdev->ifindex, - .daddr = ip6h->daddr, - .saddr = ip6h->saddr, - .flowlabel = ip6_flowinfo(ip6h), - .flowi6_mark = skb->mark, - .flowi6_proto = ip6h->nexthdr, - }; - - skb_dst_drop(skb); - dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6, - skb, flags); - skb_dst_set(skb, dst); - break; - } -#endif - default: - break; - } - -out: - return skb; -} - -unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state) -{ - struct ipvl_addr *addr; - unsigned int len; - - addr = ipvlan_skb_to_addr(skb, skb->dev); - if (!addr) - goto out; - - skb->dev = addr->master->dev; - len = skb->len + ETH_HLEN; - ipvlan_count_rx(addr->master, len, true, false); -out: - return NF_ACCEPT; -} diff --git a/drivers/net/ipvlan/ipvlan_l3s.c b/drivers/net/ipvlan/ipvlan_l3s.c new file mode 100644 index 000000000000..9a2f24078a54 --- /dev/null +++ b/drivers/net/ipvlan/ipvlan_l3s.c @@ -0,0 +1,227 @@ +/* Copyright (c) 2014 Mahesh Bandewar + * + * 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; either version 2 of + * the License, or (at your option) any later version. + */ + +#include "ipvlan.h" + +static unsigned int ipvlan_netid __read_mostly; + +struct ipvlan_netns { + unsigned int ipvl_nf_hook_refcnt; +}; + +static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb, + struct net_device *dev) +{ + struct ipvl_addr *addr = NULL; + struct ipvl_port *port; + int addr_type; + void *lyr3h; + + if (!dev || !netif_is_ipvlan_port(dev)) + goto out; + + port = ipvlan_port_get_rcu(dev); + if (!port || port->mode != IPVLAN_MODE_L3S) + goto out; + + lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); + if (!lyr3h) + goto out; + + addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); +out: + return addr; +} + +static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, + struct sk_buff *skb, u16 proto) +{ + struct ipvl_addr *addr; + struct net_device *sdev; + + addr = ipvlan_skb_to_addr(skb, dev); + if (!addr) + goto out; + + sdev = addr->master->dev; + switch (proto) { + case AF_INET: + { + struct iphdr *ip4h = ip_hdr(skb); + int err; + + err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr, + ip4h->tos, sdev); + if (unlikely(err)) + goto out; + break; + } +#if IS_ENABLED(CONFIG_IPV6) + case AF_INET6: + { + struct dst_entry *dst; + struct ipv6hdr *ip6h = ipv6_hdr(skb); + int flags = RT6_LOOKUP_F_HAS_SADDR; + struct flowi6 fl6 = { + .flowi6_iif = sdev->ifindex, + .daddr = ip6h->daddr, + .saddr = ip6h->saddr, + .flowlabel = ip6_flowinfo(ip6h), + .flowi6_mark = skb->mark, + .flowi6_proto = ip6h->nexthdr, + }; + + skb_dst_drop(skb); + dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6, + skb, flags); + skb_dst_set(skb, dst); + break; + } +#endif + default: + break; + } +out: + return skb; +} + +static const struct l3mdev_ops ipvl_l3mdev_ops = { + .l3mdev_l3_rcv = ipvlan_l3_rcv, +}; + +static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) +{ + struct ipvl_addr *addr; + unsigned int len; + + addr = ipvlan_skb_to_addr(skb, skb->dev); + if (!addr) + goto out; + + skb->dev = addr->master->dev; + len = skb->len + ETH_HLEN; + ipvlan_count_rx(addr->master, len, true, false); +out: + return NF_ACCEPT; +} + +static const struct nf_hook_ops ipvl_nfops[] = { + { + .hook = ipvlan_nf_input, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_IN, + .priority = INT_MAX, + }, +#if IS_ENABLED(CONFIG_IPV6) + { + .hook = ipvlan_nf_input, + .pf = NFPROTO_IPV6, + .hooknum = NF_INET_LOCAL_IN, + .priority = INT_MAX, + }, +#endif +}; + +static int ipvlan_register_nf_hook(struct net *net) +{ + struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); + int err = 0; + + if (!vnet->ipvl_nf_hook_refcnt) { + err = nf_register_net_hooks(net, ipvl_nfops, + ARRAY_SIZE(ipvl_nfops)); + if (!err) + vnet->ipvl_nf_hook_refcnt = 1; + } else { + vnet->ipvl_nf_hook_refcnt++; + } + + return err; +} + +static void ipvlan_unregister_nf_hook(struct net *net) +{ + struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); + + if (WARN_ON(!vnet->ipvl_nf_hook_refcnt)) + return; + + vnet->ipvl_nf_hook_refcnt--; + if (!vnet->ipvl_nf_hook_refcnt) + nf_unregister_net_hooks(net, ipvl_nfops, + ARRAY_SIZE(ipvl_nfops)); +} + +void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet) +{ + struct ipvlan_netns *old_vnet; + + ASSERT_RTNL(); + + old_vnet = net_generic(oldnet, ipvlan_netid); + if (!old_vnet->ipvl_nf_hook_refcnt) + return; + + ipvlan_register_nf_hook(newnet); + ipvlan_unregister_nf_hook(oldnet); +} + +static void ipvlan_ns_exit(struct net *net) +{ + struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); + + if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) { + vnet->ipvl_nf_hook_refcnt = 0; + nf_unregister_net_hooks(net, ipvl_nfops, + ARRAY_SIZE(ipvl_nfops)); + } +} + +static struct pernet_operations ipvlan_net_ops = { + .id = &ipvlan_netid, + .size = sizeof(struct ipvlan_netns), + .exit = ipvlan_ns_exit, +}; + +int ipvlan_l3s_init(void) +{ + return register_pernet_subsys(&ipvlan_net_ops); +} + +void ipvlan_l3s_cleanup(void) +{ + unregister_pernet_subsys(&ipvlan_net_ops); +} + +int ipvlan_l3s_register(struct ipvl_port *port) +{ + struct net_device *dev = port->dev; + int ret; + + ASSERT_RTNL(); + + ret = ipvlan_register_nf_hook(read_pnet(&port->pnet)); + if (!ret) { + dev->l3mdev_ops = &ipvl_l3mdev_ops; + dev->priv_flags |= IFF_L3MDEV_MASTER; + } + + return ret; +} + +void ipvlan_l3s_unregister(struct ipvl_port *port) +{ + struct net_device *dev = port->dev; + + ASSERT_RTNL(); + + dev->priv_flags &= ~IFF_L3MDEV_MASTER; + ipvlan_unregister_nf_hook(read_pnet(&port->pnet)); + dev->l3mdev_ops = NULL; +} diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 19bdde60680c..8ec73d973079 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -9,73 +9,10 @@ #include "ipvlan.h" -static unsigned int ipvlan_netid __read_mostly; - -struct ipvlan_netns { - unsigned int ipvl_nf_hook_refcnt; -}; - -static const struct nf_hook_ops ipvl_nfops[] = { - { - .hook = ipvlan_nf_input, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_LOCAL_IN, - .priority = INT_MAX, - }, -#if IS_ENABLED(CONFIG_IPV6) - { - .hook = ipvlan_nf_input, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_IN, - .priority = INT_MAX, - }, -#endif -}; - -static const struct l3mdev_ops ipvl_l3mdev_ops = { - .l3mdev_l3_rcv = ipvlan_l3_rcv, -}; - -static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev) -{ - ipvlan->dev->mtu = dev->mtu; -} - -static int ipvlan_register_nf_hook(struct net *net) -{ - struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); - int err = 0; - - if (!vnet->ipvl_nf_hook_refcnt) { - err = nf_register_net_hooks(net, ipvl_nfops, - ARRAY_SIZE(ipvl_nfops)); - if (!err) - vnet->ipvl_nf_hook_refcnt = 1; - } else { - vnet->ipvl_nf_hook_refcnt++; - } - - return err; -} - -static void ipvlan_unregister_nf_hook(struct net *net) -{ - struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); - - if (WARN_ON(!vnet->ipvl_nf_hook_refcnt)) - return; - - vnet->ipvl_nf_hook_refcnt--; - if (!vnet->ipvl_nf_hook_refcnt) - nf_unregister_net_hooks(net, ipvl_nfops, - ARRAY_SIZE(ipvl_nfops)); -} - static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval, struct netlink_ext_ack *extack) { struct ipvl_dev *ipvlan; - struct net_device *mdev = port->dev; unsigned int flags; int err; @@ -97,17 +34,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval, } if (nval == IPVLAN_MODE_L3S) { /* New mode is L3S */ - err = ipvlan_register_nf_hook(read_pnet(&port->pnet)); - if (!err) { - mdev->l3mdev_ops = &ipvl_l3mdev_ops; - mdev->priv_flags |= IFF_L3MDEV_MASTER; - } else + err = ipvlan_l3s_register(port); + if (err) goto fail; } else if (port->mode == IPVLAN_MODE_L3S) { /* Old mode was L3S */ - mdev->priv_flags &= ~IFF_L3MDEV_MASTER; - ipvlan_unregister_nf_hook(read_pnet(&port->pnet)); - mdev->l3mdev_ops = NULL; + ipvlan_l3s_unregister(port); } port->mode = nval; } @@ -166,11 +98,8 @@ static void ipvlan_port_destroy(struct net_device *dev) struct ipvl_port *port = ipvlan_port_get_rtnl(dev); struct sk_buff *skb; - if (port->mode == IPVLAN_MODE_L3S) { - dev->priv_flags &= ~IFF_L3MDEV_MASTER; - ipvlan_unregister_nf_hook(dev_net(dev)); - dev->l3mdev_ops = NULL; - } + if (port->mode == IPVLAN_MODE_L3S) + ipvlan_l3s_unregister(port); netdev_rx_handler_unregister(dev); cancel_work_sync(&port->wq); while ((skb = __skb_dequeue(&port->backlog)) != NULL) { @@ -446,6 +375,11 @@ static const struct header_ops ipvlan_header_ops = { .cache_update = eth_header_cache_update, }; +static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev) +{ + ipvlan->dev->mtu = dev->mtu; +} + static bool netif_is_ipvlan(const struct net_device *dev) { /* both ipvlan and ipvtap devices use the same netdev_ops */ @@ -781,7 +715,6 @@ static int ipvlan_device_event(struct notifier_block *unused, case NETDEV_REGISTER: { struct net *oldnet, *newnet = dev_net(dev); - struct ipvlan_netns *old_vnet; oldnet = read_pnet(&port->pnet); if (net_eq(newnet, oldnet)) @@ -789,12 +722,7 @@ static int ipvlan_device_event(struct notifier_block *unused, write_pnet(&port->pnet, newnet); - old_vnet = net_generic(oldnet, ipvlan_netid); - if (!old_vnet->ipvl_nf_hook_refcnt) - break; - - ipvlan_register_nf_hook(newnet); - ipvlan_unregister_nf_hook(oldnet); + ipvlan_migrate_l3s_hook(oldnet, newnet); break; } case NETDEV_UNREGISTER: @@ -1068,23 +996,6 @@ static struct notifier_block ipvlan_addr6_vtor_notifier_block __read_mostly = { }; #endif -static void ipvlan_ns_exit(struct net *net) -{ - struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid); - - if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) { - vnet->ipvl_nf_hook_refcnt = 0; - nf_unregister_net_hooks(net, ipvl_nfops, - ARRAY_SIZE(ipvl_nfops)); - } -} - -static struct pernet_operations ipvlan_net_ops = { - .id = &ipvlan_netid, - .size = sizeof(struct ipvlan_netns), - .exit = ipvlan_ns_exit, -}; - static int __init ipvlan_init_module(void) { int err; @@ -1099,13 +1010,13 @@ static int __init ipvlan_init_module(void) register_inetaddr_notifier(&ipvlan_addr4_notifier_block); register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block); - err = register_pernet_subsys(&ipvlan_net_ops); + err = ipvlan_l3s_init(); if (err < 0) goto error; err = ipvlan_link_register(&ipvlan_link_ops); if (err < 0) { - unregister_pernet_subsys(&ipvlan_net_ops); + ipvlan_l3s_cleanup(); goto error; } @@ -1126,7 +1037,7 @@ error: static void __exit ipvlan_cleanup_module(void) { rtnl_link_unregister(&ipvlan_link_ops); - unregister_pernet_subsys(&ipvlan_net_ops); + ipvlan_l3s_cleanup(); unregister_netdevice_notifier(&ipvlan_notifier_block); unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block); unregister_inetaddr_validator_notifier( -- cgit v1.2.3 From b9ad6de534279daa1158f52693f6c0f54c6de6ae Mon Sep 17 00:00:00 2001 From: Paul Fox Date: Fri, 8 Feb 2019 16:25:37 +0000 Subject: sfc: add bundle partition definitions to mtd Signed-off-by: Paul Fox Signed-off-by: Bert Kenward Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef10.c | 2 ++ drivers/net/ethernet/sfc/mcdi_pcol.h | 8 ++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 6062e99fa69b..bc92d73047c6 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -6046,6 +6046,8 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = { { NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS, 0, 0, "sfc_dynamic_cfg_dflt" }, { NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS, 0, 0, "sfc_exp_rom_cfg_dflt" }, { NVRAM_PARTITION_TYPE_STATUS, 0, 0, "sfc_status" }, + { NVRAM_PARTITION_TYPE_BUNDLE, 0, 0, "sfc_bundle" }, + { NVRAM_PARTITION_TYPE_BUNDLE_METADATA, 0, 0, "sfc_bundle_metadata" }, }; #define EF10_NVRAM_PARTITION_COUNT ARRAY_SIZE(efx_ef10_nvram_types) diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h index 3839eec783ea..20a5523bf9f3 100644 --- a/drivers/net/ethernet/sfc/mcdi_pcol.h +++ b/drivers/net/ethernet/sfc/mcdi_pcol.h @@ -6784,6 +6784,14 @@ * subset of the information stored in this partition. */ #define NVRAM_PARTITION_TYPE_FRU_INFORMATION 0x1d00 +/* enum: Bundle image partition */ +#define NVRAM_PARTITION_TYPE_BUNDLE 0x1e00 +/* enum: Bundle metadata partition that holds additional information related to + * a bundle update in TLV format + */ +#define NVRAM_PARTITION_TYPE_BUNDLE_METADATA 0x1e01 +/* enum: Bundle update non-volatile log output partition */ +#define NVRAM_PARTITION_TYPE_BUNDLE_LOG 0x1e02 /* enum: Start of reserved value range (firmware may use for any purpose) */ #define NVRAM_PARTITION_TYPE_RESERVED_VALUES_MIN 0xff00 /* enum: End of reserved value range (firmware may use for any purpose) */ -- cgit v1.2.3 From c0bc5d8e2badeebe14b4005da794a8705b69320e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 8 Feb 2019 17:41:13 +0100 Subject: nfp: flower: remove unused index from nfp_fl_pedit() Static checker warning complains on uninitialized variable: drivers/net/ethernet/netronome/nfp/flower/action.c:618 nfp_fl_pedit() error: uninitialized symbol 'idx'. Which is actually never used from the functions that take it as parameter. Remove it. Fixes: 738678817573 ("drivers: net: use flow action infrastructure") Reported-by: Dan Carpenter Signed-off-by: Pablo Neira Ayuso Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/action.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index 583e97c99e68..eeda4ed98333 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -345,7 +345,7 @@ static void nfp_fl_set_helper32(u32 value, u32 mask, u8 *p_exact, u8 *p_mask) } static int -nfp_fl_set_eth(const struct flow_action_entry *act, int idx, u32 off, +nfp_fl_set_eth(const struct flow_action_entry *act, u32 off, struct nfp_fl_set_eth *set_eth) { u32 exact, mask; @@ -376,7 +376,7 @@ struct ipv4_ttl_word { }; static int -nfp_fl_set_ip4(const struct flow_action_entry *act, int idx, u32 off, +nfp_fl_set_ip4(const struct flow_action_entry *act, u32 off, struct nfp_fl_set_ip4_addrs *set_ip_addr, struct nfp_fl_set_ip4_ttl_tos *set_ip_ttl_tos) { @@ -505,7 +505,7 @@ nfp_fl_set_ip6_hop_limit_flow_label(u32 off, __be32 exact, __be32 mask, } static int -nfp_fl_set_ip6(const struct flow_action_entry *act, int idx, u32 off, +nfp_fl_set_ip6(const struct flow_action_entry *act, u32 off, struct nfp_fl_set_ipv6_addr *ip_dst, struct nfp_fl_set_ipv6_addr *ip_src, struct nfp_fl_set_ipv6_tc_hl_fl *ip_hl_fl) @@ -541,7 +541,7 @@ nfp_fl_set_ip6(const struct flow_action_entry *act, int idx, u32 off, } static int -nfp_fl_set_tport(const struct flow_action_entry *act, int idx, u32 off, +nfp_fl_set_tport(const struct flow_action_entry *act, u32 off, struct nfp_fl_set_tport *set_tport, int opcode) { u32 exact, mask; @@ -598,8 +598,8 @@ nfp_fl_pedit(const struct flow_action_entry *act, struct nfp_fl_set_eth set_eth; size_t act_size = 0; u8 ip_proto = 0; - int idx, err; u32 offset; + int err; memset(&set_ip6_tc_hl_fl, 0, sizeof(set_ip6_tc_hl_fl)); memset(&set_ip_ttl_tos, 0, sizeof(set_ip_ttl_tos)); @@ -614,22 +614,22 @@ nfp_fl_pedit(const struct flow_action_entry *act, switch (htype) { case TCA_PEDIT_KEY_EX_HDR_TYPE_ETH: - err = nfp_fl_set_eth(act, idx, offset, &set_eth); + err = nfp_fl_set_eth(act, offset, &set_eth); break; case TCA_PEDIT_KEY_EX_HDR_TYPE_IP4: - err = nfp_fl_set_ip4(act, idx, offset, &set_ip_addr, + err = nfp_fl_set_ip4(act, offset, &set_ip_addr, &set_ip_ttl_tos); break; case TCA_PEDIT_KEY_EX_HDR_TYPE_IP6: - err = nfp_fl_set_ip6(act, idx, offset, &set_ip6_dst, + err = nfp_fl_set_ip6(act, offset, &set_ip6_dst, &set_ip6_src, &set_ip6_tc_hl_fl); break; case TCA_PEDIT_KEY_EX_HDR_TYPE_TCP: - err = nfp_fl_set_tport(act, idx, offset, &set_tport, + err = nfp_fl_set_tport(act, offset, &set_tport, NFP_FL_ACTION_OPCODE_SET_TCP); break; case TCA_PEDIT_KEY_EX_HDR_TYPE_UDP: - err = nfp_fl_set_tport(act, idx, offset, &set_tport, + err = nfp_fl_set_tport(act, offset, &set_tport, NFP_FL_ACTION_OPCODE_SET_UDP); break; default: -- cgit v1.2.3 From a9b6d9ef0965d352a7c87175d7e9575b0e31d6d8 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 8 Feb 2019 12:37:33 -0600 Subject: veth: Mark expected switch fall-throughs In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/veth.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/veth.c b/drivers/net/veth.c index f412ea1cef18..fbf890ebbeae 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -540,8 +540,10 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_rq *rq, goto xdp_xmit; default: bpf_warn_invalid_xdp_action(act); + /* fall through */ case XDP_ABORTED: trace_xdp_exception(rq->dev, xdp_prog, act); + /* fall through */ case XDP_DROP: goto err_xdp; } @@ -661,8 +663,10 @@ static struct sk_buff *veth_xdp_rcv_skb(struct veth_rq *rq, struct sk_buff *skb, goto xdp_xmit; default: bpf_warn_invalid_xdp_action(act); + /* fall through */ case XDP_ABORTED: trace_xdp_exception(rq->dev, xdp_prog, act); + /* fall through */ case XDP_DROP: goto drop; } -- cgit v1.2.3 From 2067458cf67490ba1013c918803852fe5e56221a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 8 Feb 2019 12:53:56 -0600 Subject: net: appletalk: cops: mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Notice that, in this particular case, the fall-through annotation is placed at the beginning of the code comment, which is what GCC is expecting to find. Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/appletalk/cops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index f90bb723985f..b3c63d2f16aa 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -301,7 +301,7 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) dev->irq = cops_irq(ioaddr, board); if (dev->irq) break; - /* No IRQ found on this port, fallthrough */ + /* fall through - Once no IRQ found on this port. */ case 1: retval = -EINVAL; goto err_out; -- cgit v1.2.3 From 209d6e7b47e3547b1fdf84de2d0c9d18cbf335cf Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 8 Feb 2019 13:07:29 -0600 Subject: net: usb: pegasus: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/usb/pegasus.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index f4247b275e09..63e44e746ccc 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -1011,6 +1011,7 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) switch (cmd) { case SIOCDEVPRIVATE: data[0] = pegasus->phy; + /* fall through */ case SIOCDEVPRIVATE + 1: read_mii_word(pegasus, data[0], data[1] & 0x1f, &data[3]); res = 0; -- cgit v1.2.3 From 0d156a371542b14cf9bdd75c8e8453172864e964 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 8 Feb 2019 13:09:06 -0600 Subject: net: usb: rtl8150: mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/usb/rtl8150.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 3f145e4c6c08..59dbdbb5feff 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -847,6 +847,7 @@ static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) switch (cmd) { case SIOCDEVPRIVATE: data[0] = dev->phy; + /* fall through */ case SIOCDEVPRIVATE + 1: read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]); break; -- cgit v1.2.3 From 1323f75fba732a20a694b66ee9eac22387664a4c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 8 Feb 2019 13:14:12 -0600 Subject: net: fddi: skfp: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/fddi/skfp/pcmplc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/fddi/skfp/pcmplc.c b/drivers/net/fddi/skfp/pcmplc.c index 6ef44c480bd5..f29f5a6a45ab 100644 --- a/drivers/net/fddi/skfp/pcmplc.c +++ b/drivers/net/fddi/skfp/pcmplc.c @@ -851,6 +851,7 @@ static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd) case ACTIONS(PC5_SIGNAL) : ACTIONS_DONE() ; + /* fall through */ case PC5_SIGNAL : if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT)) break ; -- cgit v1.2.3 From 671f2f96813569fcc4bac306cb5a61752de9b91d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 8 Feb 2019 13:16:47 -0600 Subject: net: wimax/i2400m: mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index f8eb66ef2944..73842a830645 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -210,6 +210,7 @@ retry: msleep(10); /* give the device some time */ goto retry; } + /* fall through */ case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ -- cgit v1.2.3 From 7499a288bf1a4a49be9d72beb0a5c7b9aa6ffec9 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 8 Feb 2019 13:58:38 -0600 Subject: xen-netback: mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Warning level 3 was used: -Wimplicit-fallthrough=3 This patch is part of the ongoing efforts to enabling -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/xen-netback/xenbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 2625740bdc4a..330ddb64930f 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -655,7 +655,7 @@ static void frontend_changed(struct xenbus_device *dev, set_backend_state(be, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; - /* fall through if not online */ + /* fall through - if not online */ case XenbusStateUnknown: set_backend_state(be, XenbusStateClosed); device_unregister(&dev->dev); -- cgit v1.2.3 From 7c62cfb8c5744b377e9f33806e0db87a00dc6884 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:45 +0000 Subject: devlink: publish params only after driver init is done Currently, user can do dump or get of param values right after the devlink params are registered. However the driver may not be initialized which is an issue. The same problem happens during notification upon param registration. Allow driver to publish devlink params whenever it is ready to handle get() ops. Note that this cannot be resolved by init reordering, as the "driverinit" params have to be available before the driver is initialized (it needs the param values there). Signed-off-by: Jiri Pirko Cc: Michael Chan Cc: Tariq Toukan Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 3 ++ drivers/net/ethernet/mellanox/mlx4/main.c | 1 + drivers/net/ethernet/mellanox/mlxsw/core.c | 5 +++ include/net/devlink.h | 11 ++++++ net/core/devlink.c | 48 ++++++++++++++++++++++- 5 files changed, 67 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index a6abfa4fb168..2955e404fd18 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -258,6 +258,9 @@ int bnxt_dl_register(struct bnxt *bp) netdev_err(bp->dev, "devlink_port_params_register failed"); goto err_dl_port_unreg; } + + devlink_params_publish(dl); + return 0; err_dl_port_unreg: diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index bdb8dd161923..1f6e16d5ea6b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -3981,6 +3981,7 @@ static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto err_params_unregister; + devlink_params_publish(devlink); pci_save_state(pdev); return 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 4f6fa515394e..b505d3858235 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1062,6 +1062,9 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, goto err_driver_init; } + if (mlxsw_driver->params_register && !reload) + devlink_params_publish(devlink); + return 0; err_driver_init: @@ -1131,6 +1134,8 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, return; } + if (mlxsw_core->driver->params_unregister && !reload) + devlink_params_unpublish(devlink); if (mlxsw_core->driver->fini) mlxsw_core->driver->fini(mlxsw_core); mlxsw_thermal_fini(mlxsw_core->thermal); diff --git a/include/net/devlink.h b/include/net/devlink.h index c12ad6e9095d..2b384a38911b 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -358,6 +358,7 @@ struct devlink_param_item { const struct devlink_param *param; union devlink_param_value driverinit_value; bool driverinit_value_valid; + bool published; }; enum devlink_param_generic_id { @@ -618,6 +619,8 @@ int devlink_params_register(struct devlink *devlink, void devlink_params_unregister(struct devlink *devlink, const struct devlink_param *params, size_t params_count); +void devlink_params_publish(struct devlink *devlink); +void devlink_params_unpublish(struct devlink *devlink); int devlink_port_params_register(struct devlink_port *devlink_port, const struct devlink_param *params, size_t params_count); @@ -724,6 +727,14 @@ static inline void devlink_unregister(struct devlink *devlink) { } +static inline void devlink_params_publish(struct devlink *devlink) +{ +} + +static inline void devlink_params_unpublish(struct devlink *devlink) +{ +} + static inline void devlink_free(struct devlink *devlink) { kfree(devlink); diff --git a/net/core/devlink.c b/net/core/devlink.c index 7fbdba547d4f..e6a015b8ac9b 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -2858,6 +2858,7 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, u32 portid, u32 seq, int flags) { union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; + bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {}; const struct devlink_param *param = param_item->param; struct devlink_param_gset_ctx ctx; struct nlattr *param_values_list; @@ -2876,12 +2877,15 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, return -EOPNOTSUPP; param_value[i] = param_item->driverinit_value; } else { + if (!param_item->published) + continue; ctx.cmode = i; err = devlink_param_get(devlink, param, &ctx); if (err) return err; param_value[i] = ctx.val; } + param_value_set[i] = true; } hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); @@ -2916,7 +2920,7 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, goto param_nest_cancel; for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { - if (!devlink_param_cmode_is_supported(param, i)) + if (!param_value_set[i]) continue; err = devlink_nl_param_value_fill_one(msg, param->type, i, param_value[i]); @@ -5886,6 +5890,48 @@ void devlink_params_unregister(struct devlink *devlink, } EXPORT_SYMBOL_GPL(devlink_params_unregister); +/** + * devlink_params_publish - publish configuration parameters + * + * @devlink: devlink + * + * Publish previously registered configuration parameters. + */ +void devlink_params_publish(struct devlink *devlink) +{ + struct devlink_param_item *param_item; + + list_for_each_entry(param_item, &devlink->param_list, list) { + if (param_item->published) + continue; + param_item->published = true; + devlink_param_notify(devlink, 0, param_item, + DEVLINK_CMD_PARAM_NEW); + } +} +EXPORT_SYMBOL_GPL(devlink_params_publish); + +/** + * devlink_params_unpublish - unpublish configuration parameters + * + * @devlink: devlink + * + * Unpublish previously registered configuration parameters. + */ +void devlink_params_unpublish(struct devlink *devlink) +{ + struct devlink_param_item *param_item; + + list_for_each_entry(param_item, &devlink->param_list, list) { + if (!param_item->published) + continue; + param_item->published = false; + devlink_param_notify(devlink, 0, param_item, + DEVLINK_CMD_PARAM_DEL); + } +} +EXPORT_SYMBOL_GPL(devlink_params_unpublish); + /** * devlink_port_params_register - register port configuration parameters * -- cgit v1.2.3 From 9069a3817d82b01b3a55da382c774e3575946130 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:46 +0000 Subject: lib: objagg: implement optimization hints assembly and use hints for object creation Implement simple greedy algo to find more optimized root-delta tree for a given objagg instance. This "hints" can be used by a driver to: 1) check if the hints are better (driver's choice) than the original objagg tree. Driver does comparison of objagg stats and hints stats. 2) use the hints to create a new objagg instance which will construct the root-delta tree according to the passed hints. Currently, only a simple greedy algorithm is implemented. Basically it finds the roots according to the maximal possible user count including deltas. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c | 37 +- include/linux/objagg.h | 20 +- lib/objagg.c | 573 ++++++++++++++++++++- lib/test_objagg.c | 194 ++++++- 4 files changed, 802 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index 2941967e1cc5..302070a74f2e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -1200,6 +1200,32 @@ mlxsw_sp_acl_erp_delta_fill(const struct mlxsw_sp_acl_erp_key *parent_key, return 0; } +static bool mlxsw_sp_acl_erp_delta_check(void *priv, const void *parent_obj, + const void *obj) +{ + const struct mlxsw_sp_acl_erp_key *parent_key = parent_obj; + const struct mlxsw_sp_acl_erp_key *key = obj; + u16 delta_start; + u8 delta_mask; + int err; + + err = mlxsw_sp_acl_erp_delta_fill(parent_key, key, + &delta_start, &delta_mask); + return err ? false : true; +} + +static int mlxsw_sp_acl_erp_hints_obj_cmp(const void *obj1, const void *obj2) +{ + const struct mlxsw_sp_acl_erp_key *key1 = obj1; + const struct mlxsw_sp_acl_erp_key *key2 = obj2; + + /* For hints purposes, two objects are considered equal + * in case the masks are the same. Does not matter what + * the "ctcam" value is. + */ + return memcmp(key1->mask, key2->mask, sizeof(key1->mask)); +} + static void *mlxsw_sp_acl_erp_delta_create(void *priv, void *parent_obj, void *obj) { @@ -1254,12 +1280,17 @@ static void mlxsw_sp_acl_erp_delta_destroy(void *priv, void *delta_priv) kfree(delta); } -static void *mlxsw_sp_acl_erp_root_create(void *priv, void *obj) +static void *mlxsw_sp_acl_erp_root_create(void *priv, void *obj, + unsigned int root_id) { struct mlxsw_sp_acl_atcam_region *aregion = priv; struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table; struct mlxsw_sp_acl_erp_key *key = obj; + if (!key->ctcam && + root_id != OBJAGG_OBJ_ROOT_ID_INVALID && + root_id >= MLXSW_SP_ACL_ERP_MAX_PER_REGION) + return ERR_PTR(-ENOBUFS); return erp_table->ops->erp_create(erp_table, key); } @@ -1273,6 +1304,8 @@ static void mlxsw_sp_acl_erp_root_destroy(void *priv, void *root_priv) static const struct objagg_ops mlxsw_sp_acl_erp_objagg_ops = { .obj_size = sizeof(struct mlxsw_sp_acl_erp_key), + .delta_check = mlxsw_sp_acl_erp_delta_check, + .hints_obj_cmp = mlxsw_sp_acl_erp_hints_obj_cmp, .delta_create = mlxsw_sp_acl_erp_delta_create, .delta_destroy = mlxsw_sp_acl_erp_delta_destroy, .root_create = mlxsw_sp_acl_erp_root_create, @@ -1290,7 +1323,7 @@ mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion) return ERR_PTR(-ENOMEM); erp_table->objagg = objagg_create(&mlxsw_sp_acl_erp_objagg_ops, - aregion); + NULL, aregion); if (IS_ERR(erp_table->objagg)) { err = PTR_ERR(erp_table->objagg); goto err_objagg_create; diff --git a/include/linux/objagg.h b/include/linux/objagg.h index 34f38c186ea0..a675286df1af 100644 --- a/include/linux/objagg.h +++ b/include/linux/objagg.h @@ -6,14 +6,19 @@ struct objagg_ops { size_t obj_size; + bool (*delta_check)(void *priv, const void *parent_obj, + const void *obj); + int (*hints_obj_cmp)(const void *obj1, const void *obj2); void * (*delta_create)(void *priv, void *parent_obj, void *obj); void (*delta_destroy)(void *priv, void *delta_priv); - void * (*root_create)(void *priv, void *obj); + void * (*root_create)(void *priv, void *obj, unsigned int root_id); +#define OBJAGG_OBJ_ROOT_ID_INVALID UINT_MAX void (*root_destroy)(void *priv, void *root_priv); }; struct objagg; struct objagg_obj; +struct objagg_hints; const void *objagg_obj_root_priv(const struct objagg_obj *objagg_obj); const void *objagg_obj_delta_priv(const struct objagg_obj *objagg_obj); @@ -21,7 +26,8 @@ const void *objagg_obj_raw(const struct objagg_obj *objagg_obj); struct objagg_obj *objagg_obj_get(struct objagg *objagg, void *obj); void objagg_obj_put(struct objagg *objagg, struct objagg_obj *objagg_obj); -struct objagg *objagg_create(const struct objagg_ops *ops, void *priv); +struct objagg *objagg_create(const struct objagg_ops *ops, + struct objagg_hints *hints, void *priv); void objagg_destroy(struct objagg *objagg); struct objagg_obj_stats { @@ -43,4 +49,14 @@ struct objagg_stats { const struct objagg_stats *objagg_stats_get(struct objagg *objagg); void objagg_stats_put(const struct objagg_stats *objagg_stats); +enum objagg_opt_algo_type { + OBJAGG_OPT_ALGO_SIMPLE_GREEDY, +}; + +struct objagg_hints *objagg_hints_get(struct objagg *objagg, + enum objagg_opt_algo_type opt_algo_type); +void objagg_hints_put(struct objagg_hints *objagg_hints); +const struct objagg_stats * +objagg_hints_stats_get(struct objagg_hints *objagg_hints); + #endif diff --git a/lib/objagg.c b/lib/objagg.c index dae390bcef1a..befe8a47d080 100644 --- a/lib/objagg.c +++ b/lib/objagg.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -11,6 +12,34 @@ #define CREATE_TRACE_POINTS #include +struct objagg_hints { + struct rhashtable node_ht; + struct rhashtable_params ht_params; + struct list_head node_list; + unsigned int node_count; + unsigned int root_count; + unsigned int refcount; + const struct objagg_ops *ops; +}; + +struct objagg_hints_node { + struct rhash_head ht_node; /* member of objagg_hints->node_ht */ + struct list_head list; /* member of objagg_hints->node_list */ + struct objagg_hints_node *parent; + unsigned int root_id; + struct objagg_obj_stats_info stats_info; + unsigned long obj[0]; +}; + +static struct objagg_hints_node * +objagg_hints_lookup(struct objagg_hints *objagg_hints, void *obj) +{ + if (!objagg_hints) + return NULL; + return rhashtable_lookup_fast(&objagg_hints->node_ht, obj, + objagg_hints->ht_params); +} + struct objagg { const struct objagg_ops *ops; void *priv; @@ -18,6 +47,8 @@ struct objagg { struct rhashtable_params ht_params; struct list_head obj_list; unsigned int obj_count; + struct ida root_ida; + struct objagg_hints *hints; }; struct objagg_obj { @@ -30,6 +61,7 @@ struct objagg_obj { void *delta_priv; /* user delta private */ void *root_priv; /* user root private */ }; + unsigned int root_id; unsigned int refcount; /* counts number of users of this object * including nested objects */ @@ -130,7 +162,8 @@ static struct objagg_obj *objagg_obj_lookup(struct objagg *objagg, void *obj) static int objagg_obj_parent_assign(struct objagg *objagg, struct objagg_obj *objagg_obj, - struct objagg_obj *parent) + struct objagg_obj *parent, + bool take_parent_ref) { void *delta_priv; @@ -144,7 +177,8 @@ static int objagg_obj_parent_assign(struct objagg *objagg, */ objagg_obj->parent = parent; objagg_obj->delta_priv = delta_priv; - objagg_obj_ref_inc(objagg_obj->parent); + if (take_parent_ref) + objagg_obj_ref_inc(objagg_obj->parent); trace_objagg_obj_parent_assign(objagg, objagg_obj, parent, parent->refcount); @@ -164,7 +198,7 @@ static int objagg_obj_parent_lookup_assign(struct objagg *objagg, if (!objagg_obj_is_root(objagg_obj_cur)) continue; err = objagg_obj_parent_assign(objagg, objagg_obj, - objagg_obj_cur); + objagg_obj_cur, true); if (!err) return 0; } @@ -184,16 +218,68 @@ static void objagg_obj_parent_unassign(struct objagg *objagg, __objagg_obj_put(objagg, objagg_obj->parent); } +static int objagg_obj_root_id_alloc(struct objagg *objagg, + struct objagg_obj *objagg_obj, + struct objagg_hints_node *hnode) +{ + unsigned int min, max; + int root_id; + + /* In case there are no hints available, the root id is invalid. */ + if (!objagg->hints) { + objagg_obj->root_id = OBJAGG_OBJ_ROOT_ID_INVALID; + return 0; + } + + if (hnode) { + min = hnode->root_id; + max = hnode->root_id; + } else { + /* For objects with no hint, start after the last + * hinted root_id. + */ + min = objagg->hints->root_count; + max = ~0; + } + + root_id = ida_alloc_range(&objagg->root_ida, min, max, GFP_KERNEL); + + if (root_id < 0) + return root_id; + objagg_obj->root_id = root_id; + return 0; +} + +static void objagg_obj_root_id_free(struct objagg *objagg, + struct objagg_obj *objagg_obj) +{ + if (!objagg->hints) + return; + ida_free(&objagg->root_ida, objagg_obj->root_id); +} + static int objagg_obj_root_create(struct objagg *objagg, - struct objagg_obj *objagg_obj) + struct objagg_obj *objagg_obj, + struct objagg_hints_node *hnode) { - objagg_obj->root_priv = objagg->ops->root_create(objagg->priv, - objagg_obj->obj); - if (IS_ERR(objagg_obj->root_priv)) - return PTR_ERR(objagg_obj->root_priv); + int err; + err = objagg_obj_root_id_alloc(objagg, objagg_obj, hnode); + if (err) + return err; + objagg_obj->root_priv = objagg->ops->root_create(objagg->priv, + objagg_obj->obj, + objagg_obj->root_id); + if (IS_ERR(objagg_obj->root_priv)) { + err = PTR_ERR(objagg_obj->root_priv); + goto err_root_create; + } trace_objagg_obj_root_create(objagg, objagg_obj); return 0; + +err_root_create: + objagg_obj_root_id_free(objagg, objagg_obj); + return err; } static void objagg_obj_root_destroy(struct objagg *objagg, @@ -201,19 +287,69 @@ static void objagg_obj_root_destroy(struct objagg *objagg, { trace_objagg_obj_root_destroy(objagg, objagg_obj); objagg->ops->root_destroy(objagg->priv, objagg_obj->root_priv); + objagg_obj_root_id_free(objagg, objagg_obj); +} + +static struct objagg_obj *__objagg_obj_get(struct objagg *objagg, void *obj); + +static int objagg_obj_init_with_hints(struct objagg *objagg, + struct objagg_obj *objagg_obj, + bool *hint_found) +{ + struct objagg_hints_node *hnode; + struct objagg_obj *parent; + int err; + + hnode = objagg_hints_lookup(objagg->hints, objagg_obj->obj); + if (!hnode) { + *hint_found = false; + return 0; + } + *hint_found = true; + + if (!hnode->parent) + return objagg_obj_root_create(objagg, objagg_obj, hnode); + + parent = __objagg_obj_get(objagg, hnode->parent->obj); + if (IS_ERR(parent)) + return PTR_ERR(parent); + + err = objagg_obj_parent_assign(objagg, objagg_obj, parent, false); + if (err) { + *hint_found = false; + err = 0; + goto err_parent_assign; + } + + return 0; + +err_parent_assign: + objagg_obj_put(objagg, parent); + return err; } static int objagg_obj_init(struct objagg *objagg, struct objagg_obj *objagg_obj) { + bool hint_found; int err; + /* First, try to use hints if they are available and + * if they provide result. + */ + err = objagg_obj_init_with_hints(objagg, objagg_obj, &hint_found); + if (err) + return err; + + if (hint_found) + return 0; + /* Try to find if the object can be aggregated under an existing one. */ err = objagg_obj_parent_lookup_assign(objagg, objagg_obj); if (!err) return 0; /* If aggregation is not possible, make the object a root. */ - return objagg_obj_root_create(objagg, objagg_obj); + return objagg_obj_root_create(objagg, objagg_obj, NULL); } static void objagg_obj_fini(struct objagg *objagg, @@ -349,8 +485,9 @@ EXPORT_SYMBOL(objagg_obj_put); /** * objagg_create - creates a new objagg instance - * @ops: user-specific callbacks - * @priv: pointer to a private data passed to the ops + * @ops: user-specific callbacks + * @objagg_hints: hints, can be NULL + * @priv: pointer to a private data passed to the ops * * Note: all locking must be provided by the caller. * @@ -374,18 +511,25 @@ EXPORT_SYMBOL(objagg_obj_put); * Returns a pointer to newly created objagg instance in case of success, * otherwise it returns pointer error using ERR_PTR macro. */ -struct objagg *objagg_create(const struct objagg_ops *ops, void *priv) +struct objagg *objagg_create(const struct objagg_ops *ops, + struct objagg_hints *objagg_hints, void *priv) { struct objagg *objagg; int err; if (WARN_ON(!ops || !ops->root_create || !ops->root_destroy || - !ops->delta_create || !ops->delta_destroy)) + !ops->delta_check || !ops->delta_create || + !ops->delta_destroy)) return ERR_PTR(-EINVAL); + objagg = kzalloc(sizeof(*objagg), GFP_KERNEL); if (!objagg) return ERR_PTR(-ENOMEM); objagg->ops = ops; + if (objagg_hints) { + objagg->hints = objagg_hints; + objagg_hints->refcount++; + } objagg->priv = priv; INIT_LIST_HEAD(&objagg->obj_list); @@ -397,6 +541,8 @@ struct objagg *objagg_create(const struct objagg_ops *ops, void *priv) if (err) goto err_rhashtable_init; + ida_init(&objagg->root_ida); + trace_objagg_create(objagg); return objagg; @@ -415,8 +561,11 @@ EXPORT_SYMBOL(objagg_create); void objagg_destroy(struct objagg *objagg) { trace_objagg_destroy(objagg); + ida_destroy(&objagg->root_ida); WARN_ON(!list_empty(&objagg->obj_list)); rhashtable_destroy(&objagg->obj_ht); + if (objagg->hints) + objagg_hints_put(objagg->hints); kfree(objagg); } EXPORT_SYMBOL(objagg_destroy); @@ -496,6 +645,404 @@ void objagg_stats_put(const struct objagg_stats *objagg_stats) } EXPORT_SYMBOL(objagg_stats_put); +static struct objagg_hints_node * +objagg_hints_node_create(struct objagg_hints *objagg_hints, + struct objagg_obj *objagg_obj, size_t obj_size, + struct objagg_hints_node *parent_hnode) +{ + unsigned int user_count = objagg_obj->stats.user_count; + struct objagg_hints_node *hnode; + int err; + + hnode = kzalloc(sizeof(*hnode) + obj_size, GFP_KERNEL); + if (!hnode) + return ERR_PTR(-ENOMEM); + memcpy(hnode->obj, &objagg_obj->obj, obj_size); + hnode->stats_info.stats.user_count = user_count; + hnode->stats_info.stats.delta_user_count = user_count; + if (parent_hnode) { + parent_hnode->stats_info.stats.delta_user_count += user_count; + } else { + hnode->root_id = objagg_hints->root_count++; + hnode->stats_info.is_root = true; + } + hnode->stats_info.objagg_obj = objagg_obj; + + err = rhashtable_insert_fast(&objagg_hints->node_ht, &hnode->ht_node, + objagg_hints->ht_params); + if (err) + goto err_ht_insert; + + list_add(&hnode->list, &objagg_hints->node_list); + hnode->parent = parent_hnode; + objagg_hints->node_count++; + + return hnode; + +err_ht_insert: + kfree(hnode); + return ERR_PTR(err); +} + +static void objagg_hints_flush(struct objagg_hints *objagg_hints) +{ + struct objagg_hints_node *hnode, *tmp; + + list_for_each_entry_safe(hnode, tmp, &objagg_hints->node_list, list) { + list_del(&hnode->list); + rhashtable_remove_fast(&objagg_hints->node_ht, &hnode->ht_node, + objagg_hints->ht_params); + kfree(hnode); + } +} + +struct objagg_tmp_node { + struct objagg_obj *objagg_obj; + bool crossed_out; +}; + +struct objagg_tmp_graph { + struct objagg_tmp_node *nodes; + unsigned long nodes_count; + unsigned long *edges; +}; + +static int objagg_tmp_graph_edge_index(struct objagg_tmp_graph *graph, + int parent_index, int index) +{ + return index * graph->nodes_count + parent_index; +} + +static void objagg_tmp_graph_edge_set(struct objagg_tmp_graph *graph, + int parent_index, int index) +{ + int edge_index = objagg_tmp_graph_edge_index(graph, index, + parent_index); + + __set_bit(edge_index, graph->edges); +} + +static bool objagg_tmp_graph_is_edge(struct objagg_tmp_graph *graph, + int parent_index, int index) +{ + int edge_index = objagg_tmp_graph_edge_index(graph, index, + parent_index); + + return test_bit(edge_index, graph->edges); +} + +static unsigned int objagg_tmp_graph_node_weight(struct objagg_tmp_graph *graph, + unsigned int index) +{ + struct objagg_tmp_node *node = &graph->nodes[index]; + unsigned int weight = node->objagg_obj->stats.user_count; + int j; + + /* Node weight is sum of node users and all other nodes users + * that this node can represent with delta. + */ + + if (node->crossed_out) + return 0; + for (j = 0; j < graph->nodes_count; j++) { + if (!objagg_tmp_graph_is_edge(graph, index, j)) + continue; + node = &graph->nodes[j]; + if (node->crossed_out) + continue; + weight += node->objagg_obj->stats.user_count; + } + return weight; +} + +static int objagg_tmp_graph_node_max_weight(struct objagg_tmp_graph *graph) +{ + unsigned int max_weight = 0; + unsigned int weight; + int max_index = -1; + int i; + + for (i = 0; i < graph->nodes_count; i++) { + weight = objagg_tmp_graph_node_weight(graph, i); + if (weight > max_weight) { + max_weight = weight; + max_index = i; + } + } + return max_index; +} + +static struct objagg_tmp_graph *objagg_tmp_graph_create(struct objagg *objagg) +{ + unsigned int nodes_count = objagg->obj_count; + struct objagg_tmp_graph *graph; + struct objagg_tmp_node *node; + struct objagg_tmp_node *pnode; + struct objagg_obj *objagg_obj; + size_t alloc_size; + int i, j; + + graph = kzalloc(sizeof(*graph), GFP_KERNEL); + if (!graph) + return NULL; + + graph->nodes = kcalloc(nodes_count, sizeof(*graph->nodes), GFP_KERNEL); + if (!graph->nodes) + goto err_nodes_alloc; + graph->nodes_count = nodes_count; + + alloc_size = BITS_TO_LONGS(nodes_count * nodes_count) * + sizeof(unsigned long); + graph->edges = kzalloc(alloc_size, GFP_KERNEL); + if (!graph->edges) + goto err_edges_alloc; + + i = 0; + list_for_each_entry(objagg_obj, &objagg->obj_list, list) { + node = &graph->nodes[i++]; + node->objagg_obj = objagg_obj; + } + + /* Assemble a temporary graph. Insert edge X->Y in case Y can be + * in delta of X. + */ + for (i = 0; i < nodes_count; i++) { + for (j = 0; j < nodes_count; j++) { + if (i == j) + continue; + pnode = &graph->nodes[i]; + node = &graph->nodes[j]; + if (objagg->ops->delta_check(objagg->priv, + pnode->objagg_obj->obj, + node->objagg_obj->obj)) { + objagg_tmp_graph_edge_set(graph, i, j); + + } + } + } + return graph; + +err_edges_alloc: + kfree(graph->nodes); +err_nodes_alloc: + kfree(graph); + return NULL; +} + +static void objagg_tmp_graph_destroy(struct objagg_tmp_graph *graph) +{ + kfree(graph->edges); + kfree(graph->nodes); + kfree(graph); +} + +static int +objagg_opt_simple_greedy_fillup_hints(struct objagg_hints *objagg_hints, + struct objagg *objagg) +{ + struct objagg_hints_node *hnode, *parent_hnode; + struct objagg_tmp_graph *graph; + struct objagg_tmp_node *node; + int index; + int j; + int err; + + graph = objagg_tmp_graph_create(objagg); + if (!graph) + return -ENOMEM; + + /* Find the nodes from the ones that can accommodate most users + * and cross them out of the graph. Save them to the hint list. + */ + while ((index = objagg_tmp_graph_node_max_weight(graph)) != -1) { + node = &graph->nodes[index]; + node->crossed_out = true; + hnode = objagg_hints_node_create(objagg_hints, + node->objagg_obj, + objagg->ops->obj_size, + NULL); + if (IS_ERR(hnode)) { + err = PTR_ERR(hnode); + goto out; + } + parent_hnode = hnode; + for (j = 0; j < graph->nodes_count; j++) { + if (!objagg_tmp_graph_is_edge(graph, index, j)) + continue; + node = &graph->nodes[j]; + if (node->crossed_out) + continue; + node->crossed_out = true; + hnode = objagg_hints_node_create(objagg_hints, + node->objagg_obj, + objagg->ops->obj_size, + parent_hnode); + if (IS_ERR(hnode)) { + err = PTR_ERR(hnode); + goto out; + } + } + } + + err = 0; +out: + objagg_tmp_graph_destroy(graph); + return err; +} + +struct objagg_opt_algo { + int (*fillup_hints)(struct objagg_hints *objagg_hints, + struct objagg *objagg); +}; + +static const struct objagg_opt_algo objagg_opt_simple_greedy = { + .fillup_hints = objagg_opt_simple_greedy_fillup_hints, +}; + + +static const struct objagg_opt_algo *objagg_opt_algos[] = { + [OBJAGG_OPT_ALGO_SIMPLE_GREEDY] = &objagg_opt_simple_greedy, +}; + +static int objagg_hints_obj_cmp(struct rhashtable_compare_arg *arg, + const void *obj) +{ + struct rhashtable *ht = arg->ht; + struct objagg_hints *objagg_hints = + container_of(ht, struct objagg_hints, node_ht); + const struct objagg_ops *ops = objagg_hints->ops; + const char *ptr = obj; + + ptr += ht->p.key_offset; + return ops->hints_obj_cmp ? ops->hints_obj_cmp(ptr, arg->key) : + memcmp(ptr, arg->key, ht->p.key_len); +} + +/** + * objagg_hints_get - obtains hints instance + * @objagg: objagg instance + * @opt_algo_type: type of hints finding algorithm + * + * Note: all locking must be provided by the caller. + * + * According to the algo type, the existing objects of objagg instance + * are going to be went-through to assemble an optimal tree. We call this + * tree hints. These hints can be later on used for creation of + * a new objagg instance. There, the future object creations are going + * to be consulted with these hints in order to find out, where exactly + * the new object should be put as a root or delta. + * + * Returns a pointer to hints instance in case of success, + * otherwise it returns pointer error using ERR_PTR macro. + */ +struct objagg_hints *objagg_hints_get(struct objagg *objagg, + enum objagg_opt_algo_type opt_algo_type) +{ + const struct objagg_opt_algo *algo = objagg_opt_algos[opt_algo_type]; + struct objagg_hints *objagg_hints; + int err; + + objagg_hints = kzalloc(sizeof(*objagg_hints), GFP_KERNEL); + if (!objagg_hints) + return ERR_PTR(-ENOMEM); + + objagg_hints->ops = objagg->ops; + objagg_hints->refcount = 1; + + INIT_LIST_HEAD(&objagg_hints->node_list); + + objagg_hints->ht_params.key_len = objagg->ops->obj_size; + objagg_hints->ht_params.key_offset = + offsetof(struct objagg_hints_node, obj); + objagg_hints->ht_params.head_offset = + offsetof(struct objagg_hints_node, ht_node); + objagg_hints->ht_params.obj_cmpfn = objagg_hints_obj_cmp; + + err = rhashtable_init(&objagg_hints->node_ht, &objagg_hints->ht_params); + if (err) + goto err_rhashtable_init; + + err = algo->fillup_hints(objagg_hints, objagg); + if (err) + goto err_fillup_hints; + + if (WARN_ON(objagg_hints->node_count != objagg->obj_count)) + goto err_node_count_check; + + return objagg_hints; + +err_node_count_check: +err_fillup_hints: + objagg_hints_flush(objagg_hints); + rhashtable_destroy(&objagg_hints->node_ht); +err_rhashtable_init: + kfree(objagg_hints); + return ERR_PTR(err); +} +EXPORT_SYMBOL(objagg_hints_get); + +/** + * objagg_hints_put - puts hints instance + * @objagg_hints: objagg hints instance + * + * Note: all locking must be provided by the caller. + */ +void objagg_hints_put(struct objagg_hints *objagg_hints) +{ + if (--objagg_hints->refcount) + return; + objagg_hints_flush(objagg_hints); + rhashtable_destroy(&objagg_hints->node_ht); + kfree(objagg_hints); +} +EXPORT_SYMBOL(objagg_hints_put); + +/** + * objagg_hints_stats_get - obtains stats of the hints instance + * @objagg_hints: hints instance + * + * Note: all locking must be provided by the caller. + * + * The returned structure contains statistics of all objects + * currently in use, ordered by following rules: + * 1) Root objects are always on lower indexes than the rest. + * 2) Objects with higher delta user count are always on lower + * indexes. + * 3) In case multiple objects have the same delta user count, + * the objects are ordered by user count. + * + * Returns a pointer to stats instance in case of success, + * otherwise it returns pointer error using ERR_PTR macro. + */ +const struct objagg_stats * +objagg_hints_stats_get(struct objagg_hints *objagg_hints) +{ + struct objagg_stats *objagg_stats; + struct objagg_hints_node *hnode; + int i; + + objagg_stats = kzalloc(struct_size(objagg_stats, stats_info, + objagg_hints->node_count), + GFP_KERNEL); + if (!objagg_stats) + return ERR_PTR(-ENOMEM); + + i = 0; + list_for_each_entry(hnode, &objagg_hints->node_list, list) { + memcpy(&objagg_stats->stats_info[i], &hnode->stats_info, + sizeof(objagg_stats->stats_info[0])); + i++; + } + objagg_stats->stats_info_count = i; + + sort(objagg_stats->stats_info, objagg_stats->stats_info_count, + sizeof(struct objagg_obj_stats_info), + objagg_stats_info_sort_cmp_func, NULL); + + return objagg_stats; +} +EXPORT_SYMBOL(objagg_hints_stats_get); + MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Jiri Pirko "); MODULE_DESCRIPTION("Object aggregation manager"); diff --git a/lib/test_objagg.c b/lib/test_objagg.c index ab57144bb0cd..3744573b6365 100644 --- a/lib/test_objagg.c +++ b/lib/test_objagg.c @@ -87,6 +87,15 @@ static void world_obj_put(struct world *world, struct objagg *objagg, #define MAX_KEY_ID_DIFF 5 +static bool delta_check(void *priv, const void *parent_obj, const void *obj) +{ + const struct tokey *parent_key = parent_obj; + const struct tokey *key = obj; + int diff = key->id - parent_key->id; + + return diff >= 0 && diff <= MAX_KEY_ID_DIFF; +} + static void *delta_create(void *priv, void *parent_obj, void *obj) { struct tokey *parent_key = parent_obj; @@ -95,7 +104,7 @@ static void *delta_create(void *priv, void *parent_obj, void *obj) int diff = key->id - parent_key->id; struct delta *delta; - if (diff < 0 || diff > MAX_KEY_ID_DIFF) + if (!delta_check(priv, parent_obj, obj)) return ERR_PTR(-EINVAL); delta = kzalloc(sizeof(*delta), GFP_KERNEL); @@ -115,7 +124,7 @@ static void delta_destroy(void *priv, void *delta_priv) kfree(delta); } -static void *root_create(void *priv, void *obj) +static void *root_create(void *priv, void *obj, unsigned int id) { struct world *world = priv; struct tokey *key = obj; @@ -268,6 +277,12 @@ stats_put: return err; } +static bool delta_check_dummy(void *priv, const void *parent_obj, + const void *obj) +{ + return false; +} + static void *delta_create_dummy(void *priv, void *parent_obj, void *obj) { return ERR_PTR(-EOPNOTSUPP); @@ -279,6 +294,7 @@ static void delta_destroy_dummy(void *priv, void *delta_priv) static const struct objagg_ops nodelta_ops = { .obj_size = sizeof(struct tokey), + .delta_check = delta_check_dummy, .delta_create = delta_create_dummy, .delta_destroy = delta_destroy_dummy, .root_create = root_create, @@ -292,7 +308,7 @@ static int test_nodelta(void) int i; int err; - objagg = objagg_create(&nodelta_ops, &world); + objagg = objagg_create(&nodelta_ops, NULL, &world); if (IS_ERR(objagg)) return PTR_ERR(objagg); @@ -357,6 +373,7 @@ err_stats_second_zero: static const struct objagg_ops delta_ops = { .obj_size = sizeof(struct tokey), + .delta_check = delta_check, .delta_create = delta_create, .delta_destroy = delta_destroy, .root_create = root_create, @@ -793,7 +810,7 @@ static int test_delta(void) int i; int err; - objagg = objagg_create(&delta_ops, &world); + objagg = objagg_create(&delta_ops, NULL, &world); if (IS_ERR(objagg)) return PTR_ERR(objagg); @@ -815,6 +832,170 @@ err_do_action_item: return err; } +struct hints_case { + const unsigned int *key_ids; + size_t key_ids_count; + struct expect_stats expect_stats; + struct expect_stats expect_stats_hints; +}; + +static const unsigned int hints_case_key_ids[] = { + 1, 7, 3, 5, 3, 1, 30, 8, 8, 5, 6, 8, +}; + +static const struct hints_case hints_case = { + .key_ids = hints_case_key_ids, + .key_ids_count = ARRAY_SIZE(hints_case_key_ids), + .expect_stats = + EXPECT_STATS(7, ROOT(1, 2, 7), ROOT(7, 1, 4), ROOT(30, 1, 1), + DELTA(8, 3), DELTA(3, 2), + DELTA(5, 2), DELTA(6, 1)), + .expect_stats_hints = + EXPECT_STATS(7, ROOT(3, 2, 9), ROOT(1, 2, 2), ROOT(30, 1, 1), + DELTA(8, 3), DELTA(5, 2), + DELTA(6, 1), DELTA(7, 1)), +}; + +static void __pr_debug_stats(const struct objagg_stats *stats) +{ + int i; + + for (i = 0; i < stats->stats_info_count; i++) + pr_debug("Stat index %d key %u: u %d, d %d, %s\n", i, + obj_to_key_id(stats->stats_info[i].objagg_obj), + stats->stats_info[i].stats.user_count, + stats->stats_info[i].stats.delta_user_count, + stats->stats_info[i].is_root ? "root" : "noroot"); +} + +static void pr_debug_stats(struct objagg *objagg) +{ + const struct objagg_stats *stats; + + stats = objagg_stats_get(objagg); + if (IS_ERR(stats)) + return; + __pr_debug_stats(stats); + objagg_stats_put(stats); +} + +static void pr_debug_hints_stats(struct objagg_hints *objagg_hints) +{ + const struct objagg_stats *stats; + + stats = objagg_hints_stats_get(objagg_hints); + if (IS_ERR(stats)) + return; + __pr_debug_stats(stats); + objagg_stats_put(stats); +} + +static int check_expect_hints_stats(struct objagg_hints *objagg_hints, + const struct expect_stats *expect_stats, + const char **errmsg) +{ + const struct objagg_stats *stats; + int err; + + stats = objagg_hints_stats_get(objagg_hints); + if (IS_ERR(stats)) + return PTR_ERR(stats); + err = __check_expect_stats(stats, expect_stats, errmsg); + objagg_stats_put(stats); + return err; +} + +static int test_hints_case(const struct hints_case *hints_case) +{ + struct objagg_obj *objagg_obj; + struct objagg_hints *hints; + struct world world2 = {}; + struct world world = {}; + struct objagg *objagg2; + struct objagg *objagg; + const char *errmsg; + int i; + int err; + + objagg = objagg_create(&delta_ops, NULL, &world); + if (IS_ERR(objagg)) + return PTR_ERR(objagg); + + for (i = 0; i < hints_case->key_ids_count; i++) { + objagg_obj = world_obj_get(&world, objagg, + hints_case->key_ids[i]); + if (IS_ERR(objagg_obj)) { + err = PTR_ERR(objagg_obj); + goto err_world_obj_get; + } + } + + pr_debug_stats(objagg); + err = check_expect_stats(objagg, &hints_case->expect_stats, &errmsg); + if (err) { + pr_err("Stats: %s\n", errmsg); + goto err_check_expect_stats; + } + + hints = objagg_hints_get(objagg, OBJAGG_OPT_ALGO_SIMPLE_GREEDY); + if (IS_ERR(hints)) { + err = PTR_ERR(hints); + goto err_hints_get; + } + + pr_debug_hints_stats(hints); + err = check_expect_hints_stats(hints, &hints_case->expect_stats_hints, + &errmsg); + if (err) { + pr_err("Hints stats: %s\n", errmsg); + goto err_check_expect_hints_stats; + } + + objagg2 = objagg_create(&delta_ops, hints, &world2); + if (IS_ERR(objagg)) + return PTR_ERR(objagg); + + for (i = 0; i < hints_case->key_ids_count; i++) { + objagg_obj = world_obj_get(&world2, objagg2, + hints_case->key_ids[i]); + if (IS_ERR(objagg_obj)) { + err = PTR_ERR(objagg_obj); + goto err_world2_obj_get; + } + } + + pr_debug_stats(objagg2); + err = check_expect_stats(objagg2, &hints_case->expect_stats_hints, + &errmsg); + if (err) { + pr_err("Stats2: %s\n", errmsg); + goto err_check_expect_stats2; + } + + err = 0; + +err_check_expect_stats2: +err_world2_obj_get: + for (i--; i >= 0; i--) + world_obj_put(&world2, objagg, hints_case->key_ids[i]); + objagg_hints_put(hints); + objagg_destroy(objagg2); + i = hints_case->key_ids_count; +err_check_expect_hints_stats: +err_hints_get: +err_check_expect_stats: +err_world_obj_get: + for (i--; i >= 0; i--) + world_obj_put(&world, objagg, hints_case->key_ids[i]); + + objagg_destroy(objagg); + return err; +} +static int test_hints(void) +{ + return test_hints_case(&hints_case); +} + static int __init test_objagg_init(void) { int err; @@ -822,7 +1003,10 @@ static int __init test_objagg_init(void) err = test_nodelta(); if (err) return err; - return test_delta(); + err = test_delta(); + if (err) + return err; + return test_hints(); } static void __exit test_objagg_exit(void) -- cgit v1.2.3 From 0f54236da0c2b6664c4d08407fe8c2b7ad17d955 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:48 +0000 Subject: mlxsw: spectrum_acl: Split region struct into region and vregion Do the split of region struct so the new region struct is related to the actual HW region, whereas vregion struct is a SW abstration of that. This split prepares possibility for vregion to hold 2 HW regions which is needed for region ERP rehash flow. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 299 ++++++++++++--------- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 5 +- 2 files changed, 180 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 11456e1f236f..092a461cd5fb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -153,7 +153,7 @@ struct mlxsw_sp_acl_tcam_pattern { struct mlxsw_sp_acl_tcam_group { struct mlxsw_sp_acl_tcam *tcam; u16 id; - struct list_head region_list; + struct list_head vregion_list; unsigned int region_count; struct rhashtable chunk_ht; struct mlxsw_sp_acl_tcam_group_ops *ops; @@ -163,12 +163,20 @@ struct mlxsw_sp_acl_tcam_group { struct mlxsw_afk_element_usage tmplt_elusage; }; +struct mlxsw_sp_acl_tcam_vregion { + struct mlxsw_sp_acl_tcam_region *region; + struct list_head list; /* Member of a TCAM group */ + struct list_head chunk_list; /* List of chunks under this vregion */ + struct mlxsw_sp_acl_tcam_group *group; + struct mlxsw_afk_key_info *key_info; +}; + struct mlxsw_sp_acl_tcam_chunk { - struct list_head list; /* Member of a TCAM region */ + struct list_head list; /* Member of a TCAM vregion */ struct rhash_head ht_node; /* Member of a chunk HT */ - unsigned int priority; /* Priority within the region and group */ + unsigned int priority; /* Priority within the vregion and group */ struct mlxsw_sp_acl_tcam_group *group; - struct mlxsw_sp_acl_tcam_region *region; + struct mlxsw_sp_acl_tcam_vregion *vregion; unsigned int ref_count; unsigned long priv[0]; /* priv has to be always the last item */ @@ -190,13 +198,14 @@ static const struct rhashtable_params mlxsw_sp_acl_tcam_chunk_ht_params = { static int mlxsw_sp_acl_tcam_group_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_group *group) { - struct mlxsw_sp_acl_tcam_region *region; + struct mlxsw_sp_acl_tcam_vregion *vregion; char pagt_pl[MLXSW_REG_PAGT_LEN]; int acl_index = 0; mlxsw_reg_pagt_pack(pagt_pl, group->id); - list_for_each_entry(region, &group->region_list, list) - mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++, region->id); + list_for_each_entry(vregion, &group->vregion_list, list) + mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++, + vregion->region->id); mlxsw_reg_pagt_size_set(pagt_pl, acl_index); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pagt), pagt_pl); } @@ -219,7 +228,7 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp, memcpy(&group->tmplt_elusage, tmplt_elusage, sizeof(group->tmplt_elusage)); } - INIT_LIST_HEAD(&group->region_list); + INIT_LIST_HEAD(&group->vregion_list); err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id); if (err) return err; @@ -243,7 +252,7 @@ static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp *mlxsw_sp, rhashtable_destroy(&group->chunk_ht); mlxsw_sp_acl_tcam_group_id_put(tcam, group->id); - WARN_ON(!list_empty(&group->region_list)); + WARN_ON(!list_empty(&group->vregion_list)); } static int @@ -283,140 +292,150 @@ mlxsw_sp_acl_tcam_group_id(struct mlxsw_sp_acl_tcam_group *group) } static unsigned int -mlxsw_sp_acl_tcam_region_prio(struct mlxsw_sp_acl_tcam_region *region) +mlxsw_sp_acl_tcam_vregion_prio(struct mlxsw_sp_acl_tcam_vregion *vregion) { struct mlxsw_sp_acl_tcam_chunk *chunk; - if (list_empty(®ion->chunk_list)) + if (list_empty(&vregion->chunk_list)) return 0; - /* As a priority of a region, return priority of the first chunk */ - chunk = list_first_entry(®ion->chunk_list, typeof(*chunk), list); + /* As a priority of a vregion, return priority of the first chunk */ + chunk = list_first_entry(&vregion->chunk_list, + typeof(*chunk), list); return chunk->priority; } static unsigned int -mlxsw_sp_acl_tcam_region_max_prio(struct mlxsw_sp_acl_tcam_region *region) +mlxsw_sp_acl_tcam_vregion_max_prio(struct mlxsw_sp_acl_tcam_vregion *vregion) { struct mlxsw_sp_acl_tcam_chunk *chunk; - if (list_empty(®ion->chunk_list)) + if (list_empty(&vregion->chunk_list)) return 0; - chunk = list_last_entry(®ion->chunk_list, typeof(*chunk), list); + chunk = list_last_entry(&vregion->chunk_list, + typeof(*chunk), list); return chunk->priority; } -static void -mlxsw_sp_acl_tcam_group_list_add(struct mlxsw_sp_acl_tcam_group *group, - struct mlxsw_sp_acl_tcam_region *region) +static int +mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_region *region) { - struct mlxsw_sp_acl_tcam_region *region2; - struct list_head *pos; + struct mlxsw_sp_acl_tcam_group *group = region->vregion->group; + int err; + + if (group->region_count == group->tcam->max_group_size) + return -ENOBUFS; + + err = mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group); + if (err) + return err; - /* Position the region inside the list according to priority */ - list_for_each(pos, &group->region_list) { - region2 = list_entry(pos, typeof(*region2), list); - if (mlxsw_sp_acl_tcam_region_prio(region2) > - mlxsw_sp_acl_tcam_region_prio(region)) - break; - } - list_add_tail(®ion->list, pos); group->region_count++; + return 0; } static void -mlxsw_sp_acl_tcam_group_list_del(struct mlxsw_sp_acl_tcam_group *group, - struct mlxsw_sp_acl_tcam_region *region) +mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_region *region) { + struct mlxsw_sp_acl_tcam_group *group = region->vregion->group; + group->region_count--; - list_del(®ion->list); + mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group); } static int -mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, - struct mlxsw_sp_acl_tcam_region *region) +mlxsw_sp_acl_tcam_group_vregion_attach(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_group *group, + struct mlxsw_sp_acl_tcam_vregion *vregion) { + struct mlxsw_sp_acl_tcam_vregion *vregion2; + struct list_head *pos; int err; - if (group->region_count == group->tcam->max_group_size) - return -ENOBUFS; - - mlxsw_sp_acl_tcam_group_list_add(group, region); + /* Position the vregion inside the list according to priority */ + list_for_each(pos, &group->vregion_list) { + vregion2 = list_entry(pos, typeof(*vregion2), list); + if (mlxsw_sp_acl_tcam_vregion_prio(vregion2) > + mlxsw_sp_acl_tcam_vregion_prio(vregion)) + break; + } + list_add_tail(&vregion->list, pos); + vregion->group = group; - err = mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group); + err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, vregion->region); if (err) - goto err_group_update; - region->group = group; + goto err_region_attach; return 0; -err_group_update: - mlxsw_sp_acl_tcam_group_list_del(group, region); - mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group); +err_region_attach: + list_del(&vregion->list); return err; } static void -mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_region *region) +mlxsw_sp_acl_tcam_group_vregion_detach(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion) { - struct mlxsw_sp_acl_tcam_group *group = region->group; - - mlxsw_sp_acl_tcam_group_list_del(group, region); - mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group); + list_del(&vregion->list); + mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, vregion->region); } -static struct mlxsw_sp_acl_tcam_region * -mlxsw_sp_acl_tcam_group_region_find(struct mlxsw_sp_acl_tcam_group *group, - unsigned int priority, - struct mlxsw_afk_element_usage *elusage, - bool *p_need_split) +static struct mlxsw_sp_acl_tcam_vregion * +mlxsw_sp_acl_tcam_group_vregion_find(struct mlxsw_sp_acl_tcam_group *group, + unsigned int priority, + struct mlxsw_afk_element_usage *elusage, + bool *p_need_split) { - struct mlxsw_sp_acl_tcam_region *region, *region2; + struct mlxsw_sp_acl_tcam_vregion *vregion, *vregion2; struct list_head *pos; bool issubset; - list_for_each(pos, &group->region_list) { - region = list_entry(pos, typeof(*region), list); + list_for_each(pos, &group->vregion_list) { + vregion = list_entry(pos, typeof(*vregion), list); /* First, check if the requested priority does not rather belong - * under some of the next regions. + * under some of the next vregions. */ - if (pos->next != &group->region_list) { /* not last */ - region2 = list_entry(pos->next, typeof(*region2), list); - if (priority >= mlxsw_sp_acl_tcam_region_prio(region2)) + if (pos->next != &group->vregion_list) { /* not last */ + vregion2 = list_entry(pos->next, typeof(*vregion2), + list); + if (priority >= + mlxsw_sp_acl_tcam_vregion_prio(vregion2)) continue; } - issubset = mlxsw_afk_key_info_subset(region->key_info, elusage); + issubset = mlxsw_afk_key_info_subset(vregion->key_info, + elusage); /* If requested element usage would not fit and the priority - * is lower than the currently inspected region we cannot - * use this region, so return NULL to indicate new region has + * is lower than the currently inspected vregion we cannot + * use this region, so return NULL to indicate new vregion has * to be created. */ if (!issubset && - priority < mlxsw_sp_acl_tcam_region_prio(region)) + priority < mlxsw_sp_acl_tcam_vregion_prio(vregion)) return NULL; /* If requested element usage would not fit and the priority - * is higher than the currently inspected region we cannot - * use this region. There is still some hope that the next - * region would be the fit. So let it be processed and + * is higher than the currently inspected vregion we cannot + * use this vregion. There is still some hope that the next + * vregion would be the fit. So let it be processed and * eventually break at the check right above this. */ if (!issubset && - priority > mlxsw_sp_acl_tcam_region_max_prio(region)) + priority > mlxsw_sp_acl_tcam_vregion_max_prio(vregion)) continue; - /* Indicate if the region needs to be split in order to add + /* Indicate if the vregion needs to be split in order to add * the requested priority. Split is needed when requested - * element usage won't fit into the found region. + * element usage won't fit into the found vregion. */ *p_need_split = !issubset; - return region; + return vregion; } - return NULL; /* New region has to be created. */ + return NULL; /* New vregion has to be created. */ } static void @@ -511,24 +530,18 @@ mlxsw_sp_acl_tcam_region_disable(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_acl_tcam_region * mlxsw_sp_acl_tcam_region_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam, - struct mlxsw_afk_element_usage *elusage) + struct mlxsw_sp_acl_tcam_vregion *vregion) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); struct mlxsw_sp_acl_tcam_region *region; int err; region = kzalloc(sizeof(*region) + ops->region_priv_size, GFP_KERNEL); if (!region) return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(®ion->chunk_list); region->mlxsw_sp = mlxsw_sp; - - region->key_info = mlxsw_afk_key_info_get(afk, elusage); - if (IS_ERR(region->key_info)) { - err = PTR_ERR(region->key_info); - goto err_key_info_get; - } + region->vregion = vregion; + region->key_info = vregion->key_info; err = mlxsw_sp_acl_tcam_region_id_get(tcam, ®ion->id); if (err) @@ -561,8 +574,6 @@ err_tcam_region_alloc: err_tcam_region_associate: mlxsw_sp_acl_tcam_region_id_put(tcam, region->id); err_region_id_get: - mlxsw_afk_key_info_put(region->key_info); -err_key_info_get: kfree(region); return ERR_PTR(err); } @@ -576,11 +587,56 @@ mlxsw_sp_acl_tcam_region_destroy(struct mlxsw_sp *mlxsw_sp, ops->region_fini(mlxsw_sp, region->priv); mlxsw_sp_acl_tcam_region_disable(mlxsw_sp, region); mlxsw_sp_acl_tcam_region_free(mlxsw_sp, region); - mlxsw_sp_acl_tcam_region_id_put(region->group->tcam, region->id); - mlxsw_afk_key_info_put(region->key_info); + mlxsw_sp_acl_tcam_region_id_put(region->vregion->group->tcam, + region->id); kfree(region); } +static struct mlxsw_sp_acl_tcam_vregion * +mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam *tcam, + struct mlxsw_afk_element_usage *elusage) +{ + struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); + struct mlxsw_sp_acl_tcam_vregion *vregion; + int err; + + vregion = kzalloc(sizeof(*vregion), GFP_KERNEL); + if (!vregion) + return ERR_PTR(-ENOMEM); + INIT_LIST_HEAD(&vregion->chunk_list); + + vregion->key_info = mlxsw_afk_key_info_get(afk, elusage); + if (IS_ERR(vregion->key_info)) { + err = PTR_ERR(vregion->key_info); + goto err_key_info_get; + } + + vregion->region = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, tcam, + vregion); + if (IS_ERR(vregion->region)) { + err = PTR_ERR(vregion->region); + goto err_region_create; + } + + return vregion; + +err_region_create: + mlxsw_afk_key_info_put(vregion->key_info); +err_key_info_get: + kfree(vregion); + return ERR_PTR(err); +} + +static void +mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion) +{ + mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region); + mlxsw_afk_key_info_put(vregion->key_info); + kfree(vregion); +} + static int mlxsw_sp_acl_tcam_chunk_assoc(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_group *group, @@ -588,48 +644,49 @@ mlxsw_sp_acl_tcam_chunk_assoc(struct mlxsw_sp *mlxsw_sp, struct mlxsw_afk_element_usage *elusage, struct mlxsw_sp_acl_tcam_chunk *chunk) { - struct mlxsw_sp_acl_tcam_region *region; - bool region_created = false; + struct mlxsw_sp_acl_tcam_vregion *vregion; + bool vregion_created = false; bool need_split; int err; - region = mlxsw_sp_acl_tcam_group_region_find(group, priority, elusage, - &need_split); - if (region && need_split) { + vregion = mlxsw_sp_acl_tcam_group_vregion_find(group, priority, elusage, + &need_split); + if (vregion && need_split) { /* According to priority, the chunk should belong to an - * existing region. However, this chunk needs elements - * that region does not contain. We need to split the existing - * region into two and create a new region for this chunk + * existing vregion. However, this chunk needs elements + * that vregion does not contain. We need to split the existing + * vregion into two and create a new vregion for this chunk * in between. This is not supported now. */ return -EOPNOTSUPP; } - if (!region) { - struct mlxsw_afk_element_usage region_elusage; + if (!vregion) { + struct mlxsw_afk_element_usage vregion_elusage; mlxsw_sp_acl_tcam_group_use_patterns(group, elusage, - ®ion_elusage); - region = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, group->tcam, - ®ion_elusage); - if (IS_ERR(region)) - return PTR_ERR(region); - region_created = true; + &vregion_elusage); + vregion = mlxsw_sp_acl_tcam_vregion_create(mlxsw_sp, + group->tcam, + &vregion_elusage); + if (IS_ERR(vregion)) + return PTR_ERR(vregion); + vregion_created = true; } - chunk->region = region; - list_add_tail(&chunk->list, ®ion->chunk_list); + chunk->vregion = vregion; + list_add_tail(&chunk->list, &vregion->chunk_list); - if (!region_created) + if (!vregion_created) return 0; - err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, group, region); + err = mlxsw_sp_acl_tcam_group_vregion_attach(mlxsw_sp, group, vregion); if (err) - goto err_group_region_attach; + goto err_group_vregion_attach; return 0; -err_group_region_attach: - mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region); +err_group_vregion_attach: + mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); return err; } @@ -637,12 +694,12 @@ static void mlxsw_sp_acl_tcam_chunk_deassoc(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_chunk *chunk) { - struct mlxsw_sp_acl_tcam_region *region = chunk->region; + struct mlxsw_sp_acl_tcam_vregion *vregion = chunk->vregion; list_del(&chunk->list); - if (list_empty(®ion->chunk_list)) { - mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, region); - mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region); + if (list_empty(&vregion->chunk_list)) { + mlxsw_sp_acl_tcam_group_vregion_detach(mlxsw_sp, vregion); + mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); } } @@ -671,7 +728,7 @@ mlxsw_sp_acl_tcam_chunk_create(struct mlxsw_sp *mlxsw_sp, if (err) goto err_chunk_assoc; - ops->chunk_init(chunk->region->priv, chunk->priv, priority); + ops->chunk_init(chunk->vregion->region->priv, chunk->priv, priority); err = rhashtable_insert_fast(&group->chunk_ht, &chunk->ht_node, mlxsw_sp_acl_tcam_chunk_ht_params); @@ -713,7 +770,7 @@ mlxsw_sp_acl_tcam_chunk_get(struct mlxsw_sp *mlxsw_sp, chunk = rhashtable_lookup_fast(&group->chunk_ht, &priority, mlxsw_sp_acl_tcam_chunk_ht_params); if (chunk) { - if (WARN_ON(!mlxsw_afk_key_info_subset(chunk->region->key_info, + if (WARN_ON(!mlxsw_afk_key_info_subset(chunk->vregion->key_info, elusage))) return ERR_PTR(-EINVAL); chunk->ref_count++; @@ -753,7 +810,7 @@ static int mlxsw_sp_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp, if (IS_ERR(chunk)) return PTR_ERR(chunk); - region = chunk->region; + region = chunk->vregion->region; err = ops->entry_add(mlxsw_sp, region->priv, chunk->priv, entry->priv, rulei); @@ -773,7 +830,7 @@ static void mlxsw_sp_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp, { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk; - struct mlxsw_sp_acl_tcam_region *region = chunk->region; + struct mlxsw_sp_acl_tcam_region *region = chunk->vregion->region; ops->entry_del(mlxsw_sp, region->priv, chunk->priv, entry->priv); mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, chunk); @@ -786,7 +843,7 @@ mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk; - struct mlxsw_sp_acl_tcam_region *region = chunk->region; + struct mlxsw_sp_acl_tcam_region *region = chunk->vregion->region; return ops->entry_action_replace(mlxsw_sp, region->priv, entry->priv, rulei); @@ -799,7 +856,7 @@ mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp, { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk; - struct mlxsw_sp_acl_tcam_region *region = chunk->region; + struct mlxsw_sp_acl_tcam_region *region = chunk->vregion->region; return ops->entry_activity_get(mlxsw_sp, region->priv, entry->priv, activity); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 0858d5b06353..7e961a64eeaf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -67,11 +67,10 @@ mlxsw_sp_acl_tcam_profile_ops(struct mlxsw_sp *mlxsw_sp, (MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN * BITS_PER_BYTE) struct mlxsw_sp_acl_tcam_group; +struct mlxsw_sp_acl_tcam_vregion; struct mlxsw_sp_acl_tcam_region { - struct list_head list; /* Member of a TCAM group */ - struct list_head chunk_list; /* List of chunks under this region */ - struct mlxsw_sp_acl_tcam_group *group; + struct mlxsw_sp_acl_tcam_vregion *vregion; enum mlxsw_reg_ptar_key_type key_type; u16 id; /* ACL ID and region ID - they are same */ char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN]; -- cgit v1.2.3 From b2d6b4d2beee81e1c30501954dc4ba198bb996c4 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:49 +0000 Subject: mlxsw: spectrum_acl: Split chunk struct into chunk and vchunk Do the split of chunk struct so the new chunk struct is related to the actual HW chunk (differs between Spectrum and Spectrum-2), whereas vchunk struct is a SW abstraction of that. This split prepares possibility for vchunk to hold 2 HW chunks which is needed for region ERP rehash flow. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 256 ++++++++++++--------- 1 file changed, 150 insertions(+), 106 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 092a461cd5fb..091df6e0f805 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -155,7 +155,7 @@ struct mlxsw_sp_acl_tcam_group { u16 id; struct list_head vregion_list; unsigned int region_count; - struct rhashtable chunk_ht; + struct rhashtable vchunk_ht; struct mlxsw_sp_acl_tcam_group_ops *ops; const struct mlxsw_sp_acl_tcam_pattern *patterns; unsigned int patterns_count; @@ -166,32 +166,39 @@ struct mlxsw_sp_acl_tcam_group { struct mlxsw_sp_acl_tcam_vregion { struct mlxsw_sp_acl_tcam_region *region; struct list_head list; /* Member of a TCAM group */ - struct list_head chunk_list; /* List of chunks under this vregion */ + struct list_head vchunk_list; /* List of vchunks under this vregion */ struct mlxsw_sp_acl_tcam_group *group; struct mlxsw_afk_key_info *key_info; }; +struct mlxsw_sp_acl_tcam_vchunk; + struct mlxsw_sp_acl_tcam_chunk { + struct mlxsw_sp_acl_tcam_vchunk *vchunk; + unsigned long priv[0]; + /* priv has to be always the last item */ +}; + +struct mlxsw_sp_acl_tcam_vchunk { + struct mlxsw_sp_acl_tcam_chunk *chunk; struct list_head list; /* Member of a TCAM vregion */ struct rhash_head ht_node; /* Member of a chunk HT */ unsigned int priority; /* Priority within the vregion and group */ struct mlxsw_sp_acl_tcam_group *group; struct mlxsw_sp_acl_tcam_vregion *vregion; unsigned int ref_count; - unsigned long priv[0]; - /* priv has to be always the last item */ }; struct mlxsw_sp_acl_tcam_entry { - struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_vchunk *vchunk; unsigned long priv[0]; /* priv has to be always the last item */ }; -static const struct rhashtable_params mlxsw_sp_acl_tcam_chunk_ht_params = { +static const struct rhashtable_params mlxsw_sp_acl_tcam_vchunk_ht_params = { .key_len = sizeof(unsigned int), - .key_offset = offsetof(struct mlxsw_sp_acl_tcam_chunk, priority), - .head_offset = offsetof(struct mlxsw_sp_acl_tcam_chunk, ht_node), + .key_offset = offsetof(struct mlxsw_sp_acl_tcam_vchunk, priority), + .head_offset = offsetof(struct mlxsw_sp_acl_tcam_vchunk, ht_node), .automatic_shrinking = true, }; @@ -233,8 +240,8 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp, if (err) return err; - err = rhashtable_init(&group->chunk_ht, - &mlxsw_sp_acl_tcam_chunk_ht_params); + err = rhashtable_init(&group->vchunk_ht, + &mlxsw_sp_acl_tcam_vchunk_ht_params); if (err) goto err_rhashtable_init; @@ -250,7 +257,7 @@ static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam *tcam = group->tcam; - rhashtable_destroy(&group->chunk_ht); + rhashtable_destroy(&group->vchunk_ht); mlxsw_sp_acl_tcam_group_id_put(tcam, group->id); WARN_ON(!list_empty(&group->vregion_list)); } @@ -294,26 +301,26 @@ mlxsw_sp_acl_tcam_group_id(struct mlxsw_sp_acl_tcam_group *group) static unsigned int mlxsw_sp_acl_tcam_vregion_prio(struct mlxsw_sp_acl_tcam_vregion *vregion) { - struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_vchunk *vchunk; - if (list_empty(&vregion->chunk_list)) + if (list_empty(&vregion->vchunk_list)) return 0; - /* As a priority of a vregion, return priority of the first chunk */ - chunk = list_first_entry(&vregion->chunk_list, - typeof(*chunk), list); - return chunk->priority; + /* As a priority of a vregion, return priority of the first vchunk */ + vchunk = list_first_entry(&vregion->vchunk_list, + typeof(*vchunk), list); + return vchunk->priority; } static unsigned int mlxsw_sp_acl_tcam_vregion_max_prio(struct mlxsw_sp_acl_tcam_vregion *vregion) { - struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_vchunk *vchunk; - if (list_empty(&vregion->chunk_list)) + if (list_empty(&vregion->vchunk_list)) return 0; - chunk = list_last_entry(&vregion->chunk_list, - typeof(*chunk), list); - return chunk->priority; + vchunk = list_last_entry(&vregion->vchunk_list, + typeof(*vchunk), list); + return vchunk->priority; } static int @@ -604,7 +611,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, vregion = kzalloc(sizeof(*vregion), GFP_KERNEL); if (!vregion) return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(&vregion->chunk_list); + INIT_LIST_HEAD(&vregion->vchunk_list); vregion->key_info = mlxsw_afk_key_info_get(afk, elusage); if (IS_ERR(vregion->key_info)) { @@ -638,11 +645,11 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, } static int -mlxsw_sp_acl_tcam_chunk_assoc(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, - unsigned int priority, - struct mlxsw_afk_element_usage *elusage, - struct mlxsw_sp_acl_tcam_chunk *chunk) +mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_group *group, + unsigned int priority, + struct mlxsw_afk_element_usage *elusage, + struct mlxsw_sp_acl_tcam_vchunk *vchunk) { struct mlxsw_sp_acl_tcam_vregion *vregion; bool vregion_created = false; @@ -652,10 +659,10 @@ mlxsw_sp_acl_tcam_chunk_assoc(struct mlxsw_sp *mlxsw_sp, vregion = mlxsw_sp_acl_tcam_group_vregion_find(group, priority, elusage, &need_split); if (vregion && need_split) { - /* According to priority, the chunk should belong to an - * existing vregion. However, this chunk needs elements + /* According to priority, the vchunk should belong to an + * existing vregion. However, this vchunk needs elements * that vregion does not contain. We need to split the existing - * vregion into two and create a new vregion for this chunk + * vregion into two and create a new vregion for this vchunk * in between. This is not supported now. */ return -EOPNOTSUPP; @@ -673,8 +680,8 @@ mlxsw_sp_acl_tcam_chunk_assoc(struct mlxsw_sp *mlxsw_sp, vregion_created = true; } - chunk->vregion = vregion; - list_add_tail(&chunk->list, &vregion->chunk_list); + vchunk->vregion = vregion; + list_add_tail(&vchunk->list, &vregion->vchunk_list); if (!vregion_created) return 0; @@ -691,13 +698,13 @@ err_group_vregion_attach: } static void -mlxsw_sp_acl_tcam_chunk_deassoc(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_chunk *chunk) +mlxsw_sp_acl_tcam_vchunk_deassoc(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vchunk *vchunk) { - struct mlxsw_sp_acl_tcam_vregion *vregion = chunk->vregion; + struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion; - list_del(&chunk->list); - if (list_empty(&vregion->chunk_list)) { + list_del(&vchunk->list); + if (list_empty(&vregion->vchunk_list)) { mlxsw_sp_acl_tcam_group_vregion_detach(mlxsw_sp, vregion); mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); } @@ -705,87 +712,120 @@ mlxsw_sp_acl_tcam_chunk_deassoc(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_acl_tcam_chunk * mlxsw_sp_acl_tcam_chunk_create(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, - unsigned int priority, - struct mlxsw_afk_element_usage *elusage) + struct mlxsw_sp_acl_tcam_vchunk *vchunk, + struct mlxsw_sp_acl_tcam_region *region) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_sp_acl_tcam_chunk *chunk; + + chunk = kzalloc(sizeof(*chunk) + ops->chunk_priv_size, GFP_KERNEL); + if (!chunk) + return ERR_PTR(-ENOMEM); + chunk->vchunk = vchunk; + + ops->chunk_init(region->priv, chunk->priv, vchunk->priority); + return chunk; +} + +static void +mlxsw_sp_acl_tcam_chunk_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_chunk *chunk) +{ + const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + + ops->chunk_fini(chunk->priv); + kfree(chunk); +} + +static struct mlxsw_sp_acl_tcam_vchunk * +mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_group *group, + unsigned int priority, + struct mlxsw_afk_element_usage *elusage) +{ + struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; if (priority == MLXSW_SP_ACL_TCAM_CATCHALL_PRIO) return ERR_PTR(-EINVAL); - chunk = kzalloc(sizeof(*chunk) + ops->chunk_priv_size, GFP_KERNEL); - if (!chunk) + vchunk = kzalloc(sizeof(*vchunk), GFP_KERNEL); + if (!vchunk) return ERR_PTR(-ENOMEM); - chunk->priority = priority; - chunk->group = group; - chunk->ref_count = 1; + vchunk->priority = priority; + vchunk->group = group; + vchunk->ref_count = 1; - err = mlxsw_sp_acl_tcam_chunk_assoc(mlxsw_sp, group, priority, - elusage, chunk); + err = mlxsw_sp_acl_tcam_vchunk_assoc(mlxsw_sp, group, priority, + elusage, vchunk); if (err) - goto err_chunk_assoc; + goto err_vchunk_assoc; - ops->chunk_init(chunk->vregion->region->priv, chunk->priv, priority); - - err = rhashtable_insert_fast(&group->chunk_ht, &chunk->ht_node, - mlxsw_sp_acl_tcam_chunk_ht_params); + err = rhashtable_insert_fast(&group->vchunk_ht, &vchunk->ht_node, + mlxsw_sp_acl_tcam_vchunk_ht_params); if (err) goto err_rhashtable_insert; - return chunk; + vchunk->chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, + vchunk->vregion->region); + if (IS_ERR(vchunk->chunk)) { + err = PTR_ERR(vchunk->chunk); + goto err_chunk_create; + } + + return vchunk; +err_chunk_create: + rhashtable_remove_fast(&group->vchunk_ht, &vchunk->ht_node, + mlxsw_sp_acl_tcam_vchunk_ht_params); err_rhashtable_insert: - ops->chunk_fini(chunk->priv); - mlxsw_sp_acl_tcam_chunk_deassoc(mlxsw_sp, chunk); -err_chunk_assoc: - kfree(chunk); + mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk); +err_vchunk_assoc: + kfree(vchunk); return ERR_PTR(err); } static void -mlxsw_sp_acl_tcam_chunk_destroy(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_chunk *chunk) +mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vchunk *vchunk) { - const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_group *group = chunk->group; + struct mlxsw_sp_acl_tcam_group *group = vchunk->group; - rhashtable_remove_fast(&group->chunk_ht, &chunk->ht_node, - mlxsw_sp_acl_tcam_chunk_ht_params); - ops->chunk_fini(chunk->priv); - mlxsw_sp_acl_tcam_chunk_deassoc(mlxsw_sp, chunk); - kfree(chunk); + mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk); + rhashtable_remove_fast(&group->vchunk_ht, &vchunk->ht_node, + mlxsw_sp_acl_tcam_vchunk_ht_params); + mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk); + kfree(vchunk); } -static struct mlxsw_sp_acl_tcam_chunk * -mlxsw_sp_acl_tcam_chunk_get(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, - unsigned int priority, - struct mlxsw_afk_element_usage *elusage) +static struct mlxsw_sp_acl_tcam_vchunk * +mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_group *group, + unsigned int priority, + struct mlxsw_afk_element_usage *elusage) { - struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_vchunk *vchunk; - chunk = rhashtable_lookup_fast(&group->chunk_ht, &priority, - mlxsw_sp_acl_tcam_chunk_ht_params); - if (chunk) { - if (WARN_ON(!mlxsw_afk_key_info_subset(chunk->vregion->key_info, + vchunk = rhashtable_lookup_fast(&group->vchunk_ht, &priority, + mlxsw_sp_acl_tcam_vchunk_ht_params); + if (vchunk) { + if (WARN_ON(!mlxsw_afk_key_info_subset(vchunk->vregion->key_info, elusage))) return ERR_PTR(-EINVAL); - chunk->ref_count++; - return chunk; + vchunk->ref_count++; + return vchunk; } - return mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, group, - priority, elusage); + return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, group, + priority, elusage); } -static void mlxsw_sp_acl_tcam_chunk_put(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_chunk *chunk) +static void +mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vchunk *vchunk) { - if (--chunk->ref_count) + if (--vchunk->ref_count) return; - mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, chunk); + mlxsw_sp_acl_tcam_vchunk_destroy(mlxsw_sp, vchunk); } static size_t mlxsw_sp_acl_tcam_entry_priv_size(struct mlxsw_sp *mlxsw_sp) @@ -801,27 +841,29 @@ static int mlxsw_sp_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_vchunk *vchunk; struct mlxsw_sp_acl_tcam_region *region; + struct mlxsw_sp_acl_tcam_chunk *chunk; int err; - chunk = mlxsw_sp_acl_tcam_chunk_get(mlxsw_sp, group, rulei->priority, - &rulei->values.elusage); - if (IS_ERR(chunk)) - return PTR_ERR(chunk); + vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, group, rulei->priority, + &rulei->values.elusage); + if (IS_ERR(vchunk)) + return PTR_ERR(vchunk); - region = chunk->vregion->region; + chunk = vchunk->chunk; + region = vchunk->vregion->region; err = ops->entry_add(mlxsw_sp, region->priv, chunk->priv, entry->priv, rulei); if (err) goto err_entry_add; - entry->chunk = chunk; + entry->vchunk = vchunk; return 0; err_entry_add: - mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, chunk); + mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk); return err; } @@ -829,11 +871,12 @@ static void mlxsw_sp_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_entry *entry) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk; - struct mlxsw_sp_acl_tcam_region *region = chunk->vregion->region; + struct mlxsw_sp_acl_tcam_vchunk *vchunk = entry->vchunk; + struct mlxsw_sp_acl_tcam_chunk *chunk = vchunk->chunk; + struct mlxsw_sp_acl_tcam_region *region = vchunk->vregion->region; ops->entry_del(mlxsw_sp, region->priv, chunk->priv, entry->priv); - mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, chunk); + mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk); } static int @@ -842,8 +885,8 @@ mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk; - struct mlxsw_sp_acl_tcam_region *region = chunk->vregion->region; + struct mlxsw_sp_acl_tcam_vchunk *vchunk = entry->vchunk; + struct mlxsw_sp_acl_tcam_region *region = vchunk->vregion->region; return ops->entry_action_replace(mlxsw_sp, region->priv, entry->priv, rulei); @@ -855,8 +898,8 @@ mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp, bool *activity) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_chunk *chunk = entry->chunk; - struct mlxsw_sp_acl_tcam_region *region = chunk->vregion->region; + struct mlxsw_sp_acl_tcam_vchunk *vchunk = entry->vchunk; + struct mlxsw_sp_acl_tcam_region *region = vchunk->vregion->region; return ops->entry_activity_get(mlxsw_sp, region->priv, entry->priv, activity); @@ -1033,7 +1076,7 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = { }; struct mlxsw_sp_acl_tcam_mr_ruleset { - struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_vchunk *vchunk; struct mlxsw_sp_acl_tcam_group group; }; @@ -1063,10 +1106,11 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp, * specific ACL Group ID which must exist in HW before multicast router * is initialized. */ - ruleset->chunk = mlxsw_sp_acl_tcam_chunk_get(mlxsw_sp, &ruleset->group, - 1, tmplt_elusage); - if (IS_ERR(ruleset->chunk)) { - err = PTR_ERR(ruleset->chunk); + ruleset->vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, + &ruleset->group, 1, + tmplt_elusage); + if (IS_ERR(ruleset->vchunk)) { + err = PTR_ERR(ruleset->vchunk); goto err_chunk_get; } @@ -1082,7 +1126,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_del(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv) { struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv; - mlxsw_sp_acl_tcam_chunk_put(mlxsw_sp, ruleset->chunk); + mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, ruleset->vchunk); mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group); } -- cgit v1.2.3 From c4c2dc54293c556b8a05b9da024f92f8225a9eb8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:50 +0000 Subject: mlxsw: spectrum_acl: Split entry struct into entry and ventry Do the split of entry struct so the new entry struct is related to the actual HW entry, whereas ventry struct is a SW abstration of that. This split prepares possibility for ventry to hold 2 HW entries which is needed for region ERP rehash flow. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 2 +- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 170 +++++++++++++-------- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 2 +- 3 files changed, 108 insertions(+), 66 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 2649d128a57c..38e027815393 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -640,7 +640,7 @@ mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp, int err; mlxsw_sp_acl_ruleset_ref_inc(ruleset); - rule = kzalloc(sizeof(*rule) + ops->rule_priv_size(mlxsw_sp), + rule = kzalloc(sizeof(*rule) + ops->rule_priv_size, GFP_KERNEL); if (!rule) { err = -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 091df6e0f805..36921ed1d2d5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -190,11 +190,16 @@ struct mlxsw_sp_acl_tcam_vchunk { }; struct mlxsw_sp_acl_tcam_entry { - struct mlxsw_sp_acl_tcam_vchunk *vchunk; + struct mlxsw_sp_acl_tcam_ventry *ventry; unsigned long priv[0]; /* priv has to be always the last item */ }; +struct mlxsw_sp_acl_tcam_ventry { + struct mlxsw_sp_acl_tcam_entry *entry; + struct mlxsw_sp_acl_tcam_vchunk *vchunk; +}; + static const struct rhashtable_params mlxsw_sp_acl_tcam_vchunk_ht_params = { .key_len = sizeof(unsigned int), .key_offset = offsetof(struct mlxsw_sp_acl_tcam_vchunk, priority), @@ -828,65 +833,52 @@ mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_acl_tcam_vchunk_destroy(mlxsw_sp, vchunk); } -static size_t mlxsw_sp_acl_tcam_entry_priv_size(struct mlxsw_sp *mlxsw_sp) -{ - const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - - return ops->entry_priv_size; -} - -static int mlxsw_sp_acl_tcam_entry_add(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, - struct mlxsw_sp_acl_tcam_entry *entry, - struct mlxsw_sp_acl_rule_info *rulei) +static struct mlxsw_sp_acl_tcam_entry * +mlxsw_sp_acl_tcam_entry_create(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_ventry *ventry, + struct mlxsw_sp_acl_tcam_region *region, + struct mlxsw_sp_acl_tcam_chunk *chunk, + struct mlxsw_sp_acl_rule_info *rulei) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_vchunk *vchunk; - struct mlxsw_sp_acl_tcam_region *region; - struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_entry *entry; int err; - vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, group, rulei->priority, - &rulei->values.elusage); - if (IS_ERR(vchunk)) - return PTR_ERR(vchunk); - - chunk = vchunk->chunk; - region = vchunk->vregion->region; + entry = kzalloc(sizeof(*entry) + ops->entry_priv_size, GFP_KERNEL); + if (!entry) + return ERR_PTR(-ENOMEM); + entry->ventry = ventry; err = ops->entry_add(mlxsw_sp, region->priv, chunk->priv, entry->priv, rulei); if (err) goto err_entry_add; - entry->vchunk = vchunk; - return 0; + return entry; err_entry_add: - mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk); - return err; + kfree(entry); + return ERR_PTR(err); } -static void mlxsw_sp_acl_tcam_entry_del(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_entry *entry) +static void mlxsw_sp_acl_tcam_entry_destroy(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_region *region, + struct mlxsw_sp_acl_tcam_chunk *chunk, + struct mlxsw_sp_acl_tcam_entry *entry) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_vchunk *vchunk = entry->vchunk; - struct mlxsw_sp_acl_tcam_chunk *chunk = vchunk->chunk; - struct mlxsw_sp_acl_tcam_region *region = vchunk->vregion->region; ops->entry_del(mlxsw_sp, region->priv, chunk->priv, entry->priv); - mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk); + kfree(entry); } static int mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_region *region, struct mlxsw_sp_acl_tcam_entry *entry, struct mlxsw_sp_acl_rule_info *rulei) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_vchunk *vchunk = entry->vchunk; - struct mlxsw_sp_acl_tcam_region *region = vchunk->vregion->region; return ops->entry_action_replace(mlxsw_sp, region->priv, entry->priv, rulei); @@ -894,17 +886,79 @@ mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_region *region, struct mlxsw_sp_acl_tcam_entry *entry, bool *activity) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_vchunk *vchunk = entry->vchunk; - struct mlxsw_sp_acl_tcam_region *region = vchunk->vregion->region; return ops->entry_activity_get(mlxsw_sp, region->priv, entry->priv, activity); } +static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_group *group, + struct mlxsw_sp_acl_tcam_ventry *ventry, + struct mlxsw_sp_acl_rule_info *rulei) +{ + struct mlxsw_sp_acl_tcam_vchunk *vchunk; + int err; + + vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, group, rulei->priority, + &rulei->values.elusage); + if (IS_ERR(vchunk)) + return PTR_ERR(vchunk); + + ventry->vchunk = vchunk; + ventry->entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, + vchunk->vregion->region, + vchunk->chunk, rulei); + if (IS_ERR(ventry->entry)) { + err = PTR_ERR(ventry->entry); + goto err_entry_create; + } + + return 0; + +err_entry_create: + mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk); + return err; +} + +static void mlxsw_sp_acl_tcam_ventry_del(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_ventry *ventry) +{ + struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk; + + mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, vchunk->vregion->region, + vchunk->chunk, ventry->entry); + mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk); +} + +static int +mlxsw_sp_acl_tcam_ventry_action_replace(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_ventry *ventry, + struct mlxsw_sp_acl_rule_info *rulei) +{ + struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk; + + return mlxsw_sp_acl_tcam_entry_action_replace(mlxsw_sp, + vchunk->vregion->region, + ventry->entry, rulei); +} + +static int +mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_ventry *ventry, + bool *activity) +{ + struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk; + + return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, + vchunk->vregion->region, + ventry->entry, activity); +} + static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = { MLXSW_AFK_ELEMENT_SRC_SYS_PORT, MLXSW_AFK_ELEMENT_DMAC_32_47, @@ -959,7 +1013,7 @@ struct mlxsw_sp_acl_tcam_flower_ruleset { }; struct mlxsw_sp_acl_tcam_flower_rule { - struct mlxsw_sp_acl_tcam_entry entry; + struct mlxsw_sp_acl_tcam_ventry ventry; }; static int @@ -1017,12 +1071,6 @@ mlxsw_sp_acl_tcam_flower_ruleset_group_id(void *ruleset_priv) return mlxsw_sp_acl_tcam_group_id(&ruleset->group); } -static size_t mlxsw_sp_acl_tcam_flower_rule_priv_size(struct mlxsw_sp *mlxsw_sp) -{ - return sizeof(struct mlxsw_sp_acl_tcam_flower_rule) + - mlxsw_sp_acl_tcam_entry_priv_size(mlxsw_sp); -} - static int mlxsw_sp_acl_tcam_flower_rule_add(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, void *rule_priv, @@ -1031,8 +1079,8 @@ mlxsw_sp_acl_tcam_flower_rule_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv; struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv; - return mlxsw_sp_acl_tcam_entry_add(mlxsw_sp, &ruleset->group, - &rule->entry, rulei); + return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->group, + &rule->ventry, rulei); } static void @@ -1040,7 +1088,7 @@ mlxsw_sp_acl_tcam_flower_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv) { struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv; - mlxsw_sp_acl_tcam_entry_del(mlxsw_sp, &rule->entry); + mlxsw_sp_acl_tcam_ventry_del(mlxsw_sp, &rule->ventry); } static int @@ -1057,8 +1105,8 @@ mlxsw_sp_acl_tcam_flower_rule_activity_get(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv; - return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, &rule->entry, - activity); + return mlxsw_sp_acl_tcam_ventry_activity_get(mlxsw_sp, &rule->ventry, + activity); } static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = { @@ -1068,7 +1116,7 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = { .ruleset_bind = mlxsw_sp_acl_tcam_flower_ruleset_bind, .ruleset_unbind = mlxsw_sp_acl_tcam_flower_ruleset_unbind, .ruleset_group_id = mlxsw_sp_acl_tcam_flower_ruleset_group_id, - .rule_priv_size = mlxsw_sp_acl_tcam_flower_rule_priv_size, + .rule_priv_size = sizeof(struct mlxsw_sp_acl_tcam_flower_rule), .rule_add = mlxsw_sp_acl_tcam_flower_rule_add, .rule_del = mlxsw_sp_acl_tcam_flower_rule_del, .rule_action_replace = mlxsw_sp_acl_tcam_flower_rule_action_replace, @@ -1081,7 +1129,7 @@ struct mlxsw_sp_acl_tcam_mr_ruleset { }; struct mlxsw_sp_acl_tcam_mr_rule { - struct mlxsw_sp_acl_tcam_entry entry; + struct mlxsw_sp_acl_tcam_ventry ventry; }; static int @@ -1155,12 +1203,6 @@ mlxsw_sp_acl_tcam_mr_ruleset_group_id(void *ruleset_priv) return mlxsw_sp_acl_tcam_group_id(&ruleset->group); } -static size_t mlxsw_sp_acl_tcam_mr_rule_priv_size(struct mlxsw_sp *mlxsw_sp) -{ - return sizeof(struct mlxsw_sp_acl_tcam_mr_rule) + - mlxsw_sp_acl_tcam_entry_priv_size(mlxsw_sp); -} - static int mlxsw_sp_acl_tcam_mr_rule_add(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, void *rule_priv, @@ -1169,8 +1211,8 @@ mlxsw_sp_acl_tcam_mr_rule_add(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv; struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv; - return mlxsw_sp_acl_tcam_entry_add(mlxsw_sp, &ruleset->group, - &rule->entry, rulei); + return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->group, + &rule->ventry, rulei); } static void @@ -1178,7 +1220,7 @@ mlxsw_sp_acl_tcam_mr_rule_del(struct mlxsw_sp *mlxsw_sp, void *rule_priv) { struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv; - mlxsw_sp_acl_tcam_entry_del(mlxsw_sp, &rule->entry); + mlxsw_sp_acl_tcam_ventry_del(mlxsw_sp, &rule->ventry); } static int @@ -1188,8 +1230,8 @@ mlxsw_sp_acl_tcam_mr_rule_action_replace(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv; - return mlxsw_sp_acl_tcam_entry_action_replace(mlxsw_sp, &rule->entry, - rulei); + return mlxsw_sp_acl_tcam_ventry_action_replace(mlxsw_sp, &rule->ventry, + rulei); } static int @@ -1198,8 +1240,8 @@ mlxsw_sp_acl_tcam_mr_rule_activity_get(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv; - return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, &rule->entry, - activity); + return mlxsw_sp_acl_tcam_ventry_activity_get(mlxsw_sp, &rule->ventry, + activity); } static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_mr_ops = { @@ -1209,7 +1251,7 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_mr_ops = { .ruleset_bind = mlxsw_sp_acl_tcam_mr_ruleset_bind, .ruleset_unbind = mlxsw_sp_acl_tcam_mr_ruleset_unbind, .ruleset_group_id = mlxsw_sp_acl_tcam_mr_ruleset_group_id, - .rule_priv_size = mlxsw_sp_acl_tcam_mr_rule_priv_size, + .rule_priv_size = sizeof(struct mlxsw_sp_acl_tcam_mr_rule), .rule_add = mlxsw_sp_acl_tcam_mr_rule_add, .rule_del = mlxsw_sp_acl_tcam_mr_rule_del, .rule_action_replace = mlxsw_sp_acl_tcam_mr_rule_action_replace, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 7e961a64eeaf..c6d4aac82ddb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -43,7 +43,7 @@ struct mlxsw_sp_acl_profile_ops { struct mlxsw_sp_port *mlxsw_sp_port, bool ingress); u16 (*ruleset_group_id)(void *ruleset_priv); - size_t (*rule_priv_size)(struct mlxsw_sp *mlxsw_sp); + size_t rule_priv_size; int (*rule_add)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, void *rule_priv, struct mlxsw_sp_acl_rule_info *rulei); -- cgit v1.2.3 From 29a2102a29085f5505d86bd3cbfe11c6fa08340d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:51 +0000 Subject: mlxsw: spectrum_acl: Implement basic ERP rehash hits creation Introduce an initial implementation of rehash logic in ERP code. Currently, the rehash is considered as needed only in case number of roots in the hints is smaller than the number of roots actually in use. In that case return hints pointer and let it be obtained through the callpath through the Spectrum-2 TCAM op. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 + .../ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c | 14 ++++ .../ethernet/mellanox/mlxsw/spectrum_acl_atcam.c | 11 ++++ .../net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c | 74 ++++++++++++++++++++++ .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 6 ++ 5 files changed, 107 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 4fe0996c7cdd..6432a1ce51f3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -708,6 +708,8 @@ struct mlxsw_sp_acl_tcam_ops { void (*region_fini)(struct mlxsw_sp *mlxsw_sp, void *region_priv); int (*region_associate)(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_region *region); + void * (*region_rehash_hints_get)(void *region_priv); + void (*region_rehash_hints_put)(void *hints_priv); size_t chunk_priv_size; void (*chunk_init)(void *region_priv, void *chunk_priv, unsigned int priority); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c index d380b3403960..4808b29294d0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c @@ -166,6 +166,18 @@ mlxsw_sp2_acl_tcam_region_associate(struct mlxsw_sp *mlxsw_sp, return mlxsw_sp_acl_atcam_region_associate(mlxsw_sp, region->id); } +static void *mlxsw_sp2_acl_tcam_region_rehash_hints_get(void *region_priv) +{ + struct mlxsw_sp2_acl_tcam_region *region = region_priv; + + return mlxsw_sp_acl_atcam_rehash_hints_get(®ion->aregion); +} + +static void mlxsw_sp2_acl_tcam_region_rehash_hints_put(void *hints_priv) +{ + mlxsw_sp_acl_atcam_rehash_hints_put(hints_priv); +} + static void mlxsw_sp2_acl_tcam_chunk_init(void *region_priv, void *chunk_priv, unsigned int priority) { @@ -243,6 +255,8 @@ const struct mlxsw_sp_acl_tcam_ops mlxsw_sp2_acl_tcam_ops = { .region_init = mlxsw_sp2_acl_tcam_region_init, .region_fini = mlxsw_sp2_acl_tcam_region_fini, .region_associate = mlxsw_sp2_acl_tcam_region_associate, + .region_rehash_hints_get = mlxsw_sp2_acl_tcam_region_rehash_hints_get, + .region_rehash_hints_put = mlxsw_sp2_acl_tcam_region_rehash_hints_put, .chunk_priv_size = sizeof(struct mlxsw_sp2_acl_tcam_chunk), .chunk_init = mlxsw_sp2_acl_tcam_chunk_init, .chunk_fini = mlxsw_sp2_acl_tcam_chunk_fini, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index a74a390901ac..e98037e4d03e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -634,3 +634,14 @@ void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp, { mlxsw_sp_acl_erps_fini(mlxsw_sp, atcam); } + +void * +mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion) +{ + return mlxsw_sp_acl_erp_rehash_hints_get(aregion); +} + +void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv) +{ + mlxsw_sp_acl_erp_rehash_hints_put(hints_priv); +} diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index 302070a74f2e..013ab43a7727 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -1370,6 +1370,80 @@ mlxsw_sp_acl_erp_region_param_init(struct mlxsw_sp_acl_atcam_region *aregion) return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pererp), pererp_pl); } +static int +mlxsw_sp_acl_erp_hints_check(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_atcam_region *aregion, + struct objagg_hints *hints, bool *p_rehash_needed) +{ + struct objagg *objagg = aregion->erp_table->objagg; + const struct objagg_stats *ostats; + const struct objagg_stats *hstats; + int err; + + *p_rehash_needed = false; + + ostats = objagg_stats_get(objagg); + if (IS_ERR(ostats)) { + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get ERP stats\n"); + return PTR_ERR(ostats); + } + + hstats = objagg_hints_stats_get(hints); + if (IS_ERR(hstats)) { + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get ERP hints stats\n"); + err = PTR_ERR(hstats); + goto err_hints_stats_get; + } + + /* Very basic criterion for now. */ + if (hstats->root_count < ostats->root_count) + *p_rehash_needed = true; + + err = 0; + + objagg_stats_put(hstats); +err_hints_stats_get: + objagg_stats_put(ostats); + return err; +} + +void * +mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion) +{ + struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp; + struct objagg_hints *hints; + bool rehash_needed; + int err; + + hints = objagg_hints_get(aregion->erp_table->objagg, + OBJAGG_OPT_ALGO_SIMPLE_GREEDY); + if (IS_ERR(hints)) { + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to create ERP hints\n"); + return ERR_CAST(hints); + } + err = mlxsw_sp_acl_erp_hints_check(mlxsw_sp, aregion, hints, + &rehash_needed); + if (err) + goto errout; + + if (!rehash_needed) { + err = -EAGAIN; + goto errout; + } + return hints; + +errout: + objagg_hints_put(hints); + return ERR_PTR(err); +} + +void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv) +{ + struct objagg_hints *hints = hints_priv; + + objagg_hints_put(hints); +} + int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion) { struct mlxsw_sp_acl_erp_table *erp_table; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index c6d4aac82ddb..a90942bc1fe9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -229,6 +229,9 @@ int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); +void * +mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion); +void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv); struct mlxsw_sp_acl_erp_delta; @@ -259,6 +262,9 @@ void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_erp_mask *erp_mask, struct mlxsw_sp_acl_atcam_entry *aentry); +void * +mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion); +void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv); int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion); void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp, -- cgit v1.2.3 From a339bf8aafbc4b9a9234da290b0cc50c50e9c15b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:52 +0000 Subject: mlxsw: spectrum_acl: Pass hints priv all the way to ERP code The hints priv comes from ERP code and it is possible to obtain it from TCAM code. Add arg to appropriate functions so the hints priv could be passed back down to ERP code. Pass NULL now as the follow-up patches would pass an actual hints priv pointer. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 3 ++- drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c | 3 ++- drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c | 6 ++++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c | 3 ++- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c | 11 +++++++---- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 3 ++- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 4 +++- 7 files changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 6432a1ce51f3..3d17b4a368f4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -704,7 +704,8 @@ struct mlxsw_sp_acl_tcam_ops { size_t region_priv_size; int (*region_init)(struct mlxsw_sp *mlxsw_sp, void *region_priv, void *tcam_priv, - struct mlxsw_sp_acl_tcam_region *region); + struct mlxsw_sp_acl_tcam_region *region, + void *hints_priv); void (*region_fini)(struct mlxsw_sp *mlxsw_sp, void *region_priv); int (*region_associate)(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_region *region); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c index 6e444525713f..3a636f753607 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum1_acl_tcam.c @@ -112,7 +112,8 @@ mlxsw_sp1_acl_ctcam_region_catchall_del(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp1_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv, void *tcam_priv, - struct mlxsw_sp_acl_tcam_region *_region) + struct mlxsw_sp_acl_tcam_region *_region, + void *hints_priv) { struct mlxsw_sp1_acl_tcam_region *region = region_priv; int err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c index 4808b29294d0..6c66a0f1b79e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c @@ -139,7 +139,8 @@ static void mlxsw_sp2_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, void *priv) static int mlxsw_sp2_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv, void *tcam_priv, - struct mlxsw_sp_acl_tcam_region *_region) + struct mlxsw_sp_acl_tcam_region *_region, + void *hints_priv) { struct mlxsw_sp2_acl_tcam_region *region = region_priv; struct mlxsw_sp2_acl_tcam *tcam = tcam_priv; @@ -147,7 +148,8 @@ mlxsw_sp2_acl_tcam_region_init(struct mlxsw_sp *mlxsw_sp, void *region_priv, region->region = _region; return mlxsw_sp_acl_atcam_region_init(mlxsw_sp, &tcam->atcam, - ®ion->aregion, _region, + ®ion->aregion, + _region, hints_priv, &mlxsw_sp2_acl_ctcam_region_ops); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c index e98037e4d03e..ded4cf658680 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c @@ -318,6 +318,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_tcam_region *region, + void *hints_priv, const struct mlxsw_sp_acl_ctcam_region_ops *ops) { int err; @@ -334,7 +335,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, err = aregion->ops->init(aregion); if (err) goto err_ops_init; - err = mlxsw_sp_acl_erp_region_init(aregion); + err = mlxsw_sp_acl_erp_region_init(aregion, hints_priv); if (err) goto err_erp_region_init; err = mlxsw_sp_acl_ctcam_region_init(mlxsw_sp, &aregion->cregion, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index 013ab43a7727..e935c36638d9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -1313,7 +1313,8 @@ static const struct objagg_ops mlxsw_sp_acl_erp_objagg_ops = { }; static struct mlxsw_sp_acl_erp_table * -mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion) +mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion, + struct objagg_hints *hints) { struct mlxsw_sp_acl_erp_table *erp_table; int err; @@ -1323,7 +1324,7 @@ mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion) return ERR_PTR(-ENOMEM); erp_table->objagg = objagg_create(&mlxsw_sp_acl_erp_objagg_ops, - NULL, aregion); + hints, aregion); if (IS_ERR(erp_table->objagg)) { err = PTR_ERR(erp_table->objagg); goto err_objagg_create; @@ -1444,12 +1445,14 @@ void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv) objagg_hints_put(hints); } -int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion) +int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion, + void *hints_priv) { struct mlxsw_sp_acl_erp_table *erp_table; + struct objagg_hints *hints = hints_priv; int err; - erp_table = mlxsw_sp_acl_erp_table_create(aregion); + erp_table = mlxsw_sp_acl_erp_table_create(aregion, hints); if (IS_ERR(erp_table)) return PTR_ERR(erp_table); aregion->erp_table = erp_table; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 36921ed1d2d5..1077c893438b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -572,7 +572,8 @@ mlxsw_sp_acl_tcam_region_create(struct mlxsw_sp *mlxsw_sp, if (err) goto err_tcam_region_enable; - err = ops->region_init(mlxsw_sp, region->priv, tcam->priv, region); + err = ops->region_init(mlxsw_sp, region->priv, tcam->priv, + region, NULL); if (err) goto err_tcam_region_init; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index a90942bc1fe9..c2a340270982 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -206,6 +206,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_tcam_region *region, + void *hints_priv, const struct mlxsw_sp_acl_ctcam_region_ops *ops); void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion, @@ -265,7 +266,8 @@ void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp, void * mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion); void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv); -int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion); +int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion, + void *hints_priv); void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion); int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam *atcam); -- cgit v1.2.3 From 5c661f142c1699095fbb80efb48198ef4c6c9d1d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:53 +0000 Subject: mlxsw: reg: Add multi field to PAGT register For Spectrum-2 this allows parallel lookups in multiple regions. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 11 ++++++++++- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 5f8066ab7d40..227720ce3982 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2199,6 +2199,14 @@ MLXSW_ITEM32(reg, pagt, size, 0x00, 0, 8); */ MLXSW_ITEM32(reg, pagt, acl_group_id, 0x08, 0, 16); +/* reg_pagt_multi + * Multi-ACL + * 0 - This ACL is the last ACL in the multi-ACL + * 1 - This ACL is part of a multi-ACL + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, pagt, multi, 0x30, 31, 1, 0x04, 0x00, false); + /* reg_pagt_acl_id * ACL identifier * Access: RW @@ -2212,12 +2220,13 @@ static inline void mlxsw_reg_pagt_pack(char *payload, u16 acl_group_id) } static inline void mlxsw_reg_pagt_acl_id_pack(char *payload, int index, - u16 acl_id) + u16 acl_id, bool multi) { u8 size = mlxsw_reg_pagt_size_get(payload); if (index >= size) mlxsw_reg_pagt_size_set(payload, index + 1); + mlxsw_reg_pagt_multi_set(payload, index, multi); mlxsw_reg_pagt_acl_id_set(payload, index, acl_id); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 1077c893438b..12d202afa233 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -217,7 +217,7 @@ static int mlxsw_sp_acl_tcam_group_update(struct mlxsw_sp *mlxsw_sp, mlxsw_reg_pagt_pack(pagt_pl, group->id); list_for_each_entry(vregion, &group->vregion_list, list) mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++, - vregion->region->id); + vregion->region->id, false); mlxsw_reg_pagt_size_set(pagt_pl, acl_index); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pagt), pagt_pl); } -- cgit v1.2.3 From e5e7962ee5c277f769791d1d857d3641200ee0eb Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:54 +0000 Subject: mlxsw: spectrum_acl: Implement region migration according to hints If the hints are returned, the migration should be started. For that to happen, there is a need to create a second physical region in TCAM with new ERP set by passing the hints and then move chunk by chunk, entry by entry. During the transition, two lookups will occur. One in old region and another in new region. The highest priority rule will be chosen. In an unlikely case that the migration will fail and also rollback to original region will fail the vregion will become in bad state. Everything will work, only no future rehash will be possible. In a follow-up work, this can be resolved by trying to resume the rollback in delayed work and repair the vregion. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 287 +++++++++++++++++++-- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 2 + 2 files changed, 268 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 12d202afa233..9239ff4e94c4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -23,6 +23,8 @@ size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp) return ops->priv_size; } +#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT 5000 /* ms */ + int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam) { @@ -33,6 +35,10 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, size_t alloc_size; int err; + tcam->vregion_rehash_intrvl = + MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT; + INIT_LIST_HEAD(&tcam->vregion_list); + max_tcam_regions = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_TCAM_REGIONS); max_regions = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_REGIONS); @@ -165,24 +171,33 @@ struct mlxsw_sp_acl_tcam_group { struct mlxsw_sp_acl_tcam_vregion { struct mlxsw_sp_acl_tcam_region *region; + struct mlxsw_sp_acl_tcam_region *region2; /* Used during migration */ struct list_head list; /* Member of a TCAM group */ + struct list_head tlist; /* Member of a TCAM */ struct list_head vchunk_list; /* List of vchunks under this vregion */ struct mlxsw_sp_acl_tcam_group *group; struct mlxsw_afk_key_info *key_info; + struct mlxsw_sp_acl_tcam *tcam; + struct delayed_work rehash_dw; + struct mlxsw_sp *mlxsw_sp; + bool failed_rollback; /* Indicates failed rollback during migration */ }; struct mlxsw_sp_acl_tcam_vchunk; struct mlxsw_sp_acl_tcam_chunk { struct mlxsw_sp_acl_tcam_vchunk *vchunk; + struct mlxsw_sp_acl_tcam_region *region; unsigned long priv[0]; /* priv has to be always the last item */ }; struct mlxsw_sp_acl_tcam_vchunk { struct mlxsw_sp_acl_tcam_chunk *chunk; + struct mlxsw_sp_acl_tcam_chunk *chunk2; /* Used during migration */ struct list_head list; /* Member of a TCAM vregion */ struct rhash_head ht_node; /* Member of a chunk HT */ + struct list_head ventry_list; unsigned int priority; /* Priority within the vregion and group */ struct mlxsw_sp_acl_tcam_group *group; struct mlxsw_sp_acl_tcam_vregion *vregion; @@ -191,13 +206,16 @@ struct mlxsw_sp_acl_tcam_vchunk { struct mlxsw_sp_acl_tcam_entry { struct mlxsw_sp_acl_tcam_ventry *ventry; + struct mlxsw_sp_acl_tcam_chunk *chunk; unsigned long priv[0]; /* priv has to be always the last item */ }; struct mlxsw_sp_acl_tcam_ventry { struct mlxsw_sp_acl_tcam_entry *entry; + struct list_head list; /* Member of a TCAM vchunk */ struct mlxsw_sp_acl_tcam_vchunk *vchunk; + struct mlxsw_sp_acl_rule_info *rulei; }; static const struct rhashtable_params mlxsw_sp_acl_tcam_vchunk_ht_params = { @@ -215,9 +233,13 @@ static int mlxsw_sp_acl_tcam_group_update(struct mlxsw_sp *mlxsw_sp, int acl_index = 0; mlxsw_reg_pagt_pack(pagt_pl, group->id); - list_for_each_entry(vregion, &group->vregion_list, list) + list_for_each_entry(vregion, &group->vregion_list, list) { + if (vregion->region2) + mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++, + vregion->region2->id, true); mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++, vregion->region->id, false); + } mlxsw_reg_pagt_size_set(pagt_pl, acl_index); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pagt), pagt_pl); } @@ -391,6 +413,9 @@ mlxsw_sp_acl_tcam_group_vregion_detach(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion) { list_del(&vregion->list); + if (vregion->region2) + mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, + vregion->region2); mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, vregion->region); } @@ -542,7 +567,8 @@ mlxsw_sp_acl_tcam_region_disable(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_acl_tcam_region * mlxsw_sp_acl_tcam_region_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam, - struct mlxsw_sp_acl_tcam_vregion *vregion) + struct mlxsw_sp_acl_tcam_vregion *vregion, + void *hints_priv) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_sp_acl_tcam_region *region; @@ -573,7 +599,7 @@ mlxsw_sp_acl_tcam_region_create(struct mlxsw_sp *mlxsw_sp, goto err_tcam_region_enable; err = ops->region_init(mlxsw_sp, region->priv, tcam->priv, - region, NULL); + region, hints_priv); if (err) goto err_tcam_region_init; @@ -605,11 +631,42 @@ mlxsw_sp_acl_tcam_region_destroy(struct mlxsw_sp *mlxsw_sp, kfree(region); } +static void +mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion *vregion) +{ + unsigned long interval = vregion->tcam->vregion_rehash_intrvl; + + if (!interval) + return; + mlxsw_core_schedule_dw(&vregion->rehash_dw, + msecs_to_jiffies(interval)); +} + +static int +mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion); + +static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) +{ + struct mlxsw_sp_acl_tcam_vregion *vregion = + container_of(work, struct mlxsw_sp_acl_tcam_vregion, + rehash_dw.work); + + /* TODO: Take rtnl lock here as the rest of the code counts on it + * now. Later, this should be replaced by per-vregion lock. + */ + rtnl_lock(); + mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion); + rtnl_unlock(); + mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); +} + static struct mlxsw_sp_acl_tcam_vregion * mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam, struct mlxsw_afk_element_usage *elusage) { + const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); struct mlxsw_sp_acl_tcam_vregion *vregion; int err; @@ -618,6 +675,8 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, if (!vregion) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&vregion->vchunk_list); + vregion->tcam = tcam; + vregion->mlxsw_sp = mlxsw_sp; vregion->key_info = mlxsw_afk_key_info_get(afk, elusage); if (IS_ERR(vregion->key_info)) { @@ -626,12 +685,21 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, } vregion->region = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, tcam, - vregion); + vregion, NULL); if (IS_ERR(vregion->region)) { err = PTR_ERR(vregion->region); goto err_region_create; } + list_add_tail(&vregion->tlist, &tcam->vregion_list); + + if (ops->region_rehash_hints_get) { + /* Create the delayed work for vregion periodic rehash */ + INIT_DELAYED_WORK(&vregion->rehash_dw, + mlxsw_sp_acl_tcam_vregion_rehash_work); + mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); + } + return vregion; err_region_create: @@ -645,6 +713,13 @@ static void mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion) { + const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + + if (ops->region_rehash_hints_get) + cancel_delayed_work_sync(&vregion->rehash_dw); + list_del(&vregion->tlist); + if (vregion->region2) + mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2); mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region); mlxsw_afk_key_info_put(vregion->key_info); kfree(vregion); @@ -728,6 +803,7 @@ mlxsw_sp_acl_tcam_chunk_create(struct mlxsw_sp *mlxsw_sp, if (!chunk) return ERR_PTR(-ENOMEM); chunk->vchunk = vchunk; + chunk->region = region; ops->chunk_init(region->priv, chunk->priv, vchunk->priority); return chunk; @@ -758,6 +834,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, vchunk = kzalloc(sizeof(*vchunk), GFP_KERNEL); if (!vchunk) return ERR_PTR(-ENOMEM); + INIT_LIST_HEAD(&vchunk->ventry_list); vchunk->priority = priority; vchunk->group = group; vchunk->ref_count = 1; @@ -797,6 +874,8 @@ mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_group *group = vchunk->group; + if (vchunk->chunk2) + mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk); rhashtable_remove_fast(&group->vchunk_ht, &vchunk->ht_node, mlxsw_sp_acl_tcam_vchunk_ht_params); @@ -837,9 +916,7 @@ mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_acl_tcam_entry * mlxsw_sp_acl_tcam_entry_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_ventry *ventry, - struct mlxsw_sp_acl_tcam_region *region, - struct mlxsw_sp_acl_tcam_chunk *chunk, - struct mlxsw_sp_acl_rule_info *rulei) + struct mlxsw_sp_acl_tcam_chunk *chunk) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_sp_acl_tcam_entry *entry; @@ -849,9 +926,10 @@ mlxsw_sp_acl_tcam_entry_create(struct mlxsw_sp *mlxsw_sp, if (!entry) return ERR_PTR(-ENOMEM); entry->ventry = ventry; + entry->chunk = chunk; - err = ops->entry_add(mlxsw_sp, region->priv, chunk->priv, - entry->priv, rulei); + err = ops->entry_add(mlxsw_sp, chunk->region->priv, chunk->priv, + entry->priv, ventry->rulei); if (err) goto err_entry_add; @@ -863,13 +941,12 @@ err_entry_add: } static void mlxsw_sp_acl_tcam_entry_destroy(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_region *region, - struct mlxsw_sp_acl_tcam_chunk *chunk, struct mlxsw_sp_acl_tcam_entry *entry) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - ops->entry_del(mlxsw_sp, region->priv, chunk->priv, entry->priv); + ops->entry_del(mlxsw_sp, entry->chunk->region->priv, + entry->chunk->priv, entry->priv); kfree(entry); } @@ -887,13 +964,12 @@ mlxsw_sp_acl_tcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_region *region, struct mlxsw_sp_acl_tcam_entry *entry, bool *activity) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - return ops->entry_activity_get(mlxsw_sp, region->priv, + return ops->entry_activity_get(mlxsw_sp, entry->chunk->region->priv, entry->priv, activity); } @@ -911,14 +987,16 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp, return PTR_ERR(vchunk); ventry->vchunk = vchunk; + ventry->rulei = rulei; ventry->entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, - vchunk->vregion->region, - vchunk->chunk, rulei); + vchunk->chunk); if (IS_ERR(ventry->entry)) { err = PTR_ERR(ventry->entry); goto err_entry_create; } + list_add_tail(&ventry->list, &vchunk->ventry_list); + return 0; err_entry_create: @@ -931,8 +1009,8 @@ static void mlxsw_sp_acl_tcam_ventry_del(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk; - mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, vchunk->vregion->region, - vchunk->chunk, ventry->entry); + list_del(&ventry->list); + mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry); mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk); } @@ -953,13 +1031,180 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_ventry *ventry, bool *activity) { - struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk; - return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, - vchunk->vregion->region, ventry->entry, activity); } +static int +mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_ventry *ventry, + struct mlxsw_sp_acl_tcam_chunk *chunk2) +{ + struct mlxsw_sp_acl_tcam_entry *entry2; + + entry2 = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk2); + if (IS_ERR(entry2)) + return PTR_ERR(entry2); + mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry); + ventry->entry = entry2; + return 0; +} + +static int +mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vchunk *vchunk, + struct mlxsw_sp_acl_tcam_region *region, + bool this_is_rollback) +{ + struct mlxsw_sp_acl_tcam_ventry *ventry; + struct mlxsw_sp_acl_tcam_chunk *chunk2; + int err; + int err2; + + chunk2 = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region); + if (IS_ERR(chunk2)) { + if (this_is_rollback) + vchunk->vregion->failed_rollback = true; + return PTR_ERR(chunk2); + } + vchunk->chunk2 = chunk2; + list_for_each_entry(ventry, &vchunk->ventry_list, list) { + err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, + vchunk->chunk2); + if (err) { + if (this_is_rollback) { + vchunk->vregion->failed_rollback = true; + return err; + } + goto rollback; + } + } + mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk); + vchunk->chunk = chunk2; + vchunk->chunk2 = NULL; + return 0; + +rollback: + /* Migrate the entries back to the original chunk. If some entry + * migration fails, there's no good way how to proceed. Set the + * vregion with "failed_rollback" flag. + */ + list_for_each_entry_continue_reverse(ventry, &vchunk->ventry_list, + list) { + err2 = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, + vchunk->chunk); + if (err2) { + vchunk->vregion->failed_rollback = true; + goto err_rollback; + } + } + + mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); + vchunk->chunk2 = NULL; + +err_rollback: + return err; +} + +static int +mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion) +{ + struct mlxsw_sp_acl_tcam_vchunk *vchunk; + int err; + + list_for_each_entry(vchunk, &vregion->vchunk_list, list) { + err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, + vregion->region2, + false); + if (err) + goto rollback; + } + return 0; + +rollback: + list_for_each_entry_continue_reverse(vchunk, &vregion->vchunk_list, + list) { + mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, + vregion->region, true); + } + return err; +} + +static int +mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion, + void *hints_priv) +{ + struct mlxsw_sp_acl_tcam_region *region2, *unused_region; + int err; + + region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam, + vregion, hints_priv); + if (IS_ERR(region2)) + return PTR_ERR(region2); + + vregion->region2 = region2; + err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, region2); + if (err) + goto err_group_region_attach; + + err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion); + if (!vregion->failed_rollback) { + if (!err) { + /* In case of successful migration, region2 is used and + * the original is unused. + */ + unused_region = vregion->region; + vregion->region = vregion->region2; + } else { + /* In case of failure during migration, the original + * region is still used. + */ + unused_region = vregion->region2; + } + vregion->region2 = NULL; + mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, unused_region); + mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, unused_region); + } + return err; + +err_group_region_attach: + vregion->region2 = NULL; + mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2); + return err; +} + +static int +mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion) +{ + const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + void *hints_priv; + int err; + + if (vregion->failed_rollback) + return -EBUSY; + + hints_priv = ops->region_rehash_hints_get(vregion->region->priv); + if (IS_ERR(hints_priv)) { + err = PTR_ERR(hints_priv); + if (err != -EAGAIN) + dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n"); + return err; + } + + err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, hints_priv); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); + if (vregion->failed_rollback) + dev_err(mlxsw_sp->bus_info->dev, "Failed to rollback during vregion migration fail\n"); + } + + ops->region_rehash_hints_put(hints_priv); + return err; +} + static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = { MLXSW_AFK_ELEMENT_SRC_SYS_PORT, MLXSW_AFK_ELEMENT_DMAC_32_47, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index c2a340270982..440a3483ed7b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -17,6 +17,8 @@ struct mlxsw_sp_acl_tcam { unsigned long *used_groups; /* bit array */ unsigned int max_groups; unsigned int max_group_size; + struct list_head vregion_list; + u32 vregion_rehash_intrvl; /* ms */ unsigned long priv[0]; /* priv has to be always the last item */ }; -- cgit v1.2.3 From 98bbf70c1c41fb9547c3a18c0f1b96f6ebb8eb1d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:55 +0000 Subject: mlxsw: spectrum: add "acl_region_rehash_interval" devlink param Expose new driver-specific "acl_region_rehash_interval" devlink param which would allow user to alter default ACL region rehash interval. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- Documentation/networking/devlink-params-mlxsw.txt | 8 +++ drivers/net/ethernet/mellanox/mlxsw/core.h | 5 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 69 +++++++++++++++++++++- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 + drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 16 +++++ .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 36 +++++++++++ .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 5 ++ 7 files changed, 139 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/devlink-params-mlxsw.txt b/Documentation/networking/devlink-params-mlxsw.txt index 2c5c67a920c9..c63ea9fc7009 100644 --- a/Documentation/networking/devlink-params-mlxsw.txt +++ b/Documentation/networking/devlink-params-mlxsw.txt @@ -1,2 +1,10 @@ fw_load_policy [DEVICE, GENERIC] Configuration mode: driverinit + +acl_region_rehash_interval [DEVICE, DRIVER-SPECIFIC] + Sets an interval for periodic ACL region rehashes. + The value is in milliseconds, minimal value is "3000". + Value "0" disables the periodic work. + The first rehash will be run right after value is set. + Type: u32 + Configuration mode: runtime diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 4e114f35ee0d..c8e16a305969 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -394,4 +394,9 @@ static inline void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) #endif +enum mlxsw_devlink_param_id { + MLXSW_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, + MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL, +}; + #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 8dd808b7f931..7c9745cecbbd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4413,6 +4413,71 @@ static void mlxsw_sp_params_unregister(struct mlxsw_core *mlxsw_core) ARRAY_SIZE(mlxsw_sp_devlink_params)); } +static int +mlxsw_sp_params_acl_region_rehash_intrvl_get(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + + ctx->val.vu32 = mlxsw_sp_acl_region_rehash_intrvl_get(mlxsw_sp); + return 0; +} + +static int +mlxsw_sp_params_acl_region_rehash_intrvl_set(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + + return mlxsw_sp_acl_region_rehash_intrvl_set(mlxsw_sp, ctx->val.vu32); +} + +static const struct devlink_param mlxsw_sp2_devlink_params[] = { + DEVLINK_PARAM_DRIVER(MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL, + "acl_region_rehash_interval", + DEVLINK_PARAM_TYPE_U32, + BIT(DEVLINK_PARAM_CMODE_RUNTIME), + mlxsw_sp_params_acl_region_rehash_intrvl_get, + mlxsw_sp_params_acl_region_rehash_intrvl_set, + NULL), +}; + +static int mlxsw_sp2_params_register(struct mlxsw_core *mlxsw_core) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_core); + union devlink_param_value value; + int err; + + err = mlxsw_sp_params_register(mlxsw_core); + if (err) + return err; + + err = devlink_params_register(devlink, mlxsw_sp2_devlink_params, + ARRAY_SIZE(mlxsw_sp2_devlink_params)); + if (err) + goto err_devlink_params_register; + + value.vu32 = 0; + devlink_param_driverinit_value_set(devlink, + MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL, + value); + return 0; + +err_devlink_params_register: + mlxsw_sp_params_unregister(mlxsw_core); + return err; +} + +static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core) +{ + devlink_params_unregister(priv_to_devlink(mlxsw_core), + mlxsw_sp2_devlink_params, + ARRAY_SIZE(mlxsw_sp2_devlink_params)); + mlxsw_sp_params_unregister(mlxsw_core); +} + static struct mlxsw_driver mlxsw_sp1_driver = { .kind = mlxsw_sp1_driver_name, .priv_size = sizeof(struct mlxsw_sp), @@ -4461,8 +4526,8 @@ static struct mlxsw_driver mlxsw_sp2_driver = { .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, .txhdr_construct = mlxsw_sp_txhdr_construct, .resources_register = mlxsw_sp2_resources_register, - .params_register = mlxsw_sp_params_register, - .params_unregister = mlxsw_sp_params_unregister, + .params_register = mlxsw_sp2_params_register, + .params_unregister = mlxsw_sp2_params_unregister, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sp2_config_profile, .res_query_enabled = true, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 3d17b4a368f4..ceebc91f4f1d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -690,6 +690,8 @@ struct mlxsw_sp_fid *mlxsw_sp_acl_dummy_fid(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_acl_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp); +u32 mlxsw_sp_acl_region_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp); +int mlxsw_sp_acl_region_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, u32 val); /* spectrum_acl_tcam.c */ struct mlxsw_sp_acl_tcam; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c index 38e027815393..a146a44634e9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c @@ -912,3 +912,19 @@ void mlxsw_sp_acl_fini(struct mlxsw_sp *mlxsw_sp) mlxsw_afk_destroy(acl->afk); kfree(acl); } + +u32 mlxsw_sp_acl_region_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp) +{ + struct mlxsw_sp_acl *acl = mlxsw_sp->acl; + + return mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(mlxsw_sp, + &acl->tcam); +} + +int mlxsw_sp_acl_region_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, u32 val) +{ + struct mlxsw_sp_acl *acl = mlxsw_sp->acl; + + return mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(mlxsw_sp, + &acl->tcam, val); +} diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 9239ff4e94c4..f2cb37c0d300 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -24,6 +24,7 @@ size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp) } #define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT 5000 /* ms */ +#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN 3000 /* ms */ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam) @@ -725,6 +726,41 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, kfree(vregion); } +u32 mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam *tcam) +{ + const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + u32 vregion_rehash_intrvl; + + if (WARN_ON(!ops->region_rehash_hints_get)) + return 0; + vregion_rehash_intrvl = tcam->vregion_rehash_intrvl; + return vregion_rehash_intrvl; +} + +int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam *tcam, + u32 val) +{ + const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + struct mlxsw_sp_acl_tcam_vregion *vregion; + + if (val < MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN && val) + return -EINVAL; + if (WARN_ON(!ops->region_rehash_hints_get)) + return -EOPNOTSUPP; + tcam->vregion_rehash_intrvl = val; + rtnl_lock(); + list_for_each_entry(vregion, &tcam->vregion_list, tlist) { + if (val) + mlxsw_core_schedule_dw(&vregion->rehash_dw, 0); + else + cancel_delayed_work_sync(&vregion->rehash_dw); + } + rtnl_unlock(); + return 0; +} + static int mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_group *group, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 440a3483ed7b..96bd42a9fbc3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -28,6 +28,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam); void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam); +u32 mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam *tcam); +int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam *tcam, + u32 val); int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_rule_info *rulei, u32 *priority, bool fillup_priority); -- cgit v1.2.3 From 3985de7260a7342a474a0792fcd23737341657ce Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 7 Feb 2019 11:22:55 +0000 Subject: mlxsw: spectrum_acl: Add couple of vregion rehash tracepoints As vregion rehash is happening in delayed work, add some visibility to the process using a few tracepoints. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 9 +++- include/trace/events/mlxsw.h | 61 ++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index f2cb37c0d300..7e225a86e3a8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "reg.h" #include "core.h" @@ -1175,6 +1176,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_region *region2, *unused_region; int err; + trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); + region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam, vregion, hints_priv); if (IS_ERR(region2)) @@ -1219,6 +1222,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, void *hints_priv; int err; + trace_mlxsw_sp_acl_tcam_vregion_rehash(mlxsw_sp, vregion); if (vregion->failed_rollback) return -EBUSY; @@ -1233,8 +1237,11 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, hints_priv); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); - if (vregion->failed_rollback) + if (vregion->failed_rollback) { + trace_mlxsw_sp_acl_tcam_vregion_rehash_dis(mlxsw_sp, + vregion); dev_err(mlxsw_sp->bus_info->dev, "Failed to rollback during vregion migration fail\n"); + } } ops->region_rehash_hints_put(hints_priv); diff --git a/include/trace/events/mlxsw.h b/include/trace/events/mlxsw.h index 6c2bafcade18..a5ce6df9dc49 100644 --- a/include/trace/events/mlxsw.h +++ b/include/trace/events/mlxsw.h @@ -11,6 +11,7 @@ struct mlxsw_sp; struct mlxsw_sp_acl_atcam_region; +struct mlxsw_sp_acl_tcam_vregion; TRACE_EVENT(mlxsw_sp_acl_atcam_entry_add_ctcam_spill, TP_PROTO(const struct mlxsw_sp *mlxsw_sp, @@ -32,6 +33,66 @@ TRACE_EVENT(mlxsw_sp_acl_atcam_entry_add_ctcam_spill, __entry->mlxsw_sp, __entry->aregion) ); +TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_rehash, + TP_PROTO(const struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_acl_tcam_vregion *vregion), + + TP_ARGS(mlxsw_sp, vregion), + + TP_STRUCT__entry( + __field(const void *, mlxsw_sp) + __field(const void *, vregion) + ), + + TP_fast_assign( + __entry->mlxsw_sp = mlxsw_sp; + __entry->vregion = vregion; + ), + + TP_printk("mlxsw_sp %p, vregion %p", + __entry->mlxsw_sp, __entry->vregion) +); + +TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_migrate, + TP_PROTO(const struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_acl_tcam_vregion *vregion), + + TP_ARGS(mlxsw_sp, vregion), + + TP_STRUCT__entry( + __field(const void *, mlxsw_sp) + __field(const void *, vregion) + ), + + TP_fast_assign( + __entry->mlxsw_sp = mlxsw_sp; + __entry->vregion = vregion; + ), + + TP_printk("mlxsw_sp %p, vregion %p", + __entry->mlxsw_sp, __entry->vregion) +); + +TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_rehash_dis, + TP_PROTO(const struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_acl_tcam_vregion *vregion), + + TP_ARGS(mlxsw_sp, vregion), + + TP_STRUCT__entry( + __field(const void *, mlxsw_sp) + __field(const void *, vregion) + ), + + TP_fast_assign( + __entry->mlxsw_sp = mlxsw_sp; + __entry->vregion = vregion; + ), + + TP_printk("mlxsw_sp %p, vregion %p", + __entry->mlxsw_sp, __entry->vregion) +); + #endif /* _MLXSW_TRACEPOINT_H */ /* This part must be outside protection */ -- cgit v1.2.3 From 3e3e0cdfca483064982329cda07394abff653dd0 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 6 Feb 2019 18:56:10 +0100 Subject: net: macb: add sam9x60-macb compatibility string Add a new compatibility string for this product. It's using at91sam9260-macb layout but has a newer hardware revision: it's safer to use its own string. Signed-off-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 2b2882615e8b..eaabe8c278ec 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3943,6 +3943,7 @@ static const struct of_device_id macb_dt_ids[] = { { .compatible = "cdns,np4-macb", .data = &np4_config }, { .compatible = "cdns,pc302-gem", .data = &pc302gem_config }, { .compatible = "cdns,gem", .data = &pc302gem_config }, + { .compatible = "cdns,sam9x60-macb", .data = &at91sam9260_config }, { .compatible = "atmel,sama5d2-gem", .data = &sama5d2_config }, { .compatible = "atmel,sama5d3-gem", .data = &sama5d3_config }, { .compatible = "atmel,sama5d3-macb", .data = &sama5d3macb_config }, -- cgit v1.2.3 From 93c0970493c71f264e6c3c7caf1ff24a9e1de786 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 6 Feb 2019 19:39:52 +0100 Subject: net: phy: consider latched link-down status in polling mode The link status value latches link-down events. To get the current status we read the register twice in genphy_update_link(). There's a potential risk that we miss a link-down event in polling mode. This may cause issues if the user e.g. connects his machine to a different network. On the other hand reading the latched value may cause issues in interrupt mode. Following scenario: - After boot link goes up - phy_start() is called triggering an aneg restart, hence link goes down and link-down info is latched. - After aneg has finished link goes up and triggers an interrupt. Interrupt handler reads link status, means it reads the latched "link is down" info. But there won't be another interrupt as long as link stays up, therefore phylib will never recognize that link is up. Deal with both scenarios by reading the register twice in interrupt mode only. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 10 ++++++++-- drivers/net/phy/phy_device.c | 13 +++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 6adfe1f6319e..706a92a8c1b2 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -141,9 +141,15 @@ int genphy_c45_read_link(struct phy_device *phydev) mmd_mask &= ~BIT(devad); /* The link state is latched low so that momentary link - * drops can be detected. Do not double-read the status - * register if the link is down. + * drops can be detected. Do not double-read the status + * in polling mode to detect such short link drops. */ + if (!phy_polling_mode(phydev)) { + val = phy_read_mmd(phydev, devad, MDIO_STAT1); + if (val < 0) + return val; + } + val = phy_read_mmd(phydev, devad, MDIO_STAT1); if (val < 0) return val; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 891e0178b97f..d490cd2a8962 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1729,10 +1729,15 @@ int genphy_update_link(struct phy_device *phydev) { int status; - /* Do a fake read */ - status = phy_read(phydev, MII_BMSR); - if (status < 0) - return status; + /* The link state is latched low so that momentary link + * drops can be detected. Do not double-read the status + * in polling mode to detect such short link drops. + */ + if (!phy_polling_mode(phydev)) { + status = phy_read(phydev, MII_BMSR); + if (status < 0) + return status; + } /* Read link and autonegotiation status */ status = phy_read(phydev, MII_BMSR); -- cgit v1.2.3 From 1f03f2609f3d76622389ae5b60a7c692a47bcc1b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 12:45:57 -0800 Subject: net: dsa: bcm_sf2: Remove stats mutex We no longer need a dedicated statistics mutex since we leverage b53_common for statistics now. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 1 - drivers/net/dsa/bcm_sf2.h | 3 --- 2 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 361fbde76654..a97b18595be9 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -1062,7 +1062,6 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, priv); spin_lock_init(&priv->indir_lock); - mutex_init(&priv->stats_mutex); mutex_init(&priv->cfp.lock); INIT_LIST_HEAD(&priv->cfp.rules_list); diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index faaef320ec48..83e1d8001447 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -87,9 +87,6 @@ struct bcm_sf2_priv { /* Backing b53_device */ struct b53_device *dev; - /* Mutex protecting access to the MIB counters */ - struct mutex stats_mutex; - struct bcm_sf2_hw_params hw_params; struct bcm_sf2_port_status port_sts[DSA_MAX_PORTS]; -- cgit v1.2.3 From badd62c249f3ef2d5af315ac2666256492e0af49 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 12:45:58 -0800 Subject: net: dsa: bcm_sf2: Prepare for adding CFP statistics In preparation for adding CFP statistics, we will need to overlay the standard B53 statistics, so create specific bcm_sf2_sw_* functions to call into their b53_common.c counterpart. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index a97b18595be9..ce5f4260ea1a 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -894,12 +894,30 @@ static const struct b53_io_ops bcm_sf2_io_ops = { .write64 = bcm_sf2_core_write64, }; +static void bcm_sf2_sw_get_strings(struct dsa_switch *ds, int port, + u32 stringset, uint8_t *data) +{ + b53_get_strings(ds, port, stringset, data); +} + +static void bcm_sf2_sw_get_ethtool_stats(struct dsa_switch *ds, int port, + uint64_t *data) +{ + b53_get_ethtool_stats(ds, port, data); +} + +static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds, int port, + int sset) +{ + return b53_get_sset_count(ds, port, sset); +} + static const struct dsa_switch_ops bcm_sf2_ops = { .get_tag_protocol = b53_get_tag_protocol, .setup = bcm_sf2_sw_setup, - .get_strings = b53_get_strings, - .get_ethtool_stats = b53_get_ethtool_stats, - .get_sset_count = b53_get_sset_count, + .get_strings = bcm_sf2_sw_get_strings, + .get_ethtool_stats = bcm_sf2_sw_get_ethtool_stats, + .get_sset_count = bcm_sf2_sw_get_sset_count, .get_ethtool_phy_stats = b53_get_ethtool_phy_stats, .get_phy_flags = bcm_sf2_sw_get_phy_flags, .phylink_validate = bcm_sf2_sw_validate, -- cgit v1.2.3 From f4ae9c0840b7e1f9bd2177189a45a21e6f11aa8d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 12:45:59 -0800 Subject: net: dsa: bcm_sf2: Add support for CFP statistics Return CFP policer statistics (Green, Yellow or Red) as part of the standard ethtool statistics. This helps debug when CFP rules may not be hit (0 counter). Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 16 +++++++- drivers/net/dsa/bcm_sf2.h | 5 +++ drivers/net/dsa/bcm_sf2_cfp.c | 88 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/bcm_sf2_regs.h | 4 ++ 4 files changed, 112 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index ce5f4260ea1a..5193da67dcdc 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -897,19 +897,33 @@ static const struct b53_io_ops bcm_sf2_io_ops = { static void bcm_sf2_sw_get_strings(struct dsa_switch *ds, int port, u32 stringset, uint8_t *data) { + int cnt = b53_get_sset_count(ds, port, stringset); + b53_get_strings(ds, port, stringset, data); + bcm_sf2_cfp_get_strings(ds, port, stringset, + data + cnt * ETH_GSTRING_LEN); } static void bcm_sf2_sw_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) { + int cnt = b53_get_sset_count(ds, port, ETH_SS_STATS); + b53_get_ethtool_stats(ds, port, data); + bcm_sf2_cfp_get_ethtool_stats(ds, port, data + cnt); } static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds, int port, int sset) { - return b53_get_sset_count(ds, port, sset); + int cnt = b53_get_sset_count(ds, port, sset); + + if (cnt < 0) + return cnt; + + cnt += bcm_sf2_cfp_get_sset_count(ds, port, sset); + + return cnt; } static const struct dsa_switch_ops bcm_sf2_ops = { diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index 83e1d8001447..eb3655bea467 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -213,5 +213,10 @@ int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port, int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv); void bcm_sf2_cfp_exit(struct dsa_switch *ds); int bcm_sf2_cfp_resume(struct dsa_switch *ds); +void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port, + u32 stringset, uint8_t *data); +void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port, + uint64_t *data); +int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset); #endif /* __BCM_SF2_H */ diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c index 6d8059dc77b7..8747d18297fa 100644 --- a/drivers/net/dsa/bcm_sf2_cfp.c +++ b/drivers/net/dsa/bcm_sf2_cfp.c @@ -1201,3 +1201,91 @@ int bcm_sf2_cfp_resume(struct dsa_switch *ds) return ret; } + +static const struct bcm_sf2_cfp_stat { + unsigned int offset; + unsigned int ram_loc; + const char *name; +} bcm_sf2_cfp_stats[] = { + { + .offset = CORE_STAT_GREEN_CNTR, + .ram_loc = GREEN_STAT_RAM, + .name = "Green" + }, + { + .offset = CORE_STAT_YELLOW_CNTR, + .ram_loc = YELLOW_STAT_RAM, + .name = "Yellow" + }, + { + .offset = CORE_STAT_RED_CNTR, + .ram_loc = RED_STAT_RAM, + .name = "Red" + }, +}; + +void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port, + u32 stringset, uint8_t *data) +{ + struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); + unsigned int s = ARRAY_SIZE(bcm_sf2_cfp_stats); + char buf[ETH_GSTRING_LEN]; + unsigned int i, j, iter; + + if (stringset != ETH_SS_STATS) + return; + + for (i = 1; i < priv->num_cfp_rules; i++) { + for (j = 0; j < s; j++) { + snprintf(buf, sizeof(buf), + "CFP%03d_%sCntr", + i, bcm_sf2_cfp_stats[j].name); + iter = (i - 1) * s + j; + strlcpy(data + iter * ETH_GSTRING_LEN, + buf, ETH_GSTRING_LEN); + } + } +} + +void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port, + uint64_t *data) +{ + struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); + unsigned int s = ARRAY_SIZE(bcm_sf2_cfp_stats); + const struct bcm_sf2_cfp_stat *stat; + unsigned int i, j, iter; + struct cfp_rule *rule; + int ret; + + mutex_lock(&priv->cfp.lock); + for (i = 1; i < priv->num_cfp_rules; i++) { + rule = bcm_sf2_cfp_rule_find(priv, port, i); + if (!rule) + continue; + + for (j = 0; j < s; j++) { + stat = &bcm_sf2_cfp_stats[j]; + + bcm_sf2_cfp_rule_addr_set(priv, i); + ret = bcm_sf2_cfp_op(priv, stat->ram_loc | OP_SEL_READ); + if (ret) + continue; + + iter = (i - 1) * s + j; + data[iter] = core_readl(priv, stat->offset); + } + + } + mutex_unlock(&priv->cfp.lock); +} + +int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset) +{ + struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); + + if (sset != ETH_SS_STATS) + return 0; + + /* 3 counters per CFP rules */ + return (priv->num_cfp_rules - 1) * ARRAY_SIZE(bcm_sf2_cfp_stats); +} diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h index 0a1e530d52b7..67f056206f37 100644 --- a/drivers/net/dsa/bcm_sf2_regs.h +++ b/drivers/net/dsa/bcm_sf2_regs.h @@ -400,6 +400,10 @@ enum bcm_sf2_reg_offs { #define CORE_RATE_METER6 0x281e0 #define CIR_REF_CNT_MASK 0x7ffff +#define CORE_STAT_GREEN_CNTR 0x28200 +#define CORE_STAT_YELLOW_CNTR 0x28210 +#define CORE_STAT_RED_CNTR 0x28220 + #define CORE_CFP_CTL_REG 0x28400 #define CFP_EN_MAP_MASK 0x1ff -- cgit v1.2.3 From db78ed2737b8607744623ba75bd477da8ad8a3cf Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 6 Feb 2019 12:46:00 -0800 Subject: net: dsa: bcm_sf2: Allow looping back CFP rules When the source and destination port of a CFP rule match, we must set the loopback bit enable to allow that, otherwise the frame is discarded. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2_cfp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c index 8747d18297fa..0b9ca4bdf47e 100644 --- a/drivers/net/dsa/bcm_sf2_cfp.c +++ b/drivers/net/dsa/bcm_sf2_cfp.c @@ -213,6 +213,7 @@ static inline unsigned int bcm_sf2_cfp_rule_size(struct bcm_sf2_priv *priv) static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv, unsigned int rule_index, + int src_port, unsigned int port_num, unsigned int queue_num, bool fwd_map_change) @@ -230,6 +231,10 @@ static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv, else reg = 0; + /* Enable looping back to the original port */ + if (src_port == port_num) + reg |= LOOP_BK_EN; + core_writel(priv, reg, CORE_ACT_POL_DATA0); /* Set classification ID that needs to be put in Broadcom tag */ @@ -443,7 +448,7 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, } /* Insert into Action and policer RAMs now */ - ret = bcm_sf2_cfp_act_pol_set(priv, rule_index, port_num, + ret = bcm_sf2_cfp_act_pol_set(priv, rule_index, port, port_num, queue_num, true); if (ret) goto out_err_flow_rule; @@ -733,7 +738,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, } /* Insert into Action and policer RAMs now */ - ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port_num, + ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port, port_num, queue_num, false); if (ret) goto out_err_flow_rule; @@ -795,7 +800,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, /* Insert into Action and policer RAMs now, set chain ID to * the one we are chained to */ - ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port_num, + ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port, port_num, queue_num, true); if (ret) goto out_err_flow_rule; -- cgit v1.2.3 From df9c716deb76642d0077770bca7107a31568c113 Mon Sep 17 00:00:00 2001 From: Sudarsana Reddy Kalluru Date: Thu, 7 Feb 2019 06:20:11 -0800 Subject: qed: Add API for SmartAN query. The patch adds driver interface to read the SmartAN capability from management firmware. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_hsi.h | 1 + drivers/net/ethernet/qlogic/qed/qed_main.c | 2 ++ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 6 ++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.h | 10 ++++++++++ include/linux/qed/qed_if.h | 1 + 5 files changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 417121e74ee9..37edaa847512 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -12796,6 +12796,7 @@ struct public_drv_mb { #define FW_MB_PARAM_GET_PF_RDMA_BOTH 0x3 /* get MFW feature support response */ +#define FW_MB_PARAM_FEATURE_SUPPORT_SMARTLINQ 0x00000001 #define FW_MB_PARAM_FEATURE_SUPPORT_EEE 0x00000002 #define FW_MB_PARAM_FEATURE_SUPPORT_VLINK 0x00010000 diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index b47352643fb5..f164d4acebcb 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -281,6 +281,8 @@ int qed_fill_dev_info(struct qed_dev *cdev, if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME) dev_info->wol_support = true; + dev_info->smart_an = qed_mcp_is_smart_an_supported(p_hwfn); + dev_info->abs_pf_id = QED_LEADING_HWFN(cdev)->abs_pf_id; } else { qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major, diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index bb8541847aa5..cc27fd60d689 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -3654,6 +3654,12 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock, } } +bool qed_mcp_is_smart_an_supported(struct qed_hwfn *p_hwfn) +{ + return !!(p_hwfn->mcp_info->capabilities & + FW_MB_PARAM_FEATURE_SUPPORT_SMARTLINQ); +} + int qed_mcp_get_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { u32 mcp_resp; diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 6e1d72a669ae..2799e6741765 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -1148,6 +1148,16 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock, struct qed_resc_unlock_params *p_unlock, enum qed_resc_lock resource, bool b_is_permanent); + +/** + * @brief - Return whether management firmware support smart AN + * + * @param p_hwfn + * + * @return bool - true if feature is supported. + */ +bool qed_mcp_is_smart_an_supported(struct qed_hwfn *p_hwfn); + /** * @brief Learn of supported MFW features; To be done during early init * diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index 35170f74ed80..f6165d304b4d 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h @@ -643,6 +643,7 @@ struct qed_dev_info { u16 mtu; bool wol_support; + bool smart_an; /* MBI version */ u32 mbi_version; -- cgit v1.2.3 From f15cff0438d2b44f532e476fff45672a830eaaa7 Mon Sep 17 00:00:00 2001 From: Sudarsana Reddy Kalluru Date: Thu, 7 Feb 2019 06:20:12 -0800 Subject: qede: Add ethtool interface for SmartAN query. The patch adds driver support to query SmartAN capability via ethtool. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Ariel Elior Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index 16331c6c6fa7..c6238083e898 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -186,11 +186,13 @@ static const struct { enum { QEDE_PRI_FLAG_CMT, + QEDE_PRI_FLAG_SMART_AN_SUPPORT, /* MFW supports SmartAN */ QEDE_PRI_FLAG_LEN, }; static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = { "Coupled-Function", + "SmartAN capable", }; enum qede_ethtool_tests { @@ -404,8 +406,15 @@ static int qede_get_sset_count(struct net_device *dev, int stringset) static u32 qede_get_priv_flags(struct net_device *dev) { struct qede_dev *edev = netdev_priv(dev); + u32 flags = 0; - return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT; + if (edev->dev_info.common.num_hwfns > 1) + flags |= BIT(QEDE_PRI_FLAG_CMT); + + if (edev->dev_info.common.smart_an) + flags |= BIT(QEDE_PRI_FLAG_SMART_AN_SUPPORT); + + return flags; } struct qede_link_mode_mapping { -- cgit v1.2.3 From fd6d122678054fb10582143de1922e5dab11b1d8 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 21:13:13 -0600 Subject: net: usb: cdc-phonet: use struct_size() in alloc_netdev() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = alloc(sizeof(struct foo) + count * sizeof(void *)); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = alloc(struct_size(instance, entry, count)); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/usb/cdc-phonet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 78b16eb9e58c..63aaae487995 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -361,8 +361,8 @@ static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *i else return -EINVAL; - dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size, - ifname, NET_NAME_UNKNOWN, usbpn_setup); + dev = alloc_netdev(struct_size(pnd, urbs, rxq_size), ifname, + NET_NAME_UNKNOWN, usbpn_setup); if (!dev) return -ENOMEM; -- cgit v1.2.3 From a3deec5b3f13b9807bbf2522b4779e4c07cbad66 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 21:16:48 -0600 Subject: wan: wanxl: use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; size = sizeof(struct foo) + count * sizeof(struct boo); instance = alloc(size, GFP_KERNEL) Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = alloc(struct_size(instance, entry, count), GFP_KERNEL) Notice that, in this case, variable alloc_size is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/wan/wanxl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index d573a57bc301..459ce52a0a4d 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -565,7 +565,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev, u32 plx_phy; /* PLX PCI base address */ u32 mem_phy; /* memory PCI base addr */ u8 __iomem *mem; /* memory virtual base addr */ - int i, ports, alloc_size; + int i, ports; #ifndef MODULE pr_info_once("%s\n", version); @@ -601,8 +601,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev, default: ports = 4; } - alloc_size = sizeof(struct card) + ports * sizeof(struct port); - card = kzalloc(alloc_size, GFP_KERNEL); + card = kzalloc(struct_size(card, ports, ports), GFP_KERNEL); if (card == NULL) { pci_release_regions(pdev); pci_disable_device(pdev); -- cgit v1.2.3 From 13644be211bfd9e4685425c5adf7430a04768a06 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 21:22:17 -0600 Subject: wimax/i2400m: use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; size = sizeof(struct foo) + count * sizeof(void *); instance = alloc(size, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: size = struct_size(instance, entry, count); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index 0b602951ff6b..d28b96d06919 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c @@ -1260,8 +1260,8 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) goto error_msg_hdr_check; result = -EIO; num_pls = le16_to_cpu(msg_hdr->num_pls); - pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */ - num_pls * sizeof(msg_hdr->pld[0]); + /* Check payload descriptor(s) */ + pl_itr = struct_size(msg_hdr, pld, num_pls); pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN); if (pl_itr > skb_len) { /* got all the payload descriptors? */ dev_err(dev, "RX: HW BUG? message too short (%u bytes) for " -- cgit v1.2.3 From 370600afdd2e33665c84d06f34e7c223d5379b4a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 21:29:10 -0600 Subject: bnx2x: Use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; size = sizeof(struct foo) + count * sizeof(struct boo); instance = kzalloc(size, GFP_KERNEL) Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL) Notice that, in this case, variable fsz is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c index 8e0a317b31f7..a9bdc21873d3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c @@ -1654,13 +1654,9 @@ static int bnx2x_vf_mbx_macvlan_list(struct bnx2x *bp, { int i, j; struct bnx2x_vf_mac_vlan_filters *fl = NULL; - size_t fsz; - fsz = tlv->n_mac_vlan_filters * - sizeof(struct bnx2x_vf_mac_vlan_filter) + - sizeof(struct bnx2x_vf_mac_vlan_filters); - - fl = kzalloc(fsz, GFP_KERNEL); + fl = kzalloc(struct_size(fl, filters, tlv->n_mac_vlan_filters), + GFP_KERNEL); if (!fl) return -ENOMEM; -- cgit v1.2.3 From 9e475293cd40fc9c14de63c53b5754f06007059d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 21:42:41 -0600 Subject: mlxsw: spectrum_router: Use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; size = sizeof(struct foo) + count * sizeof(struct boo); instance = kzalloc(size, GFP_KERNEL) Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL) Notice that, in this case, variable alloc_size is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 6754061d9b72..818040ce4d68 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -3814,13 +3814,11 @@ mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi) struct mlxsw_sp_nexthop_group *nh_grp; struct mlxsw_sp_nexthop *nh; struct fib_nh *fib_nh; - size_t alloc_size; int i; int err; - alloc_size = sizeof(*nh_grp) + - fi->fib_nhs * sizeof(struct mlxsw_sp_nexthop); - nh_grp = kzalloc(alloc_size, GFP_KERNEL); + nh_grp = kzalloc(struct_size(nh_grp, nexthops, fi->fib_nhs), + GFP_KERNEL); if (!nh_grp) return ERR_PTR(-ENOMEM); nh_grp->priv = fi; @@ -5066,13 +5064,11 @@ mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_nexthop_group *nh_grp; struct mlxsw_sp_rt6 *mlxsw_sp_rt6; struct mlxsw_sp_nexthop *nh; - size_t alloc_size; int i = 0; int err; - alloc_size = sizeof(*nh_grp) + - fib6_entry->nrt6 * sizeof(struct mlxsw_sp_nexthop); - nh_grp = kzalloc(alloc_size, GFP_KERNEL); + nh_grp = kzalloc(struct_size(nh_grp, nexthops, fib6_entry->nrt6), + GFP_KERNEL); if (!nh_grp) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&nh_grp->fib_list); -- cgit v1.2.3 From af6f12f22b141d755876ab95635619166b1c574e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 21:47:25 -0600 Subject: nfp: flower: cmsg: use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; size = sizeof(struct foo) + count * sizeof(void *); instance = alloc(size, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = alloc(struct_size(instance, entry, count), GFP_KERNEL); Notice that, in this case, variable size is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c index 56b22ea32474..cf9e1118ee8f 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c @@ -45,11 +45,9 @@ nfp_flower_cmsg_mac_repr_start(struct nfp_app *app, unsigned int num_ports) { struct nfp_flower_cmsg_mac_repr *msg; struct sk_buff *skb; - unsigned int size; - size = sizeof(*msg) + num_ports * sizeof(msg->ports[0]); - skb = nfp_flower_cmsg_alloc(app, size, NFP_FLOWER_CMSG_TYPE_MAC_REPR, - GFP_KERNEL); + skb = nfp_flower_cmsg_alloc(app, struct_size(msg, ports, num_ports), + NFP_FLOWER_CMSG_TYPE_MAC_REPR, GFP_KERNEL); if (!skb) return NULL; -- cgit v1.2.3 From 9a00536c38e9df8b6d942316888990d849fe1d01 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 21:55:37 -0600 Subject: fm10k: use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; size = sizeof(struct foo) + count * sizeof(struct boo); instance = kzalloc(size, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); Notice that, in this case, variable size is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 6fd15a734324..5a0419421511 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1603,14 +1603,12 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface, { struct fm10k_q_vector *q_vector; struct fm10k_ring *ring; - int ring_count, size; + int ring_count; ring_count = txr_count + rxr_count; - size = sizeof(struct fm10k_q_vector) + - (sizeof(struct fm10k_ring) * ring_count); /* allocate q_vector and rings */ - q_vector = kzalloc(size, GFP_KERNEL); + q_vector = kzalloc(struct_size(q_vector, ring, ring_count), GFP_KERNEL); if (!q_vector) return -ENOMEM; -- cgit v1.2.3 From c397ab21ba362d5c5215e53f36685a9fffc45f66 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 7 Feb 2019 20:22:20 +0100 Subject: net: phy: don't double-read link status register if link is up The link status register latches link-down events. Therefore, if link is reported as being up, there's no need for a second read. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 2 ++ drivers/net/phy/phy_device.c | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 706a92a8c1b2..eff9e5a4d831 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -148,6 +148,8 @@ int genphy_c45_read_link(struct phy_device *phydev) val = phy_read_mmd(phydev, devad, MDIO_STAT1); if (val < 0) return val; + else if (val & MDIO_STAT1_LSTATUS) + continue; } val = phy_read_mmd(phydev, devad, MDIO_STAT1); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index d490cd2a8962..9369e1323c39 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1735,8 +1735,12 @@ int genphy_update_link(struct phy_device *phydev) */ if (!phy_polling_mode(phydev)) { status = phy_read(phydev, MII_BMSR); - if (status < 0) + if (status < 0) { return status; + } else if (status & BMSR_LSTATUS) { + phydev->link = 1; + return 0; + } } /* Read link and autonegotiation status */ -- cgit v1.2.3 From a0feac18b8b590d9b588b4285841bac7c372fd8b Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 22:15:40 -0600 Subject: igb: use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; size = sizeof(struct foo) + count * sizeof(struct boo); instance = alloc(size, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: size = struct_size(instance, entry, count); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/igb/igb_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 6d812e96572d..69b230c53fed 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -1189,15 +1189,15 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter, { struct igb_q_vector *q_vector; struct igb_ring *ring; - int ring_count, size; + int ring_count; + size_t size; /* igb only supports 1 Tx and/or 1 Rx queue per vector */ if (txr_count > 1 || rxr_count > 1) return -ENOMEM; ring_count = txr_count + rxr_count; - size = sizeof(struct igb_q_vector) + - (sizeof(struct igb_ring) * ring_count); + size = struct_size(q_vector, ring, ring_count); /* allocate q_vector and rings */ q_vector = adapter->q_vector[v_idx]; -- cgit v1.2.3 From 196d7311fab5941b1bc883471c7f46350fa1a797 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 22:19:45 -0600 Subject: igc: Use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; size = sizeof(struct foo) + count * sizeof(struct boo); instance = kzalloc(size, GFP_KERNEL) Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL) Notice that, in this case, variable size is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/igc/igc_main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 11c75433fe22..87a11879bf2d 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -2958,22 +2958,21 @@ static int igc_alloc_q_vector(struct igc_adapter *adapter, { struct igc_q_vector *q_vector; struct igc_ring *ring; - int ring_count, size; + int ring_count; /* igc only supports 1 Tx and/or 1 Rx queue per vector */ if (txr_count > 1 || rxr_count > 1) return -ENOMEM; ring_count = txr_count + rxr_count; - size = sizeof(struct igc_q_vector) + - (sizeof(struct igc_ring) * ring_count); /* allocate q_vector and rings */ q_vector = adapter->q_vector[v_idx]; if (!q_vector) - q_vector = kzalloc(size, GFP_KERNEL); + q_vector = kzalloc(struct_size(q_vector, ring, ring_count), + GFP_KERNEL); else - memset(q_vector, 0, size); + memset(q_vector, 0, struct_size(q_vector, ring, ring_count)); if (!q_vector) return -ENOMEM; -- cgit v1.2.3 From 439bb9edd430f606cce80b791307190ba23f7266 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 7 Feb 2019 22:22:58 -0600 Subject: ixgbe: Use struct_size() helper One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; size = sizeof(struct foo) + count * sizeof(struct boo); instance = kzalloc(size, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); Notice that, in this case, variable size is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index 62e6499e4146..cc3196ae5aea 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -836,12 +836,10 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, struct ixgbe_ring *ring; int node = NUMA_NO_NODE; int cpu = -1; - int ring_count, size; + int ring_count; u8 tcs = adapter->hw_tcs; ring_count = txr_count + rxr_count + xdp_count; - size = sizeof(struct ixgbe_q_vector) + - (sizeof(struct ixgbe_ring) * ring_count); /* customize cpu for Flow Director mapping */ if ((tcs <= 1) && !(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) { @@ -855,9 +853,11 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, } /* allocate q_vector and rings */ - q_vector = kzalloc_node(size, GFP_KERNEL, node); + q_vector = kzalloc_node(struct_size(q_vector, ring, ring_count), + GFP_KERNEL, node); if (!q_vector) - q_vector = kzalloc(size, GFP_KERNEL); + q_vector = kzalloc(struct_size(q_vector, ring, ring_count), + GFP_KERNEL); if (!q_vector) return -ENOMEM; -- cgit v1.2.3 From 388ca27ffd21c6b31d6378d4b24b7c49066848a0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Feb 2019 15:35:38 +0000 Subject: net: marvell: mvpp2: phylink compliance updates Sven Auhagen reported issues with negotiation on a couple of his platforms using a mixture of SFP and PHYs in various different modes. Debugging to root cause proved difficult, but essentially the problem comes down to the mvpp2 phylink implementation being slightly at odds with what is expected. phylink operates in three modes: phy, fixed-link, and in-band mode. In the first two modes, the expected behaviour from a MAC driver is that phylink resolves the operating mode and passes the mode to the MAC driver for it to program, including when the link should be brought up or taken down. This is basically the same as the libphy approach. This does not negate the requirement to advertise a correct control word for interface modes that have control words where that can be reasonably controlled. The second mode is in-band mode, where the MAC is expected to use the in-band control word to determine the operating mode. The mvneta driver implements the correct pattern required to support this: configure the port interface type separately from the in-band mode(s). This is now specified in the phylink documentation patches. mvpp2 was programming in-band mode for SGMII and the 802.3z modes no what, and avoided forcing the link up in fixed/phy modes. This caused a problem with some boards where the PHY is by default programmed to enter AN bypass mode, the PHY would report that the link was up, but the mvpp2 never completed the exchange of control word. Another issue that mvpp2 has is it sets SGMII AN format control word for both SGMII and 802.3z modes. The format of the control word is defined by MVPP2_GMAC_INBAND_AN_MASK, which should be set for SGMII and clear for 802.3z. Available Marvell documentation for earlier GMAC implementations does not make this clear, but this has been ascertained via extensive testing on earlier GMAC implementations, and then confirmed with a Macchiatobin Single Shot connected to a Clearfog: when MVPP2_GMAC_INBAND_AN_MASK is set, the clearfog does not receive the advertised pause mode settings. Lastly, there is no flow control in the in-band control word in Cisco SGMII, setting the flow control autonegotiation bit even with a PHY that has the Marvell extension to send this information does not result in the flow control being enabled at the MAC. We need to do this manually using the information provided via phylink. Re-code mvpp2's mac_config() and mac_link_up() to follow this pattern. This allows Sven Auhagen's board and Macchiatobin to reliably bring the link up with the 88e1512 PHY with phylink operating in PHY mode with COMPHY built as a module but the rest of the networking built-in, and u-boot having brought up the interface. in-band mode requires an additional patch to resolve another problem. Tested-by: Sven Auhagen Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 97 ++++++++++++++++--------- 1 file changed, 61 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 5c0c26fd8363..f16ba7817f62 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4557,58 +4557,84 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, an &= ~(MVPP2_GMAC_CONFIG_MII_SPEED | MVPP2_GMAC_CONFIG_GMII_SPEED | MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_FC_ADV_EN | MVPP2_GMAC_FC_ADV_ASM_EN | MVPP2_GMAC_FLOW_CTRL_AUTONEG | - MVPP2_GMAC_CONFIG_FULL_DUPLEX | MVPP2_GMAC_AN_DUPLEX_EN | - MVPP2_GMAC_FORCE_LINK_DOWN); + MVPP2_GMAC_CONFIG_FULL_DUPLEX | MVPP2_GMAC_AN_DUPLEX_EN); ctrl0 &= ~MVPP2_GMAC_PORT_TYPE_MASK; - ctrl2 &= ~(MVPP2_GMAC_PORT_RESET_MASK | MVPP2_GMAC_PCS_ENABLE_MASK); + ctrl2 &= ~(MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PORT_RESET_MASK | + MVPP2_GMAC_PCS_ENABLE_MASK); + ctrl4 &= ~(MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN); + /* Configure port type */ if (phy_interface_mode_is_8023z(state->interface)) { - /* 1000BaseX and 2500BaseX ports cannot negotiate speed nor can - * they negotiate duplex: they are always operating with a fixed - * speed of 1000/2500Mbps in full duplex, so force 1000/2500 - * speed and full duplex here. - */ - ctrl0 |= MVPP2_GMAC_PORT_TYPE_MASK; - an |= MVPP2_GMAC_CONFIG_GMII_SPEED | - MVPP2_GMAC_CONFIG_FULL_DUPLEX; - } else if (!phy_interface_mode_is_rgmii(state->interface)) { - an |= MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_FLOW_CTRL_AUTONEG; + ctrl2 |= MVPP2_GMAC_PCS_ENABLE_MASK; + ctrl4 &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL; + ctrl4 |= MVPP22_CTRL4_SYNC_BYPASS_DIS | + MVPP22_CTRL4_DP_CLK_SEL | + MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE; + } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { + ctrl2 |= MVPP2_GMAC_PCS_ENABLE_MASK | MVPP2_GMAC_INBAND_AN_MASK; + ctrl4 &= ~MVPP22_CTRL4_EXT_PIN_GMII_SEL; + ctrl4 |= MVPP22_CTRL4_SYNC_BYPASS_DIS | + MVPP22_CTRL4_DP_CLK_SEL | + MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE; + } else if (phy_interface_mode_is_rgmii(state->interface)) { + ctrl4 &= ~MVPP22_CTRL4_DP_CLK_SEL; + ctrl4 |= MVPP22_CTRL4_EXT_PIN_GMII_SEL | + MVPP22_CTRL4_SYNC_BYPASS_DIS | + MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE; } - if (state->duplex) - an |= MVPP2_GMAC_CONFIG_FULL_DUPLEX; + /* Configure advertisement bits */ if (phylink_test(state->advertising, Pause)) an |= MVPP2_GMAC_FC_ADV_EN; if (phylink_test(state->advertising, Asym_Pause)) an |= MVPP2_GMAC_FC_ADV_ASM_EN; - if (phy_interface_mode_is_8023z(state->interface) || - state->interface == PHY_INTERFACE_MODE_SGMII) { - an |= MVPP2_GMAC_IN_BAND_AUTONEG; - ctrl2 |= MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PCS_ENABLE_MASK; + /* Configure negotiation style */ + if (!phylink_autoneg_inband(mode)) { + /* Phy or fixed speed - no in-band AN */ + if (state->duplex) + an |= MVPP2_GMAC_CONFIG_FULL_DUPLEX; - ctrl4 &= ~(MVPP22_CTRL4_EXT_PIN_GMII_SEL | - MVPP22_CTRL4_RX_FC_EN | MVPP22_CTRL4_TX_FC_EN); - ctrl4 |= MVPP22_CTRL4_SYNC_BYPASS_DIS | - MVPP22_CTRL4_DP_CLK_SEL | - MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE; + if (state->speed == SPEED_1000 || state->speed == SPEED_2500) + an |= MVPP2_GMAC_CONFIG_GMII_SPEED; + else if (state->speed == SPEED_100) + an |= MVPP2_GMAC_CONFIG_MII_SPEED; if (state->pause & MLO_PAUSE_TX) ctrl4 |= MVPP22_CTRL4_TX_FC_EN; if (state->pause & MLO_PAUSE_RX) ctrl4 |= MVPP22_CTRL4_RX_FC_EN; - } else if (phy_interface_mode_is_rgmii(state->interface)) { - an |= MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS; + } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { + /* SGMII in-band mode receives the speed and duplex from + * the PHY. Flow control information is not received. */ + an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN | MVPP2_GMAC_FORCE_LINK_PASS); + an |= MVPP2_GMAC_IN_BAND_AUTONEG | + MVPP2_GMAC_AN_SPEED_EN | + MVPP2_GMAC_AN_DUPLEX_EN; - if (state->speed == SPEED_1000) - an |= MVPP2_GMAC_CONFIG_GMII_SPEED; - else if (state->speed == SPEED_100) - an |= MVPP2_GMAC_CONFIG_MII_SPEED; + if (state->pause & MLO_PAUSE_TX) + ctrl4 |= MVPP22_CTRL4_TX_FC_EN; + if (state->pause & MLO_PAUSE_RX) + ctrl4 |= MVPP22_CTRL4_RX_FC_EN; + } else if (phy_interface_mode_is_8023z(state->interface)) { + /* 1000BaseX and 2500BaseX ports cannot negotiate speed nor can + * they negotiate duplex: they are always operating with a fixed + * speed of 1000/2500Mbps in full duplex, so force 1000/2500 + * speed and full duplex here. + */ + ctrl0 |= MVPP2_GMAC_PORT_TYPE_MASK; + an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN | MVPP2_GMAC_FORCE_LINK_PASS); + an |= MVPP2_GMAC_CONFIG_GMII_SPEED | + MVPP2_GMAC_CONFIG_FULL_DUPLEX; - ctrl4 &= ~MVPP22_CTRL4_DP_CLK_SEL; - ctrl4 |= MVPP22_CTRL4_EXT_PIN_GMII_SEL | - MVPP22_CTRL4_SYNC_BYPASS_DIS | - MVPP22_CTRL4_QSGMII_BYPASS_ACTIVE; + if (state->pause & MLO_PAUSE_AN && state->an_enabled) { + an |= MVPP2_GMAC_FLOW_CTRL_AUTONEG; + } else { + if (state->pause & MLO_PAUSE_TX) + ctrl4 |= MVPP22_CTRL4_TX_FC_EN; + if (state->pause & MLO_PAUSE_RX) + ctrl4 |= MVPP22_CTRL4_RX_FC_EN; + } } writel(ctrl0, port->base + MVPP2_GMAC_CTRL_0_REG); @@ -4670,8 +4696,7 @@ static void mvpp2_mac_link_up(struct net_device *dev, unsigned int mode, interface != PHY_INTERFACE_MODE_10GKR) { val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); val &= ~MVPP2_GMAC_FORCE_LINK_DOWN; - if (phy_interface_mode_is_rgmii(interface)) - val |= MVPP2_GMAC_FORCE_LINK_PASS; + val |= MVPP2_GMAC_FORCE_LINK_PASS; writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); } -- cgit v1.2.3 From 316734fdcf70900a83065360cff11a5826919067 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Feb 2019 15:35:43 +0000 Subject: net: marvell: mvpp2: fix stuck in-band SGMII negotiation It appears that the mvpp22 can get stuck with SGMII negotiation. The symptoms are that in-band negotiation never completes and the partner (eg, PHY) never reports SGMII link up, or if it supports negotiation bypass, goes into negotiation bypass mode (which will happen when the PHY sees that the MAC is alive but gets no response.) Triggering the PHY end of the link to re-negotiate results in the bypass bit clearing on the PHY, and then re-setting - indicating that the problem is at the mvpp22 GMAC end. Asserting the GMAC reset and de-asserting it resolves the issue. Arrange to assert the GMAC reset at probe time, and deassert it only after we have configured the GMAC for the appropriate mode. This resolves the issue. Tested-by: Sven Auhagen Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index f16ba7817f62..7a60456d91be 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1377,13 +1377,9 @@ static void mvpp2_port_reset(struct mvpp2_port *port) for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++) mvpp2_read_count(port, &mvpp2_ethtool_regs[i]); - val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) & - ~MVPP2_GMAC_PORT_RESET_MASK; + val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) | + MVPP2_GMAC_PORT_RESET_MASK; writel(val, port->base + MVPP2_GMAC_CTRL_2_REG); - - while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) & - MVPP2_GMAC_PORT_RESET_MASK) - continue; } /* Change maximum receive size of the port */ @@ -4539,12 +4535,15 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, const struct phylink_link_state *state) { u32 an, ctrl0, ctrl2, ctrl4; + u32 old_ctrl2; an = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); ctrl0 = readl(port->base + MVPP2_GMAC_CTRL_0_REG); ctrl2 = readl(port->base + MVPP2_GMAC_CTRL_2_REG); ctrl4 = readl(port->base + MVPP22_GMAC_CTRL_4_REG); + old_ctrl2 = ctrl2; + /* Force link down */ an &= ~MVPP2_GMAC_FORCE_LINK_PASS; an |= MVPP2_GMAC_FORCE_LINK_DOWN; @@ -4641,6 +4640,12 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, writel(ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG); writel(ctrl4, port->base + MVPP22_GMAC_CTRL_4_REG); writel(an, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + + if (old_ctrl2 & MVPP2_GMAC_PORT_RESET_MASK) { + while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) & + MVPP2_GMAC_PORT_RESET_MASK) + continue; + } } static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, -- cgit v1.2.3 From d14e078f23cc9711acd299c91e77076c3f1ddddb Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Feb 2019 15:35:49 +0000 Subject: net: marvell: mvpp2: only reprogram what is necessary on mac_config mac_config() can be called at any point, and the expected behaviour from MAC drivers is to only reprogram when necessary - and certainly avoid taking the link down on every call. Unfortunately, mvpp2 does exactly that - it takes the link down, and reprograms everything, and then releases the forced-link down. This is bad, it can cause the link to bounce: - SFP detects signal, disables LOS indication. - SFP code calls into phylink, calling phylink_sfp_link_up() which triggers a resolve. - phylink_resolve() calls phylink_get_mac_state() and finds the MAC reporting link up. - phylink wants to configure the pause mode on the MAC, so calls phylink_mac_config() - mvpp2 takes the link down temporarily, generating a MAC link down event followed by another MAC link event. - phylink calls mac_link_up() and then processes the MAC link down event. - phylink_resolve() gets called again, registers the link down, and calls mach_link_down() before re-running itself. - phylink_resolve() starts again at step 3 above. This sequence repeats. GMAC versions prior to mvpp2 do not require the link to be taken down except when certain link properties (eg, switching between SGMII and 1000base-X mode, or enabling/disabling in-band negotiation) are changed. Implement this for mvpp2. Tested-by: Sven Auhagen Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 58 +++++++++++++++---------- 1 file changed, 35 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 7a60456d91be..133a6d4f94a1 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4534,29 +4534,21 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, const struct phylink_link_state *state) { - u32 an, ctrl0, ctrl2, ctrl4; - u32 old_ctrl2; + u32 old_an, an; + u32 old_ctrl0, ctrl0; + u32 old_ctrl2, ctrl2; + u32 old_ctrl4, ctrl4; - an = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); - ctrl0 = readl(port->base + MVPP2_GMAC_CTRL_0_REG); - ctrl2 = readl(port->base + MVPP2_GMAC_CTRL_2_REG); - ctrl4 = readl(port->base + MVPP22_GMAC_CTRL_4_REG); - - old_ctrl2 = ctrl2; - - /* Force link down */ - an &= ~MVPP2_GMAC_FORCE_LINK_PASS; - an |= MVPP2_GMAC_FORCE_LINK_DOWN; - writel(an, port->base + MVPP2_GMAC_AUTONEG_CONFIG); - - /* Set the GMAC in a reset state */ - ctrl2 |= MVPP2_GMAC_PORT_RESET_MASK; - writel(ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG); + old_an = an = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); + old_ctrl0 = ctrl0 = readl(port->base + MVPP2_GMAC_CTRL_0_REG); + old_ctrl2 = ctrl2 = readl(port->base + MVPP2_GMAC_CTRL_2_REG); + old_ctrl4 = ctrl4 = readl(port->base + MVPP22_GMAC_CTRL_4_REG); an &= ~(MVPP2_GMAC_CONFIG_MII_SPEED | MVPP2_GMAC_CONFIG_GMII_SPEED | MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_FC_ADV_EN | MVPP2_GMAC_FC_ADV_ASM_EN | MVPP2_GMAC_FLOW_CTRL_AUTONEG | - MVPP2_GMAC_CONFIG_FULL_DUPLEX | MVPP2_GMAC_AN_DUPLEX_EN); + MVPP2_GMAC_CONFIG_FULL_DUPLEX | MVPP2_GMAC_AN_DUPLEX_EN | + MVPP2_GMAC_IN_BAND_AUTONEG | MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS); ctrl0 &= ~MVPP2_GMAC_PORT_TYPE_MASK; ctrl2 &= ~(MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PORT_RESET_MASK | MVPP2_GMAC_PCS_ENABLE_MASK); @@ -4623,7 +4615,8 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, */ ctrl0 |= MVPP2_GMAC_PORT_TYPE_MASK; an &= ~(MVPP2_GMAC_FORCE_LINK_DOWN | MVPP2_GMAC_FORCE_LINK_PASS); - an |= MVPP2_GMAC_CONFIG_GMII_SPEED | + an |= MVPP2_GMAC_IN_BAND_AUTONEG | + MVPP2_GMAC_CONFIG_GMII_SPEED | MVPP2_GMAC_CONFIG_FULL_DUPLEX; if (state->pause & MLO_PAUSE_AN && state->an_enabled) { @@ -4636,10 +4629,29 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, } } - writel(ctrl0, port->base + MVPP2_GMAC_CTRL_0_REG); - writel(ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG); - writel(ctrl4, port->base + MVPP22_GMAC_CTRL_4_REG); - writel(an, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + if ((old_ctrl0 ^ ctrl0) & MVPP2_GMAC_PORT_TYPE_MASK || + (old_ctrl2 ^ ctrl2) & MVPP2_GMAC_INBAND_AN_MASK || + (old_an ^ an) & MVPP2_GMAC_IN_BAND_AUTONEG) { + /* Force link down */ + old_an &= ~MVPP2_GMAC_FORCE_LINK_PASS; + old_an |= MVPP2_GMAC_FORCE_LINK_DOWN; + writel(old_an, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + + /* Set the GMAC in a reset state - do this in a way that + * ensures we clear it below. + */ + old_ctrl2 |= MVPP2_GMAC_PORT_RESET_MASK; + writel(old_ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG); + } + + if (old_ctrl0 != ctrl0) + writel(ctrl0, port->base + MVPP2_GMAC_CTRL_0_REG); + if (old_ctrl2 != ctrl2) + writel(ctrl2, port->base + MVPP2_GMAC_CTRL_2_REG); + if (old_ctrl4 != ctrl4) + writel(ctrl4, port->base + MVPP22_GMAC_CTRL_4_REG); + if (old_an != an) + writel(an, port->base + MVPP2_GMAC_AUTONEG_CONFIG); if (old_ctrl2 & MVPP2_GMAC_PORT_RESET_MASK) { while (readl(port->base + MVPP2_GMAC_CTRL_2_REG) & -- cgit v1.2.3 From 417f3d08feffe3be29a5f868bcf817b476539338 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Feb 2019 15:35:54 +0000 Subject: net: marvell: mvpp2: read correct pause bits When reading the pause bits in mac_link_state, mvpp2 was reporting the state of the "active pause" bits, which are set when the MAC is in pause mode. This is not what phylink wants - we want the negotiated pause state. Fix the definition so we read the correct bits. Tested-by: Sven Auhagen Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 398328f10743..96e3f0669032 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -402,8 +402,8 @@ #define MVPP2_GMAC_STATUS0_GMII_SPEED BIT(1) #define MVPP2_GMAC_STATUS0_MII_SPEED BIT(2) #define MVPP2_GMAC_STATUS0_FULL_DUPLEX BIT(3) -#define MVPP2_GMAC_STATUS0_RX_PAUSE BIT(6) -#define MVPP2_GMAC_STATUS0_TX_PAUSE BIT(7) +#define MVPP2_GMAC_STATUS0_RX_PAUSE BIT(4) +#define MVPP2_GMAC_STATUS0_TX_PAUSE BIT(5) #define MVPP2_GMAC_STATUS0_AN_COMPLETE BIT(11) #define MVPP2_GMAC_PORT_FIFO_CFG_1_REG 0x1c #define MVPP2_GMAC_TX_FIFO_MIN_TH_OFFS 6 -- cgit v1.2.3 From a4650477179017f47706c3cc7641927326bb663c Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 8 Feb 2019 15:35:59 +0000 Subject: net: marvell: mvpp2: fix AN restart phylink already limits which interface modes are able to call the MACs AN restart function, but in any case, the commentry seems incorrect: the AN restart bit does not automatically clear when set. This has been found via manual setting using devmem2, and we can observe that the AN does indeed restart and complete, yet the AN restart bit remains set. Explicitly clear the AN restart bit. Tested-by: Sven Auhagen Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 133a6d4f94a1..8a2dd9104e37 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4497,17 +4497,12 @@ static int mvpp2_phylink_mac_link_state(struct net_device *dev, static void mvpp2_mac_an_restart(struct net_device *dev) { struct mvpp2_port *port = netdev_priv(dev); - u32 val; - - if (port->phy_interface != PHY_INTERFACE_MODE_SGMII) - return; + u32 val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); - val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); - /* The RESTART_AN bit is cleared by the h/w after restarting the AN - * process. - */ - val |= MVPP2_GMAC_IN_BAND_RESTART_AN | MVPP2_GMAC_IN_BAND_AUTONEG; - writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + writel(val | MVPP2_GMAC_IN_BAND_RESTART_AN, + port->base + MVPP2_GMAC_AUTONEG_CONFIG); + writel(val & ~MVPP2_GMAC_IN_BAND_RESTART_AN, + port->base + MVPP2_GMAC_AUTONEG_CONFIG); } static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, -- cgit v1.2.3 From 3b5e74e0afe3382f9354b657714ac40673b7c597 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 8 Feb 2019 19:25:22 +0100 Subject: net: phy: disregard "Clause 22 registers present" bit in get_phy_c45_devs_in_pkg Bit 0 in register 1.5 doesn't represent a device but is a flag that Clause 22 registers are present. Therefore disregard this bit when populating the device list. If code needs this information it should read register 1.5 directly instead of accessing the device list. Because this bit doesn't represent a device don't define a MDIO_MMD_XYZ constant, just define a MDIO_DEVS_XYZ constant for the flag in the device list bitmap. v2: - make masking of bit 0 more explicit - improve commit message Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 3 +++ include/uapi/linux/mdio.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 9369e1323c39..d4fc1fd8af41 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -684,6 +684,9 @@ static int get_phy_c45_devs_in_pkg(struct mii_bus *bus, int addr, int dev_addr, return -EIO; *devices_in_package |= (phy_reg & 0xffff); + /* Bit 0 doesn't represent a device, it indicates c22 regs presence */ + *devices_in_package &= ~BIT(0); + return 0; } diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h index 2e6e309f0847..0e012b168e4d 100644 --- a/include/uapi/linux/mdio.h +++ b/include/uapi/linux/mdio.h @@ -115,6 +115,7 @@ /* Device present registers. */ #define MDIO_DEVS_PRESENT(devad) (1 << (devad)) +#define MDIO_DEVS_C22PRESENT MDIO_DEVS_PRESENT(0) #define MDIO_DEVS_PMAPMD MDIO_DEVS_PRESENT(MDIO_MMD_PMAPMD) #define MDIO_DEVS_WIS MDIO_DEVS_PRESENT(MDIO_MMD_WIS) #define MDIO_DEVS_PCS MDIO_DEVS_PRESENT(MDIO_MMD_PCS) -- cgit v1.2.3 From 50684da7427b3c36ce0ccf89814df28d9dbe3fe4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 9 Feb 2019 09:46:53 +0100 Subject: net: phy: remove unneeded masking of PHY register read results PHY registers are only 16 bits wide, therefore, if the read was successful, there's no need to mask out the higher 16 bits. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index d4fc1fd8af41..31f9e7c491a1 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -676,13 +676,13 @@ static int get_phy_c45_devs_in_pkg(struct mii_bus *bus, int addr, int dev_addr, phy_reg = mdiobus_read(bus, addr, reg_addr); if (phy_reg < 0) return -EIO; - *devices_in_package = (phy_reg & 0xffff) << 16; + *devices_in_package = phy_reg << 16; reg_addr = MII_ADDR_C45 | dev_addr << 16 | MDIO_DEVS1; phy_reg = mdiobus_read(bus, addr, reg_addr); if (phy_reg < 0) return -EIO; - *devices_in_package |= (phy_reg & 0xffff); + *devices_in_package |= phy_reg; /* Bit 0 doesn't represent a device, it indicates c22 regs presence */ *devices_in_package &= ~BIT(0); @@ -746,13 +746,13 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id, phy_reg = mdiobus_read(bus, addr, reg_addr); if (phy_reg < 0) return -EIO; - c45_ids->device_ids[i] = (phy_reg & 0xffff) << 16; + c45_ids->device_ids[i] = phy_reg << 16; reg_addr = MII_ADDR_C45 | i << 16 | MII_PHYSID2; phy_reg = mdiobus_read(bus, addr, reg_addr); if (phy_reg < 0) return -EIO; - c45_ids->device_ids[i] |= (phy_reg & 0xffff); + c45_ids->device_ids[i] |= phy_reg; } *phy_id = 0; return 0; @@ -789,14 +789,14 @@ static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id, return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO; } - *phy_id = (phy_reg & 0xffff) << 16; + *phy_id = phy_reg << 16; /* Grab the bits from PHYIR2, and put them in the lower half */ phy_reg = mdiobus_read(bus, addr, MII_PHYSID2); if (phy_reg < 0) return -EIO; - *phy_id |= (phy_reg & 0xffff); + *phy_id |= phy_reg; return 0; } -- cgit v1.2.3 From 92ed2eb7f4b73e9944b432e5c8c65ec3ec00eb9d Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 9 Feb 2019 14:46:30 +0100 Subject: net: phy: probe the PHY before determining the supported features We will soon support asking the PHY at runtime to determine what features it supports, rather than forcing it to be compile time. But we should probe the PHY first. So probe the phy driver earlier. Signed-off-by: Andrew Lunn Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 31f9e7c491a1..92b7a71df0ac 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2220,6 +2220,18 @@ static int phy_probe(struct device *dev) mutex_lock(&phydev->lock); + if (phydev->drv->probe) { + /* Deassert the reset signal */ + phy_device_reset(phydev, 0); + + err = phydev->drv->probe(phydev); + if (err) { + /* Assert the reset signal */ + phy_device_reset(phydev, 1); + goto out; + } + } + /* Start out supporting everything. Eventually, * a controller will attach, and may modify one * or both of these values @@ -2267,17 +2279,7 @@ static int phy_probe(struct device *dev) /* Set the state to READY by default */ phydev->state = PHY_READY; - if (phydev->drv->probe) { - /* Deassert the reset signal */ - phy_device_reset(phydev, 0); - - err = phydev->drv->probe(phydev); - if (err) { - /* Assert the reset signal */ - phy_device_reset(phydev, 1); - } - } - +out: mutex_unlock(&phydev->lock); return err; -- cgit v1.2.3 From efbdfdc29bdd4dbf79ad4bddc8f7a5ac62c66bfe Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 9 Feb 2019 15:24:47 +0100 Subject: net: phy: Add support for asking the PHY its abilities Add support for runtime determination of what the PHY supports, by adding a new function to the phy driver. The get_features call should set the phydev->supported member with the features the PHY supports. It is only called if phydrv->features is NULL. This requires minor changes to pause. The PHY driver should not set pause abilities, except for when it has odd cause capabilities, e.g. pause cannot be disabled. With this change, phydev->supported already contains the drivers abilities, including pause. So rather than considering phydrv->features, look at the phydev->supported, and enable pause if neither of the pause bits are already set. Signed-off-by: Andrew Lunn [hkallweit1@gmail.com: fixed small checkpatch complaint in one comment] Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 31 +++++++++++++++---------------- include/linux/phy.h | 6 ++++++ 2 files changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 92b7a71df0ac..8573d17ece0f 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2236,7 +2236,14 @@ static int phy_probe(struct device *dev) * a controller will attach, and may modify one * or both of these values */ - linkmode_copy(phydev->supported, phydrv->features); + if (phydrv->features) { + linkmode_copy(phydev->supported, phydrv->features); + } else { + err = phydrv->get_features(phydev); + if (err) + goto out; + } + of_set_phy_supported(phydev); linkmode_copy(phydev->advertising, phydev->supported); @@ -2256,20 +2263,8 @@ static int phy_probe(struct device *dev) * (e.g. hardware erratum) where the driver wants to set only one * of these bits. */ - if (test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydrv->features) || - test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydrv->features)) { - linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, - phydev->supported); - linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - phydev->supported); - if (test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydrv->features)) - linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, - phydev->supported); - if (test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - phydrv->features)) - linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - phydev->supported); - } else { + if (!test_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported) && + !test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported)) { linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported); linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, @@ -2315,7 +2310,11 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner) { int retval; - if (WARN_ON(!new_driver->features)) { + /* Either the features are hard coded, or dynamically + * determine. It cannot be both or neither + */ + if (WARN_ON((!new_driver->features && !new_driver->get_features) || + (new_driver->features && new_driver->get_features))) { pr_err("%s: Driver features are missing\n", new_driver->name); return -EINVAL; } diff --git a/include/linux/phy.h b/include/linux/phy.h index f41bf651f6a0..d2ffae992e4a 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -502,6 +502,12 @@ struct phy_driver { */ int (*probe)(struct phy_device *phydev); + /* + * Probe the hardware to determine what abilities it has. + * Should only set phydev->supported. + */ + int (*get_features)(struct phy_device *phydev); + /* PHY Power Management */ int (*suspend)(struct phy_device *phydev); int (*resume)(struct phy_device *phydev); -- cgit v1.2.3 From e240b7dbb73c4d5a2997356992a3cfe3ff99951a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 9 Feb 2019 16:06:51 +0000 Subject: net: marvell: mvpp2: clear flow control modes in 10G mode When mvpp2 configures the flow control modes in mvpp2_xlg_config() for 10G mode, it only ever set the flow control enable bits. There is no mechanism to clear these bits, which means that userspace is unable to use standard APIs to disable flow control (the only way is to poke the register directly.) Fix the missing bit clearance to allow flow control to be disabled. This means that, by default, as there is no negotiation in 10G modes with mvpp2, flow control is now disabled rather than being rx-only. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 8a2dd9104e37..eef8833e5aae 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4515,8 +4515,13 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, if (state->pause & MLO_PAUSE_TX) ctrl0 |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN; + else + ctrl0 &= ~MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN; + if (state->pause & MLO_PAUSE_RX) ctrl0 |= MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN; + else + ctrl0 &= ~MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN; ctrl4 &= ~MVPP22_XLG_CTRL4_MACMODSELECT_GMAC; ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC | -- cgit v1.2.3 From ec26016b953778c1727040adb98a0132b9162334 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 8 Feb 2019 22:25:44 +0100 Subject: net: dsa: mv88e6xxx: SERDES support 2500BaseT via external PHY By using an external PHY, ports 9 and 10 can support 2500BaseT. So set this link mode in the mask when validating. Signed-off-by: Andrew Lunn Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 669a7f13fdce..39c780363764 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -647,8 +647,10 @@ static void mv88e6390_phylink_validate(struct mv88e6xxx_chip *chip, int port, unsigned long *mask, struct phylink_link_state *state) { - if (port >= 9) + if (port >= 9) { phylink_set(mask, 2500baseX_Full); + phylink_set(mask, 2500baseT_Full); + } /* No ethtool bits for 200Mbps */ phylink_set(mask, 1000baseT_Full); -- cgit v1.2.3 From 99c864667c9fe3d1113a2b906aa942d01c87e996 Mon Sep 17 00:00:00 2001 From: Nikita Yushchenko Date: Fri, 8 Feb 2019 22:12:23 +0100 Subject: net: phy: aquantia: add support for AQCS109 Add support for the AQCS109. From software point of view, it should be almost equivalent to AQR107. v2: - make Nikita the author - document what I changed Signed-off-by: Nikita Yushchenko Signed-off-by: Andrew Lunn [hkallweit1@gmail.com: use PHY_ID_MATCH_MODEL mascro] Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 482004efa62d..0f772a47a18e 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -17,6 +17,7 @@ #define PHY_ID_AQR105 0x03a1b4a2 #define PHY_ID_AQR106 0x03a1b4d0 #define PHY_ID_AQR107 0x03a1b4e0 +#define PHY_ID_AQCS109 0x03a1b5c2 #define PHY_ID_AQR405 0x03a1b4b0 #define MDIO_AN_TX_VEND_STATUS1 0xc800 @@ -202,6 +203,16 @@ static struct phy_driver aqr_driver[] = { .ack_interrupt = aqr_ack_interrupt, .read_status = aqr_read_status, }, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), + .name = "Aquantia AQCS109", + .features = PHY_10GBIT_FULL_FEATURES, + .aneg_done = genphy_c45_aneg_done, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, +}, { PHY_ID_MATCH_MODEL(PHY_ID_AQR405), .name = "Aquantia AQR405", @@ -222,6 +233,7 @@ static struct mdio_device_id __maybe_unused aqr_tbl[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, { } }; -- cgit v1.2.3 From b8554d4f7288f86fb278e0bc7b5b19579bf16b69 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 10 Feb 2019 19:57:56 +0100 Subject: net: phy: add register modifying helpers returning 1 on change When modifying registers there are scenarios where we need to know whether the register content actually changed. This patch adds new helpers to not break users of the current ones, phy_modify() etc. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy-core.c | 127 +++++++++++++++++++++++++++++++++++++++++---- include/linux/phy.h | 12 ++++- 2 files changed, 128 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index 7d6aad287f84..cdea028d1328 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -531,7 +531,7 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) EXPORT_SYMBOL(phy_write_mmd); /** - * __phy_modify() - Convenience function for modifying a PHY register + * __phy_modify_changed() - Convenience function for modifying a PHY register * @phydev: a pointer to a &struct phy_device * @regnum: register number * @mask: bit mask of bits to clear @@ -539,16 +539,69 @@ EXPORT_SYMBOL(phy_write_mmd); * * Unlocked helper function which allows a PHY register to be modified as * new register value = (old register value & ~mask) | set + * + * Returns negative errno, 0 if there was no change, and 1 in case of change */ -int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) +int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, + u16 set) { - int ret; + int new, ret; ret = __phy_read(phydev, regnum); if (ret < 0) return ret; - ret = __phy_write(phydev, regnum, (ret & ~mask) | set); + new = (ret & ~mask) | set; + if (new == ret) + return 0; + + ret = __phy_write(phydev, regnum, new); + + return ret < 0 ? ret : 1; +} +EXPORT_SYMBOL_GPL(__phy_modify_changed); + +/** + * phy_modify_changed - Function for modifying a PHY register + * @phydev: the phy_device struct + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + * + * Returns negative errno, 0 if there was no change, and 1 in case of change + */ +int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) +{ + int ret; + + mutex_lock(&phydev->mdio.bus->mdio_lock); + ret = __phy_modify_changed(phydev, regnum, mask, set); + mutex_unlock(&phydev->mdio.bus->mdio_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_modify_changed); + +/** + * __phy_modify - Convenience function for modifying a PHY register + * @phydev: the phy_device struct + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) +{ + int ret; + + ret = __phy_modify_changed(phydev, regnum, mask, set); return ret < 0 ? ret : 0; } @@ -578,7 +631,7 @@ int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set) EXPORT_SYMBOL_GPL(phy_modify); /** - * __phy_modify_mmd - Convenience function for modifying a register on MMD + * __phy_modify_mmd_changed - Function for modifying a register on MMD * @phydev: the phy_device struct * @devad: the MMD containing register to modify * @regnum: register number to modify @@ -587,17 +640,73 @@ EXPORT_SYMBOL_GPL(phy_modify); * * Unlocked helper function which allows a MMD register to be modified as * new register value = (old register value & ~mask) | set + * + * Returns negative errno, 0 if there was no change, and 1 in case of change */ -int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, - u16 mask, u16 set) +int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) { - int ret; + int new, ret; ret = __phy_read_mmd(phydev, devad, regnum); if (ret < 0) return ret; - ret = __phy_write_mmd(phydev, devad, regnum, (ret & ~mask) | set); + new = (ret & ~mask) | set; + if (new == ret) + return 0; + + ret = __phy_write_mmd(phydev, devad, regnum, new); + + return ret < 0 ? ret : 1; +} +EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed); + +/** + * phy_modify_mmd_changed - Function for modifying a register on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + * + * Returns negative errno, 0 if there was no change, and 1 in case of change + */ +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) +{ + int ret; + + mutex_lock(&phydev->mdio.bus->mdio_lock); + ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set); + mutex_unlock(&phydev->mdio.bus->mdio_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_modify_mmd_changed); + +/** + * __phy_modify_mmd - Convenience function for modifying a register on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @mask: bit mask of bits to clear + * @set: new value of bits set in mask to write to @regnum + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set) +{ + int ret; + + ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set); return ret < 0 ? ret : 0; } diff --git a/include/linux/phy.h b/include/linux/phy.h index d2ffae992e4a..378da9a6165e 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -799,13 +799,21 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); */ int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); +int __phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, + u16 set); +int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, + u16 set); int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set); int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set); +int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set); +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set); int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, - u16 mask, u16 set); + u16 mask, u16 set); int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, - u16 mask, u16 set); + u16 mask, u16 set); /** * __phy_set_bits - Convenience function for setting bits in a PHY register -- cgit v1.2.3 From b06d8e5a5dcc21063a0a84658b7106f40aa400e4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 10 Feb 2019 19:58:49 +0100 Subject: net: phy: marvell10g: fix usage of new MMD modifying helpers When replacing mv3310_modify() with phy_modify_mmd() we missed that they behave differently, mv3310_modify() returns 1 on a changed register value whilst phy_modify_mmd() returns 0. Fix this by replacing phy_modify_mmd() with phy_modify_mmd_changed() where needed. Fixes: b52c018ddccf ("net: phy: make use of new MMD accessors") Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 96a79c6c7810..08362dc657cd 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -141,10 +141,9 @@ static int mv3310_hwmon_config(struct phy_device *phydev, bool enable) return ret; val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE; - ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL, - MV_V2_TEMP_CTRL_MASK, val); - return ret < 0 ? ret : 0; + return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL, + MV_V2_TEMP_CTRL_MASK, val); } static void mv3310_hwmon_disable(void *data) @@ -345,7 +344,7 @@ static int mv3310_config_aneg(struct phy_device *phydev) linkmode_and(phydev->advertising, phydev->advertising, phydev->supported); - ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, linkmode_adv_to_mii_adv_t(phydev->advertising)); @@ -355,7 +354,7 @@ static int mv3310_config_aneg(struct phy_device *phydev) changed = true; reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); - ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MV_AN_CTRL1000, + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000, ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg); if (ret < 0) return ret; @@ -369,8 +368,8 @@ static int mv3310_config_aneg(struct phy_device *phydev) else reg = 0; - ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV10G, reg); + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV10G, reg); if (ret < 0) return ret; if (ret > 0) -- cgit v1.2.3 From 4f9744ed3c285fd2d2cf7f9a43c00c03604a2515 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 10 Feb 2019 19:59:57 +0100 Subject: net: phy: use phy_modify_changed in genphy_config_advert Use phy_modify_changed() to simplify the code. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8573d17ece0f..3d14e48aebc5 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1516,7 +1516,7 @@ EXPORT_SYMBOL(phy_reset_after_clk_enable); static int genphy_config_advert(struct phy_device *phydev) { u32 advertise; - int oldadv, adv, bmsr; + int bmsr, adv; int err, changed = 0; /* Only allow advertising what this PHY supports */ @@ -1529,22 +1529,14 @@ static int genphy_config_advert(struct phy_device *phydev) phydev->advertising); /* Setup standard advertisement */ - adv = phy_read(phydev, MII_ADVERTISE); - if (adv < 0) - return adv; - - oldadv = adv; - adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | - ADVERTISE_PAUSE_ASYM); - adv |= ethtool_adv_to_mii_adv_t(advertise); - - if (adv != oldadv) { - err = phy_write(phydev, MII_ADVERTISE, adv); - - if (err < 0) - return err; + err = phy_modify_changed(phydev, MII_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_100BASE4 | + ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, + ethtool_adv_to_mii_adv_t(advertise)); + if (err < 0) + return err; + if (err > 0) changed = 1; - } bmsr = phy_read(phydev, MII_BMSR); if (bmsr < 0) @@ -1558,25 +1550,20 @@ static int genphy_config_advert(struct phy_device *phydev) return changed; /* Configure gigabit if it's supported */ - adv = phy_read(phydev, MII_CTRL1000); - if (adv < 0) - return adv; - - oldadv = adv; - adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - + adv = 0; if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, phydev->supported) || linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, phydev->supported)) - adv |= ethtool_adv_to_mii_ctrl1000_t(advertise); + adv = ethtool_adv_to_mii_ctrl1000_t(advertise); - if (adv != oldadv) - changed = 1; - - err = phy_write(phydev, MII_CTRL1000, adv); + err = phy_modify_changed(phydev, MII_CTRL1000, + ADVERTISE_1000FULL | ADVERTISE_1000HALF, + adv); if (err < 0) return err; + if (err > 0) + changed = 1; return changed; } -- cgit v1.2.3 From f440b125450dfc65ce0386eb231da2f663c45ca0 Mon Sep 17 00:00:00 2001 From: Cody Schuffelen Date: Wed, 6 Feb 2019 15:54:15 -0800 Subject: virt_wifi: Remove REGULATORY_WIPHY_SELF_MANAGED REGULATORY_WIPHY_SELF_MANAGED as set here breaks NL80211_CMD_GET_REG, because it expects the wiphy to do regulatory management. Since virt_wifi does not do regulatory management, this triggers a WARN_ON in NL80211_CMD_GET_REG and fails the netlink command. Removing REGULATORY_WIPHY_SELF_MANAGED fixes the problem and the virtual wireless network continues to work. Signed-off-by: Cody Schuffelen Acked-by: Alistair Strachan Acked-by: Greg Hartman Signed-off-by: Johannes Berg --- drivers/net/wireless/virt_wifi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index 71044c6cfd8c..606999f102eb 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -360,7 +360,6 @@ static struct wiphy *virt_wifi_make_wiphy(void) wiphy->bands[NL80211_BAND_5GHZ] = &band_5ghz; wiphy->bands[NL80211_BAND_60GHZ] = NULL; - wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); priv = wiphy_priv(wiphy); -- cgit v1.2.3 From 7ba31e6e0cdc0cc2e60e1fcbf467f3c95aea948e Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Fri, 8 Feb 2019 14:55:23 +0200 Subject: ath10k: assign 'n_cipher_suites = 11' for WCN3990 to enable WPA3 Hostapd uses CCMP, GCMP & GCMP-256 as 'wpa_pairwise' option to run WPA3. In WCN3990 firmware cipher suite numbers 9 to 11 are for CCMP, GCMP & GCMP-256. To enable CCMP, GCMP & GCMP-256 cipher suites in WCN3990 firmware, host sets 'n_cipher_suites = 11' while initializing hardware parameters. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Abhishek Ambure Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 327a74c052e5..c9b75b69de63 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -561,7 +561,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .hw_ops = &wcn3990_ops, .decap_align_bytes = 1, .num_peers = TARGET_HL_10_TLV_NUM_PEERS, - .n_cipher_suites = 8, + .n_cipher_suites = 11, .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT, .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES, .target_64bit = true, -- cgit v1.2.3 From 7d94f862d6482e1159ccca669cbf21c724d159e1 Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Fri, 8 Feb 2019 14:55:26 +0200 Subject: ath10k: update GCMP & GCMP-256 cipher suite number for WCN3990 TLV based firmware ex. QCA6174, WCN3990 expects key cipher value set to 9 while non-TLV firmware expects key cipher value set to 8 for enabling GCMP and GCMP-256 cipher suites. To fix this problem, attach the key cipher suite values based on wmi version. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Signed-off-by: Abhishek Ambure Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 12 +++++------ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 6 ++++-- drivers/net/wireless/ath/ath10k/wmi.c | 30 ++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 33 ++++++++++++++++++++++--------- 5 files changed, 65 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 46e9c8c97a4d..f2278d0c3efa 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1182,6 +1182,7 @@ struct ath10k { u32 ampdu_reference; + const u8 *wmi_key_cipher; void *ce_priv; u32 sta_tid_stats_mask; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 4dd64f310885..6c66a3435d57 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -250,24 +250,24 @@ static int ath10k_send_key(struct ath10k_vif *arvif, switch (key->cipher) { case WLAN_CIPHER_SUITE_CCMP: - arg.key_cipher = WMI_CIPHER_AES_CCM; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM]; key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT; break; case WLAN_CIPHER_SUITE_TKIP: - arg.key_cipher = WMI_CIPHER_TKIP; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_TKIP]; arg.key_txmic_len = 8; arg.key_rxmic_len = 8; break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - arg.key_cipher = WMI_CIPHER_WEP; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_WEP]; break; case WLAN_CIPHER_SUITE_CCMP_256: - arg.key_cipher = WMI_CIPHER_AES_CCM; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM]; break; case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: - arg.key_cipher = WMI_CIPHER_AES_GCM; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_GCM]; break; case WLAN_CIPHER_SUITE_BIP_GMAC_128: case WLAN_CIPHER_SUITE_BIP_GMAC_256: @@ -284,7 +284,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif, key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; if (cmd == DISABLE_KEY) { - arg.key_cipher = WMI_CIPHER_NONE; + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_NONE]; arg.key_data = NULL; } diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 90617e1a074c..7621dfe8a61c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -2060,9 +2060,11 @@ ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar, size_t len; void *ptr; - if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL) + if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] && + arg->key_data) return ERR_PTR(-EINVAL); - if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL) + if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] && + !arg->key_data) return ERR_PTR(-EINVAL); len = sizeof(*tlv) + sizeof(*cmd) + diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index b99b3a19eda5..903aa8cffc43 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1606,6 +1606,30 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = { .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX, }; +static const u8 wmi_key_cipher_suites[] = { + [WMI_CIPHER_NONE] = WMI_CIPHER_NONE, + [WMI_CIPHER_WEP] = WMI_CIPHER_WEP, + [WMI_CIPHER_TKIP] = WMI_CIPHER_TKIP, + [WMI_CIPHER_AES_OCB] = WMI_CIPHER_AES_OCB, + [WMI_CIPHER_AES_CCM] = WMI_CIPHER_AES_CCM, + [WMI_CIPHER_WAPI] = WMI_CIPHER_WAPI, + [WMI_CIPHER_CKIP] = WMI_CIPHER_CKIP, + [WMI_CIPHER_AES_CMAC] = WMI_CIPHER_AES_CMAC, + [WMI_CIPHER_AES_GCM] = WMI_CIPHER_AES_GCM, +}; + +static const u8 wmi_tlv_key_cipher_suites[] = { + [WMI_CIPHER_NONE] = WMI_TLV_CIPHER_NONE, + [WMI_CIPHER_WEP] = WMI_TLV_CIPHER_WEP, + [WMI_CIPHER_TKIP] = WMI_TLV_CIPHER_TKIP, + [WMI_CIPHER_AES_OCB] = WMI_TLV_CIPHER_AES_OCB, + [WMI_CIPHER_AES_CCM] = WMI_TLV_CIPHER_AES_CCM, + [WMI_CIPHER_WAPI] = WMI_TLV_CIPHER_WAPI, + [WMI_CIPHER_CKIP] = WMI_TLV_CIPHER_CKIP, + [WMI_CIPHER_AES_CMAC] = WMI_TLV_CIPHER_AES_CMAC, + [WMI_CIPHER_AES_GCM] = WMI_TLV_CIPHER_AES_GCM, +}; + static const struct wmi_peer_flags_map wmi_peer_flags_map = { .auth = WMI_PEER_AUTH, .qos = WMI_PEER_QOS, @@ -9252,6 +9276,7 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_10_4_vdev_param_map; ar->wmi.pdev_param = &wmi_10_4_pdev_param_map; ar->wmi.peer_flags = &wmi_10_2_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_10_2_4: ar->wmi.cmd = &wmi_10_2_4_cmd_map; @@ -9259,6 +9284,7 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map; ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map; ar->wmi.peer_flags = &wmi_10_2_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_10_2: ar->wmi.cmd = &wmi_10_2_cmd_map; @@ -9266,6 +9292,7 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_10x_vdev_param_map; ar->wmi.pdev_param = &wmi_10x_pdev_param_map; ar->wmi.peer_flags = &wmi_10_2_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_10_1: ar->wmi.cmd = &wmi_10x_cmd_map; @@ -9273,6 +9300,7 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_10x_vdev_param_map; ar->wmi.pdev_param = &wmi_10x_pdev_param_map; ar->wmi.peer_flags = &wmi_10x_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_MAIN: ar->wmi.cmd = &wmi_cmd_map; @@ -9280,9 +9308,11 @@ int ath10k_wmi_attach(struct ath10k *ar) ar->wmi.vdev_param = &wmi_vdev_param_map; ar->wmi.pdev_param = &wmi_pdev_param_map; ar->wmi.peer_flags = &wmi_peer_flags_map; + ar->wmi_key_cipher = wmi_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_TLV: ath10k_wmi_tlv_attach(ar); + ar->wmi_key_cipher = wmi_tlv_key_cipher_suites; break; case ATH10K_FW_WMI_OP_VERSION_UNSET: case ATH10K_FW_WMI_OP_VERSION_MAX: diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 1f82f101e23d..f849481ed65e 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4931,15 +4931,30 @@ struct wmi_key_seq_counter { __le32 key_seq_counter_h; } __packed; -#define WMI_CIPHER_NONE 0x0 /* clear key */ -#define WMI_CIPHER_WEP 0x1 -#define WMI_CIPHER_TKIP 0x2 -#define WMI_CIPHER_AES_OCB 0x3 -#define WMI_CIPHER_AES_CCM 0x4 -#define WMI_CIPHER_WAPI 0x5 -#define WMI_CIPHER_CKIP 0x6 -#define WMI_CIPHER_AES_CMAC 0x7 -#define WMI_CIPHER_AES_GCM 0x8 +enum wmi_cipher_suites { + WMI_CIPHER_NONE, + WMI_CIPHER_WEP, + WMI_CIPHER_TKIP, + WMI_CIPHER_AES_OCB, + WMI_CIPHER_AES_CCM, + WMI_CIPHER_WAPI, + WMI_CIPHER_CKIP, + WMI_CIPHER_AES_CMAC, + WMI_CIPHER_AES_GCM, +}; + +enum wmi_tlv_cipher_suites { + WMI_TLV_CIPHER_NONE, + WMI_TLV_CIPHER_WEP, + WMI_TLV_CIPHER_TKIP, + WMI_TLV_CIPHER_AES_OCB, + WMI_TLV_CIPHER_AES_CCM, + WMI_TLV_CIPHER_WAPI, + WMI_TLV_CIPHER_CKIP, + WMI_TLV_CIPHER_AES_CMAC, + WMI_TLV_CIPHER_ANY, + WMI_TLV_CIPHER_AES_GCM, +}; struct wmi_vdev_install_key_cmd { __le32 vdev_id; -- cgit v1.2.3 From 05e7ba24b10d30ff40150073f448da4cf26ba189 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 8 Feb 2019 14:55:28 +0200 Subject: ath10k: implement set_base_macaddr to fix rx-bssid mask in multiple APs conf Many integrated QCA9984 WiFis in various IPQ806x platform routers from various vendors (Netgear R7800, ZyXEL NBG6817, TP-LINK C2600, etc.) have either blank, bogus or non-unique MAC-addresses in their calibration data. As a result, OpenWrt utilizes a discouraged binary calibration data patching method that allows to modify the device's MAC-addresses right at the source. This is because the ath10k' firmware extracts the MAC address from the supplied radio/calibration data and issues a response to the ath10k linux driver. Which was designed to take the main MAC in ath10k_wmi_event_ready(). Part of the "setting an alternate MAC" issue was already tackled by a patch from Brian Norris: commit 9d5804662ce1 ("ath10k: retrieve MAC address from system firmware if provided") by allowing the option to specify an alternate MAC-address with the established device_get_mac_address() function which extracts the right address from DeviceTree/fwnode mac-address or local-mac-address properties and saves it for later. However, Ben Greear noted that the Qualcomm's ath10k firmware is liable to not properly calculate its rx-bssid mask in this case. This can cause issues in the popluar "multiple AP with a single ath10k instance" configurations. To improve MAC address handling, Felix Fietkau suggested to call pdev_set_base_macaddr_cmdid before bringing up the first vif and use the first vif MAC address there. Which is in ath10k_core_start(). This patch implement Felix Fietkau's request to "call pdev_set_base_macaddr_cmdid before bringing up the first vif". The pdev_set_base_macaddr_cmdid is already declared for all devices and version. The driver just needed the support code for this function. Tested on: QCA9880/CUS223, firmwares: 10.2.4.13-2, 10.2.4.70.44, 10.2.4-1.0-00041 QCA9887/MR33 firmware:10.2.4-1.0-00033 QCA4019/RT-AC58U firmware: 10.4-3.4-00104, 10.4-3.5.3-00057 QCA9984/R7800 firmware: Candela Technologies (CT) Firmware BugLink: https://lists.openwrt.org/pipermail/openwrt-devel/2018-November/014595.html Fixes: 9d5804662ce1 ("ath10k: retrieve MAC address from system firmware if provided") Cc: Brian Norris Cc: Ben Greear Cc: Felix Fietkau Cc: Mathias Kresin Signed-off-by: Christian Lamparter Tested-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 7 +++++++ drivers/net/wireless/ath/ath10k/wmi-ops.h | 18 ++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.c | 21 +++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 4 ++++ 4 files changed, 50 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index c9b75b69de63..1ce4645dac34 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2659,6 +2659,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, goto err_hif_stop; } + status = ath10k_wmi_pdev_set_base_macaddr(ar, ar->mac_addr); + if (status && status != -EOPNOTSUPP) { + ath10k_err(ar, + "failed to set base mac address: %d\n", status); + goto err_hif_stop; + } + /* Some firmware revisions do not properly set up hardware rx filter * registers. * diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index e92d00a6a2a1..015084220857 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -69,6 +69,8 @@ struct wmi_ops { struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt); struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar); + struct sk_buff *(*gen_pdev_set_base_macaddr)(struct ath10k *ar, + const u8 macaddr[ETH_ALEN]); struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g, u16 ctl2g, u16 ctl5g, enum wmi_dfs_region dfs_reg); @@ -519,6 +521,22 @@ ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g, ar->wmi.cmd->pdev_set_regdomain_cmdid); } +static inline int +ath10k_wmi_pdev_set_base_macaddr(struct ath10k *ar, const u8 macaddr[ETH_ALEN]) +{ + struct sk_buff *skb; + + if (!ar->wmi.ops->gen_pdev_set_base_macaddr) + return -EOPNOTSUPP; + + skb = ar->wmi.ops->gen_pdev_set_base_macaddr(ar, macaddr); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->pdev_set_base_macaddr_cmdid); +} + static inline int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 903aa8cffc43..cb876c221d8f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -6286,6 +6286,25 @@ int ath10k_wmi_connect(struct ath10k *ar) return 0; } +static struct sk_buff * +ath10k_wmi_op_gen_pdev_set_base_macaddr(struct ath10k *ar, + const u8 macaddr[ETH_ALEN]) +{ + struct wmi_pdev_set_base_macaddr_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); + if (!skb) + return ERR_PTR(-ENOMEM); + + cmd = (struct wmi_pdev_set_base_macaddr_cmd *)skb->data; + ether_addr_copy(cmd->mac_addr.addr, macaddr); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi pdev basemac %pM\n", macaddr); + return skb; +} + static struct sk_buff * ath10k_wmi_op_gen_pdev_set_rd(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g, u16 ctl2g, u16 ctl5g, @@ -9095,6 +9114,7 @@ static const struct wmi_ops wmi_10_2_ops = { .gen_peer_create = ath10k_wmi_op_gen_peer_create, .gen_peer_delete = ath10k_wmi_op_gen_peer_delete, .gen_peer_flush = ath10k_wmi_op_gen_peer_flush, + .gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr, .gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param, .gen_set_psmode = ath10k_wmi_op_gen_set_psmode, .gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps, @@ -9213,6 +9233,7 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume, + .gen_pdev_set_base_macaddr = ath10k_wmi_op_gen_pdev_set_base_macaddr, .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd, .gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param, .gen_init = ath10k_wmi_10_4_op_gen_init, diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index f849481ed65e..86f128b9a34a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4085,6 +4085,10 @@ struct wmi_pdev_set_param_cmd { __le32 param_value; } __packed; +struct wmi_pdev_set_base_macaddr_cmd { + struct wmi_mac_addr mac_addr; +} __packed; + /* valid period is 1 ~ 60000ms, unit in millisecond */ #define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000 -- cgit v1.2.3 From 185be1c66469b2c31bd3a0502b3cdf0e654f95eb Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 8 Feb 2019 14:55:31 +0200 Subject: ath10k: enable bus layer suspend/resume for WCN3990 Register snoc bus layer suspend/resume PM ops and configure the wakeup source(CE2) for the device. Testing: Tested on WCN3990 HW. Tested FW: WLAN.HL.2.0-01192-QCAHLSWMTPLZ-1. Signed-off-by: Govind Singh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/snoc.c | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 097211daaa46..eff19fd543c8 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -30,6 +30,7 @@ #define ATH10K_SNOC_RX_POST_RETRY_MS 50 #define CE_POLL_PIPE 4 +#define ATH10K_SNOC_WAKE_IRQ 2 static char *const ce_name[] = { "WLAN_CE_0", @@ -1048,6 +1049,46 @@ err_wlan_enable: return ret; } +#ifdef CONFIG_PM +static int ath10k_snoc_hif_suspend(struct ath10k *ar) +{ + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + int ret; + + if (!device_may_wakeup(ar->dev)) + return -EPERM; + + ret = enable_irq_wake(ar_snoc->ce_irqs[ATH10K_SNOC_WAKE_IRQ].irq_line); + if (ret) { + ath10k_err(ar, "failed to enable wakeup irq :%d\n", ret); + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc device suspended\n"); + + return ret; +} + +static int ath10k_snoc_hif_resume(struct ath10k *ar) +{ + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + int ret; + + if (!device_may_wakeup(ar->dev)) + return -EPERM; + + ret = disable_irq_wake(ar_snoc->ce_irqs[ATH10K_SNOC_WAKE_IRQ].irq_line); + if (ret) { + ath10k_err(ar, "failed to disable wakeup irq: %d\n", ret); + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc device resumed\n"); + + return ret; +} +#endif + static const struct ath10k_hif_ops ath10k_snoc_hif_ops = { .read32 = ath10k_snoc_read32, .write32 = ath10k_snoc_write32, @@ -1061,6 +1102,10 @@ static const struct ath10k_hif_ops ath10k_snoc_hif_ops = { .send_complete_check = ath10k_snoc_hif_send_complete_check, .get_free_queue_number = ath10k_snoc_hif_get_free_queue_number, .get_target_info = ath10k_snoc_hif_get_target_info, +#ifdef CONFIG_PM + .suspend = ath10k_snoc_hif_suspend, + .resume = ath10k_snoc_hif_resume, +#endif }; static const struct ath10k_bus_ops ath10k_snoc_bus_ops = { -- cgit v1.2.3 From de8781d7e74d0a5ba7938330476c9d33f7db4c83 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 8 Feb 2019 14:55:33 +0200 Subject: ath10k: disable interface pause wow config for integrated chipset wow pause iface config controls the PCI D0/D3-WOW cases for pcie bus state. Firmware does not expects WOW_IFACE_PAUSE_ENABLED config for bus/link that cannot be suspended ex:snoc and does not trigger common subsystem shutdown. Disable interface pause wow config for integrated chipset(WCN3990) for correct WOW configuration in the firmware. Testing: Tested on WCN3990 HW. Tested FW: WLAN.HL.2.0-01192-QCAHLSWMTPLZ-1. Signed-off-by: Govind Singh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 5 +++-- drivers/net/wireless/ath/ath10k/core.h | 2 ++ drivers/net/wireless/ath/ath10k/coredump.c | 2 +- drivers/net/wireless/ath/ath10k/debug.c | 4 ++-- drivers/net/wireless/ath/ath10k/htc.c | 6 +++--- drivers/net/wireless/ath/ath10k/htt_rx.c | 10 +++++----- drivers/net/wireless/ath/ath10k/htt_tx.c | 6 +++--- drivers/net/wireless/ath/ath10k/pci.c | 3 ++- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 ++ drivers/net/wireless/ath/ath10k/wmi-tlv.h | 7 +++++++ 11 files changed, 31 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 1ce4645dac34..f64008b5da0d 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2994,8 +2994,9 @@ err: int ath10k_core_register(struct ath10k *ar, const struct ath10k_bus_params *bus_params) { - ar->chip_id = bus_params->chip_id; - ar->dev_type = bus_params->dev_type; + ar->bus_param.chip_id = bus_params->chip_id; + ar->bus_param.dev_type = bus_params->dev_type; + ar->bus_param.link_can_suspend = bus_params->link_can_suspend; queue_work(ar->workqueue, &ar->register_work); return 0; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index f2278d0c3efa..23d7a34e3714 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -922,6 +922,7 @@ enum ath10k_dev_type { struct ath10k_bus_params { u32 chip_id; enum ath10k_dev_type dev_type; + bool link_can_suspend; }; struct ath10k { @@ -1191,6 +1192,7 @@ struct ath10k { enum ath10k_radar_confirmation_state radar_conf_state; struct ath10k_radar_found_info last_radar_info; struct work_struct radar_confirmation_work; + struct ath10k_bus_params bus_param; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c index eadae2f9206b..bf84e999466f 100644 --- a/drivers/net/wireless/ath/ath10k/coredump.c +++ b/drivers/net/wireless/ath/ath10k/coredump.c @@ -1167,7 +1167,7 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar) dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION); guid_copy(&dump_data->guid, &crash_data->guid); - dump_data->chip_id = cpu_to_le32(ar->chip_id); + dump_data->chip_id = cpu_to_le32(ar->bus_param.chip_id); dump_data->bus_type = cpu_to_le32(0); dump_data->target_version = cpu_to_le32(ar->target_version); dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major); diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 02988fc378a1..9f2534d6b56f 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -58,7 +58,7 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar) ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x", ar->hw_params.name, ar->target_version, - ar->chip_id, + ar->bus_param.chip_id, ar->id.subsystem_vendor, ar->id.subsystem_device); ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n", @@ -625,7 +625,7 @@ static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf, size_t len; char buf[50]; - len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id); + len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->bus_param.chip_id); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 28daed5981a1..7654a21323ce 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -53,7 +53,7 @@ static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc, { struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); - if (htc->ar->dev_type != ATH10K_DEV_TYPE_HL) + if (htc->ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); skb_pull(skb, sizeof(struct ath10k_htc_hdr)); } @@ -138,7 +138,7 @@ int ath10k_htc_send(struct ath10k_htc *htc, ath10k_htc_prepare_tx_skb(ep, skb); skb_cb->eid = eid; - if (ar->dev_type != ATH10K_DEV_TYPE_HL) { + if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) { skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE); ret = dma_mapping_error(dev, skb_cb->paddr); @@ -161,7 +161,7 @@ int ath10k_htc_send(struct ath10k_htc *htc, return 0; err_unmap: - if (ar->dev_type != ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); err_credits: if (ep->tx_credit_flow_enabled) { diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 89d84dc73a44..a01d1ae6b398 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -265,7 +265,7 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar) struct ath10k_htt *htt = &ar->htt; int ret; - if (ar->dev_type == ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) return 0; spin_lock_bh(&htt->rx_ring.lock); @@ -282,7 +282,7 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar) void ath10k_htt_rx_free(struct ath10k_htt *htt) { - if (htt->ar->dev_type == ATH10K_DEV_TYPE_HL) + if (htt->ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) return; del_timer_sync(&htt->rx_ring.refill_retry_timer); @@ -760,7 +760,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) size_t size; struct timer_list *timer = &htt->rx_ring.refill_retry_timer; - if (ar->dev_type == ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) return 0; htt->rx_confused = false; @@ -3237,7 +3237,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; } case HTT_T2H_MSG_TYPE_RX_IND: - if (ar->dev_type == ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb); @@ -3533,7 +3533,7 @@ void ath10k_htt_set_rx_ops(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; - if (ar->dev_type == ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) htt->rx_ops = &htt_rx_ops_hl; else if (ar->hw_params.target_64bit) htt->rx_ops = &htt_rx_ops_64; diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 7b89d950c26d..33639a6bf7d6 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -495,7 +495,7 @@ int ath10k_htt_tx_start(struct ath10k_htt *htt) if (htt->tx_mem_allocated) return 0; - if (ar->dev_type == ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) return 0; ret = ath10k_htt_tx_alloc_buf(htt); @@ -1224,7 +1224,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) return 0; err_unmap_msdu: - if (ar->dev_type != ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); err_free_txdesc: dev_kfree_skb_any(txdesc); @@ -1763,7 +1763,7 @@ void ath10k_htt_set_tx_ops(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; - if (ar->dev_type == ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) htt->tx_ops = &htt_tx_ops_hl; else if (ar->hw_params.target_64bit) htt->tx_ops = &htt_tx_ops_64; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 7dd35599d09f..eb18e8ea0b54 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2283,7 +2283,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) return 1; case QCA6164_2_1_DEVICE_ID: case QCA6174_2_1_DEVICE_ID: - switch (MS(ar->chip_id, SOC_CHIP_ID_REV)) { + switch (MS(ar->bus_param.chip_id, SOC_CHIP_ID_REV)) { case QCA6174_HW_1_0_CHIP_ID_REV: case QCA6174_HW_1_1_CHIP_ID_REV: case QCA6174_HW_2_1_CHIP_ID_REV: @@ -3636,6 +3636,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, } bus_params.dev_type = ATH10K_DEV_TYPE_LL; + bus_params.link_can_suspend = true; bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (bus_params.chip_id == 0xffffffff) { ath10k_err(ar, "failed to get chip id\n"); diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 23606b6972d0..f13d88906b5a 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -95,7 +95,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); - if (ar->dev_type != ATH10K_DEV_TYPE_HL) + if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); ath10k_report_offchan_tx(htt->ar, msdu); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 7621dfe8a61c..5d05bff2c5da 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3323,6 +3323,8 @@ ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k *ar) cmd = (void *)tlv->value; cmd->enable = __cpu_to_le32(1); + if (!ar->bus_param.link_can_suspend) + cmd->pause_iface_config = __cpu_to_le32(WOW_IFACE_PAUSE_DISABLED); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow enable\n"); return skb; diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 298d917f72cd..4fba5815cd61 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -2001,8 +2001,15 @@ struct wmi_tlv_set_quiet_cmd { __le32 enabled; } __packed; +enum wmi_tlv_wow_interface_cfg { + WOW_IFACE_PAUSE_ENABLED, + WOW_IFACE_PAUSE_DISABLED +}; + struct wmi_tlv_wow_enable_cmd { __le32 enable; + __le32 pause_iface_config; + __le32 flags; } __packed; struct wmi_tlv_wow_host_wakeup_ind { -- cgit v1.2.3 From c40e448e0bcf1541c0d0c42a197ef4f183a83db0 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 8 Feb 2019 14:55:35 +0200 Subject: ath10k: request credit report if flow control enabled on ep FW credit flow control is enabled for only WMI ctrl service(CE3) but credit update is requested unconditionally on all HTC services as part of HTC tx in CE3/CE0/CE4. This is causing WOW failure as FW is not expecting credit report request on other end-points(CE0/CE4). Request credit report only on those endpoints where credit flow control is enabled. Testing: Tested on WCN3990 HW. Tested FW: WLAN.HL.2.0-01192-QCAHLSWMTPLZ-1. Signed-off-by: Govind Singh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 7654a21323ce..5aa57a01c033 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -88,7 +88,8 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep, hdr->eid = ep->eid; hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr)); hdr->flags = 0; - hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE; + if (ep->tx_credit_flow_enabled) + hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE; spin_lock_bh(&ep->htc->tx_lock); hdr->seq_no = ep->seq_no++; -- cgit v1.2.3 From 25733c4e67df7f29a599bbd9ed313c172d72a02b Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 8 Feb 2019 14:55:38 +0200 Subject: ath10k: pci: use mutex for diagnostic window CE polling The DIAG copy engine is only used via polling, but it holds a spinlock with softirqs disabled. Each iteration of our read/write loops can theoretically take 20ms (two 10ms timeout loops), and this loop can be run an unbounded number of times while holding the spinlock -- dependent on the request size given by the caller. As of commit 39501ea64116 ("ath10k: download firmware via diag Copy Engine for QCA6174 and QCA9377."), we transfer large chunks of firmware memory using this mechanism. With large enough firmware segments, this becomes an exceedingly long period for disabling soft IRQs. For example, with a 500KiB firmware segment, in testing QCA6174A, I see 200 loop iterations of about 50-100us each, which can total about 10-20ms. In reality, we don't really need to block softirqs for this duration. The DIAG CE is only used in polling mode, and we only need to hold ce_lock to make sure any CE bookkeeping is done without screwing up another CE. Otherwise, we only need to ensure exclusion between ath10k_pci_diag_{read,write}_mem() contexts. This patch moves to use fine-grained locking for the shared ce_lock, while adding a new mutex just to ensure mutual exclusion of diag read/write operations. Tested on QCA6174A, firmware version WLAN.RM.4.4.1-00132-QCARMSWPZ-1. Fixes: 39501ea64116 ("ath10k: download firmware via diag Copy Engine for QCA6174 and QCA9377.") Signed-off-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 41 +++++++++++++---------------------- drivers/net/wireless/ath/ath10k/pci.h | 3 +++ 2 files changed, 18 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index eb18e8ea0b54..600ddaad8845 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -913,7 +913,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, int nbytes) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret = 0; u32 *buf; unsigned int completed_nbytes, alloc_nbytes, remaining_bytes; @@ -924,8 +923,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, void *data_buf = NULL; int i; - spin_lock_bh(&ce->ce_lock); - + mutex_lock(&ar_pci->ce_diag_mutex); ce_diag = ar_pci->ce_diag; /* @@ -960,19 +958,17 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, nbytes = min_t(unsigned int, remaining_bytes, DIAG_TRANSFER_LIMIT); - ret = ce_diag->ops->ce_rx_post_buf(ce_diag, &ce_data, ce_data); + ret = ath10k_ce_rx_post_buf(ce_diag, &ce_data, ce_data); if (ret != 0) goto done; /* Request CE to send from Target(!) address to Host buffer */ - ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0, - 0); + ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0, 0); if (ret) goto done; i = 0; - while (ath10k_ce_completed_send_next_nolock(ce_diag, - NULL) != 0) { + while (ath10k_ce_completed_send_next(ce_diag, NULL) != 0) { udelay(DIAG_ACCESS_CE_WAIT_US); i += DIAG_ACCESS_CE_WAIT_US; @@ -983,10 +979,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, } i = 0; - while (ath10k_ce_completed_recv_next_nolock(ce_diag, - (void **)&buf, - &completed_nbytes) - != 0) { + while (ath10k_ce_completed_recv_next(ce_diag, (void **)&buf, + &completed_nbytes) != 0) { udelay(DIAG_ACCESS_CE_WAIT_US); i += DIAG_ACCESS_CE_WAIT_US; @@ -1019,7 +1013,7 @@ done: dma_free_coherent(ar->dev, alloc_nbytes, data_buf, ce_data_base); - spin_unlock_bh(&ce->ce_lock); + mutex_unlock(&ar_pci->ce_diag_mutex); return ret; } @@ -1067,7 +1061,6 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, const void *data, int nbytes) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_ce *ce = ath10k_ce_priv(ar); int ret = 0; u32 *buf; unsigned int completed_nbytes, alloc_nbytes, remaining_bytes; @@ -1076,8 +1069,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, dma_addr_t ce_data_base = 0; int i; - spin_lock_bh(&ce->ce_lock); - + mutex_lock(&ar_pci->ce_diag_mutex); ce_diag = ar_pci->ce_diag; /* @@ -1118,7 +1110,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, memcpy(data_buf, data, nbytes); /* Set up to receive directly into Target(!) address */ - ret = ce_diag->ops->ce_rx_post_buf(ce_diag, &address, address); + ret = ath10k_ce_rx_post_buf(ce_diag, &address, address); if (ret != 0) goto done; @@ -1126,14 +1118,12 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, * Request CE to send caller-supplied data that * was copied to bounce buffer to Target(!) address. */ - ret = ath10k_ce_send_nolock(ce_diag, NULL, ce_data_base, - nbytes, 0, 0); + ret = ath10k_ce_send(ce_diag, NULL, ce_data_base, nbytes, 0, 0); if (ret != 0) goto done; i = 0; - while (ath10k_ce_completed_send_next_nolock(ce_diag, - NULL) != 0) { + while (ath10k_ce_completed_send_next(ce_diag, NULL) != 0) { udelay(DIAG_ACCESS_CE_WAIT_US); i += DIAG_ACCESS_CE_WAIT_US; @@ -1144,10 +1134,8 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, } i = 0; - while (ath10k_ce_completed_recv_next_nolock(ce_diag, - (void **)&buf, - &completed_nbytes) - != 0) { + while (ath10k_ce_completed_recv_next(ce_diag, (void **)&buf, + &completed_nbytes) != 0) { udelay(DIAG_ACCESS_CE_WAIT_US); i += DIAG_ACCESS_CE_WAIT_US; @@ -1182,7 +1170,7 @@ done: ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n", address, ret); - spin_unlock_bh(&ce->ce_lock); + mutex_unlock(&ar_pci->ce_diag_mutex); return ret; } @@ -3462,6 +3450,7 @@ int ath10k_pci_setup_resource(struct ath10k *ar) spin_lock_init(&ce->ce_lock); spin_lock_init(&ar_pci->ps_lock); + mutex_init(&ar_pci->ce_diag_mutex); timer_setup(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, 0); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index e8d86331c539..a9270fa6463c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -19,6 +19,7 @@ #define _PCI_H_ #include +#include #include "hw.h" #include "ce.h" @@ -128,6 +129,8 @@ struct ath10k_pci { /* Copy Engine used for Diagnostic Accesses */ struct ath10k_ce_pipe *ce_diag; + /* For protecting ce_diag */ + struct mutex ce_diag_mutex; struct ath10k_ce ce; struct timer_list rx_post_retry; -- cgit v1.2.3 From 3c545a25939c27f85430588110c657ede5fdfe0a Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Fri, 8 Feb 2019 15:50:10 +0200 Subject: ath10k: enable Factory Test Mode for WCN3990 The support to put WCN3990 firmware into Factory test mode is not present currently. The WCN3990 firmware can operate in Factory test mode based on the mode it receives in the wlan enable message from the host driver. When the host driver is started in testmode send the operating mode as UTF mode, to the WCN3990 firmware, in the wlan enable message to start the firmware in Factory test mode. Tested on: WCN3990 Tested FW: WLAN.HL.2.0-01192-QCAHLSWMTPLZ-1. Signed-off-by: Rakesh Pillai Reviewed-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 3 ++- drivers/net/wireless/ath/ath10k/core.c | 2 +- drivers/net/wireless/ath/ath10k/hif.h | 7 ++++--- drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath10k/pci.c | 3 ++- drivers/net/wireless/ath/ath10k/sdio.c | 3 ++- drivers/net/wireless/ath/ath10k/snoc.c | 20 ++++++++++++++++---- drivers/net/wireless/ath/ath10k/testmode.c | 2 +- drivers/net/wireless/ath/ath10k/usb.c | 3 ++- 9 files changed, 31 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 4cd69aca75e2..66b7ca9ced17 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -661,7 +661,8 @@ static void ath10k_ahb_hif_stop(struct ath10k *ar) ath10k_pci_flush(ar); } -static int ath10k_ahb_hif_power_up(struct ath10k *ar) +static int ath10k_ahb_hif_power_up(struct ath10k *ar, + enum ath10k_firmware_mode fw_mode) { int ret; diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index f64008b5da0d..ca6085076c68 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2780,7 +2780,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar) struct bmi_target_info target_info; int ret = 0; - ret = ath10k_hif_power_up(ar); + ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL); if (ret) { ath10k_err(ar, "could not power on hif bus (%d)\n", ret); return ret; diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 5f7f1e08866f..04320d792c88 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -83,7 +83,7 @@ struct ath10k_hif_ops { void (*write32)(struct ath10k *ar, u32 address, u32 value); /* Power up the device and enter BMI transfer mode for FW download */ - int (*power_up)(struct ath10k *ar); + int (*power_up)(struct ath10k *ar, enum ath10k_firmware_mode fw_mode); /* Power down the device and free up resources. stop() must be called * before this if start() was called earlier @@ -174,9 +174,10 @@ static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar, return ar->hif.ops->get_free_queue_number(ar, pipe_id); } -static inline int ath10k_hif_power_up(struct ath10k *ar) +static inline int ath10k_hif_power_up(struct ath10k *ar, + enum ath10k_firmware_mode fw_mode) { - return ar->hif.ops->power_up(ar); + return ar->hif.ops->power_up(ar, fw_mode); } static inline void ath10k_hif_power_down(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 6c66a3435d57..c8af35ff2019 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4705,7 +4705,7 @@ static int ath10k_start(struct ieee80211_hw *hw) goto err; } - ret = ath10k_hif_power_up(ar); + ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL); if (ret) { ath10k_err(ar, "Could not init hif: %d\n", ret); goto err_off; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 600ddaad8845..71d854e2f9fc 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2794,7 +2794,8 @@ static int ath10k_pci_chip_reset(struct ath10k *ar) return ar_pci->pci_hard_reset(ar); } -static int ath10k_pci_hif_power_up(struct ath10k *ar) +static int ath10k_pci_hif_power_up(struct ath10k *ar, + enum ath10k_firmware_mode fw_mode) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index f3b2e148e6ce..7654536b830b 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -1381,7 +1381,8 @@ static int ath10k_sdio_hif_disable_intrs(struct ath10k *ar) return ret; } -static int ath10k_sdio_hif_power_up(struct ath10k *ar) +static int ath10k_sdio_hif_power_up(struct ath10k *ar, + enum ath10k_firmware_mode fw_mode) { struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar); struct sdio_func *func = ar_sdio->func; diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index eff19fd543c8..b81b02ae384f 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -957,7 +957,8 @@ static int ath10k_snoc_init_pipes(struct ath10k *ar) return 0; } -static int ath10k_snoc_wlan_enable(struct ath10k *ar) +static int ath10k_snoc_wlan_enable(struct ath10k *ar, + enum ath10k_firmware_mode fw_mode) { struct ath10k_tgt_pipe_cfg tgt_cfg[CE_COUNT_MAX]; struct ath10k_qmi_wlan_enable_cfg cfg; @@ -991,7 +992,17 @@ static int ath10k_snoc_wlan_enable(struct ath10k *ar) cfg.shadow_reg_cfg = (struct ath10k_shadow_reg_cfg *) &target_shadow_reg_cfg_map; - mode = QMI_WLFW_MISSION_V01; + switch (fw_mode) { + case ATH10K_FIRMWARE_MODE_NORMAL: + mode = QMI_WLFW_MISSION_V01; + break; + case ATH10K_FIRMWARE_MODE_UTF: + mode = QMI_WLFW_FTM_V01; + break; + default: + ath10k_err(ar, "invalid firmware mode %d\n", fw_mode); + return -EINVAL; + } return ath10k_qmi_wlan_enable(ar, &cfg, mode, NULL); @@ -1020,14 +1031,15 @@ static void ath10k_snoc_hif_power_down(struct ath10k *ar) ath10k_ce_free_rri(ar); } -static int ath10k_snoc_hif_power_up(struct ath10k *ar) +static int ath10k_snoc_hif_power_up(struct ath10k *ar, + enum ath10k_firmware_mode fw_mode) { int ret; ath10k_dbg(ar, ATH10K_DBG_SNOC, "%s:WCN3990 driver state = %d\n", __func__, ar->state); - ret = ath10k_snoc_wlan_enable(ar); + ret = ath10k_snoc_wlan_enable(ar, fw_mode); if (ret) { ath10k_err(ar, "failed to enable wcn3990: %d\n", ret); return ret; diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index c24ee616833c..67faafecaf06 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -270,7 +270,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", ar->testmode.utf_mode_fw.fw_file.wmi_op_version); - ret = ath10k_hif_power_up(ar); + ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_UTF); if (ret) { ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret); ar->state = ATH10K_STATE_OFF; diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c index f731d35ee76d..d3677765f96c 100644 --- a/drivers/net/wireless/ath/ath10k/usb.c +++ b/drivers/net/wireless/ath/ath10k/usb.c @@ -706,7 +706,8 @@ static void ath10k_usb_hif_send_complete_check(struct ath10k *ar, { } -static int ath10k_usb_hif_power_up(struct ath10k *ar) +static int ath10k_usb_hif_power_up(struct ath10k *ar, + enum ath10k_firmware_mode fw_mode) { return 0; } -- cgit v1.2.3 From 1863008369ae0407508033b4b00f98b985adeb15 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Fri, 8 Feb 2019 15:50:24 +0200 Subject: ath10k: fix shadow register implementation for WCN3990 WCN3990 supports shadow registers write operation support for copy engine for regular operation in powersave mode. Since WCN3990 is a 64-bit target, the shadow register implementation needs to be done in the copy engine handlers for 64-bit target. Currently the shadow register implementation is present in the 32-bit target handlers of copy engine. Fix the shadow register copy engine write operation implementation for 64-bit target(WCN3990). Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1 Fixes: b7ba83f7c414 ("ath10k: add support for shadow register for WNC3990") Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 26 +++++++++++++------------- drivers/net/wireless/ath/ath10k/ce.h | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 8b4a9102d7eb..32f4802b3942 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -545,14 +545,8 @@ static int _ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, write_index = CE_RING_IDX_INCR(nentries_mask, write_index); /* WORKAROUND */ - if (!(flags & CE_SEND_FLAG_GATHER)) { - if (ar->hw_params.shadow_reg_support) - ath10k_ce_shadow_src_ring_write_index_set(ar, ce_state, - write_index); - else - ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, - write_index); - } + if (!(flags & CE_SEND_FLAG_GATHER)) + ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index); src_ring->write_index = write_index; exit: @@ -626,8 +620,14 @@ static int _ath10k_ce_send_nolock_64(struct ath10k_ce_pipe *ce_state, /* Update Source Ring Write Index */ write_index = CE_RING_IDX_INCR(nentries_mask, write_index); - if (!(flags & CE_SEND_FLAG_GATHER)) - ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index); + if (!(flags & CE_SEND_FLAG_GATHER)) { + if (ar->hw_params.shadow_reg_support) + ath10k_ce_shadow_src_ring_write_index_set(ar, ce_state, + write_index); + else + ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, + write_index); + } src_ring->write_index = write_index; exit: @@ -1449,12 +1449,12 @@ static int ath10k_ce_alloc_shadow_base(struct ath10k *ar, u32 nentries) { src_ring->shadow_base_unaligned = kcalloc(nentries, - sizeof(struct ce_desc), + sizeof(struct ce_desc_64), GFP_KERNEL); if (!src_ring->shadow_base_unaligned) return -ENOMEM; - src_ring->shadow_base = (struct ce_desc *) + src_ring->shadow_base = (struct ce_desc_64 *) PTR_ALIGN(src_ring->shadow_base_unaligned, CE_DESC_RING_ALIGN); return 0; @@ -1506,7 +1506,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries); if (ret) { dma_free_coherent(ar->dev, - (nentries * sizeof(struct ce_desc) + + (nentries * sizeof(struct ce_desc_64) + CE_DESC_RING_ALIGN), src_ring->base_addr_owner_space_unaligned, base_addr); diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index c44a52e8a6af..f3b4f7ec863d 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -118,7 +118,7 @@ struct ath10k_ce_ring { dma_addr_t base_addr_ce_space; char *shadow_base_unaligned; - struct ce_desc *shadow_base; + struct ce_desc_64 *shadow_base; /* keep last */ void *per_transfer_context[0]; -- cgit v1.2.3 From cbd72b485214f085a022b56a3051524577d891fe Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Thu, 7 Feb 2019 20:05:58 -0800 Subject: net: dsa: microchip: add switch offload forwarding support The flag offload_fwd_mark is set as the switch can forward frames by itself. This can be considered a fix to a problem introduced in commit c2e866911e254067 where the port membership are not set in sync. The flag offload_fwd_mark just needs to be set in tag_ksz.c to prevent the software bridge from forwarding duplicate multicast frames. Fixes: c2e866911e254067 ("microchip: break KSZ9477 DSA driver into two files") Signed-off-by: Tristram Ha Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz9477.c | 7 ++++--- net/dsa/tag_ksz.c | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 89ed059bb576..674d77e1b029 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -397,6 +397,7 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port, struct ksz_port *p = &dev->ports[port]; u8 data; int member = -1; + int forward = dev->member; ksz_pread8(dev, port, P_STP_CTRL, &data); data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); @@ -464,10 +465,10 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port, } /* When topology has changed the function ksz_update_port_member - * should be called to modify port forwarding behavior. However - * as the offload_fwd_mark indication cannot be reported here - * the switch forwarding function is not enabled. + * should be called to modify port forwarding behavior. */ + if (forward != dev->member) + ksz_update_port_member(dev, port); } static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port) diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c index da71b9e2af52..927e9c86f745 100644 --- a/net/dsa/tag_ksz.c +++ b/net/dsa/tag_ksz.c @@ -67,6 +67,8 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb, pskb_trim_rcsum(skb, skb->len - len); + skb->offload_fwd_mark = true; + return skb; } -- cgit v1.2.3 From 1fbf1252df0e4212e17f98130cb5372b3bc019b0 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 6 Feb 2019 15:00:19 -0800 Subject: mlx5: use RCU lock in mlx5_eq_cq_get() mlx5_eq_cq_get() is called in IRQ handler, the spinlock inside gets a lot of contentions when we test some heavy workload with 60 RX queues and 80 CPU's, and it is clearly shown in the flame graph. In fact, radix_tree_lookup() is perfectly fine with RCU read lock, we don't have to take a spinlock on this hot path. This is pretty much similar to commit 291c566a2891 ("net/mlx4_core: Fix racy CQ (Completion Queue) free"). Slow paths are still serialized with the spinlock, and with synchronize_irq() it should be safe to just move the fast path to RCU read lock. This patch itself reduces the latency by about 50% for our memcached workload on a 4.14 kernel we test. In upstream, as pointed out by Saeed, this spinlock gets some rework in commit 02d92f790364 ("net/mlx5: CQ Database per EQ"), so the difference could be smaller. Cc: Saeed Mahameed Cc: Tariq Toukan Acked-by: Saeed Mahameed Signed-off-by: Cong Wang Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index ee04aab65a9f..7092457705a2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -114,11 +114,11 @@ static struct mlx5_core_cq *mlx5_eq_cq_get(struct mlx5_eq *eq, u32 cqn) struct mlx5_cq_table *table = &eq->cq_table; struct mlx5_core_cq *cq = NULL; - spin_lock(&table->lock); + rcu_read_lock(); cq = radix_tree_lookup(&table->tree, cqn); if (likely(cq)) mlx5_cq_hold(cq); - spin_unlock(&table->lock); + rcu_read_unlock(); return cq; } @@ -371,9 +371,9 @@ int mlx5_eq_add_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq) struct mlx5_cq_table *table = &eq->cq_table; int err; - spin_lock_irq(&table->lock); + spin_lock(&table->lock); err = radix_tree_insert(&table->tree, cq->cqn, cq); - spin_unlock_irq(&table->lock); + spin_unlock(&table->lock); return err; } @@ -383,9 +383,9 @@ int mlx5_eq_del_cq(struct mlx5_eq *eq, struct mlx5_core_cq *cq) struct mlx5_cq_table *table = &eq->cq_table; struct mlx5_core_cq *tmp; - spin_lock_irq(&table->lock); + spin_lock(&table->lock); tmp = radix_tree_delete(&table->tree, cq->cqn); - spin_unlock_irq(&table->lock); + spin_unlock(&table->lock); if (!tmp) { mlx5_core_warn(eq->dev, "cq 0x%x not found in eq 0x%x tree\n", eq->eqn, cq->cqn); -- cgit v1.2.3 From 05fe4ab75cc42c17c934755d6b5e5d34f0540578 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sun, 10 Feb 2019 19:35:30 -0800 Subject: nfp: devlink: use the generic manufacture identifier instead of vendor Vendor may sound ambiguous, let's rename the fab string to "board.manufacture" (which was just added as a generic identifier). Signed-off-by: Jakub Kicinski Reviewed-by: Dirk van der Merwe Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index dddbb0575be9..bf4e124dbdd2 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -178,7 +178,7 @@ static const struct nfp_devlink_versions_simple { } nfp_devlink_versions_hwinfo[] = { { DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, "assembly.partno", }, { DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, "assembly.revision", }, - { "board.vendor", /* fab */ "assembly.vendor", }, + { DEVLINK_INFO_VERSION_GENERIC_BOARD_MANUFACTURE, "assembly.vendor", }, { "board.model", /* code name */ "assembly.model", }, }; -- cgit v1.2.3 From 1f5cf1036cbe4df7f078312561b5fefb2594a3bd Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Sun, 10 Feb 2019 19:35:31 -0800 Subject: nfp: devlink: include vendor/product info in serial number The manufacturing team requests we include vendor and product in the serial number field, as the serial number itself is not unique across manufacturing facilities and products. Signed-off-by: Jakub Kicinski Reviewed-by: Dirk van der Merwe Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index bf4e124dbdd2..080a301f379e 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -258,18 +258,33 @@ nfp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, struct netlink_ext_ack *extack) { struct nfp_pf *pf = devlink_priv(devlink); + const char *sn, *vendor, *part; struct nfp_nsp *nsp; char *buf = NULL; - const char *sn; int err; err = devlink_info_driver_name_put(req, "nfp"); if (err) return err; + vendor = nfp_hwinfo_lookup(pf->hwinfo, "assembly.vendor"); + part = nfp_hwinfo_lookup(pf->hwinfo, "assembly.partno"); sn = nfp_hwinfo_lookup(pf->hwinfo, "assembly.serial"); - if (sn) { - err = devlink_info_serial_number_put(req, sn); + if (vendor && part && sn) { + char *buf; + + buf = kmalloc(strlen(vendor) + strlen(part) + strlen(sn) + 1, + GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf[0] = '\0'; + strcat(buf, vendor); + strcat(buf, part); + strcat(buf, sn); + + err = devlink_info_serial_number_put(req, buf); + kfree(buf); if (err) return err; } -- cgit v1.2.3 From dd27c2e3d0a05c01ff14bb672d1a3f0fdd8f98fc Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 12 Feb 2019 00:20:39 -0800 Subject: bpf: offload: add priv field for drivers Currently bpf_offload_dev does not have any priv pointer, forcing the drivers to work backwards from the netdev in program metadata. This is not great given programs are conceptually associated with the offload device, and it means one or two unnecessary deferences. Add a priv pointer to bpf_offload_dev. Signed-off-by: Jakub Kicinski Reviewed-by: Quentin Monnet Signed-off-by: Daniel Borkmann --- drivers/net/ethernet/netronome/nfp/bpf/main.c | 2 +- drivers/net/ethernet/netronome/nfp/bpf/offload.c | 4 +--- drivers/net/netdevsim/bpf.c | 5 +++-- include/linux/bpf.h | 3 ++- kernel/bpf/offload.c | 10 +++++++++- 5 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c index dccae0319204..275de9f4c61c 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/main.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c @@ -465,7 +465,7 @@ static int nfp_bpf_init(struct nfp_app *app) app->ctrl_mtu = nfp_bpf_ctrl_cmsg_mtu(bpf); } - bpf->bpf_dev = bpf_offload_dev_create(&nfp_bpf_dev_ops); + bpf->bpf_dev = bpf_offload_dev_create(&nfp_bpf_dev_ops, bpf); err = PTR_ERR_OR_ZERO(bpf->bpf_dev); if (err) goto err_free_neutral_maps; diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c index 55c7dbf8b421..15dce97650a5 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c @@ -185,8 +185,6 @@ static void nfp_prog_free(struct nfp_prog *nfp_prog) static int nfp_bpf_verifier_prep(struct bpf_prog *prog) { - struct nfp_net *nn = netdev_priv(prog->aux->offload->netdev); - struct nfp_app *app = nn->app; struct nfp_prog *nfp_prog; int ret; @@ -197,7 +195,7 @@ static int nfp_bpf_verifier_prep(struct bpf_prog *prog) INIT_LIST_HEAD(&nfp_prog->insns); nfp_prog->type = prog->type; - nfp_prog->bpf = app->priv; + nfp_prog->bpf = bpf_offload_dev_priv(prog->aux->offload->offdev); ret = nfp_prog_prepare(nfp_prog, prog->insnsi, prog->len); if (ret) diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c index 172b271c8bd2..f92c43453ec6 100644 --- a/drivers/net/netdevsim/bpf.c +++ b/drivers/net/netdevsim/bpf.c @@ -248,7 +248,7 @@ static int nsim_bpf_create_prog(struct netdevsim *ns, struct bpf_prog *prog) static int nsim_bpf_verifier_prep(struct bpf_prog *prog) { - struct netdevsim *ns = netdev_priv(prog->aux->offload->netdev); + struct netdevsim *ns = bpf_offload_dev_priv(prog->aux->offload->offdev); if (!ns->bpf_bind_accept) return -EOPNOTSUPP; @@ -589,7 +589,8 @@ int nsim_bpf_init(struct netdevsim *ns) if (IS_ERR_OR_NULL(ns->sdev->ddir_bpf_bound_progs)) return -ENOMEM; - ns->sdev->bpf_dev = bpf_offload_dev_create(&nsim_bpf_dev_ops); + ns->sdev->bpf_dev = bpf_offload_dev_create(&nsim_bpf_dev_ops, + ns); err = PTR_ERR_OR_ZERO(ns->sdev->bpf_dev); if (err) return err; diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 7f58828755fd..de18227b3d95 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -773,8 +773,9 @@ int bpf_map_offload_get_next_key(struct bpf_map *map, bool bpf_offload_prog_map_match(struct bpf_prog *prog, struct bpf_map *map); struct bpf_offload_dev * -bpf_offload_dev_create(const struct bpf_prog_offload_ops *ops); +bpf_offload_dev_create(const struct bpf_prog_offload_ops *ops, void *priv); void bpf_offload_dev_destroy(struct bpf_offload_dev *offdev); +void *bpf_offload_dev_priv(struct bpf_offload_dev *offdev); int bpf_offload_dev_netdev_register(struct bpf_offload_dev *offdev, struct net_device *netdev); void bpf_offload_dev_netdev_unregister(struct bpf_offload_dev *offdev, diff --git a/kernel/bpf/offload.c b/kernel/bpf/offload.c index 39dba8c90331..ba635209ae9a 100644 --- a/kernel/bpf/offload.c +++ b/kernel/bpf/offload.c @@ -35,6 +35,7 @@ static DECLARE_RWSEM(bpf_devs_lock); struct bpf_offload_dev { const struct bpf_prog_offload_ops *ops; struct list_head netdevs; + void *priv; }; struct bpf_offload_netdev { @@ -669,7 +670,7 @@ unlock: EXPORT_SYMBOL_GPL(bpf_offload_dev_netdev_unregister); struct bpf_offload_dev * -bpf_offload_dev_create(const struct bpf_prog_offload_ops *ops) +bpf_offload_dev_create(const struct bpf_prog_offload_ops *ops, void *priv) { struct bpf_offload_dev *offdev; int err; @@ -688,6 +689,7 @@ bpf_offload_dev_create(const struct bpf_prog_offload_ops *ops) return ERR_PTR(-ENOMEM); offdev->ops = ops; + offdev->priv = priv; INIT_LIST_HEAD(&offdev->netdevs); return offdev; @@ -700,3 +702,9 @@ void bpf_offload_dev_destroy(struct bpf_offload_dev *offdev) kfree(offdev); } EXPORT_SYMBOL_GPL(bpf_offload_dev_destroy); + +void *bpf_offload_dev_priv(struct bpf_offload_dev *offdev) +{ + return offdev->priv; +} +EXPORT_SYMBOL_GPL(bpf_offload_dev_priv); -- cgit v1.2.3 From 0ff8409b521b7b315bd69c4f1fbff024dc6219f6 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 12 Feb 2019 00:18:02 -0800 Subject: nfp: flower: remove double new line Recent cls_flower offload rewrite added a double new line. Signed-off-by: Jakub Kicinski Reviewed-by: Quentin Monnet Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/offload.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index fe1469d201af..450d7296fd57 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -187,7 +187,6 @@ nfp_flower_calculate_key_layers(struct nfp_app *app, if (ipv4_addrs.mask->dst != cpu_to_be32(~0)) return -EOPNOTSUPP; - flow_rule_match_enc_ports(rule, &enc_ports); if (enc_ports.mask->dst != cpu_to_be16(~0)) return -EOPNOTSUPP; -- cgit v1.2.3 From 48ebab31d424fbdb8ede8914923bec671a933246 Mon Sep 17 00:00:00 2001 From: Nir Dotan Date: Tue, 12 Feb 2019 16:29:51 +0000 Subject: mlxsw: spectrum: Set LAG port collector only when active The LAG port collecting (receive) function was mistakenly set when the port was registered as a LAG member, while it should be set only when the port collection state is set to true. Set LAG port to collecting when it is set to distributing, as described in the IEEE link aggregation standard coupled control mux machine state diagram. Signed-off-by: Nir Dotan Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 62 +++++++++++++++++++------- 1 file changed, 45 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 7c9745cecbbd..9686d3822b92 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4771,9 +4771,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index); if (err) goto err_col_port_add; - err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port, lag_id); - if (err) - goto err_col_port_enable; mlxsw_core_lag_mapping_set(mlxsw_sp->core, lag_id, port_index, mlxsw_sp_port->local_port); @@ -4787,8 +4784,6 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, return 0; -err_col_port_enable: - mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id); err_col_port_add: if (!lag->ref_count) mlxsw_sp_lag_destroy(mlxsw_sp, lag_id); @@ -4807,7 +4802,6 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, lag = mlxsw_sp_lag_get(mlxsw_sp, lag_id); WARN_ON(lag->ref_count == 0); - mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, lag_id); mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id); /* Any VLANs configured on the port are no longer valid */ @@ -4852,21 +4846,56 @@ static int mlxsw_sp_lag_dist_port_remove(struct mlxsw_sp_port *mlxsw_sp_port, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sldr), sldr_pl); } -static int mlxsw_sp_port_lag_tx_en_set(struct mlxsw_sp_port *mlxsw_sp_port, - bool lag_tx_enabled) +static int +mlxsw_sp_port_lag_col_dist_enable(struct mlxsw_sp_port *mlxsw_sp_port) { - if (lag_tx_enabled) - return mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, - mlxsw_sp_port->lag_id); - else - return mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port, - mlxsw_sp_port->lag_id); + int err; + + err = mlxsw_sp_lag_col_port_enable(mlxsw_sp_port, + mlxsw_sp_port->lag_id); + if (err) + return err; + + err = mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id); + if (err) + goto err_dist_port_add; + + return 0; + +err_dist_port_add: + mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, mlxsw_sp_port->lag_id); + return err; +} + +static int +mlxsw_sp_port_lag_col_dist_disable(struct mlxsw_sp_port *mlxsw_sp_port) +{ + int err; + + err = mlxsw_sp_lag_dist_port_remove(mlxsw_sp_port, + mlxsw_sp_port->lag_id); + if (err) + return err; + + err = mlxsw_sp_lag_col_port_disable(mlxsw_sp_port, + mlxsw_sp_port->lag_id); + if (err) + goto err_col_port_disable; + + return 0; + +err_col_port_disable: + mlxsw_sp_lag_dist_port_add(mlxsw_sp_port, mlxsw_sp_port->lag_id); + return err; } static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port, struct netdev_lag_lower_state_info *info) { - return mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, info->tx_enabled); + if (info->tx_enabled) + return mlxsw_sp_port_lag_col_dist_enable(mlxsw_sp_port); + else + return mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port); } static int mlxsw_sp_port_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, @@ -5089,8 +5118,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, err = mlxsw_sp_port_lag_join(mlxsw_sp_port, upper_dev); } else { - mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, - false); + mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port); mlxsw_sp_port_lag_leave(mlxsw_sp_port, upper_dev); } -- cgit v1.2.3 From 24f91ce0d27c535b3f91fc4e6627a3761db094c4 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 12 Feb 2019 16:29:52 +0000 Subject: mlxsw: spectrum_router: Drop unnecessary WARN_ON_ONCE() In case the register access failed an error would be logged anyway, so we can drop the warning. Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 818040ce4d68..52fed8c7bf1e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -6142,7 +6142,7 @@ static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif) mlxsw_reg_ritr_rif_pack(ritr_pl, rif); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl); - if (WARN_ON_ONCE(err)) + if (err) return err; mlxsw_reg_ritr_enable_set(ritr_pl, false); -- cgit v1.2.3 From 384c2f7473bc4f6b25f62060ab4d5985726bb12d Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 12 Feb 2019 16:29:53 +0000 Subject: mlxsw: spectrum_flower: Fix VLAN modify action support The driver does not support VLAN push and pop, but only VLAN modify. Fixes: 738678817573 ("drivers: net: use flow action infrastructure") Signed-off-by: Ido Schimmel Acked-by: Jiri Pirko Cc: Pablo Neira Ayuso Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 9af9f5c1b25c..15f804453cd6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -102,8 +102,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, return err; } break; - case FLOW_ACTION_VLAN_PUSH: - case FLOW_ACTION_VLAN_POP: { + case FLOW_ACTION_VLAN_MANGLE: { u16 proto = be16_to_cpu(act->vlan.proto); u8 prio = act->vlan.prio; u16 vid = act->vlan.vid; -- cgit v1.2.3 From e222822f9be03c6d985ba1af1f22ec863368b8d0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Feb 2019 14:19:57 +0100 Subject: net: caif: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Also use the proper Kconfig symbol to check for DMA API availability. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/net/caif/caif_spi.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index d28a1398c091..7608bc3e00df 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -73,35 +73,37 @@ MODULE_PARM_DESC(spi_down_tail_align, "SPI downlink tail alignment."); #define LOW_WATER_MARK 100 #define HIGH_WATER_MARK (LOW_WATER_MARK*5) -#ifdef CONFIG_UML +#ifndef CONFIG_HAS_DMA /* * We sometimes use UML for debugging, but it cannot handle * dma_alloc_coherent so we have to wrap it. */ -static inline void *dma_alloc(dma_addr_t *daddr) +static inline void *dma_alloc(struct cfspi *cfspi, dma_addr_t *daddr) { return kmalloc(SPI_DMA_BUF_LEN, GFP_KERNEL); } -static inline void dma_free(void *cpu_addr, dma_addr_t handle) +static inline void dma_free(struct cfspi *cfspi, void *cpu_addr, + dma_addr_t handle) { kfree(cpu_addr); } #else -static inline void *dma_alloc(dma_addr_t *daddr) +static inline void *dma_alloc(struct cfspi *cfspi, dma_addr_t *daddr) { - return dma_alloc_coherent(NULL, SPI_DMA_BUF_LEN, daddr, + return dma_alloc_coherent(&cfspi->pdev->dev, SPI_DMA_BUF_LEN, daddr, GFP_KERNEL); } -static inline void dma_free(void *cpu_addr, dma_addr_t handle) +static inline void dma_free(struct cfspi *cfspi, void *cpu_addr, + dma_addr_t handle) { - dma_free_coherent(NULL, SPI_DMA_BUF_LEN, cpu_addr, handle); + dma_free_coherent(&cfspi->pdev->dev, SPI_DMA_BUF_LEN, cpu_addr, handle); } -#endif /* CONFIG_UML */ +#endif /* CONFIG_HAS_DMA */ #ifdef CONFIG_DEBUG_FS @@ -610,13 +612,13 @@ static int cfspi_init(struct net_device *dev) } /* Allocate DMA buffers. */ - cfspi->xfer.va_tx[0] = dma_alloc(&cfspi->xfer.pa_tx[0]); + cfspi->xfer.va_tx[0] = dma_alloc(cfspi, &cfspi->xfer.pa_tx[0]); if (!cfspi->xfer.va_tx[0]) { res = -ENODEV; goto err_dma_alloc_tx_0; } - cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx); + cfspi->xfer.va_rx = dma_alloc(cfspi, &cfspi->xfer.pa_rx); if (!cfspi->xfer.va_rx) { res = -ENODEV; @@ -665,9 +667,9 @@ static int cfspi_init(struct net_device *dev) return 0; err_create_wq: - dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx); + dma_free(cfspi, cfspi->xfer.va_rx, cfspi->xfer.pa_rx); err_dma_alloc_rx: - dma_free(cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]); + dma_free(cfspi, cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]); err_dma_alloc_tx_0: return res; } @@ -683,8 +685,8 @@ static void cfspi_uninit(struct net_device *dev) cfspi->ndev = NULL; /* Free DMA buffers. */ - dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx); - dma_free(cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]); + dma_free(cfspi, cfspi->xfer.va_rx, cfspi->xfer.pa_rx); + dma_free(cfspi, cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]); set_bit(SPI_TERMINATE, &cfspi->state); wake_up_interruptible(&cfspi->wait); destroy_workqueue(cfspi->wq); -- cgit v1.2.3 From 3c69aec48f3c89bf1b29f11ea949c4f595577ab4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Feb 2019 14:19:58 +0100 Subject: au1000_eth: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/au1000_eth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index e833d1b3fe18..e5073aeea06a 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -1167,7 +1167,7 @@ static int au1000_probe(struct platform_device *pdev) /* Allocate the data buffers * Snooping works fine with eth on all au1xxx */ - aup->vaddr = (u32)dma_alloc_attrs(NULL, MAX_BUF_SIZE * + aup->vaddr = (u32)dma_alloc_attrs(&pdev->dev, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), &aup->dma_addr, 0, DMA_ATTR_NON_CONSISTENT); @@ -1349,7 +1349,7 @@ err_remap3: err_remap2: iounmap(aup->mac); err_remap1: - dma_free_attrs(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), + dma_free_attrs(&pdev->dev, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), (void *)aup->vaddr, aup->dma_addr, DMA_ATTR_NON_CONSISTENT); err_vaddr: @@ -1383,7 +1383,7 @@ static int au1000_remove(struct platform_device *pdev) if (aup->tx_db_inuse[i]) au1000_ReleaseDB(aup, aup->tx_db_inuse[i]); - dma_free_attrs(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), + dma_free_attrs(&pdev->dev, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS), (void *)aup->vaddr, aup->dma_addr, DMA_ATTR_NON_CONSISTENT); -- cgit v1.2.3 From 564923e4c0b6505436d756dcaf8d84ca33307ee3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Feb 2019 14:19:59 +0100 Subject: macb_main: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Signed-off-by: Christoph Hellwig Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index eaabe8c278ec..4d1509f431d7 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3673,9 +3673,9 @@ static netdev_tx_t at91ether_start_xmit(struct sk_buff *skb, /* Store packet information (to free when Tx completed) */ lp->skb = skb; lp->skb_length = skb->len; - lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(NULL, lp->skb_physaddr)) { + lp->skb_physaddr = dma_map_single(&lp->pdev->dev, skb->data, + skb->len, DMA_TO_DEVICE); + if (dma_mapping_error(&lp->pdev->dev, lp->skb_physaddr)) { dev_kfree_skb_any(skb); dev->stats.tx_dropped++; netdev_err(dev, "%s: DMA mapping error\n", __func__); @@ -3765,7 +3765,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id) if (lp->skb) { dev_kfree_skb_irq(lp->skb); lp->skb = NULL; - dma_unmap_single(NULL, lp->skb_physaddr, + dma_unmap_single(&lp->pdev->dev, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE); dev->stats.tx_packets++; dev->stats.tx_bytes += lp->skb_length; -- cgit v1.2.3 From 74e0deb89a8ba27c132b1f0e08643e215b5c1f92 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Feb 2019 14:20:00 +0100 Subject: lantiq_etop: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Note this driver seems to lack dma_unmap_* calls entirely, but fixing that is left for another time. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/net/ethernet/lantiq_etop.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 32ac9045cdae..f9bb890733b5 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -112,10 +112,12 @@ struct ltq_etop_priv { static int ltq_etop_alloc_skb(struct ltq_etop_chan *ch) { + struct ltq_etop_priv *priv = netdev_priv(ch->netdev); + ch->skb[ch->dma.desc] = netdev_alloc_skb(ch->netdev, MAX_DMA_DATA_LEN); if (!ch->skb[ch->dma.desc]) return -ENOMEM; - ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL, + ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(&priv->pdev->dev, ch->skb[ch->dma.desc]->data, MAX_DMA_DATA_LEN, DMA_FROM_DEVICE); ch->dma.desc_base[ch->dma.desc].addr = @@ -487,7 +489,7 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev) netif_trans_update(dev); spin_lock_irqsave(&priv->lock, flags); - desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len, + desc->addr = ((unsigned int) dma_map_single(&priv->pdev->dev, skb->data, len, DMA_TO_DEVICE)) - byte_offset; wmb(); desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP | -- cgit v1.2.3 From e86b76f63351e8393c6a7d15bd46366da16ffd3f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Feb 2019 14:20:01 +0100 Subject: pxa168_eth: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Note that this driver seems to entirely lack dma_map_single error handling, but that is left for another time. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/pxa168_eth.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index f8a6d6e3cb7a..35f2142aac5e 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -201,6 +201,7 @@ struct tx_desc { }; struct pxa168_eth_private { + struct platform_device *pdev; int port_num; /* User Ethernet port number */ int phy_addr; int phy_speed; @@ -331,7 +332,7 @@ static void rxq_refill(struct net_device *dev) used_rx_desc = pep->rx_used_desc_q; p_used_rx_desc = &pep->p_rx_desc_area[used_rx_desc]; size = skb_end_pointer(skb) - skb->data; - p_used_rx_desc->buf_ptr = dma_map_single(NULL, + p_used_rx_desc->buf_ptr = dma_map_single(&pep->pdev->dev, skb->data, size, DMA_FROM_DEVICE); @@ -743,7 +744,7 @@ static int txq_reclaim(struct net_device *dev, int force) netdev_err(dev, "Error in TX\n"); dev->stats.tx_errors++; } - dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); + dma_unmap_single(&pep->pdev->dev, addr, count, DMA_TO_DEVICE); if (skb) dev_kfree_skb_irq(skb); released++; @@ -805,7 +806,7 @@ static int rxq_process(struct net_device *dev, int budget) if (rx_next_curr_desc == rx_used_desc) pep->rx_resource_err = 1; pep->rx_desc_count--; - dma_unmap_single(NULL, rx_desc->buf_ptr, + dma_unmap_single(&pep->pdev->dev, rx_desc->buf_ptr, rx_desc->buf_size, DMA_FROM_DEVICE); received_packets++; @@ -1274,7 +1275,8 @@ pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) length = skb->len; pep->tx_skb[tx_index] = skb; desc->byte_cnt = length; - desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + desc->buf_ptr = dma_map_single(&pep->pdev->dev, skb->data, length, + DMA_TO_DEVICE); skb_tx_timestamp(skb); @@ -1528,6 +1530,7 @@ static int pxa168_eth_probe(struct platform_device *pdev) if (err) goto err_free_mdio; + pep->pdev = pdev; SET_NETDEV_DEV(dev, &pdev->dev); pxa168_init_hw(pep); err = register_netdev(dev); -- cgit v1.2.3 From 5dac33ad6f0d1dbc20736fa13d833250e7f12a26 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Feb 2019 14:20:02 +0100 Subject: moxart_ether: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/net/ethernet/moxa/moxart_ether.c | 11 +++++++---- drivers/net/ethernet/moxa/moxart_ether.h | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index b34055ac476f..00dec0ffb11b 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -81,11 +81,13 @@ static void moxart_mac_free_memory(struct net_device *ndev) priv->rx_buf_size, DMA_FROM_DEVICE); if (priv->tx_desc_base) - dma_free_coherent(NULL, TX_REG_DESC_SIZE * TX_DESC_NUM, + dma_free_coherent(&priv->pdev->dev, + TX_REG_DESC_SIZE * TX_DESC_NUM, priv->tx_desc_base, priv->tx_base); if (priv->rx_desc_base) - dma_free_coherent(NULL, RX_REG_DESC_SIZE * RX_DESC_NUM, + dma_free_coherent(&priv->pdev->dev, + RX_REG_DESC_SIZE * RX_DESC_NUM, priv->rx_desc_base, priv->rx_base); kfree(priv->tx_buf_base); @@ -476,6 +478,7 @@ static int moxart_mac_probe(struct platform_device *pdev) priv = netdev_priv(ndev); priv->ndev = ndev; + priv->pdev = pdev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ndev->base_addr = res->start; @@ -491,7 +494,7 @@ static int moxart_mac_probe(struct platform_device *pdev) priv->tx_buf_size = TX_BUF_SIZE; priv->rx_buf_size = RX_BUF_SIZE; - priv->tx_desc_base = dma_alloc_coherent(NULL, TX_REG_DESC_SIZE * + priv->tx_desc_base = dma_alloc_coherent(&pdev->dev, TX_REG_DESC_SIZE * TX_DESC_NUM, &priv->tx_base, GFP_DMA | GFP_KERNEL); if (!priv->tx_desc_base) { @@ -499,7 +502,7 @@ static int moxart_mac_probe(struct platform_device *pdev) goto init_fail; } - priv->rx_desc_base = dma_alloc_coherent(NULL, RX_REG_DESC_SIZE * + priv->rx_desc_base = dma_alloc_coherent(&pdev->dev, RX_REG_DESC_SIZE * RX_DESC_NUM, &priv->rx_base, GFP_DMA | GFP_KERNEL); if (!priv->rx_desc_base) { diff --git a/drivers/net/ethernet/moxa/moxart_ether.h b/drivers/net/ethernet/moxa/moxart_ether.h index bee608b547d1..bf4c3029cd0c 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.h +++ b/drivers/net/ethernet/moxa/moxart_ether.h @@ -292,6 +292,7 @@ #define LINK_STATUS 0x4 struct moxart_mac_priv_t { + struct platform_device *pdev; void __iomem *base; unsigned int reg_maccr; unsigned int reg_imr; -- cgit v1.2.3 From 8d4c28fbc284bf2dee08afff146def47cafbc227 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Feb 2019 14:20:03 +0100 Subject: meth: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Also use GFP_KERNEL instead of GFP_ATOMIC as the gfp_t for the memory allocation, as we aren't in interrupt context or under a lock. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/net/ethernet/sgi/meth.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c index 0e1b7e960b98..67954a9e3675 100644 --- a/drivers/net/ethernet/sgi/meth.c +++ b/drivers/net/ethernet/sgi/meth.c @@ -68,6 +68,8 @@ module_param(timeout, int, 0); * packets in and out, so there is place for a packet */ struct meth_private { + struct platform_device *pdev; + /* in-memory copy of MAC Control register */ u64 mac_ctrl; @@ -211,8 +213,8 @@ static void meth_check_link(struct net_device *dev) static int meth_init_tx_ring(struct meth_private *priv) { /* Init TX ring */ - priv->tx_ring = dma_alloc_coherent(NULL, TX_RING_BUFFER_SIZE, - &priv->tx_ring_dma, GFP_ATOMIC); + priv->tx_ring = dma_alloc_coherent(&priv->pdev->dev, + TX_RING_BUFFER_SIZE, &priv->tx_ring_dma, GFP_KERNEL); if (!priv->tx_ring) return -ENOMEM; @@ -236,7 +238,7 @@ static int meth_init_rx_ring(struct meth_private *priv) priv->rx_ring[i]=(rx_packet*)(priv->rx_skbs[i]->head); /* I'll need to re-sync it after each RX */ priv->rx_ring_dmas[i] = - dma_map_single(NULL, priv->rx_ring[i], + dma_map_single(&priv->pdev->dev, priv->rx_ring[i], METH_RX_BUFF_SIZE, DMA_FROM_DEVICE); mace->eth.rx_fifo = priv->rx_ring_dmas[i]; } @@ -253,7 +255,7 @@ static void meth_free_tx_ring(struct meth_private *priv) dev_kfree_skb(priv->tx_skbs[i]); priv->tx_skbs[i] = NULL; } - dma_free_coherent(NULL, TX_RING_BUFFER_SIZE, priv->tx_ring, + dma_free_coherent(&priv->pdev->dev, TX_RING_BUFFER_SIZE, priv->tx_ring, priv->tx_ring_dma); } @@ -263,7 +265,7 @@ static void meth_free_rx_ring(struct meth_private *priv) int i; for (i = 0; i < RX_RING_ENTRIES; i++) { - dma_unmap_single(NULL, priv->rx_ring_dmas[i], + dma_unmap_single(&priv->pdev->dev, priv->rx_ring_dmas[i], METH_RX_BUFF_SIZE, DMA_FROM_DEVICE); priv->rx_ring[i] = 0; priv->rx_ring_dmas[i] = 0; @@ -393,7 +395,8 @@ static void meth_rx(struct net_device* dev, unsigned long int_status) fifo_rptr = (fifo_rptr - 1) & 0x0f; } while (priv->rx_write != fifo_rptr) { - dma_unmap_single(NULL, priv->rx_ring_dmas[priv->rx_write], + dma_unmap_single(&priv->pdev->dev, + priv->rx_ring_dmas[priv->rx_write], METH_RX_BUFF_SIZE, DMA_FROM_DEVICE); status = priv->rx_ring[priv->rx_write]->status.raw; #if MFE_DEBUG @@ -454,7 +457,8 @@ static void meth_rx(struct net_device* dev, unsigned long int_status) priv->rx_ring[priv->rx_write] = (rx_packet*)skb->head; priv->rx_ring[priv->rx_write]->status.raw = 0; priv->rx_ring_dmas[priv->rx_write] = - dma_map_single(NULL, priv->rx_ring[priv->rx_write], + dma_map_single(&priv->pdev->dev, + priv->rx_ring[priv->rx_write], METH_RX_BUFF_SIZE, DMA_FROM_DEVICE); mace->eth.rx_fifo = priv->rx_ring_dmas[priv->rx_write]; ADVANCE_RX_PTR(priv->rx_write); @@ -637,7 +641,7 @@ static void meth_tx_1page_prepare(struct meth_private *priv, } /* first page */ - catbuf = dma_map_single(NULL, buffer_data, buffer_len, + catbuf = dma_map_single(&priv->pdev->dev, buffer_data, buffer_len, DMA_TO_DEVICE); desc->data.cat_buf[0].form.start_addr = catbuf >> 3; desc->data.cat_buf[0].form.len = buffer_len - 1; @@ -663,12 +667,12 @@ static void meth_tx_2page_prepare(struct meth_private *priv, } /* first page */ - catbuf1 = dma_map_single(NULL, buffer1_data, buffer1_len, + catbuf1 = dma_map_single(&priv->pdev->dev, buffer1_data, buffer1_len, DMA_TO_DEVICE); desc->data.cat_buf[0].form.start_addr = catbuf1 >> 3; desc->data.cat_buf[0].form.len = buffer1_len - 1; /* second page */ - catbuf2 = dma_map_single(NULL, buffer2_data, buffer2_len, + catbuf2 = dma_map_single(&priv->pdev->dev, buffer2_data, buffer2_len, DMA_TO_DEVICE); desc->data.cat_buf[1].form.start_addr = catbuf2 >> 3; desc->data.cat_buf[1].form.len = buffer2_len - 1; @@ -840,6 +844,7 @@ static int meth_probe(struct platform_device *pdev) memcpy(dev->dev_addr, o2meth_eaddr, ETH_ALEN); priv = netdev_priv(dev); + priv->pdev = pdev; spin_lock_init(&priv->meth_lock); SET_NETDEV_DEV(dev, &pdev->dev); -- cgit v1.2.3 From 0eb1645a8daaabab8583333046afac90b5b77fe0 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 11 Feb 2019 14:20:04 +0100 Subject: smc911x: pass struct device to DMA API functions The DMA API generally relies on a struct device to work properly, and only barely works without one for legacy reasons. Pass the easily available struct device from the platform_device to remedy this. Note that smc911x apparently is a PIO chip with an external DMA handshake, and we probably use the wrong device here. But at least it matches the mapping side, which apparently works or at least worked in the not too distant past. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smc911x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index 8355dfbb8ec3..b550e624500d 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -1188,7 +1188,7 @@ smc911x_tx_dma_irq(void *data) DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, dev, "TX DMA irq handler\n"); BUG_ON(skb == NULL); - dma_unmap_single(NULL, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE); + dma_unmap_single(lp->dev, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE); netif_trans_update(dev); dev_kfree_skb_irq(skb); lp->current_tx_skb = NULL; @@ -1219,7 +1219,7 @@ smc911x_rx_dma_irq(void *data) DBG(SMC_DEBUG_FUNC, dev, "--> %s\n", __func__); DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, dev, "RX DMA irq handler\n"); - dma_unmap_single(NULL, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE); + dma_unmap_single(lp->dev, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE); BUG_ON(skb == NULL); lp->current_rx_skb = NULL; PRINT_PKT(skb->data, skb->len); -- cgit v1.2.3 From da203dfa89ce83c55b6623f73560ef7ec742aca4 Mon Sep 17 00:00:00 2001 From: Vasundhara Volam Date: Mon, 11 Feb 2019 14:46:17 +0530 Subject: Revert "devlink: Add a generic wake_on_lan port parameter" This reverts commit b639583f9e36d044ac1b13090ae812266992cbac. As per discussion with Jakub Kicinski and Michal Kubecek, this will be better addressed by soon-too-come ethtool netlink API with additional indication that given configuration request is supposed to be persisted. Also, remove the parameter support from bnxt_en driver. Cc: Jiri Pirko Cc: Michael Chan Cc: Michal Kubecek Suggested-by: Jakub Kicinski Signed-off-by: Vasundhara Volam Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c | 19 +------------------ drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h | 1 - include/net/devlink.h | 8 -------- net/core/devlink.c | 5 ----- 4 files changed, 1 insertion(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c index 2955e404fd18..e1feb97bcd81 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c @@ -37,8 +37,6 @@ static const struct bnxt_dl_nvm_param nvm_params[] = { NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7}, {BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK, BNXT_NVM_SHARED_CFG, 1}, - - {DEVLINK_PARAM_GENERIC_ID_WOL, NVM_OFF_WOL, BNXT_NVM_PORT_CFG, 1}, }; static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, @@ -72,8 +70,7 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, bytesize = roundup(nvm_param.num_bits, BITS_PER_BYTE) / BITS_PER_BYTE; switch (bytesize) { case 1: - if (nvm_param.num_bits == 1 && - nvm_param.id != DEVLINK_PARAM_GENERIC_ID_WOL) + if (nvm_param.num_bits == 1) buf = &val->vbool; else buf = &val->vu8; @@ -167,17 +164,6 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 id, return 0; } -static int bnxt_dl_wol_validate(struct devlink *dl, u32 id, - union devlink_param_value val, - struct netlink_ext_ack *extack) -{ - if (val.vu8 && val.vu8 != DEVLINK_PARAM_WAKE_MAGIC) { - NL_SET_ERR_MSG_MOD(extack, "WOL type is not supported"); - return -EINVAL; - } - return 0; -} - static const struct devlink_param bnxt_dl_params[] = { DEVLINK_PARAM_GENERIC(ENABLE_SRIOV, BIT(DEVLINK_PARAM_CMODE_PERMANENT), @@ -203,9 +189,6 @@ static const struct devlink_param bnxt_dl_params[] = { }; static const struct devlink_param bnxt_dl_port_params[] = { - DEVLINK_PARAM_GENERIC(WOL, BIT(DEVLINK_PARAM_CMODE_PERMANENT), - bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, - bnxt_dl_wol_validate), }; int bnxt_dl_register(struct bnxt *bp) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h index da065ca84cc7..5b6b2c7d97cf 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h @@ -35,7 +35,6 @@ static inline void bnxt_link_bp_to_dl(struct bnxt *bp, struct devlink *dl) #define NVM_OFF_MSIX_VEC_PER_PF_MAX 108 #define NVM_OFF_MSIX_VEC_PER_PF_MIN 114 -#define NVM_OFF_WOL 152 #define NVM_OFF_IGNORE_ARI 164 #define NVM_OFF_DIS_GRE_VER_CHECK 171 #define NVM_OFF_ENABLE_SRIOV 401 diff --git a/include/net/devlink.h b/include/net/devlink.h index 07660fe4c0e3..c6d88759b7d5 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -370,17 +370,12 @@ enum devlink_param_generic_id { DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, - DEVLINK_PARAM_GENERIC_ID_WOL, /* add new param generic ids above here*/ __DEVLINK_PARAM_GENERIC_ID_MAX, DEVLINK_PARAM_GENERIC_ID_MAX = __DEVLINK_PARAM_GENERIC_ID_MAX - 1, }; -enum devlink_param_wol_types { - DEVLINK_PARAM_WAKE_MAGIC = (1 << 0), -}; - #define DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME "internal_error_reset" #define DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE DEVLINK_PARAM_TYPE_BOOL @@ -405,9 +400,6 @@ enum devlink_param_wol_types { #define DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME "fw_load_policy" #define DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE DEVLINK_PARAM_TYPE_U8 -#define DEVLINK_PARAM_GENERIC_WOL_NAME "wake_on_lan" -#define DEVLINK_PARAM_GENERIC_WOL_TYPE DEVLINK_PARAM_TYPE_U8 - #define DEVLINK_PARAM_GENERIC(_id, _cmodes, _get, _set, _validate) \ { \ .id = DEVLINK_PARAM_GENERIC_ID_##_id, \ diff --git a/net/core/devlink.c b/net/core/devlink.c index ec02459eea94..d3dfdcacf7eb 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -2701,11 +2701,6 @@ static const struct devlink_param devlink_param_generic[] = { .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME, .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE, }, - { - .id = DEVLINK_PARAM_GENERIC_ID_WOL, - .name = DEVLINK_PARAM_GENERIC_WOL_NAME, - .type = DEVLINK_PARAM_GENERIC_WOL_TYPE, - }, }; static int devlink_param_generic_verify(const struct devlink_param *param) -- cgit v1.2.3 From 0946cf1dc7b6da951b4eb3fbcfd8e926dd0e787b Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 11 Feb 2019 11:46:01 +0000 Subject: net: phylink: only call mac_config() during resolve when link is up There's little point calling mac_config() when the link is down. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/phy/phylink.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 2e21ce42e388..a148866cbb14 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -302,6 +302,13 @@ static void phylink_mac_config(struct phylink *pl, pl->ops->mac_config(pl->netdev, pl->link_an_mode, state); } +static void phylink_mac_config_up(struct phylink *pl, + const struct phylink_link_state *state) +{ + if (state->link) + phylink_mac_config(pl, state); +} + static void phylink_mac_an_restart(struct phylink *pl) { if (pl->link_config.an_enabled && @@ -401,12 +408,12 @@ static void phylink_resolve(struct work_struct *w) case MLO_AN_PHY: link_state = pl->phy_state; phylink_resolve_flow(pl, &link_state); - phylink_mac_config(pl, &link_state); + phylink_mac_config_up(pl, &link_state); break; case MLO_AN_FIXED: phylink_get_fixed_state(pl, &link_state); - phylink_mac_config(pl, &link_state); + phylink_mac_config_up(pl, &link_state); break; case MLO_AN_INBAND: -- cgit v1.2.3 From 86e58135bc4ac68b41be11d82f1b1f87cb6119ba Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 11 Feb 2019 11:46:06 +0000 Subject: net: phylink: add phylink_init_eee() helper Provide phylink_init_eee() to allow MAC drivers to initialise PHY EEE from within the ethtool set_eee() method. Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/phy/phylink.c | 18 ++++++++++++++++++ include/linux/phylink.h | 1 + 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index a148866cbb14..33f66dcd369a 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1271,6 +1271,24 @@ int phylink_get_eee_err(struct phylink *pl) } EXPORT_SYMBOL_GPL(phylink_get_eee_err); +/** + * phylink_init_eee() - init and check the EEE features + * @pl: a pointer to a &struct phylink returned from phylink_create() + * @clk_stop_enable: allow PHY to stop receive clock + * + * Must be called either with RTNL held or within mac_link_up() + */ +int phylink_init_eee(struct phylink *pl, bool clk_stop_enable) +{ + int ret = -EOPNOTSUPP; + + if (pl->phydev) + ret = phy_init_eee(pl->phydev, clk_stop_enable); + + return ret; +} +EXPORT_SYMBOL_GPL(phylink_init_eee); + /** * phylink_ethtool_get_eee() - read the energy efficient ethernet parameters * @pl: a pointer to a &struct phylink returned from phylink_create() diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 021fc6595856..f57059e4353f 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -220,6 +220,7 @@ void phylink_ethtool_get_pauseparam(struct phylink *, int phylink_ethtool_set_pauseparam(struct phylink *, struct ethtool_pauseparam *); int phylink_get_eee_err(struct phylink *); +int phylink_init_eee(struct phylink *, bool); int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *); int phylink_ethtool_set_eee(struct phylink *, struct ethtool_eee *); int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); -- cgit v1.2.3 From b7d286f01b9d9021695188092e36f405f2ecd276 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 11 Feb 2019 10:23:10 +0000 Subject: net: marvell: mvpp2: add mvpp2_is_xlg() helper Add a mvpp2_is_xlg() helper to identify whether the interface mode should be using the XLGMAC rather than the GMAC. Signed-off-by: Russell King Reviewed-by: Maxime Chevallier Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index eef8833e5aae..8b42b0367c35 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -965,6 +965,11 @@ mvpp2_shared_interrupt_mask_unmask(struct mvpp2_port *port, bool mask) } /* Port configuration routines */ +static bool mvpp2_is_xlg(phy_interface_t interface) +{ + return interface == PHY_INTERFACE_MODE_10GKR || + interface == PHY_INTERFACE_MODE_XAUI; +} static void mvpp22_gop_init_rgmii(struct mvpp2_port *port) { @@ -1181,9 +1186,7 @@ static void mvpp2_port_enable(struct mvpp2_port *port) u32 val; /* Only GOP port 0 has an XLG MAC */ - if (port->gop_id == 0 && - (port->phy_interface == PHY_INTERFACE_MODE_XAUI || - port->phy_interface == PHY_INTERFACE_MODE_10GKR)) { + if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) { val = readl(port->base + MVPP22_XLG_CTRL0_REG); val |= MVPP22_XLG_CTRL0_PORT_EN | MVPP22_XLG_CTRL0_MAC_RESET_DIS; @@ -1202,9 +1205,7 @@ static void mvpp2_port_disable(struct mvpp2_port *port) u32 val; /* Only GOP port 0 has an XLG MAC */ - if (port->gop_id == 0 && - (port->phy_interface == PHY_INTERFACE_MODE_XAUI || - port->phy_interface == PHY_INTERFACE_MODE_10GKR)) { + if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) { val = readl(port->base + MVPP22_XLG_CTRL0_REG); val &= ~MVPP22_XLG_CTRL0_PORT_EN; writel(val, port->base + MVPP22_XLG_CTRL0_REG); @@ -3146,8 +3147,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG); ctrl3 &= ~MVPP22_XLG_CTRL3_MACMODESELECT_MASK; - if (port->phy_interface == PHY_INTERFACE_MODE_XAUI || - port->phy_interface == PHY_INTERFACE_MODE_10GKR) + if (mvpp2_is_xlg(port->phy_interface)) ctrl3 |= MVPP22_XLG_CTRL3_MACMODESELECT_10G; else ctrl3 |= MVPP22_XLG_CTRL3_MACMODESELECT_GMAC; @@ -3155,9 +3155,7 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) writel(ctrl3, port->base + MVPP22_XLG_CTRL3_REG); } - if (port->gop_id == 0 && - (port->phy_interface == PHY_INTERFACE_MODE_XAUI || - port->phy_interface == PHY_INTERFACE_MODE_10GKR)) + if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) mvpp2_xlg_max_rx_size_set(port); else mvpp2_gmac_max_rx_size_set(port); -- cgit v1.2.3 From 1d9b041e9c5cb6a06e0943f14daf9806e6fe55f1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 11 Feb 2019 10:23:15 +0000 Subject: net: marvell: mvpp2: use mvpp2_is_xlg() helper elsewhere There are several places which make the decision whether to access the XLGMAC vs GMAC that only check for PHY_INTERFACE_MODE_10GKR and not its XAUI variant. Switch these to use the new helper so that we have consistency through the driver. Signed-off-by: Russell King Reviewed-by: Maxime Chevallier Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 8b42b0367c35..191d9ce85b7e 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1106,7 +1106,7 @@ static void mvpp22_gop_unmask_irq(struct mvpp2_port *port) if (port->gop_id == 0) { /* Enable the XLG/GIG irqs for this port */ val = readl(port->base + MVPP22_XLG_EXT_INT_MASK); - if (port->phy_interface == PHY_INTERFACE_MODE_10GKR) + if (mvpp2_is_xlg(port->phy_interface)) val |= MVPP22_XLG_EXT_INT_MASK_XLG; else val |= MVPP22_XLG_EXT_INT_MASK_GIG; @@ -2456,8 +2456,7 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id) mvpp22_gop_mask_irq(port); - if (port->gop_id == 0 && - port->phy_interface == PHY_INTERFACE_MODE_10GKR) { + if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) { val = readl(port->base + MVPP22_XLG_INT_STAT); if (val & MVPP22_XLG_INT_STAT_LINK) { event = true; @@ -4665,7 +4664,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, bool change_interface = port->phy_interface != state->interface; /* Check for invalid configuration */ - if (state->interface == PHY_INTERFACE_MODE_10GKR && port->gop_id != 0) { + if (mvpp2_is_xlg(state->interface) && port->gop_id != 0) { netdev_err(dev, "Invalid mode on %s\n", dev->name); return; } @@ -4685,7 +4684,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, } /* mac (re)configuration */ - if (state->interface == PHY_INTERFACE_MODE_10GKR) + if (mvpp2_is_xlg(state->interface)) mvpp2_xlg_config(port, mode, state); else if (phy_interface_mode_is_rgmii(state->interface) || phy_interface_mode_is_8023z(state->interface) || @@ -4707,8 +4706,7 @@ static void mvpp2_mac_link_up(struct net_device *dev, unsigned int mode, struct mvpp2_port *port = netdev_priv(dev); u32 val; - if (!phylink_autoneg_inband(mode) && - interface != PHY_INTERFACE_MODE_10GKR) { + if (!phylink_autoneg_inband(mode) && !mvpp2_is_xlg(interface)) { val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); val &= ~MVPP2_GMAC_FORCE_LINK_DOWN; val |= MVPP2_GMAC_FORCE_LINK_PASS; @@ -4728,8 +4726,7 @@ static void mvpp2_mac_link_down(struct net_device *dev, unsigned int mode, struct mvpp2_port *port = netdev_priv(dev); u32 val; - if (!phylink_autoneg_inband(mode) && - interface != PHY_INTERFACE_MODE_10GKR) { + if (!phylink_autoneg_inband(mode) && !mvpp2_is_xlg(interface)) { val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); val &= ~MVPP2_GMAC_FORCE_LINK_PASS; val |= MVPP2_GMAC_FORCE_LINK_DOWN; -- cgit v1.2.3 From 9f771f1f52f26acd61479eb1919801cbbfab3a57 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 11 Feb 2019 22:16:13 +0100 Subject: net: phy: simplify genphy_config_eee_advert Use new function phy_modify_mmd_changed(), the result speaks for itself. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 3d14e48aebc5..2c61282a2726 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1578,31 +1578,16 @@ static int genphy_config_advert(struct phy_device *phydev) */ static int genphy_config_eee_advert(struct phy_device *phydev) { - int broken = phydev->eee_broken_modes; - int old_adv, adv; + int err; /* Nothing to disable */ - if (!broken) + if (!phydev->eee_broken_modes) return 0; - /* If the following call fails, we assume that EEE is not - * supported by the phy. If we read 0, EEE is not advertised - * In both case, we don't need to continue - */ - adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV); - if (adv <= 0) - return 0; - - old_adv = adv; - adv &= ~broken; - - /* Advertising remains unchanged with the broken mask */ - if (old_adv == adv) - return 0; - - phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv); - - return 1; + err = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, + phydev->eee_broken_modes, 0); + /* If the call failed, we assume that EEE is not supported */ + return err < 0 ? 0 : err; } /** -- cgit v1.2.3 From 1ecb195753a18b44df29238994026d5e4cb64db3 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 11 Feb 2019 13:17:47 -0800 Subject: mlxsw: spectrum_switchdev: Remove getting PORT_BRIDGE_FLAGS There is no code that will query the SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS attribute remove support for that. Signed-off-by: Florian Fainelli Acked-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 95e37de3e48f..4c5780f8f4b2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -431,19 +431,6 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan) mlxsw_sp_bridge_vlan_destroy(bridge_vlan); } -static void mlxsw_sp_port_bridge_flags_get(struct mlxsw_sp_bridge *bridge, - struct net_device *dev, - unsigned long *brport_flags) -{ - struct mlxsw_sp_bridge_port *bridge_port; - - bridge_port = mlxsw_sp_bridge_port_find(bridge, dev); - if (WARN_ON(!bridge_port)) - return; - - memcpy(brport_flags, &bridge_port->flags, sizeof(*brport_flags)); -} - static int mlxsw_sp_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { @@ -451,10 +438,6 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev, struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: - mlxsw_sp_port_bridge_flags_get(mlxsw_sp->bridge, attr->orig_dev, - &attr->u.brport_flags); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD; -- cgit v1.2.3 From 610d2b601bbab632e91c6edfb15c44790ad85d32 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 11 Feb 2019 13:17:48 -0800 Subject: rocker: Remove getting PORT_BRIDGE_FLAGS There is no code that attempts to get the SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS attribute, remove support for that. Signed-off-by: Florian Fainelli Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.h | 2 -- drivers/net/ethernet/rocker/rocker_main.c | 15 --------------- drivers/net/ethernet/rocker/rocker_ofdpa.c | 10 ---------- 3 files changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/rocker/rocker.h b/drivers/net/ethernet/rocker/rocker.h index 748fb12260a6..2b2e1c4f0dc3 100644 --- a/drivers/net/ethernet/rocker/rocker.h +++ b/drivers/net/ethernet/rocker/rocker.h @@ -109,8 +109,6 @@ struct rocker_world_ops { int (*port_attr_bridge_flags_set)(struct rocker_port *rocker_port, unsigned long brport_flags, struct switchdev_trans *trans); - int (*port_attr_bridge_flags_get)(const struct rocker_port *rocker_port, - unsigned long *p_brport_flags); int (*port_attr_bridge_flags_support_get)(const struct rocker_port * rocker_port, unsigned long * diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 66f72f8c46e5..5ce8d5aba603 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -1582,17 +1582,6 @@ rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port, trans); } -static int -rocker_world_port_attr_bridge_flags_get(const struct rocker_port *rocker_port, - unsigned long *p_brport_flags) -{ - struct rocker_world_ops *wops = rocker_port->rocker->wops; - - if (!wops->port_attr_bridge_flags_get) - return -EOPNOTSUPP; - return wops->port_attr_bridge_flags_get(rocker_port, p_brport_flags); -} - static int rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port * rocker_port, @@ -2061,10 +2050,6 @@ static int rocker_port_attr_get(struct net_device *dev, int err = 0; switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: - err = rocker_world_port_attr_bridge_flags_get(rocker_port, - &attr->u.brport_flags); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: err = rocker_world_port_attr_bridge_flags_support_get(rocker_port, &attr->u.brport_flags_support); diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c index bea7895930f6..9c07f6040720 100644 --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c @@ -2511,16 +2511,6 @@ static int ofdpa_port_attr_bridge_flags_set(struct rocker_port *rocker_port, return err; } -static int -ofdpa_port_attr_bridge_flags_get(const struct rocker_port *rocker_port, - unsigned long *p_brport_flags) -{ - const struct ofdpa_port *ofdpa_port = rocker_port->wpriv; - - *p_brport_flags = ofdpa_port->brport_flags; - return 0; -} - static int ofdpa_port_attr_bridge_flags_support_get(const struct rocker_port * rocker_port, -- cgit v1.2.3 From 1b8b589d91038e9641f1a3b80bbe145bf7d0706b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 11 Feb 2019 13:17:49 -0800 Subject: staging: fsl-dpaa2: ethsw: Remove getting PORT_BRIDGE_FLAGS There is no code that tries to get the attribute SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, remove support for doing that. Signed-off-by: Florian Fainelli Acked-by: Greg Kroah-Hartman Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index e559f4c25cf7..e5a14c7c777f 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -646,11 +646,6 @@ static int swdev_port_attr_get(struct net_device *netdev, struct ethsw_port_priv *port_priv = netdev_priv(netdev); switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: - attr->u.brport_flags = - (port_priv->ethsw_data->learning ? BR_LEARNING : 0) | - (port_priv->flood ? BR_FLOOD : 0); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD; break; -- cgit v1.2.3 From 1e562c815e67185e030bcaa06323e95d85d80987 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 12 Feb 2019 12:23:56 +0800 Subject: ptp_qoriq: make structure/function names more consistent Strings containing "ptp_qoriq" or "qoriq_ptp" which were used for structure/function names were complained by users. Let's just use the unique "ptp_qoriq" to make these names more consistent. This patch is just to unify the names using "ptp_qoriq". It hasn't changed any functions. Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 2 +- drivers/net/ethernet/freescale/gianfar_ethtool.c | 2 +- drivers/ptp/ptp_qoriq.c | 288 ++++++++++----------- drivers/ptp/ptp_qoriq_debugfs.c | 36 +-- include/linux/fsl/ptp_qoriq.h | 14 +- 5 files changed, 171 insertions(+), 171 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c index 62497119c85f..bdee441bc3b7 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c @@ -501,7 +501,7 @@ static int dpaa_get_ts_info(struct net_device *net_dev, struct device_node *mac_node = dev->of_node; struct device_node *fman_node = NULL, *ptp_node = NULL; struct platform_device *ptp_dev = NULL; - struct qoriq_ptp *ptp = NULL; + struct ptp_qoriq *ptp = NULL; info->phc_index = -1; diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 241325c35cb4..27ed995f439a 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -1492,7 +1492,7 @@ static int gfar_get_ts_info(struct net_device *dev, struct gfar_private *priv = netdev_priv(dev); struct platform_device *ptp_dev; struct device_node *ptp_node; - struct qoriq_ptp *ptp = NULL; + struct ptp_qoriq *ptp = NULL; info->phc_index = -1; diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index 43416b2e8a13..8c10d0f8864f 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -37,10 +37,10 @@ * Register access functions */ -/* Caller must hold qoriq_ptp->lock. */ -static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp) +/* Caller must hold ptp_qoriq->lock. */ +static u64 tmr_cnt_read(struct ptp_qoriq *ptp_qoriq) { - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u64 ns; u32 lo, hi; @@ -51,10 +51,10 @@ static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp) return ns; } -/* Caller must hold qoriq_ptp->lock. */ -static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns) +/* Caller must hold ptp_qoriq->lock. */ +static void tmr_cnt_write(struct ptp_qoriq *ptp_qoriq, u64 ns) { - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 hi = ns >> 32; u32 lo = ns & 0xffffffff; @@ -62,36 +62,36 @@ static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns) qoriq_write(®s->ctrl_regs->tmr_cnt_h, hi); } -/* Caller must hold qoriq_ptp->lock. */ -static void set_alarm(struct qoriq_ptp *qoriq_ptp) +/* Caller must hold ptp_qoriq->lock. */ +static void set_alarm(struct ptp_qoriq *ptp_qoriq) { - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u64 ns; u32 lo, hi; - ns = tmr_cnt_read(qoriq_ptp) + 1500000000ULL; + ns = tmr_cnt_read(ptp_qoriq) + 1500000000ULL; ns = div_u64(ns, 1000000000UL) * 1000000000ULL; - ns -= qoriq_ptp->tclk_period; + ns -= ptp_qoriq->tclk_period; hi = ns >> 32; lo = ns & 0xffffffff; qoriq_write(®s->alarm_regs->tmr_alarm1_l, lo); qoriq_write(®s->alarm_regs->tmr_alarm1_h, hi); } -/* Caller must hold qoriq_ptp->lock. */ -static void set_fipers(struct qoriq_ptp *qoriq_ptp) +/* Caller must hold ptp_qoriq->lock. */ +static void set_fipers(struct ptp_qoriq *ptp_qoriq) { - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; - set_alarm(qoriq_ptp); - qoriq_write(®s->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1); - qoriq_write(®s->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2); + set_alarm(ptp_qoriq); + qoriq_write(®s->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1); + qoriq_write(®s->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2); } -static int extts_clean_up(struct qoriq_ptp *qoriq_ptp, int index, +static int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, bool update_event) { - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; struct ptp_clock_event event; void __iomem *reg_etts_l; void __iomem *reg_etts_h; @@ -122,11 +122,11 @@ static int extts_clean_up(struct qoriq_ptp *qoriq_ptp, int index, if (update_event) { event.timestamp = ((u64) hi) << 32; event.timestamp |= lo; - ptp_clock_event(qoriq_ptp->clock, &event); + ptp_clock_event(ptp_qoriq->clock, &event); } stat = qoriq_read(®s->ctrl_regs->tmr_stat); - } while (qoriq_ptp->extts_fifo_support && (stat & valid)); + } while (ptp_qoriq->extts_fifo_support && (stat & valid)); return 0; } @@ -137,61 +137,61 @@ static int extts_clean_up(struct qoriq_ptp *qoriq_ptp, int index, static irqreturn_t isr(int irq, void *priv) { - struct qoriq_ptp *qoriq_ptp = priv; - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq *ptp_qoriq = priv; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; struct ptp_clock_event event; u64 ns; u32 ack = 0, lo, hi, mask, val, irqs; - spin_lock(&qoriq_ptp->lock); + spin_lock(&ptp_qoriq->lock); val = qoriq_read(®s->ctrl_regs->tmr_tevent); mask = qoriq_read(®s->ctrl_regs->tmr_temask); - spin_unlock(&qoriq_ptp->lock); + spin_unlock(&ptp_qoriq->lock); irqs = val & mask; if (irqs & ETS1) { ack |= ETS1; - extts_clean_up(qoriq_ptp, 0, true); + extts_clean_up(ptp_qoriq, 0, true); } if (irqs & ETS2) { ack |= ETS2; - extts_clean_up(qoriq_ptp, 1, true); + extts_clean_up(ptp_qoriq, 1, true); } if (irqs & ALM2) { ack |= ALM2; - if (qoriq_ptp->alarm_value) { + if (ptp_qoriq->alarm_value) { event.type = PTP_CLOCK_ALARM; event.index = 0; - event.timestamp = qoriq_ptp->alarm_value; - ptp_clock_event(qoriq_ptp->clock, &event); + event.timestamp = ptp_qoriq->alarm_value; + ptp_clock_event(ptp_qoriq->clock, &event); } - if (qoriq_ptp->alarm_interval) { - ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval; + if (ptp_qoriq->alarm_interval) { + ns = ptp_qoriq->alarm_value + ptp_qoriq->alarm_interval; hi = ns >> 32; lo = ns & 0xffffffff; qoriq_write(®s->alarm_regs->tmr_alarm2_l, lo); qoriq_write(®s->alarm_regs->tmr_alarm2_h, hi); - qoriq_ptp->alarm_value = ns; + ptp_qoriq->alarm_value = ns; } else { - spin_lock(&qoriq_ptp->lock); + spin_lock(&ptp_qoriq->lock); mask = qoriq_read(®s->ctrl_regs->tmr_temask); mask &= ~ALM2EN; qoriq_write(®s->ctrl_regs->tmr_temask, mask); - spin_unlock(&qoriq_ptp->lock); - qoriq_ptp->alarm_value = 0; - qoriq_ptp->alarm_interval = 0; + spin_unlock(&ptp_qoriq->lock); + ptp_qoriq->alarm_value = 0; + ptp_qoriq->alarm_interval = 0; } } if (irqs & PP1) { ack |= PP1; event.type = PTP_CLOCK_PPS; - ptp_clock_event(qoriq_ptp->clock, &event); + ptp_clock_event(ptp_qoriq->clock, &event); } if (ack) { @@ -210,14 +210,14 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) u64 adj, diff; u32 tmr_add; int neg_adj = 0; - struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; if (scaled_ppm < 0) { neg_adj = 1; scaled_ppm = -scaled_ppm; } - tmr_add = qoriq_ptp->tmr_add; + tmr_add = ptp_qoriq->tmr_add; adj = tmr_add; /* calculate diff as adj*(scaled_ppm/65536)/1000000 @@ -238,16 +238,16 @@ static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta) { s64 now; unsigned long flags; - struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); + struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); - spin_lock_irqsave(&qoriq_ptp->lock, flags); + spin_lock_irqsave(&ptp_qoriq->lock, flags); - now = tmr_cnt_read(qoriq_ptp); + now = tmr_cnt_read(ptp_qoriq); now += delta; - tmr_cnt_write(qoriq_ptp, now); - set_fipers(qoriq_ptp); + tmr_cnt_write(ptp_qoriq, now); + set_fipers(ptp_qoriq); - spin_unlock_irqrestore(&qoriq_ptp->lock, flags); + spin_unlock_irqrestore(&ptp_qoriq->lock, flags); return 0; } @@ -257,13 +257,13 @@ static int ptp_qoriq_gettime(struct ptp_clock_info *ptp, { u64 ns; unsigned long flags; - struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); + struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); - spin_lock_irqsave(&qoriq_ptp->lock, flags); + spin_lock_irqsave(&ptp_qoriq->lock, flags); - ns = tmr_cnt_read(qoriq_ptp); + ns = tmr_cnt_read(ptp_qoriq); - spin_unlock_irqrestore(&qoriq_ptp->lock, flags); + spin_unlock_irqrestore(&ptp_qoriq->lock, flags); *ts = ns_to_timespec64(ns); @@ -275,16 +275,16 @@ static int ptp_qoriq_settime(struct ptp_clock_info *ptp, { u64 ns; unsigned long flags; - struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); + struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); ns = timespec64_to_ns(ts); - spin_lock_irqsave(&qoriq_ptp->lock, flags); + spin_lock_irqsave(&ptp_qoriq->lock, flags); - tmr_cnt_write(qoriq_ptp, ns); - set_fipers(qoriq_ptp); + tmr_cnt_write(ptp_qoriq, ns); + set_fipers(ptp_qoriq); - spin_unlock_irqrestore(&qoriq_ptp->lock, flags); + spin_unlock_irqrestore(&ptp_qoriq->lock, flags); return 0; } @@ -292,8 +292,8 @@ static int ptp_qoriq_settime(struct ptp_clock_info *ptp, static int ptp_qoriq_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) { - struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; unsigned long flags; u32 bit, mask = 0; @@ -311,7 +311,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, } if (on) - extts_clean_up(qoriq_ptp, rq->extts.index, false); + extts_clean_up(ptp_qoriq, rq->extts.index, false); break; case PTP_CLK_REQ_PPS: @@ -321,7 +321,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, return -EOPNOTSUPP; } - spin_lock_irqsave(&qoriq_ptp->lock, flags); + spin_lock_irqsave(&ptp_qoriq->lock, flags); mask = qoriq_read(®s->ctrl_regs->tmr_temask); if (on) { @@ -333,7 +333,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, qoriq_write(®s->ctrl_regs->tmr_temask, mask); - spin_unlock_irqrestore(&qoriq_ptp->lock, flags); + spin_unlock_irqrestore(&ptp_qoriq->lock, flags); return 0; } @@ -354,7 +354,7 @@ static const struct ptp_clock_info ptp_qoriq_caps = { }; /** - * qoriq_ptp_nominal_freq - calculate nominal frequency according to + * ptp_qoriq_nominal_freq - calculate nominal frequency according to * reference clock frequency * * @clk_src: reference clock frequency @@ -365,7 +365,7 @@ static const struct ptp_clock_info ptp_qoriq_caps = { * * Return the nominal frequency */ -static u32 qoriq_ptp_nominal_freq(u32 clk_src) +static u32 ptp_qoriq_nominal_freq(u32 clk_src) { u32 remainder = 0; @@ -385,9 +385,9 @@ static u32 qoriq_ptp_nominal_freq(u32 clk_src) } /** - * qoriq_ptp_auto_config - calculate a set of default configurations + * ptp_qoriq_auto_config - calculate a set of default configurations * - * @qoriq_ptp: pointer to qoriq_ptp + * @ptp_qoriq: pointer to ptp_qoriq * @node: pointer to device_node * * If below dts properties are not provided, this function will be @@ -401,7 +401,7 @@ static u32 qoriq_ptp_nominal_freq(u32 clk_src) * * Return 0 if success */ -static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp, +static int ptp_qoriq_auto_config(struct ptp_qoriq *ptp_qoriq, struct device_node *node) { struct clk *clk; @@ -411,7 +411,7 @@ static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp, u32 remainder = 0; u32 clk_src = 0; - qoriq_ptp->cksel = DEFAULT_CKSEL; + ptp_qoriq->cksel = DEFAULT_CKSEL; clk = of_clk_get(node, 0); if (!IS_ERR(clk)) { @@ -424,12 +424,12 @@ static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp, return -EINVAL; } - nominal_freq = qoriq_ptp_nominal_freq(clk_src); + nominal_freq = ptp_qoriq_nominal_freq(clk_src); if (!nominal_freq) return -EINVAL; - qoriq_ptp->tclk_period = 1000000000UL / nominal_freq; - qoriq_ptp->tmr_prsc = DEFAULT_TMR_PRSC; + ptp_qoriq->tclk_period = 1000000000UL / nominal_freq; + ptp_qoriq->tmr_prsc = DEFAULT_TMR_PRSC; /* Calculate initial frequency compensation value for TMR_ADD register. * freq_comp = ceil(2^32 / freq_ratio) @@ -440,171 +440,171 @@ static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp, if (remainder) freq_comp++; - qoriq_ptp->tmr_add = freq_comp; - qoriq_ptp->tmr_fiper1 = DEFAULT_FIPER1_PERIOD - qoriq_ptp->tclk_period; - qoriq_ptp->tmr_fiper2 = DEFAULT_FIPER2_PERIOD - qoriq_ptp->tclk_period; + ptp_qoriq->tmr_add = freq_comp; + ptp_qoriq->tmr_fiper1 = DEFAULT_FIPER1_PERIOD - ptp_qoriq->tclk_period; + ptp_qoriq->tmr_fiper2 = DEFAULT_FIPER2_PERIOD - ptp_qoriq->tclk_period; /* max_adj = 1000000000 * (freq_ratio - 1.0) - 1 * freq_ratio = reference_clock_freq / nominal_freq */ max_adj = 1000000000ULL * (clk_src - nominal_freq); max_adj = div_u64(max_adj, nominal_freq) - 1; - qoriq_ptp->caps.max_adj = max_adj; + ptp_qoriq->caps.max_adj = max_adj; return 0; } -static int qoriq_ptp_probe(struct platform_device *dev) +static int ptp_qoriq_probe(struct platform_device *dev) { struct device_node *node = dev->dev.of_node; - struct qoriq_ptp *qoriq_ptp; - struct qoriq_ptp_registers *regs; + struct ptp_qoriq *ptp_qoriq; + struct ptp_qoriq_registers *regs; struct timespec64 now; int err = -ENOMEM; u32 tmr_ctrl; unsigned long flags; void __iomem *base; - qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL); - if (!qoriq_ptp) + ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL); + if (!ptp_qoriq) goto no_memory; err = -EINVAL; - qoriq_ptp->dev = &dev->dev; - qoriq_ptp->caps = ptp_qoriq_caps; + ptp_qoriq->dev = &dev->dev; + ptp_qoriq->caps = ptp_qoriq_caps; - if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel)) - qoriq_ptp->cksel = DEFAULT_CKSEL; + if (of_property_read_u32(node, "fsl,cksel", &ptp_qoriq->cksel)) + ptp_qoriq->cksel = DEFAULT_CKSEL; if (of_property_read_bool(node, "fsl,extts-fifo")) - qoriq_ptp->extts_fifo_support = true; + ptp_qoriq->extts_fifo_support = true; else - qoriq_ptp->extts_fifo_support = false; + ptp_qoriq->extts_fifo_support = false; if (of_property_read_u32(node, - "fsl,tclk-period", &qoriq_ptp->tclk_period) || + "fsl,tclk-period", &ptp_qoriq->tclk_period) || of_property_read_u32(node, - "fsl,tmr-prsc", &qoriq_ptp->tmr_prsc) || + "fsl,tmr-prsc", &ptp_qoriq->tmr_prsc) || of_property_read_u32(node, - "fsl,tmr-add", &qoriq_ptp->tmr_add) || + "fsl,tmr-add", &ptp_qoriq->tmr_add) || of_property_read_u32(node, - "fsl,tmr-fiper1", &qoriq_ptp->tmr_fiper1) || + "fsl,tmr-fiper1", &ptp_qoriq->tmr_fiper1) || of_property_read_u32(node, - "fsl,tmr-fiper2", &qoriq_ptp->tmr_fiper2) || + "fsl,tmr-fiper2", &ptp_qoriq->tmr_fiper2) || of_property_read_u32(node, - "fsl,max-adj", &qoriq_ptp->caps.max_adj)) { + "fsl,max-adj", &ptp_qoriq->caps.max_adj)) { pr_warn("device tree node missing required elements, try automatic configuration\n"); - if (qoriq_ptp_auto_config(qoriq_ptp, node)) + if (ptp_qoriq_auto_config(ptp_qoriq, node)) goto no_config; } err = -ENODEV; - qoriq_ptp->irq = platform_get_irq(dev, 0); + ptp_qoriq->irq = platform_get_irq(dev, 0); - if (qoriq_ptp->irq < 0) { + if (ptp_qoriq->irq < 0) { pr_err("irq not in device tree\n"); goto no_node; } - if (request_irq(qoriq_ptp->irq, isr, IRQF_SHARED, DRIVER, qoriq_ptp)) { + if (request_irq(ptp_qoriq->irq, isr, IRQF_SHARED, DRIVER, ptp_qoriq)) { pr_err("request_irq failed\n"); goto no_node; } - qoriq_ptp->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!qoriq_ptp->rsrc) { + ptp_qoriq->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!ptp_qoriq->rsrc) { pr_err("no resource\n"); goto no_resource; } - if (request_resource(&iomem_resource, qoriq_ptp->rsrc)) { + if (request_resource(&iomem_resource, ptp_qoriq->rsrc)) { pr_err("resource busy\n"); goto no_resource; } - spin_lock_init(&qoriq_ptp->lock); + spin_lock_init(&ptp_qoriq->lock); - base = ioremap(qoriq_ptp->rsrc->start, - resource_size(qoriq_ptp->rsrc)); + base = ioremap(ptp_qoriq->rsrc->start, + resource_size(ptp_qoriq->rsrc)); if (!base) { pr_err("ioremap ptp registers failed\n"); goto no_ioremap; } - qoriq_ptp->base = base; + ptp_qoriq->base = base; if (of_device_is_compatible(node, "fsl,fman-ptp-timer")) { - qoriq_ptp->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET; - qoriq_ptp->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET; - qoriq_ptp->regs.fiper_regs = base + FMAN_FIPER_REGS_OFFSET; - qoriq_ptp->regs.etts_regs = base + FMAN_ETTS_REGS_OFFSET; + ptp_qoriq->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET; + ptp_qoriq->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET; + ptp_qoriq->regs.fiper_regs = base + FMAN_FIPER_REGS_OFFSET; + ptp_qoriq->regs.etts_regs = base + FMAN_ETTS_REGS_OFFSET; } else { - qoriq_ptp->regs.ctrl_regs = base + CTRL_REGS_OFFSET; - qoriq_ptp->regs.alarm_regs = base + ALARM_REGS_OFFSET; - qoriq_ptp->regs.fiper_regs = base + FIPER_REGS_OFFSET; - qoriq_ptp->regs.etts_regs = base + ETTS_REGS_OFFSET; + ptp_qoriq->regs.ctrl_regs = base + CTRL_REGS_OFFSET; + ptp_qoriq->regs.alarm_regs = base + ALARM_REGS_OFFSET; + ptp_qoriq->regs.fiper_regs = base + FIPER_REGS_OFFSET; + ptp_qoriq->regs.etts_regs = base + ETTS_REGS_OFFSET; } ktime_get_real_ts64(&now); - ptp_qoriq_settime(&qoriq_ptp->caps, &now); + ptp_qoriq_settime(&ptp_qoriq->caps, &now); tmr_ctrl = - (qoriq_ptp->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | - (qoriq_ptp->cksel & CKSEL_MASK) << CKSEL_SHIFT; + (ptp_qoriq->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | + (ptp_qoriq->cksel & CKSEL_MASK) << CKSEL_SHIFT; - spin_lock_irqsave(&qoriq_ptp->lock, flags); + spin_lock_irqsave(&ptp_qoriq->lock, flags); - regs = &qoriq_ptp->regs; + regs = &ptp_qoriq->regs; qoriq_write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl); - qoriq_write(®s->ctrl_regs->tmr_add, qoriq_ptp->tmr_add); - qoriq_write(®s->ctrl_regs->tmr_prsc, qoriq_ptp->tmr_prsc); - qoriq_write(®s->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1); - qoriq_write(®s->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2); - set_alarm(qoriq_ptp); + qoriq_write(®s->ctrl_regs->tmr_add, ptp_qoriq->tmr_add); + qoriq_write(®s->ctrl_regs->tmr_prsc, ptp_qoriq->tmr_prsc); + qoriq_write(®s->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1); + qoriq_write(®s->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2); + set_alarm(ptp_qoriq); qoriq_write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD); - spin_unlock_irqrestore(&qoriq_ptp->lock, flags); + spin_unlock_irqrestore(&ptp_qoriq->lock, flags); - qoriq_ptp->clock = ptp_clock_register(&qoriq_ptp->caps, &dev->dev); - if (IS_ERR(qoriq_ptp->clock)) { - err = PTR_ERR(qoriq_ptp->clock); + ptp_qoriq->clock = ptp_clock_register(&ptp_qoriq->caps, &dev->dev); + if (IS_ERR(ptp_qoriq->clock)) { + err = PTR_ERR(ptp_qoriq->clock); goto no_clock; } - qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock); + ptp_qoriq->phc_index = ptp_clock_index(ptp_qoriq->clock); - ptp_qoriq_create_debugfs(qoriq_ptp); - platform_set_drvdata(dev, qoriq_ptp); + ptp_qoriq_create_debugfs(ptp_qoriq); + platform_set_drvdata(dev, ptp_qoriq); return 0; no_clock: - iounmap(qoriq_ptp->base); + iounmap(ptp_qoriq->base); no_ioremap: - release_resource(qoriq_ptp->rsrc); + release_resource(ptp_qoriq->rsrc); no_resource: - free_irq(qoriq_ptp->irq, qoriq_ptp); + free_irq(ptp_qoriq->irq, ptp_qoriq); no_config: no_node: - kfree(qoriq_ptp); + kfree(ptp_qoriq); no_memory: return err; } -static int qoriq_ptp_remove(struct platform_device *dev) +static int ptp_qoriq_remove(struct platform_device *dev) { - struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev); - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq *ptp_qoriq = platform_get_drvdata(dev); + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; qoriq_write(®s->ctrl_regs->tmr_temask, 0); qoriq_write(®s->ctrl_regs->tmr_ctrl, 0); - ptp_qoriq_remove_debugfs(qoriq_ptp); - ptp_clock_unregister(qoriq_ptp->clock); - iounmap(qoriq_ptp->base); - release_resource(qoriq_ptp->rsrc); - free_irq(qoriq_ptp->irq, qoriq_ptp); - kfree(qoriq_ptp); + ptp_qoriq_remove_debugfs(ptp_qoriq); + ptp_clock_unregister(ptp_qoriq->clock); + iounmap(ptp_qoriq->base); + release_resource(ptp_qoriq->rsrc); + free_irq(ptp_qoriq->irq, ptp_qoriq); + kfree(ptp_qoriq); return 0; } @@ -616,16 +616,16 @@ static const struct of_device_id match_table[] = { }; MODULE_DEVICE_TABLE(of, match_table); -static struct platform_driver qoriq_ptp_driver = { +static struct platform_driver ptp_qoriq_driver = { .driver = { .name = "ptp_qoriq", .of_match_table = match_table, }, - .probe = qoriq_ptp_probe, - .remove = qoriq_ptp_remove, + .probe = ptp_qoriq_probe, + .remove = ptp_qoriq_remove, }; -module_platform_driver(qoriq_ptp_driver); +module_platform_driver(ptp_qoriq_driver); MODULE_AUTHOR("Richard Cochran "); MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer"); diff --git a/drivers/ptp/ptp_qoriq_debugfs.c b/drivers/ptp/ptp_qoriq_debugfs.c index 970595021088..3a70daf03727 100644 --- a/drivers/ptp/ptp_qoriq_debugfs.c +++ b/drivers/ptp/ptp_qoriq_debugfs.c @@ -7,8 +7,8 @@ static int ptp_qoriq_fiper1_lpbk_get(void *data, u64 *val) { - struct qoriq_ptp *qoriq_ptp = data; - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq *ptp_qoriq = data; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 ctrl; ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); @@ -19,8 +19,8 @@ static int ptp_qoriq_fiper1_lpbk_get(void *data, u64 *val) static int ptp_qoriq_fiper1_lpbk_set(void *data, u64 val) { - struct qoriq_ptp *qoriq_ptp = data; - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq *ptp_qoriq = data; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 ctrl; ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); @@ -38,8 +38,8 @@ DEFINE_DEBUGFS_ATTRIBUTE(ptp_qoriq_fiper1_fops, ptp_qoriq_fiper1_lpbk_get, static int ptp_qoriq_fiper2_lpbk_get(void *data, u64 *val) { - struct qoriq_ptp *qoriq_ptp = data; - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq *ptp_qoriq = data; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 ctrl; ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); @@ -50,8 +50,8 @@ static int ptp_qoriq_fiper2_lpbk_get(void *data, u64 *val) static int ptp_qoriq_fiper2_lpbk_set(void *data, u64 val) { - struct qoriq_ptp *qoriq_ptp = data; - struct qoriq_ptp_registers *regs = &qoriq_ptp->regs; + struct ptp_qoriq *ptp_qoriq = data; + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 ctrl; ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); @@ -67,35 +67,35 @@ static int ptp_qoriq_fiper2_lpbk_set(void *data, u64 val) DEFINE_DEBUGFS_ATTRIBUTE(ptp_qoriq_fiper2_fops, ptp_qoriq_fiper2_lpbk_get, ptp_qoriq_fiper2_lpbk_set, "%llu\n"); -void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp) +void ptp_qoriq_create_debugfs(struct ptp_qoriq *ptp_qoriq) { struct dentry *root; - root = debugfs_create_dir(dev_name(qoriq_ptp->dev), NULL); + root = debugfs_create_dir(dev_name(ptp_qoriq->dev), NULL); if (IS_ERR(root)) return; if (!root) goto err_root; - qoriq_ptp->debugfs_root = root; + ptp_qoriq->debugfs_root = root; if (!debugfs_create_file_unsafe("fiper1-loopback", 0600, root, - qoriq_ptp, &ptp_qoriq_fiper1_fops)) + ptp_qoriq, &ptp_qoriq_fiper1_fops)) goto err_node; if (!debugfs_create_file_unsafe("fiper2-loopback", 0600, root, - qoriq_ptp, &ptp_qoriq_fiper2_fops)) + ptp_qoriq, &ptp_qoriq_fiper2_fops)) goto err_node; return; err_node: debugfs_remove_recursive(root); - qoriq_ptp->debugfs_root = NULL; + ptp_qoriq->debugfs_root = NULL; err_root: - dev_err(qoriq_ptp->dev, "failed to initialize debugfs\n"); + dev_err(ptp_qoriq->dev, "failed to initialize debugfs\n"); } -void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp) +void ptp_qoriq_remove_debugfs(struct ptp_qoriq *ptp_qoriq) { - debugfs_remove_recursive(qoriq_ptp->debugfs_root); - qoriq_ptp->debugfs_root = NULL; + debugfs_remove_recursive(ptp_qoriq->debugfs_root); + ptp_qoriq->debugfs_root = NULL; } diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index 94e9797e434c..c2a32d9ec6ba 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -49,7 +49,7 @@ struct etts_regs { u32 tmr_etts2_l; /* Timestamp of general purpose external trigger */ }; -struct qoriq_ptp_registers { +struct ptp_qoriq_registers { struct ctrl_regs __iomem *ctrl_regs; struct alarm_regs __iomem *alarm_regs; struct fiper_regs __iomem *fiper_regs; @@ -136,9 +136,9 @@ struct qoriq_ptp_registers { #define DEFAULT_FIPER1_PERIOD 1000000000 #define DEFAULT_FIPER2_PERIOD 100000 -struct qoriq_ptp { +struct ptp_qoriq { void __iomem *base; - struct qoriq_ptp_registers regs; + struct ptp_qoriq_registers regs; spinlock_t lock; /* protects regs */ struct ptp_clock *clock; struct ptp_clock_info caps; @@ -172,12 +172,12 @@ static inline void qoriq_write(unsigned __iomem *addr, u32 val) } #ifdef CONFIG_DEBUG_FS -void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp); -void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp); +void ptp_qoriq_create_debugfs(struct ptp_qoriq *ptp_qoriq); +void ptp_qoriq_remove_debugfs(struct ptp_qoriq *ptp_qoriq); #else -static inline void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp) +static inline void ptp_qoriq_create_debugfs(struct ptp_qoriq *ptp_qoriq) { } -static inline void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp) +static inline void ptp_qoriq_remove_debugfs(struct ptp_qoriq *ptp_qoriq) { } #endif -- cgit v1.2.3 From 73356e4ea895d5d4fb2bed30c32d3293b090f3ce Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 12 Feb 2019 12:23:57 +0800 Subject: ptp_qoriq: make ptp operations global This patch is to make functions of ptp operations global, so that ENETC PTP driver which is a PCI driver for same 1588 timer IP block could reuse them. Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/ptp/ptp_qoriq.c | 27 ++++++++++++++++----------- include/linux/fsl/ptp_qoriq.h | 9 +++++++++ 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index 8c10d0f8864f..1f3e73e62de9 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -135,7 +134,7 @@ static int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, * Interrupt service routine */ -static irqreturn_t isr(int irq, void *priv) +irqreturn_t ptp_qoriq_isr(int irq, void *priv) { struct ptp_qoriq *ptp_qoriq = priv; struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; @@ -200,12 +199,13 @@ static irqreturn_t isr(int irq, void *priv) } else return IRQ_NONE; } +EXPORT_SYMBOL_GPL(ptp_qoriq_isr); /* * PTP clock operations */ -static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) { u64 adj, diff; u32 tmr_add; @@ -233,8 +233,9 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) return 0; } +EXPORT_SYMBOL_GPL(ptp_qoriq_adjfine); -static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta) +int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta) { s64 now; unsigned long flags; @@ -251,9 +252,9 @@ static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta) return 0; } +EXPORT_SYMBOL_GPL(ptp_qoriq_adjtime); -static int ptp_qoriq_gettime(struct ptp_clock_info *ptp, - struct timespec64 *ts) +int ptp_qoriq_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) { u64 ns; unsigned long flags; @@ -269,9 +270,10 @@ static int ptp_qoriq_gettime(struct ptp_clock_info *ptp, return 0; } +EXPORT_SYMBOL_GPL(ptp_qoriq_gettime); -static int ptp_qoriq_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts) +int ptp_qoriq_settime(struct ptp_clock_info *ptp, + const struct timespec64 *ts) { u64 ns; unsigned long flags; @@ -288,9 +290,10 @@ static int ptp_qoriq_settime(struct ptp_clock_info *ptp, return 0; } +EXPORT_SYMBOL_GPL(ptp_qoriq_settime); -static int ptp_qoriq_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, int on) +int ptp_qoriq_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) { struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; @@ -336,6 +339,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, spin_unlock_irqrestore(&ptp_qoriq->lock, flags); return 0; } +EXPORT_SYMBOL_GPL(ptp_qoriq_enable); static const struct ptp_clock_info ptp_qoriq_caps = { .owner = THIS_MODULE, @@ -508,7 +512,8 @@ static int ptp_qoriq_probe(struct platform_device *dev) pr_err("irq not in device tree\n"); goto no_node; } - if (request_irq(ptp_qoriq->irq, isr, IRQF_SHARED, DRIVER, ptp_qoriq)) { + if (request_irq(ptp_qoriq->irq, ptp_qoriq_isr, IRQF_SHARED, + DRIVER, ptp_qoriq)) { pr_err("request_irq failed\n"); goto no_node; } diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index c2a32d9ec6ba..75e6f0523cb1 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -7,6 +7,7 @@ #define __PTP_QORIQ_H__ #include +#include #include /* @@ -171,6 +172,14 @@ static inline void qoriq_write(unsigned __iomem *addr, u32 val) iowrite32be(val, addr); } +irqreturn_t ptp_qoriq_isr(int irq, void *priv); +int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm); +int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta); +int ptp_qoriq_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts); +int ptp_qoriq_settime(struct ptp_clock_info *ptp, + const struct timespec64 *ts); +int ptp_qoriq_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on); #ifdef CONFIG_DEBUG_FS void ptp_qoriq_create_debugfs(struct ptp_qoriq *ptp_qoriq); void ptp_qoriq_remove_debugfs(struct ptp_qoriq *ptp_qoriq); -- cgit v1.2.3 From ff54571a747bc1fc8e132ef9c512451ec6de3336 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 12 Feb 2019 12:23:58 +0800 Subject: ptp_qoriq: convert to use ptp_qoriq_init/free Moved QorIQ PTP clock initialization/free into new functions ptp_qoriq_init()/ptp_qoriq_free(). These functions could also be reused by ENETC PTP drvier which is a PCI driver for same 1588 timer IP block. Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/ptp/ptp_qoriq.c | 144 ++++++++++++++++++++++-------------------- include/linux/fsl/ptp_qoriq.h | 3 + 2 files changed, 80 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index 1f3e73e62de9..db4f929ea4e9 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -458,25 +458,17 @@ static int ptp_qoriq_auto_config(struct ptp_qoriq *ptp_qoriq, return 0; } -static int ptp_qoriq_probe(struct platform_device *dev) +int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, + const struct ptp_clock_info caps) { - struct device_node *node = dev->dev.of_node; - struct ptp_qoriq *ptp_qoriq; + struct device_node *node = ptp_qoriq->dev->of_node; struct ptp_qoriq_registers *regs; struct timespec64 now; - int err = -ENOMEM; - u32 tmr_ctrl; unsigned long flags; - void __iomem *base; - - ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL); - if (!ptp_qoriq) - goto no_memory; - - err = -EINVAL; + u32 tmr_ctrl; - ptp_qoriq->dev = &dev->dev; - ptp_qoriq->caps = ptp_qoriq_caps; + ptp_qoriq->base = base; + ptp_qoriq->caps = caps; if (of_property_read_u32(node, "fsl,cksel", &ptp_qoriq->cksel)) ptp_qoriq->cksel = DEFAULT_CKSEL; @@ -501,44 +493,9 @@ static int ptp_qoriq_probe(struct platform_device *dev) pr_warn("device tree node missing required elements, try automatic configuration\n"); if (ptp_qoriq_auto_config(ptp_qoriq, node)) - goto no_config; + return -ENODEV; } - err = -ENODEV; - - ptp_qoriq->irq = platform_get_irq(dev, 0); - - if (ptp_qoriq->irq < 0) { - pr_err("irq not in device tree\n"); - goto no_node; - } - if (request_irq(ptp_qoriq->irq, ptp_qoriq_isr, IRQF_SHARED, - DRIVER, ptp_qoriq)) { - pr_err("request_irq failed\n"); - goto no_node; - } - - ptp_qoriq->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!ptp_qoriq->rsrc) { - pr_err("no resource\n"); - goto no_resource; - } - if (request_resource(&iomem_resource, ptp_qoriq->rsrc)) { - pr_err("resource busy\n"); - goto no_resource; - } - - spin_lock_init(&ptp_qoriq->lock); - - base = ioremap(ptp_qoriq->rsrc->start, - resource_size(ptp_qoriq->rsrc)); - if (!base) { - pr_err("ioremap ptp registers failed\n"); - goto no_ioremap; - } - - ptp_qoriq->base = base; - if (of_device_is_compatible(node, "fsl,fman-ptp-timer")) { ptp_qoriq->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET; ptp_qoriq->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET; @@ -558,6 +515,7 @@ static int ptp_qoriq_probe(struct platform_device *dev) (ptp_qoriq->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | (ptp_qoriq->cksel & CKSEL_MASK) << CKSEL_SHIFT; + spin_lock_init(&ptp_qoriq->lock); spin_lock_irqsave(&ptp_qoriq->lock, flags); regs = &ptp_qoriq->regs; @@ -571,16 +529,77 @@ static int ptp_qoriq_probe(struct platform_device *dev) spin_unlock_irqrestore(&ptp_qoriq->lock, flags); - ptp_qoriq->clock = ptp_clock_register(&ptp_qoriq->caps, &dev->dev); - if (IS_ERR(ptp_qoriq->clock)) { - err = PTR_ERR(ptp_qoriq->clock); - goto no_clock; - } - ptp_qoriq->phc_index = ptp_clock_index(ptp_qoriq->clock); + ptp_qoriq->clock = ptp_clock_register(&ptp_qoriq->caps, ptp_qoriq->dev); + if (IS_ERR(ptp_qoriq->clock)) + return PTR_ERR(ptp_qoriq->clock); + ptp_qoriq->phc_index = ptp_clock_index(ptp_qoriq->clock); ptp_qoriq_create_debugfs(ptp_qoriq); - platform_set_drvdata(dev, ptp_qoriq); + return 0; +} +EXPORT_SYMBOL_GPL(ptp_qoriq_init); + +void ptp_qoriq_free(struct ptp_qoriq *ptp_qoriq) +{ + struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; + + qoriq_write(®s->ctrl_regs->tmr_temask, 0); + qoriq_write(®s->ctrl_regs->tmr_ctrl, 0); + + ptp_qoriq_remove_debugfs(ptp_qoriq); + ptp_clock_unregister(ptp_qoriq->clock); + iounmap(ptp_qoriq->base); + free_irq(ptp_qoriq->irq, ptp_qoriq); +} +EXPORT_SYMBOL_GPL(ptp_qoriq_free); + +static int ptp_qoriq_probe(struct platform_device *dev) +{ + struct ptp_qoriq *ptp_qoriq; + int err = -ENOMEM; + void __iomem *base; + ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL); + if (!ptp_qoriq) + goto no_memory; + + ptp_qoriq->dev = &dev->dev; + + err = -ENODEV; + + ptp_qoriq->irq = platform_get_irq(dev, 0); + if (ptp_qoriq->irq < 0) { + pr_err("irq not in device tree\n"); + goto no_node; + } + if (request_irq(ptp_qoriq->irq, ptp_qoriq_isr, IRQF_SHARED, + DRIVER, ptp_qoriq)) { + pr_err("request_irq failed\n"); + goto no_node; + } + + ptp_qoriq->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!ptp_qoriq->rsrc) { + pr_err("no resource\n"); + goto no_resource; + } + if (request_resource(&iomem_resource, ptp_qoriq->rsrc)) { + pr_err("resource busy\n"); + goto no_resource; + } + + base = ioremap(ptp_qoriq->rsrc->start, + resource_size(ptp_qoriq->rsrc)); + if (!base) { + pr_err("ioremap ptp registers failed\n"); + goto no_ioremap; + } + + err = ptp_qoriq_init(ptp_qoriq, base, ptp_qoriq_caps); + if (err) + goto no_clock; + + platform_set_drvdata(dev, ptp_qoriq); return 0; no_clock: @@ -589,7 +608,6 @@ no_ioremap: release_resource(ptp_qoriq->rsrc); no_resource: free_irq(ptp_qoriq->irq, ptp_qoriq); -no_config: no_node: kfree(ptp_qoriq); no_memory: @@ -599,18 +617,10 @@ no_memory: static int ptp_qoriq_remove(struct platform_device *dev) { struct ptp_qoriq *ptp_qoriq = platform_get_drvdata(dev); - struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; - qoriq_write(®s->ctrl_regs->tmr_temask, 0); - qoriq_write(®s->ctrl_regs->tmr_ctrl, 0); - - ptp_qoriq_remove_debugfs(ptp_qoriq); - ptp_clock_unregister(ptp_qoriq->clock); - iounmap(ptp_qoriq->base); + ptp_qoriq_free(ptp_qoriq); release_resource(ptp_qoriq->rsrc); - free_irq(ptp_qoriq->irq, ptp_qoriq); kfree(ptp_qoriq); - return 0; } diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index 75e6f0523cb1..757aec385493 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -173,6 +173,9 @@ static inline void qoriq_write(unsigned __iomem *addr, u32 val) } irqreturn_t ptp_qoriq_isr(int irq, void *priv); +int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, + const struct ptp_clock_info caps); +void ptp_qoriq_free(struct ptp_qoriq *ptp_qoriq); int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm); int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta); int ptp_qoriq_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts); -- cgit v1.2.3 From f038ddf25b80be90e1af9439935bdb66fdbf5e28 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 12 Feb 2019 12:23:59 +0800 Subject: ptp_qoriq: add little enadian support There is QorIQ 1588 timer IP block on the new ENETC Ethernet controller. However it uses little endian mode which is different with before. This patch is to add little endian support for the driver by using "little-endian" dts node property. Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/ptp/ptp_qoriq.c | 69 +++++++++++++++++++++++------------------ drivers/ptp/ptp_qoriq_debugfs.c | 12 +++---- include/linux/fsl/ptp_qoriq.h | 21 +++++++++---- 3 files changed, 60 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index db4f929ea4e9..ed4dc398c57b 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -43,8 +43,8 @@ static u64 tmr_cnt_read(struct ptp_qoriq *ptp_qoriq) u64 ns; u32 lo, hi; - lo = qoriq_read(®s->ctrl_regs->tmr_cnt_l); - hi = qoriq_read(®s->ctrl_regs->tmr_cnt_h); + lo = ptp_qoriq->read(®s->ctrl_regs->tmr_cnt_l); + hi = ptp_qoriq->read(®s->ctrl_regs->tmr_cnt_h); ns = ((u64) hi) << 32; ns |= lo; return ns; @@ -57,8 +57,8 @@ static void tmr_cnt_write(struct ptp_qoriq *ptp_qoriq, u64 ns) u32 hi = ns >> 32; u32 lo = ns & 0xffffffff; - qoriq_write(®s->ctrl_regs->tmr_cnt_l, lo); - qoriq_write(®s->ctrl_regs->tmr_cnt_h, hi); + ptp_qoriq->write(®s->ctrl_regs->tmr_cnt_l, lo); + ptp_qoriq->write(®s->ctrl_regs->tmr_cnt_h, hi); } /* Caller must hold ptp_qoriq->lock. */ @@ -73,8 +73,8 @@ static void set_alarm(struct ptp_qoriq *ptp_qoriq) ns -= ptp_qoriq->tclk_period; hi = ns >> 32; lo = ns & 0xffffffff; - qoriq_write(®s->alarm_regs->tmr_alarm1_l, lo); - qoriq_write(®s->alarm_regs->tmr_alarm1_h, hi); + ptp_qoriq->write(®s->alarm_regs->tmr_alarm1_l, lo); + ptp_qoriq->write(®s->alarm_regs->tmr_alarm1_h, hi); } /* Caller must hold ptp_qoriq->lock. */ @@ -83,8 +83,8 @@ static void set_fipers(struct ptp_qoriq *ptp_qoriq) struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; set_alarm(ptp_qoriq); - qoriq_write(®s->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1); - qoriq_write(®s->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2); + ptp_qoriq->write(®s->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1); + ptp_qoriq->write(®s->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2); } static int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, @@ -115,8 +115,8 @@ static int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, event.index = index; do { - lo = qoriq_read(reg_etts_l); - hi = qoriq_read(reg_etts_h); + lo = ptp_qoriq->read(reg_etts_l); + hi = ptp_qoriq->read(reg_etts_h); if (update_event) { event.timestamp = ((u64) hi) << 32; @@ -124,7 +124,7 @@ static int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, ptp_clock_event(ptp_qoriq->clock, &event); } - stat = qoriq_read(®s->ctrl_regs->tmr_stat); + stat = ptp_qoriq->read(®s->ctrl_regs->tmr_stat); } while (ptp_qoriq->extts_fifo_support && (stat & valid)); return 0; @@ -144,8 +144,8 @@ irqreturn_t ptp_qoriq_isr(int irq, void *priv) spin_lock(&ptp_qoriq->lock); - val = qoriq_read(®s->ctrl_regs->tmr_tevent); - mask = qoriq_read(®s->ctrl_regs->tmr_temask); + val = ptp_qoriq->read(®s->ctrl_regs->tmr_tevent); + mask = ptp_qoriq->read(®s->ctrl_regs->tmr_temask); spin_unlock(&ptp_qoriq->lock); @@ -173,14 +173,14 @@ irqreturn_t ptp_qoriq_isr(int irq, void *priv) ns = ptp_qoriq->alarm_value + ptp_qoriq->alarm_interval; hi = ns >> 32; lo = ns & 0xffffffff; - qoriq_write(®s->alarm_regs->tmr_alarm2_l, lo); - qoriq_write(®s->alarm_regs->tmr_alarm2_h, hi); + ptp_qoriq->write(®s->alarm_regs->tmr_alarm2_l, lo); + ptp_qoriq->write(®s->alarm_regs->tmr_alarm2_h, hi); ptp_qoriq->alarm_value = ns; } else { spin_lock(&ptp_qoriq->lock); - mask = qoriq_read(®s->ctrl_regs->tmr_temask); + mask = ptp_qoriq->read(®s->ctrl_regs->tmr_temask); mask &= ~ALM2EN; - qoriq_write(®s->ctrl_regs->tmr_temask, mask); + ptp_qoriq->write(®s->ctrl_regs->tmr_temask, mask); spin_unlock(&ptp_qoriq->lock); ptp_qoriq->alarm_value = 0; ptp_qoriq->alarm_interval = 0; @@ -194,7 +194,7 @@ irqreturn_t ptp_qoriq_isr(int irq, void *priv) } if (ack) { - qoriq_write(®s->ctrl_regs->tmr_tevent, ack); + ptp_qoriq->write(®s->ctrl_regs->tmr_tevent, ack); return IRQ_HANDLED; } else return IRQ_NONE; @@ -229,7 +229,7 @@ int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; - qoriq_write(®s->ctrl_regs->tmr_add, tmr_add); + ptp_qoriq->write(®s->ctrl_regs->tmr_add, tmr_add); return 0; } @@ -326,15 +326,15 @@ int ptp_qoriq_enable(struct ptp_clock_info *ptp, spin_lock_irqsave(&ptp_qoriq->lock, flags); - mask = qoriq_read(®s->ctrl_regs->tmr_temask); + mask = ptp_qoriq->read(®s->ctrl_regs->tmr_temask); if (on) { mask |= bit; - qoriq_write(®s->ctrl_regs->tmr_tevent, bit); + ptp_qoriq->write(®s->ctrl_regs->tmr_tevent, bit); } else { mask &= ~bit; } - qoriq_write(®s->ctrl_regs->tmr_temask, mask); + ptp_qoriq->write(®s->ctrl_regs->tmr_temask, mask); spin_unlock_irqrestore(&ptp_qoriq->lock, flags); return 0; @@ -496,6 +496,14 @@ int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, return -ENODEV; } + if (of_property_read_bool(node, "little-endian")) { + ptp_qoriq->read = qoriq_read_le; + ptp_qoriq->write = qoriq_write_le; + } else { + ptp_qoriq->read = qoriq_read_be; + ptp_qoriq->write = qoriq_write_be; + } + if (of_device_is_compatible(node, "fsl,fman-ptp-timer")) { ptp_qoriq->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET; ptp_qoriq->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET; @@ -519,13 +527,14 @@ int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, spin_lock_irqsave(&ptp_qoriq->lock, flags); regs = &ptp_qoriq->regs; - qoriq_write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl); - qoriq_write(®s->ctrl_regs->tmr_add, ptp_qoriq->tmr_add); - qoriq_write(®s->ctrl_regs->tmr_prsc, ptp_qoriq->tmr_prsc); - qoriq_write(®s->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1); - qoriq_write(®s->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2); + ptp_qoriq->write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl); + ptp_qoriq->write(®s->ctrl_regs->tmr_add, ptp_qoriq->tmr_add); + ptp_qoriq->write(®s->ctrl_regs->tmr_prsc, ptp_qoriq->tmr_prsc); + ptp_qoriq->write(®s->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1); + ptp_qoriq->write(®s->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2); set_alarm(ptp_qoriq); - qoriq_write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD); + ptp_qoriq->write(®s->ctrl_regs->tmr_ctrl, + tmr_ctrl|FIPERST|RTPE|TE|FRD); spin_unlock_irqrestore(&ptp_qoriq->lock, flags); @@ -543,8 +552,8 @@ void ptp_qoriq_free(struct ptp_qoriq *ptp_qoriq) { struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; - qoriq_write(®s->ctrl_regs->tmr_temask, 0); - qoriq_write(®s->ctrl_regs->tmr_ctrl, 0); + ptp_qoriq->write(®s->ctrl_regs->tmr_temask, 0); + ptp_qoriq->write(®s->ctrl_regs->tmr_ctrl, 0); ptp_qoriq_remove_debugfs(ptp_qoriq); ptp_clock_unregister(ptp_qoriq->clock); diff --git a/drivers/ptp/ptp_qoriq_debugfs.c b/drivers/ptp/ptp_qoriq_debugfs.c index 3a70daf03727..e8dddcedf288 100644 --- a/drivers/ptp/ptp_qoriq_debugfs.c +++ b/drivers/ptp/ptp_qoriq_debugfs.c @@ -11,7 +11,7 @@ static int ptp_qoriq_fiper1_lpbk_get(void *data, u64 *val) struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 ctrl; - ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); + ctrl = ptp_qoriq->read(®s->ctrl_regs->tmr_ctrl); *val = ctrl & PP1L ? 1 : 0; return 0; @@ -23,13 +23,13 @@ static int ptp_qoriq_fiper1_lpbk_set(void *data, u64 val) struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 ctrl; - ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); + ctrl = ptp_qoriq->read(®s->ctrl_regs->tmr_ctrl); if (val == 0) ctrl &= ~PP1L; else ctrl |= PP1L; - qoriq_write(®s->ctrl_regs->tmr_ctrl, ctrl); + ptp_qoriq->write(®s->ctrl_regs->tmr_ctrl, ctrl); return 0; } @@ -42,7 +42,7 @@ static int ptp_qoriq_fiper2_lpbk_get(void *data, u64 *val) struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 ctrl; - ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); + ctrl = ptp_qoriq->read(®s->ctrl_regs->tmr_ctrl); *val = ctrl & PP2L ? 1 : 0; return 0; @@ -54,13 +54,13 @@ static int ptp_qoriq_fiper2_lpbk_set(void *data, u64 val) struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; u32 ctrl; - ctrl = qoriq_read(®s->ctrl_regs->tmr_ctrl); + ctrl = ptp_qoriq->read(®s->ctrl_regs->tmr_ctrl); if (val == 0) ctrl &= ~PP2L; else ctrl |= PP2L; - qoriq_write(®s->ctrl_regs->tmr_ctrl, ctrl); + ptp_qoriq->write(®s->ctrl_regs->tmr_ctrl, ctrl); return 0; } diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index 757aec385493..1f8bb6a6a121 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -157,21 +157,30 @@ struct ptp_qoriq { u32 cksel; u32 tmr_fiper1; u32 tmr_fiper2; + u32 (*read)(unsigned __iomem *addr); + void (*write)(unsigned __iomem *addr, u32 val); }; -static inline u32 qoriq_read(unsigned __iomem *addr) +static inline u32 qoriq_read_be(unsigned __iomem *addr) { - u32 val; - - val = ioread32be(addr); - return val; + return ioread32be(addr); } -static inline void qoriq_write(unsigned __iomem *addr, u32 val) +static inline void qoriq_write_be(unsigned __iomem *addr, u32 val) { iowrite32be(val, addr); } +static inline u32 qoriq_read_le(unsigned __iomem *addr) +{ + return ioread32(addr); +} + +static inline void qoriq_write_le(unsigned __iomem *addr, u32 val) +{ + iowrite32(val, addr); +} + irqreturn_t ptp_qoriq_isr(int irq, void *priv); int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, const struct ptp_clock_info caps); -- cgit v1.2.3 From d4e176870bffde373d9688c54aad8f92b3394ba6 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 12 Feb 2019 12:24:01 +0800 Subject: ptp_qoriq: fix register memory map The 1588 timer on eTSEC Ethernet controller uses different register memory map with DPAA Ethernet controller. Now the new ENETC Ethernet controller uses same reigster memory map with DPAA. To support ENETC, let's use register memory map of DPAA/ENETC in default. Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/ptp/ptp_qoriq.c | 11 ++++++----- include/linux/fsl/ptp_qoriq.h | 18 +++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index ed4dc398c57b..42d3654f77f0 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -504,11 +504,12 @@ int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, ptp_qoriq->write = qoriq_write_be; } - if (of_device_is_compatible(node, "fsl,fman-ptp-timer")) { - ptp_qoriq->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET; - ptp_qoriq->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET; - ptp_qoriq->regs.fiper_regs = base + FMAN_FIPER_REGS_OFFSET; - ptp_qoriq->regs.etts_regs = base + FMAN_ETTS_REGS_OFFSET; + /* The eTSEC uses differnt memory map with DPAA/ENETC */ + if (of_device_is_compatible(node, "fsl,etsec-ptp")) { + ptp_qoriq->regs.ctrl_regs = base + ETSEC_CTRL_REGS_OFFSET; + ptp_qoriq->regs.alarm_regs = base + ETSEC_ALARM_REGS_OFFSET; + ptp_qoriq->regs.fiper_regs = base + ETSEC_FIPER_REGS_OFFSET; + ptp_qoriq->regs.etts_regs = base + ETSEC_ETTS_REGS_OFFSET; } else { ptp_qoriq->regs.ctrl_regs = base + CTRL_REGS_OFFSET; ptp_qoriq->regs.alarm_regs = base + ALARM_REGS_OFFSET; diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index 1f8bb6a6a121..f127adb71041 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -58,15 +58,15 @@ struct ptp_qoriq_registers { }; /* Offset definitions for the four register groups */ -#define CTRL_REGS_OFFSET 0x0 -#define ALARM_REGS_OFFSET 0x40 -#define FIPER_REGS_OFFSET 0x80 -#define ETTS_REGS_OFFSET 0xa0 - -#define FMAN_CTRL_REGS_OFFSET 0x80 -#define FMAN_ALARM_REGS_OFFSET 0xb8 -#define FMAN_FIPER_REGS_OFFSET 0xd0 -#define FMAN_ETTS_REGS_OFFSET 0xe0 +#define ETSEC_CTRL_REGS_OFFSET 0x0 +#define ETSEC_ALARM_REGS_OFFSET 0x40 +#define ETSEC_FIPER_REGS_OFFSET 0x80 +#define ETSEC_ETTS_REGS_OFFSET 0xa0 + +#define CTRL_REGS_OFFSET 0x80 +#define ALARM_REGS_OFFSET 0xb8 +#define FIPER_REGS_OFFSET 0xd0 +#define ETTS_REGS_OFFSET 0xe0 /* Bit definitions for the TMR_CTRL register */ -- cgit v1.2.3 From ad6e1be64ae135abae8f7e51c4f2f74f4f4e5420 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 12 Feb 2019 12:24:02 +0800 Subject: ptp: add QorIQ PTP support for ENETC This patch is to add QorIQ PTP support for ENETC. ENETC PTP driver which is a PCI driver for same 1588 timer IP block will reuse QorIQ PTP driver. Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/ptp/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index aeb4a8b2e0af..7fe18636915a 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -43,7 +43,7 @@ config PTP_1588_CLOCK_DTE config PTP_1588_CLOCK_QORIQ tristate "Freescale QorIQ 1588 timer as PTP clock" - depends on GIANFAR || FSL_DPAA_ETH + depends on GIANFAR || FSL_DPAA_ETH || FSL_ENETC || FSL_ENETC_VF depends on PTP_1588_CLOCK default y help -- cgit v1.2.3 From 19971f5ea0ab449818db5016ea1229a654a13a5c Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 12 Feb 2019 12:24:03 +0800 Subject: enetc: add PTP clock driver This patch is to add PTP clock driver for ENETC. The driver reused QorIQ PTP clock driver. Signed-off-by: Yangbo Lu Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/Kconfig | 12 ++ drivers/net/ethernet/freescale/enetc/Makefile | 3 + drivers/net/ethernet/freescale/enetc/enetc_hw.h | 5 +- drivers/net/ethernet/freescale/enetc/enetc_ptp.c | 144 +++++++++++++++++++++++ 4 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_ptp.c (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig index f9dd26fbfc83..8429f5c1d810 100644 --- a/drivers/net/ethernet/freescale/enetc/Kconfig +++ b/drivers/net/ethernet/freescale/enetc/Kconfig @@ -17,3 +17,15 @@ config FSL_ENETC_VF virtual function (VF) devices enabled by the ENETC PF driver. If compiled as module (M), the module name is fsl-enetc-vf. + +config FSL_ENETC_PTP_CLOCK + tristate "ENETC PTP clock driver" + depends on PTP_1588_CLOCK_QORIQ && (FSL_ENETC || FSL_ENETC_VF) + default y + help + This driver adds support for using the ENETC 1588 timer + as a PTP clock. This clock is only useful if your PTP + programs are getting hardware time stamps on the PTP Ethernet + packets using the SO_TIMESTAMPING API. + + If compiled as module (M), the module name is fsl-enetc-ptp. diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile index 9529b01872ca..697660294dbc 100644 --- a/drivers/net/ethernet/freescale/enetc/Makefile +++ b/drivers/net/ethernet/freescale/enetc/Makefile @@ -13,3 +13,6 @@ fsl-enetc-vf-$(CONFIG_FSL_ENETC_VF) += enetc.o enetc_cbdr.o \ enetc_ethtool.o fsl-enetc-vf-objs := enetc_vf.o $(fsl-enetc-vf-y) endif + +obj-$(CONFIG_FSL_ENETC_PTP_CLOCK) += fsl-enetc-ptp.o +fsl-enetc-ptp-$(CONFIG_FSL_ENETC_PTP_CLOCK) += enetc_ptp.o diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h index efa0b1a5ef4f..df8eb8882d92 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h @@ -4,8 +4,9 @@ #include /* ENETC device IDs */ -#define ENETC_DEV_ID_PF 0xe100 -#define ENETC_DEV_ID_VF 0xef00 +#define ENETC_DEV_ID_PF 0xe100 +#define ENETC_DEV_ID_VF 0xef00 +#define ENETC_DEV_ID_PTP 0xee02 /* ENETC register block BAR */ #define ENETC_BAR_REGS 0 diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c new file mode 100644 index 000000000000..dc2f58a7c9e5 --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2019 NXP */ + +#include +#include +#include + +#include "enetc.h" + +static struct ptp_clock_info enetc_ptp_caps = { + .owner = THIS_MODULE, + .name = "ENETC PTP clock", + .max_adj = 512000, + .n_alarm = 0, + .n_ext_ts = 2, + .n_per_out = 0, + .n_pins = 0, + .pps = 1, + .adjfine = ptp_qoriq_adjfine, + .adjtime = ptp_qoriq_adjtime, + .gettime64 = ptp_qoriq_gettime, + .settime64 = ptp_qoriq_settime, + .enable = ptp_qoriq_enable, +}; + +static int enetc_ptp_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct ptp_qoriq *ptp_qoriq; + void __iomem *base; + int err, len, n; + + if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) { + dev_info(&pdev->dev, "device is disabled, skipping\n"); + return -ENODEV; + } + + err = pci_enable_device_mem(pdev); + if (err) { + dev_err(&pdev->dev, "device enable failed\n"); + return err; + } + + /* set up for high or low dma */ + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (err) { + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, + "DMA configuration failed: 0x%x\n", err); + goto err_dma; + } + } + + err = pci_request_mem_regions(pdev, KBUILD_MODNAME); + if (err) { + dev_err(&pdev->dev, "pci_request_regions failed err=%d\n", err); + goto err_pci_mem_reg; + } + + pci_set_master(pdev); + + ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL); + if (!ptp_qoriq) { + err = -ENOMEM; + goto err_alloc_ptp; + } + + len = pci_resource_len(pdev, ENETC_BAR_REGS); + + base = ioremap(pci_resource_start(pdev, ENETC_BAR_REGS), len); + if (!base) { + err = -ENXIO; + dev_err(&pdev->dev, "ioremap() failed\n"); + goto err_ioremap; + } + + /* Allocate 1 interrupt */ + n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX); + if (n != 1) { + err = -EPERM; + goto err_irq; + } + + ptp_qoriq->irq = pci_irq_vector(pdev, 0); + + err = request_irq(ptp_qoriq->irq, ptp_qoriq_isr, 0, DRIVER, ptp_qoriq); + if (err) { + dev_err(&pdev->dev, "request_irq() failed!\n"); + goto err_irq; + } + + ptp_qoriq->dev = &pdev->dev; + + err = ptp_qoriq_init(ptp_qoriq, base, enetc_ptp_caps); + if (err) + goto err_no_clock; + + pci_set_drvdata(pdev, ptp_qoriq); + + return 0; + +err_no_clock: + free_irq(ptp_qoriq->irq, ptp_qoriq); +err_irq: + iounmap(base); +err_ioremap: + kfree(ptp_qoriq); +err_alloc_ptp: + pci_release_mem_regions(pdev); +err_pci_mem_reg: +err_dma: + pci_disable_device(pdev); + + return err; +} + +static void enetc_ptp_remove(struct pci_dev *pdev) +{ + struct ptp_qoriq *ptp_qoriq = pci_get_drvdata(pdev); + + ptp_qoriq_free(ptp_qoriq); + kfree(ptp_qoriq); + + pci_release_mem_regions(pdev); + pci_disable_device(pdev); +} + +static const struct pci_device_id enetc_ptp_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PTP) }, + { 0, } /* End of table. */ +}; +MODULE_DEVICE_TABLE(pci, enetc_ptp_id_table); + +static struct pci_driver enetc_ptp_driver = { + .name = KBUILD_MODNAME, + .id_table = enetc_ptp_id_table, + .probe = enetc_ptp_probe, + .remove = enetc_ptp_remove, +}; +module_pci_driver(enetc_ptp_driver); + +MODULE_DESCRIPTION("ENETC PTP clock driver"); +MODULE_LICENSE("Dual BSD/GPL"); -- cgit v1.2.3 From 74abc07dee613086f9c0ded9e263ddc959a6de04 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Mon, 11 Feb 2019 18:04:17 +0200 Subject: net/mlx4_en: Force CHECKSUM_NONE for short ethernet frames When an ethernet frame is padded to meet the minimum ethernet frame size, the padding octets are not covered by the hardware checksum. Fortunately the padding octets are usually zero's, which don't affect checksum. However, it is not guaranteed. For example, switches might choose to make other use of these octets. This repeatedly causes kernel hardware checksum fault. Prior to the cited commit below, skb checksum was forced to be CHECKSUM_NONE when padding is detected. After it, we need to keep skb->csum updated. However, fixing up CHECKSUM_COMPLETE requires to verify and parse IP headers, it does not worth the effort as the packets are so small that CHECKSUM_COMPLETE has no significant advantage. Future work: when reporting checksum complete is not an option for IP non-TCP/UDP packets, we can actually fallback to report checksum unnecessary, by looking at cqe IPOK bit. Fixes: 88078d98d1bb ("net: pskb_trim_rcsum() and CHECKSUM_COMPLETE are friends") Cc: Eric Dumazet Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 9a0881cb7f51..6c01314e87b0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -617,6 +617,8 @@ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb, } #endif +#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN) + /* We reach this function only after checking that any of * the (IPv4 | IPv6) bits are set in cqe->status. */ @@ -624,9 +626,20 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va, netdev_features_t dev_features) { __wsum hw_checksum = 0; + void *hdr; + + /* CQE csum doesn't cover padding octets in short ethernet + * frames. And the pad field is appended prior to calculating + * and appending the FCS field. + * + * Detecting these padded frames requires to verify and parse + * IP headers, so we simply force all those small frames to skip + * checksum complete. + */ + if (short_frame(skb->len)) + return -EINVAL; - void *hdr = (u8 *)va + sizeof(struct ethhdr); - + hdr = (u8 *)va + sizeof(struct ethhdr); hw_checksum = csum_unfold((__force __sum16)cqe->checksum); if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) && @@ -819,6 +832,11 @@ xdp_drop_no_cnt: skb_record_rx_queue(skb, cq_ring); if (likely(dev->features & NETIF_F_RXCSUM)) { + /* TODO: For IP non TCP/UDP packets when csum complete is + * not an option (not supported or any other reason) we can + * actually check cqe IPOK status bit and report + * CHECKSUM_UNNECESSARY rather than CHECKSUM_NONE + */ if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP | MLX4_CQE_STATUS_UDP)) && (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) && -- cgit v1.2.3 From 84dbea461e490d7bba3706637efd7835eb3c8205 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:16 +0100 Subject: s390/qeth: reduce data length for ARP cache query qeth_l3_query_arp_cache_info() indicates a data length that's much larger than the actual length of its request (ie. the value passed to qeth_get_setassparms_cmd()). The confusion presumably comes from the fact that the cmd _response_ can be quite large - but that's no concern for the initial request IO. Fixing this up allows us to use the generic qeth_send_ipa_cmd() infrastructure. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 3 --- drivers/s390/net/qeth_core_main.c | 13 ++++++------- drivers/s390/net/qeth_core_mpc.h | 5 ----- drivers/s390/net/qeth_l3_main.c | 4 +--- 4 files changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 71d27a804920..f35e0b58ba4e 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -1004,9 +1004,6 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob); struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); int qeth_query_switch_attributes(struct qeth_card *card, struct qeth_switch_info *sw_info); -int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, - int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long), - void *reply_param); unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset); int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, struct sk_buff *skb, struct qeth_hdr *hdr, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6ef0c89370b5..47927613d43c 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2020,12 +2020,12 @@ EXPORT_SYMBOL_GPL(qeth_prepare_control_data); * field 'param' of the structure qeth_reply. */ -int qeth_send_control_data(struct qeth_card *card, int len, - struct qeth_cmd_buffer *iob, - int (*reply_cb)(struct qeth_card *cb_card, - struct qeth_reply *cb_reply, - unsigned long cb_cmd), - void *reply_param) +static int qeth_send_control_data(struct qeth_card *card, int len, + struct qeth_cmd_buffer *iob, + int (*reply_cb)(struct qeth_card *cb_card, + struct qeth_reply *cb_reply, + unsigned long cb_cmd), + void *reply_param) { struct qeth_channel *channel = iob->channel; int rc; @@ -2116,7 +2116,6 @@ time_err: qeth_put_reply(reply); return rc; } -EXPORT_SYMBOL_GPL(qeth_send_control_data); static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index c7fb14a61eed..07a48ee95dba 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -834,15 +834,10 @@ enum qeth_ipa_arp_return_codes { extern const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc); extern const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd); -#define QETH_SETASS_BASE_LEN (IPA_PDU_HEADER_SIZE + \ - sizeof(struct qeth_ipacmd_hdr) + \ - sizeof(struct qeth_ipacmd_setassparms_hdr)) #define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \ sizeof(struct qeth_ipacmd_setadpparms_hdr)) #define QETH_SNMP_SETADP_CMDLENGTH 16 -#define QETH_ARP_DATA_SIZE 3968 -#define QETH_ARP_CMD_LEN (QETH_ARP_DATA_SIZE + 8) /* Helper functions */ #define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \ (cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY)) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index f7d0623999ba..f0b790810ebc 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1696,9 +1696,7 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card, return -ENOMEM; cmd = __ipa_cmd(iob); cmd->data.setassparms.data.query_arp.request_bits = 0x000F; - rc = qeth_send_control_data(card, - QETH_SETASS_BASE_LEN + QETH_ARP_CMD_LEN, - iob, qeth_l3_arp_query_cb, qinfo); + rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_query_cb, qinfo); if (rc) QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n", CARD_DEVID(card), rc); -- cgit v1.2.3 From c21532771e9f965a609d4280bade7139b1452273 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:17 +0100 Subject: s390/qeth: consolidate filling of low-level cmd length fields The code to fill the IPA length fields is duplicated three times across the driver: 1. qeth_send_ipa_cmd() sets IPA_CMD_LENGTH, which matches the defaults in the IPA_PDU_HEADER template. 2. for OSN, qeth_osn_send_ipa_cmd() bypasses this logic and inserts the length passed by the caller. 3. SNMP commands (that can outgrow IPA_CMD_LENGTH) have their own way of setting the length fields, via qeth_send_ipa_snmp_cmd(). Consolidate this into qeth_prepare_ipa_cmd(), which all originators of IPA cmds already call during setup of their cmd. Let qeth_send_ipa_cmd() pull the length from the cmd instead of hard-coding IPA_CMD_LENGTH. For now, the SNMP code still needs to fix-up its length fields manually. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 3 ++- drivers/s390/net/qeth_core_main.c | 43 +++++++++++++++------------------------ drivers/s390/net/qeth_core_mpc.c | 19 ++++------------- drivers/s390/net/qeth_core_mpc.h | 2 -- drivers/s390/net/qeth_l2_main.c | 17 ++++++---------- 5 files changed, 28 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index f35e0b58ba4e..07840f9c0bb3 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -1000,7 +1000,8 @@ void qeth_tx_timeout(struct net_device *); void qeth_prepare_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *); void qeth_release_buffer(struct qeth_channel *, struct qeth_cmd_buffer *); -void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob); +void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, + u16 cmd_length); struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); int qeth_query_switch_attributes(struct qeth_card *card, struct qeth_switch_info *sw_info); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 47927613d43c..5f450df886c6 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2815,14 +2815,20 @@ static void qeth_fill_ipacmd_header(struct qeth_card *card, cmd->hdr.prot_version = prot; } -void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob) +void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, + u16 cmd_length) { + u16 total_length = IPA_PDU_HEADER_SIZE + cmd_length; u8 prot_type = qeth_mpc_select_prot_type(card); memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); + memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &total_length, 2); memcpy(QETH_IPA_CMD_PROT_TYPE(iob->data), &prot_type, 1); + memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &cmd_length, 2); + memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &cmd_length, 2); memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data), &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &cmd_length, 2); } EXPORT_SYMBOL_GPL(qeth_prepare_ipa_cmd); @@ -2833,7 +2839,7 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card, iob = qeth_get_buffer(&card->write); if (iob) { - qeth_prepare_ipa_cmd(card, iob); + qeth_prepare_ipa_cmd(card, iob, sizeof(struct qeth_ipa_cmd)); qeth_fill_ipacmd_header(card, __ipa_cmd(iob), ipacmd, prot); } else { dev_warn(&card->gdev->dev, @@ -2857,11 +2863,12 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, unsigned long), void *reply_param) { + u16 length; int rc; QETH_CARD_TEXT(card, 4, "sendipa"); - rc = qeth_send_control_data(card, IPA_CMD_LENGTH, - iob, reply_cb, reply_param); + memcpy(&length, QETH_IPA_PDU_LEN_TOTAL(iob->data), 2); + rc = qeth_send_control_data(card, length, iob, reply_cb, reply_param); if (rc == -ETIME) { qeth_clear_ipacmd_list(card); qeth_schedule_recovery(card); @@ -4460,27 +4467,6 @@ static int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) return rc; } -static int qeth_send_ipa_snmp_cmd(struct qeth_card *card, - struct qeth_cmd_buffer *iob, int len, - int (*reply_cb)(struct qeth_card *, struct qeth_reply *, - unsigned long), - void *reply_param) -{ - u16 s1, s2; - - QETH_CARD_TEXT(card, 4, "sendsnmp"); - - /* adjust PDU length fields in IPA_PDU_HEADER */ - s1 = (u32) IPA_PDU_HEADER_SIZE + len; - s2 = (u32) len; - memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2); - memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2); - memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2); - memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2); - return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob, - reply_cb, reply_param); -} - static int qeth_snmp_command_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long sdata) { @@ -4586,10 +4572,13 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata) rc = -ENOMEM; goto out; } + + /* for large requests, fix-up the length fields: */ + qeth_prepare_ipa_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len); + cmd = __ipa_cmd(iob); memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len); - rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len, - qeth_snmp_command_cb, (void *)&qinfo); + rc = qeth_send_ipa_cmd(card, iob, qeth_snmp_command_cb, &qinfo); if (rc) QETH_DBF_MESSAGE(2, "SNMP command failed on device %x: (%#x)\n", CARD_DEVID(card), rc); diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c index 16fc51ad0514..7ff221ae0a2e 100644 --- a/drivers/s390/net/qeth_core_mpc.c +++ b/drivers/s390/net/qeth_core_mpc.c @@ -125,24 +125,13 @@ unsigned char DM_ACT[] = { unsigned char IPA_PDU_HEADER[] = { 0x00, 0xe0, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, - 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, - (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) / 256, - (IPA_PDU_HEADER_SIZE+sizeof(struct qeth_ipa_cmd)) % 256, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, - sizeof(struct qeth_ipa_cmd) / 256, - sizeof(struct qeth_ipa_cmd) % 256, - 0x00, - sizeof(struct qeth_ipa_cmd) / 256, - sizeof(struct qeth_ipa_cmd) % 256, - 0x05, - 0x77, 0x77, 0x77, 0x77, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, - sizeof(struct qeth_ipa_cmd) / 256, - sizeof(struct qeth_ipa_cmd) % 256, - 0x00, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, }; struct ipa_rc_msg { diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 07a48ee95dba..1ac88da91a40 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -21,8 +21,6 @@ extern unsigned char IPA_PDU_HEADER[]; #define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer + 0x2c) -#define IPA_CMD_LENGTH (IPA_PDU_HEADER_SIZE + sizeof(struct qeth_ipa_cmd)) - #define QETH_SEQ_NO_LENGTH 4 #define QETH_MPC_TOKEN_LENGTH 4 #define QETH_MCL_LENGTH 4 diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index ef0b5eaf2532..453b3f7f272c 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1124,20 +1124,14 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len, } static int qeth_osn_send_ipa_cmd(struct qeth_card *card, - struct qeth_cmd_buffer *iob, int data_len) + struct qeth_cmd_buffer *iob) { - u16 s1, s2; + u16 length; QETH_CARD_TEXT(card, 4, "osndipa"); - qeth_prepare_ipa_cmd(card, iob); - s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len); - s2 = (u16)data_len; - memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2); - memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2); - memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2); - memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2); - return qeth_osn_send_control_data(card, s1, iob); + memcpy(&length, QETH_IPA_PDU_LEN_TOTAL(iob->data), 2); + return qeth_osn_send_control_data(card, length, iob); } int qeth_osn_assist(struct net_device *dev, void *data, int data_len) @@ -1154,8 +1148,9 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len) if (!qeth_card_hw_is_reachable(card)) return -ENODEV; iob = qeth_wait_for_buffer(&card->write); + qeth_prepare_ipa_cmd(card, iob, (u16) data_len); memcpy(__ipa_cmd(iob), data, data_len); - return qeth_osn_send_ipa_cmd(card, iob, data_len); + return qeth_osn_send_ipa_cmd(card, iob); } EXPORT_SYMBOL(qeth_osn_assist); -- cgit v1.2.3 From 7e83747dc95438c83d27e2ed8dbdc3e21fc88e83 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:18 +0100 Subject: s390/qeth: enable only required csum offload features Current code attempts to enable all advertised HW csum offload features. Future-proof this by enabling only those features that we actually use. Also, the IPv4 header csum feature is only needed for TX on L3 devices. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 5f450df886c6..31720044656a 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -6329,8 +6329,11 @@ static int qeth_send_checksum_on(struct qeth_card *card, int cstype, struct qeth_checksum_cmd chksum_cb; int rc; - if (prot == QETH_PROT_IPV4) + /* some L3 HW requires combined L3+L4 csum offload: */ + if (IS_LAYER3(card) && prot == QETH_PROT_IPV4 && + cstype == IPA_OUTBOUND_CHECKSUM) required_features |= QETH_IPA_CHECKSUM_IP_HDR; + rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_START, 0, &chksum_cb, prot); if (!rc) { @@ -6351,8 +6354,12 @@ static int qeth_send_checksum_on(struct qeth_card *card, int cstype, prot, QETH_CARD_IFNAME(card)); return rc; } + + if (chksum_cb.supported & QETH_IPA_CHECKSUM_LP2LP) + required_features |= QETH_IPA_CHECKSUM_LP2LP; + rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_ENABLE, - chksum_cb.supported, &chksum_cb, + required_features, &chksum_cb, prot); if (!rc) { if ((required_features & chksum_cb.enabled) != -- cgit v1.2.3 From 4386e34fab6c89b7b8dae4a44e3cbed5c16a1c4f Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:19 +0100 Subject: s390/qeth: align csum offload with TSO control logic csum offload and TSO have similar programming requirements. The TSO code was reworked with commit "s390/qeth: enhance TSO control sequence", adjust the csum control flow accordingly. Primarily this means replacing custom helpers with more generic infrastructure. Also, change the LP2LP check so that it warns on TX offload (not RX). This is where reduced csum capability actually matters. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 129 ++++++++++++++------------------------ drivers/s390/net/qeth_core_mpc.h | 7 --- 2 files changed, 47 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 31720044656a..428175e1cb5d 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -6267,66 +6267,33 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev, } EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_link_ksettings); -/* Callback to handle checksum offload command reply from OSA card. - * Verify that required features have been enabled on the card. - * Return error in hdr->return_code as this value is checked by caller. - * - * Always returns zero to indicate no further messages from the OSA card. - */ -static int qeth_ipa_checksum_run_cmd_cb(struct qeth_card *card, - struct qeth_reply *reply, - unsigned long data) +static int qeth_start_csum_cb(struct qeth_card *card, struct qeth_reply *reply, + unsigned long data) { struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; - struct qeth_checksum_cmd *chksum_cb = - (struct qeth_checksum_cmd *)reply->param; + u32 *features = reply->param; - QETH_CARD_TEXT(card, 4, "chkdoccb"); if (qeth_setassparms_inspect_rc(cmd)) return 0; - memset(chksum_cb, 0, sizeof(*chksum_cb)); - if (cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) { - chksum_cb->supported = - cmd->data.setassparms.data.chksum.supported; - QETH_CARD_TEXT_(card, 3, "strt:%x", chksum_cb->supported); - } - if (cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_ENABLE) { - chksum_cb->supported = - cmd->data.setassparms.data.chksum.supported; - chksum_cb->enabled = - cmd->data.setassparms.data.chksum.enabled; - QETH_CARD_TEXT_(card, 3, "supp:%x", chksum_cb->supported); - QETH_CARD_TEXT_(card, 3, "enab:%x", chksum_cb->enabled); - } + *features = cmd->data.setassparms.data.flags_32bit; return 0; } -/* Send command to OSA card and check results. */ -static int qeth_ipa_checksum_run_cmd(struct qeth_card *card, - enum qeth_ipa_funcs ipa_func, - __u16 cmd_code, long data, - struct qeth_checksum_cmd *chksum_cb, - enum qeth_prot_versions prot) +static int qeth_set_csum_off(struct qeth_card *card, enum qeth_ipa_funcs cstype, + enum qeth_prot_versions prot) { - struct qeth_cmd_buffer *iob; - - QETH_CARD_TEXT(card, 4, "chkdocmd"); - iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, - sizeof(__u32), prot); - if (!iob) - return -ENOMEM; - - __ipa_cmd(iob)->data.setassparms.data.flags_32bit = (__u32) data; - return qeth_send_ipa_cmd(card, iob, qeth_ipa_checksum_run_cmd_cb, - chksum_cb); + return qeth_send_simple_setassparms_prot(card, cstype, + IPA_CMD_ASS_STOP, 0, prot); } -static int qeth_send_checksum_on(struct qeth_card *card, int cstype, - enum qeth_prot_versions prot) +static int qeth_set_csum_on(struct qeth_card *card, enum qeth_ipa_funcs cstype, + enum qeth_prot_versions prot) { u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP; - struct qeth_checksum_cmd chksum_cb; + struct qeth_cmd_buffer *iob; + struct qeth_ipa_caps caps; + u32 features; int rc; /* some L3 HW requires combined L3+L4 csum offload: */ @@ -6334,59 +6301,57 @@ static int qeth_send_checksum_on(struct qeth_card *card, int cstype, cstype == IPA_OUTBOUND_CHECKSUM) required_features |= QETH_IPA_CHECKSUM_IP_HDR; - rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_START, 0, - &chksum_cb, prot); - if (!rc) { - if ((required_features & chksum_cb.supported) != - required_features) - rc = -EIO; - else if (!(QETH_IPA_CHECKSUM_LP2LP & chksum_cb.supported) && - cstype == IPA_INBOUND_CHECKSUM) - dev_warn(&card->gdev->dev, - "Hardware checksumming is performed only if %s and its peer use different OSA Express 3 ports\n", - QETH_CARD_IFNAME(card)); - } - if (rc) { - qeth_send_simple_setassparms_prot(card, cstype, - IPA_CMD_ASS_STOP, 0, prot); - dev_warn(&card->gdev->dev, - "Starting HW IPv%d checksumming for %s failed, using SW checksumming\n", - prot, QETH_CARD_IFNAME(card)); + iob = qeth_get_setassparms_cmd(card, cstype, IPA_CMD_ASS_START, 0, + prot); + if (!iob) + return -ENOMEM; + + rc = qeth_send_ipa_cmd(card, iob, qeth_start_csum_cb, &features); + if (rc) return rc; - } - if (chksum_cb.supported & QETH_IPA_CHECKSUM_LP2LP) - required_features |= QETH_IPA_CHECKSUM_LP2LP; + if ((required_features & features) != required_features) { + qeth_set_csum_off(card, cstype, prot); + return -EOPNOTSUPP; + } - rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_ENABLE, - required_features, &chksum_cb, + iob = qeth_get_setassparms_cmd(card, cstype, IPA_CMD_ASS_ENABLE, 4, prot); - if (!rc) { - if ((required_features & chksum_cb.enabled) != - required_features) - rc = -EIO; + if (!iob) { + qeth_set_csum_off(card, cstype, prot); + return -ENOMEM; } + + if (features & QETH_IPA_CHECKSUM_LP2LP) + required_features |= QETH_IPA_CHECKSUM_LP2LP; + __ipa_cmd(iob)->data.setassparms.data.flags_32bit = required_features; + rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_get_caps_cb, &caps); if (rc) { - qeth_send_simple_setassparms_prot(card, cstype, - IPA_CMD_ASS_STOP, 0, prot); - dev_warn(&card->gdev->dev, - "Enabling HW IPv%d checksumming for %s failed, using SW checksumming\n", - prot, QETH_CARD_IFNAME(card)); + qeth_set_csum_off(card, cstype, prot); return rc; } + if (!qeth_ipa_caps_supported(&caps, required_features) || + !qeth_ipa_caps_enabled(&caps, required_features)) { + qeth_set_csum_off(card, cstype, prot); + return -EOPNOTSUPP; + } + dev_info(&card->gdev->dev, "HW Checksumming (%sbound IPv%d) enabled\n", cstype == IPA_INBOUND_CHECKSUM ? "in" : "out", prot); + if (!qeth_ipa_caps_enabled(&caps, QETH_IPA_CHECKSUM_LP2LP) && + cstype == IPA_OUTBOUND_CHECKSUM) + dev_warn(&card->gdev->dev, + "Hardware checksumming is performed only if %s and its peer use different OSA Express 3 ports\n", + QETH_CARD_IFNAME(card)); return 0; } static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype, enum qeth_prot_versions prot) { - int rc = (on) ? qeth_send_checksum_on(card, cstype, prot) - : qeth_send_simple_setassparms_prot(card, cstype, - IPA_CMD_ASS_STOP, 0, - prot); + int rc = (on) ? qeth_set_csum_on(card, cstype, prot) : + qeth_set_csum_off(card, cstype, prot); return rc ? -EIO : 0; } diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 1ac88da91a40..7919a0c8109a 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -417,12 +417,6 @@ enum qeth_ipa_checksum_bits { QETH_IPA_CHECKSUM_LP2LP = 0x0020 }; -/* IPA Assist checksum offload reply layout. */ -struct qeth_checksum_cmd { - __u32 supported; - __u32 enabled; -} __packed; - enum qeth_ipa_large_send_caps { QETH_IPA_LARGE_SEND_TCP = 0x00000001, }; @@ -438,7 +432,6 @@ struct qeth_ipacmd_setassparms { union { __u32 flags_32bit; struct qeth_ipa_caps caps; - struct qeth_checksum_cmd chksum; struct qeth_arp_cache_entry arp_entry; struct qeth_arp_query_data query_arp; struct qeth_tso_start_data tso; -- cgit v1.2.3 From 51581fd07d8b8f5c3ff4444d6a8d2dc130d6cf57 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:20 +0100 Subject: s390/qeth: limit trace to valid data of command request 'len' specifies how much data we send to the HW, don't dump beyond this boundary. As of today this is no big concern - commands are built in full, zeroed pages. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 428175e1cb5d..ae2ea0a0edce 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1991,7 +1991,7 @@ void qeth_prepare_control_data(struct qeth_card *card, int len, card->seqno.pdu_hdr++; memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(iob->data), &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH); - QETH_DBF_HEX(CTRL, 2, iob->data, QETH_DBF_CTRL_LEN); + QETH_DBF_HEX(CTRL, 2, iob->data, min(len, QETH_DBF_CTRL_LEN)); } EXPORT_SYMBOL_GPL(qeth_prepare_control_data); -- cgit v1.2.3 From 0951c6babf49d2f2429cbfbea5cf792d427ecc6a Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:21 +0100 Subject: s390/qeth: simplify reply object handling Current code enqueues & dequeues a reply object from the waiter list in various places. In particular, the dequeue & enqueue in qeth_send_control_data_cb() looks fragile - this can cause qeth_clear_ipacmd_list() to skip the active object. Add some helpers, and boil the logic down by giving qeth_send_control_data() the sole responsibility to add and remove objects. qeth_send_control_data_cb() and qeth_clear_ipacmd_list() will now only notify the reply object to interrupt its wait cycle. This can cause a slight delay in the removal, but that's no concern. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 118 ++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index ae2ea0a0edce..04beb0922b31 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -566,6 +566,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card) if (reply) { refcount_set(&reply->refcnt, 1); atomic_set(&reply->received, 0); + init_waitqueue_head(&reply->wait_q); } return reply; } @@ -581,6 +582,26 @@ static void qeth_put_reply(struct qeth_reply *reply) kfree(reply); } +static void qeth_enqueue_reply(struct qeth_card *card, struct qeth_reply *reply) +{ + spin_lock_irq(&card->lock); + list_add_tail(&reply->list, &card->cmd_waiter_list); + spin_unlock_irq(&card->lock); +} + +static void qeth_dequeue_reply(struct qeth_card *card, struct qeth_reply *reply) +{ + spin_lock_irq(&card->lock); + list_del(&reply->list); + spin_unlock_irq(&card->lock); +} + +static void qeth_notify_reply(struct qeth_reply *reply) +{ + atomic_inc(&reply->received); + wake_up(&reply->wait_q); +} + static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc, struct qeth_card *card) { @@ -657,19 +678,15 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, void qeth_clear_ipacmd_list(struct qeth_card *card) { - struct qeth_reply *reply, *r; + struct qeth_reply *reply; unsigned long flags; QETH_CARD_TEXT(card, 4, "clipalst"); spin_lock_irqsave(&card->lock, flags); - list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) { - qeth_get_reply(reply); + list_for_each_entry(reply, &card->cmd_waiter_list, list) { reply->rc = -EIO; - atomic_inc(&reply->received); - list_del_init(&reply->list); - wake_up(&reply->wait_q); - qeth_put_reply(reply); + qeth_notify_reply(reply); } spin_unlock_irqrestore(&card->lock, flags); } @@ -774,9 +791,10 @@ static void qeth_send_control_data_cb(struct qeth_card *card, struct qeth_cmd_buffer *iob) { struct qeth_ipa_cmd *cmd = NULL; - struct qeth_reply *reply, *r; + struct qeth_reply *reply = NULL; + struct qeth_reply *r; unsigned long flags; - int keep_reply; + int keep_reply = 0; int rc = 0; QETH_CARD_TEXT(card, 4, "sndctlcb"); @@ -808,44 +826,40 @@ static void qeth_send_control_data_cb(struct qeth_card *card, goto out; } + /* match against pending cmd requests */ spin_lock_irqsave(&card->lock, flags); - list_for_each_entry_safe(reply, r, &card->cmd_waiter_list, list) { - if ((reply->seqno == QETH_IDX_COMMAND_SEQNO) || - ((cmd) && (reply->seqno == cmd->hdr.seqno))) { + list_for_each_entry(r, &card->cmd_waiter_list, list) { + if ((r->seqno == QETH_IDX_COMMAND_SEQNO) || + (cmd && (r->seqno == cmd->hdr.seqno))) { + reply = r; + /* take the object outside the lock */ qeth_get_reply(reply); - list_del_init(&reply->list); - spin_unlock_irqrestore(&card->lock, flags); - keep_reply = 0; - if (reply->callback != NULL) { - if (cmd) { - reply->offset = (__u16)((char *)cmd - - (char *)iob->data); - keep_reply = reply->callback(card, - reply, - (unsigned long)cmd); - } else - keep_reply = reply->callback(card, - reply, - (unsigned long)iob); - } - if (cmd) - reply->rc = (u16) cmd->hdr.return_code; - else if (iob->rc) - reply->rc = iob->rc; - if (keep_reply) { - spin_lock_irqsave(&card->lock, flags); - list_add_tail(&reply->list, - &card->cmd_waiter_list); - spin_unlock_irqrestore(&card->lock, flags); - } else { - atomic_inc(&reply->received); - wake_up(&reply->wait_q); - } - qeth_put_reply(reply); - goto out; + break; } } spin_unlock_irqrestore(&card->lock, flags); + + if (!reply) + goto out; + + if (reply->callback) { + if (cmd) { + reply->offset = (u16)((char *)cmd - (char *)iob->data); + keep_reply = reply->callback(card, reply, + (unsigned long)cmd); + } else + keep_reply = reply->callback(card, reply, + (unsigned long)iob); + } + if (cmd) + reply->rc = (u16) cmd->hdr.return_code; + else if (iob->rc) + reply->rc = iob->rc; + + if (!keep_reply) + qeth_notify_reply(reply); + qeth_put_reply(reply); + out: memcpy(&card->seqno.pdu_hdr_ack, QETH_PDU_HEADER_SEQ_NO(iob->data), @@ -2047,8 +2061,6 @@ static int qeth_send_control_data(struct qeth_card *card, int len, reply->callback = reply_cb; reply->param = reply_param; - init_waitqueue_head(&reply->wait_q); - while (atomic_cmpxchg(&channel->irq_pending, 0, 1)) ; if (IS_IPA(iob->data)) { @@ -2062,9 +2074,7 @@ static int qeth_send_control_data(struct qeth_card *card, int len, } qeth_prepare_control_data(card, len, iob); - spin_lock_irq(&card->lock); - list_add_tail(&reply->list, &card->cmd_waiter_list); - spin_unlock_irq(&card->lock); + qeth_enqueue_reply(card, reply); timeout = jiffies + event_timeout; @@ -2077,10 +2087,8 @@ static int qeth_send_control_data(struct qeth_card *card, int len, QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n", CARD_DEVID(card), rc); QETH_CARD_TEXT_(card, 2, " err%d", rc); - spin_lock_irq(&card->lock); - list_del_init(&reply->list); + qeth_dequeue_reply(card, reply); qeth_put_reply(reply); - spin_unlock_irq(&card->lock); qeth_release_buffer(channel, iob); atomic_set(&channel->irq_pending, 0); wake_up(&card->wait_q); @@ -2102,19 +2110,15 @@ static int qeth_send_control_data(struct qeth_card *card, int len, } } + qeth_dequeue_reply(card, reply); rc = reply->rc; qeth_put_reply(reply); return rc; time_err: - reply->rc = -ETIME; - spin_lock_irq(&card->lock); - list_del_init(&reply->list); - spin_unlock_irq(&card->lock); - atomic_inc(&reply->received); - rc = reply->rc; + qeth_dequeue_reply(card, reply); qeth_put_reply(reply); - return rc; + return -ETIME; } static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply, -- cgit v1.2.3 From 54daaca7024d5419dad64db8a3e65f6b38f24b7f Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:22 +0100 Subject: s390/qeth: cancel cmd on early error When sending cmds via qeth_send_control_data(), qeth puts the request on the IO channel and then blocks on the reply object until the response has been received. If the IO completes with error, there will never be a response and we block until the reply-wait hits its timeout. For this case, connect the request buffer to its reply object, so that we can immediately cancel the wait. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 + drivers/s390/net/qeth_core_main.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 07840f9c0bb3..83f710336685 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -595,6 +595,7 @@ struct qeth_channel; struct qeth_cmd_buffer { enum qeth_cmd_buffer_state state; struct qeth_channel *channel; + struct qeth_reply *reply; unsigned char *data; int rc; void (*callback)(struct qeth_card *card, struct qeth_channel *channel, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 04beb0922b31..b1a7a35a086e 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -743,6 +743,10 @@ void qeth_release_buffer(struct qeth_channel *channel, spin_lock_irqsave(&channel->iob_lock, flags); iob->state = BUF_STATE_FREE; iob->callback = qeth_send_control_data_cb; + if (iob->reply) { + qeth_put_reply(iob->reply); + iob->reply = NULL; + } iob->rc = 0; spin_unlock_irqrestore(&channel->iob_lock, flags); wake_up(&channel->wait_q); @@ -756,6 +760,17 @@ static void qeth_release_buffer_cb(struct qeth_card *card, qeth_release_buffer(channel, iob); } +static void qeth_cancel_cmd(struct qeth_cmd_buffer *iob, int rc) +{ + struct qeth_reply *reply = iob->reply; + + if (reply) { + reply->rc = rc; + qeth_notify_reply(reply); + } + qeth_release_buffer(iob->channel, iob); +} + static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel) { struct qeth_cmd_buffer *buffer = NULL; @@ -990,9 +1005,8 @@ static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev, return 0; } -static long qeth_check_irb_error(struct qeth_card *card, - struct ccw_device *cdev, unsigned long intparm, - struct irb *irb) +static int qeth_check_irb_error(struct qeth_card *card, struct ccw_device *cdev, + unsigned long intparm, struct irb *irb) { if (!IS_ERR(irb)) return 0; @@ -1003,7 +1017,7 @@ static long qeth_check_irb_error(struct qeth_card *card, CCW_DEVID(cdev)); QETH_CARD_TEXT(card, 2, "ckirberr"); QETH_CARD_TEXT_(card, 2, " rc%d", -EIO); - break; + return -EIO; case -ETIMEDOUT: dev_warn(&cdev->dev, "A hardware operation timed out" " on the device\n"); @@ -1015,14 +1029,14 @@ static long qeth_check_irb_error(struct qeth_card *card, wake_up(&card->wait_q); } } - break; + return -ETIMEDOUT; default: QETH_DBF_MESSAGE(2, "unknown error %ld on channel %x\n", PTR_ERR(irb), CCW_DEVID(cdev)); QETH_CARD_TEXT(card, 2, "ckirberr"); QETH_CARD_TEXT(card, 2, " rc???"); + return PTR_ERR(irb); } - return PTR_ERR(irb); } static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, @@ -1057,10 +1071,11 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, if (qeth_intparm_is_iob(intparm)) iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm); - if (qeth_check_irb_error(card, cdev, intparm, irb)) { + rc = qeth_check_irb_error(card, cdev, intparm, irb); + if (rc) { /* IO was terminated, free its resources. */ if (iob) - qeth_release_buffer(iob->channel, iob); + qeth_cancel_cmd(iob, rc); atomic_set(&channel->irq_pending, 0); wake_up(&card->wait_q); return; @@ -1116,7 +1131,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm, if (rc) { card->read_or_write_problem = 1; if (iob) - qeth_release_buffer(iob->channel, iob); + qeth_cancel_cmd(iob, rc); qeth_clear_ipacmd_list(card); qeth_schedule_recovery(card); goto out; @@ -2061,6 +2076,10 @@ static int qeth_send_control_data(struct qeth_card *card, int len, reply->callback = reply_cb; reply->param = reply_param; + /* pairs with qeth_release_buffer(): */ + qeth_get_reply(reply); + iob->reply = reply; + while (atomic_cmpxchg(&channel->irq_pending, 0, 1)) ; if (IS_IPA(iob->data)) { -- cgit v1.2.3 From 4b7ae12216948229b065d6bf4776a5681d46330c Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:23 +0100 Subject: s390/qeth: allow cmd callbacks to return errnos Error propagation from cmd callbacks currently works in a way where qeth_send_control_data_cb() picks the raw HW code from the response, and the cmd's originator later translates this into an errno. The callback itself only returns 0 ("done") or 1 ("expect more data"). This is 1. limiting, as the only means for the callback to report an internal error is to invent pseudo HW codes (such as IPA_RC_ENOMEM), that the originator then needs to understand. For non-IPA callbacks, we even provide a separate field in the IO buffer metadata (iob->rc) so the callback can pass back a return value. 2. fragile, as the originator must take care to not translate any errno that is returned by qeth's own IO code paths (eg -ENOMEM). Also, any originator that forgets to translate the HW codes potentially passes garbage back to its caller. For instance, see commit 2aa4867198c2 ("s390/qeth: translate SETVLAN/DELVLAN errors"). Introduce a new model where all HW error translation is done within the callback, and the callback returns > 0, if it expects more data (as before) == 0, on success < 0, with an errno Start off with converting all callbacks to the new model that either a) pass back pseudo HW codes, or b) have a dependency on a specific HW error code. Also convert c) the one callback that uses iob->rc, and d) qeth_setadpparms_change_macaddr_cb() so that it can pass back an error back to qeth_l2_request_initial_mac() even when the cmd itself was successful. The old model remains supported: if the callback returns 0, we still propagate the response's HW error code back to the originator. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 - drivers/s390/net/qeth_core_main.c | 82 +++++++++++++++++++++------------------ drivers/s390/net/qeth_core_mpc.c | 4 +- drivers/s390/net/qeth_core_mpc.h | 1 - drivers/s390/net/qeth_l2_main.c | 2 +- drivers/s390/net/qeth_l3_main.c | 50 ++++++++++++++---------- 6 files changed, 76 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 83f710336685..18696ffb662d 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -597,7 +597,6 @@ struct qeth_cmd_buffer { struct qeth_channel *channel; struct qeth_reply *reply; unsigned char *data; - int rc; void (*callback)(struct qeth_card *card, struct qeth_channel *channel, struct qeth_cmd_buffer *iob); }; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index b1a7a35a086e..cdb65ba99888 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -747,7 +747,6 @@ void qeth_release_buffer(struct qeth_channel *channel, qeth_put_reply(iob->reply); iob->reply = NULL; } - iob->rc = 0; spin_unlock_irqrestore(&channel->iob_lock, flags); wake_up(&channel->wait_q); } @@ -809,7 +808,6 @@ static void qeth_send_control_data_cb(struct qeth_card *card, struct qeth_reply *reply = NULL; struct qeth_reply *r; unsigned long flags; - int keep_reply = 0; int rc = 0; QETH_CARD_TEXT(card, 4, "sndctlcb"); @@ -857,22 +855,27 @@ static void qeth_send_control_data_cb(struct qeth_card *card, if (!reply) goto out; - if (reply->callback) { + if (!reply->callback) { + rc = 0; + } else { if (cmd) { reply->offset = (u16)((char *)cmd - (char *)iob->data); - keep_reply = reply->callback(card, reply, - (unsigned long)cmd); - } else - keep_reply = reply->callback(card, reply, - (unsigned long)iob); + rc = reply->callback(card, reply, (unsigned long)cmd); + } else { + rc = reply->callback(card, reply, (unsigned long)iob); + } } - if (cmd) - reply->rc = (u16) cmd->hdr.return_code; - else if (iob->rc) - reply->rc = iob->rc; - if (!keep_reply) + if (rc <= 0) { + if (cmd) + reply->rc = (u16) cmd->hdr.return_code; + + /* for callbacks with proper errnos: */ + if (rc < 0) + reply->rc = rc; qeth_notify_reply(reply); + } + qeth_put_reply(reply); out: @@ -1293,7 +1296,6 @@ static int qeth_setup_channel(struct qeth_channel *channel, bool alloc_buffers) channel->iob[cnt].state = BUF_STATE_FREE; channel->iob[cnt].channel = channel; channel->iob[cnt].callback = qeth_send_control_data_cb; - channel->iob[cnt].rc = 0; } if (cnt < QETH_CMD_BUFFER_NO) { qeth_clean_channel(channel); @@ -2343,9 +2345,8 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply, QETH_DBF_TEXT(SETUP, 2, "olmlimit"); dev_err(&card->gdev->dev, "A connection could not be " "established because of an OLM limit\n"); - iob->rc = -EMLINK; + return -EMLINK; } - QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); return 0; } @@ -2900,9 +2901,19 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, } EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd); +static int qeth_send_startlan_cb(struct qeth_card *card, + struct qeth_reply *reply, unsigned long data) +{ + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; + + if (cmd->hdr.return_code == IPA_RC_LAN_OFFLINE) + return -ENETDOWN; + + return (cmd->hdr.return_code) ? -EIO : 0; +} + static int qeth_send_startlan(struct qeth_card *card) { - int rc; struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(SETUP, 2, "strtlan"); @@ -2910,8 +2921,7 @@ static int qeth_send_startlan(struct qeth_card *card) iob = qeth_get_ipacmd_buffer(card, IPA_CMD_STARTLAN, 0); if (!iob) return -ENOMEM; - rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); - return rc; + return qeth_send_ipa_cmd(card, iob, qeth_send_startlan_cb, NULL); } static int qeth_setadpparms_inspect_rc(struct qeth_ipa_cmd *cmd) @@ -4238,12 +4248,15 @@ static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card, QETH_CARD_TEXT(card, 4, "chgmaccb"); if (qeth_setadpparms_inspect_rc(cmd)) - return 0; + return -EIO; adp_cmd = &cmd->data.setadapterparms; + if (!is_valid_ether_addr(adp_cmd->data.change_addr.addr)) + return -EADDRNOTAVAIL; + if (IS_LAYER2(card) && IS_OSD(card) && !IS_VM_NIC(card) && !(adp_cmd->hdr.flags & QETH_SETADP_FLAGS_VIRTUAL_MAC)) - return 0; + return -EADDRNOTAVAIL; ether_addr_copy(card->dev->dev_addr, adp_cmd->data.change_addr.addr); return 0; @@ -4507,13 +4520,13 @@ static int qeth_snmp_command_cb(struct qeth_card *card, if (cmd->hdr.return_code) { QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code); - return 0; + return -EIO; } if (cmd->data.setadapterparms.hdr.return_code) { cmd->hdr.return_code = cmd->data.setadapterparms.hdr.return_code; QETH_CARD_TEXT_(card, 4, "scer2%x", cmd->hdr.return_code); - return 0; + return -EIO; } data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data)); if (cmd->data.setadapterparms.hdr.seq_no == 1) { @@ -4528,9 +4541,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card, /* check if there is enough room in userspace */ if ((qinfo->udata_len - qinfo->udata_offset) < data_len) { - QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOMEM); - cmd->hdr.return_code = IPA_RC_ENOMEM; - return 0; + QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOSPC); + return -ENOSPC; } QETH_CARD_TEXT_(card, 4, "snore%i", cmd->data.setadapterparms.hdr.used_total); @@ -4625,16 +4637,14 @@ static int qeth_setadpparms_query_oat_cb(struct qeth_card *card, QETH_CARD_TEXT(card, 3, "qoatcb"); if (qeth_setadpparms_inspect_rc(cmd)) - return 0; + return -EIO; priv = (struct qeth_qoat_priv *)reply->param; resdatalen = cmd->data.setadapterparms.hdr.cmdlength; resdata = (char *)data + 28; - if (resdatalen > (priv->buffer_len - priv->response_len)) { - cmd->hdr.return_code = IPA_RC_FFFF; - return 0; - } + if (resdatalen > (priv->buffer_len - priv->response_len)) + return -ENOSPC; memcpy((priv->buffer + priv->response_len), resdata, resdatalen); @@ -4707,9 +4717,7 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata) if (copy_to_user(udata, &oat_data, sizeof(struct qeth_query_oat_data))) rc = -EFAULT; - } else - if (rc == IPA_RC_FFFF) - rc = -EFAULT; + } out_free: vfree(priv.buffer); @@ -5128,12 +5136,10 @@ retriable: rc = qeth_send_startlan(card); if (rc) { QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); - if (rc == IPA_RC_LAN_OFFLINE) { - dev_warn(&card->gdev->dev, - "The LAN is offline\n"); + if (rc == -ENETDOWN) { + dev_warn(&card->gdev->dev, "The LAN is offline\n"); *carrier_ok = false; } else { - rc = -ENODEV; goto out; } } else { diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c index 7ff221ae0a2e..e3f4866c158e 100644 --- a/drivers/s390/net/qeth_core_mpc.c +++ b/drivers/s390/net/qeth_core_mpc.c @@ -201,12 +201,10 @@ static const struct ipa_rc_msg qeth_ipa_rc_msg[] = { {IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"}, {IPA_RC_VEPA_TO_VEB_TRANSITION, "Adj. switch disabled port mode RR"}, {IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"}, - {IPA_RC_ENOMEM, "Memory problem"}, + /* default for qeth_get_ipa_msg(): */ {IPA_RC_FFFF, "Unknown Error"} }; - - const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc) { int x; diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 7919a0c8109a..4b1690380ebe 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -229,7 +229,6 @@ enum qeth_ipa_return_codes { IPA_RC_LAN_OFFLINE = 0xe080, IPA_RC_VEPA_TO_VEB_TRANSITION = 0xe090, IPA_RC_INVALID_IP_VERSION2 = 0xf001, - IPA_RC_ENOMEM = 0xfffe, IPA_RC_FFFF = 0xffff }; /* for VNIC Characteristics */ diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 453b3f7f272c..6d9eb54ea3b0 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -393,7 +393,7 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) if (!IS_OSN(card)) { rc = qeth_setadpparms_change_macaddr(card); - if (!rc && is_valid_ether_addr(card->dev->dev_addr)) + if (!rc) goto out; QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n", CARD_DEVID(card), rc); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index f0b790810ebc..852bfd5cc3e9 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -253,8 +253,7 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *tmp_addr) } else rc = qeth_l3_register_addr_entry(card, addr); - if (!rc || (rc == IPA_RC_DUPLICATE_IP_ADDRESS) || - (rc == IPA_RC_LAN_OFFLINE)) { + if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) { addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING; if (addr->ref_counter < 1) { qeth_l3_deregister_addr_entry(card, addr); @@ -338,10 +337,28 @@ static void qeth_l3_recover_ip(struct qeth_card *card) } +static int qeth_l3_setdelip_cb(struct qeth_card *card, struct qeth_reply *reply, + unsigned long data) +{ + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; + + switch (cmd->hdr.return_code) { + case IPA_RC_SUCCESS: + return 0; + case IPA_RC_DUPLICATE_IP_ADDRESS: + return -EADDRINUSE; + case IPA_RC_MC_ADDR_NOT_FOUND: + return -ENOENT; + case IPA_RC_LAN_OFFLINE: + return -ENETDOWN; + default: + return -EIO; + } +} + static int qeth_l3_send_setdelmc(struct qeth_card *card, struct qeth_ipaddr *addr, int ipacmd) { - int rc; struct qeth_cmd_buffer *iob; struct qeth_ipa_cmd *cmd; @@ -358,9 +375,7 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card, else memcpy(&cmd->data.setdelipm.ip4, &addr->u.a4.addr, 4); - rc = qeth_send_ipa_cmd(card, iob, NULL, NULL); - - return rc; + return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL); } static void qeth_l3_fill_netmask(u8 *netmask, unsigned int len) @@ -422,7 +437,7 @@ static int qeth_l3_send_setdelip(struct qeth_card *card, cmd->data.setdelip4.flags = flags; } - return qeth_send_ipa_cmd(card, iob, NULL, NULL); + return qeth_send_ipa_cmd(card, iob, qeth_l3_setdelip_cb, NULL); } static int qeth_l3_send_setrouting(struct qeth_card *card, @@ -1481,14 +1496,14 @@ static void qeth_l3_set_rx_mode(struct net_device *dev) switch (addr->disp_flag) { case QETH_DISP_ADDR_DELETE: rc = qeth_l3_deregister_addr_entry(card, addr); - if (!rc || rc == IPA_RC_MC_ADDR_NOT_FOUND) { + if (!rc || rc == -ENOENT) { hash_del(&addr->hnode); kfree(addr); } break; case QETH_DISP_ADDR_ADD: rc = qeth_l3_register_addr_entry(card, addr); - if (rc && rc != IPA_RC_LAN_OFFLINE) { + if (rc && rc != -ENETDOWN) { hash_del(&addr->hnode); kfree(addr); break; @@ -1599,7 +1614,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, struct qeth_ipa_cmd *cmd; struct qeth_arp_query_data *qdata; struct qeth_arp_query_info *qinfo; - int i; int e; int entrybytes_done; int stripped_bytes; @@ -1613,13 +1627,13 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, if (cmd->hdr.return_code) { QETH_CARD_TEXT(card, 4, "arpcberr"); QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code); - return 0; + return qeth_l3_arp_makerc(cmd->hdr.return_code); } if (cmd->data.setassparms.hdr.return_code) { cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; QETH_CARD_TEXT(card, 4, "setaperr"); QETH_CARD_TEXT_(card, 4, "%i", cmd->hdr.return_code); - return 0; + return qeth_l3_arp_makerc(cmd->hdr.return_code); } qdata = &cmd->data.setassparms.data.query_arp; QETH_CARD_TEXT_(card, 4, "anoen%i", qdata->no_entries); @@ -1646,9 +1660,9 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, break; if ((qinfo->udata_len - qinfo->udata_offset) < esize) { - QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM); - cmd->hdr.return_code = IPA_RC_ENOMEM; - goto out_error; + QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOSPC); + memset(qinfo->udata, 0, 4); + return -ENOSPC; } memcpy(qinfo->udata + qinfo->udata_offset, @@ -1671,10 +1685,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, memcpy(qinfo->udata + QETH_QARP_MASK_OFFSET, &qdata->reply_bits, 2); QETH_CARD_TEXT_(card, 4, "rc%i", 0); return 0; -out_error: - i = 0; - memcpy(qinfo->udata, &i, 4); - return 0; } static int qeth_l3_query_arp_cache_info(struct qeth_card *card, @@ -1700,7 +1710,7 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card, if (rc) QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n", CARD_DEVID(card), rc); - return qeth_l3_arp_makerc(rc); + return rc; } static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) -- cgit v1.2.3 From 1709ff8d8603dcfe977ed58557f552b46695d2a3 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:24 +0100 Subject: s390/qeth: convert bridgeport callbacks By letting the callbacks deal with error translation, we no longer need to pass the raw error codes back to the originator. This allows us to slim down the callback's private data, and nicely simplifies the code. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 94 ++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 6d9eb54ea3b0..955fb24af418 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1407,8 +1407,6 @@ static void qeth_bridge_host_event(struct qeth_card *card, /* SETBRIDGEPORT support; sending commands */ struct _qeth_sbp_cbctl { - u16 ipa_rc; - u16 cmd_rc; union { u32 supported; struct { @@ -1418,23 +1416,21 @@ struct _qeth_sbp_cbctl { } data; }; -/** - * qeth_bridgeport_makerc() - derive "traditional" error from hardware codes. - * @card: qeth_card structure pointer, for debug messages. - * @cbctl: state structure with hardware return codes. - * @setcmd: IPA command code - * - * Returns negative errno-compatible error indication or 0 on success. - */ static int qeth_bridgeport_makerc(struct qeth_card *card, - struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd) + struct qeth_ipa_cmd *cmd) { + struct qeth_ipacmd_setbridgeport *sbp = &cmd->data.sbp; + enum qeth_ipa_sbp_cmd setcmd = sbp->hdr.command_code; + u16 ipa_rc = cmd->hdr.return_code; + u16 sbp_rc = sbp->hdr.return_code; int rc; - int is_iqd = (card->info.type == QETH_CARD_TYPE_IQD); - if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) || - (!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc))) - switch (cbctl->cmd_rc) { + if (ipa_rc == IPA_RC_SUCCESS && sbp_rc == IPA_RC_SUCCESS) + return 0; + + if ((IS_IQD(card) && ipa_rc == IPA_RC_SUCCESS) || + (!IS_IQD(card) && ipa_rc == sbp_rc)) { + switch (sbp_rc) { case IPA_RC_SUCCESS: rc = 0; break; @@ -1498,8 +1494,8 @@ static int qeth_bridgeport_makerc(struct qeth_card *card, default: rc = -EIO; } - else - switch (cbctl->ipa_rc) { + } else { + switch (ipa_rc) { case IPA_RC_NOTSUPP: rc = -EOPNOTSUPP; break; @@ -1509,10 +1505,11 @@ static int qeth_bridgeport_makerc(struct qeth_card *card, default: rc = -EIO; } + } if (rc) { - QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc); - QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc); + QETH_CARD_TEXT_(card, 2, "SBPi%04x", ipa_rc); + QETH_CARD_TEXT_(card, 2, "SBPc%04x", sbp_rc); } return rc; } @@ -1544,15 +1541,15 @@ static int qeth_bridgeport_query_support_cb(struct qeth_card *card, { struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param; + int rc; + QETH_CARD_TEXT(card, 2, "brqsupcb"); - cbctl->ipa_rc = cmd->hdr.return_code; - cbctl->cmd_rc = cmd->data.sbp.hdr.return_code; - if ((cbctl->ipa_rc == 0) && (cbctl->cmd_rc == 0)) { - cbctl->data.supported = - cmd->data.sbp.data.query_cmds_supp.supported_cmds; - } else { - cbctl->data.supported = 0; - } + rc = qeth_bridgeport_makerc(card, cmd); + if (rc) + return rc; + + cbctl->data.supported = + cmd->data.sbp.data.query_cmds_supp.supported_cmds; return 0; } @@ -1573,12 +1570,11 @@ static void qeth_bridgeport_query_support(struct qeth_card *card) sizeof(struct qeth_sbp_query_cmds_supp)); if (!iob) return; + if (qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_support_cb, - (void *)&cbctl) || - qeth_bridgeport_makerc(card, &cbctl, - IPA_SBP_QUERY_COMMANDS_SUPPORTED)) { - /* non-zero makerc signifies failure, and produce messages */ + &cbctl)) { card->options.sbp.role = QETH_SBP_ROLE_NONE; + card->options.sbp.supported_funcs = 0; return; } card->options.sbp.supported_funcs = cbctl.data.supported; @@ -1590,16 +1586,16 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card, struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; struct qeth_sbp_query_ports *qports = &cmd->data.sbp.data.query_ports; struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param; + int rc; QETH_CARD_TEXT(card, 2, "brqprtcb"); - cbctl->ipa_rc = cmd->hdr.return_code; - cbctl->cmd_rc = cmd->data.sbp.hdr.return_code; - if ((cbctl->ipa_rc != 0) || (cbctl->cmd_rc != 0)) - return 0; + rc = qeth_bridgeport_makerc(card, cmd); + if (rc) + return rc; + if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) { - cbctl->cmd_rc = 0xffff; QETH_CARD_TEXT_(card, 2, "SBPs%04x", qports->entry_length); - return 0; + return -EINVAL; } /* first entry contains the state of the local port */ if (qports->num_entries > 0) { @@ -1624,7 +1620,6 @@ static int qeth_bridgeport_query_ports_cb(struct qeth_card *card, int qeth_bridgeport_query_ports(struct qeth_card *card, enum qeth_sbp_roles *role, enum qeth_sbp_states *state) { - int rc = 0; struct qeth_cmd_buffer *iob; struct _qeth_sbp_cbctl cbctl = { .data = { @@ -1641,22 +1636,18 @@ int qeth_bridgeport_query_ports(struct qeth_card *card, iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_BRIDGE_PORTS, 0); if (!iob) return -ENOMEM; - rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb, - (void *)&cbctl); - if (rc < 0) - return rc; - return qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS); + + return qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb, + &cbctl); } static int qeth_bridgeport_set_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data; - struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param; + QETH_CARD_TEXT(card, 2, "brsetrcb"); - cbctl->ipa_rc = cmd->hdr.return_code; - cbctl->cmd_rc = cmd->data.sbp.hdr.return_code; - return 0; + return qeth_bridgeport_makerc(card, cmd); } /** @@ -1668,10 +1659,8 @@ static int qeth_bridgeport_set_cb(struct qeth_card *card, */ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role) { - int rc = 0; int cmdlength; struct qeth_cmd_buffer *iob; - struct _qeth_sbp_cbctl cbctl; enum qeth_ipa_sbp_cmd setcmd; QETH_CARD_TEXT(card, 2, "brsetrol"); @@ -1696,11 +1685,8 @@ int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role) iob = qeth_sbp_build_cmd(card, setcmd, cmdlength); if (!iob) return -ENOMEM; - rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb, - (void *)&cbctl); - if (rc < 0) - return rc; - return qeth_bridgeport_makerc(card, &cbctl, setcmd); + + return qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb, NULL); } /** -- cgit v1.2.3 From 742d4d40831d3d2bd2dff0bd2c9488b944231cb2 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Tue, 12 Feb 2019 18:33:25 +0100 Subject: s390/qeth: convert remaining legacy cmd callbacks This calls the existing errno translation helpers from the callbacks, adding trivial wrappers where necessary. For cmds that have no sophisticated errno translation, default to -EIO. For IPA cmds with no callback, fall back to a minimal default. This is currently being used by qeth_l3_send_setrouting(). Thus having all converted all callbacks, remove the legacy path in qeth_send_control_data_cb(). Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 113 +++++++++++++++++++------------------- drivers/s390/net/qeth_l2_main.c | 37 ++++++------- drivers/s390/net/qeth_l3_main.c | 74 ++++++++++++++++--------- 3 files changed, 121 insertions(+), 103 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index cdb65ba99888..5ca934775c42 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -867,12 +867,7 @@ static void qeth_send_control_data_cb(struct qeth_card *card, } if (rc <= 0) { - if (cmd) - reply->rc = (u16) cmd->hdr.return_code; - - /* for callbacks with proper errnos: */ - if (rc < 0) - reply->rc = rc; + reply->rc = rc; qeth_notify_reply(reply); } @@ -2039,15 +2034,13 @@ EXPORT_SYMBOL_GPL(qeth_prepare_control_data); * for the IPA commands. * @reply_param: private pointer passed to the callback * - * Returns the value of the `return_code' field of the response - * block returned from the hardware, or other error indication. - * Value of zero indicates successful execution of the command. - * * Callback function gets called one or more times, with cb_cmd * pointing to the response returned by the hardware. Callback - * function must return non-zero if more reply blocks are expected, - * and zero if the last or only reply block is received. Callback - * function can get the value of the reply_param pointer from the + * function must return + * > 0 if more reply blocks are expected, + * 0 if the last or only reply block is received, and + * < 0 on error. + * Callback function can get the value of the reply_param pointer from the * field 'param' of the structure qeth_reply. */ @@ -2876,6 +2869,14 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card, } EXPORT_SYMBOL_GPL(qeth_get_ipacmd_buffer); +static int qeth_send_ipa_cmd_cb(struct qeth_card *card, + struct qeth_reply *reply, unsigned long data) +{ + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; + + return (cmd->hdr.return_code) ? -EIO : 0; +} + /** * qeth_send_ipa_cmd() - send an IPA command * @@ -2891,6 +2892,9 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, int rc; QETH_CARD_TEXT(card, 4, "sendipa"); + + if (reply_cb == NULL) + reply_cb = qeth_send_ipa_cmd_cb; memcpy(&length, QETH_IPA_PDU_LEN_TOTAL(iob->data), 2); rc = qeth_send_control_data(card, length, iob, reply_cb, reply_param); if (rc == -ETIME) { @@ -2939,7 +2943,7 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card, QETH_CARD_TEXT(card, 3, "quyadpcb"); if (qeth_setadpparms_inspect_rc(cmd)) - return 0; + return -EIO; if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) { card->info.link_type = @@ -2994,19 +2998,18 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, cmd = (struct qeth_ipa_cmd *) data; switch (cmd->hdr.return_code) { + case IPA_RC_SUCCESS: + break; case IPA_RC_NOTSUPP: case IPA_RC_L2_UNSUPPORTED_CMD: QETH_DBF_TEXT(SETUP, 2, "ipaunsup"); card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS; card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS; - return 0; + return -EOPNOTSUPP; default: - if (cmd->hdr.return_code) { - QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n", - CARD_DEVID(card), - cmd->hdr.return_code); - return 0; - } + QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n", + CARD_DEVID(card), cmd->hdr.return_code); + return -EIO; } if (cmd->hdr.prot_version == QETH_PROT_IPV4) { @@ -3044,7 +3047,7 @@ static int qeth_query_switch_attributes_cb(struct qeth_card *card, QETH_CARD_TEXT(card, 2, "qswiatcb"); if (qeth_setadpparms_inspect_rc(cmd)) - return 0; + return -EIO; sw_info = (struct qeth_switch_info *)reply->param; attrs = &cmd->data.setadapterparms.data.query_switch_attributes; @@ -3076,15 +3079,15 @@ int qeth_query_switch_attributes(struct qeth_card *card, static int qeth_query_setdiagass_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; - __u16 rc; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; + u16 rc = cmd->hdr.return_code; - cmd = (struct qeth_ipa_cmd *)data; - rc = cmd->hdr.return_code; - if (rc) + if (rc) { QETH_CARD_TEXT_(card, 2, "diagq:%x", rc); - else - card->info.diagass_support = cmd->data.diagass.ext; + return -EIO; + } + + card->info.diagass_support = cmd->data.diagass.ext; return 0; } @@ -3131,13 +3134,13 @@ static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid) static int qeth_hw_trap_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; - __u16 rc; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; + u16 rc = cmd->hdr.return_code; - cmd = (struct qeth_ipa_cmd *)data; - rc = cmd->hdr.return_code; - if (rc) + if (rc) { QETH_CARD_TEXT_(card, 2, "trapc:%x", rc); + return -EIO; + } return 0; } @@ -4196,7 +4199,7 @@ static int qeth_setadp_promisc_mode_cb(struct qeth_card *card, setparms->data.mode = SET_PROMISC_MODE_OFF; } card->info.promisc_mode = setparms->data.mode; - return 0; + return (cmd->hdr.return_code) ? -EIO : 0; } void qeth_setadp_promisc_mode(struct qeth_card *card) @@ -4295,7 +4298,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, QETH_CARD_TEXT(card, 4, "setaccb"); if (cmd->hdr.return_code) - return 0; + return -EIO; qeth_setadpparms_inspect_rc(cmd); access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl; @@ -4369,7 +4372,7 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, card->options.isolation = card->options.prev_isolation; break; } - return 0; + return (cmd->hdr.return_code) ? -EIO : 0; } static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card, @@ -4734,7 +4737,7 @@ static int qeth_query_card_info_cb(struct qeth_card *card, QETH_CARD_TEXT(card, 2, "qcrdincb"); if (qeth_setadpparms_inspect_rc(cmd)) - return 0; + return -EIO; card_info = &cmd->data.setadapterparms.data.card_info; carrier_info->card_type = card_info->card_type; @@ -5409,7 +5412,7 @@ static int qeth_setassparms_get_caps_cb(struct qeth_card *card, struct qeth_ipa_caps *caps = reply->param; if (qeth_setassparms_inspect_rc(cmd)) - return 0; + return -EIO; caps->supported = cmd->data.setassparms.data.caps.supported; caps->enabled = cmd->data.setassparms.data.caps.enabled; @@ -5419,18 +5422,18 @@ static int qeth_setassparms_get_caps_cb(struct qeth_card *card, int qeth_setassparms_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; QETH_CARD_TEXT(card, 4, "defadpcb"); - cmd = (struct qeth_ipa_cmd *) data; - if (cmd->hdr.return_code == 0) { - cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; - if (cmd->hdr.prot_version == QETH_PROT_IPV4) - card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; - if (cmd->hdr.prot_version == QETH_PROT_IPV6) - card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; - } + if (cmd->hdr.return_code) + return -EIO; + + cmd->hdr.return_code = cmd->data.setassparms.hdr.return_code; + if (cmd->hdr.prot_version == QETH_PROT_IPV4) + card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; + if (cmd->hdr.prot_version == QETH_PROT_IPV6) + card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; return 0; } EXPORT_SYMBOL_GPL(qeth_setassparms_cb); @@ -6303,7 +6306,7 @@ static int qeth_start_csum_cb(struct qeth_card *card, struct qeth_reply *reply, u32 *features = reply->param; if (qeth_setassparms_inspect_rc(cmd)) - return 0; + return -EIO; *features = cmd->data.setassparms.data.flags_32bit; return 0; @@ -6379,9 +6382,8 @@ static int qeth_set_csum_on(struct qeth_card *card, enum qeth_ipa_funcs cstype, static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype, enum qeth_prot_versions prot) { - int rc = (on) ? qeth_set_csum_on(card, cstype, prot) : - qeth_set_csum_off(card, cstype, prot); - return rc ? -EIO : 0; + return on ? qeth_set_csum_on(card, cstype, prot) : + qeth_set_csum_off(card, cstype, prot); } static int qeth_start_tso_cb(struct qeth_card *card, struct qeth_reply *reply, @@ -6391,7 +6393,7 @@ static int qeth_start_tso_cb(struct qeth_card *card, struct qeth_reply *reply, struct qeth_tso_start_data *tso_data = reply->param; if (qeth_setassparms_inspect_rc(cmd)) - return 0; + return -EIO; tso_data->mss = cmd->data.setassparms.data.tso.mss; tso_data->supported = cmd->data.setassparms.data.tso.supported; @@ -6457,10 +6459,7 @@ static int qeth_set_tso_on(struct qeth_card *card, static int qeth_set_ipa_tso(struct qeth_card *card, bool on, enum qeth_prot_versions prot) { - int rc = on ? qeth_set_tso_on(card, prot) : - qeth_set_tso_off(card, prot); - - return rc ? -EIO : 0; + return on ? qeth_set_tso_on(card, prot) : qeth_set_tso_off(card, prot); } static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 955fb24af418..c566139da43d 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -35,7 +35,7 @@ static void qeth_l2_vnicc_init(struct qeth_card *card); static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc, u32 *timeout); -static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode) +static int qeth_l2_setdelmac_makerc(struct qeth_card *card, u16 retcode) { int rc; @@ -62,9 +62,6 @@ static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode) case IPA_RC_L2_MAC_NOT_FOUND: rc = -ENOENT; break; - case -ENOMEM: - rc = -ENOMEM; - break; default: rc = -EIO; break; @@ -72,6 +69,15 @@ static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode) return rc; } +static int qeth_l2_send_setdelmac_cb(struct qeth_card *card, + struct qeth_reply *reply, + unsigned long data) +{ + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; + + return qeth_l2_setdelmac_makerc(card, cmd->hdr.return_code); +} + static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, enum qeth_ipa_cmds ipacmd) { @@ -85,8 +91,7 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac, cmd = __ipa_cmd(iob); cmd->data.setdelmac.mac_length = ETH_ALEN; ether_addr_copy(cmd->data.setdelmac.mac, mac); - return qeth_setdelmac_makerc(card, qeth_send_ipa_cmd(card, iob, - NULL, NULL)); + return qeth_send_ipa_cmd(card, iob, qeth_l2_send_setdelmac_cb, NULL); } static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) @@ -205,7 +210,7 @@ static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } } -static int qeth_setdelvlan_makerc(struct qeth_card *card, int retcode) +static int qeth_l2_setdelvlan_makerc(struct qeth_card *card, u16 retcode) { if (retcode) QETH_CARD_TEXT_(card, 2, "err%04x", retcode); @@ -221,8 +226,6 @@ static int qeth_setdelvlan_makerc(struct qeth_card *card, int retcode) return -ENOENT; case IPA_RC_L2_VLAN_ID_NOT_ALLOWED: return -EPERM; - case -ENOMEM: - return -ENOMEM; default: return -EIO; } @@ -240,9 +243,8 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card, cmd->data.setdelvlan.vlan_id, CARD_DEVID(card), cmd->hdr.return_code); QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command); - QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code); } - return 0; + return qeth_l2_setdelvlan_makerc(card, cmd->hdr.return_code); } static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, @@ -257,8 +259,7 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, return -ENOMEM; cmd = __ipa_cmd(iob); cmd->data.setdelvlan.vlan_id = i; - return qeth_setdelvlan_makerc(card, qeth_send_ipa_cmd(card, iob, - qeth_l2_send_setdelvlan_cb, NULL)); + return qeth_send_ipa_cmd(card, iob, qeth_l2_send_setdelvlan_cb, NULL); } static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, @@ -1790,7 +1791,7 @@ static bool qeth_bridgeport_is_in_use(struct qeth_card *card) /* VNIC Characteristics support */ /* handle VNICC IPA command return codes; convert to error codes */ -static int qeth_l2_vnicc_makerc(struct qeth_card *card, int ipa_rc) +static int qeth_l2_vnicc_makerc(struct qeth_card *card, u16 ipa_rc) { int rc; @@ -1848,7 +1849,7 @@ static int qeth_l2_vnicc_request_cb(struct qeth_card *card, QETH_CARD_TEXT(card, 2, "vniccrcb"); if (cmd->hdr.return_code) - return 0; + return qeth_l2_vnicc_makerc(card, cmd->hdr.return_code); /* return results to caller */ card->options.vnicc.sup_chars = rep->hdr.sup; card->options.vnicc.cur_chars = rep->hdr.cur; @@ -1869,7 +1870,6 @@ static int qeth_l2_vnicc_request(struct qeth_card *card, struct qeth_ipacmd_vnicc *req; struct qeth_cmd_buffer *iob; struct qeth_ipa_cmd *cmd; - int rc; QETH_CARD_TEXT(card, 2, "vniccreq"); @@ -1912,10 +1912,7 @@ static int qeth_l2_vnicc_request(struct qeth_card *card, } /* send request */ - rc = qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, - (void *) cbctl); - - return qeth_l2_vnicc_makerc(card, rc); + return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, cbctl); } /* VNICC query VNIC characteristics request */ diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 852bfd5cc3e9..8eb24c7f2750 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -957,12 +957,13 @@ static int qeth_l3_start_ipassists(struct qeth_card *card) static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; - cmd = (struct qeth_ipa_cmd *) data; - if (cmd->hdr.return_code == 0) - ether_addr_copy(card->dev->dev_addr, - cmd->data.create_destroy_addr.unique_id); + if (cmd->hdr.return_code) + return -EIO; + + ether_addr_copy(card->dev->dev_addr, + cmd->data.create_destroy_addr.unique_id); return 0; } @@ -990,19 +991,18 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card) static int qeth_l3_get_unique_id_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct qeth_ipa_cmd *cmd; + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; - cmd = (struct qeth_ipa_cmd *) data; - if (cmd->hdr.return_code == 0) + if (cmd->hdr.return_code == 0) { card->info.unique_id = *((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]); - else { - card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED | - UNIQUE_ID_NOT_BY_CARD; - dev_warn(&card->gdev->dev, "The network adapter failed to " - "generate a unique ID\n"); + return 0; } - return 0; + + card->info.unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED | + UNIQUE_ID_NOT_BY_CARD; + dev_warn(&card->gdev->dev, "The network adapter failed to generate a unique ID\n"); + return -EIO; } static int qeth_l3_get_unique_id(struct qeth_card *card) @@ -1085,7 +1085,7 @@ qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply, cmd->data.diagass.action, CARD_DEVID(card)); } - return 0; + return rc ? -EIO : 0; } static int @@ -1524,7 +1524,7 @@ static void qeth_l3_set_rx_mode(struct net_device *dev) qeth_l3_handle_promisc_mode(card); } -static int qeth_l3_arp_makerc(int rc) +static int qeth_l3_arp_makerc(u16 rc) { switch (rc) { case IPA_RC_SUCCESS: @@ -1541,8 +1541,18 @@ static int qeth_l3_arp_makerc(int rc) } } +static int qeth_l3_arp_cmd_cb(struct qeth_card *card, struct qeth_reply *reply, + unsigned long data) +{ + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data; + + qeth_setassparms_cb(card, reply, data); + return qeth_l3_arp_makerc(cmd->hdr.return_code); +} + static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) { + struct qeth_cmd_buffer *iob; int rc; QETH_CARD_TEXT(card, 3, "arpstnoe"); @@ -1557,13 +1567,19 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { return -EOPNOTSUPP; } - rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING, - IPA_CMD_ASS_ARP_SET_NO_ENTRIES, - no_entries); + + iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_SET_NO_ENTRIES, 4, + QETH_PROT_IPV4); + if (!iob) + return -ENOMEM; + + __ipa_cmd(iob)->data.setassparms.data.flags_32bit = (u32) no_entries; + rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL); if (rc) QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on device %x: %#x\n", CARD_DEVID(card), rc); - return qeth_l3_arp_makerc(rc); + return rc; } static __u32 get_arp_entry_size(struct qeth_card *card, @@ -1792,16 +1808,16 @@ static int qeth_l3_arp_modify_entry(struct qeth_card *card, cmd_entry = &__ipa_cmd(iob)->data.setassparms.data.arp_entry; ether_addr_copy(cmd_entry->macaddr, entry->macaddr); memcpy(cmd_entry->ipaddr, entry->ipaddr, 4); - rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_cb, NULL); + rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL); if (rc) QETH_DBF_MESSAGE(2, "Could not modify (cmd: %#x) ARP entry on device %x: %#x\n", arp_cmd, CARD_DEVID(card), rc); - - return qeth_l3_arp_makerc(rc); + return rc; } static int qeth_l3_arp_flush_cache(struct qeth_card *card) { + struct qeth_cmd_buffer *iob; int rc; QETH_CARD_TEXT(card, 3, "arpflush"); @@ -1816,12 +1832,18 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card) if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { return -EOPNOTSUPP; } - rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING, - IPA_CMD_ASS_ARP_FLUSH_CACHE, 0); + + iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_FLUSH_CACHE, 0, + QETH_PROT_IPV4); + if (!iob) + return -ENOMEM; + + rc = qeth_send_ipa_cmd(card, iob, qeth_l3_arp_cmd_cb, NULL); if (rc) QETH_DBF_MESSAGE(2, "Could not flush ARP cache on device %x: %#x\n", CARD_DEVID(card), rc); - return qeth_l3_arp_makerc(rc); + return rc; } static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -- cgit v1.2.3 From b6cd7dd99a89ee2f0595bf3e62682a3cde3d4a62 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 11 Feb 2019 16:34:44 -0600 Subject: ser_gigaset: mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/isdn/gigaset/ser-gigaset.c: In function ‘gigaset_tty_ioctl’: drivers/isdn/gigaset/ser-gigaset.c:627:3: warning: this statement may fall through [-Wimplicit-fallthrough=] switch (arg) { ^~~~~~ drivers/isdn/gigaset/ser-gigaset.c:638:2: note: here default: ^~~~~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Acked-by: Paul Bolle Signed-off-by: David S. Miller --- drivers/isdn/gigaset/ser-gigaset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index ab0b63a4d045..e1de8b1a1001 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -633,7 +633,7 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file, flush_send_queue(cs); break; } - /* Pass through */ + /* fall through */ default: /* pass through to underlying serial device */ -- cgit v1.2.3 From 56e9b6b9601c113b1c19c61e70ac972444cb40aa Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 11 Feb 2019 16:38:21 -0600 Subject: isdn: i4l: isdn_tty: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/isdn/i4l/isdn_tty.c: In function ‘isdn_tty_edit_at’: drivers/isdn/i4l/isdn_tty.c:3644:18: warning: this statement may fall through [-Wimplicit-fallthrough=] m->mdmcmdl = 0; ~~~~~~~~~~~^~~ drivers/isdn/i4l/isdn_tty.c:3646:5: note: here case 0: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index dc1cded716c1..43700fc19a31 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -3642,7 +3642,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info *info) break; } else m->mdmcmdl = 0; - /* Fall through, check for 'A' */ + /* Fall through - check for 'A' */ case 0: if (c == 'A') { m->mdmcmd[m->mdmcmdl] = c; -- cgit v1.2.3 From b67de691f60b471401798498c1bc68e63b00708d Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 11 Feb 2019 16:42:37 -0600 Subject: isdn_v110: mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/isdn/i4l/isdn_v110.c: In function ‘EncodeMatrix’: drivers/isdn/i4l/isdn_v110.c:353:7: warning: this statement may fall through [-Wimplicit-fallthrough=] if (line >= mlen) { ^ drivers/isdn/i4l/isdn_v110.c:358:3: note: here case 128: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_v110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c index 2a5f6668756c..d11fe76f138f 100644 --- a/drivers/isdn/i4l/isdn_v110.c +++ b/drivers/isdn/i4l/isdn_v110.c @@ -354,7 +354,7 @@ EncodeMatrix(unsigned char *buf, int len, unsigned char *m, int mlen) printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n"); return line; } - /* else: fall through */ + /* fall through */ case 128: m[line] = 128; /* leftmost -> set byte to 1000000 */ mbit = 64; /* current bit in the matrix line */ -- cgit v1.2.3 From acc65103c15c7e6e468662568e8d5e1306c264e9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 11 Feb 2019 18:47:01 +0200 Subject: ath10k: fix line length warning in ath10k_ce_alloc_dest_ring() Commit 750afb08ca71 ("cross-tree: phase out dma_zalloc_coherent()") introduced a new checkpatch warning: drivers/net/wireless/ath/ath10k/ce.c:1602: line over 90 characters Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 32f4802b3942..9dbe7574443c 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1599,7 +1599,8 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, */ dest_ring->base_addr_owner_space_unaligned = dma_alloc_coherent(ar->dev, - (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), + (nentries * sizeof(struct ce_desc) + + CE_DESC_RING_ALIGN), &base_addr, GFP_KERNEL); if (!dest_ring->base_addr_owner_space_unaligned) { kfree(dest_ring); -- cgit v1.2.3 From 89cea7493a3463f1eb3846940870a229d0713e27 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Mon, 11 Feb 2019 18:47:47 +0200 Subject: ath9k: Switch to mac80211 TXQ scheduling and airtime APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This moves the ath9k driver to use the mac80211 TXQ scheduling and airtime accounting APIs, removing the corresponding state tracking inside the driver. Signed-off-by: Toke Høiland-Jørgensen [rmanohar@codeaurora.org: fixed checkpatch error and warnings] Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ath9k.h | 14 -- drivers/net/wireless/ath/ath9k/debug.c | 3 - drivers/net/wireless/ath/ath9k/debug.h | 8 - drivers/net/wireless/ath/ath9k/debug_sta.c | 70 --------- drivers/net/wireless/ath/ath9k/init.c | 3 +- drivers/net/wireless/ath/ath9k/recv.c | 9 +- drivers/net/wireless/ath/ath9k/xmit.c | 244 +++++++++-------------------- 7 files changed, 75 insertions(+), 276 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0fca44e91a71..a412b352182c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -112,8 +112,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_TXFIFO_DEPTH 8 #define ATH_TX_ERROR 0x01 -#define ATH_AIRTIME_QUANTUM 300 /* usec */ - /* Stop tx traffic 1ms before the GO goes away */ #define ATH_P2P_PS_STOP_TIME 1000 @@ -246,10 +244,8 @@ struct ath_atx_tid { s8 bar_index; bool active; bool clear_ps_filter; - bool has_queued; }; -void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid); void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid); struct ath_node { @@ -263,12 +259,9 @@ struct ath_node { bool sleeping; bool no_ps_filter; - s64 airtime_deficit[IEEE80211_NUM_ACS]; - u32 airtime_rx_start; #ifdef CONFIG_ATH9K_STATION_STATISTICS struct ath_rx_rate_stats rx_rate_stats; - struct ath_airtime_stats airtime_stats; #endif u8 key_idx[4]; @@ -986,11 +979,6 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ -#define AIRTIME_USE_TX BIT(0) -#define AIRTIME_USE_RX BIT(1) -#define AIRTIME_USE_NEW_QUEUES BIT(2) -#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX))) - struct ath_softc { struct ieee80211_hw *hw; struct device *dev; @@ -1034,8 +1022,6 @@ struct ath_softc { short nbcnvifs; unsigned long ps_usecount; - u16 airtime_flags; /* AIRTIME_* */ - struct ath_rx rx; struct ath_tx tx; struct ath_beacon beacon; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 4399e9ad058f..0dfea5d6e949 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1443,9 +1443,6 @@ int ath9k_init_debug(struct ath_hw *ah) #endif debugfs_create_file("tpc", 0600, sc->debug.debugfs_phy, sc, &fops_tpc); - debugfs_create_u16("airtime_flags", 0600, - sc->debug.debugfs_phy, &sc->airtime_flags); - debugfs_create_file("nf_override", 0600, sc->debug.debugfs_phy, sc, &fops_nf_override); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 79607db14387..33826aa13687 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -319,20 +319,12 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb); -void ath_debug_airtime(struct ath_softc *sc, - struct ath_node *an, - u32 rx, u32 tx); #else static inline void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb) { } -static inline void ath_debug_airtime(struct ath_softc *sc, - struct ath_node *an, - u32 rx, u32 tx) -{ -} #endif /* CONFIG_ATH9K_STATION_STATISTICS */ #endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c index e8fcd3e1c470..d95cabddce33 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -242,75 +242,6 @@ static const struct file_operations fops_node_recv = { .llseek = default_llseek, }; -void ath_debug_airtime(struct ath_softc *sc, - struct ath_node *an, - u32 rx, - u32 tx) -{ - struct ath_airtime_stats *astats = &an->airtime_stats; - - astats->rx_airtime += rx; - astats->tx_airtime += tx; -} - -static ssize_t read_airtime(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_node *an = file->private_data; - struct ath_airtime_stats *astats; - static const char *qname[4] = { - "VO", "VI", "BE", "BK" - }; - u32 len = 0, size = 256; - char *buf; - size_t retval; - int i; - - buf = kzalloc(size, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - astats = &an->airtime_stats; - - len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime); - len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime); - len += scnprintf(buf + len, size - len, "Deficit: "); - for (i = 0; i < 4; i++) - len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]); - if (len < size) - buf[len++] = '\n'; - - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - - return retval; -} - -static ssize_t -write_airtime_reset_stub(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct ath_node *an = file->private_data; - struct ath_airtime_stats *astats; - int i; - - astats = &an->airtime_stats; - astats->rx_airtime = 0; - astats->tx_airtime = 0; - for (i = 0; i < 4; i++) - an->airtime_deficit[i] = ATH_AIRTIME_QUANTUM; - return count; -} - -static const struct file_operations fops_airtime = { - .read = read_airtime, - .write = write_airtime_reset_stub, - .open = simple_open, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - - void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -320,5 +251,4 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, debugfs_create_file("node_aggr", 0444, dir, an, &fops_node_aggr); debugfs_create_file("node_recv", 0444, dir, an, &fops_node_recv); - debugfs_create_file("airtime", 0644, dir, an, &fops_airtime); } diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index fae572b38416..98141b699c88 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -676,8 +676,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, /* Will be cleared in ath9k_start() */ set_bit(ATH_OP_INVALID, &common->op_flags); - sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX | - AIRTIME_USE_NEW_QUEUES); sc->sc_ah = ah; sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); @@ -1013,6 +1011,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) SET_IEEE80211_PERM_ADDR(hw, common->macaddr); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); } int ath9k_init_device(u16 devid, struct ath_softc *sc, diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 30d1bd832d90..285a62d3019d 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1054,14 +1054,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc, len, rxs->rate_idx, is_sp); } - if (!!(sc->airtime_flags & AIRTIME_USE_RX)) { - spin_lock_bh(&acq->lock); - an->airtime_deficit[acno] -= airtime; - if (an->airtime_deficit[acno] <= 0) - __ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno)); - spin_unlock_bh(&acq->lock); - } - ath_debug_airtime(sc, an, airtime, 0); + ieee80211_sta_register_airtime(sta, tidno, 0, airtime); exit: rcu_read_unlock(); } diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f448d5716639..06e0c5a6fab6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -113,44 +113,14 @@ void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) ath_tx_status(hw, skb); } -void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; - struct ath_chanctx *ctx = avp->chanctx; - struct ath_acq *acq; - struct list_head *tid_list; - u8 acno = TID_TO_WME_AC(tid->tidno); - - if (!ctx || !list_empty(&tid->list)) - return; - - - acq = &ctx->acq[acno]; - if ((sc->airtime_flags & AIRTIME_USE_NEW_QUEUES) && - tid->an->airtime_deficit[acno] > 0) - tid_list = &acq->acq_new; - else - tid_list = &acq->acq_old; - - list_add_tail(&tid->list, tid_list); -} - void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; - struct ath_chanctx *ctx = avp->chanctx; - struct ath_acq *acq; + struct ieee80211_txq *queue = + container_of((void *)tid, struct ieee80211_txq, drv_priv); - if (!ctx || !list_empty(&tid->list)) - return; - - acq = &ctx->acq[TID_TO_WME_AC(tid->tidno)]; - spin_lock_bh(&acq->lock); - __ath_tx_queue_tid(sc, tid); - spin_unlock_bh(&acq->lock); + ieee80211_schedule_txq(sc->hw, queue); } - void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue) { struct ath_softc *sc = hw->priv; @@ -163,11 +133,7 @@ void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue) tid->tidno); ath_txq_lock(sc, txq); - - tid->has_queued = true; - ath_tx_queue_tid(sc, tid); ath_txq_schedule(sc, txq); - ath_txq_unlock(sc, txq); } @@ -217,8 +183,8 @@ ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb) return ATH_AN_2_TID(an, tidno); } -static struct sk_buff * -ath_tid_pull(struct ath_atx_tid *tid) +static int +ath_tid_pull(struct ath_atx_tid *tid, struct sk_buff **skbuf) { struct ieee80211_txq *txq = container_of((void*)tid, struct ieee80211_txq, drv_priv); struct ath_softc *sc = tid->an->sc; @@ -229,20 +195,16 @@ ath_tid_pull(struct ath_atx_tid *tid) }; struct sk_buff *skb; struct ath_frame_info *fi; - int q; - - if (!tid->has_queued) - return NULL; + int q, ret; skb = ieee80211_tx_dequeue(hw, txq); - if (!skb) { - tid->has_queued = false; - return NULL; - } + if (!skb) + return -ENOENT; - if (ath_tx_prepare(hw, skb, &txctl)) { + ret = ath_tx_prepare(hw, skb, &txctl); + if (ret) { ieee80211_free_txskb(hw, skb); - return NULL; + return ret; } q = skb_get_queue_mapping(skb); @@ -252,24 +214,19 @@ ath_tid_pull(struct ath_atx_tid *tid) ++tid->txq->pending_frames; } - return skb; -} - - -static bool ath_tid_has_buffered(struct ath_atx_tid *tid) -{ - return !skb_queue_empty(&tid->retry_q) || tid->has_queued; + *skbuf = skb; + return 0; } -static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid) +static int ath_tid_dequeue(struct ath_atx_tid *tid, + struct sk_buff **skb) { - struct sk_buff *skb; - - skb = __skb_dequeue(&tid->retry_q); - if (!skb) - skb = ath_tid_pull(tid); + int ret = 0; + *skb = __skb_dequeue(&tid->retry_q); + if (!*skb) + ret = ath_tid_pull(tid, skb); - return skb; + return ret; } static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) @@ -365,11 +322,12 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, struct list_head bf_head; struct ath_tx_status ts; struct ath_frame_info *fi; + int ret; memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); - while ((skb = ath_tid_dequeue(tid))) { + while ((ret = ath_tid_dequeue(tid, &skb)) == 0) { fi = get_frame_info(skb); bf = fi->bf; @@ -681,7 +639,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, skb_queue_splice_tail(&bf_pending, &tid->retry_q); if (!an->sleeping) { ath_tx_queue_tid(sc, tid); - if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) tid->clear_ps_filter = true; } @@ -708,11 +665,11 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf) return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); } -static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an, - struct ath_atx_tid *tid, struct ath_buf *bf, +static void ath_tx_count_airtime(struct ath_softc *sc, + struct ieee80211_sta *sta, + struct ath_buf *bf, struct ath_tx_status *ts) { - struct ath_txq *txq = tid->txq; u32 airtime = 0; int i; @@ -722,17 +679,7 @@ static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an, airtime += rate_dur * bf->rates[i].count; } - if (sc->airtime_flags & AIRTIME_USE_TX) { - int q = txq->mac80211_qnum; - struct ath_acq *acq = &sc->cur_chan->acq[q]; - - spin_lock_bh(&acq->lock); - an->airtime_deficit[q] -= airtime; - if (an->airtime_deficit[q] <= 0) - __ath_tx_queue_tid(sc, tid); - spin_unlock_bh(&acq->lock); - } - ath_debug_airtime(sc, an, 0, airtime); + ieee80211_sta_register_airtime(sta, ts->tid, airtime, 0); } static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, @@ -762,7 +709,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, if (sta) { struct ath_node *an = (struct ath_node *)sta->drv_priv; tid = ath_get_skb_tid(sc, an, bf->bf_mpdu); - ath_tx_count_airtime(sc, an, tid, bf, ts); + ath_tx_count_airtime(sc, sta, bf, ts); if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) tid->clear_ps_filter = true; } @@ -947,20 +894,21 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, return ndelim; } -static struct ath_buf * +static int ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) + struct ath_atx_tid *tid, struct ath_buf **buf) { struct ieee80211_tx_info *tx_info; struct ath_frame_info *fi; - struct sk_buff *skb, *first_skb = NULL; struct ath_buf *bf; + struct sk_buff *skb, *first_skb = NULL; u16 seqno; + int ret; while (1) { - skb = ath_tid_dequeue(tid); - if (!skb) - break; + ret = ath_tid_dequeue(tid, &skb); + if (ret < 0) + return ret; fi = get_frame_info(skb); bf = fi->bf; @@ -992,7 +940,7 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) { bf->bf_state.bf_type = 0; - return bf; + break; } bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; @@ -1011,7 +959,7 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, first_skb = skb; continue; } - break; + return -EINPROGRESS; } if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) { @@ -1028,10 +976,11 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq, if (bf_isampdu(bf)) ath_tx_addto_baw(sc, tid, bf); - return bf; + break; } - return NULL; + *buf = bf; + return 0; } static int @@ -1041,7 +990,7 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) struct ath_buf *bf = bf_first, *bf_prev = NULL; - int nframes = 0, ndelim; + int nframes = 0, ndelim, ret; u16 aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw = tid->baw_size / 2; struct ieee80211_tx_info *tx_info; @@ -1093,7 +1042,9 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, bf_prev = bf; - bf = ath_tx_get_tid_subframe(sc, txq, tid); + ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf); + if (ret < 0) + break; } goto finish; stop: @@ -1490,7 +1441,7 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf_first) { struct ath_buf *bf = bf_first, *bf_prev = NULL; - int nframes = 0; + int nframes = 0, ret; do { struct ieee80211_tx_info *tx_info; @@ -1504,8 +1455,8 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, if (nframes >= 2) break; - bf = ath_tx_get_tid_subframe(sc, txq, tid); - if (!bf) + ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf); + if (ret < 0) break; tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); @@ -1518,30 +1469,27 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, } while (1); } -static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) +static int ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid) { - struct ath_buf *bf; + struct ath_buf *bf = NULL; struct ieee80211_tx_info *tx_info; struct list_head bf_q; - int aggr_len = 0; + int aggr_len = 0, ret; bool aggr; - if (!ath_tid_has_buffered(tid)) - return false; - INIT_LIST_HEAD(&bf_q); - bf = ath_tx_get_tid_subframe(sc, txq, tid); - if (!bf) - return false; + ret = ath_tx_get_tid_subframe(sc, txq, tid, &bf); + if (ret < 0) + return ret; tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) || (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) { __skb_queue_tail(&tid->retry_q, bf->bf_mpdu); - return false; + return -EBUSY; } ath_set_rates(tid->an->vif, tid->an->sta, bf); @@ -1551,7 +1499,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_form_burst(sc, txq, tid, &bf_q, bf); if (list_empty(&bf_q)) - return false; + return -EAGAIN; if (tid->clear_ps_filter || tid->an->no_ps_filter) { tid->clear_ps_filter = false; @@ -1560,7 +1508,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_tx_fill_desc(sc, bf, txq, aggr_len); ath_tx_txqaddbuf(sc, txq, &bf_q, false); - return true; + return 0; } int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, @@ -1623,28 +1571,16 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_atx_tid *tid; - struct ath_txq *txq; int tidno; ath_dbg(common, XMIT, "%s called\n", __func__); for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { tid = ath_node_to_tid(an, tidno); - txq = tid->txq; - - ath_txq_lock(sc, txq); - - if (list_empty(&tid->list)) { - ath_txq_unlock(sc, txq); - continue; - } if (!skb_queue_empty(&tid->retry_q)) ieee80211_sta_set_buffered(sta, tid->tidno, true); - list_del_init(&tid->list); - - ath_txq_unlock(sc, txq); } } @@ -1663,11 +1599,12 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) ath_txq_lock(sc, txq); tid->clear_ps_filter = true; - if (ath_tid_has_buffered(tid)) { + if (!skb_queue_empty(&tid->retry_q)) { ath_tx_queue_tid(sc, tid); ath_txq_schedule(sc, txq); } ath_txq_unlock_complete(sc, txq); + } } @@ -1698,9 +1635,9 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, struct ath_txq *txq = sc->tx.uapsdq; struct ieee80211_tx_info *info; struct list_head bf_q; - struct ath_buf *bf_tail = NULL, *bf; + struct ath_buf *bf_tail = NULL, *bf = NULL; int sent = 0; - int i; + int i, ret; INIT_LIST_HEAD(&bf_q); for (i = 0; tids && nframes; i++, tids >>= 1) { @@ -1713,8 +1650,9 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, ath_txq_lock(sc, tid->txq); while (nframes > 0) { - bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid); - if (!bf) + ret = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, + tid, &bf); + if (ret < 0) break; ath9k_set_moredata(sc, bf, true); @@ -1980,11 +1918,11 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) */ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) { + struct ieee80211_hw *hw = sc->hw; struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ieee80211_txq *queue; struct ath_atx_tid *tid; - struct list_head *tid_list; - struct ath_acq *acq; - bool active = AIRTIME_ACTIVE(sc->airtime_flags); + int ret; if (txq->mac80211_qnum < 0) return; @@ -1992,58 +1930,26 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) return; + ieee80211_txq_schedule_start(hw, txq->mac80211_qnum); spin_lock_bh(&sc->chan_lock); rcu_read_lock(); - acq = &sc->cur_chan->acq[txq->mac80211_qnum]; if (sc->cur_chan->stopped) goto out; -begin: - tid_list = &acq->acq_new; - if (list_empty(tid_list)) { - tid_list = &acq->acq_old; - if (list_empty(tid_list)) - goto out; - } - tid = list_first_entry(tid_list, struct ath_atx_tid, list); - - if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) { - spin_lock_bh(&acq->lock); - tid->an->airtime_deficit[txq->mac80211_qnum] += ATH_AIRTIME_QUANTUM; - list_move_tail(&tid->list, &acq->acq_old); - spin_unlock_bh(&acq->lock); - goto begin; - } - - if (!ath_tid_has_buffered(tid)) { - spin_lock_bh(&acq->lock); - if ((tid_list == &acq->acq_new) && !list_empty(&acq->acq_old)) - list_move_tail(&tid->list, &acq->acq_old); - else { - list_del_init(&tid->list); - } - spin_unlock_bh(&acq->lock); - goto begin; - } + while ((queue = ieee80211_next_txq(hw, txq->mac80211_qnum))) { + tid = (struct ath_atx_tid *)queue->drv_priv; + ret = ath_tx_sched_aggr(sc, txq, tid); + ath_dbg(common, QUEUE, "ath_tx_sched_aggr returned %d\n", ret); - /* - * If we succeed in scheduling something, immediately restart to make - * sure we keep the HW busy. - */ - if(ath_tx_sched_aggr(sc, txq, tid)) { - if (!active) { - spin_lock_bh(&acq->lock); - list_move_tail(&tid->list, &acq->acq_old); - spin_unlock_bh(&acq->lock); - } - goto begin; + ieee80211_return_txq(hw, queue); } out: rcu_read_unlock(); spin_unlock_bh(&sc->chan_lock); + ieee80211_txq_schedule_end(hw, txq->mac80211_qnum); } void ath_txq_schedule_all(struct ath_softc *sc) @@ -2887,9 +2793,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) struct ath_atx_tid *tid; int tidno, acno; - for (acno = 0; acno < IEEE80211_NUM_ACS; acno++) - an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM; - for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { tid = ath_node_to_tid(an, tidno); tid->an = an; @@ -2899,7 +2802,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->baw_head = tid->baw_tail = 0; tid->active = false; tid->clear_ps_filter = true; - tid->has_queued = false; __skb_queue_head_init(&tid->retry_q); INIT_LIST_HEAD(&tid->list); acno = TID_TO_WME_AC(tidno); -- cgit v1.2.3 From bb2edb733586527b8d0957d92f786daecb07e80b Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Mon, 11 Feb 2019 18:47:49 +0200 Subject: ath10k: migrate to mac80211 txq scheduling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ath10k maintains common txqs list for all stations. This txq management can be removed by migrating to mac80211 txq APIs and let mac80211 handle txqs reordering based on reported airtime. By doing this, txq fairness maintained in ath10k i.e processing N frames per txq is removed. By adapting to mac80211 APIs, ath10k will support mac80211 based airtime fairness algorithm. Tested on QCA4019 with firmware version 10.4-3.2.1.1-00015 Tested on QCA9984 with firmware version 10.4-3.9.0.1-00005 Tested-by: Venkateswara Naralasetty Co-developed-by: Rajkumar Manoharan Signed-off-by: Rajkumar Manoharan Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 2 - drivers/net/wireless/ath/ath10k/core.h | 6 +- drivers/net/wireless/ath/ath10k/htc.h | 1 - drivers/net/wireless/ath/ath10k/htt_rx.c | 8 +++ drivers/net/wireless/ath/ath10k/mac.c | 98 ++++++++++++++------------------ 5 files changed, 54 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index ca6085076c68..d39963aacc8d 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -3116,9 +3116,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, mutex_init(&ar->conf_mutex); spin_lock_init(&ar->data_lock); - spin_lock_init(&ar->txqs_lock); - INIT_LIST_HEAD(&ar->txqs); INIT_LIST_HEAD(&ar->peers); init_waitqueue_head(&ar->peer_mapping_wq); init_waitqueue_head(&ar->htt.empty_tx_wq); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 23d7a34e3714..4b730eec88d2 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -90,6 +90,9 @@ /* The magic used by QCA spec */ #define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_" +/* Default Airtime weight multipler (Tuned for multiclient performance) */ +#define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4 + struct ath10k; static inline const char *ath10k_bus_str(enum ath10k_bus bus) @@ -1069,10 +1072,7 @@ struct ath10k { /* protects shared structure data */ spinlock_t data_lock; - /* protects: ar->txqs, artxq->list */ - spinlock_t txqs_lock; - struct list_head txqs; struct list_head arvifs; struct list_head peers; struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS]; diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index 51fda6c23f69..cb30add7dd33 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -51,7 +51,6 @@ struct ath10k; */ #define HTC_HOST_MAX_MSG_PER_RX_BUNDLE 8 -#define HTC_HOST_MAX_MSG_PER_TX_BUNDLE 16 enum ath10k_htc_tx_flags { ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01, diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index a01d1ae6b398..98c525189087 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2596,6 +2596,7 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) u8 tid; int ret; int i; + bool may_tx; ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind\n"); @@ -2668,8 +2669,13 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) num_msdus = 0; num_bytes = 0; + ieee80211_txq_schedule_start(hw, txq->ac); + may_tx = ieee80211_txq_may_transmit(hw, txq); while (num_msdus < max_num_msdus && num_bytes < max_num_bytes) { + if (!may_tx) + break; + ret = ath10k_mac_tx_push_txq(hw, txq); if (ret < 0) break; @@ -2677,6 +2683,8 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) num_msdus++; num_bytes += ret; } + ieee80211_return_txq(hw, txq); + ieee80211_txq_schedule_end(hw, txq->ac); record->num_msdus = cpu_to_le16(num_msdus); record->num_bytes = cpu_to_le32(num_bytes); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index c8af35ff2019..0d5215da410a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3890,7 +3890,6 @@ static void ath10k_mac_txq_init(struct ieee80211_txq *txq) static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) { - struct ath10k_txq *artxq; struct ath10k_skb_cb *cb; struct sk_buff *msdu; int msdu_id; @@ -3898,12 +3897,6 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) if (!txq) return; - artxq = (void *)txq->drv_priv; - spin_lock_bh(&ar->txqs_lock); - if (!list_empty(&artxq->list)) - list_del_init(&artxq->list); - spin_unlock_bh(&ar->txqs_lock); - spin_lock_bh(&ar->htt.tx_lock); idr_for_each_entry(&ar->htt.pending_tx, msdu, msdu_id) { cb = ATH10K_SKB_CB(msdu); @@ -3943,7 +3936,6 @@ static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw, struct ath10k_txq *artxq = (void *)txq->drv_priv; /* No need to get locks */ - if (ar->htt.tx_q_state.mode == HTT_TX_MODE_SWITCH_PUSH) return true; @@ -4030,48 +4022,45 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, return skb_len; } -void ath10k_mac_tx_push_pending(struct ath10k *ar) +static int ath10k_mac_schedule_txq(struct ieee80211_hw *hw, u32 ac) { - struct ieee80211_hw *hw = ar->hw; struct ieee80211_txq *txq; - struct ath10k_txq *artxq; - struct ath10k_txq *last; - int ret; - int max; - - if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2)) - return; - - spin_lock_bh(&ar->txqs_lock); - rcu_read_lock(); - - last = list_last_entry(&ar->txqs, struct ath10k_txq, list); - while (!list_empty(&ar->txqs)) { - artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list); - txq = container_of((void *)artxq, struct ieee80211_txq, - drv_priv); + int ret = 0; - /* Prevent aggressive sta/tid taking over tx queue */ - max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE; - ret = 0; - while (ath10k_mac_tx_can_push(hw, txq) && max--) { + ieee80211_txq_schedule_start(hw, ac); + while ((txq = ieee80211_next_txq(hw, ac))) { + while (ath10k_mac_tx_can_push(hw, txq)) { ret = ath10k_mac_tx_push_txq(hw, txq); if (ret < 0) break; } + ieee80211_return_txq(hw, txq); + ath10k_htt_tx_txq_update(hw, txq); + if (ret == -EBUSY) + break; + } + ieee80211_txq_schedule_end(hw, ac); + + return ret; +} - list_del_init(&artxq->list); - if (ret != -ENOENT) - list_add_tail(&artxq->list, &ar->txqs); +void ath10k_mac_tx_push_pending(struct ath10k *ar) +{ + struct ieee80211_hw *hw = ar->hw; + u32 ac; - ath10k_htt_tx_txq_update(hw, txq); + if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH) + return; - if (artxq == last || (ret < 0 && ret != -ENOENT)) + if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2)) + return; + + rcu_read_lock(); + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { + if (ath10k_mac_schedule_txq(hw, ac) == -EBUSY) break; } - rcu_read_unlock(); - spin_unlock_bh(&ar->txqs_lock); } EXPORT_SYMBOL(ath10k_mac_tx_push_pending); @@ -4310,31 +4299,28 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { struct ath10k *ar = hw->priv; - struct ath10k_txq *artxq = (void *)txq->drv_priv; - struct ieee80211_txq *f_txq; - struct ath10k_txq *f_artxq; - int ret = 0; - int max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE; + int ret; + u8 ac; - spin_lock_bh(&ar->txqs_lock); - if (list_empty(&artxq->list)) - list_add_tail(&artxq->list, &ar->txqs); + ath10k_htt_tx_txq_update(hw, txq); + if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH) + return; - f_artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list); - f_txq = container_of((void *)f_artxq, struct ieee80211_txq, drv_priv); - list_del_init(&f_artxq->list); + ac = txq->ac; + ieee80211_txq_schedule_start(hw, ac); + txq = ieee80211_next_txq(hw, ac); + if (!txq) + goto out; - while (ath10k_mac_tx_can_push(hw, f_txq) && max--) { - ret = ath10k_mac_tx_push_txq(hw, f_txq); + while (ath10k_mac_tx_can_push(hw, txq)) { + ret = ath10k_mac_tx_push_txq(hw, txq); if (ret < 0) break; } - if (ret != -ENOENT) - list_add_tail(&f_artxq->list, &ar->txqs); - spin_unlock_bh(&ar->txqs_lock); - - ath10k_htt_tx_txq_update(hw, f_txq); + ieee80211_return_txq(hw, txq); ath10k_htt_tx_txq_update(hw, txq); +out: + ieee80211_txq_schedule_end(hw, ac); } /* Must not be called with conf_mutex held as workers can use that also. */ @@ -8727,6 +8713,8 @@ int ath10k_mac_register(struct ath10k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; + ret = ieee80211_register_hw(ar->hw); if (ret) { ath10k_err(ar, "failed to register ieee80211: %d\n", ret); -- cgit v1.2.3 From d1ce37b7831ac6445c60f34b680f7214359e87ab Mon Sep 17 00:00:00 2001 From: Kan Yan Date: Mon, 11 Feb 2019 18:47:52 +0200 Subject: ath10k: report estimated frame transmit airtime to improve fairness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The airtime of a transmitted frame will be estimated from last used tx rate which the firmware reports with the peer stats feature (WMI_SERVICE_PEER_STATS). The airtime is computed on the tx path and it will be reported to mac80211 upon tx completion. This change is based on Kan's orginal commit in Chromium tree ("CHROMIUM: ath10k: Implementing airtime fairness based TX scheduler") ref: https://chromium-review.googlesource.com/588190 Tested on QCA4019 with firmware version 10.4-3.2.1.1-00015 Tested on QCA9984 with firmware version 10.4-3.9.0.1-00005 Signed-off-by: Kan Yan [rmanohar@codeaurora.org: ported only the airtime computation] Signed-off-by: Rajkumar Manoharan [toke@redhat.com: Rebase to mac80211-next, add test note] Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 2 ++ drivers/net/wireless/ath/ath10k/htt_rx.c | 1 + drivers/net/wireless/ath/ath10k/mac.c | 57 ++++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/txrx.c | 4 +++ 4 files changed, 61 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 4b730eec88d2..59958664dde4 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -126,6 +126,7 @@ struct ath10k_skb_cb { u8 flags; u8 eid; u16 msdu_id; + u16 airtime_est; struct ieee80211_vif *vif; struct ieee80211_txq *txq; } __packed; @@ -498,6 +499,7 @@ struct ath10k_sta { u16 peer_id; struct rate_info txrate; struct ieee80211_tx_info tx_info; + u32 last_tx_bitrate; struct work_struct update_wk; u64 rx_duration; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 98c525189087..77f494d52ec3 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -3080,6 +3080,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, arsta->txrate.nss = txrate.nss; arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw); + arsta->last_tx_bitrate = cfg80211_calculate_bitrate(&arsta->txrate); if (sgi) arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0d5215da410a..88c7b58c9e2f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3544,7 +3544,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, struct ieee80211_vif *vif, struct ieee80211_txq *txq, - struct sk_buff *skb) + struct sk_buff *skb, u16 airtime) { struct ieee80211_hdr *hdr = (void *)skb->data; struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb); @@ -3561,6 +3561,7 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, cb->vif = vif; cb->txq = txq; + cb->airtime_est = airtime; } bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) @@ -3948,6 +3949,49 @@ static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw, return false; } +/* Return estimated airtime in microsecond, which is calculated using last + * reported TX rate. This is just a rough estimation because host driver has no + * knowledge of the actual transmit rate, retries or aggregation. If actual + * airtime can be reported by firmware, then delta between estimated and actual + * airtime can be adjusted from deficit. + */ +#define IEEE80211_ATF_OVERHEAD 100 /* IFS + some slot time */ +#define IEEE80211_ATF_OVERHEAD_IFS 16 /* IFS only */ +static u16 ath10k_mac_update_airtime(struct ath10k *ar, + struct ieee80211_txq *txq, + struct sk_buff *skb) +{ + struct ath10k_sta *arsta; + u32 pktlen; + u16 airtime = 0; + + if (!txq || !txq->sta) + return airtime; + + spin_lock_bh(&ar->data_lock); + arsta = (struct ath10k_sta *)txq->sta->drv_priv; + + pktlen = skb->len + 38; /* Assume MAC header 30, SNAP 8 for most case */ + if (arsta->last_tx_bitrate) { + /* airtime in us, last_tx_bitrate in 100kbps */ + airtime = (pktlen * 8 * (1000 / 100)) + / arsta->last_tx_bitrate; + /* overhead for media access time and IFS */ + airtime += IEEE80211_ATF_OVERHEAD_IFS; + } else { + /* This is mostly for throttle excessive BC/MC frames, and the + * airtime/rate doesn't need be exact. Airtime of BC/MC frames + * in 2G get some discount, which helps prevent very low rate + * frames from being blocked for too long. + */ + airtime = (pktlen * 8 * (1000 / 100)) / 60; /* 6M */ + airtime += IEEE80211_ATF_OVERHEAD; + } + spin_unlock_bh(&ar->data_lock); + + return airtime; +} + int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { @@ -3963,6 +4007,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, size_t skb_len; bool is_mgmt, is_presp; int ret; + u16 airtime; spin_lock_bh(&ar->htt.tx_lock); ret = ath10k_htt_tx_inc_pending(htt); @@ -3980,7 +4025,8 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, return -ENOENT; } - ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); + airtime = ath10k_mac_update_airtime(ar, txq, skb); + ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime); skb_len = skb->len; txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); @@ -4247,8 +4293,10 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw, bool is_mgmt; bool is_presp; int ret; + u16 airtime; - ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); + airtime = ath10k_mac_update_airtime(ar, txq, skb); + ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb, airtime); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); @@ -8604,6 +8652,9 @@ int ath10k_mac_register(struct ath10k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); + if (ath10k_peer_stats_enabled(ar)) + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); /* * on LL hardware queues are managed entirely by the FW * so we only advertise to mac we can do the queues thing diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index f13d88906b5a..44c13b884603 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -95,6 +95,10 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); + if (txq && txq->sta) + ieee80211_sta_register_airtime(txq->sta, txq->tid, + skb_cb->airtime_est, 0); + if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); -- cgit v1.2.3 From 059104bff31252684fd4dbc8117e9d767efc2022 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Chitrapu Date: Mon, 11 Feb 2019 18:47:54 +0200 Subject: ath10k: add support to configure ftm responder role Configure fine timing measurement (FTM) responder role from the ftm_responder bss param sent by mac80211. With FTM functionality offloaded to firmware, adding the interface allows userspace to enable or disable FTM responder functionality. ath10k disables it at the time of interface creation. Supported FW: 10.4 Tested on IPQ4019 with firmware: 10.4-3.2.1.1-00022 Signed-off-by: Pradeep Kumar Chitrapu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 30 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.c | 4 ++++ drivers/net/wireless/ath/ath10k/wmi.h | 10 ++++++++++ 4 files changed, 45 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 59958664dde4..360842633d20 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -576,6 +576,7 @@ struct ath10k_vif { bool nohwcrypt; int num_legacy_stations; int txpower; + bool ftm_responder; struct wmi_wmm_params_all_arg wmm_params; struct work_struct ap_csa_work; struct delayed_work connection_loss_work; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 88c7b58c9e2f..bf094f44e9ad 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -5376,6 +5376,17 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, goto err_peer_delete; } + if (test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map)) { + vdev_param = ar->wmi.vdev_param->rtt_responder_role; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, + arvif->ftm_responder); + + /* It is harmless to not set FTM role. Do not warn */ + if (ret && ret != -EOPNOTSUPP) + ath10k_warn(ar, "failed to set vdev %i FTM Responder: %d\n", + arvif->vdev_id, ret); + } + if (vif->type == NL80211_IFTYPE_MONITOR) { ar->monitor_arvif = arvif; ret = ath10k_monitor_recalc(ar); @@ -5650,6 +5661,20 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ether_addr_copy(arvif->bssid, info->bssid); + if (changed & BSS_CHANGED_FTM_RESPONDER && + arvif->ftm_responder != info->ftm_responder && + test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map)) { + arvif->ftm_responder = info->ftm_responder; + + vdev_param = ar->wmi.vdev_param->rtt_responder_role; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, + arvif->ftm_responder); + + ath10k_dbg(ar, ATH10K_DBG_MAC, + "mac vdev %d ftm_responder %d:ret %d\n", + arvif->vdev_id, arvif->ftm_responder, ret); + } + if (changed & BSS_CHANGED_BEACON_ENABLED) ath10k_control_beaconing(arvif, info); @@ -8655,6 +8680,11 @@ int ath10k_mac_register(struct ath10k *ar) if (ath10k_peer_stats_enabled(ar)) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); + + if (test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map)) + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); + /* * on LL hardware queues are managed entirely by the FW * so we only advertise to mac we can do the queues thing diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index cb876c221d8f..704c71bc3ef6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -827,6 +827,7 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = { .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, .disable_4addr_src_lrn = WMI_VDEV_PARAM_UNSUPPORTED, + .rtt_responder_role = WMI_VDEV_PARAM_UNSUPPORTED, }; /* 10.X WMI VDEV param map */ @@ -903,6 +904,7 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, .disable_4addr_src_lrn = WMI_VDEV_PARAM_UNSUPPORTED, + .rtt_responder_role = WMI_VDEV_PARAM_UNSUPPORTED, }; static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { @@ -978,6 +980,7 @@ static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = { .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED, .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED, .disable_4addr_src_lrn = WMI_VDEV_PARAM_UNSUPPORTED, + .rtt_responder_role = WMI_VDEV_PARAM_UNSUPPORTED, }; static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { @@ -1056,6 +1059,7 @@ static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = { .inc_tsf = WMI_10_4_VDEV_PARAM_TSF_INCREMENT, .dec_tsf = WMI_10_4_VDEV_PARAM_TSF_DECREMENT, .disable_4addr_src_lrn = WMI_10_4_VDEV_PARAM_DISABLE_4_ADDR_SRC_LRN, + .rtt_responder_role = WMI_10_4_VDEV_PARAM_ENABLE_DISABLE_RTT_RESPONDER_ROLE, }; static struct wmi_pdev_param_map wmi_pdev_param_map = { diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 86f128b9a34a..85de53af4817 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -208,6 +208,7 @@ enum wmi_service { WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT, WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT, WMI_SERVICE_THERM_THROT, + WMI_SERVICE_RTT_RESPONDER_ROLE, /* keep last */ WMI_SERVICE_MAX, @@ -368,6 +369,10 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_HTT_ASSERT_TRIGGER_SUPPORT, WMI_10_4_SERVICE_VDEV_FILTER_NEIGHBOR_RX_PACKETS, WMI_10_4_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT, + WMI_10_4_SERVICE_PEER_CHWIDTH_CHANGE, + WMI_10_4_SERVICE_RX_FILTER_OUT_COUNT, + WMI_10_4_SERVICE_RTT_RESPONDER_ROLE, + WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, }; static inline char *wmi_service_name(int service_id) @@ -483,6 +488,8 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_RESET_CHIP); SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI); SVCSTR(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT); + SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE); + default: return NULL; } @@ -799,6 +806,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT, len); SVCMAP(WMI_10_4_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT, WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT, len); + SVCMAP(WMI_10_4_SERVICE_RTT_RESPONDER_ROLE, + WMI_SERVICE_RTT_RESPONDER_ROLE, len); } #undef SVCMAP @@ -5104,6 +5113,7 @@ struct wmi_vdev_param_map { u32 inc_tsf; u32 dec_tsf; u32 disable_4addr_src_lrn; + u32 rtt_responder_role; }; #define WMI_VDEV_PARAM_UNSUPPORTED 0 -- cgit v1.2.3 From 4920ce3bf7e0d533441b3c8e50b40a6f1897492b Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Mon, 11 Feb 2019 18:47:56 +0200 Subject: ath10k: add dynamic vlan support Multicast/broadcast traffic destined for a particular vlan group will always be encrypted in software. To enable dynamic VLANs, it requires driver support for sending software encrypted packets. In ath10k, sending software encrypted frames is allowed only when we insmod the driver with cryptmode param set to 1, this configuration disables hardware crypto and enables RAW mode implicitly. Since, enabling raw mode has performance impact, this cannot be considered as an ideal solution for supporting VLANs in the driver. As an alternative take, in this approach, cryptographic keys for unicast traffic (per peer PTKs) and keys for non-vlan group traffic will be configured in hardware, allowing hardware encryption for unicast and non-vlan group traffic. Only vlan group traffic will be encrypted in software and pushed to the target with encap mode set to RAW in the TX descriptors. Not all firmwares can support this type of key configuration(having few keys installed in hardware and few only in software); for this purpose a new WMI service flag "WMI_SERVICE_PER_PACKET_SW_ENCRYPT" is introduced to advertise this support. Also, adding the logic required to send sw encrypted frames in raw mode. Hardwares Tested : QCA9984, QCA988X Firmwares Tested : 10.4-3.5.3-00057, 10.2.4-1.0-00042 Signed-off-by: Manikanta Pubbisetty Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/mac.c | 26 ++++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/wmi.h | 6 ++++++ 3 files changed, 31 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 360842633d20..2f43600717ec 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -119,6 +119,7 @@ enum ath10k_skb_flags { ATH10K_SKB_F_DELIVER_CAB = BIT(2), ATH10K_SKB_F_MGMT = BIT(3), ATH10K_SKB_F_QOS = BIT(4), + ATH10K_SKB_F_RAW_TX = BIT(5), }; struct ath10k_skb_cb { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index bf094f44e9ad..22774e127507 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3397,6 +3397,7 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar, struct sk_buff *skb) { const struct ieee80211_hdr *hdr = (void *)skb->data; + const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); __le16 fc = hdr->frame_control; if (!vif || vif->type == NL80211_IFTYPE_MONITOR) @@ -3438,7 +3439,8 @@ ath10k_mac_tx_h_get_txmode(struct ath10k *ar, if (ieee80211_is_data_present(fc) && sta && sta->tdls) return ATH10K_HW_TXRX_ETHERNET; - if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) + if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) || + skb_cb->flags & ATH10K_SKB_F_RAW_TX) return ATH10K_HW_TXRX_RAW; return ATH10K_HW_TXRX_NATIVE_WIFI; @@ -3548,6 +3550,9 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, { struct ieee80211_hdr *hdr = (void *)skb->data; struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb); + const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + bool is_data = ieee80211_is_data(hdr->frame_control) || + ieee80211_is_data_qos(hdr->frame_control); cb->flags = 0; if (!ath10k_tx_h_use_hwcrypto(vif, skb)) @@ -3559,6 +3564,16 @@ static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, if (ieee80211_is_data_qos(hdr->frame_control)) cb->flags |= ATH10K_SKB_F_QOS; + /* Data frames encrypted in software will be posted to firmware + * with tx encap mode set to RAW. Ex: Multicast traffic generated + * for a specific VLAN group will always be encrypted in software. + */ + if (is_data && ieee80211_has_protected(hdr->frame_control) && + !info->control.hw_key) { + cb->flags |= ATH10K_SKB_F_NO_HWCRYPT; + cb->flags |= ATH10K_SKB_F_RAW_TX; + } + cb->vif = vif; cb->txq = txq; cb->airtime_est = airtime; @@ -3668,6 +3683,7 @@ static int ath10k_mac_tx(struct ath10k *ar, { struct ieee80211_hw *hw = ar->hw; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); int ret; /* We should disable CCK RATE due to P2P */ @@ -3685,7 +3701,8 @@ static int ath10k_mac_tx(struct ath10k *ar, ath10k_tx_h_8023(skb); break; case ATH10K_HW_TXRX_RAW: - if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { + if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) && + !(skb_cb->flags & ATH10K_SKB_F_RAW_TX)) { WARN_ON_ONCE(1); ieee80211_free_txskb(hw, skb); return -ENOTSUPP; @@ -8802,6 +8819,11 @@ int ath10k_mac_register(struct ath10k *ar) goto err_dfs_detector_exit; } + if (test_bit(WMI_SERVICE_PER_PACKET_SW_ENCRYPT, ar->wmi.svc_map)) { + ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); + ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); + } + if (!ath_is_world_regd(&ar->ath_common.regulatory)) { ret = regulatory_hint(ar->hw->wiphy, ar->ath_common.regulatory.alpha2); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 85de53af4817..5886b4c1b16b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -209,6 +209,7 @@ enum wmi_service { WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT, WMI_SERVICE_THERM_THROT, WMI_SERVICE_RTT_RESPONDER_ROLE, + WMI_SERVICE_PER_PACKET_SW_ENCRYPT, /* keep last */ WMI_SERVICE_MAX, @@ -489,6 +490,7 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI); SVCSTR(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT); SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE); + SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT); default: return NULL; @@ -586,6 +588,8 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, len); SVCMAP(WMI_10X_SERVICE_BB_TIMING_CONFIG_SUPPORT, WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT, len); + SVCMAP(WMI_10X_SERVICE_PER_PACKET_SW_ENCRYPT, + WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len); } static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out, @@ -808,6 +812,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT, len); SVCMAP(WMI_10_4_SERVICE_RTT_RESPONDER_ROLE, WMI_SERVICE_RTT_RESPONDER_ROLE, len); + SVCMAP(WMI_10_4_SERVICE_PER_PACKET_SW_ENCRYPT, + WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len); } #undef SVCMAP -- cgit v1.2.3 From bb31b7cb106c0447c5cd77ed23dda5a70cce0881 Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Mon, 11 Feb 2019 18:47:59 +0200 Subject: ath10k: report tx airtime provided by fw If supported, update transmit airtime in mac80211 with the airtime values reported by the firmware. TX airtime of the PPDU is reported via HTT data TX completion indication message. A new service flag 'WMI_SERVICE_REPORT_AIRTIME' is added to advertise the firmware support. For firmwares which do not support this feature, TX airtime is calculated in the driver using TX bitrate. Hardwares tested : QCA9984 Firmwares tested : 10.4-3.6.1-00841 Signed-off-by: Manikanta Pubbisetty Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 3 ++ drivers/net/wireless/ath/ath10k/htt.h | 21 ++++++++++++- drivers/net/wireless/ath/ath10k/htt_rx.c | 52 ++++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/mac.c | 6 +++- drivers/net/wireless/ath/ath10k/txrx.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.h | 7 +++++ 6 files changed, 86 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index d39963aacc8d..6c1dd5f8d012 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2631,6 +2631,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, ar->wmi.svc_map)) val |= WMI_10_4_TX_DATA_ACK_RSSI; + if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map)) + val |= WMI_10_4_REPORT_AIRTIME; + status = ath10k_mac_ext_resource_config(ar, val); if (status) { ath10k_err(ar, diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index f5fa86f6efad..005fad94edad 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -571,6 +571,7 @@ struct htt_mgmt_tx_completion { #define HTT_RX_INDICATION_INFO0_EXT_TID_LSB (0) #define HTT_RX_INDICATION_INFO0_FLUSH_VALID (1 << 5) #define HTT_RX_INDICATION_INFO0_RELEASE_VALID (1 << 6) +#define HTT_RX_INDICATION_INFO0_PPDU_DURATION BIT(7) #define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_MASK 0x0000003F #define HTT_RX_INDICATION_INFO1_FLUSH_START_SEQNO_LSB 0 @@ -583,7 +584,10 @@ struct htt_mgmt_tx_completion { #define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_MASK 0xFF000000 #define HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES_LSB 24 -#define HTT_TX_CMPL_FLAG_DATA_RSSI BIT(0) +#define HTT_TX_CMPL_FLAG_DATA_RSSI BIT(0) +#define HTT_TX_CMPL_FLAG_PPID_PRESENT BIT(1) +#define HTT_TX_CMPL_FLAG_PA_PRESENT BIT(2) +#define HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT BIT(3) struct htt_rx_indication_hdr { u8 info0; /* %HTT_RX_INDICATION_INFO0_ */ @@ -873,6 +877,21 @@ struct htt_data_tx_completion { __le16 msdus[0]; /* variable length based on %num_msdus */ } __packed; +#define HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK GENMASK(15, 0) +#define HTT_TX_PPDU_DUR_INFO0_TID_MASK GENMASK(20, 16) + +struct htt_data_tx_ppdu_dur { + __le32 info0; /* HTT_TX_PPDU_DUR_INFO0_ */ + __le32 tx_duration; /* in usecs */ +} __packed; + +#define HTT_TX_COMPL_PPDU_DUR_INFO0_NUM_ENTRIES_MASK GENMASK(7, 0) + +struct htt_data_tx_compl_ppdu_dur { + __le32 info0; /* HTT_TX_COMPL_PPDU_DUR_INFO0_ */ + struct htt_data_tx_ppdu_dur ppdu_dur[0]; +} __packed; + struct htt_tx_compl_ind_base { u32 hdr; u16 payload[1/*or more*/]; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 77f494d52ec3..d5c666c2504c 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2220,8 +2220,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, int status = MS(resp->data_tx_completion.flags, HTT_DATA_TX_STATUS); __le16 msdu_id, *msdus; bool rssi_enabled = false; - u8 msdu_count = 0; + u8 msdu_count = 0, num_airtime_records, tid; int i; + struct htt_data_tx_compl_ppdu_dur *ppdu_info; + struct ath10k_peer *peer; + u16 ppdu_info_offset = 0, peer_id; + u32 tx_duration; switch (status) { case HTT_DATA_TX_STATUS_NO_ACK: @@ -2245,12 +2249,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, resp->data_tx_completion.num_msdus); msdu_count = resp->data_tx_completion.num_msdus; + msdus = resp->data_tx_completion.msdus; if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI) rssi_enabled = true; for (i = 0; i < msdu_count; i++) { - msdus = resp->data_tx_completion.msdus; msdu_id = msdus[i]; tx_done.msdu_id = __le16_to_cpu(msdu_id); @@ -2282,6 +2286,50 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, ath10k_txrx_tx_unref(htt, &tx_done); } } + + if (!(resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT)) + return; + + ppdu_info_offset = (msdu_count & 0x01) ? msdu_count + 1 : msdu_count; + + if (rssi_enabled) + ppdu_info_offset += ppdu_info_offset; + + if (resp->data_tx_completion.flags2 & + (HTT_TX_CMPL_FLAG_PPID_PRESENT | HTT_TX_CMPL_FLAG_PA_PRESENT)) + ppdu_info_offset += 2; + + ppdu_info = (struct htt_data_tx_compl_ppdu_dur *)&msdus[ppdu_info_offset]; + num_airtime_records = FIELD_GET(HTT_TX_COMPL_PPDU_DUR_INFO0_NUM_ENTRIES_MASK, + __le32_to_cpu(ppdu_info->info0)); + + for (i = 0; i < num_airtime_records; i++) { + struct htt_data_tx_ppdu_dur *ppdu_dur; + u32 info0; + + ppdu_dur = &ppdu_info->ppdu_dur[i]; + info0 = __le32_to_cpu(ppdu_dur->info0); + + peer_id = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK, + info0); + rcu_read_lock(); + spin_lock_bh(&ar->data_lock); + + peer = ath10k_peer_find_by_id(ar, peer_id); + if (!peer) { + spin_unlock_bh(&ar->data_lock); + rcu_read_unlock(); + continue; + } + + tid = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_TID_MASK, info0); + tx_duration = __le32_to_cpu(ppdu_dur->tx_duration); + + ieee80211_sta_register_airtime(peer->sta, tid, tx_duration, 0); + + spin_unlock_bh(&ar->data_lock); + rcu_read_unlock(); + } } static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 22774e127507..795446d31f78 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3985,6 +3985,9 @@ static u16 ath10k_mac_update_airtime(struct ath10k *ar, if (!txq || !txq->sta) return airtime; + if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map)) + return airtime; + spin_lock_bh(&ar->data_lock); arsta = (struct ath10k_sta *)txq->sta->drv_priv; @@ -8694,7 +8697,8 @@ int ath10k_mac_register(struct ath10k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); - if (ath10k_peer_stats_enabled(ar)) + if (ath10k_peer_stats_enabled(ar) || + test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map)) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 44c13b884603..a555fa38d834 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -95,7 +95,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt, wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); - if (txq && txq->sta) + if (txq && txq->sta && skb_cb->airtime_est) ieee80211_sta_register_airtime(txq->sta, txq->tid, skb_cb->airtime_est, 0); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 5886b4c1b16b..f26dc801e3b8 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -210,6 +210,7 @@ enum wmi_service { WMI_SERVICE_THERM_THROT, WMI_SERVICE_RTT_RESPONDER_ROLE, WMI_SERVICE_PER_PACKET_SW_ENCRYPT, + WMI_SERVICE_REPORT_AIRTIME, /* keep last */ WMI_SERVICE_MAX, @@ -374,6 +375,7 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_RX_FILTER_OUT_COUNT, WMI_10_4_SERVICE_RTT_RESPONDER_ROLE, WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, + WMI_10_4_SERVICE_REPORT_AIRTIME, }; static inline char *wmi_service_name(int service_id) @@ -491,6 +493,7 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT); SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE); SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT); + SVCSTR(WMI_SERVICE_REPORT_AIRTIME); default: return NULL; @@ -814,6 +817,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_RTT_RESPONDER_ROLE, len); SVCMAP(WMI_10_4_SERVICE_PER_PACKET_SW_ENCRYPT, WMI_SERVICE_PER_PACKET_SW_ENCRYPT, len); + SVCMAP(WMI_10_4_SERVICE_REPORT_AIRTIME, + WMI_SERVICE_REPORT_AIRTIME, len); } #undef SVCMAP @@ -2989,6 +2994,8 @@ enum wmi_10_4_feature_mask { WMI_10_4_TDLS_CONN_TRACKER_IN_HOST_MODE = BIT(11), WMI_10_4_TDLS_EXPLICIT_MODE_ONLY = BIT(12), WMI_10_4_TX_DATA_ACK_RSSI = BIT(16), + WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT = BIT(17), + WMI_10_4_REPORT_AIRTIME = BIT(18), }; -- cgit v1.2.3 From 2321dd5d78fb150432083bdd17ecf19707bef1f9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 11 Feb 2019 18:48:01 +0200 Subject: ath10k: add missing values to wmi_service_name() After implementing the next patch GCC reported: drivers/net/wireless/ath/ath10k/wmi.h:385:2: warning: enumeration value 'WMI_SERVICE_BTCOEX' not handled in switch [-Wswitch] drivers/net/wireless/ath/ath10k/wmi.h:385:2: warning: enumeration value 'WMI_SERVICE_MGMT_TX_WMI' not handled in switch [-Wswitch] drivers/net/wireless/ath/ath10k/wmi.h:385:2: warning: enumeration value 'WMI_SERVICE_SPOOF_MAC_SUPPORT' not handled in switch [-Wswitch] drivers/net/wireless/ath/ath10k/wmi.h:385:2: warning: enumeration value 'WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT' not handled in switch [-Wswitch] drivers/net/wireless/ath/ath10k/wmi.h:385:2: warning: enumeration value 'WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT' not handled in switch [-Wswitch] drivers/net/wireless/ath/ath10k/wmi.h:385:2: warning: enumeration value 'WMI_SERVICE_THERM_THROT' not handled in switch [-Wswitch] Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index f26dc801e3b8..2a3cc45f3359 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -475,6 +475,7 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_TX_MODE_PUSH_PULL); SVCSTR(WMI_SERVICE_TX_MODE_DYNAMIC); SVCSTR(WMI_SERVICE_VDEV_RX_FILTER); + SVCSTR(WMI_SERVICE_BTCOEX); SVCSTR(WMI_SERVICE_CHECK_CAL_VERSION); SVCSTR(WMI_SERVICE_DBGLOG_WARN2); SVCSTR(WMI_SERVICE_BTCOEX_DUTY_CYCLE); @@ -484,13 +485,18 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_SMART_LOGGING_SUPPORT); SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE); SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY); + SVCSTR(WMI_SERVICE_MGMT_TX_WMI); SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH); SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS); SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT); SVCSTR(WMI_SERVICE_TPC_STATS_FINAL); SVCSTR(WMI_SERVICE_RESET_CHIP); + SVCSTR(WMI_SERVICE_SPOOF_MAC_SUPPORT); SVCSTR(WMI_SERVICE_TX_DATA_ACK_RSSI); SVCSTR(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT); + SVCSTR(WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT); + SVCSTR(WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT); + SVCSTR(WMI_SERVICE_THERM_THROT); SVCSTR(WMI_SERVICE_RTT_RESPONDER_ROLE); SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT); SVCSTR(WMI_SERVICE_REPORT_AIRTIME); -- cgit v1.2.3 From 95cccf4d79fec4186b6a0d0723b4bc2c07282c0a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 11 Feb 2019 18:48:04 +0200 Subject: ath10k: make wmi_service_name() warn about missing service ids When adding a new value to enum wmi_service it's very easy to miss that the new value should be also added to wmi_service_name() mapping function. Modify the function so that GCC can now warn about this: drivers/net/wireless/ath/ath10k/wmi.h:385:2: warning: enumeration value 'WMI_SERVICE_FOO' not handled in switch [-Wswitch] And also add a reminder to the enum. Thanks to Jouni Malinen for the idea. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 2a3cc45f3359..370124eb4fd8 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -212,6 +212,8 @@ enum wmi_service { WMI_SERVICE_PER_PACKET_SW_ENCRYPT, WMI_SERVICE_REPORT_AIRTIME, + /* Remember to add the new value to wmi_service_name()! */ + /* keep last */ WMI_SERVICE_MAX, }; @@ -378,7 +380,7 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_REPORT_AIRTIME, }; -static inline char *wmi_service_name(int service_id) +static inline char *wmi_service_name(enum wmi_service service_id) { #define SVCSTR(x) case x: return #x @@ -501,11 +503,13 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_PER_PACKET_SW_ENCRYPT); SVCSTR(WMI_SERVICE_REPORT_AIRTIME); - default: + case WMI_SERVICE_MAX: return NULL; } #undef SVCSTR + + return NULL; } #define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \ -- cgit v1.2.3 From db3b6280f5f1a8bd91c97bfb344bfc80655d07b2 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 11 Feb 2019 18:48:06 +0200 Subject: ath10k: change wmi.h to include only ieee80211.h wmi.h does not use anything from mac80211.h so change it to include only ieee80211.h. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 370124eb4fd8..0e2787821121 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -20,7 +20,7 @@ #define _WMI_H_ #include -#include +#include /* * This file specifies the WMI interface for the Unified Software -- cgit v1.2.3 From 385bd8816cb517efc7fdd0a5d4081c76b16d5da1 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 11 Feb 2019 18:48:08 +0200 Subject: ath10k: align ath10k_htt_txbuf structures With W=1 GCC warns: drivers/net/wireless/ath/ath10k/htt.h:1746:1: warning: alignment 1 of 'struct ath10k_htt_txbuf_32' is less than 4 [-Wpacked-not-aligned] drivers/net/wireless/ath/ath10k/htt.h:1753:1: warning: alignment 1 of 'struct ath10k_htt_txbuf_64' is less than 4 [-Wpacked-not-aligned] Fix that by using __align(4). Compile tested only. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 005fad94edad..d194bbe18fc3 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1743,14 +1743,14 @@ struct ath10k_htt_txbuf_32 { struct ath10k_htc_hdr htc_hdr; struct htt_cmd_hdr cmd_hdr; struct htt_data_tx_desc cmd_tx; -} __packed; +} __packed __aligned(4); struct ath10k_htt_txbuf_64 { struct htt_data_tx_desc_frag frags[2]; struct ath10k_htc_hdr htc_hdr; struct htt_cmd_hdr cmd_hdr; struct htt_data_tx_desc_64 cmd_tx; -} __packed; +} __packed __aligned(4); struct ath10k_htt { struct ath10k *ar; -- cgit v1.2.3 From bdf2bd9aa684511bcb4271f185f735525ca27a70 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 11 Feb 2019 18:48:11 +0200 Subject: ath10k: fix documentation in ath10k_wow_convert_8023_to_80211() With W=1 there's a warning: drivers/net/wireless/ath/ath10k/wow.c:93: warning: Function parameter or member 'new' not described in 'ath10k_wow_convert_8023_to_80211' drivers/net/wireless/ath/ath10k/wow.c:93: warning: Function parameter or member 'old' not described in 'ath10k_wow_convert_8023_to_80211' Fix it by changing the documentation marker '/**' to a normal code comment. While at it, clean up the line wrapping. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wow.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c index 36d4245c308e..b36fa0f8892e 100644 --- a/drivers/net/wireless/ath/ath10k/wow.c +++ b/drivers/net/wireless/ath/ath10k/wow.c @@ -77,7 +77,7 @@ static int ath10k_wow_cleanup(struct ath10k *ar) return 0; } -/** +/* * Convert a 802.3 format to a 802.11 format. * +------------+-----------+--------+----------------+ * 802.3: |dest mac(6B)|src mac(6B)|type(2B)| body... | @@ -88,9 +88,8 @@ static int ath10k_wow_cleanup(struct ath10k *ar) * 802.11: |4B|dest mac(6B)| 6B |src mac(6B)| 8B |type(2B)| body... | * +--+------------+----+-----------+---------------+-----------+ */ -static void ath10k_wow_convert_8023_to_80211 - (struct cfg80211_pkt_pattern *new, - const struct cfg80211_pkt_pattern *old) +static void ath10k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new, + const struct cfg80211_pkt_pattern *old) { u8 hdr_8023_pattern[ETH_HLEN] = {}; u8 hdr_8023_bit_mask[ETH_HLEN] = {}; -- cgit v1.2.3 From 01dc76dfdc917282121220abcc2ae0e7308b441f Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 11 Feb 2019 18:48:13 +0200 Subject: ath10k: copy the whole struct ath10k_bus_params in ath10k_core_register() Instead of copying fields one by one copy the whole structure. This way there's no need to modify the function every time we add a new field to the struct. Compile tested only. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 6c1dd5f8d012..a1b2aea4a77f 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2997,9 +2997,8 @@ err: int ath10k_core_register(struct ath10k *ar, const struct ath10k_bus_params *bus_params) { - ar->bus_param.chip_id = bus_params->chip_id; - ar->bus_param.dev_type = bus_params->dev_type; - ar->bus_param.link_can_suspend = bus_params->link_can_suspend; + ar->bus_param = *bus_params; + queue_work(ar->workqueue, &ar->register_work); return 0; -- cgit v1.2.3 From bd3606c29fccd0fe3d1061a61811cabf1abf7110 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 12 Feb 2019 13:39:05 -0800 Subject: rocker: Remove port_attr_bridge_flags_get assignment After 610d2b601bba ("rocker: Remove getting PORT_BRIDGE_FLAGS") we no longer have a port_attr_bridge_flags_get member in the rocker_world_ops structre, fix that. Fixes: 610d2b601bba ("rocker: Remove getting PORT_BRIDGE_FLAGS") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker_ofdpa.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c index 9c07f6040720..fa296a7c255d 100644 --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c @@ -2813,7 +2813,6 @@ struct rocker_world_ops rocker_ofdpa_ops = { .port_stop = ofdpa_port_stop, .port_attr_stp_state_set = ofdpa_port_attr_stp_state_set, .port_attr_bridge_flags_set = ofdpa_port_attr_bridge_flags_set, - .port_attr_bridge_flags_get = ofdpa_port_attr_bridge_flags_get, .port_attr_bridge_flags_support_get = ofdpa_port_attr_bridge_flags_support_get, .port_attr_bridge_ageing_time_set = ofdpa_port_attr_bridge_ageing_time_set, .port_obj_vlan_add = ofdpa_port_obj_vlan_add, -- cgit v1.2.3 From 0f56623dc48aaee2ead9d61098fc6c2a2d864c78 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 12 Feb 2019 15:39:58 -0800 Subject: mlxsw: spectrum_switchdev: Remove unused variables After 1ecb195753a1 ("mlxsw: spectrum_switchdev: Remove getting PORT_BRIDGE_FLAGS") we are not accessing any driver private data structure, so the mlxsw_sp_port and mlxsw_sp variables are unused. Fixes: 1ecb195753a1 ("mlxsw: spectrum_switchdev: Remove getting PORT_BRIDGE_FLAGS") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 4c5780f8f4b2..1f492b7dbea8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -434,9 +434,6 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan) static int mlxsw_sp_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { - struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - switch (attr->id) { case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD | -- cgit v1.2.3 From fd80a14363eec09cef018dc8a1074efc298a0a07 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 12 Feb 2019 15:39:59 -0800 Subject: staging: fsl-dpaa2: ethsw: Remove unused port_priv variable After 1b8b589d9103 ("staging: fsl-dpaa2: ethsw: Remove getting PORT_BRIDGE_FLAGS") we are not accessing any driver private data anymore, remove port_priv which is unused. Fixes: 1b8b589d9103 ("staging: fsl-dpaa2: ethsw: Remove getting PORT_BRIDGE_FLAGS") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index e5a14c7c777f..1b3943b71254 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -643,8 +643,6 @@ static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev) static int swdev_port_attr_get(struct net_device *netdev, struct switchdev_attr *attr) { - struct ethsw_port_priv *port_priv = netdev_priv(netdev); - switch (attr->id) { case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD; -- cgit v1.2.3 From 224d71ccc07c6b221e4fdff7cd3d04c6033228c5 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Mon, 11 Feb 2019 13:56:07 +0200 Subject: net/mlx5: Align ODP capability function with netdev coding style Update newly introduced function to be aligned to netdev coding style. Fixes: 46861e3e88be ("net/mlx5: Set ODP SRQ support in firmware") Reported-by: Saeed Mahameed Signed-off-by: Leon Romanovsky --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index e38aa206ab6d..6d45518edbdc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -461,9 +461,9 @@ static int handle_hca_cap_atomic(struct mlx5_core_dev *dev) static int handle_hca_cap_odp(struct mlx5_core_dev *dev) { - void *set_ctx; void *set_hca_cap; - int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); + void *set_ctx; + int set_sz; int err; if (!MLX5_CAP_GEN(dev, pg)) @@ -473,15 +473,12 @@ static int handle_hca_cap_odp(struct mlx5_core_dev *dev) if (err) return err; - /** - * If all bits are cleared we shouldn't try to set it - * or we might fail while trying to access a reserved bit. - */ if (!(MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive) || MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive) || MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive))) return 0; + set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); set_ctx = kzalloc(set_sz, GFP_KERNEL); if (!set_ctx) return -ENOMEM; @@ -492,13 +489,13 @@ static int handle_hca_cap_odp(struct mlx5_core_dev *dev) /* set ODP SRQ support for RC/UD and XRC transports */ MLX5_SET(odp_cap, set_hca_cap, ud_odp_caps.srq_receive, - (MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive))); + MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive)); MLX5_SET(odp_cap, set_hca_cap, rc_odp_caps.srq_receive, - (MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive))); + MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive)); MLX5_SET(odp_cap, set_hca_cap, xrc_odp_caps.srq_receive, - (MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive))); + MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive)); err = set_caps(dev, set_ctx, set_sz, MLX5_SET_HCA_CAP_OP_MOD_ODP); -- cgit v1.2.3 From a4eaed9f9a895b16bb2c54e0ff6b3c99404fec92 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Mon, 11 Feb 2019 15:25:26 +0100 Subject: net: phy: Mask-out non-compatible modes when setting the max-speed When setting a PHY's max speed using either the max-speed DT property or ethtool, we should mask-out all non-compatible modes according to the settings table, instead of just the 10/100BASET modes. Signed-off-by: Maxime Chevallier Suggested-by: Russell King Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy-core.c | 45 +++++++++++++++++++++++++++++++++++++ drivers/net/phy/phy_device.c | 53 -------------------------------------------- include/linux/phy.h | 1 + 3 files changed, 46 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index cdea028d1328..855abf487279 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -4,6 +4,7 @@ */ #include #include +#include const char *phy_speed_to_str(int speed) { @@ -338,6 +339,50 @@ size_t phy_speeds(unsigned int *speeds, size_t size, return count; } +static int __set_phy_supported(struct phy_device *phydev, u32 max_speed) +{ + const struct phy_setting *p; + int i; + + for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) { + if (p->speed > max_speed) + linkmode_clear_bit(p->bit, phydev->supported); + else + break; + } + + return 0; +} + +int phy_set_max_speed(struct phy_device *phydev, u32 max_speed) +{ + int err; + + err = __set_phy_supported(phydev, max_speed); + if (err) + return err; + + linkmode_copy(phydev->advertising, phydev->supported); + + return 0; +} +EXPORT_SYMBOL(phy_set_max_speed); + +void of_set_phy_supported(struct phy_device *phydev) +{ + struct device_node *node = phydev->mdio.dev.of_node; + u32 max_speed; + + if (!IS_ENABLED(CONFIG_OF_MDIO)) + return; + + if (!node) + return; + + if (!of_property_read_u32(node, "max-speed", &max_speed)) + __set_phy_supported(phydev, max_speed); +} + /** * phy_resolve_aneg_linkmode - resolve the advertisements into phy settings * @phydev: The phy_device struct diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2c61282a2726..64497ec293e1 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1949,44 +1949,6 @@ int genphy_loopback(struct phy_device *phydev, bool enable) } EXPORT_SYMBOL(genphy_loopback); -static int __set_phy_supported(struct phy_device *phydev, u32 max_speed) -{ - switch (max_speed) { - case SPEED_10: - linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, - phydev->supported); - linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, - phydev->supported); - /* fall through */ - case SPEED_100: - linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, - phydev->supported); - linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - phydev->supported); - break; - case SPEED_1000: - break; - default: - return -ENOTSUPP; - } - - return 0; -} - -int phy_set_max_speed(struct phy_device *phydev, u32 max_speed) -{ - int err; - - err = __set_phy_supported(phydev, max_speed); - if (err) - return err; - - linkmode_copy(phydev->advertising, phydev->supported); - - return 0; -} -EXPORT_SYMBOL(phy_set_max_speed); - /** * phy_remove_link_mode - Remove a supported link mode * @phydev: phy_device structure to remove link mode from @@ -2117,21 +2079,6 @@ bool phy_validate_pause(struct phy_device *phydev, } EXPORT_SYMBOL(phy_validate_pause); -static void of_set_phy_supported(struct phy_device *phydev) -{ - struct device_node *node = phydev->mdio.dev.of_node; - u32 max_speed; - - if (!IS_ENABLED(CONFIG_OF_MDIO)) - return; - - if (!node) - return; - - if (!of_property_read_u32(node, "max-speed", &max_speed)) - __set_phy_supported(phydev, max_speed); -} - static void of_set_phy_eee_broken(struct phy_device *phydev) { struct device_node *node = phydev->mdio.dev.of_node; diff --git a/include/linux/phy.h b/include/linux/phy.h index 378da9a6165e..20344c7744d8 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -673,6 +673,7 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact); size_t phy_speeds(unsigned int *speeds, size_t size, unsigned long *mask); +void of_set_phy_supported(struct phy_device *phydev); static inline bool __phy_is_started(struct phy_device *phydev) { -- cgit v1.2.3 From 3feb9b23bf4cbf9f34568035170c6f1c25416523 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Mon, 11 Feb 2019 15:25:27 +0100 Subject: net: phy: Move of_set_phy_eee_broken to phy-core.c Since of_set_phy_supported was moved to phy-core.c, we can also move of_set_phy_eee_broken to the same location, so that we have all OF functions in the same place. This patch doesn't intend to introduce any change in behaviour. Signed-off-by: Maxime Chevallier Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy-core.c | 27 +++++++++++++++++++++++++++ drivers/net/phy/phy_device.c | 28 ---------------------------- include/linux/phy.h | 1 + 3 files changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index 855abf487279..de58a59815d5 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -383,6 +383,33 @@ void of_set_phy_supported(struct phy_device *phydev) __set_phy_supported(phydev, max_speed); } +void of_set_phy_eee_broken(struct phy_device *phydev) +{ + struct device_node *node = phydev->mdio.dev.of_node; + u32 broken = 0; + + if (!IS_ENABLED(CONFIG_OF_MDIO)) + return; + + if (!node) + return; + + if (of_property_read_bool(node, "eee-broken-100tx")) + broken |= MDIO_EEE_100TX; + if (of_property_read_bool(node, "eee-broken-1000t")) + broken |= MDIO_EEE_1000T; + if (of_property_read_bool(node, "eee-broken-10gt")) + broken |= MDIO_EEE_10GT; + if (of_property_read_bool(node, "eee-broken-1000kx")) + broken |= MDIO_EEE_1000KX; + if (of_property_read_bool(node, "eee-broken-10gkx4")) + broken |= MDIO_EEE_10GKX4; + if (of_property_read_bool(node, "eee-broken-10gkr")) + broken |= MDIO_EEE_10GKR; + + phydev->eee_broken_modes = broken; +} + /** * phy_resolve_aneg_linkmode - resolve the advertisements into phy settings * @phydev: The phy_device struct diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 64497ec293e1..a752de2fff5e 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -30,7 +30,6 @@ #include #include #include -#include MODULE_DESCRIPTION("PHY library"); MODULE_AUTHOR("Andy Fleming"); @@ -2079,33 +2078,6 @@ bool phy_validate_pause(struct phy_device *phydev, } EXPORT_SYMBOL(phy_validate_pause); -static void of_set_phy_eee_broken(struct phy_device *phydev) -{ - struct device_node *node = phydev->mdio.dev.of_node; - u32 broken = 0; - - if (!IS_ENABLED(CONFIG_OF_MDIO)) - return; - - if (!node) - return; - - if (of_property_read_bool(node, "eee-broken-100tx")) - broken |= MDIO_EEE_100TX; - if (of_property_read_bool(node, "eee-broken-1000t")) - broken |= MDIO_EEE_1000T; - if (of_property_read_bool(node, "eee-broken-10gt")) - broken |= MDIO_EEE_10GT; - if (of_property_read_bool(node, "eee-broken-1000kx")) - broken |= MDIO_EEE_1000KX; - if (of_property_read_bool(node, "eee-broken-10gkx4")) - broken |= MDIO_EEE_10GKX4; - if (of_property_read_bool(node, "eee-broken-10gkr")) - broken |= MDIO_EEE_10GKR; - - phydev->eee_broken_modes = broken; -} - static bool phy_drv_supports_irq(struct phy_driver *phydrv) { return phydrv->config_intr && phydrv->ack_interrupt; diff --git a/include/linux/phy.h b/include/linux/phy.h index 20344c7744d8..1a1d93a2a906 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -674,6 +674,7 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask, size_t phy_speeds(unsigned int *speeds, size_t size, unsigned long *mask); void of_set_phy_supported(struct phy_device *phydev); +void of_set_phy_eee_broken(struct phy_device *phydev); static inline bool __phy_is_started(struct phy_device *phydev) { -- cgit v1.2.3 From ac3f5533343f6ec7fa24a27f0ae22bbfd27e0b23 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Mon, 11 Feb 2019 15:25:28 +0100 Subject: net: phy: Extract genphy_c45_pma_read_abilities from marvell10g Marvell 10G PHY driver has a generic way of initializing the supported link modes by reading the PHY's C45 PMA abilities. This can be made generic, since these registers are part of the 802.3 specifications. This commit extracts the config_init link_mode initialization code from marvell10g and uses it to introduce the genphy_c45_pma_read_abilities function. Only PMA modes are read, it's still up to the caller to set the Pause parameters. Signed-off-by: Maxime Chevallier Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 78 +++++--------------------------------------- drivers/net/phy/phy-c45.c | 74 +++++++++++++++++++++++++++++++++++++++++ include/linux/phy.h | 1 + 3 files changed, 83 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 08362dc657cd..496805c0ddfe 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -233,8 +233,7 @@ static int mv3310_resume(struct phy_device *phydev) static int mv3310_config_init(struct phy_device *phydev) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; - int val; + int ret, val; /* Check that the PHY interface type is compatible */ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && @@ -243,8 +242,8 @@ static int mv3310_config_init(struct phy_device *phydev) phydev->interface != PHY_INTERFACE_MODE_10GKR) return -ENODEV; - __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported); - __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported); + __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported); + __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported); if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) { val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); @@ -252,74 +251,13 @@ static int mv3310_config_init(struct phy_device *phydev) return val; if (val & MDIO_AN_STAT1_ABLE) - __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported); + __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + phydev->supported); } - val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2); - if (val < 0) - return val; - - /* Ethtool does not support the WAN mode bits */ - if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR | - MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 | - MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW | - MDIO_PMA_STAT2_10GBEW)) - __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported); - if (val & MDIO_PMA_STAT2_10GBSR) - __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported); - if (val & MDIO_PMA_STAT2_10GBLR) - __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported); - if (val & MDIO_PMA_STAT2_10GBER) - __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported); - - if (val & MDIO_PMA_STAT2_EXTABLE) { - val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE); - if (val < 0) - return val; - - if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT | - MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT)) - __set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported); - if (val & MDIO_PMA_EXTABLE_10GBLRM) - __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported); - if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR | - MDIO_PMA_EXTABLE_1000BKX)) - __set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported); - if (val & MDIO_PMA_EXTABLE_10GBLRM) - __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, - supported); - if (val & MDIO_PMA_EXTABLE_10GBT) - __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, - supported); - if (val & MDIO_PMA_EXTABLE_10GBKX4) - __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, - supported); - if (val & MDIO_PMA_EXTABLE_10GBKR) - __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, - supported); - if (val & MDIO_PMA_EXTABLE_1000BT) - __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - supported); - if (val & MDIO_PMA_EXTABLE_1000BKX) - __set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, - supported); - if (val & MDIO_PMA_EXTABLE_100BTX) { - __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, - supported); - __set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, - supported); - } - if (val & MDIO_PMA_EXTABLE_10BT) { - __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, - supported); - __set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, - supported); - } - } - - linkmode_copy(phydev->supported, supported); - linkmode_and(phydev->advertising, phydev->advertising, - phydev->supported); + ret = genphy_c45_pma_read_abilities(phydev); + if (ret) + return ret; return 0; } diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index eff9e5a4d831..6f028de4dae1 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -271,6 +271,80 @@ int genphy_c45_read_mdix(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(genphy_c45_read_mdix); +/** + * genphy_c45_pma_read_abilities - read supported link modes from PMA + * @phydev: target phy_device struct + * + * Read the supported link modes from the PMA Status 2 (1.8) register. If bit + * 1.8.9 is set, the list of supported modes is build using the values in the + * PMA Extended Abilities (1.11) register, indicating 1000BASET an 10G related + * modes. If bit 1.11.14 is set, then the list is also extended with the modes + * in the 2.5G/5G PMA Extended register (1.21), indicating if 2.5GBASET and + * 5GBASET are supported. + */ +int genphy_c45_pma_read_abilities(struct phy_device *phydev) +{ + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + phydev->supported, + val & MDIO_PMA_STAT2_10GBSR); + + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + phydev->supported, + val & MDIO_PMA_STAT2_10GBLR); + + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, + phydev->supported, + val & MDIO_PMA_STAT2_10GBER); + + if (val & MDIO_PMA_STAT2_EXTABLE) { + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_10GBLRM); + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_10GBT); + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_10GBKX4); + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_10GBKR); + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_1000BT); + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_1000BKX); + + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_100BTX); + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_100BTX); + + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_10BT); + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, + phydev->supported, + val & MDIO_PMA_EXTABLE_10BT); + } + + return 0; +} +EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities); + /* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev) diff --git a/include/linux/phy.h b/include/linux/phy.h index 1a1d93a2a906..177a330d84e5 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1116,6 +1116,7 @@ int genphy_c45_read_pma(struct phy_device *phydev); int genphy_c45_pma_setup_forced(struct phy_device *phydev); int genphy_c45_an_disable_aneg(struct phy_device *phydev); int genphy_c45_read_mdix(struct phy_device *phydev); +int genphy_c45_pma_read_abilities(struct phy_device *phydev); /* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev); -- cgit v1.2.3 From 7fd8afa8933a095a97995885740999f174e61b60 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Mon, 11 Feb 2019 15:25:29 +0100 Subject: net: phy: Add generic support for 2.5GBaseT and 5GBaseT The 802.3bz specification, based on previous by the NBASET alliance, defines the 2.5GBaseT and 5GBaseT link modes for ethernet traffic on cat5e, cat6 and cat7 cables. These mode integrate with the already defined C45 MDIO PMA/PMD registers set that added 10G support, by defining some previously reserved bits, and adding a new register (2.5G/5G Extended abilities). This commit adds the required definitions in include/uapi/linux/mdio.h to support these modes, and detect when a link-partner advertises them. It also adds support for these mode in the generic C45 PHY infrastructure. Signed-off-by: Maxime Chevallier Reviewed-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 37 +++++++++++++++++++++++++++++++++++++ include/uapi/linux/mdio.h | 16 ++++++++++++++++ 2 files changed, 53 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 6f028de4dae1..7af5fa81daf6 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -47,6 +47,16 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev) /* Assume 1000base-T */ ctrl2 |= MDIO_PMA_CTRL2_1000BT; break; + case SPEED_2500: + ctrl1 |= MDIO_CTRL1_SPEED2_5G; + /* Assume 2.5Gbase-T */ + ctrl2 |= MDIO_PMA_CTRL2_2_5GBT; + break; + case SPEED_5000: + ctrl1 |= MDIO_CTRL1_SPEED5G; + /* Assume 5Gbase-T */ + ctrl2 |= MDIO_PMA_CTRL2_5GBT; + break; case SPEED_10000: ctrl1 |= MDIO_CTRL1_SPEED10G; /* Assume 10Gbase-T */ @@ -194,6 +204,12 @@ int genphy_c45_read_lpa(struct phy_device *phydev) if (val < 0) return val; + if (val & MDIO_AN_10GBT_STAT_LP2_5G) + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->lp_advertising); + if (val & MDIO_AN_10GBT_STAT_LP5G) + linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + phydev->lp_advertising); if (val & MDIO_AN_10GBT_STAT_LP10G) linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, phydev->lp_advertising); @@ -224,6 +240,12 @@ int genphy_c45_read_pma(struct phy_device *phydev) case MDIO_PMA_CTRL1_SPEED1000: phydev->speed = SPEED_1000; break; + case MDIO_CTRL1_SPEED2_5G: + phydev->speed = SPEED_2500; + break; + case MDIO_CTRL1_SPEED5G: + phydev->speed = SPEED_5000; + break; case MDIO_CTRL1_SPEED10G: phydev->speed = SPEED_10000; break; @@ -339,6 +361,21 @@ int genphy_c45_pma_read_abilities(struct phy_device *phydev) linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, phydev->supported, val & MDIO_PMA_EXTABLE_10BT); + + if (val & MDIO_PMA_EXTABLE_NBT) { + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, + MDIO_PMA_NG_EXTABLE); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->supported, + val & MDIO_PMA_NG_EXTABLE_2_5GBT); + + linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + phydev->supported, + val & MDIO_PMA_NG_EXTABLE_5GBT); + } } return 0; diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h index 0e012b168e4d..0a552061ff1c 100644 --- a/include/uapi/linux/mdio.h +++ b/include/uapi/linux/mdio.h @@ -45,6 +45,7 @@ #define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */ #define MDIO_AN_LPA 19 /* AN LP abilities (base page) */ #define MDIO_PCS_EEE_ABLE 20 /* EEE Capability register */ +#define MDIO_PMA_NG_EXTABLE 21 /* 2.5G/5G PMA/PMD extended ability */ #define MDIO_PCS_EEE_WK_ERR 22 /* EEE wake error counter */ #define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */ #define MDIO_AN_EEE_ADV 60 /* EEE advertisement */ @@ -92,6 +93,10 @@ #define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00) /* 10PASS-TS/2BASE-TL */ #define MDIO_CTRL1_SPEED10P2B (MDIO_CTRL1_SPEEDSELEXT | 0x04) +/* 2.5 Gb/s */ +#define MDIO_CTRL1_SPEED2_5G (MDIO_CTRL1_SPEEDSELEXT | 0x18) +/* 5 Gb/s */ +#define MDIO_CTRL1_SPEED5G (MDIO_CTRL1_SPEEDSELEXT | 0x1c) /* Status register 1. */ #define MDIO_STAT1_LPOWERABLE 0x0002 /* Low-power ability */ @@ -145,6 +150,8 @@ #define MDIO_PMA_CTRL2_1000BKX 0x000d /* 1000BASE-KX type */ #define MDIO_PMA_CTRL2_100BTX 0x000e /* 100BASE-TX type */ #define MDIO_PMA_CTRL2_10BT 0x000f /* 10BASE-T type */ +#define MDIO_PMA_CTRL2_2_5GBT 0x0030 /* 2.5GBaseT type */ +#define MDIO_PMA_CTRL2_5GBT 0x0031 /* 5GBaseT type */ #define MDIO_PCS_CTRL2_TYPE 0x0003 /* PCS type selection */ #define MDIO_PCS_CTRL2_10GBR 0x0000 /* 10GBASE-R type */ #define MDIO_PCS_CTRL2_10GBX 0x0001 /* 10GBASE-X type */ @@ -198,6 +205,7 @@ #define MDIO_PMA_EXTABLE_1000BKX 0x0040 /* 1000BASE-KX ability */ #define MDIO_PMA_EXTABLE_100BTX 0x0080 /* 100BASE-TX ability */ #define MDIO_PMA_EXTABLE_10BT 0x0100 /* 10BASE-T ability */ +#define MDIO_PMA_EXTABLE_NBT 0x4000 /* 2.5/5GBASE-T ability */ /* PHY XGXS lane state register. */ #define MDIO_PHYXS_LNSTAT_SYNC0 0x0001 @@ -234,9 +242,13 @@ #define MDIO_PCS_10GBRT_STAT2_BER 0x3f00 /* AN 10GBASE-T control register. */ +#define MDIO_AN_10GBT_CTRL_ADV2_5G 0x0080 /* Advertise 2.5GBASE-T */ +#define MDIO_AN_10GBT_CTRL_ADV5G 0x0100 /* Advertise 5GBASE-T */ #define MDIO_AN_10GBT_CTRL_ADV10G 0x1000 /* Advertise 10GBASE-T */ /* AN 10GBASE-T status register. */ +#define MDIO_AN_10GBT_STAT_LP2_5G 0x0020 /* LP is 2.5GBT capable */ +#define MDIO_AN_10GBT_STAT_LP5G 0x0040 /* LP is 5GBT capable */ #define MDIO_AN_10GBT_STAT_LPTRR 0x0200 /* LP training reset req. */ #define MDIO_AN_10GBT_STAT_LPLTABLE 0x0400 /* LP loop timing ability */ #define MDIO_AN_10GBT_STAT_LP10G 0x0800 /* LP is 10GBT capable */ @@ -265,6 +277,10 @@ #define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */ #define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */ +/* 2.5G/5G Extended abilities register. */ +#define MDIO_PMA_NG_EXTABLE_2_5GBT 0x0001 /* 2.5GBASET ability */ +#define MDIO_PMA_NG_EXTABLE_5GBT 0x0002 /* 5GBASET ability */ + /* LASI RX_ALARM control/status registers. */ #define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */ #define MDIO_PMA_LASI_RX_PCSLFLT 0x0008 /* PCS RX local fault */ -- cgit v1.2.3 From 46befd3249d72fb8dfce6d1c019511c247245ba6 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 12 Feb 2019 23:47:31 +0800 Subject: net: neterion: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/neterion/s2io.c | 2 +- drivers/net/ethernet/neterion/vxge/vxge-main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 82be90075695..feda9644289d 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -3055,7 +3055,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data) /* Updating the statistics block */ swstats->mem_freed += skb->truesize; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); get_info.offset++; if (get_info.offset == get_info.fifo_len + 1) diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 0da7393b2ef3..b877acec5cde 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -114,7 +114,7 @@ static inline void VXGE_COMPLETE_VPATH_TX(struct vxge_fifo *fifo) /* free SKBs */ for (temp = completed; temp != skb_ptr; temp++) - dev_kfree_skb_irq(*temp); + dev_consume_skb_irq(*temp); } while (more); } -- cgit v1.2.3 From eae15bdc2a0c13e5d908e5c41702fdf0076e218a Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 12 Feb 2019 23:49:57 +0800 Subject: net: qualcomm: emac: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in emac_mac_tx_process() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/qualcomm/emac/emac-mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index 8d790313ee3d..20d2400ad300 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -1204,7 +1204,7 @@ void emac_mac_tx_process(struct emac_adapter *adpt, struct emac_tx_queue *tx_q) if (tpbuf->skb) { pkts_compl++; bytes_compl += tpbuf->skb->len; - dev_kfree_skb_irq(tpbuf->skb); + dev_consume_skb_irq(tpbuf->skb); tpbuf->skb = NULL; } -- cgit v1.2.3 From d270f67d325ca709f3f98d5965e401235e6e4422 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 12 Feb 2019 23:51:45 +0800 Subject: net: atheros: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 2 +- drivers/net/ethernet/atheros/atlx/atl1.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 3164aad29bcf..9dfe6a9431e6 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -1259,7 +1259,7 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter) } if (tx_buffer->skb) { - dev_kfree_skb_irq(tx_buffer->skb); + dev_consume_skb_irq(tx_buffer->skb); tx_buffer->skb = NULL; } diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index 63edc5706c09..9e07b469066a 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -2088,7 +2088,7 @@ static int atl1_intr_tx(struct atl1_adapter *adapter) } if (buffer_info->skb) { - dev_kfree_skb_irq(buffer_info->skb); + dev_consume_skb_irq(buffer_info->skb); buffer_info->skb = NULL; } -- cgit v1.2.3 From 5f5a8c75daed965a3631ab98a783846260d2729d Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 12 Feb 2019 23:52:53 +0800 Subject: net: apple: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in mace_interrupt() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/apple/mace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c index 68b9ee489489..4d9819d2894d 100644 --- a/drivers/net/ethernet/apple/mace.c +++ b/drivers/net/ethernet/apple/mace.c @@ -764,7 +764,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id) dev->stats.tx_bytes += mp->tx_bufs[i]->len; ++dev->stats.tx_packets; } - dev_kfree_skb_irq(mp->tx_bufs[i]); + dev_consume_skb_irq(mp->tx_bufs[i]); --mp->tx_active; if (++i >= N_TX_RING) i = 0; -- cgit v1.2.3 From 412261d5c901472b025c8dcea173997209f28ab2 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 12 Feb 2019 23:56:00 +0800 Subject: net: moxa: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in moxart_tx_finished() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/moxa/moxart_ether.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index 00dec0ffb11b..e1651756bf9d 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -300,7 +300,7 @@ static void moxart_tx_finished(struct net_device *ndev) ndev->stats.tx_packets++; ndev->stats.tx_bytes += priv->tx_skb[tx_tail]->len; - dev_kfree_skb_irq(priv->tx_skb[tx_tail]); + dev_consume_skb_irq(priv->tx_skb[tx_tail]); priv->tx_skb[tx_tail] = NULL; tx_tail = TX_NEXT(tx_tail); -- cgit v1.2.3 From 8f5eeb9097fc46bd68a95870cbf2d04de3c4f968 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 12 Feb 2019 23:56:53 +0800 Subject: net: fealnx: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in intr_handler() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/fealnx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index ae55da60ed0e..c24fd56a2c71 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c @@ -1531,7 +1531,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) /* Free the original skb. */ pci_unmap_single(np->pci_dev, np->cur_tx->buffer, np->cur_tx->skbuff->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(np->cur_tx->skbuff); + dev_consume_skb_irq(np->cur_tx->skbuff); np->cur_tx->skbuff = NULL; --np->really_tx_count; if (np->cur_tx->control & TXLD) { -- cgit v1.2.3 From e78042eb6e2d831f9e616d7cfa1dce3021504b5d Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Tue, 12 Feb 2019 23:59:04 +0800 Subject: net: sis: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/sis/sis190.c | 2 +- drivers/net/ethernet/sis/sis900.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c index 808cf9816673..5b351beb78cb 100644 --- a/drivers/net/ethernet/sis/sis190.c +++ b/drivers/net/ethernet/sis/sis190.c @@ -714,7 +714,7 @@ static void sis190_tx_interrupt(struct net_device *dev, sis190_unmap_tx_skb(tp->pci_dev, skb, txd); tp->Tx_skbuff[entry] = NULL; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); } if (tp->dirty_tx != dirty_tx) { diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 4bb89f74742c..6073387511f8 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -1927,7 +1927,7 @@ static void sis900_finish_xmit (struct net_device *net_dev) pci_unmap_single(sis_priv->pci_dev, sis_priv->tx_ring[entry].bufptr, skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); sis_priv->tx_skbuff[entry] = NULL; sis_priv->tx_ring[entry].bufptr = 0; sis_priv->tx_ring[entry].cmdsts = 0; -- cgit v1.2.3 From b9560a22a440a8813e613226c730d38cbbdb39eb Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 00:00:02 +0800 Subject: net: macb: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in at91ether_interrupt() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Reviewed-by: Claudiu Beznea Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 4d1509f431d7..0d6288dd609a 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3763,7 +3763,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id) dev->stats.tx_errors++; if (lp->skb) { - dev_kfree_skb_irq(lp->skb); + dev_consume_skb_irq(lp->skb); lp->skb = NULL; dma_unmap_single(&lp->pdev->dev, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE); -- cgit v1.2.3 From 88e425843ee26f80b82d984e8ec4b662c38eb0ed Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 00:01:11 +0800 Subject: net: ixp4xx_eth: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in eth_txdone_irq() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/xscale/ixp4xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index aee55c03def0..ed6623a9801e 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -139,7 +139,7 @@ #ifdef __ARMEB__ typedef struct sk_buff buffer_t; #define free_buffer dev_kfree_skb -#define free_buffer_irq dev_kfree_skb_irq +#define free_buffer_irq dev_consume_skb_irq #else typedef void buffer_t; #define free_buffer kfree -- cgit v1.2.3 From 01e3497163eadaed0bd404bf6d36210cecf591d5 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 12 Feb 2019 16:01:53 +0000 Subject: qed: fix indentation issue with statements in an if-block There are some statements in an if-block that are not correctly indented. Fix these. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_cxt.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index 35c9f484eb9f..e61d1d905415 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -2135,12 +2135,12 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn, u32 rdma_tasks) struct qed_eth_pf_params *p_params = &p_hwfn->pf_params.eth_pf_params; - if (!p_params->num_vf_cons) - p_params->num_vf_cons = - ETH_PF_PARAMS_VF_CONS_DEFAULT; - qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_ETH, - p_params->num_cons, - p_params->num_vf_cons); + if (!p_params->num_vf_cons) + p_params->num_vf_cons = + ETH_PF_PARAMS_VF_CONS_DEFAULT; + qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_ETH, + p_params->num_cons, + p_params->num_vf_cons); p_hwfn->p_cxt_mngr->arfs_count = p_params->num_arfs_filters; break; } -- cgit v1.2.3 From cba2bf7a22acaaa18e9030596464b11ee57e077e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 12 Feb 2019 16:08:07 +0000 Subject: qlge: fix some indentation issues There are some statements that are indented incorrectly. Fix these. Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c | 4 ++-- drivers/net/ethernet/qlogic/qlge/qlge_main.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c index 5edbd532127d..a6886cc5654c 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c @@ -249,8 +249,8 @@ static void ql_update_stats(struct ql_adapter *qdev) spin_lock(&qdev->stats_lock); if (ql_sem_spinlock(qdev, qdev->xg_sem_mask)) { - netif_err(qdev, drv, qdev->ndev, - "Couldn't get xgmac sem.\n"); + netif_err(qdev, drv, qdev->ndev, + "Couldn't get xgmac sem.\n"); goto quit; } /* diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 059ba9429e51..096515c27263 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -1159,10 +1159,10 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) map = lbq_desc->p.pg_chunk.map + lbq_desc->p.pg_chunk.offset; - dma_unmap_addr_set(lbq_desc, mapaddr, map); + dma_unmap_addr_set(lbq_desc, mapaddr, map); dma_unmap_len_set(lbq_desc, maplen, rx_ring->lbq_buf_size); - *lbq_desc->addr = cpu_to_le64(map); + *lbq_desc->addr = cpu_to_le64(map); pci_dma_sync_single_for_device(qdev->pdev, map, rx_ring->lbq_buf_size, -- cgit v1.2.3 From f8b1f9f6459c8274865ef819bdedead577096254 Mon Sep 17 00:00:00 2001 From: Vishal Kulkarni Date: Wed, 13 Feb 2019 10:48:52 +0530 Subject: cxgb4vf: Few more link management changes. CR4_QSFP 10G Speed technology should be 10000baseKR_Full And also report available FEC modes. Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 84be3313fede..3300b69a42b3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -1408,7 +1408,7 @@ static void fw_caps_to_lmm(enum fw_port_type port_type, case FW_PORT_TYPE_CR4_QSFP: SET_LMM(FIBRE); FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full); - FW_CAPS_TO_LMM(SPEED_10G, 10000baseSR_Full); + FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full); FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full); FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full); FW_CAPS_TO_LMM(SPEED_50G, 50000baseCR2_Full); @@ -1419,6 +1419,13 @@ static void fw_caps_to_lmm(enum fw_port_type port_type, break; } + if (fw_caps & FW_PORT_CAP32_FEC_V(FW_PORT_CAP32_FEC_M)) { + FW_CAPS_TO_LMM(FEC_RS, FEC_RS); + FW_CAPS_TO_LMM(FEC_BASER_RS, FEC_BASER); + } else { + SET_LMM(FEC_NONE); + } + FW_CAPS_TO_LMM(ANEG, Autoneg); FW_CAPS_TO_LMM(802_3_PAUSE, Pause); FW_CAPS_TO_LMM(802_3_ASM_DIR, Asym_Pause); -- cgit v1.2.3 From d517ee7ca8ff8dfe2b200fd7b3087f00ede5f56f Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:44 +0000 Subject: mlxsw: spectrum: Move QSFP EEPROM definitions to common location Move QSFP EEPROM definitions to common location from the spectrum driver in order to make them available for other mlxsw modules. They are common for all kind of chips and have relation to SFF specifications 8024, 8436, 8472, 8636, rather than to chip type. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 32 ++++++++++++- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 62 +++++++++----------------- 2 files changed, 52 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 227720ce3982..1190a6a501a5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -8055,13 +8055,41 @@ MLXSW_ITEM32(reg, mcia, device_address, 0x04, 0, 16); */ MLXSW_ITEM32(reg, mcia, size, 0x08, 0, 16); -#define MLXSW_SP_REG_MCIA_EEPROM_SIZE 48 +#define MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH 256 +#define MLXSW_REG_MCIA_EEPROM_SIZE 48 +#define MLXSW_REG_MCIA_I2C_ADDR_LOW 0x50 +#define MLXSW_REG_MCIA_I2C_ADDR_HIGH 0x51 +#define MLXSW_REG_MCIA_PAGE0_LO_OFF 0xa0 +#define MLXSW_REG_MCIA_TH_ITEM_SIZE 2 +#define MLXSW_REG_MCIA_TH_PAGE_NUM 3 +#define MLXSW_REG_MCIA_PAGE0_LO 0 +#define MLXSW_REG_MCIA_TH_PAGE_OFF 0x80 + +enum mlxsw_reg_mcia_eeprom_module_info_rev_id { + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_UNSPC = 0x00, + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8436 = 0x01, + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636 = 0x03, +}; + +enum mlxsw_reg_mcia_eeprom_module_info_id { + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP = 0x03, + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP = 0x0C, + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS = 0x0D, + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 = 0x11, + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD = 0x18, +}; + +enum mlxsw_reg_mcia_eeprom_module_info { + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID, + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID, + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE, +}; /* reg_mcia_eeprom * Bytes to read/write. * Access: RW */ -MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_SP_REG_MCIA_EEPROM_SIZE); +MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE); static inline void mlxsw_reg_mcia_pack(char *payload, u8 module, u8 lock, u8 page_number, u16 device_addr, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 9686d3822b92..abac923a8d04 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2723,23 +2723,23 @@ static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port, unsigned int *p_read_size) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - char eeprom_tmp[MLXSW_SP_REG_MCIA_EEPROM_SIZE]; + char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE]; char mcia_pl[MLXSW_REG_MCIA_LEN]; u16 i2c_addr; int status; int err; - size = min_t(u16, size, MLXSW_SP_REG_MCIA_EEPROM_SIZE); + size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE); - if (offset < MLXSW_SP_EEPROM_PAGE_LENGTH && - offset + size > MLXSW_SP_EEPROM_PAGE_LENGTH) + if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH && + offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) /* Cross pages read, read until offset 256 in low page */ - size = MLXSW_SP_EEPROM_PAGE_LENGTH - offset; + size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset; - i2c_addr = MLXSW_SP_I2C_ADDR_LOW; - if (offset >= MLXSW_SP_EEPROM_PAGE_LENGTH) { - i2c_addr = MLXSW_SP_I2C_ADDR_HIGH; - offset -= MLXSW_SP_EEPROM_PAGE_LENGTH; + i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW; + if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) { + i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH; + offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH; } mlxsw_reg_mcia_pack(mcia_pl, mlxsw_sp_port->mapping.module, @@ -2760,55 +2760,37 @@ static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port, return 0; } -enum mlxsw_sp_eeprom_module_info_rev_id { - MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_UNSPC = 0x00, - MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8436 = 0x01, - MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636 = 0x03, -}; - -enum mlxsw_sp_eeprom_module_info_id { - MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP = 0x03, - MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP = 0x0C, - MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS = 0x0D, - MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 = 0x11, -}; - -enum mlxsw_sp_eeprom_module_info { - MLXSW_SP_EEPROM_MODULE_INFO_ID, - MLXSW_SP_EEPROM_MODULE_INFO_REV_ID, - MLXSW_SP_EEPROM_MODULE_INFO_SIZE, -}; - static int mlxsw_sp_get_module_info(struct net_device *netdev, struct ethtool_modinfo *modinfo) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev); - u8 module_info[MLXSW_SP_EEPROM_MODULE_INFO_SIZE]; + u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE]; + u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE; u8 module_rev_id, module_id; unsigned int read_size; int err; - err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0, - MLXSW_SP_EEPROM_MODULE_INFO_SIZE, + err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0, offset, module_info, &read_size); if (err) return err; - if (read_size < MLXSW_SP_EEPROM_MODULE_INFO_SIZE) + if (read_size < offset) return -EIO; - module_rev_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_REV_ID]; - module_id = module_info[MLXSW_SP_EEPROM_MODULE_INFO_ID]; + module_rev_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID]; + module_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID]; switch (module_id) { - case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP: + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: modinfo->type = ETH_MODULE_SFF_8436; modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; break; - case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS: - case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28: - if (module_id == MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 || - module_rev_id >= MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636) { + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */ + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: + if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 || + module_rev_id >= + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) { modinfo->type = ETH_MODULE_SFF_8636; modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; } else { @@ -2816,7 +2798,7 @@ static int mlxsw_sp_get_module_info(struct net_device *netdev, modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; } break; - case MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP: + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: modinfo->type = ETH_MODULE_SFF_8472; modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; break; -- cgit v1.2.3 From 5f28ef71a5ce7f3995c11e765683202fb10c1fbd Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:45 +0000 Subject: mlxsw: reg: Add Management Temperature Bulk Register Add MTBR (Management Temperature Bulk Register), which is used for port temperature reading in a bulk mode. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 1190a6a501a5..13856f40b8a7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -8001,6 +8001,80 @@ static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp, mlxsw_reg_mtmp_sensor_name_memcpy_from(payload, sensor_name); } +/* MTBR - Management Temperature Bulk Register + * ------------------------------------------- + * This register is used for bulk temperature reading. + */ +#define MLXSW_REG_MTBR_ID 0x900F +#define MLXSW_REG_MTBR_BASE_LEN 0x10 /* base length, without records */ +#define MLXSW_REG_MTBR_REC_LEN 0x04 /* record length */ +#define MLXSW_REG_MTBR_REC_MAX_COUNT 47 /* firmware limitation */ +#define MLXSW_REG_MTBR_LEN (MLXSW_REG_MTBR_BASE_LEN + \ + MLXSW_REG_MTBR_REC_LEN * \ + MLXSW_REG_MTBR_REC_MAX_COUNT) + +MLXSW_REG_DEFINE(mtbr, MLXSW_REG_MTBR_ID, MLXSW_REG_MTBR_LEN); + +/* reg_mtbr_base_sensor_index + * Base sensors index to access (0 - ASIC sensor, 1-63 - ambient sensors, + * 64-127 are mapped to the SFP+/QSFP modules sequentially). + * Access: Index + */ +MLXSW_ITEM32(reg, mtbr, base_sensor_index, 0x00, 0, 7); + +/* reg_mtbr_num_rec + * Request: Number of records to read + * Response: Number of records read + * See above description for more details. + * Range 1..255 + * Access: RW + */ +MLXSW_ITEM32(reg, mtbr, num_rec, 0x04, 0, 8); + +/* reg_mtbr_rec_max_temp + * The highest measured temperature from the sensor. + * When the bit mte is cleared, the field max_temperature is reserved. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, mtbr, rec_max_temp, MLXSW_REG_MTBR_BASE_LEN, 16, + 16, MLXSW_REG_MTBR_REC_LEN, 0x00, false); + +/* reg_mtbr_rec_temp + * Temperature reading from the sensor. Reading is in 0..125 Celsius + * degrees units. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, mtbr, rec_temp, MLXSW_REG_MTBR_BASE_LEN, 0, 16, + MLXSW_REG_MTBR_REC_LEN, 0x00, false); + +static inline void mlxsw_reg_mtbr_pack(char *payload, u8 base_sensor_index, + u8 num_rec) +{ + MLXSW_REG_ZERO(mtbr, payload); + mlxsw_reg_mtbr_base_sensor_index_set(payload, base_sensor_index); + mlxsw_reg_mtbr_num_rec_set(payload, num_rec); +} + +/* Error codes from temperatute reading */ +enum mlxsw_reg_mtbr_temp_status { + MLXSW_REG_MTBR_NO_CONN = 0x8000, + MLXSW_REG_MTBR_NO_TEMP_SENS = 0x8001, + MLXSW_REG_MTBR_INDEX_NA = 0x8002, + MLXSW_REG_MTBR_BAD_SENS_INFO = 0x8003, +}; + +/* Base index for reading modules temperature */ +#define MLXSW_REG_MTBR_BASE_MODULE_INDEX 64 + +static inline void mlxsw_reg_mtbr_temp_unpack(char *payload, int rec_ind, + u16 *p_temp, u16 *p_max_temp) +{ + if (p_temp) + *p_temp = mlxsw_reg_mtbr_rec_temp_get(payload, rec_ind); + if (p_max_temp) + *p_max_temp = mlxsw_reg_mtbr_rec_max_temp_get(payload, rec_ind); +} + /* MCIA - Management Cable Info Access * ----------------------------------- * MCIA register is used to access the SFP+ and QSFP connector's EPROM. @@ -9779,6 +9853,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mfsl), MLXSW_REG(mtcap), MLXSW_REG(mtmp), + MLXSW_REG(mtbr), MLXSW_REG(mcia), MLXSW_REG(mpat), MLXSW_REG(mpar), -- cgit v1.2.3 From 3760c2b99e20ee16cd328aca890ac0aca3c72ac5 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:46 +0000 Subject: mlxsw: reg: Add Fan Out of Range Event Register Add FORE (Fan Out of Range Event Register), which is used for fan fault reading. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 13856f40b8a7..cbd0193ec3f6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -7875,6 +7875,35 @@ static inline void mlxsw_reg_mfsl_unpack(char *payload, u8 tacho, *p_tach_max = mlxsw_reg_mfsl_tach_max_get(payload); } +/* FORE - Fan Out of Range Event Register + * -------------------------------------- + * This register reports the status of the controlled fans compared to the + * range defined by the MFSL register. + */ +#define MLXSW_REG_FORE_ID 0x9007 +#define MLXSW_REG_FORE_LEN 0x0C + +MLXSW_REG_DEFINE(fore, MLXSW_REG_FORE_ID, MLXSW_REG_FORE_LEN); + +/* fan_under_limit + * Fan speed is below the low limit defined in MFSL register. Each bit relates + * to a single tachometer and indicates the specific tachometer reading is + * below the threshold. + * Access: RO + */ +MLXSW_ITEM32(reg, fore, fan_under_limit, 0x00, 16, 10); + +static inline void mlxsw_reg_fore_unpack(char *payload, u8 tacho, + bool *fault) +{ + u16 limit; + + if (fault) { + limit = mlxsw_reg_fore_fan_under_limit_get(payload); + *fault = limit & BIT(tacho); + } +} + /* MTCAP - Management Temperature Capabilities * ------------------------------------------- * This register exposes the capabilities of the device and @@ -9851,6 +9880,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mfsc), MLXSW_REG(mfsm), MLXSW_REG(mfsl), + MLXSW_REG(fore), MLXSW_REG(mtcap), MLXSW_REG(mtmp), MLXSW_REG(mtbr), -- cgit v1.2.3 From d93c19a1d95c90b6ded1dc3c8ccfe0e46e220af8 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:47 +0000 Subject: mlxsw: core: Add API for QSFP module temperature thresholds reading Add new API to read QSFP module's temperature thresholds - warning and critical. New internal API reads the temperature thresholds from the modules, which are equipped with the thermal sensor. These thresholds will be exposed via hwmon subsystem. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Makefile | 2 +- drivers/net/ethernet/mellanox/mlxsw/core_env.c | 117 +++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core_env.h | 10 +++ 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_env.c create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_env.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index bbf45f10c208..a01d15546e37 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_MLXSW_CORE) += mlxsw_core.o mlxsw_core-objs := core.o core_acl_flex_keys.o \ - core_acl_flex_actions.o + core_acl_flex_actions.o core_env.o mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c new file mode 100644 index 000000000000..160d6cd164f4 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */ + +#include +#include + +#include "core.h" +#include "core_env.h" +#include "item.h" +#include "reg.h" + +static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, + bool *qsfp) +{ + char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE]; + char mcia_pl[MLXSW_REG_MCIA_LEN]; + u8 ident; + int err; + + mlxsw_reg_mcia_pack(mcia_pl, id, 0, MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, 1, + MLXSW_REG_MCIA_I2C_ADDR_LOW); + err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); + if (err) + return err; + mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp); + ident = eeprom_tmp[0]; + switch (ident) { + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: + *qsfp = false; + break; + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: /* fall-through */ + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */ + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: /* fall-through */ + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_DD: + *qsfp = true; + break; + default: + return -EINVAL; + } + + return 0; +} + +int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, + int off, int *temp) +{ + char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE]; + union { + u8 buf[MLXSW_REG_MCIA_TH_ITEM_SIZE]; + u16 temp; + } temp_thresh; + char mcia_pl[MLXSW_REG_MCIA_LEN] = {0}; + char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0}; + u16 module_temp; + bool qsfp; + int err; + + mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, + 1); + err = mlxsw_reg_query(core, MLXSW_REG(mtbr), mtbr_pl); + if (err) + return err; + + /* Don't read temperature thresholds for module with no valid info. */ + mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &module_temp, NULL); + switch (module_temp) { + case MLXSW_REG_MTBR_BAD_SENS_INFO: /* fall-through */ + case MLXSW_REG_MTBR_NO_CONN: /* fall-through */ + case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */ + case MLXSW_REG_MTBR_INDEX_NA: + *temp = 0; + return 0; + default: + /* Do not consider thresholds for zero temperature. */ + if (!MLXSW_REG_MTMP_TEMP_TO_MC(module_temp)) { + *temp = 0; + return 0; + } + break; + } + + /* Read Free Side Device Temperature Thresholds from page 03h + * (MSB at lower byte address). + * Bytes: + * 128-129 - Temp High Alarm (SFP_TEMP_HIGH_ALARM); + * 130-131 - Temp Low Alarm (SFP_TEMP_LOW_ALARM); + * 132-133 - Temp High Warning (SFP_TEMP_HIGH_WARN); + * 134-135 - Temp Low Warning (SFP_TEMP_LOW_WARN); + */ + + /* Validate module identifier value. */ + err = mlxsw_env_validate_cable_ident(core, module, &qsfp); + if (err) + return err; + + if (qsfp) + mlxsw_reg_mcia_pack(mcia_pl, module, 0, + MLXSW_REG_MCIA_TH_PAGE_NUM, + MLXSW_REG_MCIA_TH_PAGE_OFF + off, + MLXSW_REG_MCIA_TH_ITEM_SIZE, + MLXSW_REG_MCIA_I2C_ADDR_LOW); + else + mlxsw_reg_mcia_pack(mcia_pl, module, 0, + MLXSW_REG_MCIA_PAGE0_LO, + off, MLXSW_REG_MCIA_TH_ITEM_SIZE, + MLXSW_REG_MCIA_I2C_ADDR_HIGH); + + err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl); + if (err) + return err; + + mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp); + memcpy(temp_thresh.buf, eeprom_tmp, MLXSW_REG_MCIA_TH_ITEM_SIZE); + *temp = temp_thresh.temp * 1000; + + return 0; +} diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h new file mode 100644 index 000000000000..6dbdf63f3ee1 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ +/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */ + +#ifndef _MLXSW_CORE_ENV_H +#define _MLXSW_CORE_ENV_H + +int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, + int off, int *temp); + +#endif -- cgit v1.2.3 From 3dcfe179570550c888ecfcd3d443d4de90a2d855 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:48 +0000 Subject: mlxsw: core: Set different thermal polling time based on bus frequency capability Add low frequency bus capability in order to allow core functionality separation based on bus type. Driver could run over PCIe, which is considered as high frequency bus or I2C, which is considered as low frequency bus. In the last case time setting, for example, for thermal polling interval, should be increased. Use different thermal monitoring based on bus type. For I2C bus time is set to 20 seconds, while for PCIe 1 second polling interval is used. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.h | 1 + drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 10 ++++++++-- drivers/net/ethernet/mellanox/mlxsw/i2c.c | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index c8e16a305969..cd0c6aa0dff9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -344,6 +344,7 @@ struct mlxsw_bus_info { struct mlxsw_fw_rev fw_rev; u8 vsd[MLXSW_CMD_BOARDINFO_VSD_LEN]; u8 psid[MLXSW_CMD_BOARDINFO_PSID_LEN]; + u8 low_frequency; }; struct mlxsw_hwmon; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 61f897b40f82..b1f9b459766c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -13,6 +13,7 @@ #include "core.h" #define MLXSW_THERMAL_POLL_INT 1000 /* ms */ +#define MLXSW_THERMAL_SLOW_POLL_INT 20000 /* ms */ #define MLXSW_THERMAL_MAX_TEMP 110000 /* 110C */ #define MLXSW_THERMAL_MAX_STATE 10 #define MLXSW_THERMAL_MAX_DUTY 255 @@ -76,6 +77,7 @@ struct mlxsw_thermal { struct mlxsw_core *core; const struct mlxsw_bus_info *bus_info; struct thermal_zone_device *tzdev; + int polling_delay; struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; @@ -172,7 +174,7 @@ static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev, mutex_lock(&tzdev->lock); if (mode == THERMAL_DEVICE_ENABLED) - tzdev->polling_delay = MLXSW_THERMAL_POLL_INT; + tzdev->polling_delay = thermal->polling_delay; else tzdev->polling_delay = 0; @@ -423,13 +425,17 @@ int mlxsw_thermal_init(struct mlxsw_core *core, thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL, i); + thermal->polling_delay = bus_info->low_frequency ? + MLXSW_THERMAL_SLOW_POLL_INT : + MLXSW_THERMAL_POLL_INT; + thermal->tzdev = thermal_zone_device_register("mlxsw", MLXSW_THERMAL_NUM_TRIPS, MLXSW_THERMAL_TRIP_MASK, thermal, &mlxsw_thermal_ops, NULL, 0, - MLXSW_THERMAL_POLL_INT); + thermal->polling_delay); if (IS_ERR(thermal->tzdev)) { err = PTR_ERR(thermal->tzdev); dev_err(dev, "Failed to register thermal zone\n"); diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index 798bd5aca384..a87ca6b6580d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -503,6 +503,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client, mlxsw_i2c->bus_info.device_kind = id->name; mlxsw_i2c->bus_info.device_name = client->name; mlxsw_i2c->bus_info.dev = &client->dev; + mlxsw_i2c->bus_info.low_frequency = true; mlxsw_i2c->dev = &client->dev; err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info, -- cgit v1.2.3 From 69115b7d01c4715faf7803fea54017d76f195155 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:50 +0000 Subject: mlxsw: core: Modify thermal zone definition Modify thermal zone trip points setting for better alignment with system thermal requirement. Add hysteresis thresholds for thermal trips in order to avoid throttling around thermal trip point. If hysteresis temperature is not considered, PWM can have side effect of flip up/down on thermal trip point boundary. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 37 ++++++++++++++++------ 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index b1f9b459766c..dbf9a845084a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -15,6 +15,7 @@ #define MLXSW_THERMAL_POLL_INT 1000 /* ms */ #define MLXSW_THERMAL_SLOW_POLL_INT 20000 /* ms */ #define MLXSW_THERMAL_MAX_TEMP 110000 /* 110C */ +#define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */ #define MLXSW_THERMAL_MAX_STATE 10 #define MLXSW_THERMAL_MAX_DUTY 255 /* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values @@ -30,6 +31,7 @@ struct mlxsw_thermal_trip { int type; int temp; + int hyst; int min_state; int max_state; }; @@ -38,25 +40,22 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = { { /* In range - 0-40% PWM */ .type = THERMAL_TRIP_ACTIVE, .temp = 75000, + .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, .min_state = 0, .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, }, - { /* High - 40-100% PWM */ + { + /* In range - 40-100% PWM */ .type = THERMAL_TRIP_ACTIVE, .temp = 80000, + .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, .max_state = MLXSW_THERMAL_MAX_STATE, }, - { - /* Very high - 100% PWM */ - .type = THERMAL_TRIP_ACTIVE, - .temp = 85000, - .min_state = MLXSW_THERMAL_MAX_STATE, - .max_state = MLXSW_THERMAL_MAX_STATE, - }, { /* Warning */ .type = THERMAL_TRIP_HOT, - .temp = 105000, + .temp = 85000, + .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, .min_state = MLXSW_THERMAL_MAX_STATE, .max_state = MLXSW_THERMAL_MAX_STATE, }, @@ -246,6 +245,24 @@ static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev, return 0; } +static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev, + int trip, int *p_hyst) +{ + struct mlxsw_thermal *thermal = tzdev->devdata; + + *p_hyst = thermal->trips[trip].hyst; + return 0; +} + +static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev, + int trip, int hyst) +{ + struct mlxsw_thermal *thermal = tzdev->devdata; + + thermal->trips[trip].hyst = hyst; + return 0; +} + static struct thermal_zone_device_ops mlxsw_thermal_ops = { .bind = mlxsw_thermal_bind, .unbind = mlxsw_thermal_unbind, @@ -255,6 +272,8 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = { .get_trip_type = mlxsw_thermal_get_trip_type, .get_trip_temp = mlxsw_thermal_get_trip_temp, .set_trip_temp = mlxsw_thermal_set_trip_temp, + .get_trip_hyst = mlxsw_thermal_get_trip_hyst, + .set_trip_hyst = mlxsw_thermal_set_trip_hyst, }; static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, -- cgit v1.2.3 From 41e760841d262a88c39b16808e16d57e7a13cc66 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:51 +0000 Subject: mlxsw: core: Replace thermal temperature trips with defines Replace thermal hardcoded temperature trip values with defines. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index dbf9a845084a..b9fb33417a82 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -14,7 +14,10 @@ #define MLXSW_THERMAL_POLL_INT 1000 /* ms */ #define MLXSW_THERMAL_SLOW_POLL_INT 20000 /* ms */ -#define MLXSW_THERMAL_MAX_TEMP 110000 /* 110C */ +#define MLXSW_THERMAL_ASIC_TEMP_NORM 75000 /* 75C */ +#define MLXSW_THERMAL_ASIC_TEMP_HIGH 85000 /* 85C */ +#define MLXSW_THERMAL_ASIC_TEMP_HOT 105000 /* 105C */ +#define MLXSW_THERMAL_ASIC_TEMP_CRIT 110000 /* 110C */ #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */ #define MLXSW_THERMAL_MAX_STATE 10 #define MLXSW_THERMAL_MAX_DUTY 255 @@ -39,7 +42,7 @@ struct mlxsw_thermal_trip { static const struct mlxsw_thermal_trip default_thermal_trips[] = { { /* In range - 0-40% PWM */ .type = THERMAL_TRIP_ACTIVE, - .temp = 75000, + .temp = MLXSW_THERMAL_ASIC_TEMP_NORM, .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, .min_state = 0, .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, @@ -47,21 +50,21 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = { { /* In range - 40-100% PWM */ .type = THERMAL_TRIP_ACTIVE, - .temp = 80000, + .temp = MLXSW_THERMAL_ASIC_TEMP_HIGH, .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, .max_state = MLXSW_THERMAL_MAX_STATE, }, { /* Warning */ .type = THERMAL_TRIP_HOT, - .temp = 85000, + .temp = MLXSW_THERMAL_ASIC_TEMP_HOT, .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, .min_state = MLXSW_THERMAL_MAX_STATE, .max_state = MLXSW_THERMAL_MAX_STATE, }, { /* Critical - soft poweroff */ .type = THERMAL_TRIP_CRITICAL, - .temp = MLXSW_THERMAL_MAX_TEMP, + .temp = MLXSW_THERMAL_ASIC_TEMP_CRIT, .min_state = MLXSW_THERMAL_MAX_STATE, .max_state = MLXSW_THERMAL_MAX_STATE, } @@ -238,7 +241,7 @@ static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev, struct mlxsw_thermal *thermal = tzdev->devdata; if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS || - temp > MLXSW_THERMAL_MAX_TEMP) + temp > MLXSW_THERMAL_ASIC_TEMP_CRIT) return -EINVAL; thermal->trips[trip].temp = temp; -- cgit v1.2.3 From 2ee1165118140055bc43d22c6311acc60caf0890 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:52 +0000 Subject: mlxsw: core: Rename cooling device Rename cooling device from "Fan" to "mlxsw_fan". Name "Fan" is too common name, and such name is misleading, while it's interpreted by user. For example name "Fan" could be used by ACPI. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index b9fb33417a82..8b71706f7a27 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -431,8 +431,9 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (pwm_active & BIT(i)) { struct thermal_cooling_device *cdev; - cdev = thermal_cooling_device_register("Fan", thermal, - &mlxsw_cooling_ops); + cdev = thermal_cooling_device_register("mlxsw_fan", + thermal, + &mlxsw_cooling_ops); if (IS_ERR(cdev)) { err = PTR_ERR(cdev); dev_err(dev, "Failed to register cooling device\n"); -- cgit v1.2.3 From 2c6a33cd334baada7d9c1faeb0623407f37273f0 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:53 +0000 Subject: mlxsw: core: Extend hwmon interface with fan fault attribute Add new fan hwmon attribute for exposing fan faults (fault indication is read from Fan Out of Range Event Register). Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 34 +++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index e04e8162aa14..40e13093b62d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -121,6 +121,27 @@ static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev, return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl)); } +static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); + struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; + char fore_pl[MLXSW_REG_FORE_LEN]; + bool fault; + int err; + + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(fore), fore_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n"); + return err; + } + mlxsw_reg_fore_unpack(fore_pl, mlwsw_hwmon_attr->type_index, &fault); + + return sprintf(buf, "%u\n", fault); +} + static ssize_t mlxsw_hwmon_pwm_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -172,6 +193,7 @@ enum mlxsw_hwmon_attr_type { MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, MLXSW_HWMON_ATTR_TYPE_TEMP_RST, MLXSW_HWMON_ATTR_TYPE_FAN_RPM, + MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, MLXSW_HWMON_ATTR_TYPE_PWM, }; @@ -209,6 +231,12 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), "fan%u_input", num + 1); break; + case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT: + mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show; + mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; + snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), + "fan%u_fault", num + 1); + break; case MLXSW_HWMON_ATTR_TYPE_PWM: mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show; mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store; @@ -280,10 +308,14 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active); num = 0; for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) { - if (tacho_active & BIT(type_index)) + if (tacho_active & BIT(type_index)) { mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_FAN_RPM, + type_index, num); + mlxsw_hwmon_attr_add(mlxsw_hwmon, + MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, type_index, num++); + } } num = 0; for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) { -- cgit v1.2.3 From 5c42eaa07bd040d965b7a41b9596be5741016d1a Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:54 +0000 Subject: mlxsw: core: Extend hwmon interface with QSFP module temperature attributes Add new attributes to hwmon object for exposing QSFP module temperature input, fault indication, critical and emergency thresholds. Temperature input and fault indication are read from Management Temperature Bulk Register. Temperature thresholds are read from Management Cable Info Access Register. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 218 ++++++++++++++++++++++- 1 file changed, 215 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index 40e13093b62d..504f6bba8874 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -7,8 +7,10 @@ #include #include #include +#include #include "core.h" +#include "core_env.h" #define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127 #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \ @@ -30,6 +32,7 @@ struct mlxsw_hwmon { struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1]; struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT]; unsigned int attrs_count; + u8 sensor_count; }; static ssize_t mlxsw_hwmon_temp_show(struct device *dev, @@ -188,6 +191,136 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev, return len; } +static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); + struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; + char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0}; + u16 temp; + u8 module; + int err; + + module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; + mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, + 1); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); + if (err) { + dev_err(dev, "Failed to query module temprature sensor\n"); + return err; + } + + mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL); + /* Update status and temperature cache. */ + switch (temp) { + case MLXSW_REG_MTBR_NO_CONN: /* fall-through */ + case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */ + case MLXSW_REG_MTBR_INDEX_NA: + temp = 0; + break; + case MLXSW_REG_MTBR_BAD_SENS_INFO: + /* Untrusted cable is connected. Reading temperature from its + * sensor is faulty. + */ + temp = 0; + break; + default: + temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp); + break; + } + + return sprintf(buf, "%u\n", temp); +} + +static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); + struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; + char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0}; + u8 module, fault; + u16 temp; + int err; + + module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; + mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, + 1); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); + if (err) { + dev_err(dev, "Failed to query module temprature sensor\n"); + return err; + } + + mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL); + + /* Update status and temperature cache. */ + switch (temp) { + case MLXSW_REG_MTBR_BAD_SENS_INFO: + /* Untrusted cable is connected. Reading temperature from its + * sensor is faulty. + */ + fault = 1; + break; + case MLXSW_REG_MTBR_NO_CONN: /* fall-through */ + case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */ + case MLXSW_REG_MTBR_INDEX_NA: + default: + fault = 0; + break; + } + + return sprintf(buf, "%u\n", fault); +} + +static ssize_t +mlxsw_hwmon_module_temp_critical_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); + struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; + int temp; + u8 module; + int err; + + module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; + err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, + SFP_TEMP_HIGH_WARN, &temp); + if (err) { + dev_err(dev, "Failed to query module temprature thresholds\n"); + return err; + } + + return sprintf(buf, "%u\n", temp); +} + +static ssize_t +mlxsw_hwmon_module_temp_emergency_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); + struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; + u8 module; + int temp; + int err; + + module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; + err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, + SFP_TEMP_HIGH_ALARM, &temp); + if (err) { + dev_err(dev, "Failed to query module temprature thresholds\n"); + return err; + } + + return sprintf(buf, "%u\n", temp); +} + enum mlxsw_hwmon_attr_type { MLXSW_HWMON_ATTR_TYPE_TEMP, MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, @@ -195,6 +328,10 @@ enum mlxsw_hwmon_attr_type { MLXSW_HWMON_ATTR_TYPE_FAN_RPM, MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, MLXSW_HWMON_ATTR_TYPE_PWM, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, }; static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, @@ -244,6 +381,33 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), "pwm%u", num + 1); break; + case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE: + mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show; + mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; + snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), + "temp%u_input", num + 1); + break; + case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT: + mlxsw_hwmon_attr->dev_attr.show = + mlxsw_hwmon_module_temp_fault_show; + mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; + snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), + "temp%u_fault", num + 1); + break; + case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT: + mlxsw_hwmon_attr->dev_attr.show = + mlxsw_hwmon_module_temp_critical_show; + mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; + snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), + "temp%u_crit", num + 1); + break; + case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG: + mlxsw_hwmon_attr->dev_attr.show = + mlxsw_hwmon_module_temp_emergency_show; + mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; + snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), + "temp%u_emergency", num + 1); + break; default: WARN_ON(1); } @@ -261,7 +425,6 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) { char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0}; char mtmp_pl[MLXSW_REG_MTMP_LEN]; - u8 sensor_count; int i; int err; @@ -270,8 +433,8 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n"); return err; } - sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); - for (i = 0; i < sensor_count; i++) { + mlxsw_hwmon->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); + for (i = 0; i < mlxsw_hwmon->sensor_count; i++) { mlxsw_reg_mtmp_pack(mtmp_pl, i, true, true); err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); @@ -327,6 +490,50 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) return 0; } +static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) +{ + unsigned int module_count = mlxsw_core_max_ports(mlxsw_hwmon->core); + char pmlp_pl[MLXSW_REG_PMLP_LEN] = {0}; + int i, index; + u8 width; + int err; + + /* Add extra attributes for module temperature. Sensor index is + * assigned to sensor_count value, while all indexed before + * sensor_count are already utilized by the sensors connected through + * mtmp register by mlxsw_hwmon_temp_init(). + */ + index = mlxsw_hwmon->sensor_count; + for (i = 1; i < module_count; i++) { + mlxsw_reg_pmlp_pack(pmlp_pl, i); + err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(pmlp), + pmlp_pl); + if (err) { + dev_err(mlxsw_hwmon->bus_info->dev, "Failed to read module index %d\n", + i); + return err; + } + width = mlxsw_reg_pmlp_width_get(pmlp_pl); + if (!width) + continue; + mlxsw_hwmon_attr_add(mlxsw_hwmon, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, index, + index); + mlxsw_hwmon_attr_add(mlxsw_hwmon, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, + index, index); + mlxsw_hwmon_attr_add(mlxsw_hwmon, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, + index, index); + mlxsw_hwmon_attr_add(mlxsw_hwmon, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, + index, index); + index++; + } + + return 0; +} + int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info, struct mlxsw_hwmon **p_hwmon) @@ -349,6 +556,10 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, if (err) goto err_fans_init; + err = mlxsw_hwmon_module_init(mlxsw_hwmon); + if (err) + goto err_temp_module_init; + mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group; mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs; @@ -365,6 +576,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, return 0; err_hwmon_register: +err_temp_module_init: err_fans_init: err_temp_init: kfree(mlxsw_hwmon); -- cgit v1.2.3 From a53779de6a0ea6f25d3d5b60567ffc3671f1da7b Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:55 +0000 Subject: mlxsw: core: Add QSFP module temperature label attribute to hwmon Add label attribute to hwmon object for exposing QSFP module's temperature sensor name. Modules are labeled as "front panel xxx". The label is used by utilities such as "sensors": front panel 001: +0.0C (crit = +0.0C, emerg = +0.0C) .. front panel 020: +31.0C (crit = +70.0C, emerg = +80.0C) .. front panel 056: +41.0C (crit = +70.0C, emerg = +80.0C) Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index 504f6bba8874..f1ada4cdbd6b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -321,6 +321,18 @@ mlxsw_hwmon_module_temp_emergency_show(struct device *dev, return sprintf(buf, "%u\n", temp); } +static ssize_t +mlxsw_hwmon_module_temp_label_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = + container_of(attr, struct mlxsw_hwmon_attr, dev_attr); + + return sprintf(buf, "front panel %03u\n", + mlwsw_hwmon_attr->type_index); +} + enum mlxsw_hwmon_attr_type { MLXSW_HWMON_ATTR_TYPE_TEMP, MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, @@ -332,6 +344,7 @@ enum mlxsw_hwmon_attr_type { MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, }; static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, @@ -408,6 +421,13 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), "temp%u_emergency", num + 1); break; + case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL: + mlxsw_hwmon_attr->dev_attr.show = + mlxsw_hwmon_module_temp_label_show; + mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; + snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), + "temp%u_label", num + 1); + break; default: WARN_ON(1); } @@ -528,6 +548,9 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, index, index); + mlxsw_hwmon_attr_add(mlxsw_hwmon, + MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, + index, index); index++; } -- cgit v1.2.3 From 97cd342ae41fd524906e5acb0b760fd8331f3b1b Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Wed, 13 Feb 2019 11:28:56 +0000 Subject: mlxsw: core: Allow thermal zone binding to an external cooling device Allow thermal zone binding to an external cooling device from the cooling devices white list. It provides support for Mellanox next generation systems on which cooling device logic is not controlled through the switch registers. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 8b71706f7a27..821fef2e2230 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -31,6 +31,11 @@ #define MLXSW_THERMAL_SPEED_MAX (MLXSW_THERMAL_MAX_STATE * 2) #define MLXSW_THERMAL_SPEED_MIN_LEVEL 2 /* 20% */ +/* External cooling devices, allowed for binding to mlxsw thermal zones. */ +static char * const mlxsw_thermal_external_allowed_cdev[] = { + "mlxreg_fan", +}; + struct mlxsw_thermal_trip { int type; int temp; @@ -107,6 +112,13 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal, if (thermal->cdevs[i] == cdev) return i; + /* Allow mlxsw thermal zone binding to an external cooling device */ + for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) { + if (strnstr(cdev->type, mlxsw_thermal_external_allowed_cdev[i], + sizeof(cdev->type))) + return 0; + } + return -ENODEV; } -- cgit v1.2.3 From d9b10c6ba969c5360d4aebf18fc5ac8e393fd698 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 31 Oct 2018 11:15:30 +0200 Subject: iwlwifi: bump FW API to 45 for 9000 and 22000 series Start supporting API version 45 where applicable. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 28d8c3477371..e4933c355dfd 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -56,7 +56,7 @@ #include "iwl-config.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 44 +#define IWL_22000_UCODE_API_MAX 45 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 39 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 84adfd902002..35c1851337e6 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -57,7 +57,7 @@ #include "fw/file.h" /* Highest firmware API version supported */ -#define IWL9000_UCODE_API_MAX 44 +#define IWL9000_UCODE_API_MAX 45 /* Lowest firmware API version supported */ #define IWL9000_UCODE_API_MIN 30 -- cgit v1.2.3 From c6ac9f9fb98851f47b978a9476594fc3c477a34d Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 13 Dec 2018 14:47:40 +0200 Subject: iwlwifi: pcie: fix emergency path Allocator swaps the pending requests with 0 when it starts working. This means that relying on it n RX path to decide if to move to emergency is not always a good idea, since it may be zero, but there are still a lot of unallocated RBs in the system. Change allocator to decrement the pending requests on real time. It is more expensive since it accesses the atomic variable more times, but it gives the RX path a better idea of the system's status. Reported-by: Ilan Peer Signed-off-by: Sara Sharon Fixes: 868a1e863f95 ("iwlwifi: pcie: avoid empty free RB queue") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index c260d1251b5f..36cbfed409d0 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -538,7 +538,7 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rb_allocator *rba = &trans_pcie->rba; struct list_head local_empty; - int pending = atomic_xchg(&rba->req_pending, 0); + int pending = atomic_read(&rba->req_pending); IWL_DEBUG_RX(trans, "Pending allocation requests = %d\n", pending); @@ -593,11 +593,13 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) i++; } + atomic_dec(&rba->req_pending); pending--; + if (!pending) { - pending = atomic_xchg(&rba->req_pending, 0); + pending = atomic_read(&rba->req_pending); IWL_DEBUG_RX(trans, - "Pending allocation requests = %d\n", + "Got more pending allocation requests = %d\n", pending); } @@ -609,12 +611,15 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) spin_unlock(&rba->lock); atomic_inc(&rba->req_ready); + } spin_lock(&rba->lock); /* return unused rbds to the allocator empty list */ list_splice_tail(&local_empty, &rba->rbd_empty); spin_unlock(&rba->lock); + + IWL_DEBUG_RX(trans, "%s, exit.\n", __func__); } /* -- cgit v1.2.3 From ec4156a91d1eac4a41ce5b213652c6a2871a9465 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 17 Dec 2018 11:38:03 +0200 Subject: iwlwifi: dvm: don't use IWL_DL_FW_ERRORS Use IWL_DL_FW instead. This will free a bit for more needed prints in newer devices. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index bd3c3b921d4c..114f0ab022a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -1881,7 +1881,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, return pos; } - if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log) + if (!(iwl_have_debug_level(IWL_DL_FW)) && !full_log) size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", @@ -1897,7 +1897,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, if (!*buf) return -ENOMEM; } - if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) { + if (iwl_have_debug_level(IWL_DL_FW) || full_log) { /* * if uCode has wrapped back to top of log, * start at the oldest entry, @@ -1927,7 +1927,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) unsigned int reload_msec; unsigned long reload_jiffies; - if (iwl_have_debug_level(IWL_DL_FW_ERRORS)) + if (iwl_have_debug_level(IWL_DL_FW)) iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); /* uCode is no longer loaded. */ @@ -1965,12 +1965,12 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { if (iwlwifi_mod_params.fw_restart) { - IWL_DEBUG_FW_ERRORS(priv, - "Restarting adapter due to uCode error.\n"); + IWL_DEBUG_FW(priv, + "Restarting adapter due to uCode error.\n"); queue_work(priv->workqueue, &priv->restart); } else - IWL_DEBUG_FW_ERRORS(priv, - "Detected FW error, but not restarting\n"); + IWL_DEBUG_FW(priv, + "Detected FW error, but not restarting\n"); } } -- cgit v1.2.3 From 6dcdd165777b9b08da05b981aa295b1a47b3017a Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 17 Dec 2018 11:39:42 +0200 Subject: iwlwifi: pcie: add TPT oriented prints Currently there is no way to debug RX/TX paths using prints without harming tpt. Add prints to debug RX allocation path. We can still get 1.9 gbps with those on. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-debug.h | 5 +++-- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 20 ++++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h index a2af68a0d34b..655ff5694560 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-debug.h @@ -1,6 +1,7 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. + * Copyright (C) 2018 Intel Corporation * * Portions of this file are derived from the ipw3945 project. * @@ -159,7 +160,7 @@ do { \ /* 0x000F0000 - 0x00010000 */ #define IWL_DL_FW 0x00010000 #define IWL_DL_RF_KILL 0x00020000 -#define IWL_DL_FW_ERRORS 0x00040000 +#define IWL_DL_TPT 0x00040000 /* 0x00F00000 - 0x00100000 */ #define IWL_DL_RATE 0x00100000 #define IWL_DL_CALIB 0x00200000 @@ -193,7 +194,6 @@ do { \ #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) #define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) -#define IWL_DEBUG_FW_ERRORS(p, f, a...) IWL_DEBUG(p, IWL_DL_FW_ERRORS, f, ## a) #define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) #define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) @@ -215,6 +215,7 @@ do { \ #define IWL_DEBUG_DEV_RADIO(p, f, a...) IWL_DEBUG_DEV(p, IWL_DL_RADIO, f, ## a) #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) #define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a) +#define IWL_DEBUG_TPT(p, f, a...) IWL_DEBUG(p, IWL_DL_TPT, f, ## a) #define IWL_DEBUG_RPM(p, f, a...) IWL_DEBUG(p, IWL_DL_RPM, f, ## a) #define IWL_DEBUG_LAR(p, f, a...) IWL_DEBUG(p, IWL_DL_LAR, f, ## a) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 36cbfed409d0..49c2ce549c86 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -540,7 +540,7 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) struct list_head local_empty; int pending = atomic_read(&rba->req_pending); - IWL_DEBUG_RX(trans, "Pending allocation requests = %d\n", pending); + IWL_DEBUG_TPT(trans, "Pending allocation requests = %d\n", pending); /* If we were scheduled - there is at least one request */ spin_lock(&rba->lock); @@ -598,9 +598,10 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) if (!pending) { pending = atomic_read(&rba->req_pending); - IWL_DEBUG_RX(trans, - "Got more pending allocation requests = %d\n", - pending); + if (pending) + IWL_DEBUG_TPT(trans, + "Got more pending allocation requests = %d\n", + pending); } spin_lock(&rba->lock); @@ -619,7 +620,7 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) list_splice_tail(&local_empty, &rba->rbd_empty); spin_unlock(&rba->lock); - IWL_DEBUG_RX(trans, "%s, exit.\n", __func__); + IWL_DEBUG_TPT(trans, "%s, exit.\n", __func__); } /* @@ -1429,6 +1430,9 @@ restart: !emergency)) { iwl_pcie_rx_move_to_allocator(rxq, rba); emergency = true; + IWL_DEBUG_TPT(trans, + "RX path is in emergency. Pending allocations %d\n", + rb_pending_alloc); } IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i); @@ -1458,8 +1462,12 @@ restart: count++; if (count == 8) { count = 0; - if (rb_pending_alloc < rxq->queue_size / 3) + if (rb_pending_alloc < rxq->queue_size / 3) { + IWL_DEBUG_TPT(trans, + "RX path exited emergency. Pending allocations %d\n", + rb_pending_alloc); emergency = false; + } rxq->read = i; spin_unlock(&rxq->lock); -- cgit v1.2.3 From e41e2c26760421c6bd09d0029110e08cadc0bb8a Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 16 Dec 2018 14:02:29 +0200 Subject: iwlwifi: dbg_ini: implement monitor sram memory dump Implement monitor sram memory dump in the new dump mechanism. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 23 +++++++++++++++++------ drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 1 + 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 390401300fcf..de6db880d5ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1284,6 +1284,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: + case IWL_FW_INI_REGION_INTERNAL_BUFFER: case IWL_FW_INI_REGION_CSR: size += hdr_len + dump_header_len + range_header_len * iwl_dump_ini_mem_ranges(fwrt, reg) + @@ -1312,7 +1313,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, } case IWL_FW_INI_REGION_DRAM_BUFFER: /* Transport takes care of DRAM dumping */ - case IWL_FW_INI_REGION_INTERNAL_BUFFER: case IWL_FW_INI_REGION_DRAM_IMR: /* Undefined yet */ default: @@ -1346,6 +1346,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, type = le32_to_cpu(reg->region_type); switch (type) { case IWL_FW_INI_REGION_DEVICE_MEMORY: + case IWL_FW_INI_REGION_INTERNAL_BUFFER: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; @@ -1396,7 +1397,6 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; case IWL_FW_INI_REGION_DRAM_IMR: - case IWL_FW_INI_REGION_INTERNAL_BUFFER: /* This is undefined yet */ default: break; @@ -1853,7 +1853,8 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size) } static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_allocation_data *alloc) + struct iwl_fw_ini_allocation_data *alloc, + enum iwl_fw_ini_apply_point pnt) { struct iwl_trans *trans = fwrt->trans; struct iwl_ldbg_config_cmd ldbg_cmd = { @@ -1867,9 +1868,19 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, .len[0] = sizeof(ldbg_cmd), }; int block_idx = trans->num_blocks; + u32 buf_location = le32_to_cpu(alloc->tlv.buffer_location); + + if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) { + if (!WARN(pnt != IWL_FW_INI_APPLY_EARLY, + "Invalid apply point %d for SMEM buffer allocation", + pnt)) + /* set sram monitor by enabling bit 7 */ + iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM); + return; + } - if (le32_to_cpu(alloc->tlv.buffer_location) != - IWL_FW_INI_LOCATION_DRAM_PATH) + if (buf_location != IWL_FW_INI_LOCATION_DRAM_PATH) return; if (!alloc->is_alloc) { @@ -2017,7 +2028,7 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: { struct iwl_fw_ini_allocation_data *buf_alloc = ini_tlv; - iwl_fw_dbg_buffer_apply(fwrt, ini_tlv); + iwl_fw_dbg_buffer_apply(fwrt, ini_tlv, pnt); iter += sizeof(buf_alloc->is_alloc); break; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index 42af421bbc3c..d0ce3a79c387 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -180,6 +180,7 @@ /* Bits for CSR_HW_IF_CONFIG_REG */ #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003) #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C) +#define CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM (0x00000080) #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0) #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) -- cgit v1.2.3 From 3f37c229543ea9660c478157d20b0fcffc23cdf1 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 17 Dec 2018 09:35:20 -0500 Subject: iwlwifi: mvm: don't require WOWLAN images when unified WOWLAN images in unified firmwares should not be used, so don't require them to support wowlan. This will allow to reduce the firmware's file size. Signed-off-by: Ido Yariv Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index fc251cc47b7f..ea121c398aae 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -420,6 +420,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, }; +#ifdef CONFIG_PM_SLEEP + bool unified = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); +#endif /* Tell mac80211 our characteristics */ ieee80211_hw_set(hw, SIGNAL_DBM); @@ -709,7 +713,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->wowlan = &mvm->wowlan; } - if (mvm->fw->img[IWL_UCODE_WOWLAN].num_sec && + if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) && mvm->trans->ops->d3_suspend && mvm->trans->ops->d3_resume && device_can_wakeup(mvm->trans->dev)) { -- cgit v1.2.3 From 106b791ac391f5eafbf03b3a1ced5dfa1b0e8182 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 16 Dec 2018 13:17:03 +0200 Subject: iwlwifi: dbg_ini: implement monitor dram memory dump Implement monitor dram memory dump in the new dump mechanism. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 86 +++++++++++++++++++--- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 16 +++- 2 files changed, 89 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index de6db880d5ce..512af6128fa5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1132,6 +1132,26 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt, return le32_to_cpu(range->range_data_size); } +static int +iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_error_dump_range *range, + struct iwl_fw_ini_region_cfg *reg, + int idx) +{ + u32 start_addr = iwl_read_prph(fwrt->trans, MON_BUFF_BASE_ADDR_VER2); + + if (start_addr == 0x5a5a5a5a) + return -1; + + range->start_addr = cpu_to_le32(start_addr); + range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size); + + memcpy(range->data, fwrt->trans->fw_mon[idx].block, + fwrt->trans->fw_mon[idx].size); + + return le32_to_cpu(range->range_data_size); +} + static struct iwl_fw_ini_error_dump_range *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data) { @@ -1140,6 +1160,27 @@ static struct iwl_fw_ini_error_dump_range return dump->ranges; } +static struct iwl_fw_ini_error_dump_range +*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, void *data) +{ + struct iwl_fw_ini_monitor_dram_dump *mon_dump = (void *)data; + u32 write_ptr, cycle_cnt; + unsigned long flags; + + if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) { + IWL_ERR(fwrt, "Failed to get DRAM monitor header\n"); + return NULL; + } + write_ptr = iwl_read_prph_no_grab(fwrt->trans, MON_BUFF_WRPTR_VER2); + cycle_cnt = iwl_read_prph_no_grab(fwrt->trans, MON_BUFF_CYCLE_CNT_VER2); + iwl_trans_release_nic_access(fwrt->trans, &flags); + + mon_dump->write_ptr = cpu_to_le32(write_ptr); + mon_dump->cycle_cnt = cpu_to_le32(cycle_cnt); + + return mon_dump->ranges; +} + static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { @@ -1169,6 +1210,12 @@ static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt, return size; } +static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return fwrt->trans->num_blocks ? fwrt->trans->fw_mon[0].size : 0; +} + static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { @@ -1187,6 +1234,12 @@ static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt, return fwrt->num_of_paging_blk; } +static u32 iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return 1; +} + /** * struct iwl_dump_ini_mem_ops - ini memory dump operations * @get_num_of_ranges: returns the number of memory ranges in the region. @@ -1312,7 +1365,13 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, break; } case IWL_FW_INI_REGION_DRAM_BUFFER: - /* Transport takes care of DRAM dumping */ + if (!fwrt->trans->num_blocks) + break; + size += hdr_len + + sizeof(struct iwl_fw_ini_monitor_dram_dump) * + iwl_dump_ini_mon_dram_ranges(fwrt, reg) + + iwl_dump_ini_mon_dram_get_size(fwrt, reg); + break; case IWL_FW_INI_REGION_DRAM_IMR: /* Undefined yet */ default: @@ -1324,8 +1383,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_trigger *trigger, - struct iwl_fw_error_dump_data **data, - u32 *dump_mask) + struct iwl_fw_error_dump_data **data) { int i, num = le32_to_cpu(trigger->num_regions); @@ -1363,7 +1421,11 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; case IWL_FW_INI_REGION_DRAM_BUFFER: - *dump_mask |= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR); + ops.get_num_of_ranges = iwl_dump_ini_mon_dram_ranges; + ops.get_size = iwl_dump_ini_mon_dram_get_size; + ops.fill_mem_hdr = iwl_dump_ini_mon_dram_fill_header; + ops.fill_range = iwl_dump_ini_mon_dram_iter; + iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; case IWL_FW_INI_REGION_PAGING: { ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; @@ -1406,8 +1468,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, static struct iwl_fw_error_dump_file * _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, - struct iwl_fw_dump_ptrs *fw_error_dump, - u32 *dump_mask) + struct iwl_fw_dump_ptrs *fw_error_dump) { int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type); struct iwl_fw_error_dump_data *dump_data; @@ -1440,11 +1501,10 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, dump_data = (void *)dump_file->data; dump_file->file_len = cpu_to_le32(size); - *dump_mask = 0; if (trigger) - iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data, dump_mask); + iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data); if (ext) - iwl_fw_ini_dump_trigger(fwrt, ext, &dump_data, dump_mask); + iwl_fw_ini_dump_trigger(fwrt, ext, &dump_data); return dump_file; } @@ -1470,8 +1530,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) goto out; if (fwrt->trans->ini_valid) - dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump, - &dump_mask); + dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump); else dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump); @@ -1483,7 +1542,10 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only) dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR; - fw_error_dump->trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask); + if (!fwrt->trans->ini_valid) + fw_error_dump->trans_ptr = + iwl_trans_dump_data(fwrt->trans, dump_mask); + file_len = le32_to_cpu(dump_file->file_len); fw_error_dump->fwrt_len = file_len; if (fw_error_dump->trans_ptr) { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 42e0c4c93c82..063f2b925808 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -301,7 +301,7 @@ struct iwl_fw_ini_error_dump_header { /** * struct iwl_fw_ini_error_dump - ini region dump * @header: the header of this region - * @ranges: the memory ranges of this this region + * @ranges: the memory ranges of this region */ struct iwl_fw_ini_error_dump { struct iwl_fw_ini_error_dump_header header; @@ -322,6 +322,20 @@ struct iwl_fw_error_dump_rb { u8 data[]; }; +/** + * struct iwl_fw_ini_monitor_dram_dump - ini dram monitor dump + * @header - header of the region + * @write_ptr - write pointer position in the dram + * @cycle_cnt - cycles count + * @ranges - the memory ranges of this this region + */ +struct iwl_fw_ini_monitor_dram_dump { + struct iwl_fw_ini_error_dump_header header; + __le32 write_ptr; + __le32 cycle_cnt; + struct iwl_fw_ini_error_dump_range ranges[]; +} __packed; + /** * struct iwl_fw_error_dump_paging - content of the UMAC's image page * block on DRAM -- cgit v1.2.3 From b73f9a4ae77d448eb501f746d3bbe1b737f38681 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 5 Dec 2018 11:34:09 +0100 Subject: iwlwifi: mvm: support FTM responder Add support for FTM responder for hardware/firmware combinations that advertise support for it. Signed-off-by: Johannes Berg Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/file.h | 9 + drivers/net/wireless/intel/iwlwifi/mvm/Makefile | 2 +- .../net/wireless/intel/iwlwifi/mvm/ftm-responder.c | 244 +++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 92 +++++++- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 9 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 + 6 files changed, 353 insertions(+), 5 deletions(-) create mode 100644 drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 8c6ce4142204..3bffb0f7a5e5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -370,12 +370,15 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * capability. * @IWL_UCODE_TLV_CAPA_CSI_REPORTING: firmware is capable of being configured * to report the CSI information with (certain) RX frames + * @IWL_UCODE_TLV_CAPA_FTM_CALIBRATED: has FTM calibrated and thus supports both + * initiator and responder * * @IWL_UCODE_TLV_CAPA_MLME_OFFLOAD: supports MLME offload * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ enum iwl_ucode_tlv_capa { + /* set 0 */ IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0, IWL_UCODE_TLV_CAPA_LAR_SUPPORT = (__force iwl_ucode_tlv_capa_t)1, IWL_UCODE_TLV_CAPA_UMAC_SCAN = (__force iwl_ucode_tlv_capa_t)2, @@ -397,6 +400,8 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, + + /* set 1 */ IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38, IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39, IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40, @@ -406,6 +411,9 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_COEX_SCHEMA_2 = (__force iwl_ucode_tlv_capa_t)45, IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD = (__force iwl_ucode_tlv_capa_t)46, IWL_UCODE_TLV_CAPA_ULTRA_HB_CHANNELS = (__force iwl_ucode_tlv_capa_t)48, + IWL_UCODE_TLV_CAPA_FTM_CALIBRATED = (__force iwl_ucode_tlv_capa_t)47, + + /* set 2 */ IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, @@ -426,6 +434,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89, IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90, + /* set 3 */ IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96, NUM_IWL_UCODE_TLV_CAPA diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile index 30cbd981efbd..56e8d073f5aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile @@ -4,7 +4,7 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o iwlmvm-y += scan.o time-event.o rs.o rs-fw.o iwlmvm-y += power.o coex.o -iwlmvm-y += tt.o offloading.o tdls.o +iwlmvm-y += tt.o offloading.o tdls.o ftm-responder.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o iwlmvm-$(CONFIG_PM) += d3.o diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c new file mode 100644 index 000000000000..1513b8b4062f --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c @@ -0,0 +1,244 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include +#include +#include "mvm.h" +#include "constants.h" + +static int +iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct cfg80211_chan_def *chandef) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_tof_responder_config_cmd cmd = { + .channel_num = chandef->chan->hw_value, + .cmd_valid_fields = + cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO | + IWL_TOF_RESPONDER_CMD_VALID_BSSID | + IWL_TOF_RESPONDER_CMD_VALID_STA_ID), + .sta_id = mvmvif->bcast_sta.sta_id, + }; + + lockdep_assert_held(&mvm->mutex); + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + cmd.bandwidth = IWL_TOF_BW_20_LEGACY; + break; + case NL80211_CHAN_WIDTH_20: + cmd.bandwidth = IWL_TOF_BW_20_HT; + break; + case NL80211_CHAN_WIDTH_40: + cmd.bandwidth = IWL_TOF_BW_40; + cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); + break; + case NL80211_CHAN_WIDTH_80: + cmd.bandwidth = IWL_TOF_BW_80; + cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); + break; + default: + WARN_ON(1); + return -EINVAL; + } + + memcpy(cmd.bssid, vif->addr, ETH_ALEN); + + return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RESPONDER_CONFIG_CMD, + LOCATION_GROUP, 0), + 0, sizeof(cmd), &cmd); +} + +static int +iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_ftm_responder_params *params) +{ + struct iwl_tof_responder_dyn_config_cmd cmd = { + .lci_len = cpu_to_le32(params->lci_len + 2), + .civic_len = cpu_to_le32(params->civicloc_len + 2), + }; + u8 data[IWL_LCI_CIVIC_IE_MAX_SIZE] = {0}; + struct iwl_host_cmd hcmd = { + .id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD, + LOCATION_GROUP, 0), + .data[0] = &cmd, + .len[0] = sizeof(cmd), + .data[1] = &data, + /* .len[1] set later */ + /* may not be able to DMA from stack */ + .dataflags[1] = IWL_HCMD_DFL_DUP, + }; + u32 aligned_lci_len = ALIGN(params->lci_len + 2, 4); + u32 aligned_civicloc_len = ALIGN(params->civicloc_len + 2, 4); + u8 *pos = data; + + lockdep_assert_held(&mvm->mutex); + + if (aligned_lci_len + aligned_civicloc_len > sizeof(data)) { + IWL_ERR(mvm, "LCI/civicloc data too big (%zd + %zd)\n", + params->lci_len, params->civicloc_len); + return -ENOBUFS; + } + + pos[0] = WLAN_EID_MEASURE_REPORT; + pos[1] = params->lci_len; + memcpy(pos + 2, params->lci, params->lci_len); + + pos += aligned_lci_len; + pos[0] = WLAN_EID_MEASURE_REPORT; + pos[1] = params->civicloc_len; + memcpy(pos + 2, params->civicloc, params->civicloc_len); + + hcmd.len[1] = aligned_lci_len + aligned_civicloc_len; + + return iwl_mvm_send_cmd(mvm, &hcmd); +} + +int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct ieee80211_ftm_responder_params *params; + struct ieee80211_chanctx_conf ctx, *pctx; + u16 *phy_ctxt_id; + struct iwl_mvm_phy_ctxt *phy_ctxt; + int ret; + + params = vif->bss_conf.ftmr_params; + + lockdep_assert_held(&mvm->mutex); + + if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder)) + return -EINVAL; + + if (vif->p2p || vif->type != NL80211_IFTYPE_AP || + !mvmvif->ap_ibss_active) { + IWL_ERR(mvm, "Cannot start responder, not in AP mode\n"); + return -EIO; + } + + rcu_read_lock(); + pctx = rcu_dereference(vif->chanctx_conf); + /* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care + * about changes in the ctx after releasing the lock because the driver + * is still protected by the mutex. */ + ctx = *pctx; + phy_ctxt_id = (u16 *)pctx->drv_priv; + rcu_read_unlock(); + + phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; + ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def, + ctx.rx_chains_static, + ctx.rx_chains_dynamic); + if (ret) + return ret; + + ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def); + if (ret) + return ret; + + if (params) + ret = iwl_mvm_ftm_responder_dyn_cfg_cmd(mvm, vif, params); + + return ret; +} + +void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) +{ + if (!vif->bss_conf.ftm_responder) + return; + + iwl_mvm_ftm_start_responder(mvm, vif); +} + +void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_ftm_responder_stats *resp = (void *)pkt->data; + struct cfg80211_ftm_responder_stats *stats = &mvm->ftm_resp_stats; + u32 flags = le32_to_cpu(resp->flags); + + if (resp->success_ftm == resp->ftm_per_burst) + stats->success_num++; + else if (resp->success_ftm >= 2) + stats->partial_num++; + else + stats->failed_num++; + + if ((flags & FTM_RESP_STAT_ASAP_REQ) && + (flags & FTM_RESP_STAT_ASAP_RESP)) + stats->asap_num++; + + if (flags & FTM_RESP_STAT_NON_ASAP_RESP) + stats->non_asap_num++; + + stats->total_duration_ms += le32_to_cpu(resp->duration) / USEC_PER_MSEC; + + if (flags & FTM_RESP_STAT_TRIGGER_UNKNOWN) + stats->unknown_triggers_num++; + + if (flags & FTM_RESP_STAT_DUP) + stats->reschedule_requests_num++; + + if (flags & FTM_RESP_STAT_NON_ASAP_OUT_WIN) + stats->out_of_window_triggers_num++; +} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index ea121c398aae..cba1a0fe33ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -548,6 +548,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->n_cipher_suites++; } + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) + wiphy_ext_feature_set(hw->wiphy, + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); + ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); hw->wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | @@ -1657,6 +1662,9 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, IEEE80211_VIF_SUPPORTS_CQM_RSSI); } + if (vif->bss_conf.ftm_responder) + memset(&mvm->ftm_resp_stats, 0, sizeof(mvm->ftm_resp_stats)); + iwl_mvm_vif_dbgfs_clean(mvm, vif); /* @@ -2548,6 +2556,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, if (iwl_mvm_phy_ctx_count(mvm) > 1) iwl_mvm_teardown_tdls_peers(mvm); + iwl_mvm_ftm_restart_responder(mvm, vif); + goto out_unlock; out_quota_failed: @@ -2659,6 +2669,15 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, bss_conf->txpower); iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower); } + + if (changes & BSS_CHANGED_FTM_RESPONDER) { + int ret = iwl_mvm_ftm_start_responder(mvm, vif); + + if (ret) + IWL_WARN(mvm, "Failed to enable FTM responder (%d)\n", + ret); + } + } static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, @@ -3796,11 +3815,43 @@ static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw) return 0; } +struct iwl_mvm_ftm_responder_iter_data { + bool responder; + struct ieee80211_chanctx_conf *ctx; +}; + +static void iwl_mvm_ftm_responder_chanctx_iter(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_ftm_responder_iter_data *data = _data; + + if (rcu_access_pointer(vif->chanctx_conf) == data->ctx && + vif->type == NL80211_IFTYPE_AP && vif->bss_conf.ftmr_params) + data->responder = true; +} + +static bool iwl_mvm_is_ftm_responder_chanctx(struct iwl_mvm *mvm, + struct ieee80211_chanctx_conf *ctx) +{ + struct iwl_mvm_ftm_responder_iter_data data = { + .responder = false, + .ctx = ctx, + }; + + ieee80211_iterate_active_interfaces_atomic(mvm->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_ftm_responder_chanctx_iter, + &data); + return data.responder; +} + static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm, struct ieee80211_chanctx_conf *ctx) { u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; struct iwl_mvm_phy_ctxt *phy_ctxt; + bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx); + struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def; int ret; lockdep_assert_held(&mvm->mutex); @@ -3813,7 +3864,7 @@ static int __iwl_mvm_add_chanctx(struct iwl_mvm *mvm, goto out; } - ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def, + ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def, ctx->rx_chains_static, ctx->rx_chains_dynamic); if (ret) { @@ -3868,6 +3919,8 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; + bool responder = iwl_mvm_is_ftm_responder_chanctx(mvm, ctx); + struct cfg80211_chan_def *def = responder ? &ctx->def : &ctx->min_def; if (WARN_ONCE((phy_ctxt->ref > 1) && (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH | @@ -3882,17 +3935,17 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw, /* we are only changing the min_width, may be a noop */ if (changed == IEEE80211_CHANCTX_CHANGE_MIN_WIDTH) { - if (phy_ctxt->width == ctx->min_def.width) + if (phy_ctxt->width == def->width) goto out_unlock; /* we are just toggling between 20_NOHT and 20 */ if (phy_ctxt->width <= NL80211_CHAN_WIDTH_20 && - ctx->min_def.width <= NL80211_CHAN_WIDTH_20) + def->width <= NL80211_CHAN_WIDTH_20) goto out_unlock; } iwl_mvm_bt_coex_vif_change(mvm); - iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def, + iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, def, ctx->rx_chains_static, ctx->rx_chains_dynamic); @@ -4813,6 +4866,35 @@ static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) mutex_unlock(&mvm->mutex); } +static int +iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_ftm_responder_stats *stats) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + if (vif->p2p || vif->type != NL80211_IFTYPE_AP || + !mvmvif->ap_ibss_active || !vif->bss_conf.ftm_responder) + return -EINVAL; + + mutex_lock(&mvm->mutex); + *stats = mvm->ftm_resp_stats; + mutex_unlock(&mvm->mutex); + + stats->filled = BIT(NL80211_FTM_STATS_SUCCESS_NUM) | + BIT(NL80211_FTM_STATS_PARTIAL_NUM) | + BIT(NL80211_FTM_STATS_FAILED_NUM) | + BIT(NL80211_FTM_STATS_ASAP_NUM) | + BIT(NL80211_FTM_STATS_NON_ASAP_NUM) | + BIT(NL80211_FTM_STATS_TOTAL_DURATION_MSEC) | + BIT(NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM) | + BIT(NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM) | + BIT(NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM); + + return 0; +} + static bool iwl_mvm_can_hw_csum(struct sk_buff *skb) { u8 protocol = ip_hdr(skb)->protocol; @@ -4915,6 +4997,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { #endif .get_survey = iwl_mvm_mac_get_survey, .sta_statistics = iwl_mvm_mac_sta_statistics, + .get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats, + .can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate, #ifdef CONFIG_IWLWIFI_DEBUGFS .sta_add_debugfs = iwl_mvm_sta_add_debugfs, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index ee61f4a00c5e..2bd330a093fb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1150,6 +1150,8 @@ struct iwl_mvm { u32 ciphers[IWL_MVM_NUM_CIPHERS]; struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; + struct cfg80211_ftm_responder_stats ftm_resp_stats; + struct ieee80211_vif *nan_vif; #define IWL_MAX_BAID 32 struct iwl_mvm_baid_data __rcu *baid_map[IWL_MAX_BAID]; @@ -2060,6 +2062,13 @@ void iwl_mvm_update_changed_regdom(struct iwl_mvm *mvm); int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool added_vif); +/* FTM responder */ +int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); +void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); + /* TDLS */ /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 8a16388c3a0b..d5644d252fe0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -300,6 +300,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER_ASYNC_LOCKED), RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, RX_HANDLER_SYNC), + RX_HANDLER_GRP(LOCATION_GROUP, TOF_RESPONDER_STATS, + iwl_mvm_ftm_responder_stats, RX_HANDLER_ASYNC_LOCKED), RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF, iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC), RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, -- cgit v1.2.3 From fc36ffda326706b21f70a4aff0c77d9bc94c4f0a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 5 Dec 2018 11:33:34 +0100 Subject: iwlwifi: mvm: support FTM initiator Add support for FTM initiator, i.e. peer measurements with FTM if the firmware supports FTM. Additionally, add two defines we depend on in include/linux/ieee80211.h. Signed-off-by: Johannes Berg Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/location.h | 10 +- drivers/net/wireless/intel/iwlwifi/mvm/Makefile | 3 +- drivers/net/wireless/intel/iwlwifi/mvm/constants.h | 3 + .../net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 459 +++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 56 ++- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 16 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 7 + include/linux/ieee80211.h | 2 + 8 files changed, 552 insertions(+), 4 deletions(-) create mode 100644 drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 6da91ec0df55..10cac5f987e7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -7,6 +7,7 @@ * * Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,6 +29,7 @@ * * Copyright(c) 2015 - 2017 Intel Deutschland GmbH * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -403,7 +405,10 @@ enum iwl_tof_response_mode { * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A: use antenna A fo TX ACKs during FTM * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B: use antenna B fo TX ACKs during FTM * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C: use antenna C fo TX ACKs during FTM - * @IWL_TOF_INITIATOR_FLAGS_MINDELTA_NO_PREF: no preference for minDeltaFTM + * @IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB: use the specific calib value from + * the range request command + * @IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB: use the common calib value from the + * ragne request command */ enum iwl_tof_initiator_flags { IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED = BIT(0), @@ -413,7 +418,8 @@ enum iwl_tof_initiator_flags { IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A = BIT(4), IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B = BIT(5), IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C = BIT(6), - IWL_TOF_INITIATOR_FLAGS_MINDELTA_NO_PREF = BIT(7), + IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB = BIT(15), + IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB = BIT(16), }; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ #define IWL_MVM_TOF_MAX_APS 5 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile index 56e8d073f5aa..dd268c4bd371 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/Makefile +++ b/drivers/net/wireless/intel/iwlwifi/mvm/Makefile @@ -4,7 +4,8 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o iwlmvm-y += scan.o time-event.o rs.o rs-fw.o iwlmvm-y += power.o coex.o -iwlmvm-y += tt.o offloading.o tdls.o ftm-responder.o +iwlmvm-y += tt.o offloading.o tdls.o +iwlmvm-y += ftm-responder.o ftm-initiator.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o iwlmvm-$(CONFIG_PM) += d3.o diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index d96ada3c06fc..58e29af12a14 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -63,6 +63,7 @@ #define __MVM_CONSTANTS_H #include +#include "fw-api.h" #define IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM 20 @@ -145,5 +146,7 @@ #define IWL_MVM_RS_TPC_SR_NO_INCREASE 85 /* percent */ #define IWL_MVM_RS_TPC_TX_POWER_STEP 3 #define IWL_MVM_ENABLE_EBS 1 +#define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE +#define IWL_MVM_FTM_INITIATOR_DYNACK true #endif /* __MVM_CONSTANTS_H */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c new file mode 100644 index 000000000000..eb6f084a0f8a --- /dev/null +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -0,0 +1,459 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2019 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2015 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2019 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include +#include +#include +#include "mvm.h" +#include "iwl-io.h" +#include "iwl-prph.h" +#include "constants.h" + +struct iwl_mvm_loc_entry { + struct list_head list; + u8 addr[ETH_ALEN]; + u8 lci_len, civic_len; + u8 buf[]; +}; + +static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm) +{ + struct iwl_mvm_loc_entry *e, *t; + + mvm->ftm_initiator.req = NULL; + mvm->ftm_initiator.req_wdev = NULL; + memset(mvm->ftm_initiator.responses, 0, + sizeof(mvm->ftm_initiator.responses)); + list_for_each_entry_safe(e, t, &mvm->ftm_initiator.loc_list, list) { + list_del(&e->list); + kfree(e); + } +} + +void iwl_mvm_ftm_restart(struct iwl_mvm *mvm) +{ + struct cfg80211_pmsr_result result = { + .status = NL80211_PMSR_STATUS_FAILURE, + .final = 1, + .host_time = ktime_get_boot_ns(), + .type = NL80211_PMSR_TYPE_FTM, + }; + int i; + + lockdep_assert_held(&mvm->mutex); + + if (!mvm->ftm_initiator.req) + return; + + for (i = 0; i < mvm->ftm_initiator.req->n_peers; i++) { + memcpy(result.addr, mvm->ftm_initiator.req->peers[i].addr, + ETH_ALEN); + result.ftm.burst_index = mvm->ftm_initiator.responses[i]; + + cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev, + mvm->ftm_initiator.req, + &result, GFP_KERNEL); + } + + cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev, + mvm->ftm_initiator.req, GFP_KERNEL); + iwl_mvm_ftm_reset(mvm); +} + +static int +iwl_ftm_range_request_status_to_err(enum iwl_tof_range_request_status s) +{ + switch (s) { + case IWL_TOF_RANGE_REQUEST_STATUS_SUCCESS: + return 0; + case IWL_TOF_RANGE_REQUEST_STATUS_BUSY: + return -EBUSY; + default: + WARN_ON_ONCE(1); + return -EIO; + } +} + +int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) +{ + struct iwl_tof_range_req_cmd cmd = { + .request_id = req->cookie, + .req_timeout = DIV_ROUND_UP(req->timeout, 100), + .num_of_ap = req->n_peers, + /* + * We treat it always as random, since if not we'll + * have filled our local address there instead. + */ + .macaddr_random = 1, + }; + struct iwl_host_cmd hcmd = { + .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), + .data[0] = &cmd, + .len[0] = sizeof(cmd), + .dataflags[0] = IWL_HCMD_DFL_DUP, + }; + u32 status = 0; + int err, i; + + /* use maximum for "no timeout" or bigger than what we can do */ + if (!req->timeout || req->timeout > 255 * 100) + cmd.req_timeout = 255; + + lockdep_assert_held(&mvm->mutex); + + if (mvm->ftm_initiator.req) + return -EBUSY; + + memcpy(cmd.macaddr_template, req->mac_addr, ETH_ALEN); + for (i = 0; i < ETH_ALEN; i++) + cmd.macaddr_mask[i] = ~req->mac_addr_mask[i]; + + for (i = 0; i < cmd.num_of_ap; i++) { + struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; + struct iwl_tof_range_req_ap_entry *cmd_target = &cmd.ap[i]; + u32 freq = peer->chandef.chan->center_freq; + + cmd_target->channel_num = ieee80211_frequency_to_channel(freq); + switch (peer->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + cmd_target->bandwidth = IWL_TOF_BW_20_LEGACY; + break; + case NL80211_CHAN_WIDTH_20: + cmd_target->bandwidth = IWL_TOF_BW_20_HT; + break; + case NL80211_CHAN_WIDTH_40: + cmd_target->bandwidth = IWL_TOF_BW_40; + break; + case NL80211_CHAN_WIDTH_80: + cmd_target->bandwidth = IWL_TOF_BW_80; + break; + default: + IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n", + peer->chandef.width); + return -EINVAL; + } + cmd_target->ctrl_ch_position = + (peer->chandef.width > NL80211_CHAN_WIDTH_20) ? + iwl_mvm_get_ctrl_pos(&peer->chandef) : 0; + + memcpy(cmd_target->bssid, peer->addr, ETH_ALEN); + cmd_target->measure_type = 0; /* regular two-sided FTM */ + cmd_target->num_of_bursts = peer->ftm.num_bursts_exp; + cmd_target->burst_period = + cpu_to_le16(peer->ftm.burst_period); + cmd_target->samples_per_burst = peer->ftm.ftms_per_burst; + cmd_target->retries_per_sample = peer->ftm.ftmr_retries; + cmd_target->asap_mode = peer->ftm.asap; + cmd_target->enable_dyn_ack = IWL_MVM_FTM_INITIATOR_DYNACK; + + if (peer->ftm.request_lci) + cmd_target->location_req |= IWL_TOF_LOC_LCI; + if (peer->ftm.request_civicloc) + cmd_target->location_req |= IWL_TOF_LOC_CIVIC; + + cmd_target->algo_type = IWL_MVM_FTM_INITIATOR_ALGO; + } + + if (vif->bss_conf.assoc) + memcpy(cmd.range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); + else + eth_broadcast_addr(cmd.range_req_bssid); + + err = iwl_mvm_send_cmd_status(mvm, &hcmd, &status); + if (!err && status) { + IWL_ERR(mvm, "FTM range request command failure, status: %u\n", + status); + err = iwl_ftm_range_request_status_to_err(status); + } + + if (!err) { + mvm->ftm_initiator.req = req; + mvm->ftm_initiator.req_wdev = ieee80211_vif_to_wdev(vif); + } + + return err; +} + +void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req) +{ + struct iwl_tof_range_abort_cmd cmd = { + .request_id = req->cookie, + }; + + lockdep_assert_held(&mvm->mutex); + + if (req != mvm->ftm_initiator.req) + return; + + if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RANGE_ABORT_CMD, + LOCATION_GROUP, 0), + 0, sizeof(cmd), &cmd)) + IWL_ERR(mvm, "failed to abort FTM process\n"); +} + +static int iwl_mvm_ftm_find_peer(struct cfg80211_pmsr_request *req, + const u8 *addr) +{ + int i; + + for (i = 0; i < req->n_peers; i++) { + struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; + + if (ether_addr_equal_unaligned(peer->addr, addr)) + return i; + } + + return -ENOENT; +} + +static u64 iwl_mvm_ftm_get_host_time(struct iwl_mvm *mvm, __le32 fw_gp2_ts) +{ + u32 gp2_ts = le32_to_cpu(fw_gp2_ts); + u32 curr_gp2, diff; + u64 now_from_boot_ns; + + iwl_mvm_get_sync_time(mvm, &curr_gp2, &now_from_boot_ns); + + if (curr_gp2 >= gp2_ts) + diff = curr_gp2 - gp2_ts; + else + diff = curr_gp2 + (U32_MAX - gp2_ts + 1); + + return now_from_boot_ns - (u64)diff * 1000; +} + +static void iwl_mvm_ftm_get_lci_civic(struct iwl_mvm *mvm, + struct cfg80211_pmsr_result *res) +{ + struct iwl_mvm_loc_entry *entry; + + list_for_each_entry(entry, &mvm->ftm_initiator.loc_list, list) { + if (!ether_addr_equal_unaligned(res->addr, entry->addr)) + continue; + + if (entry->lci_len) { + res->ftm.lci_len = entry->lci_len; + res->ftm.lci = entry->buf; + } + + if (entry->civic_len) { + res->ftm.civicloc_len = entry->civic_len; + res->ftm.civicloc = entry->buf + entry->lci_len; + } + + /* we found the entry we needed */ + break; + } +} + +void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_tof_range_rsp_ntfy *fw_resp = (void *)pkt->data; + int i; + + lockdep_assert_held(&mvm->mutex); + + if (!mvm->ftm_initiator.req) { + IWL_ERR(mvm, "Got FTM response but have no request?\n"); + return; + } + + if (fw_resp->request_id != (u8)mvm->ftm_initiator.req->cookie) { + IWL_ERR(mvm, "Request ID mismatch, got %u, active %u\n", + fw_resp->request_id, + (u8)mvm->ftm_initiator.req->cookie); + return; + } + + if (fw_resp->num_of_aps > mvm->ftm_initiator.req->n_peers) { + IWL_ERR(mvm, "FTM range response invalid\n"); + return; + } + + for (i = 0; i < fw_resp->num_of_aps && i < IWL_MVM_TOF_MAX_APS; i++) { + struct iwl_tof_range_rsp_ap_entry_ntfy *fw_ap = &fw_resp->ap[i]; + struct cfg80211_pmsr_result result = {}; + int peer_idx; + + peer_idx = iwl_mvm_ftm_find_peer(mvm->ftm_initiator.req, + fw_ap->bssid); + if (peer_idx < 0) { + IWL_WARN(mvm, + "Unknown address (%pM, target #%d) in FTM response.\n", + fw_ap->bssid, i); + continue; + } + + switch (fw_ap->measure_status) { + case IWL_TOF_ENTRY_SUCCESS: + result.status = NL80211_PMSR_STATUS_SUCCESS; + break; + case IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT: + result.status = NL80211_PMSR_STATUS_TIMEOUT; + break; + case IWL_TOF_ENTRY_NO_RESPONSE: + result.status = NL80211_PMSR_STATUS_FAILURE; + result.ftm.failure_reason = + NL80211_PMSR_FTM_FAILURE_NO_RESPONSE; + break; + case IWL_TOF_ENTRY_REQUEST_REJECTED: + result.status = NL80211_PMSR_STATUS_FAILURE; + result.ftm.failure_reason = + NL80211_PMSR_FTM_FAILURE_PEER_BUSY; + result.ftm.busy_retry_time = fw_ap->refusal_period; + break; + default: + result.status = NL80211_PMSR_STATUS_FAILURE; + result.ftm.failure_reason = + NL80211_PMSR_FTM_FAILURE_UNSPECIFIED; + break; + } + memcpy(result.addr, fw_ap->bssid, ETH_ALEN); + result.host_time = iwl_mvm_ftm_get_host_time(mvm, + fw_ap->timestamp); + result.type = NL80211_PMSR_TYPE_FTM; + result.ftm.burst_index = mvm->ftm_initiator.responses[peer_idx]; + mvm->ftm_initiator.responses[peer_idx]++; + /* + * FIXME: the firmware needs to report this, we don't even know + * the number of bursts the responder picked (if we asked + * it to) + */ + result.final = 0; + result.ftm.rssi_avg = fw_ap->rssi; + result.ftm.rssi_avg_valid = 1; + result.ftm.rssi_spread = fw_ap->rssi_spread; + result.ftm.rssi_spread_valid = 1; + result.ftm.rtt_avg = (s32)le32_to_cpu(fw_ap->rtt); + result.ftm.rtt_avg_valid = 1; + result.ftm.rtt_variance = le32_to_cpu(fw_ap->rtt_variance); + result.ftm.rtt_variance_valid = 1; + result.ftm.rtt_spread = le32_to_cpu(fw_ap->rtt_spread); + result.ftm.rtt_spread_valid = 1; + + iwl_mvm_ftm_get_lci_civic(mvm, &result); + + cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev, + mvm->ftm_initiator.req, + &result, GFP_KERNEL); + } + + if (fw_resp->last_in_batch) { + cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev, + mvm->ftm_initiator.req, + GFP_KERNEL); + iwl_mvm_ftm_reset(mvm); + } +} + +void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + const struct ieee80211_mgmt *mgmt = (void *)pkt->data; + size_t len = iwl_rx_packet_payload_len(pkt); + struct iwl_mvm_loc_entry *entry; + const u8 *ies, *lci, *civic, *msr_ie; + size_t ies_len, lci_len = 0, civic_len = 0; + size_t baselen = IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.ftm); + static const u8 rprt_type_lci = IEEE80211_SPCT_MSR_RPRT_TYPE_LCI; + static const u8 rprt_type_civic = IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC; + + if (len <= baselen) + return; + + lockdep_assert_held(&mvm->mutex); + + ies = mgmt->u.action.u.ftm.variable; + ies_len = len - baselen; + + msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len, + &rprt_type_lci, 1, 4); + if (msr_ie) { + lci = msr_ie + 2; + lci_len = msr_ie[1]; + } + + msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len, + &rprt_type_civic, 1, 4); + if (msr_ie) { + civic = msr_ie + 2; + civic_len = msr_ie[1]; + } + + entry = kmalloc(sizeof(*entry) + lci_len + civic_len, GFP_KERNEL); + if (!entry) + return; + + memcpy(entry->addr, mgmt->bssid, ETH_ALEN); + + entry->lci_len = lci_len; + if (lci_len) + memcpy(entry->buf, lci, lci_len); + + entry->civic_len = civic_len; + if (civic_len) + memcpy(entry->buf + lci_len, civic, civic_len); + + list_add_tail(&entry->list, &mvm->ftm_initiator.loc_list); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index cba1a0fe33ca..9377fca39edf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -184,6 +184,29 @@ static const struct iwl_fw_bcast_filter iwl_mvm_default_bcast_filters[] = { }; #endif +static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = { + .max_peers = IWL_MVM_TOF_MAX_APS, + .report_ap_tsf = 1, + .randomize_mac_addr = 1, + + .ftm = { + .supported = 1, + .asap = 1, + .non_asap = 1, + .request_lci = 1, + .request_civicloc = 1, + .max_bursts_exponent = -1, /* all supported */ + .max_ftms_per_burst = 0, /* no limits */ + .bandwidths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80), + .preambles = BIT(NL80211_PREAMBLE_LEGACY) | + BIT(NL80211_PREAMBLE_HT) | + BIT(NL80211_PREAMBLE_VHT), + }, +}; + void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type) { if (!iwl_mvm_is_d0i3_supported(mvm)) @@ -549,9 +572,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) } if (fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) + IWL_UCODE_TLV_CAPA_FTM_CALIBRATED)) { wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); + hw->wiphy->pmsr_capa = &iwl_mvm_pmsr_capa; + } ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); hw->wiphy->features |= @@ -1186,6 +1211,8 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) iwl_mvm_cleanup_roc_te(mvm); ieee80211_remain_on_channel_expired(mvm->hw); + iwl_mvm_ftm_restart(mvm); + /* * cleanup all interfaces, even inactive ones, as some might have * gone down during the HW restart @@ -4895,6 +4922,31 @@ iwl_mvm_mac_get_ftm_responder_stats(struct ieee80211_hw *hw, return 0; } +static int iwl_mvm_start_pmsr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *request) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + int ret; + + mutex_lock(&mvm->mutex); + ret = iwl_mvm_ftm_start(mvm, vif, request); + mutex_unlock(&mvm->mutex); + + return ret; +} + +static void iwl_mvm_abort_pmsr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *request) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + mutex_lock(&mvm->mutex); + iwl_mvm_ftm_abort(mvm, request); + mutex_unlock(&mvm->mutex); +} + static bool iwl_mvm_can_hw_csum(struct sk_buff *skb) { u8 protocol = ip_hdr(skb)->protocol; @@ -4998,6 +5050,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .get_survey = iwl_mvm_mac_get_survey, .sta_statistics = iwl_mvm_mac_sta_statistics, .get_ftm_responder_stats = iwl_mvm_mac_get_ftm_responder_stats, + .start_pmsr = iwl_mvm_start_pmsr, + .abort_pmsr = iwl_mvm_abort_pmsr, .can_aggregate_in_amsdu = iwl_mvm_mac_can_aggregate, #ifdef CONFIG_IWLWIFI_DEBUGFS diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 2bd330a093fb..e9873fc7bd2b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1151,6 +1151,12 @@ struct iwl_mvm { struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS]; struct cfg80211_ftm_responder_stats ftm_resp_stats; + struct { + struct cfg80211_pmsr_request *req; + struct wireless_dev *req_wdev; + struct list_head loc_list; + int responses[IWL_MVM_TOF_MAX_APS]; + } ftm_initiator; struct ieee80211_vif *nan_vif; #define IWL_MAX_BAID 32 @@ -2069,6 +2075,16 @@ void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm, void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +/* FTM initiator */ +void iwl_mvm_ftm_restart(struct iwl_mvm *mvm); +void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); +int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *request); +void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req); + /* TDLS */ /* diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index d5644d252fe0..0c276124bf0f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -302,6 +302,12 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER_SYNC), RX_HANDLER_GRP(LOCATION_GROUP, TOF_RESPONDER_STATS, iwl_mvm_ftm_responder_stats, RX_HANDLER_ASYNC_LOCKED), + + RX_HANDLER_GRP(LOCATION_GROUP, TOF_RANGE_RESPONSE_NOTIF, + iwl_mvm_ftm_range_resp, RX_HANDLER_ASYNC_LOCKED), + RX_HANDLER_GRP(LOCATION_GROUP, TOF_LC_NOTIF, + iwl_mvm_ftm_lc_notif, RX_HANDLER_ASYNC_LOCKED), + RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF, iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC), RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, @@ -693,6 +699,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, INIT_LIST_HEAD(&mvm->aux_roc_te_list); INIT_LIST_HEAD(&mvm->async_handlers_list); spin_lock_init(&mvm->time_event_lock); + INIT_LIST_HEAD(&mvm->ftm_initiator.loc_list); INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 3b04e72315e1..f1f66e675ca1 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -2118,6 +2118,8 @@ ieee80211_he_oper_size(const u8 *he_oper_ie) #define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 #define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 #define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_LCI 8 +#define IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC 11 /* 802.11g ERP information element */ #define WLAN_ERP_NON_ERP_PRESENT (1<<0) -- cgit v1.2.3 From ed714460a0ecd1d382a4cda1247fd6eb2666de28 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Dec 2018 10:40:45 +0100 Subject: iwlwifi: mvm: clean up NO_PSDU case We now no longer have any special code in iwl_mvm_pass_packet_to_mac80211(), so don't need to pass NO_PSDU packets through it. Stop doing so and clean up the code there. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 957d99932e8b..557a0b5a08ac 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -258,10 +258,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, struct ieee80211_sta *sta, bool csi) { - struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); - - if (!(rx_status->flag & RX_FLAG_NO_PSDU) && - iwl_mvm_check_pn(mvm, skb, queue, sta)) + if (iwl_mvm_check_pn(mvm, skb, queue, sta)) kfree_skb(skb); else ieee80211_rx_napi(mvm->hw, sta, skb, napi); @@ -1800,7 +1797,7 @@ void iwl_mvm_rx_monitor_ndp(struct iwl_mvm *mvm, struct napi_struct *napi, rx_status->rate_idx = rate; } - iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta, false); + ieee80211_rx_napi(mvm->hw, sta, skb, napi); out: rcu_read_unlock(); } -- cgit v1.2.3 From 22463857a16b43719e9845b47f6992d13376b2e0 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 24 Apr 2018 13:35:59 +0300 Subject: iwlwifi: receive umac and lmac error table addresses from TLVs TLV 54 holds umac debug related addresses. TLV 55 holds lmac debug related addresses. These TLVs aim to replace the alive notification data in the future. Parse and keep error table addresses received from the TLVs for both lmac and umac and use these addresses instead of the pointer received from alive notification. The feature supports only unified image. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/alive.h | 28 +++++++++++------- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 20 +++++++++++++ drivers/net/wireless/intel/iwlwifi/fw/file.h | 2 ++ drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 35 +++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 10 +++++++ drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 23 +++++++++------ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 -- drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 12 ++++---- 9 files changed, 107 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h index 08d3d8a190f6..0026e259fd87 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h @@ -96,14 +96,7 @@ enum { #define IWL_ALIVE_FLG_RFKILL BIT(0) -struct iwl_lmac_alive { - __le32 ucode_major; - __le32 ucode_minor; - u8 ver_subtype; - u8 ver_type; - u8 mac; - u8 opt; - __le32 timestamp; +struct iwl_lmac_debug_addrs { __le32 error_event_table_ptr; /* SRAM address for error log */ __le32 log_event_table_ptr; /* SRAM address for LMAC event log */ __le32 cpu_register_ptr; @@ -112,13 +105,28 @@ struct iwl_lmac_alive { __le32 scd_base_ptr; /* SRAM address for SCD */ __le32 st_fwrd_addr; /* pointer to Store and forward */ __le32 st_fwrd_size; +} __packed; /* UCODE_DEBUG_ADDRS_API_S_VER_2 */ + +struct iwl_lmac_alive { + __le32 ucode_major; + __le32 ucode_minor; + u8 ver_subtype; + u8 ver_type; + u8 mac; + u8 opt; + __le32 timestamp; + struct iwl_lmac_debug_addrs dbg_ptrs; } __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */ +struct iwl_umac_debug_addrs { + __le32 error_info_addr; /* SRAM address for UMAC error log */ + __le32 dbg_print_buff_addr; +} __packed; /* UMAC_DEBUG_ADDRS_API_S_VER_1 */ + struct iwl_umac_alive { __le32 umac_major; /* UMAC version: major */ __le32 umac_minor; /* UMAC version: minor */ - __le32 error_info_addr; /* SRAM address for UMAC error log */ - __le32 dbg_print_buff_addr; + struct iwl_umac_debug_addrs dbg_ptrs; } __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */ struct mvm_alive_resp_v3 { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index a6133b5f9e83..d11923edd695 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -442,6 +442,26 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt); +static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans, + u32 lmac_error_event_table) +{ + if (!(trans->error_event_table_tlv_status & + IWL_ERROR_EVENT_TABLE_LMAC1) || + WARN_ON(trans->lmac_error_event_table[0] != + lmac_error_event_table)) + trans->lmac_error_event_table[0] = lmac_error_event_table; +} + +static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans, + u32 umac_error_event_table) +{ + if (!(trans->error_event_table_tlv_status & + IWL_ERROR_EVENT_TABLE_UMAC) || + WARN_ON(trans->umac_error_event_table != + umac_error_event_table)) + trans->umac_error_event_table = umac_error_event_table; +} + /* This bit is used to differentiate the legacy dump from the ini dump */ #define INI_DUMP_BIT BIT(31) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 3bffb0f7a5e5..886a620e03cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -143,6 +143,8 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_FW_GSCAN_CAPA = 50, IWL_UCODE_TLV_FW_MEM_SEG = 51, IWL_UCODE_TLV_IML = 52, + IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54, + IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55, IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1, IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2, IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 2efa1dfe9b4c..784e07b648e6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -75,6 +75,7 @@ #include "iwl-dbg-tlv.h" #include "iwl-config.h" #include "iwl-modparams.h" +#include "fw/api/alive.h" /****************************************************************************** * @@ -588,6 +589,8 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv, return 0; } +#define FW_ADDR_CACHE_CONTROL 0xC0000000 + static int iwl_parse_tlv_firmware(struct iwl_drv *drv, const struct firmware *ucode_raw, struct iwl_firmware_pieces *pieces, @@ -1085,6 +1088,38 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, return -ENOMEM; break; } + case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: { + struct iwl_umac_debug_addrs *dbg_ptrs = + (void *)tlv_data; + + if (tlv_len != sizeof(*dbg_ptrs)) + goto invalid_tlv_len; + if (drv->trans->cfg->device_family < + IWL_DEVICE_FAMILY_22000) + break; + drv->trans->umac_error_event_table = + le32_to_cpu(dbg_ptrs->error_info_addr) & + ~FW_ADDR_CACHE_CONTROL; + drv->trans->error_event_table_tlv_status |= + IWL_ERROR_EVENT_TABLE_UMAC; + break; + } + case IWL_UCODE_TLV_LMAC_DEBUG_ADDRS: { + struct iwl_lmac_debug_addrs *dbg_ptrs = + (void *)tlv_data; + + if (tlv_len != sizeof(*dbg_ptrs)) + goto invalid_tlv_len; + if (drv->trans->cfg->device_family < + IWL_DEVICE_FAMILY_22000) + break; + drv->trans->lmac_error_event_table[0] = + le32_to_cpu(dbg_ptrs->error_event_table_ptr) & + ~FW_ADDR_CACHE_CONTROL; + drv->trans->error_event_table_tlv_status |= + IWL_ERROR_EVENT_TABLE_LMAC1; + break; + } case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION: case IWL_UCODE_TLV_TYPE_HCMD: case IWL_UCODE_TLV_TYPE_REGIONS: diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index ef23c6aafb5c..bbebbf3efd57 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -232,6 +232,12 @@ enum iwl_hcmd_dataflag { IWL_HCMD_DFL_DUP = BIT(1), }; +enum iwl_error_event_table_status { + IWL_ERROR_EVENT_TABLE_LMAC1 = BIT(0), + IWL_ERROR_EVENT_TABLE_LMAC2 = BIT(1), + IWL_ERROR_EVENT_TABLE_UMAC = BIT(2), +}; + /** * struct iwl_host_cmd - Host command to the uCode * @@ -759,6 +765,10 @@ struct iwl_self_init_dram { * mode is set during the initialization phase and is not * supposed to change during runtime. * @dbg_rec_on: true iff there is a fw debug recording currently active + * @lmac_error_event_table: addrs of lmacs error tables + * @umac_error_event_table: addr of umac error table + * @error_event_table_tlv_status: bitmap that indicates what error table + * pointers was recevied via TLV. use enum &iwl_error_event_table_status */ struct iwl_trans { const struct iwl_trans_ops *ops; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 36ed7d6fc971..808bc6f363d0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1899,7 +1899,7 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { - u32 base = mvm->error_event_table[0]; + u32 base = mvm->trans->lmac_error_event_table[0]; struct error_table_start { /* cf. struct iwl_error_event_table */ u32 valid; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 8140b193cc05..cf7f8c340ffe 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -218,7 +218,7 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, struct iwl_lmac_alive *lmac1; struct iwl_lmac_alive *lmac2 = NULL; u16 status; - u32 umac_error_event_table; + u32 lmac_error_event_table, umac_error_event_table; if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) { palive = (void *)pkt->data; @@ -233,30 +233,35 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, status = le16_to_cpu(palive3->status); } - mvm->error_event_table[0] = le32_to_cpu(lmac1->error_event_table_ptr); + lmac_error_event_table = + le32_to_cpu(lmac1->dbg_ptrs.error_event_table_ptr); + iwl_fw_lmac1_set_alive_err_table(mvm->trans, lmac_error_event_table); + if (lmac2) - mvm->error_event_table[1] = - le32_to_cpu(lmac2->error_event_table_ptr); - mvm->log_event_table = le32_to_cpu(lmac1->log_event_table_ptr); + mvm->trans->lmac_error_event_table[1] = + le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr); - umac_error_event_table = le32_to_cpu(umac->error_info_addr); + umac_error_event_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr); if (!umac_error_event_table) { mvm->support_umac_log = false; } else if (umac_error_event_table >= mvm->trans->cfg->min_umac_error_event_table) { mvm->support_umac_log = true; - mvm->umac_error_event_table = umac_error_event_table; } else { IWL_ERR(mvm, "Not valid error log pointer 0x%08X for %s uCode\n", - mvm->umac_error_event_table, + umac_error_event_table, (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ? "Init" : "RT"); mvm->support_umac_log = false; } - alive_data->scd_base_addr = le32_to_cpu(lmac1->scd_base_ptr); + if (mvm->support_umac_log) + iwl_fw_umac_set_alive_err_table(mvm->trans, + umac_error_event_table); + + alive_data->scd_base_addr = le32_to_cpu(lmac1->dbg_ptrs.scd_base_ptr); alive_data->valid = status == IWL_ALIVE_STATUS_OK; IWL_DEBUG_FW(mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index e9873fc7bd2b..0255157378db 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -879,9 +879,6 @@ struct iwl_mvm { bool hw_registered; bool calibrating; - u32 error_event_table[2]; - u32 log_event_table; - u32 umac_error_event_table; bool support_umac_log; u32 ampdu_ref; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 4a18997fb48a..4649327abb45 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -457,12 +457,14 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm) { struct iwl_trans *trans = mvm->trans; struct iwl_umac_error_event_table table; + u32 base = mvm->trans->umac_error_event_table; - if (!mvm->support_umac_log) + if (!mvm->support_umac_log && + !(mvm->trans->error_event_table_tlv_status & + IWL_ERROR_EVENT_TABLE_UMAC)) return; - iwl_trans_read_mem_bytes(trans, mvm->umac_error_event_table, &table, - sizeof(table)); + iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table)); if (table.valid) mvm->fwrt.dump.umac_err_id = table.error_id; @@ -494,7 +496,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num) { struct iwl_trans *trans = mvm->trans; struct iwl_error_event_table table; - u32 val, base = mvm->error_event_table[lmac_num]; + u32 val, base = mvm->trans->lmac_error_event_table[lmac_num]; if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) { if (!base) @@ -590,7 +592,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) iwl_mvm_dump_lmac_error_log(mvm, 0); - if (mvm->error_event_table[1]) + if (mvm->trans->lmac_error_event_table[1]) iwl_mvm_dump_lmac_error_log(mvm, 1); iwl_mvm_dump_umac_error_log(mvm); -- cgit v1.2.3 From b61a6610922272dce0cf4dc43b576919b7b0593c Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 21 Nov 2018 10:45:05 +0200 Subject: iwlwifi: dbg_ini: rewrite trigger flow and align to FW API changes Trigger field ignore_default was changed to override_trig. The first byte of the field indicates the driver to override existing configuration or keep the previous one The second byte of the field indicated the driver to replace the regions of the previous trigger or to append new regions to it. Change the way the active triggers are maintained to support trigger override in different apply points. Do this by making a trigger that updates at runtime by the triggers that are being used in the different apply points. In case of an assert, the driver does not reconfigure the triggers and uses the old configuration which leads to undefined behavior. Solve this by clearing the triggers in assert recovery flow. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 11 +- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 116 ++++++++++++++------- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 7 +- drivers/net/wireless/intel/iwlwifi/fw/img.h | 10 +- drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 12 +++ 5 files changed, 107 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index 75e23c426be8..70cc0820e068 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -204,8 +204,13 @@ struct iwl_fw_ini_region_tlv { * struct iwl_fw_ini_trigger - (IWL_FW_INI_TLV_TYPE_DUMP_CFG) * Region sections define IDs and triggers that use those IDs TLV * - * @trigger_id: enum &iwl_fw_ini_trigger_id - * @ignore_default: override FW TLV with binary TLV + * @trigger_id: enum &iwl_fw_ini_tigger_id + * @override_trig: determines how apply trigger in case a trigger with the + * same id is already in use. Using the first 2 bytes: + * Byte 0: if 0, override trigger configuration, otherwise use the + * existing configuration. + * Byte 1: if 0, override trigger regions, otherwise append regions to + * existing trigger. * @dump_delay: delay from trigger fire to dump, in usec * @occurrences: max amount of times to be fired * @ignore_consec: ignore consecutive triggers, in usec @@ -217,7 +222,7 @@ struct iwl_fw_ini_region_tlv { */ struct iwl_fw_ini_trigger { __le32 trigger_id; - __le32 ignore_default; + __le32 override_trig; __le32 dump_delay; __le32 occurrences; __le32 ignore_consec; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 512af6128fa5..728fe051745b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1473,20 +1473,19 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type); struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_file *dump_file; - struct iwl_fw_ini_trigger *trigger, *ext; + struct iwl_fw_ini_trigger *trigger; if (id == FW_DBG_TRIGGER_FW_ASSERT) id = IWL_FW_TRIGGER_ID_FW_ASSERT; - if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) + if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs)) || + !fwrt->dump.active_trigs[id].active) return NULL; - trigger = fwrt->dump.active_trigs[id].conf; - ext = fwrt->dump.active_trigs[id].conf_ext; + trigger = fwrt->dump.active_trigs[id].trig; size = sizeof(*dump_file); size += iwl_fw_ini_get_trigger_len(fwrt, trigger); - size += iwl_fw_ini_get_trigger_len(fwrt, ext); if (!size) return NULL; @@ -1501,10 +1500,7 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, dump_data = (void *)dump_file->data; dump_file->file_len = cpu_to_le32(size); - if (trigger) - iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data); - if (ext) - iwl_fw_ini_dump_trigger(fwrt, ext, &dump_data); + iwl_fw_ini_dump_trigger(fwrt, trigger, &dump_data); return dump_file; } @@ -1696,6 +1692,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, u32 id, const char *str, size_t len) { struct iwl_fw_dump_desc *desc; + struct iwl_fw_ini_active_triggers *active; u32 occur, delay; if (!fwrt->trans->ini_valid) @@ -1704,15 +1701,17 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, if (id == FW_DBG_TRIGGER_USER) id = IWL_FW_TRIGGER_ID_USER_TRIGGER; - if (WARN_ON(!fwrt->dump.active_trigs[id].active)) + active = &fwrt->dump.active_trigs[id]; + + if (WARN_ON(!active->active)) return -EINVAL; - delay = le32_to_cpu(fwrt->dump.active_trigs[id].conf->dump_delay); - occur = le32_to_cpu(fwrt->dump.active_trigs[id].conf->occurrences); + delay = le32_to_cpu(active->trig->dump_delay); + occur = le32_to_cpu(active->trig->occurrences); if (!occur) return 0; - if (le32_to_cpu(fwrt->dump.active_trigs[id].conf->force_restart)) { + if (le32_to_cpu(active->trig->force_restart)) { IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id); iwl_force_nmi(fwrt->trans); return 0; @@ -1722,8 +1721,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, if (!desc) return -ENOMEM; - occur--; - fwrt->dump.active_trigs[id].conf->occurrences = cpu_to_le32(occur); + active->trig->occurrences = cpu_to_le32(--occur); desc->len = len; desc->trig_desc.type = cpu_to_le32(id); @@ -2022,6 +2020,26 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, } } +static int iwl_fw_dbg_trig_realloc(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_active_triggers *active, + u32 id, int size) +{ + void *ptr; + + if (size <= active->size) + return 0; + + ptr = krealloc(active->trig, size, GFP_KERNEL); + if (!ptr) { + IWL_ERR(fwrt, "Failed to allocate memory for trigger %d\n", id); + return -ENOMEM; + } + active->trig = ptr; + active->size = size; + + return 0; +} + static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_trigger_tlv *tlv, bool ext, @@ -2034,43 +2052,63 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_trigger *trig = iter; struct iwl_fw_ini_active_triggers *active; int id = le32_to_cpu(trig->trigger_id); - u32 num; + u32 trig_regs_size = le32_to_cpu(trig->num_regions) * + sizeof(__le32); if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) break; active = &fwrt->dump.active_trigs[id]; - if (active->apply_point != apply_point) { - active->conf = NULL; - active->conf_ext = NULL; - } + if (!active->active) { + size_t trig_size = sizeof(*trig) + trig_regs_size; + + if (iwl_fw_dbg_trig_realloc(fwrt, active, id, + trig_size)) + goto next; - num = le32_to_cpu(trig->num_regions); + memcpy(active->trig, trig, trig_size); - if (ext && active->apply_point == apply_point) { - num += le32_to_cpu(active->conf->num_regions); - if (trig->ignore_default) { - active->conf_ext = active->conf; - active->conf = trig; + } else { + u32 conf_override = + !(le32_to_cpu(trig->override_trig) & 0xff); + u32 region_override = + !(le32_to_cpu(trig->override_trig) & 0xff00); + u32 offset = 0; + u32 active_regs = + le32_to_cpu(active->trig->num_regions); + u32 new_regs = le32_to_cpu(trig->num_regions); + int mem_to_add = trig_regs_size; + + if (region_override) { + mem_to_add -= active_regs * sizeof(__le32); } else { - active->conf_ext = trig; + offset += active_regs; + new_regs += active_regs; } - } else { - active->conf = trig; + + if (iwl_fw_dbg_trig_realloc(fwrt, active, id, + active->size + mem_to_add)) + goto next; + + if (conf_override) + memcpy(active->trig, trig, sizeof(*trig)); + + memcpy(active->trig->data + offset, trig->data, + trig_regs_size); + active->trig->num_regions = cpu_to_le32(new_regs); } /* Since zero means infinity - just set to -1 */ - if (!le32_to_cpu(trig->occurrences)) - trig->occurrences = cpu_to_le32(-1); - if (!le32_to_cpu(trig->ignore_consec)) - trig->ignore_consec = cpu_to_le32(-1); + if (!le32_to_cpu(active->trig->occurrences)) + active->trig->occurrences = cpu_to_le32(-1); + if (!le32_to_cpu(active->trig->ignore_consec)) + active->trig->ignore_consec = cpu_to_le32(-1); - iter += sizeof(*trig) + - le32_to_cpu(trig->num_regions) * sizeof(__le32); + active->active = true; +next: + iter += sizeof(*trig) + trig_regs_size; - active->active = num; - active->apply_point = apply_point; } } @@ -2129,6 +2167,10 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, if (apply_point == IWL_FW_INI_APPLY_EARLY) { for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++) fwrt->dump.active_regs[i] = NULL; + + /* disable the triggers, used in recovery flow */ + for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++) + fwrt->dump.active_trigs[i].active = false; } _iwl_fw_dbg_apply_point(fwrt, data, apply_point, false); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index d11923edd695..b64fdfdcbce7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -225,16 +225,17 @@ static inline bool _iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, const enum iwl_fw_dbg_trigger id) { - struct iwl_fw_ini_active_triggers *trig = &fwrt->dump.active_trigs[id]; + struct iwl_fw_ini_active_triggers *active = + &fwrt->dump.active_trigs[id]; u32 ms; if (!fwrt->trans->ini_valid) return false; - if (!trig || !trig->active) + if (!active->active) return false; - ms = le32_to_cpu(trig->conf->ignore_consec); + ms = le32_to_cpu(active->trig->ignore_consec); if (ms) ms /= USEC_PER_MSEC; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 23f982be800f..6ffa2e39a25c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -234,15 +234,13 @@ struct iwl_fw_ini_allocation_data { /** * struct iwl_fw_ini_active_triggers * @active: is this trigger active - * @apply_point: last apply point that updated this trigger - * @conf: active trigger - * @conf_ext: second trigger, contains extra regions to dump + * @size: allocated memory size of the trigger + * @trig: trigger */ struct iwl_fw_ini_active_triggers { bool active; - enum iwl_fw_ini_apply_point apply_point; - struct iwl_fw_ini_trigger *conf; - struct iwl_fw_ini_trigger *conf_ext; + size_t size; + struct iwl_fw_ini_trigger *trig; }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 52af848f2eb3..2bbae7a1f492 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -160,8 +160,20 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt) { + int i; + kfree(fwrt->dump.d3_debug_data); fwrt->dump.d3_debug_data = NULL; + + for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++) { + struct iwl_fw_ini_active_triggers *active = + &fwrt->dump.active_trigs[i]; + + active->active = false; + active->size = 0; + kfree(active->trig); + active->trig = NULL; + } } void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt); -- cgit v1.2.3 From ff911dcaa2e46627f5fc6a22802f72a8bfce4ab5 Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Mon, 19 Nov 2018 16:44:05 +0200 Subject: iwlwifi: introduce device family AX210 Add new device family AX210. Make the needed changes for this family. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 47 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/iwl-config.h | 7 ++++ drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 4 ++ drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 3 +- .../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 13 ++++-- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 8 ++++ drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 15 ++++++- .../net/wireless/intel/iwlwifi/pcie/trans-gen2.c | 7 ++-- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 17 ++++++-- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 12 +++++- 10 files changed, 119 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index e4933c355dfd..6f231d05fc1b 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -84,6 +84,10 @@ #define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-" #define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-" #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-" +#define IWL_22000_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-" +#define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-" +#define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-" +#define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-" #define IWL_22000_HR_MODULE_FIRMWARE(api) \ IWL_22000_HR_FW_PRE __stringify(api) ".ucode" @@ -107,6 +111,14 @@ IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" #define IWL_CC_A_MODULE_FIRMWARE(api) \ IWL_CC_A_FW_PRE __stringify(api) ".ucode" +#define IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(api) \ + IWL_22000_SO_A_JF_B_FW_PRE __stringify(api) ".ucode" +#define IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_22000_SO_A_HR_B_FW_PRE __stringify(api) ".ucode" +#define IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(api) \ + IWL_22000_SO_A_GF_A_FW_PRE __stringify(api) ".ucode" +#define IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(api) \ + IWL_22000_TY_A_GF_A_FW_PRE __stringify(api) ".ucode" static const struct iwl_base_params iwl_22000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_32K, @@ -179,6 +191,13 @@ static const struct iwl_ht_params iwl_22000_ht_params = { .base_params = &iwl_22560_base_params, \ .csr = &iwl_csr_v2 +#define IWL_DEVICE_AX210 \ + IWL_DEVICE_22000_COMMON, \ + .device_family = IWL_DEVICE_FAMILY_AX210, \ + .base_params = &iwl_22000_base_params, \ + .csr = &iwl_csr_v1, \ + .min_txq_size = 128 + const struct iwl_cfg iwl22000_2ac_cfg_hr = { .name = "Intel(R) Dual Band Wireless AC 22000", .fw_name_pre = IWL_22000_HR_FW_PRE, @@ -387,6 +406,30 @@ const struct iwl_cfg iwl22560_2ax_cfg_su_cdb = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, }; +const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = { + .name = "Intel(R) Wireless-AC 9560 160MHz", + .fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE, + IWL_DEVICE_AX210, +}; + +const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = { + .name = "Intel(R) Wi-Fi 6 AX201 160MHz", + .fw_name_pre = IWL_22000_SO_A_HR_B_FW_PRE, + IWL_DEVICE_AX210, +}; + +const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = { + .name = "Intel(R) Wi-Fi 7 AX211 160MHz", + .fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE, + IWL_DEVICE_AX210, +}; + +const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { + .name = "Intel(R) Wi-Fi 7 AX210 160MHz", + .fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE, + IWL_DEVICE_AX210, +}; + MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); @@ -397,3 +440,7 @@ MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 5e713730165a..d25b632eaa41 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -89,6 +89,7 @@ enum iwl_device_family { IWL_DEVICE_FAMILY_9000, IWL_DEVICE_FAMILY_22000, IWL_DEVICE_FAMILY_22560, + IWL_DEVICE_FAMILY_AX210, }; /* @@ -380,6 +381,7 @@ struct iwl_csr_params { * @d3_debug_data_base_addr: base address where D3 debug data is stored * @d3_debug_data_length: length of the D3 debug data * @bisr_workaround: BISR hardware workaround (for 22260 series devices) + * @min_txq_size: minimum number of slots required in a TX queue * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -445,6 +447,7 @@ struct iwl_cfg { u32 extra_phy_cfg_flags; u32 d3_debug_data_base_addr; u32 d3_debug_data_length; + u32 min_txq_size; }; extern const struct iwl_csr_params iwl_csr_v1; @@ -563,6 +566,10 @@ extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0; extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0; extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0; extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb; +extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0; +extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0; +extern const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0; +extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0; #endif /* CPTCFG_IWLMVM || CPTCFG_IWLFMAC */ #endif /* __IWL_CONFIG_H__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index d0ce3a79c387..aea6d03e545a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -328,11 +328,14 @@ enum { #define CSR_HW_REV_TYPE_QNJ (0x0000360) #define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364) #define CSR_HW_REV_TYPE_HR_CDB (0x0000340) +#define CSR_HW_REV_TYPE_SO (0x0000370) +#define CSR_HW_REV_TYPE_TY (0x0000420) /* RF_ID value */ #define CSR_HW_RF_ID_TYPE_JF (0x00105100) #define CSR_HW_RF_ID_TYPE_HR (0x0010A000) #define CSR_HW_RF_ID_TYPE_HRCDB (0x00109F00) +#define CSR_HW_RF_ID_TYPE_GF (0x0010D000) /* HW_RF CHIP ID */ #define CSR_HW_RF_ID_TYPE_CHIP_ID(_val) (((_val) >> 12) & 0xFFF) @@ -594,6 +597,7 @@ enum msix_hw_int_causes { MSIX_HW_INT_CAUSES_REG_ALIVE = BIT(0), MSIX_HW_INT_CAUSES_REG_WAKEUP = BIT(1), MSIX_HW_INT_CAUSES_REG_IPC = BIT(1), + MSIX_HW_INT_CAUSES_REG_IML = BIT(2), MSIX_HW_INT_CAUSES_REG_SW_ERR_V2 = BIT(5), MSIX_HW_INT_CAUSES_REG_CT_KILL = BIT(6), MSIX_HW_INT_CAUSES_REG_RF_KILL = BIT(7), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 27839c10d5e3..498c315291cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -750,7 +750,8 @@ static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, if (tid == IWL_MAX_TID_COUNT) { tid = IWL_MGMT_TID; - size = IWL_MGMT_QUEUE_SIZE; + size = max_t(u32, IWL_MGMT_QUEUE_SIZE, + mvm->trans->cfg->min_txq_size); } queue = iwl_trans_txq_alloc(mvm->trans, cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE), diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index ceb3aa03d561..55b9120a1360 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -66,6 +66,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, void *iml_img; u32 control_flags = 0; int ret; + int cmdq_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size); /* Allocate prph scratch */ prph_scratch = dma_alloc_coherent(trans->dev, sizeof(*prph_scratch), @@ -151,7 +152,7 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, ctxt_info_gen3->mcr_base_addr = cpu_to_le64(trans_pcie->rxq->used_bd_dma); ctxt_info_gen3->mtr_size = - cpu_to_le16(TFD_QUEUE_CB_SIZE(TFD_CMD_SLOTS)); + cpu_to_le16(TFD_QUEUE_CB_SIZE(cmdq_size)); ctxt_info_gen3->mcr_size = cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE)); @@ -175,8 +176,14 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, iwl_write64(trans, CSR_IML_DATA_ADDR, trans_pcie->iml_dma_addr); iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len); - iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, CSR_AUTO_FUNC_BOOT_ENA); - iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); + + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { + iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); + } else { + iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, + CSR_AUTO_FUNC_BOOT_ENA); + iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); + } return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index a22e47639a4e..4a1b7bb9a6c6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -948,6 +948,14 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)}, {IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2725, 0x0090, iwlax210_2ax_cfg_so_hr_a0)}, + {IWL_PCI_DEVICE(0x7A70, 0x0090, iwlax210_2ax_cfg_so_hr_a0)}, + {IWL_PCI_DEVICE(0x7A70, 0x0310, iwlax210_2ax_cfg_so_hr_a0)}, + {IWL_PCI_DEVICE(0x2725, 0x0020, iwlax210_2ax_cfg_so_hr_a0)}, + {IWL_PCI_DEVICE(0x2725, 0x0310, iwlax210_2ax_cfg_so_hr_a0)}, + {IWL_PCI_DEVICE(0x2725, 0x0A10, iwlax210_2ax_cfg_so_hr_a0)}, + {IWL_PCI_DEVICE(0x2725, 0x00B0, iwlax210_2ax_cfg_so_hr_a0)}, + #endif /* CONFIG_IWLMVM */ {0} diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 49c2ce549c86..587bb06c2cb1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -247,7 +247,7 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, } rxq->write_actual = round_down(rxq->write, 8); - if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) + if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) iwl_write32(trans, HBUS_TARG_WRPTR, (rxq->write_actual | ((FIRST_RX_QUEUE + rxq->id) << 16))); @@ -2133,7 +2133,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) } } - if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560 && + if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560 && inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) { /* Reflect IML transfer status */ int res = iwl_read32(trans, CSR_IML_RESP_ADDR); @@ -2152,6 +2152,17 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id) isr_stats->wakeup++; } + if (inta_hw & MSIX_HW_INT_CAUSES_REG_IML) { + /* Reflect IML transfer status */ + int res = iwl_read32(trans, CSR_IML_RESP_ADDR); + + IWL_DEBUG_ISR(trans, "IML transfer status: %d\n", res); + if (res == IWL_IMAGE_RESP_FAIL) { + isr_stats->sw++; + iwl_pcie_irq_handle_error(trans); + } + } + /* Chip got too hot and stopped itself */ if (inta_hw & MSIX_HW_INT_CAUSES_REG_CT_KILL) { IWL_ERR(trans, "Microcode CT kill error detected.\n"); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index e2d64378c932..9c203ca75de9 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -171,7 +171,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) } iwl_pcie_ctxt_info_free_paging(trans); - if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) iwl_pcie_ctxt_info_gen3_free(trans); else iwl_pcie_ctxt_info_free(trans); @@ -234,6 +234,7 @@ void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int queue_size = max_t(u32, TFD_CMD_SLOTS, trans->cfg->min_txq_size); /* TODO: most of the logic can be removed in A0 - but not in Z0 */ spin_lock(&trans_pcie->irq_lock); @@ -247,7 +248,7 @@ static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans) return -ENOMEM; /* Allocate or reset and init all Tx and Command queues */ - if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, TFD_CMD_SLOTS)) + if (iwl_pcie_gen2_tx_init(trans, trans_pcie->cmd_queue, queue_size)) return -ENOMEM; /* enable shadow regs in HW */ @@ -332,7 +333,7 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, goto out; } - if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) ret = iwl_pcie_ctxt_info_gen3_init(trans, fw); else ret = iwl_pcie_ctxt_info_init(trans, fw); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 375d8f25b886..6c30c88fc41e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1094,6 +1094,7 @@ static struct iwl_causes_list causes_list[] = { {MSIX_FH_INT_CAUSES_FH_ERR, CSR_MSIX_FH_INT_MASK_AD, 0x5}, {MSIX_HW_INT_CAUSES_REG_ALIVE, CSR_MSIX_HW_INT_MASK_AD, 0x10}, {MSIX_HW_INT_CAUSES_REG_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11}, + {MSIX_HW_INT_CAUSES_REG_IML, CSR_MSIX_HW_INT_MASK_AD, 0x12}, {MSIX_HW_INT_CAUSES_REG_CT_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x16}, {MSIX_HW_INT_CAUSES_REG_RF_KILL, CSR_MSIX_HW_INT_MASK_AD, 0x17}, {MSIX_HW_INT_CAUSES_REG_PERIODIC, CSR_MSIX_HW_INT_MASK_AD, 0x18}, @@ -1126,7 +1127,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE; int i, arr_size = - (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ? + (trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ? ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2); /* @@ -1136,7 +1137,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans) */ for (i = 0; i < arr_size; i++) { struct iwl_causes_list *causes = - (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ? + (trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ? causes_list : causes_list_v2; iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); @@ -3503,7 +3504,17 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, #if IS_ENABLED(CONFIG_IWLMVM) trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID); - if (cfg == &iwl22560_2ax_cfg_hr) { + if (cfg == &iwlax210_2ax_cfg_so_hr_a0) { + if (trans->hw_rev == CSR_HW_REV_TYPE_TY) { + trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0; + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { + trans->cfg = &iwlax210_2ax_cfg_so_jf_a0; + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { + trans->cfg = &iwlax210_2ax_cfg_so_gf_a0; + } + } else if (cfg == &iwl22560_2ax_cfg_hr) { if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { trans->cfg = &iwl22560_2ax_cfg_hr; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 28a371814387..d8773e0a6062 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -995,7 +995,11 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans) txq_id++) { bool cmd_queue = (txq_id == trans_pcie->cmd_queue); - slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + if (cmd_queue) + slots_num = max_t(u32, TFD_CMD_SLOTS, + trans->cfg->min_txq_size); + else + slots_num = TFD_TX_CMD_SLOTS; trans_pcie->txq[txq_id] = &trans_pcie->txq_memory[txq_id]; ret = iwl_pcie_txq_alloc(trans, trans_pcie->txq[txq_id], slots_num, cmd_queue); @@ -1044,7 +1048,11 @@ int iwl_pcie_tx_init(struct iwl_trans *trans) txq_id++) { bool cmd_queue = (txq_id == trans_pcie->cmd_queue); - slots_num = cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + if (cmd_queue) + slots_num = max_t(u32, TFD_CMD_SLOTS, + trans->cfg->min_txq_size); + else + slots_num = TFD_TX_CMD_SLOTS; ret = iwl_pcie_txq_init(trans, trans_pcie->txq[txq_id], slots_num, cmd_queue); if (ret) { -- cgit v1.2.3 From f130bb75d8817c560b48c4d1a0e5279968a0859d Mon Sep 17 00:00:00 2001 From: Mordechay Goodstein Date: Thu, 13 Dec 2018 23:04:51 +0200 Subject: iwlwifi: add FW recovery flow Add new API and TLV for the ability to send commands in the beginning and end of reset flow. The full flow of recovery is: 1. While loading FW, get address (from the TLV) of target buffer to read in case of reset 2. If an error/assert happens read the address data from step 1. 3. Reset the HW and load the FW. 4. Send the data read in step 2. 5. Add station keys 6. Send notification to FW that reset flow is done. The main use of the recovery flow is for support in PN/SN recovery when offloaded Signed-off-by: Mordechay Goodstein Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/alive.h | 20 ++++++++ .../net/wireless/intel/iwlwifi/fw/api/commands.h | 5 ++ drivers/net/wireless/intel/iwlwifi/fw/file.h | 1 + drivers/net/wireless/intel/iwlwifi/fw/img.h | 2 + drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 14 ++++++ drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 54 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 2 + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 18 ++++++++ 9 files changed, 118 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h index 0026e259fd87..df1bd0d2450e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/alive.h @@ -197,4 +197,24 @@ struct iwl_card_state_notif { __le32 flags; } __packed; /* CARD_STATE_NTFY_API_S_VER_1 */ +/** + * enum iwl_error_recovery_flags - flags for error recovery cmd + * @ERROR_RECOVERY_UPDATE_DB: update db from blob sent + * @ERROR_RECOVERY_END_OF_RECOVERY: end of recovery + */ +enum iwl_error_recovery_flags { + ERROR_RECOVERY_UPDATE_DB = BIT(0), + ERROR_RECOVERY_END_OF_RECOVERY = BIT(1), +}; + +/** + * struct iwl_fw_error_recovery_cmd - recovery cmd sent upon assert + * @flags: &enum iwl_error_recovery_flags + * @buf_size: db buffer size in bytes + */ +struct iwl_fw_error_recovery_cmd { + __le32 flags; + __le32 buf_size; +} __packed; /* ERROR_RECOVERY_CMD_HDR_API_S_VER_1 */ + #endif /* __iwl_fw_api_alive_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 0290b333d860..4d2274bcc0b5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -643,6 +643,11 @@ enum iwl_system_subcmd_ids { * @INIT_EXTENDED_CFG_CMD: &struct iwl_init_extended_cfg_cmd */ INIT_EXTENDED_CFG_CMD = 0x03, + + /** + * @FW_ERROR_RECOVERY_CMD: &struct iwl_fw_error_recovery_cmd + */ + FW_ERROR_RECOVERY_CMD = 0x7, }; #endif /* __iwl_fw_api_commands_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 886a620e03cf..3f61dc50c2d5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -145,6 +145,7 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_IML = 52, IWL_UCODE_TLV_UMAC_DEBUG_ADDRS = 54, IWL_UCODE_TLV_LMAC_DEBUG_ADDRS = 55, + IWL_UCODE_TLV_FW_RECOVERY_INFO = 57, IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION = IWL_UCODE_INI_TLV_GROUP | 0x1, IWL_UCODE_TLV_TYPE_HCMD = IWL_UCODE_INI_TLV_GROUP | 0x2, IWL_UCODE_TLV_TYPE_REGIONS = IWL_UCODE_INI_TLV_GROUP | 0x3, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h index 6ffa2e39a25c..f4c5a4d73206 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/img.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h @@ -105,6 +105,8 @@ struct iwl_ucode_capabilities { u32 n_scan_channels; u32 standard_phy_calibration_size; u32 flags; + u32 error_log_addr; + u32 error_log_size; unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)]; unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)]; }; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 784e07b648e6..91ec90e5eb67 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1088,6 +1088,20 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, return -ENOMEM; break; } + case IWL_UCODE_TLV_FW_RECOVERY_INFO: { + struct { + __le32 buf_addr; + __le32 buf_size; + } *recov_info = (void *)tlv_data; + + if (tlv_len != sizeof(*recov_info)) + goto invalid_tlv_len; + capa->error_log_addr = + le32_to_cpu(recov_info->buf_addr); + capa->error_log_size = + le32_to_cpu(recov_info->buf_size); + } + break; case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: { struct iwl_umac_debug_addrs *dbg_ptrs = (void *)tlv_data; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index cf7f8c340ffe..28ef204c9cf7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -976,6 +976,57 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) } #endif /* CONFIG_ACPI */ +void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags) +{ + u32 error_log_size = mvm->fw->ucode_capa.error_log_size; + int ret; + u32 resp; + + struct iwl_fw_error_recovery_cmd recovery_cmd = { + .flags = cpu_to_le32(flags), + .buf_size = 0, + }; + struct iwl_host_cmd host_cmd = { + .id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD), + .flags = CMD_WANT_SKB, + .data = {&recovery_cmd, }, + .len = {sizeof(recovery_cmd), }, + }; + + /* no error log was defined in TLV */ + if (!error_log_size) + return; + + if (flags & ERROR_RECOVERY_UPDATE_DB) { + /* no buf was allocated while HW reset */ + if (!mvm->error_recovery_buf) + return; + + host_cmd.data[1] = mvm->error_recovery_buf; + host_cmd.len[1] = error_log_size; + host_cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; + recovery_cmd.buf_size = cpu_to_le32(error_log_size); + } + + ret = iwl_mvm_send_cmd(mvm, &host_cmd); + kfree(mvm->error_recovery_buf); + mvm->error_recovery_buf = NULL; + + if (ret) { + IWL_ERR(mvm, "Failed to send recovery cmd %d\n", ret); + return; + } + + /* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */ + if (flags & ERROR_RECOVERY_UPDATE_DB) { + resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data); + if (resp) + IWL_ERR(mvm, + "Failed to send recovery cmd blob was invalid %d\n", + resp); + } +} + static int iwl_mvm_sar_init(struct iwl_mvm *mvm) { int ret; @@ -1212,6 +1263,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN); + if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) + iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB); + ret = iwl_mvm_sar_init(mvm); if (ret == 0) { ret = iwl_mvm_sar_geo_init(mvm); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 9377fca39edf..c02559766712 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1326,6 +1326,8 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm) /* allow transport/FW low power modes */ iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN); + iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_END_OF_RECOVERY); + /* * If we have TDLS peers, remove them. We don't know the last seqno/PN * of packets the FW sent out, so we must reconnect. diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 0255157378db..c70fc90680af 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1014,6 +1014,7 @@ struct iwl_mvm { /* -1 for always, 0 for never, >0 for that many times */ s8 fw_restart; + u8 *error_recovery_buf; #ifdef CONFIG_IWLWIFI_LEDS struct led_classdev led; @@ -1657,6 +1658,7 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags); void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 0c276124bf0f..f8a5a7074dc1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -422,6 +422,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { static const struct iwl_hcmd_names iwl_mvm_system_names[] = { HCMD_NAME(SHARED_MEM_CFG_CMD), HCMD_NAME(INIT_EXTENDED_CFG_CMD), + HCMD_NAME(FW_ERROR_RECOVERY_CMD), }; /* Please keep this array *SORTED* by hex value. @@ -921,6 +922,9 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) kfree(mvm->mcast_filter_cmd); mvm->mcast_filter_cmd = NULL; + kfree(mvm->error_recovery_buf); + mvm->error_recovery_buf = NULL; + #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) kfree(mvm->d3_resume_sram); #endif @@ -1301,6 +1305,20 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) /* don't let the transport/FW power down */ iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); + if (mvm->fw->ucode_capa.error_log_size) { + u32 src_size = mvm->fw->ucode_capa.error_log_size; + u32 src_addr = mvm->fw->ucode_capa.error_log_addr; + u8 *recover_buf = kzalloc(src_size, GFP_ATOMIC); + + if (recover_buf) { + mvm->error_recovery_buf = recover_buf; + iwl_trans_read_mem_bytes(mvm->trans, + src_addr, + recover_buf, + src_size); + } + } + if (fw_error && mvm->fw_restart > 0) mvm->fw_restart--; set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); -- cgit v1.2.3 From 4c816b2132aa287a1940125e7c33139710d9cf17 Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Sun, 23 Dec 2018 13:09:50 +0200 Subject: iwlwifi: do not fail on large amount of channels Until supporting UHB (ultra high band) channels for devices AX210, do not fail if number of channels reported by firmware is greater than NL80211_MAX_SUPP_REG_RULES. The Driver in that case will use only the non-UHB channels. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 484ef4556953..503860a2b36d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1102,12 +1102,12 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ? IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS; - if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES)) - return ERR_PTR(-EINVAL); - if (WARN_ON(num_of_ch > max_num_ch)) num_of_ch = max_num_ch; + if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES)) + return ERR_PTR(-EINVAL); + IWL_DEBUG_DEV(dev, IWL_DL_LAR, "building regdom for %d channels\n", num_of_ch); -- cgit v1.2.3 From cee859fe9ae33d0ed3edcc018ee4cc3081907d60 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Mon, 24 Dec 2018 10:59:13 +0200 Subject: iwlwifi: mvm: Fix possible NULL pointer dereference iwl_mvm_te_clear_data() is called for cleanup in case sending the HOT_SPOT_CMD failed. However, in case sending the command caused a fw error and restart (e.g. if the command is not supported) then the te_data pointer may no longer be valid, which leads to a NULL pointer dereference. Fix it by checking that the te_data pointer is not NULL before dereferencing it. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/time-event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 5b34100e9099..9693fa4cdc39 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -85,7 +85,7 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm, { lockdep_assert_held(&mvm->time_event_lock); - if (!te_data->vif) + if (!te_data || !te_data->vif) return; list_del(&te_data->list); -- cgit v1.2.3 From 138664a30746a0b773ad0f2b2105bb8d1e417573 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 8 Nov 2018 09:53:48 +0200 Subject: iwlwifi: mvm: support beacon IE injection This is useful for automated tests. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 106 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 22 ++--- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 11 +++ 3 files changed, 128 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index e136475a34f6..80b0b2ed69bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1188,6 +1188,108 @@ out: return ret ?: count; } +static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) +{ + struct ieee80211_vif *vif; + struct iwl_mvm_vif *mvmvif; + struct sk_buff *beacon; + struct ieee80211_tx_info *info; + struct iwl_mac_beacon_cmd beacon_cmd = {}; + u8 rate; + u16 flags; + int i; + + len /= 2; + + /* Element len should be represented by u8 */ + if (len >= U8_MAX) + return -EINVAL; + + if (!iwl_mvm_firmware_running(mvm)) + return -EIO; + + if (!iwl_mvm_has_new_tx_api(mvm) && + !fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE)) + return -EINVAL; + + rcu_read_lock(); + + for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) { + vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true); + if (!vif) + continue; + + if (vif->type == NL80211_IFTYPE_AP) + break; + } + + if (i == NUM_MAC_INDEX_DRIVER || !vif) + goto out_err; + + mvm->hw->extra_beacon_tailroom = len; + + beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL); + if (!beacon) + goto out_err; + + if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) { + dev_kfree_skb(beacon); + goto out_err; + } + + mvmvif = iwl_mvm_vif_from_mac80211(vif); + info = IEEE80211_SKB_CB(beacon); + rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); + flags = iwl_mvm_mac80211_idx_to_hwrate(rate); + + if (rate == IWL_FIRST_CCK_RATE) + flags |= IWL_MAC_BEACON_CCK; + + beacon_cmd.flags = cpu_to_le16(flags); + beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len); + beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id); + + iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx, + &beacon_cmd.tim_size, + beacon->data, beacon->len); + + mutex_lock(&mvm->mutex); + iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd, + sizeof(beacon_cmd)); + mutex_unlock(&mvm->mutex); + + dev_kfree_skb(beacon); + + rcu_read_unlock(); + return 0; + +out_err: + rcu_read_unlock(); + return -EINVAL; +} + +static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm, + char *buf, size_t count, + loff_t *ppos) +{ + int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count); + + mvm->hw->extra_beacon_tailroom = 0; + return ret ?: count; +} + +static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm, + char *buf, + size_t count, + loff_t *ppos) +{ + int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0); + + mvm->hw->extra_beacon_tailroom = 0; + return ret ?: count; +} + static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1806,6 +1908,8 @@ MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8); MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, (IWL_RSS_INDIRECTION_TABLE_SIZE * 2)); MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512); +MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512); +MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512); MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids); @@ -2007,6 +2111,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200); + MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200); + MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200); #ifdef CONFIG_ACPI MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400); #endif diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 83711b555036..9bd4376cad9b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -811,9 +811,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm, return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); } -static void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, - __le32 *tim_index, __le32 *tim_size, - u8 *beacon, u32 frame_size) +void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, + __le32 *tim_index, __le32 *tim_size, + u8 *beacon, u32 frame_size) { u32 tim_idx; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon; @@ -853,8 +853,8 @@ static u32 iwl_mvm_find_ie_offset(u8 *beacon, u8 eid, u32 frame_size) return ie - beacon; } -static u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, - struct ieee80211_vif *vif) +u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, + struct ieee80211_vif *vif) { u8 rate; @@ -904,9 +904,9 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm, } -static int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, - struct sk_buff *beacon, - void *data, int len) +int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, + struct sk_buff *beacon, + void *data, int len) { struct iwl_host_cmd cmd = { .id = BEACON_TEMPLATE_CMD, @@ -1009,9 +1009,9 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm, sizeof(beacon_cmd)); } -static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct sk_buff *beacon) +int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct sk_buff *beacon) { if (WARN_ON(!beacon)) return -EINVAL; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index c70fc90680af..f4fc81695df1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1693,6 +1693,17 @@ int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif); +int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct sk_buff *beacon); +int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm, + struct sk_buff *beacon, + void *data, int len); +u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info, + struct ieee80211_vif *vif); +void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm, + __le32 *tim_index, __le32 *tim_size, + u8 *beacon, u32 frame_size); void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, -- cgit v1.2.3 From 5cc9543a85ca0b721a0b3288cf2a54f3b1878f69 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 10 Dec 2018 09:01:56 +0100 Subject: iwlwifi: bump FW API to 46 for 9000 and 22000 series Start supporting API version 46 where applicable. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 6f231d05fc1b..b9dd50174857 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -56,7 +56,7 @@ #include "iwl-config.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 45 +#define IWL_22000_UCODE_API_MAX 46 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 39 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 35c1851337e6..3225b64eb845 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -57,7 +57,7 @@ #include "fw/file.h" /* Highest firmware API version supported */ -#define IWL9000_UCODE_API_MAX 45 +#define IWL9000_UCODE_API_MAX 46 /* Lowest firmware API version supported */ #define IWL9000_UCODE_API_MIN 30 -- cgit v1.2.3 From 2ae48edcf76721d6cfcec97e5ff18cd7983b7974 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 25 Dec 2018 12:16:32 +0200 Subject: iwlwifi: pcie: fix TX while flushing When flushing TX queues no new TX should go into the system. However, in the following scenario we get TX: 1. Queues are stopped and there are packets in overflow queue 2. Station is removed and flush begins 3. Flush empties space, and reclaim path TXes SKB from overflow queue. Note that the fact the queues are stopped during the process doesn't matter - the packet will be TXed since the TX path doesn't care if TX queues are stopped or not, just if there is space in the queue, which there is, since we just freed a packet. A fix here is rather complicated, since the flow is very racy. Change code not to warn if we are TXing from overflow TX. In case there is TX from both overflow TX and TX path we will miss a warning we optimally had, but we can live with that. Make sure we don't return before overflow queue is empty, otherwise we will think queues are empty, but they will be refilled, resulting with assert. Signed-off-by: Sara Sharon Fixes: 3955525d5d17 ("iwlwifi: pcie: buffer packets to avoid overflowing Tx queues") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 2 ++ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 24 ++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 10 +++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 9e1bcafad786..0ecd90d050e6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -400,6 +400,8 @@ struct iwl_txq { u32 id; int low_mark; int high_mark; + + bool overflow_tx; }; static inline dma_addr_t diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 6c30c88fc41e..4b31b0cdbd09 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2240,6 +2240,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_txq *txq; unsigned long now = jiffies; + bool overflow_tx; u8 wr_ptr; /* Make sure the NIC is still alive in the bus */ @@ -2251,18 +2252,37 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx) IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx); txq = trans_pcie->txq[txq_idx]; + + spin_lock_bh(&txq->lock); + overflow_tx = txq->overflow_tx || + !skb_queue_empty(&txq->overflow_q); + spin_unlock_bh(&txq->lock); + wr_ptr = READ_ONCE(txq->write_ptr); - while (txq->read_ptr != READ_ONCE(txq->write_ptr) && + while ((txq->read_ptr != READ_ONCE(txq->write_ptr) || + overflow_tx) && !time_after(jiffies, now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) { u8 write_ptr = READ_ONCE(txq->write_ptr); - if (WARN_ONCE(wr_ptr != write_ptr, + /* + * If write pointer moved during the wait, warn only + * if the TX came from op mode. In case TX came from + * trans layer (overflow TX) don't warn. + */ + if (WARN_ONCE(wr_ptr != write_ptr && !overflow_tx, "WR pointer moved while flushing %d -> %d\n", wr_ptr, write_ptr)) return -ETIMEDOUT; + wr_ptr = write_ptr; + usleep_range(1000, 2000); + + spin_lock_bh(&txq->lock); + overflow_tx = txq->overflow_tx || + !skb_queue_empty(&txq->overflow_q); + spin_unlock_bh(&txq->lock); } if (txq->read_ptr != txq->write_ptr) { diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index d8773e0a6062..9fbd37d23e85 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1181,6 +1181,15 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, __skb_queue_head_init(&overflow_skbs); skb_queue_splice_init(&txq->overflow_q, &overflow_skbs); + /* + * We are going to transmit from the overflow queue. + * Remember this state so that wait_for_txq_empty will know we + * are adding more packets to the TFD queue. It cannot rely on + * the state of &txq->overflow_q, as we just emptied it, but + * haven't TXed the content yet. + */ + txq->overflow_tx = true; + /* * This is tricky: we are in reclaim path which is non * re-entrant, so noone will try to take the access the @@ -1209,6 +1218,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, iwl_wake_queue(trans, txq); spin_lock_bh(&txq->lock); + txq->overflow_tx = false; } if (txq->read_ptr == txq->write_ptr) { -- cgit v1.2.3 From 48e775e66e2d77b1414cc065976c9ea8664ef19a Mon Sep 17 00:00:00 2001 From: Haim Dreyfuss Date: Wed, 2 Jan 2019 12:52:20 +0200 Subject: iwlwifi: mvm: add support for 32kHz external clock indication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In low power modes, the chip clock source for platform integrated devices is 32kHz. It is generated internally and supplied by a crystal oscillator. However using a 32kHz sourced from crystal oscillator has high power penalty. There is an option to get an external 32kHz clock from the platform. Past experience shows that the reliability is platform dependent, i.e. on some platforms it works good and on other it doesn’t. Working from external clock will save 0.5 mW in sleep state, from overall 1.8mW that we have today, i.e. almost 30%. Each OEM can enable or disable the use of the external 32kHz clock by setting a BIOS configuration. In case the OEM configured to use 32kHz external clock the driver will pass this indication to the FW. Signed-off-by: Haim Dreyfuss Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 32 +++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/fw/acpi.h | 22 ++++++++++++++-- drivers/net/wireless/intel/iwlwifi/fw/api/power.h | 13 ++++++--- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 7 +++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/power.c | 7 +++-- 6 files changed, 74 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index 32d000cffe9f..405038ce98d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -6,6 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright (C) 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -26,6 +27,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright (C) 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -205,3 +207,33 @@ out: return dflt_pwr_limit; } IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit); + +int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) +{ + union acpi_object *wifi_pkg, *data; + int ret; + + data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD); + if (IS_ERR(data)) + return PTR_ERR(data); + + wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE); + if (IS_ERR(wifi_pkg)) { + ret = PTR_ERR(wifi_pkg); + goto out_free; + } + + if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { + ret = -EINVAL; + goto out_free; + } + + *extl_clk = wifi_pkg->package.elements[1].integer.value; + + ret = 0; + +out_free: + kfree(data); + return ret; +} +IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 7492dfb6729b..f5704e16643f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -27,7 +27,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -67,6 +67,7 @@ #define ACPI_WGDS_METHOD "WGDS" #define ACPI_WRDD_METHOD "WRDD" #define ACPI_SPLC_METHOD "SPLC" +#define ACPI_ECKV_METHOD "ECKV" #define ACPI_WIFI_DOMAIN (0x07) @@ -86,6 +87,7 @@ #define ACPI_WGDS_WIFI_DATA_SIZE 19 #define ACPI_WRDD_WIFI_DATA_SIZE 2 #define ACPI_SPLC_WIFI_DATA_SIZE 2 +#define ACPI_ECKV_WIFI_DATA_SIZE 2 #define ACPI_WGDS_NUM_BANDS 2 #define ACPI_WGDS_TABLE_SIZE 3 @@ -109,6 +111,17 @@ int iwl_acpi_get_mcc(struct device *dev, char *mcc); u64 iwl_acpi_get_pwr_limit(struct device *dev); +/* + * iwl_acpi_get_eckv - read external clock validation from ACPI, if available + * + * @dev: the struct device + * @extl_clk: output var (2 bytes) that will get the clk indication. + * + * This function tries to read the external clock indication + * from ACPI if available. + */ +int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk); + #else /* CONFIG_ACPI */ static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method) @@ -133,5 +146,10 @@ static inline u64 iwl_acpi_get_pwr_limit(struct device *dev) return 0; } +static inline int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) +{ + return -ENOENT; +} + #endif /* CONFIG_ACPI */ #endif /* __iwl_fw_acpi__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 5844898ee92c..01f003c6cff9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -200,9 +200,16 @@ struct iwl_powertable_cmd { * @DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK: * '1' Allow to save power by turning off * receiver and transmitter. '0' - does not allow. + * @DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK: + * Device Retention indication, '1' indicate retention is enabled. + * @DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK: + * 32Khz external slow clock valid indication, '1' indicate cloack is + * valid. */ enum iwl_device_power_flags { - DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), + DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), + DEVICE_POWER_FLAGS_ALLOW_MEM_RETENTION_MSK = BIT(1), + DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK = BIT(12), }; /** diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 28ef204c9cf7..0278f19180d5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1266,6 +1266,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB); + if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid)) + IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n"); + ret = iwl_mvm_sar_init(mvm); if (ret == 0) { ret = iwl_mvm_sar_geo_init(mvm); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f4fc81695df1..9993337a2bbd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1104,6 +1104,8 @@ struct iwl_mvm { /* Indicate if device power save is allowed */ u8 ps_disabled; /* u8 instead of bool to ease debugfs_create_* usage */ + /* Indicate if 32Khz external clock is valid */ + u32 ext_clock_valid; unsigned int max_amsdu_len; /* used for debugfs only */ struct ieee80211_vif __rcu *csa_vif; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index df9f1d6cdf78..36f5fa1ee793 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -544,6 +544,9 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm) cmd.flags &= cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); #endif + if (mvm->ext_clock_valid) + cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK); + IWL_DEBUG_POWER(mvm, "Sending device power command with flags = 0x%X\n", cmd.flags); -- cgit v1.2.3 From d4f4793c2d57d3c1f56a79175233e80f896b1853 Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Tue, 1 Jan 2019 10:11:14 +0200 Subject: iwlwifi: dbg: temporarily skip periphery dump for AX210 devices Many periphery addresses have changed in AX210 devices. Until sorting out which peripheries should be dumped, skip that step for now. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 728fe051745b..1abaed5dfbf1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -8,7 +8,7 @@ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -673,7 +673,9 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr, { u32 range_len; - if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) { + if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { + /* TODO */ + } else if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) { range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000); handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr); } else { -- cgit v1.2.3 From ea695b7c69af1198ec861d29ffa0f9f95b530e0a Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Tue, 1 Jan 2019 14:03:23 +0200 Subject: iwlwifi: align to new periphery address space for AX210 family In AX210 family, UMAC periphery address space moved from 0xA00000 to 0xD00000. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 10 +++- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 12 ++-- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 16 +++--- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 6 +- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 8 +-- drivers/net/wireless/intel/iwlwifi/iwl-io.h | 43 ++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 5 +- .../wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 15 +++-- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 10 ++-- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 64 ++++++++++++---------- 10 files changed, 122 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index b9dd50174857..fd8416c53819 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018-2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018-2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -179,6 +179,10 @@ static const struct iwl_ht_params iwl_22000_ht_params = { .d3_debug_data_base_addr = 0x401000, \ .d3_debug_data_length = 60 * 1024 +#define IWL_DEVICE_AX200_COMMON \ + IWL_DEVICE_22000_COMMON, \ + .umac_prph_offset = 0x300000 + #define IWL_DEVICE_22500 \ IWL_DEVICE_22000_COMMON, \ .device_family = IWL_DEVICE_FAMILY_22000, \ @@ -192,7 +196,7 @@ static const struct iwl_ht_params iwl_22000_ht_params = { .csr = &iwl_csr_v2 #define IWL_DEVICE_AX210 \ - IWL_DEVICE_22000_COMMON, \ + IWL_DEVICE_AX200_COMMON, \ .device_family = IWL_DEVICE_FAMILY_AX210, \ .base_params = &iwl_22000_base_params, \ .csr = &iwl_csr_v1, \ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 1abaed5dfbf1..3b3692473702 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -242,7 +242,8 @@ static void iwl_fw_dump_rxf(struct iwl_fw_runtime *fwrt, cfg->lmac[0].rxfifo1_size, 0, 0); /* Pull RXF2 */ iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size, - RXF_DIFF_FROM_PREV, 1); + RXF_DIFF_FROM_PREV + + fwrt->trans->cfg->umac_prph_offset, 1); /* Pull LMAC2 RXF1 */ if (fwrt->smem_cfg.num_lmacs > 1) iwl_fwrt_dump_rxf(fwrt, dump_data, @@ -1140,7 +1141,8 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg, int idx) { - u32 start_addr = iwl_read_prph(fwrt->trans, MON_BUFF_BASE_ADDR_VER2); + u32 start_addr = iwl_read_umac_prph(fwrt->trans, + MON_BUFF_BASE_ADDR_VER2); if (start_addr == 0x5a5a5a5a) return -1; @@ -1173,8 +1175,10 @@ static struct iwl_fw_ini_error_dump_range IWL_ERR(fwrt, "Failed to get DRAM monitor header\n"); return NULL; } - write_ptr = iwl_read_prph_no_grab(fwrt->trans, MON_BUFF_WRPTR_VER2); - cycle_cnt = iwl_read_prph_no_grab(fwrt->trans, MON_BUFF_CYCLE_CNT_VER2); + write_ptr = iwl_read_umac_prph_no_grab(fwrt->trans, + MON_BUFF_WRPTR_VER2); + cycle_cnt = iwl_read_umac_prph_no_grab(fwrt->trans, + MON_BUFF_CYCLE_CNT_VER2); iwl_trans_release_nic_access(fwrt->trans, &flags); mon_dump->write_ptr = cpu_to_le32(write_ptr); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index b64fdfdcbce7..3ee86d18a97d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -8,7 +8,7 @@ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -299,13 +299,13 @@ _iwl_fw_dbg_stop_recording(struct iwl_trans *trans, } if (params) { - params->in_sample = iwl_read_prph(trans, DBGC_IN_SAMPLE); - params->out_ctrl = iwl_read_prph(trans, DBGC_OUT_CTRL); + params->in_sample = iwl_read_umac_prph(trans, DBGC_IN_SAMPLE); + params->out_ctrl = iwl_read_umac_prph(trans, DBGC_OUT_CTRL); } - iwl_write_prph(trans, DBGC_IN_SAMPLE, 0); + iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, 0); udelay(100); - iwl_write_prph(trans, DBGC_OUT_CTRL, 0); + iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0); #ifdef CONFIG_IWLWIFI_DEBUGFS trans->dbg_rec_on = false; #endif @@ -333,9 +333,9 @@ _iwl_fw_dbg_restart_recording(struct iwl_trans *trans, iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1); } else { - iwl_write_prph(trans, DBGC_IN_SAMPLE, params->in_sample); + iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample); udelay(100); - iwl_write_prph(trans, DBGC_OUT_CTRL, params->out_ctrl); + iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl); } } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index d25b632eaa41..d06196802c61 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -7,7 +7,7 @@ * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -29,7 +29,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright (C) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -382,6 +382,7 @@ struct iwl_csr_params { * @d3_debug_data_length: length of the D3 debug data * @bisr_workaround: BISR hardware workaround (for 22260 series devices) * @min_txq_size: minimum number of slots required in a TX queue + * @umac_prph_offset: offset to add to UMAC periphery address * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -448,6 +449,7 @@ struct iwl_cfg { u32 d3_debug_data_base_addr; u32 d3_debug_data_length; u32 min_txq_size; + u32 umac_prph_offset; }; extern const struct iwl_csr_params iwl_csr_v1; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index bf171edad53a..edba08768fac 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -7,7 +7,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 - 2016 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright(C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -29,7 +29,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 - 2016 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -308,8 +308,8 @@ void iwl_force_nmi(struct iwl_trans *trans) iwl_write_prph(trans, DEVICE_SET_NMI_REG, DEVICE_SET_NMI_VAL_DRV); else - iwl_write_prph(trans, UREG_NIC_SET_NMI_DRIVER, - UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK); + iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, + UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK); } IWL_EXPORT_SYMBOL(iwl_force_nmi); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.h b/drivers/net/wireless/intel/iwlwifi/iwl-io.h index bf1100837d72..920e2146ea3f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -25,7 +25,7 @@ * * BSD LICENSE * - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -104,4 +104,43 @@ int iwl_finish_nic_init(struct iwl_trans *trans); /* Error handling */ int iwl_dump_fh(struct iwl_trans *trans, char **buf); +/* + * UMAC periphery address space changed from 0xA00000 to 0xD00000 starting from + * device family AX200. So peripheries used in families above and below AX200 + * should go through iwl_..._umac_..._prph. + */ +static inline u32 iwl_umac_prph(struct iwl_trans *trans, u32 ofs) +{ + return ofs + trans->cfg->umac_prph_offset; +} + +static inline u32 iwl_read_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs) +{ + return iwl_read_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset); +} + +static inline u32 iwl_read_umac_prph(struct iwl_trans *trans, u32 ofs) +{ + return iwl_read_prph(trans, ofs + trans->cfg->umac_prph_offset); +} + +static inline void iwl_write_umac_prph_no_grab(struct iwl_trans *trans, u32 ofs, + u32 val) +{ + iwl_write_prph_no_grab(trans, ofs + trans->cfg->umac_prph_offset, val); +} + +static inline void iwl_write_umac_prph(struct iwl_trans *trans, u32 ofs, + u32 val) +{ + iwl_write_prph(trans, ofs + trans->cfg->umac_prph_offset, val); +} + +static inline int iwl_poll_umac_prph_bit(struct iwl_trans *trans, u32 addr, + u32 bits, u32 mask, int timeout) +{ + return iwl_poll_prph_bit(trans, addr + trans->cfg->umac_prph_offset, + bits, mask, timeout); +} + #endif diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 0278f19180d5..1589b64232ce 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -351,8 +351,9 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) IWL_ERR(mvm, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", - iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS), - iwl_read_prph(trans, UMAG_SB_CPU_2_STATUS)); + iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS), + iwl_read_umac_prph(trans, + UMAG_SB_CPU_2_STATUS)); else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) IWL_ERR(mvm, "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n", diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 55b9120a1360..1e36459948db 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -18,7 +18,7 @@ * * BSD LICENSE * - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -177,13 +177,12 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, trans_pcie->iml_dma_addr); iwl_write32(trans, CSR_IML_SIZE_ADDR, trans->iml_len); - if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { - iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); - } else { - iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, - CSR_AUTO_FUNC_BOOT_ENA); + iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, + CSR_AUTO_FUNC_BOOT_ENA); + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); + else iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); - } return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 587bb06c2cb1..38844215a58e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -8,7 +8,7 @@ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -202,9 +202,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) { if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { /* TODO: remove this for 22560 once fw does it */ - iwl_write_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0); - return iwl_poll_prph_bit(trans, RFH_GEN_STATUS_GEN3, - RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); + iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0); + return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_GEN3, + RXF_DMA_IDLE, RXF_DMA_IDLE, 1000); } else if (trans->cfg->mq_rx_supported) { iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0); return iwl_poll_prph_bit(trans, RFH_GEN_STATUS, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 4b31b0cdbd09..e2579a0bcc25 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -8,7 +8,7 @@ * Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -896,13 +896,13 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) if (!trans->num_blocks) return; - iwl_write_prph(trans, MON_BUFF_BASE_ADDR_VER2, - trans->fw_mon[0].physical >> - MON_BUFF_SHIFT_VER2); - iwl_write_prph(trans, MON_BUFF_END_ADDR_VER2, - (trans->fw_mon[0].physical + - trans->fw_mon[0].size - 256) >> - MON_BUFF_SHIFT_VER2); + iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, + trans->fw_mon[0].physical >> + MON_BUFF_SHIFT_VER2); + iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2, + (trans->fw_mon[0].physical + + trans->fw_mon[0].size - 256) >> + MON_BUFF_SHIFT_VER2); return; } @@ -1183,8 +1183,8 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) if (!trans_pcie->msix_enabled) { if (trans->cfg->mq_rx_supported && test_bit(STATUS_DEVICE_ENABLED, &trans->status)) - iwl_write_prph(trans, UREG_CHICK, - UREG_CHICK_MSI_ENABLE); + iwl_write_umac_prph(trans, UREG_CHICK, + UREG_CHICK_MSI_ENABLE); return; } /* @@ -1193,7 +1193,7 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) * prph. */ if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) - iwl_write_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); + iwl_write_umac_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); /* * Each cause from the causes list above and the RX causes is @@ -1561,7 +1561,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, } IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n", - iwl_read_prph(trans, WFPM_GP2)); + iwl_read_umac_prph(trans, WFPM_GP2)); val = iwl_read32(trans, CSR_RESET); if (val & CSR_RESET_REG_FLAG_NEVO_RESET) @@ -1710,15 +1710,18 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) return err; } - hpm = iwl_trans_read_prph(trans, HPM_DEBUG); + hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG); if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) { - if (iwl_trans_read_prph(trans, PREG_PRPH_WPROT_0) & - PREG_WFPM_ACCESS) { + int wfpm_val = iwl_read_umac_prph_no_grab(trans, + PREG_PRPH_WPROT_0); + + if (wfpm_val & PREG_WFPM_ACCESS) { IWL_ERR(trans, "Error, can not clear persistence bit\n"); return -EPERM; } - iwl_trans_write_prph(trans, HPM_DEBUG, hpm & ~PERSISTENCE_BIT); + iwl_write_umac_prph_no_grab(trans, HPM_DEBUG, + hpm & ~PERSISTENCE_BIT); } iwl_trans_pcie_sw_reset(trans); @@ -2968,7 +2971,8 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans, i += sizeof(u32)) *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i)); else - for (i = FH_MEM_LOWER_BOUND_GEN2; i < FH_MEM_UPPER_BOUND_GEN2; + for (i = iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2); + i < iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2); i += sizeof(u32)) *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans, i)); @@ -2993,11 +2997,11 @@ iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans, if (!iwl_trans_grab_nic_access(trans, &flags)) return 0; - iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); + iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); for (i = 0; i < buf_size_in_dwords; i++) - buffer[i] = iwl_read_prph_no_grab(trans, - MON_DMARB_RD_DATA_ADDR); - iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); + buffer[i] = iwl_read_umac_prph_no_grab(trans, + MON_DMARB_RD_DATA_ADDR); + iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); iwl_trans_release_nic_access(trans, &flags); @@ -3012,9 +3016,9 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans, /* If there was a dest TLV - use the values from there */ if (trans->ini_valid) { - base = MON_BUFF_BASE_ADDR_VER2; - write_ptr = MON_BUFF_WRPTR_VER2; - wrap_cnt = MON_BUFF_CYCLE_CNT_VER2; + base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2); + write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2); + wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2); } else if (trans->dbg_dest_tlv) { write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg); wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count); @@ -3176,8 +3180,8 @@ static struct iwl_trans_dump_data if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) { if (trans->cfg->gen2) len += sizeof(*data) + - (FH_MEM_UPPER_BOUND_GEN2 - - FH_MEM_LOWER_BOUND_GEN2); + (iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) - + iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2)); else len += sizeof(*data) + (FH_MEM_UPPER_BOUND - @@ -3507,9 +3511,11 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, if (iwl_trans_grab_nic_access(trans, &flags)) { u32 hw_step; - hw_step = iwl_read_prph_no_grab(trans, WFPM_CTRL_REG); + hw_step = iwl_read_umac_prph_no_grab(trans, + WFPM_CTRL_REG); hw_step |= ENABLE_WFPM; - iwl_write_prph_no_grab(trans, WFPM_CTRL_REG, hw_step); + iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG, + hw_step); hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG); hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF; if (hw_step == 0x3) -- cgit v1.2.3 From c8177fed9a7f3e97e975bc9f530afaace08c38ce Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Mon, 7 Jan 2019 16:36:09 +0200 Subject: iwlwifi: add force NMI for AX210 devices For AX210 devices, the periphry for forcing NMI has changed. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-io.c | 5 ++++- drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-io.c b/drivers/net/wireless/intel/iwlwifi/iwl-io.c index edba08768fac..a704e25af810 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-io.c @@ -307,9 +307,12 @@ void iwl_force_nmi(struct iwl_trans *trans) if (trans->cfg->device_family < IWL_DEVICE_FAMILY_9000) iwl_write_prph(trans, DEVICE_SET_NMI_REG, DEVICE_SET_NMI_VAL_DRV); - else + else if (trans->cfg->device_family < IWL_DEVICE_FAMILY_AX210) iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER, UREG_NIC_SET_NMI_DRIVER_NMI_FROM_DRIVER_MSK); + else + iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6, + UREG_DOORBELL_TO_ISR6_NMI_BIT); } IWL_EXPORT_SYMBOL(iwl_force_nmi); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 3aaa5f06461c..1af9f9e1ecd4 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -8,7 +8,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -433,4 +433,7 @@ enum { #define HPM_DEBUG 0xA03440 #define PERSISTENCE_BIT BIT(12) #define PREG_WFPM_ACCESS BIT(12) + +#define UREG_DOORBELL_TO_ISR6 0xA05C04 +#define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0) #endif /* __iwl_prph_h__ */ -- cgit v1.2.3 From 971377e67074a07665038d78cb48c6f570292b19 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 1 Jan 2019 17:38:32 +0200 Subject: iwlwifi: mvm: add a debug_enable op D3 debug data is disabled by default. Currently it is done by tampering the dump mask. Add an operation that will allow this to be changed without recompilation. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 4 +++- drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 5 +++-- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 6 ++++-- drivers/net/wireless/intel/iwlwifi/mvm/constants.h | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 ++++++ 5 files changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 3ee86d18a97d..16656949b505 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -376,7 +376,9 @@ static inline bool iwl_fw_dbg_is_d3_debug_enabled(struct iwl_fw_runtime *fwrt) { return fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_D3_DEBUG) && - fwrt->trans->cfg->d3_debug_data_length && + fwrt->trans->cfg->d3_debug_data_length && fwrt->ops && + fwrt->ops->d3_debug_enable && + fwrt->ops->d3_debug_enable(fwrt->ops_ctx) && iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_D3_DEBUG_DATA); } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 2bbae7a1f492..41c4a3e7ad82 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright (C) 2018-2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -27,7 +27,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright (C) 2018-2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -73,6 +73,7 @@ struct iwl_fw_runtime_ops { void (*dump_end)(void *ctx); bool (*fw_running)(void *ctx); int (*send_hcmd)(void *ctx, struct iwl_host_cmd *host_cmd); + bool (*d3_debug_enable)(void *ctx); }; #define MAX_NUM_LMAC 2 diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 91ec90e5eb67..4b75a93c7364 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -8,6 +8,7 @@ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1311,8 +1313,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) fw->ucode_capa.standard_phy_calibration_size = IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS; - /* dump all fw memory areas by default except d3 debug data */ - fw->dbg.dump_mask = 0xfffdffff; + /* dump all fw memory areas by default */ + fw->dbg.dump_mask = 0xffffffff; pieces = kzalloc(sizeof(*pieces), GFP_KERNEL); if (!pieces) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 58e29af12a14..6a3edea3d580 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -8,6 +8,7 @@ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 Intel Deutschland GmbH + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -148,5 +150,6 @@ #define IWL_MVM_ENABLE_EBS 1 #define IWL_MVM_FTM_INITIATOR_ALGO IWL_TOF_ALGO_TYPE_MAX_LIKE #define IWL_MVM_FTM_INITIATOR_DYNACK true +#define IWL_MVM_D3_DEBUG false #endif /* __MVM_CONSTANTS_H */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index f8a5a7074dc1..0bdf92c49710 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -601,11 +601,17 @@ static int iwl_mvm_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd) return ret; } +static bool iwl_mvm_d3_debug_enable(void *ctx) +{ + return IWL_MVM_D3_DEBUG; +} + static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = { .dump_start = iwl_mvm_fwrt_dump_start, .dump_end = iwl_mvm_fwrt_dump_end, .fw_running = iwl_mvm_fwrt_fw_running, .send_hcmd = iwl_mvm_fwrt_send_hcmd, + .d3_debug_enable = iwl_mvm_d3_debug_enable, }; static struct iwl_op_mode * -- cgit v1.2.3 From e2b7f83cc8c443de357cd1ad71d66541889578e8 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Wed, 9 Jan 2019 14:05:59 +0200 Subject: iwiwifi: mvm: Fix FW scan concurrency support assumptions - The FW supports up to 4 concurrent scans, so adjust the definitions accordingly. - Only a single periodic scan is supported, so enforce it in the code. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/scan.h | 6 +++--- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 18741889ec30..890a939c463d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -434,7 +434,7 @@ struct iwl_periodic_scan_complete { /* The maximum of either of these cannot exceed 8, because we use an * 8-bit mask (see IWL_MVM_SCAN_MASK in mvm.h). */ -#define IWL_MVM_MAX_UMAC_SCANS 8 +#define IWL_MVM_MAX_UMAC_SCANS 4 #define IWL_MVM_MAX_LMAC_SCANS 1 enum scan_config_flags { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 853bf679dc26..78694bc38e76 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1580,6 +1580,11 @@ static int iwl_mvm_check_running_scans(struct iwl_mvm *mvm, int type) * scheduled scan before starting a normal scan. */ + /* FW supports only a single periodic scan */ + if ((type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) && + mvm->scan_status & (IWL_MVM_SCAN_SCHED | IWL_MVM_SCAN_NETDETECT)) + return -EBUSY; + if (iwl_mvm_num_scans(mvm) < mvm->max_scans) return 0; -- cgit v1.2.3 From ff418feeec0fefb8373567c1e4e32b631587f454 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Mon, 7 Jan 2019 10:35:26 +0200 Subject: iwlwifi: mvm: add support for new FTM fw API The FTM new API uses API TLV bit 15. The driver mistakenly uses this bit for beacon filter API, although no TLV was assigned for the beacon filter API. For now, make beacon filter use bit 16 instead (not set by the fw anyway). Once a TLV is assigned to the beacon filter API it should be updated. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/location.h | 181 ++++++++++- drivers/net/wireless/intel/iwlwifi/fw/file.h | 5 + .../net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 338 +++++++++++++++------ 3 files changed, 429 insertions(+), 95 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 10cac5f987e7..5dddb21c1c4d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -324,7 +324,7 @@ enum iwl_tof_location_query { }; /** - * struct iwl_tof_range_req_ap_entry - AP configuration parameters + * struct iwl_tof_range_req_ap_entry_v2 - AP configuration parameters * @channel_num: Current AP Channel * @bandwidth: Current AP Bandwidth. One of iwl_tof_bandwidth. * @tsf_delta_direction: TSF relatively to the subject AP @@ -357,7 +357,7 @@ enum iwl_tof_location_query { * @notify_mcsi: &enum iwl_tof_mcsi_ntfy. * @reserved: For alignment and future use */ -struct iwl_tof_range_req_ap_entry { +struct iwl_tof_range_req_ap_entry_v2 { u8 channel_num; u8 bandwidth; u8 tsf_delta_direction; @@ -376,6 +376,62 @@ struct iwl_tof_range_req_ap_entry { u8 algo_type; u8 notify_mcsi; __le16 reserved; +} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_2 */ + +/** + * enum iwl_initiator_ap_flags - per responder FTM configuration flags + * @IWL_INITIATOR_AP_FLAGS_ASAP: Request for ASAP measurement. + * @IWL_INITIATOR_AP_FLAGS_LCI_REQUEST: Request for LCI information + * @IWL_INITIATOR_AP_FLAGS_CIVIC_REQUEST: Request for CIVIC information + * @IWL_INITIATOR_AP_FLAGS_DYN_ACK: Send HT/VHT ack for FTM frames. If not set, + * 20Mhz dup acks will be sent. + * @IWL_INITIATOR_AP_FLAGS_ALGO_LR: Use LR algo type for rtt calculation. + * Default algo type is ML. + * @IWL_INITIATOR_AP_FLAGS_ALGO_FFT: Use FFT algo type for rtt calculation. + * Default algo type is ML. + * @IWL_INITIATOR_AP_FLAGS_MCSI_REPORT: Send the MCSI for each FTM frame to the + * driver. + */ +enum iwl_initiator_ap_flags { + IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1), + IWL_INITIATOR_AP_FLAGS_LCI_REQUEST = BIT(2), + IWL_INITIATOR_AP_FLAGS_CIVIC_REQUEST = BIT(3), + IWL_INITIATOR_AP_FLAGS_DYN_ACK = BIT(4), + IWL_INITIATOR_AP_FLAGS_ALGO_LR = BIT(5), + IWL_INITIATOR_AP_FLAGS_ALGO_FFT = BIT(6), + IWL_INITIATOR_AP_FLAGS_MCSI_REPORT = BIT(8), +}; + +/** + * struct iwl_tof_range_req_ap_entry - AP configuration parameters + * @initiator_ap_flags: see &enum iwl_initiator_ap_flags. + * @channel_num: AP Channel number + * @bandwidth: AP bandwidth. One of iwl_tof_bandwidth. + * @ctrl_ch_position: Coding of the control channel position relative to the + * center frequency, see iwl_mvm_get_ctrl_pos(). + * @ftmr_max_retries: Max number of retries to send the FTMR in case of no + * reply from the AP. + * @bssid: AP's BSSID + * @burst_period: Recommended value to be sent to the AP. Measurement + * periodicity In units of 100ms. ignored if num_of_bursts_exp = 0 + * @samples_per_burst: the number of FTMs pairs in single Burst (1-31); + * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of + * the number of measurement iterations (min 2^0 = 1, max 2^14) + * @reserved: For alignment and future use + * @tsf_delta: not in use + */ +struct iwl_tof_range_req_ap_entry { + __le32 initiator_ap_flags; + u8 channel_num; + u8 bandwidth; + u8 ctrl_ch_position; + u8 ftmr_max_retries; + u8 bssid[ETH_ALEN]; + __le16 burst_period; + u8 samples_per_burst; + u8 num_of_bursts; + __le16 reserved; + __le32 tsf_delta; } __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_3 */ /** @@ -405,10 +461,12 @@ enum iwl_tof_response_mode { * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A: use antenna A fo TX ACKs during FTM * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B: use antenna B fo TX ACKs during FTM * @IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C: use antenna C fo TX ACKs during FTM + * @IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM: use random mac address for FTM * @IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB: use the specific calib value from * the range request command * @IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB: use the common calib value from the * ragne request command + * @IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT: support non-asap measurements */ enum iwl_tof_initiator_flags { IWL_TOF_INITIATOR_FLAGS_FAST_ALGO_DISABLED = BIT(0), @@ -418,15 +476,17 @@ enum iwl_tof_initiator_flags { IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_A = BIT(4), IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_B = BIT(5), IWL_TOF_INITIATOR_FLAGS_TX_CHAIN_SEL_C = BIT(6), + IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM = BIT(7), IWL_TOF_INITIATOR_FLAGS_SPECIFIC_CALIB = BIT(15), IWL_TOF_INITIATOR_FLAGS_COMMON_CALIB = BIT(16), + IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT = BIT(20), }; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ #define IWL_MVM_TOF_MAX_APS 5 #define IWL_MVM_TOF_MAX_TWO_SIDED_APS 5 /** - * struct iwl_tof_range_req_cmd - start measurement cmd + * struct iwl_tof_range_req_cmd_v5 - start measurement cmd * @initiator_flags: see flags @ iwl_tof_initiator_flags * @request_id: A Token incremented per request. The same Token will be * sent back in the range response @@ -454,7 +514,7 @@ enum iwl_tof_initiator_flags { * @specific_calib: The specific calib value to inject to this measurement calc * @ap: per-AP request data */ -struct iwl_tof_range_req_cmd { +struct iwl_tof_range_req_cmd_v5 { __le32 initiator_flags; u8 request_id; u8 initiator; @@ -471,10 +531,42 @@ struct iwl_tof_range_req_cmd { u8 ftm_tx_chains; __le16 common_calib; __le16 specific_calib; - struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; + struct iwl_tof_range_req_ap_entry_v2 ap[IWL_MVM_TOF_MAX_APS]; } __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_5 */ +/** + * struct iwl_tof_range_req_cmd - start measurement cmd + * @initiator_flags: see flags @ iwl_tof_initiator_flags + * @request_id: A Token incremented per request. The same Token will be + * sent back in the range response + * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) + * @range_req_bssid: ranging request BSSID + * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template. + * Bits set to 1 shall be randomized by the UMAC + * @macaddr_template: MAC address template to use for non-randomized bits + * @req_timeout_ms: Requested timeout of the response in units of milliseconds. + * This is the session time for completing the measurement. + * @tsf_mac_id: report the measurement start time for each ap in terms of the + * TSF of this mac id. 0xff to disable TSF reporting. + * @common_calib: The common calib value to inject to this measurement calc + * @specific_calib: The specific calib value to inject to this measurement calc + * @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2. + */ +struct iwl_tof_range_req_cmd { + __le32 initiator_flags; + u8 request_id; + u8 num_of_ap; + u8 range_req_bssid[ETH_ALEN]; + u8 macaddr_mask[ETH_ALEN]; + u8 macaddr_template[ETH_ALEN]; + __le32 req_timeout_ms; + __le32 tsf_mac_id; + __le16 common_calib; + __le16 specific_calib; + struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; +} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_7 */ + /* * enum iwl_tof_range_request_status - status of the sent request * @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the @@ -534,7 +626,7 @@ enum iwl_tof_entry_status { }; /* LOCATION_RANGE_RSP_AP_ENTRY_NTFY_API_S_VER_2 */ /** - * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response) + * struct iwl_tof_range_rsp_ap_entry_ntfy_v3 - AP parameters (response) * @bssid: BSSID of the AP * @measure_status: current APs measurement status, one of * &enum iwl_tof_entry_status. @@ -561,7 +653,7 @@ enum iwl_tof_entry_status { * @papd_calib_output: The result of the tof papd calibration that was injected * into the algorithm. */ -struct iwl_tof_range_rsp_ap_entry_ntfy { +struct iwl_tof_range_rsp_ap_entry_ntfy_v3 { u8 bssid[ETH_ALEN]; u8 measure_status; u8 measure_bw; @@ -582,6 +674,59 @@ struct iwl_tof_range_rsp_ap_entry_ntfy { __le32 papd_calib_output; } __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_3 */ +/** + * struct iwl_tof_range_rsp_ap_entry_ntfy - AP parameters (response) + * @bssid: BSSID of the AP + * @measure_status: current APs measurement status, one of + * &enum iwl_tof_entry_status. + * @measure_bw: Current AP Bandwidth: 0 20MHz, 1 40MHz, 2 80MHz + * @rtt: The Round Trip Time that took for the last measurement for + * current AP [pSec] + * @rtt_variance: The Variance of the RTT values measured for current AP + * @rtt_spread: The Difference between the maximum and the minimum RTT + * values measured for current AP in the current session [pSec] + * @rssi: RSSI as uploaded in the Channel Estimation notification + * @rssi_spread: The Difference between the maximum and the minimum RSSI values + * measured for current AP in the current session + * @last_burst: 1 if no more FTM sessions are scheduled for this responder + * @refusal_period: refusal period in case of + * @IWL_TOF_ENTRY_RESPONDER_CANNOT_COLABORATE [sec] + * @timestamp: The GP2 Clock [usec] where Channel Estimation notification was + * uploaded by the LMAC + * @start_tsf: measurement start time in TSF of the mac specified in the range + * request + * @rx_rate_n_flags: rate and flags of the last FTM frame received from this + * responder + * @tx_rate_n_flags: rate and flags of the last ack sent to this responder + * @t2t3_initiator: as calculated from the algo in the initiator + * @t1t4_responder: as calculated from the algo in the responder + * @common_calib: Calib val that was used in for this AP measurement + * @specific_calib: val that was used in for this AP measurement + * @papd_calib_output: The result of the tof papd calibration that was injected + * into the algorithm. + */ +struct iwl_tof_range_rsp_ap_entry_ntfy { + u8 bssid[ETH_ALEN]; + u8 measure_status; + u8 measure_bw; + __le32 rtt; + __le32 rtt_variance; + __le32 rtt_spread; + s8 rssi; + u8 rssi_spread; + u8 last_burst; + u8 refusal_period; + __le32 timestamp; + __le32 start_tsf; + __le32 rx_rate_n_flags; + __le32 tx_rate_n_flags; + __le32 t2t3_initiator; + __le32 t1t4_responder; + __le16 common_calib; + __le16 specific_calib; + __le32 papd_calib_output; +} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_4 */ + /** * enum iwl_tof_response_status - tof response status * @@ -599,7 +744,7 @@ enum iwl_tof_response_status { }; /* LOCATION_RNG_RSP_STATUS */ /** - * struct iwl_tof_range_rsp_ntfy - ranging response notification + * struct iwl_tof_range_rsp_ntfy_v5 - ranging response notification * @request_id: A Token ID of the corresponding Range request * @request_status: status of current measurement session, one of * &enum iwl_tof_response_status. @@ -607,13 +752,29 @@ enum iwl_tof_response_status { * @num_of_aps: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) * @ap: per-AP data */ -struct iwl_tof_range_rsp_ntfy { +struct iwl_tof_range_rsp_ntfy_v5 { u8 request_id; u8 request_status; u8 last_in_batch; u8 num_of_aps; + struct iwl_tof_range_rsp_ap_entry_ntfy_v3 ap[IWL_MVM_TOF_MAX_APS]; +} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_5 */ + +/** + * struct iwl_tof_range_rsp_ntfy - ranging response notification + * @request_id: A Token ID of the corresponding Range request + * @num_of_aps: Number of APs results + * @last_report: 1 if no more FTM sessions are scheduled, 0 otherwise. + * @reserved: reserved + * @ap: per-AP data + */ +struct iwl_tof_range_rsp_ntfy { + u8 request_id; + u8 num_of_aps; + u8 last_report; + u8 reserved; struct iwl_tof_range_rsp_ap_entry_ntfy ap[IWL_MVM_TOF_MAX_APS]; -} __packed; +} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_6 */ #define IWL_MVM_TOF_MCSI_BUF_SIZE (245) /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 3f61dc50c2d5..641c95d03b15 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -9,6 +9,7 @@ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -32,6 +33,7 @@ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -270,6 +272,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; * version of the beacon notification. * @IWL_UCODE_TLV_API_BEACON_FILTER_V4: This ucode supports v4 of * BEACON_FILTER_CONFIG_API_S_VER_4. + * @IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ: This ucode supports v7 of + * LOCATION_RANGE_REQ_CMD_API_S and v6 of LOCATION_RANGE_RESP_NTFY_API_S. * * @NUM_IWL_UCODE_TLV_API: number of bits used */ @@ -296,6 +300,7 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_REDUCE_TX_POWER = (__force iwl_ucode_tlv_api_t)45, IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF = (__force iwl_ucode_tlv_api_t)46, IWL_UCODE_TLV_API_BEACON_FILTER_V4 = (__force iwl_ucode_tlv_api_t)47, + IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ = (__force iwl_ucode_tlv_api_t)49, NUM_IWL_UCODE_TLV_API #ifdef __CHECKER__ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index eb6f084a0f8a..c1d9703ab40c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -132,91 +132,224 @@ iwl_ftm_range_request_status_to_err(enum iwl_tof_range_request_status s) } } +static void iwl_mvm_ftm_cmd_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct iwl_tof_range_req_cmd_v5 *cmd, + struct cfg80211_pmsr_request *req) +{ + int i; + + cmd->request_id = req->cookie; + cmd->num_of_ap = req->n_peers; + + /* use maximum for "no timeout" or bigger than what we can do */ + if (!req->timeout || req->timeout > 255 * 100) + cmd->req_timeout = 255; + else + cmd->req_timeout = DIV_ROUND_UP(req->timeout, 100); + + /* + * We treat it always as random, since if not we'll + * have filled our local address there instead. + */ + cmd->macaddr_random = 1; + memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN); + for (i = 0; i < ETH_ALEN; i++) + cmd->macaddr_mask[i] = ~req->mac_addr_mask[i]; + + if (vif->bss_conf.assoc) + memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); + else + eth_broadcast_addr(cmd->range_req_bssid); +} + +static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct iwl_tof_range_req_cmd *cmd, + struct cfg80211_pmsr_request *req) +{ + int i; + + cmd->initiator_flags = + cpu_to_le32(IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM | + IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT); + cmd->request_id = req->cookie; + cmd->num_of_ap = req->n_peers; + + /* + * Use a large value for "no timeout". Don't use the maximum value + * because of fw limitations. + */ + if (req->timeout) + cmd->req_timeout_ms = cpu_to_le32(req->timeout); + else + cmd->req_timeout_ms = cpu_to_le32(0xfffff); + + memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN); + for (i = 0; i < ETH_ALEN; i++) + cmd->macaddr_mask[i] = ~req->mac_addr_mask[i]; + + if (vif->bss_conf.assoc) + memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); + else + eth_broadcast_addr(cmd->range_req_bssid); + + /* TODO: fill in tsf_mac_id if needed */ + cmd->tsf_mac_id = cpu_to_le32(0xff); +} + +static int iwl_mvm_ftm_target_chandef(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + u8 *channel, u8 *bandwidth, + u8 *ctrl_ch_position) +{ + u32 freq = peer->chandef.chan->center_freq; + + *channel = ieee80211_frequency_to_channel(freq); + + switch (peer->chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + *bandwidth = IWL_TOF_BW_20_LEGACY; + break; + case NL80211_CHAN_WIDTH_20: + *bandwidth = IWL_TOF_BW_20_HT; + break; + case NL80211_CHAN_WIDTH_40: + *bandwidth = IWL_TOF_BW_40; + break; + case NL80211_CHAN_WIDTH_80: + *bandwidth = IWL_TOF_BW_80; + break; + default: + IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n", + peer->chandef.width); + return -EINVAL; + } + + *ctrl_ch_position = (peer->chandef.width > NL80211_CHAN_WIDTH_20) ? + iwl_mvm_get_ctrl_pos(&peer->chandef) : 0; + + return 0; +} + +static int +iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + struct iwl_tof_range_req_ap_entry_v2 *target) +{ + int ret; + + ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num, + &target->bandwidth, + &target->ctrl_ch_position); + if (ret) + return ret; + + memcpy(target->bssid, peer->addr, ETH_ALEN); + target->burst_period = + cpu_to_le16(peer->ftm.burst_period); + target->samples_per_burst = peer->ftm.ftms_per_burst; + target->num_of_bursts = peer->ftm.num_bursts_exp; + target->measure_type = 0; /* regular two-sided FTM */ + target->retries_per_sample = peer->ftm.ftmr_retries; + target->asap_mode = peer->ftm.asap; + target->enable_dyn_ack = IWL_MVM_FTM_INITIATOR_DYNACK; + + if (peer->ftm.request_lci) + target->location_req |= IWL_TOF_LOC_LCI; + if (peer->ftm.request_civicloc) + target->location_req |= IWL_TOF_LOC_CIVIC; + + target->algo_type = IWL_MVM_FTM_INITIATOR_ALGO; + + return 0; +} + +#define FTM_PUT_FLAG(flag) (target->initiator_ap_flags |= \ + cpu_to_le32(IWL_INITIATOR_AP_FLAGS_##flag)) + +static int iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + struct iwl_tof_range_req_ap_entry *target) +{ + int ret; + + ret = iwl_mvm_ftm_target_chandef(mvm, peer, &target->channel_num, + &target->bandwidth, + &target->ctrl_ch_position); + if (ret) + return ret; + + memcpy(target->bssid, peer->addr, ETH_ALEN); + target->burst_period = + cpu_to_le16(peer->ftm.burst_period); + target->samples_per_burst = peer->ftm.ftms_per_burst; + target->num_of_bursts = peer->ftm.num_bursts_exp; + target->ftmr_max_retries = peer->ftm.ftmr_retries; + target->initiator_ap_flags = cpu_to_le32(0); + + if (peer->ftm.asap) + FTM_PUT_FLAG(ASAP); + + if (peer->ftm.request_lci) + FTM_PUT_FLAG(LCI_REQUEST); + + if (peer->ftm.request_civicloc) + FTM_PUT_FLAG(CIVIC_REQUEST); + + if (IWL_MVM_FTM_INITIATOR_DYNACK) + FTM_PUT_FLAG(DYN_ACK); + + if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_LINEAR_REG) + FTM_PUT_FLAG(ALGO_LR); + else if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT) + FTM_PUT_FLAG(ALGO_FFT); + + return 0; +} + int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_pmsr_request *req) { - struct iwl_tof_range_req_cmd cmd = { - .request_id = req->cookie, - .req_timeout = DIV_ROUND_UP(req->timeout, 100), - .num_of_ap = req->n_peers, - /* - * We treat it always as random, since if not we'll - * have filled our local address there instead. - */ - .macaddr_random = 1, - }; + struct iwl_tof_range_req_cmd_v5 cmd_v5; + struct iwl_tof_range_req_cmd cmd; + bool new_api = fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ); + u8 num_of_ap; struct iwl_host_cmd hcmd = { .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), - .data[0] = &cmd, - .len[0] = sizeof(cmd), .dataflags[0] = IWL_HCMD_DFL_DUP, }; u32 status = 0; int err, i; - /* use maximum for "no timeout" or bigger than what we can do */ - if (!req->timeout || req->timeout > 255 * 100) - cmd.req_timeout = 255; - lockdep_assert_held(&mvm->mutex); if (mvm->ftm_initiator.req) return -EBUSY; - memcpy(cmd.macaddr_template, req->mac_addr, ETH_ALEN); - for (i = 0; i < ETH_ALEN; i++) - cmd.macaddr_mask[i] = ~req->mac_addr_mask[i]; + if (new_api) { + iwl_mvm_ftm_cmd(mvm, vif, &cmd, req); + hcmd.data[0] = &cmd; + hcmd.len[0] = sizeof(cmd); + num_of_ap = cmd.num_of_ap; + } else { + iwl_mvm_ftm_cmd_v5(mvm, vif, &cmd_v5, req); + hcmd.data[0] = &cmd_v5; + hcmd.len[0] = sizeof(cmd_v5); + num_of_ap = cmd_v5.num_of_ap; + } - for (i = 0; i < cmd.num_of_ap; i++) { + for (i = 0; i < num_of_ap; i++) { struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; - struct iwl_tof_range_req_ap_entry *cmd_target = &cmd.ap[i]; - u32 freq = peer->chandef.chan->center_freq; - cmd_target->channel_num = ieee80211_frequency_to_channel(freq); - switch (peer->chandef.width) { - case NL80211_CHAN_WIDTH_20_NOHT: - cmd_target->bandwidth = IWL_TOF_BW_20_LEGACY; - break; - case NL80211_CHAN_WIDTH_20: - cmd_target->bandwidth = IWL_TOF_BW_20_HT; - break; - case NL80211_CHAN_WIDTH_40: - cmd_target->bandwidth = IWL_TOF_BW_40; - break; - case NL80211_CHAN_WIDTH_80: - cmd_target->bandwidth = IWL_TOF_BW_80; - break; - default: - IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n", - peer->chandef.width); - return -EINVAL; - } - cmd_target->ctrl_ch_position = - (peer->chandef.width > NL80211_CHAN_WIDTH_20) ? - iwl_mvm_get_ctrl_pos(&peer->chandef) : 0; - - memcpy(cmd_target->bssid, peer->addr, ETH_ALEN); - cmd_target->measure_type = 0; /* regular two-sided FTM */ - cmd_target->num_of_bursts = peer->ftm.num_bursts_exp; - cmd_target->burst_period = - cpu_to_le16(peer->ftm.burst_period); - cmd_target->samples_per_burst = peer->ftm.ftms_per_burst; - cmd_target->retries_per_sample = peer->ftm.ftmr_retries; - cmd_target->asap_mode = peer->ftm.asap; - cmd_target->enable_dyn_ack = IWL_MVM_FTM_INITIATOR_DYNACK; - - if (peer->ftm.request_lci) - cmd_target->location_req |= IWL_TOF_LOC_LCI; - if (peer->ftm.request_civicloc) - cmd_target->location_req |= IWL_TOF_LOC_CIVIC; - - cmd_target->algo_type = IWL_MVM_FTM_INITIATOR_ALGO; - } + if (new_api) + err = iwl_mvm_ftm_put_target(mvm, peer, &cmd.ap[i]); + else + err = iwl_mvm_ftm_put_target_v2(mvm, peer, + &cmd_v5.ap[i]); - if (vif->bss_conf.assoc) - memcpy(cmd.range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); - else - eth_broadcast_addr(cmd.range_req_bssid); + if (err) + return err; + } err = iwl_mvm_send_cmd_status(mvm, &hcmd, &status); if (!err && status) { @@ -305,11 +438,34 @@ static void iwl_mvm_ftm_get_lci_civic(struct iwl_mvm *mvm, } } +static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id, + u8 num_of_aps) +{ + lockdep_assert_held(&mvm->mutex); + + if (request_id != (u8)mvm->ftm_initiator.req->cookie) { + IWL_ERR(mvm, "Request ID mismatch, got %u, active %u\n", + request_id, (u8)mvm->ftm_initiator.req->cookie); + return -EINVAL; + } + + if (num_of_aps > mvm->ftm_initiator.req->n_peers) { + IWL_ERR(mvm, "FTM range response invalid\n"); + return -EINVAL; + } + + return 0; +} + void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_tof_range_rsp_ntfy_v5 *fw_resp_v5 = (void *)pkt->data; struct iwl_tof_range_rsp_ntfy *fw_resp = (void *)pkt->data; int i; + bool new_api = fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ); + u8 num_of_aps, last_in_batch; lockdep_assert_held(&mvm->mutex); @@ -318,28 +474,46 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) return; } - if (fw_resp->request_id != (u8)mvm->ftm_initiator.req->cookie) { - IWL_ERR(mvm, "Request ID mismatch, got %u, active %u\n", - fw_resp->request_id, - (u8)mvm->ftm_initiator.req->cookie); - return; - } + if (new_api) { + if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp->request_id, + fw_resp->num_of_aps)) + return; - if (fw_resp->num_of_aps > mvm->ftm_initiator.req->n_peers) { - IWL_ERR(mvm, "FTM range response invalid\n"); - return; + num_of_aps = fw_resp->num_of_aps; + last_in_batch = fw_resp->last_report; + } else { + if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp_v5->request_id, + fw_resp_v5->num_of_aps)) + return; + + num_of_aps = fw_resp_v5->num_of_aps; + last_in_batch = fw_resp_v5->last_in_batch; } - for (i = 0; i < fw_resp->num_of_aps && i < IWL_MVM_TOF_MAX_APS; i++) { - struct iwl_tof_range_rsp_ap_entry_ntfy *fw_ap = &fw_resp->ap[i]; + for (i = 0; i < num_of_aps && i < IWL_MVM_TOF_MAX_APS; i++) { struct cfg80211_pmsr_result result = {}; + struct iwl_tof_range_rsp_ap_entry_ntfy *fw_ap; int peer_idx; + if (new_api) { + fw_ap = &fw_resp->ap[i]; + result.final = fw_resp->ap[i].last_burst; + } else { + /* the first part is the same for old and new APIs */ + fw_ap = (void *)&fw_resp_v5->ap[i]; + /* + * FIXME: the firmware needs to report this, we don't + * even know the number of bursts the responder picked + * (if we asked it to) + */ + result.final = 0; + } + peer_idx = iwl_mvm_ftm_find_peer(mvm->ftm_initiator.req, fw_ap->bssid); if (peer_idx < 0) { IWL_WARN(mvm, - "Unknown address (%pM, target #%d) in FTM response.\n", + "Unknown address (%pM, target #%d) in FTM response\n", fw_ap->bssid, i); continue; } @@ -374,12 +548,6 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) result.type = NL80211_PMSR_TYPE_FTM; result.ftm.burst_index = mvm->ftm_initiator.responses[peer_idx]; mvm->ftm_initiator.responses[peer_idx]++; - /* - * FIXME: the firmware needs to report this, we don't even know - * the number of bursts the responder picked (if we asked - * it to) - */ - result.final = 0; result.ftm.rssi_avg = fw_ap->rssi; result.ftm.rssi_avg_valid = 1; result.ftm.rssi_spread = fw_ap->rssi_spread; @@ -398,7 +566,7 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) &result, GFP_KERNEL); } - if (fw_resp->last_in_batch) { + if (last_in_batch) { cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev, mvm->ftm_initiator.req, GFP_KERNEL); -- cgit v1.2.3 From 2286a99c32344c41bf2d046e74d20d5c1839026e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Jan 2019 10:58:37 +0100 Subject: iwlwifi: mvm: fix HE radiotap data4 for HE-TB PPDUs In HE-TB PPDUs (labeled HE-TRIG in radiotap), we were overwriting the data4.spatial_reuse_1 field with the spatial reuse data that the firmware gives us for SU/MU PPDUs. Fix that by moving that, we are already setting the data4.spatial_reuse_{1,2,3,4} fields in the TB PPDU case. Signed-off-by: Johannes Berg Fixes: 69f3ca8ed33d ("iwlwifi: mvm: show more HE radiotap data for TB PPDUs") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 557a0b5a08ac..b0a8d910c5c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1093,7 +1093,6 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, case IWL_RX_PHY_INFO_TYPE_HE_TB: /* HE common */ he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN | - IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN | IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN | IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN); he->data2 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN | @@ -1113,9 +1112,6 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, he->data3 |= le16_encode_bits(le32_get_bits(phy_data->d0, IWL_RX_PHY_DATA0_HE_LDPC_EXT_SYM), IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG); - he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, - IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK), - IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE); he->data5 |= le16_encode_bits(le32_get_bits(phy_data->d0, IWL_RX_PHY_DATA0_HE_PRE_FEC_PAD_MASK), IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD); @@ -1134,6 +1130,20 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, break; } + switch (phy_data->info_type) { + case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT: + case IWL_RX_PHY_INFO_TYPE_HE_MU: + case IWL_RX_PHY_INFO_TYPE_HE_SU: + he->data1 |= cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN); + he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, + IWL_RX_PHY_DATA0_HE_SPATIAL_REUSE_MASK), + IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE); + break; + default: + /* nothing here */ + break; + } + switch (phy_data->info_type) { case IWL_RX_PHY_INFO_TYPE_HE_MU_EXT: he_mu->flags1 |= -- cgit v1.2.3 From 937b10c0de68c56512fb8cd484af3c0b356fc09e Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Thu, 10 Jan 2019 17:44:17 +0200 Subject: iwlwifi: mvm: add debug prints for FTM Add debug prints for FTM results info. These prints are used by tests automation. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index c1d9703ab40c..e9822a3ec373 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -457,6 +457,27 @@ static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id, return 0; } +static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index, + struct cfg80211_pmsr_result *res) +{ + s64 rtt_avg = res->ftm.rtt_avg * 100; + + do_div(rtt_avg, 6666); + + IWL_DEBUG_INFO(mvm, "entry %d\n", index); + IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status); + IWL_DEBUG_INFO(mvm, "\tBSSID: %pM\n", res->addr); + IWL_DEBUG_INFO(mvm, "\thost time: %llu\n", res->host_time); + IWL_DEBUG_INFO(mvm, "\tburst index: %hhu\n", res->ftm.burst_index); + IWL_DEBUG_INFO(mvm, "\tsuccess num: %u\n", res->ftm.num_ftmr_successes); + IWL_DEBUG_INFO(mvm, "\trssi: %d\n", res->ftm.rssi_avg); + IWL_DEBUG_INFO(mvm, "\trssi spread: %hhu\n", res->ftm.rssi_spread); + IWL_DEBUG_INFO(mvm, "\trtt: %lld\n", res->ftm.rtt_avg); + IWL_DEBUG_INFO(mvm, "\trtt var: %llu\n", res->ftm.rtt_variance); + IWL_DEBUG_INFO(mvm, "\trtt spread: %llu\n", res->ftm.rtt_spread); + IWL_DEBUG_INFO(mvm, "\tdistance: %lld\n", rtt_avg); +} + void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); @@ -490,6 +511,10 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) last_in_batch = fw_resp_v5->last_in_batch; } + IWL_DEBUG_INFO(mvm, "Range response received\n"); + IWL_DEBUG_INFO(mvm, "request id: %lld, num of entries: %hhu\n", + mvm->ftm_initiator.req->cookie, num_of_aps); + for (i = 0; i < num_of_aps && i < IWL_MVM_TOF_MAX_APS; i++) { struct cfg80211_pmsr_result result = {}; struct iwl_tof_range_rsp_ap_entry_ntfy *fw_ap; @@ -564,6 +589,8 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev, mvm->ftm_initiator.req, &result, GFP_KERNEL); + + iwl_mvm_debug_range_resp(mvm, i, &result); } if (last_in_batch) { -- cgit v1.2.3 From 81edb6ad9399b1c3de30bee5fd3e885c32c665e6 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Mon, 14 Jan 2019 14:56:02 +0200 Subject: iwlwifi: start using B-step for some 9000 devices We don't support A-step for some device combinations anymore. So change them to use B-step, renaming and reorganizing the config structures. Additionally, fix one device that was using the wrong configuration. Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 36 +++++++++++++------------ drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 8 +++--- 3 files changed, 24 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index fd8416c53819..2d472a04807f 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -79,10 +79,10 @@ #define IWL_22000_HR_B_F0_FW_PRE "iwlwifi-Qu-b0-hr-b0-" #define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-" #define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-" -#define IWL_22000_JF_B0_FW_PRE "iwlwifi-QuQnj-a0-jf-b0-" #define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-" #define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-" #define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-" +#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-" #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-" #define IWL_22000_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-" #define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-" @@ -101,15 +101,17 @@ IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" #define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \ IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(api) \ - IWL_22000_JF_B0_FW_PRE __stringify(api) ".ucode" #define IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(api) \ IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode" #define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \ IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode" #define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" -#define IWL_CC_A_MODULE_FIRMWARE(api) \ +#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \ + IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode" +#define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \ + IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode" +#define IWL_CC_A_MODULE_FIRMWARE(api) \ IWL_CC_A_FW_PRE __stringify(api) ".ucode" #define IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(api) \ IWL_22000_SO_A_JF_B_FW_PRE __stringify(api) ".ucode" @@ -301,6 +303,18 @@ const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0 = { IWL_DEVICE_22500, }; +const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0 = { + .name = "Intel(R) Wireless-AC 9560 160MHz", + .fw_name_pre = IWL_QNJ_B_JF_B_FW_PRE, + IWL_DEVICE_22500, + /* + * This device doesn't support receiving BlockAck with a large bitmap + * so we need to restrict the size of transmitted aggregation to the + * HT size; mac80211 would otherwise pick the HE max (256) by default. + */ + .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, +}; + const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = { .name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)", .fw_name_pre = IWL_QU_B_JF_B_FW_PRE, @@ -373,18 +387,6 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = { .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, }; -const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0 = { - .name = "Intel(R) Dual Band Wireless AX 22000", - .fw_name_pre = IWL_22000_JF_B0_FW_PRE, - IWL_DEVICE_22500, - /* - * This device doesn't support receiving BlockAck with a large bitmap - * so we need to restrict the size of transmitted aggregation to the - * HT size; mac80211 would otherwise pick the HE max (256) by default. - */ - .max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT, -}; - const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = { .name = "Intel(R) Dual Band Wireless AX 22000", .fw_name_pre = IWL_22000_HR_A0_FW_PRE, @@ -439,10 +441,10 @@ MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_A_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_B_F0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_22000_JF_B0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index d06196802c61..7f2fa5cc8c2c 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -565,7 +565,7 @@ extern const struct iwl_cfg iwl22000_2ax_cfg_jf; extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0; extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0; extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0; -extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_jf_b0; +extern const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0; extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0; extern const struct iwl_cfg iwl22560_2ax_cfg_su_cdb; extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 4a1b7bb9a6c6..b839a921cec8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -8,7 +8,7 @@ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016-2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -32,7 +32,7 @@ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * All rights reserved. * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -872,6 +872,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_cfg_qnj_jf_b0)}, /* 22000 Series */ {IWL_PCI_DEVICE(0x02F0, 0x0070, iwl22560_2ax_cfg_hr)}, @@ -891,7 +892,6 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x06F0, 0x4070, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x0040, iwl22560_2ax_cfg_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0074, iwl22560_2ax_cfg_hr)}, @@ -1007,7 +1007,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (rf_id_chp == jf_chp_id) { if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ) - cfg = &iwl22000_2ax_cfg_qnj_jf_b0; + cfg = &iwl9560_2ac_cfg_qnj_jf_b0; else cfg = &iwl22000_2ac_cfg_jf; } else if (rf_id_chp == hr_chp_id) { -- cgit v1.2.3 From 159133c8247295750320292ac7749e79603ef2e9 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 13 Jan 2019 10:02:15 +0200 Subject: iwlwifi: properly use delay option in dump trigger flow Fix several issues related to dump delay: 1. In legacy dump trigger, use stop_delay field instead of trig_dis_ms. 2. ini delay is messured in usec so align both ini and legacy to usec. 3. schedule_delayed_work receives the delay value in jiffies so translate the dump delay to jiffies. Signed-off-by: Shahar S Matityahu Fixes: ea7cb8293874 ("iwlwifi: dbg: make trigger functions type agnostic") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 3b3692473702..8d1416e8a203 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1621,7 +1621,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, fwrt->dump.desc = desc; fwrt->dump.monitor_only = monitor_only; - schedule_delayed_work(&fwrt->dump.wk, delay); + schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay)); return 0; } @@ -1677,8 +1677,10 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, } trigger->occurrences = cpu_to_le16(occurrences); - delay = le16_to_cpu(trigger->trig_dis_ms); monitor_only = trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY; + + /* convert msec to usec */ + delay = le32_to_cpu(trigger->stop_delay) * USEC_PER_MSEC; } desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC); -- cgit v1.2.3 From 46c7c9828dd7105ecfb608fd2b8715f5fcba098d Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 13 Jan 2019 13:51:57 +0200 Subject: iwlwifi: dbg_ini: enable ignore consecutive trigger feature Enable ignore consecutive trigger feature which allows to configure the driver to skip consecutive triggers from the same type. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 3 +-- drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 37 ++++++++++++----------------- 2 files changed, 16 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 8d1416e8a203..202f96e9ca0c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1484,8 +1484,7 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, if (id == FW_DBG_TRIGGER_FW_ASSERT) id = IWL_FW_TRIGGER_ID_FW_ASSERT; - if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs)) || - !fwrt->dump.active_trigs[id].active) + if (!iwl_fw_ini_trigger_on(fwrt, id)) return NULL; trigger = fwrt->dump.active_trigs[id].trig; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 16656949b505..a199056234d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -162,9 +162,9 @@ iwl_fw_dbg_trigger_stop_conf_match(struct iwl_fw_runtime *fwrt, } static inline bool -iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_ms) +iwl_fw_dbg_no_trig_window(struct iwl_fw_runtime *fwrt, u32 id, u32 dis_usec) { - unsigned long wind_jiff = msecs_to_jiffies(dis_ms); + unsigned long wind_jiff = usecs_to_jiffies(dis_usec); /* If this is the first event checked, jump to update start ts */ if (fwrt->dump.non_collect_ts_start[id] && @@ -181,11 +181,12 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_fw_runtime *fwrt, struct wireless_dev *wdev, struct iwl_fw_dbg_trigger_tlv *trig) { + u32 usec = le16_to_cpu(trig->trig_dis_ms) * USEC_PER_MSEC; + if (wdev && !iwl_fw_dbg_trigger_vif_match(trig, wdev)) return false; - if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), - le16_to_cpu(trig->trig_dis_ms))) { + if (iwl_fw_dbg_no_trig_window(fwrt, le32_to_cpu(trig->id), usec)) { IWL_WARN(fwrt, "Trigger %d occurred while no-collect window.\n", trig->id); return false; @@ -222,24 +223,22 @@ _iwl_fw_dbg_trigger_on(struct iwl_fw_runtime *fwrt, }) static inline bool -_iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, - const enum iwl_fw_dbg_trigger id) +iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, + enum iwl_fw_ini_trigger_id id) { - struct iwl_fw_ini_active_triggers *active = - &fwrt->dump.active_trigs[id]; - u32 ms; + struct iwl_fw_ini_trigger *trig; + u32 usec; + - if (!fwrt->trans->ini_valid) - return false; - if (!active->active) + if (!fwrt->trans->ini_valid || id >= IWL_FW_TRIGGER_ID_NUM || + !fwrt->dump.active_trigs[id].active) return false; - ms = le32_to_cpu(active->trig->ignore_consec); - if (ms) - ms /= USEC_PER_MSEC; + trig = fwrt->dump.active_trigs[id].trig; + usec = le32_to_cpu(trig->ignore_consec); - if (iwl_fw_dbg_no_trig_window(fwrt, id, ms)) { + if (iwl_fw_dbg_no_trig_window(fwrt, id, usec)) { IWL_WARN(fwrt, "Trigger %d fired in no-collect window\n", id); return false; } @@ -247,12 +246,6 @@ _iwl_fw_ini_trigger_on(struct iwl_fw_runtime *fwrt, return true; } -#define iwl_fw_ini_trigger_on(fwrt, wdev, id) ({ \ - BUILD_BUG_ON(!__builtin_constant_p(id)); \ - BUILD_BUG_ON((id) >= IWL_FW_TRIGGER_ID_NUM); \ - _iwl_fw_ini_trigger_on((fwrt), (wdev), (id)); \ -}) - static inline void _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, struct wireless_dev *wdev, -- cgit v1.2.3 From a197e6d10ce26bdf4e7b8941321fb924b38ece02 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 16 Jan 2019 19:49:24 -0800 Subject: iwlwifi: mvm: fix the spatial reuse parsing for HE_TRIG PPDUs The spatial reuse 4 words fields are fetched from the HE-SIGA by the firmware and propagated to the driver through the Rx info. This is useful to populate the radiotap header. We were looking at the wrong place in the firmware data and got bogus values. Fix that. Signed-off-by: Emmanuel Grumbach Fixes: bdf180c8d375 ("iwlwifi: mvm: change PHY data RX for HE radiotap") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index b0a8d910c5c4..1e03acf30762 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1074,16 +1074,16 @@ static void iwl_mvm_decode_he_phy_data(struct iwl_mvm *mvm, IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN | IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN); - he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, + he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2, IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE1), IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1); - he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, + he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2, IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE2), IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2); - he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, + he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2, IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE3), IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3); - he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d0, + he->data4 |= le16_encode_bits(le32_get_bits(phy_data->d2, IWL_RX_PHY_DATA2_HE_TB_EXT_SPTL_REUSE4), IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4); /* fall through */ -- cgit v1.2.3 From 21587a9b0a48bf8922e875b54edcc5a8a9a8b19f Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 17 Jan 2019 09:57:27 +0200 Subject: iwlwifi: dbg: buffer overflow in non_collect_ts_start array The size of the buffer is IWL_FW_TRIGGER_ID_NUM - 1 which is equal to IWL_FW_TRIGGER_ID_HOST_CHANNEL_SWITCH_COMPLETE so if the driver receives this trigger, it will cause a buffer overflow. Solve this by increasing the buffer size by 1. Signed-off-by: Shahar S Matityahu Fixes: fe1b7d6c2888 ("iwlwifi: add support for triggering ini triggers") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 41c4a3e7ad82..6e843998d1c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -138,7 +138,7 @@ struct iwl_fw_runtime { u8 conf; /* ts of the beginning of a non-collect fw dbg data period */ - unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM - 1]; + unsigned long non_collect_ts_start[IWL_FW_TRIGGER_ID_NUM]; u32 *d3_debug_data; struct iwl_fw_ini_region_cfg *active_regs[IWL_FW_INI_MAX_REGION_ID]; struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM]; -- cgit v1.2.3 From 69e508b44d5c84cf48cea41344cf9a0584484e31 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 10 Jan 2019 18:07:23 +0200 Subject: iwlwifi: mvm: Don't warn on command failure during restart When HW restart is requested but not started yet, commands would not be sent to the FW, and some function calls return an error. Such cases can trigger unneeded warning messages, e.g., in iwl_mvm_mac_sta_state() and iwl_mvm_bss_info_changed_station(). Handle a couple of these cases by also checking in the WARN_ON() condition that HW restart is not requested. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index c02559766712..313de9de02fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -2364,7 +2364,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, * If update fails - SF might be running in associated * mode while disassociated - which is forbidden. */ - WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false), + ret = iwl_mvm_sf_update(mvm, vif, false); + WARN_ONCE(ret && + !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status), "Failed to update SF upon disassociation\n"); /* @@ -3169,7 +3172,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, } else if (old_state == IEEE80211_STA_AUTHORIZED && new_state == IEEE80211_STA_ASSOC) { /* disable beacon filtering */ - WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, 0)); + ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); + WARN_ON(ret && + !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status)); ret = 0; } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTH) { -- cgit v1.2.3 From 44135b7c53d4d7199de3e1cf6e850996325f4da1 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 14 Jan 2019 15:57:44 +0200 Subject: iwlwifi: mvm: Do not return an error value on HW restart When HW restart is requested but not started yet, commands would not be sent to the FW, and some function calls would return an error. In case of iwl_mvm_mac_sta_state() returning an error value when a station is removed can lead to an unneeded warning in __sta_info_destroy_part2(). Handle this by setting the return value to 0, in case HW restart is in progress. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 313de9de02fc..a3bbf2ce571f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3207,6 +3207,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, mvm_sta->wep_key = NULL; } + if (unlikely(ret && + test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status))) + ret = 0; } else { ret = -EIO; } -- cgit v1.2.3 From 86ce5c740320ba4034b13227bacab8184857f37a Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 16 Jan 2019 10:25:55 +0200 Subject: iwlwifi: dbg_ini: add early and after alive apply points to unified images Add IWL_FW_INI_APPLY_EARLY and IWL_FW_INI_APPLY_AFTER_ALIVE apply points to unified images. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 1589b64232ce..1bc51e3260eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -419,12 +419,15 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) iwl_wait_init_complete, NULL); + iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY); + /* Will also start the device */ ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR); if (ret) { IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret); goto error; } + iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE); /* Send init config command to mark that we are sending NVM access * commands -- cgit v1.2.3 From 99944b73069d8bcea573c07df8dc8d4f33e78586 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Sun, 20 Jan 2019 11:33:57 +0200 Subject: iwlwifi: mvm: stop static queues correctly AP interfaces still use some static TX queues (for probes, broadcast and multicast frames). These queues were not stopped correctly when the transport layer indicated the queue should be stopped. As a result, when flushing the queues, new frames from the overflow queue were tx'd, so the queues still had frames after flushing. This ended up in an assert since trying to remove a station with non-empty queues. Fix it by stopping the static queues correctly when required. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 0bdf92c49710..33053d136a8c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1125,6 +1125,12 @@ static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode, iwl_trans_block_txq_ptrs(mvm->trans, false); } +static int iwl_mvm_is_static_queue(struct iwl_mvm *mvm, int queue) +{ + return queue == mvm->aux_queue || queue == mvm->probe_queue || + queue == mvm->p2p_dev_queue || queue == mvm->snif_queue; +} + static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, int hw_queue, bool start) { @@ -1151,6 +1157,15 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode, goto out; mvmsta = iwl_mvm_sta_from_mac80211(sta); + if (iwl_mvm_is_static_queue(mvm, hw_queue)) { + if (!start) + ieee80211_stop_queues(mvm->hw); + else if (mvmsta->sta_state != IEEE80211_STA_NOTEXIST) + ieee80211_wake_queues(mvm->hw); + + goto out; + } + if (iwl_mvm_has_new_tx_api(mvm)) { int tid = mvm->tvqm_info[hw_queue].txq_tid; -- cgit v1.2.3 From 415d39427317d1532d7f097471cc8aca5f229b69 Mon Sep 17 00:00:00 2001 From: Tonghao Zhang Date: Mon, 11 Feb 2019 10:49:48 -0800 Subject: bonding: check slave set command firstly This patch is a little improvement. If user use the command shown as below, we should print the info [1] instead of [2]. The eth0 exists actually, and it may confuse user. $ echo "eth0" > /sys/class/net/bond4/bonding/slaves [1] "bond4: no command found in slaves file - use +ifname or -ifname" [2] "write error: No such device" Signed-off-by: Tonghao Zhang Signed-off-by: David S. Miller --- drivers/net/bonding/bond_options.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 4d5d01cb8141..da1fc17295d9 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -1375,6 +1375,7 @@ static int bond_option_slaves_set(struct bonding *bond, sscanf(newval->string, "%16s", command); /* IFNAMSIZ*/ ifname = command + 1; if ((strlen(command) <= 1) || + (command[0] != '+' && command[0] != '-') || !dev_valid_name(ifname)) goto err_no_cmd; @@ -1398,6 +1399,7 @@ static int bond_option_slaves_set(struct bonding *bond, break; default: + /* should not run here. */ goto err_no_cmd; } -- cgit v1.2.3 From 76cba8fd9c7d8dd2d18c8bee581c4176383441c6 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 23:12:02 +0800 Subject: net: dlink: sundance: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in intr_handler() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Remove a redundant blank line in intr_handler(). Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/dlink/sundance.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index 1a27176381fb..4a37a69764ce 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c @@ -1193,7 +1193,6 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) int handled = 0; int i; - do { int intr_status = ioread16(ioaddr + IntrStatus); iowrite16(intr_status, ioaddr + IntrStatus); @@ -1286,7 +1285,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) dma_unmap_single(&np->pci_dev->dev, le32_to_cpu(np->tx_ring[entry].frag[0].addr), skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq (np->tx_skbuff[entry]); + dev_consume_skb_irq(np->tx_skbuff[entry]); np->tx_skbuff[entry] = NULL; np->tx_ring[entry].frag[0].addr = 0; np->tx_ring[entry].frag[0].length = 0; @@ -1305,7 +1304,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) dma_unmap_single(&np->pci_dev->dev, le32_to_cpu(np->tx_ring[entry].frag[0].addr), skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq (np->tx_skbuff[entry]); + dev_consume_skb_irq(np->tx_skbuff[entry]); np->tx_skbuff[entry] = NULL; np->tx_ring[entry].frag[0].addr = 0; np->tx_ring[entry].frag[0].length = 0; -- cgit v1.2.3 From fc67ade130382e21a43eca81c5ed098d8a82eedd Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 23:14:54 +0800 Subject: net: amd: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/lance.c | 2 +- drivers/net/ethernet/amd/ni65.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c index b56d84c7df46..f90b454b1642 100644 --- a/drivers/net/ethernet/amd/lance.c +++ b/drivers/net/ethernet/amd/lance.c @@ -1084,7 +1084,7 @@ static irqreturn_t lance_interrupt(int irq, void *dev_id) /* We must free the original skb if it's not a data-only copy in the bounce buffer. */ if (lp->tx_skbuff[entry]) { - dev_kfree_skb_irq(lp->tx_skbuff[entry]); + dev_consume_skb_irq(lp->tx_skbuff[entry]); lp->tx_skbuff[entry] = NULL; } dirty_tx++; diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c index 8931ce6bab7b..87ff5d6d1b22 100644 --- a/drivers/net/ethernet/amd/ni65.c +++ b/drivers/net/ethernet/amd/ni65.c @@ -1028,7 +1028,7 @@ static void ni65_xmit_intr(struct net_device *dev,int csr0) #ifdef XMT_VIA_SKB if(p->tmd_skb[p->tmdlast]) { - dev_kfree_skb_irq(p->tmd_skb[p->tmdlast]); + dev_consume_skb_irq(p->tmd_skb[p->tmdlast]); p->tmd_skb[p->tmdlast] = NULL; } #endif -- cgit v1.2.3 From 5fbc136b487852b5ec06855497efb688b7aa8b4e Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 23:15:43 +0800 Subject: net: myri10ge: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in myri10ge_tx_done() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 19ce0e605096..e0340f778d8f 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -1408,7 +1408,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index) if (skb) { ss->stats.tx_bytes += skb->len; ss->stats.tx_packets++; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); if (len) pci_unmap_single(pdev, dma_unmap_addr(&tx->info[idx], -- cgit v1.2.3 From d1a096c2c72d605ddcbb53a5f71f96cf9c6d384c Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 23:17:06 +0800 Subject: net: sgi: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/sgi/ioc3-eth.c | 2 +- drivers/net/ethernet/sgi/meth.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 3140999642ba..358e66b81926 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -666,7 +666,7 @@ static inline void ioc3_tx(struct net_device *dev) packets++; skb = ip->tx_skbs[o_entry]; bytes += skb->len; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); ip->tx_skbs[o_entry] = NULL; o_entry = (o_entry + 1) & 127; /* Next */ diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c index 67954a9e3675..f425ab528224 100644 --- a/drivers/net/ethernet/sgi/meth.c +++ b/drivers/net/ethernet/sgi/meth.c @@ -525,7 +525,7 @@ static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status) DPRINTK("RPTR points us here, but packet not done?\n"); break; } - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); priv->tx_skbs[priv->tx_read] = NULL; priv->tx_ring[priv->tx_read].header.raw = 0; priv->tx_read = (priv->tx_read+1)&(TX_RING_ENTRIES-1); -- cgit v1.2.3 From 105cfb064bcd60fdd74ac29a02f09efbc6a303d8 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 23:18:09 +0800 Subject: net: micrel: ks8695net: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in ks8695_tx_irq() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/micrel/ks8695net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/micrel/ks8695net.c b/drivers/net/ethernet/micrel/ks8695net.c index b881f5d4a7f9..6006d47707cb 100644 --- a/drivers/net/ethernet/micrel/ks8695net.c +++ b/drivers/net/ethernet/micrel/ks8695net.c @@ -391,7 +391,7 @@ ks8695_tx_irq(int irq, void *dev_id) ksp->tx_buffers[buff_n].dma_ptr, ksp->tx_buffers[buff_n].length, DMA_TO_DEVICE); - dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb); + dev_consume_skb_irq(ksp->tx_buffers[buff_n].skb); ksp->tx_buffers[buff_n].skb = NULL; ksp->tx_ring_used--; } -- cgit v1.2.3 From 380ab7e3d59d790e05d39f3c1d4a6039ef0e3901 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 23:19:14 +0800 Subject: net: natsemi: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/natsemi.c | 2 +- drivers/net/ethernet/natsemi/ns83820.c | 2 +- drivers/net/ethernet/natsemi/sonic.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index b9a1a9f999ea..1a2634cbbb69 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c @@ -2173,7 +2173,7 @@ static void netdev_tx_done(struct net_device *dev) np->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); /* Free the original skb. */ - dev_kfree_skb_irq(np->tx_skbuff[entry]); + dev_consume_skb_irq(np->tx_skbuff[entry]); np->tx_skbuff[entry] = NULL; } if (netif_queue_stopped(dev) && diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 958fced4dacf..000009e18ff8 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -1003,7 +1003,7 @@ static void do_tx_done(struct net_device *ndev) addr, len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); atomic_dec(&dev->nr_tx_skbs); } else pci_unmap_page(dev->pci_dev, diff --git a/drivers/net/ethernet/natsemi/sonic.c b/drivers/net/ethernet/natsemi/sonic.c index c805dcbebd02..aaec00912ea0 100644 --- a/drivers/net/ethernet/natsemi/sonic.c +++ b/drivers/net/ethernet/natsemi/sonic.c @@ -328,7 +328,7 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id) } /* We must free the original skb */ - dev_kfree_skb_irq(lp->tx_skb[entry]); + dev_consume_skb_irq(lp->tx_skb[entry]); lp->tx_skb[entry] = NULL; /* and unmap DMA buffer */ dma_unmap_single(lp->device, lp->tx_laddr[entry], lp->tx_len[entry], DMA_TO_DEVICE); -- cgit v1.2.3 From ae6279ecb786d9132da0315700580dc23f939986 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Wed, 13 Feb 2019 23:21:02 +0800 Subject: net: nuvoton: w90p910_ether: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in w90p910_ether_start_xmit() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/nuvoton/w90p910_ether.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index c662c6f5bee3..67bf02b0763a 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c @@ -630,7 +630,7 @@ static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!(w90p910_send_frame(dev, skb->data, skb->len))) { ether->skb = skb; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); return 0; } return -EAGAIN; -- cgit v1.2.3 From a37d45b6fa1113f96200abdfdb0d8c454c97a30e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 13 Feb 2019 08:55:02 -0800 Subject: net: ipvlan_l3s: fix kconfig dependency warning Fix the kconfig warning in IPVLAN_L3S when neither INET nor IPV6 is enabled: WARNING: unmet direct dependencies detected for NET_L3_MASTER_DEV Depends on [n]: NET [=y] && (INET [=n] || IPV6 [=n]) Selected by [y]: - IPVLAN_L3S [=y] && NETDEVICES [=y] && NET_CORE [=y] && NETFILTER [=y] Signed-off-by: Randy Dunlap Cc: Mahesh Bandewar Cc: Daniel Borkmann Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7f9727f64f55..6f561767b45e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -147,6 +147,7 @@ config MACVTAP config IPVLAN_L3S depends on NETFILTER + depends on IPVLAN def_bool y select NET_L3_MASTER_DEV -- cgit v1.2.3 From 189a10f0108a8ebaf1e2f3d8bf68aeb5ebd30109 Mon Sep 17 00:00:00 2001 From: Huang Zijiang Date: Thu, 14 Feb 2019 14:39:59 +0800 Subject: isdn:hisax: Replace dev_kfree_skb_any by dev_consume_skb_any The skb should be freed by dev_consume_skb_any() in hfcpci_fill_fifo() when bcs->tx_skb is still used. The bcs->tx_skb is be replaced by skb_dequeue(&bcs->squeue), so the original bcs->tx_skb should be consumed(not drop). Signed-off-by: Huang Zijiang Signed-off-by: David S. Miller --- drivers/isdn/hisax/hfc_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 81dd465afcf4..71a8312592d6 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -656,7 +656,7 @@ hfcpci_fill_fifo(struct BCState *bcs) schedule_event(bcs, B_ACKPENDING); } - dev_kfree_skb_any(bcs->tx_skb); + dev_consume_skb_any(bcs->tx_skb); bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); -- cgit v1.2.3 From edc307bb7e4897df53248bd92f94221371c596ac Mon Sep 17 00:00:00 2001 From: Huang Zijiang Date: Thu, 14 Feb 2019 14:40:31 +0800 Subject: net:dl2k: Modify the code style escaping the warning modify the code style in order to removing the following warning when excute the script checkpatch.pl WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Huang Zijiang Signed-off-by: David S. Miller --- drivers/net/ethernet/dlink/dl2k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c index d8d423f22c4f..d4ab63f07aef 100644 --- a/drivers/net/ethernet/dlink/dl2k.c +++ b/drivers/net/ethernet/dlink/dl2k.c @@ -843,9 +843,9 @@ rio_free_tx (struct net_device *dev, int irq) desc_to_dma(&np->tx_ring[entry]), skb->len, PCI_DMA_TODEVICE); if (irq) - dev_kfree_skb_irq (skb); + dev_kfree_skb_irq(skb); else - dev_kfree_skb (skb); + dev_kfree_skb(skb); np->tx_skbuff[entry] = NULL; entry = (entry + 1) % TX_RING_SIZE; -- cgit v1.2.3 From 62f2589883405081f3e0a4aae69f3fe8932348a3 Mon Sep 17 00:00:00 2001 From: Huang Zijiang Date: Thu, 14 Feb 2019 14:40:56 +0800 Subject: net:dl2k: Replace dev_kfree_skb_irq by dev_consume_skb_irq dev_consume_skb_irq() should be called when skb xmit done.It makes drop profiles more friendly. Signed-off-by: Huang Zijiang Signed-off-by: David S. Miller --- drivers/net/ethernet/dlink/dl2k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c index d4ab63f07aef..cfcdfee718b0 100644 --- a/drivers/net/ethernet/dlink/dl2k.c +++ b/drivers/net/ethernet/dlink/dl2k.c @@ -843,7 +843,7 @@ rio_free_tx (struct net_device *dev, int irq) desc_to_dma(&np->tx_ring[entry]), skb->len, PCI_DMA_TODEVICE); if (irq) - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); else dev_kfree_skb(skb); -- cgit v1.2.3 From f3e5c07002b08f0e001015fd221187efb772afae Mon Sep 17 00:00:00 2001 From: Huang Zijiang Date: Thu, 14 Feb 2019 14:41:18 +0800 Subject: net:ethernet:cadence: Replace dev_kfree_skb_any by dev_consume_skb_any The skb should be freed by dev_consume_skb_any() in macb_pad_and_fcs() when *skb is still used. The *skb is be replaced by nskb, so the original *skb should be consumed(not drop). Signed-off-by: Huang Zijiang Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 0d6288dd609a..f2915f2fe21a 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -1734,7 +1734,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev) if (!nskb) return -ENOMEM; - dev_kfree_skb_any(*skb); + dev_consume_skb_any(*skb); *skb = nskb; } -- cgit v1.2.3 From f694be27b7c0f31e926277dbde4395d56e79f36e Mon Sep 17 00:00:00 2001 From: Huang Zijiang Date: Thu, 14 Feb 2019 14:42:13 +0800 Subject: sfc: Replace dev_kfree_skb_any by dev_consume_skb_any The skb should be freed by dev_consume_skb_any() in efx_tx_tso_fallback() when skb is still used. The skb will be replaced by segments, so the original skb should be consumed(not drop). Signed-off-by: Huang Zijiang Acked-by: Bert Kenward Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 22eb059086f7..06c8f282263f 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -471,7 +471,7 @@ static int efx_tx_tso_fallback(struct efx_tx_queue *tx_queue, if (IS_ERR(segments)) return PTR_ERR(segments); - dev_kfree_skb_any(skb); + dev_consume_skb_any(skb); skb = segments; while (skb) { -- cgit v1.2.3 From d429005fdf2c9da19429c8b343eea61bd55b7c00 Mon Sep 17 00:00:00 2001 From: Vishal Kulkarni Date: Thu, 14 Feb 2019 18:19:15 +0530 Subject: cxgb4/cxgb4vf: Add support for SGE doorbell queue timer T6 introduced a Timer Mechanism in SGE called the SGE Doorbell Queue Timer. With this we can now configure TX Queues to get CIDX Updates when: Time(CIDX == PIDX) >= Timer Previously we rely on TX Queue Status Page updates by hardware for DMA completions. This will make Hardware/Firmware actually deliver the CIDX Updates as Ingress Queue messages with commensurate Interrupts. So we now have a new RX Path component for processing CIDX Updates and reclaiming TX Descriptors faster. Original work by: Casey Leedom Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 10 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 19 +- drivers/net/ethernet/chelsio/cxgb4/sge.c | 322 +++++++++++++++++++----- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 41 +++ drivers/net/ethernet/chelsio/cxgb4/t4_hw.h | 1 + drivers/net/ethernet/chelsio/cxgb4/t4_values.h | 6 + drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 24 +- drivers/net/ethernet/chelsio/cxgb4vf/sge.c | 27 +- 8 files changed, 375 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 568715a13b5c..68d0d453eb06 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -617,6 +617,7 @@ enum { /* adapter flags */ FW_OFLD_CONN = (1 << 9), ROOT_NO_RELAXED_ORDERING = (1 << 10), SHUTTING_DOWN = (1 << 11), + SGE_DBQ_TIMER = (1 << 12), }; enum { @@ -756,6 +757,8 @@ struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */ #ifdef CONFIG_CHELSIO_T4_DCB u8 dcb_prio; /* DCB Priority bound to queue */ #endif + u8 dbqt; /* SGE Doorbell Queue Timer in use */ + unsigned int dbqtimerix; /* SGE Doorbell Queue Timer Index */ unsigned long tso; /* # of TSO requests */ unsigned long tx_cso; /* # of Tx checksum offloads */ unsigned long vlan_ins; /* # of Tx VLAN insertions */ @@ -816,6 +819,7 @@ struct sge { u16 nqs_per_uld; /* # of Rx queues per ULD */ u16 timer_val[SGE_NTIMERS]; u8 counter_val[SGE_NCOUNTERS]; + u16 dbqtimer_val[SGE_NDBQTIMERS]; u32 fl_pg_order; /* large page allocation size */ u32 stat_len; /* length of status page at ring end */ u32 pktshift; /* padding between CPL & packet data */ @@ -1402,7 +1406,7 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, rspq_flush_handler_t flush_handler, int cong); int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, struct net_device *dev, struct netdev_queue *netdevq, - unsigned int iqid); + unsigned int iqid, u8 dbqt); int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq, struct net_device *dev, unsigned int iqid, unsigned int cmplqid); @@ -1415,6 +1419,8 @@ irqreturn_t t4_sge_intr_msix(int irq, void *cookie); int t4_sge_init(struct adapter *adap); void t4_sge_start(struct adapter *adap); void t4_sge_stop(struct adapter *adap); +int t4_sge_eth_txq_egress_update(struct adapter *adap, struct sge_eth_txq *q, + int maxreclaim); void cxgb4_set_ethtool_ops(struct net_device *netdev); int cxgb4_write_rss(const struct port_info *pi, const u16 *queues); enum cpl_tx_tnl_lso_type cxgb_encap_offload_supported(struct sk_buff *skb); @@ -1821,6 +1827,8 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, unsigned int vf, unsigned int eqid); int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox, int ctxt_type); +int t4_read_sge_dbqtimers(struct adapter *adap, unsigned int ndbqtimers, + u16 *dbqtimers); void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl); int t4_update_port_info(struct port_info *pi); int t4_get_link_params(struct port_info *pi, unsigned int *link_okp, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index adf75d16e6d3..bdd11a617579 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -575,7 +575,7 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp, struct sge_eth_txq *eq; eq = container_of(txq, struct sge_eth_txq, q); - netif_tx_wake_queue(eq->txq); + t4_sge_eth_txq_egress_update(q->adap, eq, -1); } else { struct sge_uld_txq *oq; @@ -933,10 +933,13 @@ static int setup_sge_queues(struct adapter *adap) q->rspq.idx = j; memset(&q->stats, 0, sizeof(q->stats)); } - for (j = 0; j < pi->nqsets; j++, t++) { + + q = &s->ethrxq[pi->first_qset]; + for (j = 0; j < pi->nqsets; j++, t++, q++) { err = t4_sge_alloc_eth_txq(adap, t, dev, netdev_get_tx_queue(dev, j), - s->fw_evtq.cntxt_id); + q->rspq.cntxt_id, + !!(adap->flags & SGE_DBQ_TIMER)); if (err) goto freeout; } @@ -958,7 +961,7 @@ static int setup_sge_queues(struct adapter *adap) if (!is_t4(adap->params.chip)) { err = t4_sge_alloc_eth_txq(adap, &s->ptptxq, adap->port[0], netdev_get_tx_queue(adap->port[0], 0) - , s->fw_evtq.cntxt_id); + , s->fw_evtq.cntxt_id, false); if (err) goto freeout; } @@ -4325,6 +4328,14 @@ static int adap_init0(struct adapter *adap) if (ret < 0) goto bye; + /* Grab the SGE Doorbell Queue Timer values. If successful, that + * indicates that the Firmware and Hardware support this. + */ + ret = t4_read_sge_dbqtimers(adap, ARRAY_SIZE(adap->sge.dbqtimer_val), + adap->sge.dbqtimer_val); + if (!ret) + adap->flags |= SGE_DBQ_TIMER; + if (is_bypass_device(adap->pdev->device)) adap->params.bypass = 1; diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index fc0bc6458e84..f18493fb32aa 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -80,9 +80,10 @@ * Max number of Tx descriptors we clean up at a time. Should be modest as * freeing skbs isn't cheap and it happens while holding locks. We just need * to free packets faster than they arrive, we eventually catch up and keep - * the amortized cost reasonable. Must be >= 2 * TXQ_STOP_THRES. + * the amortized cost reasonable. Must be >= 2 * TXQ_STOP_THRES. It should + * also match the CIDX Flush Threshold. */ -#define MAX_TX_RECLAIM 16 +#define MAX_TX_RECLAIM 32 /* * Max number of Rx buffers we replenish at a time. Again keep this modest, @@ -401,31 +402,52 @@ static inline int reclaimable(const struct sge_txq *q) } /** - * cxgb4_reclaim_completed_tx - reclaims completed Tx descriptors + * reclaim_completed_tx - reclaims completed TX Descriptors * @adap: the adapter * @q: the Tx queue to reclaim completed descriptors from + * @maxreclaim: the maximum number of TX Descriptors to reclaim or -1 * @unmap: whether the buffers should be unmapped for DMA * - * Reclaims Tx descriptors that the SGE has indicated it has processed, - * and frees the associated buffers if possible. Called with the Tx - * queue locked. + * Reclaims Tx Descriptors that the SGE has indicated it has processed, + * and frees the associated buffers if possible. If @max == -1, then + * we'll use a defaiult maximum. Called with the TX Queue locked. */ -inline void cxgb4_reclaim_completed_tx(struct adapter *adap, struct sge_txq *q, - bool unmap) +static inline int reclaim_completed_tx(struct adapter *adap, struct sge_txq *q, + int maxreclaim, bool unmap) { - int avail = reclaimable(q); + int reclaim = reclaimable(q); - if (avail) { + if (reclaim) { /* * Limit the amount of clean up work we do at a time to keep * the Tx lock hold time O(1). */ - if (avail > MAX_TX_RECLAIM) - avail = MAX_TX_RECLAIM; + if (maxreclaim < 0) + maxreclaim = MAX_TX_RECLAIM; + if (reclaim > maxreclaim) + reclaim = maxreclaim; - free_tx_desc(adap, q, avail, unmap); - q->in_use -= avail; + free_tx_desc(adap, q, reclaim, unmap); + q->in_use -= reclaim; } + + return reclaim; +} + +/** + * cxgb4_reclaim_completed_tx - reclaims completed Tx descriptors + * @adap: the adapter + * @q: the Tx queue to reclaim completed descriptors from + * @unmap: whether the buffers should be unmapped for DMA + * + * Reclaims Tx descriptors that the SGE has indicated it has processed, + * and frees the associated buffers if possible. Called with the Tx + * queue locked. + */ +void cxgb4_reclaim_completed_tx(struct adapter *adap, struct sge_txq *q, + bool unmap) +{ + (void)reclaim_completed_tx(adap, q, -1, unmap); } EXPORT_SYMBOL(cxgb4_reclaim_completed_tx); @@ -1287,6 +1309,44 @@ static inline void t6_fill_tnl_lso(struct sk_buff *skb, tnl_lso->EthLenOffset_Size = htonl(CPL_TX_TNL_LSO_SIZE_V(skb->len)); } +/** + * t4_sge_eth_txq_egress_update - handle Ethernet TX Queue update + * @adap: the adapter + * @eq: the Ethernet TX Queue + * @maxreclaim: the maximum number of TX Descriptors to reclaim or -1 + * + * We're typically called here to update the state of an Ethernet TX + * Queue with respect to the hardware's progress in consuming the TX + * Work Requests that we've put on that Egress Queue. This happens + * when we get Egress Queue Update messages and also prophylactically + * in regular timer-based Ethernet TX Queue maintenance. + */ +int t4_sge_eth_txq_egress_update(struct adapter *adap, struct sge_eth_txq *eq, + int maxreclaim) +{ + struct sge_txq *q = &eq->q; + unsigned int reclaimed; + + if (!q->in_use || !__netif_tx_trylock(eq->txq)) + return 0; + + /* Reclaim pending completed TX Descriptors. */ + reclaimed = reclaim_completed_tx(adap, &eq->q, maxreclaim, true); + + /* If the TX Queue is currently stopped and there's now more than half + * the queue available, restart it. Otherwise bail out since the rest + * of what we want do here is with the possibility of shipping any + * currently buffered Coalesced TX Work Request. + */ + if (netif_tx_queue_stopped(eq->txq) && txq_avail(q) > (q->size / 2)) { + netif_tx_wake_queue(eq->txq); + eq->q.restarts++; + } + + __netif_tx_unlock(eq->txq); + return reclaimed; +} + /** * cxgb4_eth_xmit - add a packet to an Ethernet Tx queue * @skb: the packet @@ -1357,7 +1417,7 @@ out_free: dev_kfree_skb_any(skb); } skb_tx_timestamp(skb); - cxgb4_reclaim_completed_tx(adap, &q->q, true); + reclaim_completed_tx(adap, &q->q, -1, true); cntrl = TXPKT_L4CSUM_DIS_F | TXPKT_IPCSUM_DIS_F; #ifdef CONFIG_CHELSIO_T4_FCOE @@ -1400,8 +1460,25 @@ out_free: dev_kfree_skb_any(skb); wr_mid = FW_WR_LEN16_V(DIV_ROUND_UP(flits, 2)); if (unlikely(credits < ETHTXQ_STOP_THRES)) { + /* After we're done injecting the Work Request for this + * packet, we'll be below our "stop threshold" so stop the TX + * Queue now and schedule a request for an SGE Egress Queue + * Update message. The queue will get started later on when + * the firmware processes this Work Request and sends us an + * Egress Queue Status Update message indicating that space + * has opened up. + */ eth_txq_stop(q); - wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; + + /* If we're using the SGE Doorbell Queue Timer facility, we + * don't need to ask the Firmware to send us Egress Queue CIDX + * Updates: the Hardware will do this automatically. And + * since we send the Ingress Queue CIDX Updates to the + * corresponding Ethernet Response Queue, we'll get them very + * quickly. + */ + if (!q->dbqt) + wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; } wr = (void *)&q->q.desc[q->q.pidx]; @@ -1671,7 +1748,7 @@ static netdev_tx_t cxgb4_vf_eth_xmit(struct sk_buff *skb, /* Take this opportunity to reclaim any TX Descriptors whose DMA * transfers have completed. */ - cxgb4_reclaim_completed_tx(adapter, &txq->q, true); + reclaim_completed_tx(adapter, &txq->q, -1, true); /* Calculate the number of flits and TX Descriptors we're going to * need along with how many TX Descriptors will be left over after @@ -1715,7 +1792,16 @@ static netdev_tx_t cxgb4_vf_eth_xmit(struct sk_buff *skb, * has opened up. */ eth_txq_stop(txq); - wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; + + /* If we're using the SGE Doorbell Queue Timer facility, we + * don't need to ask the Firmware to send us Egress Queue CIDX + * Updates: the Hardware will do this automatically. And + * since we send the Ingress Queue CIDX Updates to the + * corresponding Ethernet Response Queue, we'll get them very + * quickly. + */ + if (!txq->dbqt) + wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F; } /* Start filling in our Work Request. Note that we do _not_ handle @@ -2793,6 +2879,74 @@ static int t4_tx_hststamp(struct adapter *adapter, struct sk_buff *skb, return 1; } +/** + * t4_tx_completion_handler - handle CPL_SGE_EGR_UPDATE messages + * @rspq: Ethernet RX Response Queue associated with Ethernet TX Queue + * @rsp: Response Entry pointer into Response Queue + * @gl: Gather List pointer + * + * For adapters which support the SGE Doorbell Queue Timer facility, + * we configure the Ethernet TX Queues to send CIDX Updates to the + * Associated Ethernet RX Response Queue with CPL_SGE_EGR_UPDATE + * messages. This adds a small load to PCIe Link RX bandwidth and, + * potentially, higher CPU Interrupt load, but allows us to respond + * much more quickly to the CIDX Updates. This is important for + * Upper Layer Software which isn't willing to have a large amount + * of TX Data outstanding before receiving DMA Completions. + */ +static void t4_tx_completion_handler(struct sge_rspq *rspq, + const __be64 *rsp, + const struct pkt_gl *gl) +{ + u8 opcode = ((const struct rss_header *)rsp)->opcode; + struct port_info *pi = netdev_priv(rspq->netdev); + struct adapter *adapter = rspq->adap; + struct sge *s = &adapter->sge; + struct sge_eth_txq *txq; + + /* skip RSS header */ + rsp++; + + /* FW can send EGR_UPDATEs encapsulated in a CPL_FW4_MSG. + */ + if (unlikely(opcode == CPL_FW4_MSG && + ((const struct cpl_fw4_msg *)rsp)->type == + FW_TYPE_RSSCPL)) { + rsp++; + opcode = ((const struct rss_header *)rsp)->opcode; + rsp++; + } + + if (unlikely(opcode != CPL_SGE_EGR_UPDATE)) { + pr_info("%s: unexpected FW4/CPL %#x on Rx queue\n", + __func__, opcode); + return; + } + + txq = &s->ethtxq[pi->first_qset + rspq->idx]; + + /* We've got the Hardware Consumer Index Update in the Egress Update + * message. If we're using the SGE Doorbell Queue Timer mechanism, + * these Egress Update messages will be our sole CIDX Updates we get + * since we don't want to chew up PCIe bandwidth for both Ingress + * Messages and Status Page writes. However, The code which manages + * reclaiming successfully DMA'ed TX Work Requests uses the CIDX value + * stored in the Status Page at the end of the TX Queue. It's easiest + * to simply copy the CIDX Update value from the Egress Update message + * to the Status Page. Also note that no Endian issues need to be + * considered here since both are Big Endian and we're just copying + * bytes consistently ... + */ + if (txq->dbqt) { + struct cpl_sge_egr_update *egr; + + egr = (struct cpl_sge_egr_update *)rsp; + WRITE_ONCE(txq->q.stat->cidx, egr->cidx); + } + + t4_sge_eth_txq_egress_update(adapter, txq, -1); +} + /** * t4_ethrx_handler - process an ingress ethernet packet * @q: the response queue that received the packet @@ -2816,6 +2970,15 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, struct port_info *pi; int ret = 0; + /* If we're looking at TX Queue CIDX Update, handle that separately + * and return. + */ + if (unlikely((*(u8 *)rsp == CPL_FW4_MSG) || + (*(u8 *)rsp == CPL_SGE_EGR_UPDATE))) { + t4_tx_completion_handler(q, rsp, si); + return 0; + } + if (unlikely(*(u8 *)rsp == cpl_trace_pkt)) return handle_trace_pkt(q->adap, si); @@ -3289,10 +3452,10 @@ done: static void sge_tx_timer_cb(struct timer_list *t) { - unsigned long m; - unsigned int i, budget; struct adapter *adap = from_timer(adap, t, sge.tx_timer); struct sge *s = &adap->sge; + unsigned long m, period; + unsigned int i, budget; for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++) for (m = s->txq_maperr[i]; m; m &= m - 1) { @@ -3320,29 +3483,29 @@ static void sge_tx_timer_cb(struct timer_list *t) budget = MAX_TIMER_TX_RECLAIM; i = s->ethtxq_rover; do { - struct sge_eth_txq *q = &s->ethtxq[i]; - - if (q->q.in_use && - time_after_eq(jiffies, q->txq->trans_start + HZ / 100) && - __netif_tx_trylock(q->txq)) { - int avail = reclaimable(&q->q); - - if (avail) { - if (avail > budget) - avail = budget; - - free_tx_desc(adap, &q->q, avail, true); - q->q.in_use -= avail; - budget -= avail; - } - __netif_tx_unlock(q->txq); - } + budget -= t4_sge_eth_txq_egress_update(adap, &s->ethtxq[i], + budget); + if (!budget) + break; if (++i >= s->ethqsets) i = 0; - } while (budget && i != s->ethtxq_rover); + } while (i != s->ethtxq_rover); s->ethtxq_rover = i; - mod_timer(&s->tx_timer, jiffies + (budget ? TX_QCHECK_PERIOD : 2)); + + if (budget == 0) { + /* If we found too many reclaimable packets schedule a timer + * in the near future to continue where we left off. + */ + period = 2; + } else { + /* We reclaimed all reclaimable TX Descriptors, so reschedule + * at the normal period. + */ + period = TX_QCHECK_PERIOD; + } + + mod_timer(&s->tx_timer, jiffies + period); } /** @@ -3421,7 +3584,8 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, : FW_IQ_IQTYPE_OFLD)); if (fl) { - enum chip_type chip = CHELSIO_CHIP_VERSION(adap->params.chip); + unsigned int chip_ver = + CHELSIO_CHIP_VERSION(adap->params.chip); /* Allocate the ring for the hardware free list (with space * for its status page) along with the associated software @@ -3459,10 +3623,10 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, * the smaller 64-byte value there). */ c.fl0dcaen_to_fl0cidxfthresh = - htons(FW_IQ_CMD_FL0FBMIN_V(chip <= CHELSIO_T5 ? + htons(FW_IQ_CMD_FL0FBMIN_V(chip_ver <= CHELSIO_T5 ? FETCHBURSTMIN_128B_X : - FETCHBURSTMIN_64B_X) | - FW_IQ_CMD_FL0FBMAX_V((chip <= CHELSIO_T5) ? + FETCHBURSTMIN_64B_T6_X) | + FW_IQ_CMD_FL0FBMAX_V((chip_ver <= CHELSIO_T5) ? FETCHBURSTMAX_512B_X : FETCHBURSTMAX_256B_X)); c.fl0size = htons(flsz); @@ -3584,14 +3748,24 @@ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id) adap->sge.egr_map[id - adap->sge.egr_start] = q; } +/** + * t4_sge_alloc_eth_txq - allocate an Ethernet TX Queue + * @adap: the adapter + * @txq: the SGE Ethernet TX Queue to initialize + * @dev: the Linux Network Device + * @netdevq: the corresponding Linux TX Queue + * @iqid: the Ingress Queue to which to deliver CIDX Update messages + * @dbqt: whether this TX Queue will use the SGE Doorbell Queue Timers + */ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, struct net_device *dev, struct netdev_queue *netdevq, - unsigned int iqid) + unsigned int iqid, u8 dbqt) { - int ret, nentries; - struct fw_eq_eth_cmd c; - struct sge *s = &adap->sge; + unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip); struct port_info *pi = netdev_priv(dev); + struct sge *s = &adap->sge; + struct fw_eq_eth_cmd c; + int ret, nentries; /* Add status entries */ nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc); @@ -3610,19 +3784,47 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, FW_EQ_ETH_CMD_VFN_V(0)); c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_ALLOC_F | FW_EQ_ETH_CMD_EQSTART_F | FW_LEN16(c)); - c.viid_pkd = htonl(FW_EQ_ETH_CMD_AUTOEQUEQE_F | - FW_EQ_ETH_CMD_VIID_V(pi->viid)); + + /* For TX Ethernet Queues using the SGE Doorbell Queue Timer + * mechanism, we use Ingress Queue messages for Hardware Consumer + * Index Updates on the TX Queue. Otherwise we have the Hardware + * write the CIDX Updates into the Status Page at the end of the + * TX Queue. + */ + c.autoequiqe_to_viid = htonl((dbqt + ? FW_EQ_ETH_CMD_AUTOEQUIQE_F + : FW_EQ_ETH_CMD_AUTOEQUEQE_F) | + FW_EQ_ETH_CMD_VIID_V(pi->viid)); + c.fetchszm_to_iqid = - htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(HOSTFCMODE_STATUS_PAGE_X) | + htonl(FW_EQ_ETH_CMD_HOSTFCMODE_V(dbqt + ? HOSTFCMODE_INGRESS_QUEUE_X + : HOSTFCMODE_STATUS_PAGE_X) | FW_EQ_ETH_CMD_PCIECHN_V(pi->tx_chan) | FW_EQ_ETH_CMD_FETCHRO_F | FW_EQ_ETH_CMD_IQID_V(iqid)); + + /* Note that the CIDX Flush Threshold should match MAX_TX_RECLAIM. */ c.dcaen_to_eqsize = - htonl(FW_EQ_ETH_CMD_FBMIN_V(FETCHBURSTMIN_64B_X) | + htonl(FW_EQ_ETH_CMD_FBMIN_V(chip_ver <= CHELSIO_T5 + ? FETCHBURSTMIN_64B_X + : FETCHBURSTMIN_64B_T6_X) | FW_EQ_ETH_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) | FW_EQ_ETH_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) | FW_EQ_ETH_CMD_EQSIZE_V(nentries)); + c.eqaddr = cpu_to_be64(txq->q.phys_addr); + /* If we're using the SGE Doorbell Queue Timer mechanism, pass in the + * currently configured Timer Index. THis can be changed later via an + * ethtool -C tx-usecs {Timer Val} command. Note that the SGE + * Doorbell Queue mode is currently automatically enabled in the + * Firmware by setting either AUTOEQUEQE or AUTOEQUIQE ... + */ + if (dbqt) + c.timeren_timerix = + cpu_to_be32(FW_EQ_ETH_CMD_TIMEREN_F | + FW_EQ_ETH_CMD_TIMERIX_V(txq->dbqtimerix)); + ret = t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), &c); if (ret) { kfree(txq->q.sdesc); @@ -3639,6 +3841,8 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq, txq->txq = netdevq; txq->tso = txq->tx_cso = txq->vlan_ins = 0; txq->mapping_err = 0; + txq->dbqt = dbqt; + return 0; } @@ -3646,10 +3850,11 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq, struct net_device *dev, unsigned int iqid, unsigned int cmplqid) { - int ret, nentries; - struct fw_eq_ctrl_cmd c; - struct sge *s = &adap->sge; + unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip); struct port_info *pi = netdev_priv(dev); + struct sge *s = &adap->sge; + struct fw_eq_ctrl_cmd c; + int ret, nentries; /* Add status entries */ nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc); @@ -3673,7 +3878,9 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq, FW_EQ_CTRL_CMD_PCIECHN_V(pi->tx_chan) | FW_EQ_CTRL_CMD_FETCHRO_F | FW_EQ_CTRL_CMD_IQID_V(iqid)); c.dcaen_to_eqsize = - htonl(FW_EQ_CTRL_CMD_FBMIN_V(FETCHBURSTMIN_64B_X) | + htonl(FW_EQ_CTRL_CMD_FBMIN_V(chip_ver <= CHELSIO_T5 + ? FETCHBURSTMIN_64B_X + : FETCHBURSTMIN_64B_T6_X) | FW_EQ_CTRL_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) | FW_EQ_CTRL_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) | FW_EQ_CTRL_CMD_EQSIZE_V(nentries)); @@ -3713,6 +3920,7 @@ int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq, struct net_device *dev, unsigned int iqid, unsigned int uld_type) { + unsigned int chip_ver = CHELSIO_CHIP_VERSION(adap->params.chip); int ret, nentries; struct fw_eq_ofld_cmd c; struct sge *s = &adap->sge; @@ -3743,7 +3951,9 @@ int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq, FW_EQ_OFLD_CMD_PCIECHN_V(pi->tx_chan) | FW_EQ_OFLD_CMD_FETCHRO_F | FW_EQ_OFLD_CMD_IQID_V(iqid)); c.dcaen_to_eqsize = - htonl(FW_EQ_OFLD_CMD_FBMIN_V(FETCHBURSTMIN_64B_X) | + htonl(FW_EQ_OFLD_CMD_FBMIN_V(chip_ver <= CHELSIO_T5 + ? FETCHBURSTMIN_64B_X + : FETCHBURSTMIN_64B_T6_X) | FW_EQ_OFLD_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) | FW_EQ_OFLD_CMD_CIDXFTHRESH_V(CIDXFLUSHTHRESH_32_X) | FW_EQ_OFLD_CMD_EQSIZE_V(nentries)); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index c5e5466ee38b..27af347be4af 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -6712,6 +6712,47 @@ int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox, int ctxt_type) return ret; } +/** + * t4_read_sge_dbqtimers - reag SGE Doorbell Queue Timer values + * @adap - the adapter + * @ndbqtimers: size of the provided SGE Doorbell Queue Timer table + * @dbqtimers: SGE Doorbell Queue Timer table + * + * Reads the SGE Doorbell Queue Timer values into the provided table. + * Returns 0 on success (Firmware and Hardware support this feature), + * an error on failure. + */ +int t4_read_sge_dbqtimers(struct adapter *adap, unsigned int ndbqtimers, + u16 *dbqtimers) +{ + int ret, dbqtimerix; + + ret = 0; + dbqtimerix = 0; + while (dbqtimerix < ndbqtimers) { + int nparams, param; + u32 params[7], vals[7]; + + nparams = ndbqtimers - dbqtimerix; + if (nparams > ARRAY_SIZE(params)) + nparams = ARRAY_SIZE(params); + + for (param = 0; param < nparams; param++) + params[param] = + (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DBQ_TIMER) | + FW_PARAMS_PARAM_Y_V(dbqtimerix + param)); + ret = t4_query_params(adap, adap->mbox, adap->pf, 0, + nparams, params, vals); + if (ret) + break; + + for (param = 0; param < nparams; param++) + dbqtimers[dbqtimerix++] = vals[param]; + } + return ret; +} + /** * t4_fw_hello - establish communication with FW * @adap: the adapter diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h index 361d5032c288..002fc62ea726 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h @@ -91,6 +91,7 @@ enum { SGE_CTXT_SIZE = 24, /* size of SGE context */ SGE_NTIMERS = 6, /* # of interrupt holdoff timer values */ SGE_NCOUNTERS = 4, /* # of interrupt packet counter values */ + SGE_NDBQTIMERS = 8, /* # of Doorbell Queue Timer values */ SGE_MAX_IQ_SIZE = 65520, SGE_TIMER_RSTRT_CNTR = 6, /* restart RX packet threshold counter */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_values.h b/drivers/net/ethernet/chelsio/cxgb4/t4_values.h index f6558cbfc54e..eb1aa82149db 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_values.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_values.h @@ -71,12 +71,18 @@ #define FETCHBURSTMIN_64B_X 2 #define FETCHBURSTMIN_128B_X 3 +/* T6 and later use a single-bit encoding for FetchBurstMin */ +#define FETCHBURSTMIN_64B_T6_X 0 +#define FETCHBURSTMIN_128B_T6_X 1 + #define FETCHBURSTMAX_256B_X 2 #define FETCHBURSTMAX_512B_X 3 +#define HOSTFCMODE_INGRESS_QUEUE_X 1 #define HOSTFCMODE_STATUS_PAGE_X 2 #define CIDXFLUSHTHRESH_32_X 5 +#define CIDXFLUSHTHRESH_128_X 7 #define UPDATEDELIVERY_INTERRUPT_X 1 diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 1d9b3e1e5f94..631f1663f4e0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -1254,6 +1254,8 @@ enum fw_params_param_dev { FW_PARAMS_PARAM_DEV_RDMA_WRITE_WITH_IMM = 0x21, FW_PARAMS_PARAM_DEV_RI_WRITE_CMPL_WR = 0x24, FW_PARAMS_PARAM_DEV_OPAQUE_VIID_SMT_EXTN = 0x27, + FW_PARAMS_PARAM_DEV_DBQ_TIMER = 0x29, + FW_PARAMS_PARAM_DEV_DBQ_TIMERTICK = 0x2A, }; /* @@ -1322,6 +1324,7 @@ enum fw_params_param_dmaq { FW_PARAMS_PARAM_DMAQ_EQ_CMPLIQID_CTRL = 0x11, FW_PARAMS_PARAM_DMAQ_EQ_SCHEDCLASS_ETH = 0x12, FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH = 0x13, + FW_PARAMS_PARAM_DMAQ_EQ_TIMERIX = 0x15, FW_PARAMS_PARAM_DMAQ_CONM_CTXT = 0x20, }; @@ -1751,8 +1754,8 @@ struct fw_eq_eth_cmd { __be32 fetchszm_to_iqid; __be32 dcaen_to_eqsize; __be64 eqaddr; - __be32 viid_pkd; - __be32 r8_lo; + __be32 autoequiqe_to_viid; + __be32 timeren_timerix; __be64 r9; }; @@ -1847,6 +1850,10 @@ struct fw_eq_eth_cmd { #define FW_EQ_ETH_CMD_EQSIZE_S 0 #define FW_EQ_ETH_CMD_EQSIZE_V(x) ((x) << FW_EQ_ETH_CMD_EQSIZE_S) +#define FW_EQ_ETH_CMD_AUTOEQUIQE_S 31 +#define FW_EQ_ETH_CMD_AUTOEQUIQE_V(x) ((x) << FW_EQ_ETH_CMD_AUTOEQUIQE_S) +#define FW_EQ_ETH_CMD_AUTOEQUIQE_F FW_EQ_ETH_CMD_AUTOEQUIQE_V(1U) + #define FW_EQ_ETH_CMD_AUTOEQUEQE_S 30 #define FW_EQ_ETH_CMD_AUTOEQUEQE_V(x) ((x) << FW_EQ_ETH_CMD_AUTOEQUEQE_S) #define FW_EQ_ETH_CMD_AUTOEQUEQE_F FW_EQ_ETH_CMD_AUTOEQUEQE_V(1U) @@ -1854,6 +1861,19 @@ struct fw_eq_eth_cmd { #define FW_EQ_ETH_CMD_VIID_S 16 #define FW_EQ_ETH_CMD_VIID_V(x) ((x) << FW_EQ_ETH_CMD_VIID_S) +#define FW_EQ_ETH_CMD_TIMEREN_S 3 +#define FW_EQ_ETH_CMD_TIMEREN_M 0x1 +#define FW_EQ_ETH_CMD_TIMEREN_V(x) ((x) << FW_EQ_ETH_CMD_TIMEREN_S) +#define FW_EQ_ETH_CMD_TIMEREN_G(x) \ + (((x) >> FW_EQ_ETH_CMD_TIMEREN_S) & FW_EQ_ETH_CMD_TIMEREN_M) +#define FW_EQ_ETH_CMD_TIMEREN_F FW_EQ_ETH_CMD_TIMEREN_V(1U) + +#define FW_EQ_ETH_CMD_TIMERIX_S 0 +#define FW_EQ_ETH_CMD_TIMERIX_M 0x7 +#define FW_EQ_ETH_CMD_TIMERIX_V(x) ((x) << FW_EQ_ETH_CMD_TIMERIX_S) +#define FW_EQ_ETH_CMD_TIMERIX_G(x) \ + (((x) >> FW_EQ_ETH_CMD_TIMERIX_S) & FW_EQ_ETH_CMD_TIMERIX_M) + struct fw_eq_ctrl_cmd { __be32 op_to_vfn; __be32 alloc_to_len16; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index 1d534f0baa69..11d2ba0a2bf5 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -2268,7 +2268,7 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, cmd.iqaddr = cpu_to_be64(rspq->phys_addr); if (fl) { - enum chip_type chip = + unsigned int chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip); /* * Allocate the ring for the hardware free list (with space @@ -2319,10 +2319,10 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, */ cmd.fl0dcaen_to_fl0cidxfthresh = cpu_to_be16( - FW_IQ_CMD_FL0FBMIN_V(chip <= CHELSIO_T5 ? - FETCHBURSTMIN_128B_X : - FETCHBURSTMIN_64B_X) | - FW_IQ_CMD_FL0FBMAX_V((chip <= CHELSIO_T5) ? + FW_IQ_CMD_FL0FBMIN_V(chip_ver <= CHELSIO_T5 + ? FETCHBURSTMIN_128B_X + : FETCHBURSTMIN_64B_T6_X) | + FW_IQ_CMD_FL0FBMAX_V((chip_ver <= CHELSIO_T5) ? FETCHBURSTMAX_512B_X : FETCHBURSTMAX_256B_X)); cmd.fl0size = cpu_to_be16(flsz); @@ -2411,10 +2411,11 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq, struct net_device *dev, struct netdev_queue *devq, unsigned int iqid) { + unsigned int chip_ver = CHELSIO_CHIP_VERSION(adapter->params.chip); + struct port_info *pi = netdev_priv(dev); + struct fw_eq_eth_cmd cmd, rpl; struct sge *s = &adapter->sge; int ret, nentries; - struct fw_eq_eth_cmd cmd, rpl; - struct port_info *pi = netdev_priv(dev); /* * Calculate the size of the hardware TX Queue (including the Status @@ -2448,17 +2449,19 @@ int t4vf_sge_alloc_eth_txq(struct adapter *adapter, struct sge_eth_txq *txq, cmd.alloc_to_len16 = cpu_to_be32(FW_EQ_ETH_CMD_ALLOC_F | FW_EQ_ETH_CMD_EQSTART_F | FW_LEN16(cmd)); - cmd.viid_pkd = cpu_to_be32(FW_EQ_ETH_CMD_AUTOEQUEQE_F | - FW_EQ_ETH_CMD_VIID_V(pi->viid)); + cmd.autoequiqe_to_viid = cpu_to_be32(FW_EQ_ETH_CMD_AUTOEQUEQE_F | + FW_EQ_ETH_CMD_VIID_V(pi->viid)); cmd.fetchszm_to_iqid = cpu_to_be32(FW_EQ_ETH_CMD_HOSTFCMODE_V(SGE_HOSTFCMODE_STPG) | FW_EQ_ETH_CMD_PCIECHN_V(pi->port_id) | FW_EQ_ETH_CMD_IQID_V(iqid)); cmd.dcaen_to_eqsize = - cpu_to_be32(FW_EQ_ETH_CMD_FBMIN_V(SGE_FETCHBURSTMIN_64B) | - FW_EQ_ETH_CMD_FBMAX_V(SGE_FETCHBURSTMAX_512B) | + cpu_to_be32(FW_EQ_ETH_CMD_FBMIN_V(chip_ver <= CHELSIO_T5 + ? FETCHBURSTMIN_64B_X + : FETCHBURSTMIN_64B_T6_X) | + FW_EQ_ETH_CMD_FBMAX_V(FETCHBURSTMAX_512B_X) | FW_EQ_ETH_CMD_CIDXFTHRESH_V( - SGE_CIDXFLUSHTHRESH_32) | + CIDXFLUSHTHRESH_32_X) | FW_EQ_ETH_CMD_EQSIZE_V(nentries)); cmd.eqaddr = cpu_to_be64(txq->q.phys_addr); -- cgit v1.2.3 From 543a1b85e734d2ec62e5df61641e8ea7349de4a8 Mon Sep 17 00:00:00 2001 From: Vishal Kulkarni Date: Thu, 14 Feb 2019 18:19:16 +0530 Subject: cxgb4: Add capability to get/set SGE Doorbell Queue Timer Tick This patch gets/sets SGE Doorbell Queue timer ticks via ethtool Original work by: Casey Leedom Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 1 + drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 189 ++++++++++++++++++++- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 14 +- 3 files changed, 198 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 68d0d453eb06..b7b0eb104430 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -819,6 +819,7 @@ struct sge { u16 nqs_per_uld; /* # of Rx queues per ULD */ u16 timer_val[SGE_NTIMERS]; u8 counter_val[SGE_NCOUNTERS]; + u16 dbqtimer_tick; u16 dbqtimer_val[SGE_NDBQTIMERS]; u32 fl_pg_order; /* large page allocation size */ u32 stat_len; /* length of status page at ring end */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 796043544fc3..65b8dc706c1d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -932,11 +932,190 @@ static int get_adaptive_rx_setting(struct net_device *dev) return q->rspq.adaptive_rx; } -static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) +/* Return the current global Adapter SGE Doorbell Queue Timer Tick for all + * Ethernet TX Queues. + */ +static int get_dbqtimer_tick(struct net_device *dev) +{ + struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; + + if (!(adap->flags & SGE_DBQ_TIMER)) + return 0; + + return adap->sge.dbqtimer_tick; +} + +/* Return the SGE Doorbell Queue Timer Value for the Ethernet TX Queues + * associated with a Network Device. + */ +static int get_dbqtimer(struct net_device *dev) +{ + struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; + struct sge_eth_txq *txq; + + txq = &adap->sge.ethtxq[pi->first_qset]; + + if (!(adap->flags & SGE_DBQ_TIMER)) + return 0; + + /* all of the TX Queues use the same Timer Index */ + return adap->sge.dbqtimer_val[txq->dbqtimerix]; +} + +/* Set the global Adapter SGE Doorbell Queue Timer Tick for all Ethernet TX + * Queues. This is the fundamental "Tick" that sets the scale of values which + * can be used. Individual Ethernet TX Queues index into a relatively small + * array of Tick Multipliers. Changing the base Tick will thus change all of + * the resulting Timer Values associated with those multipliers for all + * Ethernet TX Queues. + */ +static int set_dbqtimer_tick(struct net_device *dev, int usecs) +{ + struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; + struct sge *s = &adap->sge; + u32 param, val; + int ret; + + if (!(adap->flags & SGE_DBQ_TIMER)) + return 0; + + /* return early if it's the same Timer Tick we're already using */ + if (s->dbqtimer_tick == usecs) + return 0; + + /* attempt to set the new Timer Tick value */ + param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DBQ_TIMERTICK)); + val = usecs; + ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val); + if (ret) + return ret; + s->dbqtimer_tick = usecs; + + /* if successful, reread resulting dependent Timer values */ + ret = t4_read_sge_dbqtimers(adap, ARRAY_SIZE(s->dbqtimer_val), + s->dbqtimer_val); + return ret; +} + +/* Set the SGE Doorbell Queue Timer Value for the Ethernet TX Queues + * associated with a Network Device. There is a relatively small array of + * possible Timer Values so we need to pick the closest value available. + */ +static int set_dbqtimer(struct net_device *dev, int usecs) +{ + int qix, timerix, min_timerix, delta, min_delta; + struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; + struct sge *s = &adap->sge; + struct sge_eth_txq *txq; + u32 param, val; + int ret; + + if (!(adap->flags & SGE_DBQ_TIMER)) + return 0; + + /* Find the SGE Doorbell Timer Value that's closest to the requested + * value. + */ + min_delta = INT_MAX; + min_timerix = 0; + for (timerix = 0; timerix < ARRAY_SIZE(s->dbqtimer_val); timerix++) { + delta = s->dbqtimer_val[timerix] - usecs; + if (delta < 0) + delta = -delta; + if (delta < min_delta) { + min_delta = delta; + min_timerix = timerix; + } + } + + /* Return early if it's the same Timer Index we're already using. + * We use the same Timer Index for all of the TX Queues for an + * interface so it's only necessary to check the first one. + */ + txq = &s->ethtxq[pi->first_qset]; + if (txq->dbqtimerix == min_timerix) + return 0; + + for (qix = 0; qix < pi->nqsets; qix++, txq++) { + if (adap->flags & FULL_INIT_DONE) { + param = + (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DMAQ_EQ_TIMERIX) | + FW_PARAMS_PARAM_YZ_V(txq->q.cntxt_id)); + val = min_timerix; + ret = t4_set_params(adap, adap->mbox, adap->pf, 0, + 1, ¶m, &val); + if (ret) + return ret; + } + txq->dbqtimerix = min_timerix; + } + return 0; +} + +/* Set the global Adapter SGE Doorbell Queue Timer Tick for all Ethernet TX + * Queues and the Timer Value for the Ethernet TX Queues associated with a + * Network Device. Since changing the global Tick changes all of the + * available Timer Values, we need to do this first before selecting the + * resulting closest Timer Value. Moreover, since the Tick is global, + * changing it affects the Timer Values for all Network Devices on the + * adapter. So, before changing the Tick, we grab all of the current Timer + * Values for other Network Devices on this Adapter and then attempt to select + * new Timer Values which are close to the old values ... + */ +static int set_dbqtimer_tickval(struct net_device *dev, + int tick_usecs, int timer_usecs) +{ + struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; + int timer[MAX_NPORTS]; + unsigned int port; + int ret; + + /* Grab the other adapter Network Interface current timers and fill in + * the new one for this Network Interface. + */ + for_each_port(adap, port) + if (port == pi->port_id) + timer[port] = timer_usecs; + else + timer[port] = get_dbqtimer(adap->port[port]); + + /* Change the global Tick first ... */ + ret = set_dbqtimer_tick(dev, tick_usecs); + if (ret) + return ret; + + /* ... and then set all of the Network Interface Timer Values ... */ + for_each_port(adap, port) { + ret = set_dbqtimer(adap->port[port], timer[port]); + if (ret) + return ret; + } + + return 0; +} + +static int set_coalesce(struct net_device *dev, + struct ethtool_coalesce *coalesce) { - set_adaptive_rx_setting(dev, c->use_adaptive_rx_coalesce); - return set_rx_intr_params(dev, c->rx_coalesce_usecs, - c->rx_max_coalesced_frames); + int ret; + + set_adaptive_rx_setting(dev, coalesce->use_adaptive_rx_coalesce); + + ret = set_rx_intr_params(dev, coalesce->rx_coalesce_usecs, + coalesce->rx_max_coalesced_frames); + if (ret) + return ret; + + return set_dbqtimer_tickval(dev, + coalesce->tx_coalesce_usecs_irq, + coalesce->tx_coalesce_usecs); } static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) @@ -949,6 +1128,8 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) c->rx_max_coalesced_frames = (rq->intr_params & QINTR_CNT_EN_F) ? adap->sge.counter_val[rq->pktcnt_idx] : 0; c->use_adaptive_rx_coalesce = get_adaptive_rx_setting(dev); + c->tx_coalesce_usecs_irq = get_dbqtimer_tick(dev); + c->tx_coalesce_usecs = get_dbqtimer(dev); return 0; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index bdd11a617579..bcbac247a73d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -4331,8 +4331,18 @@ static int adap_init0(struct adapter *adap) /* Grab the SGE Doorbell Queue Timer values. If successful, that * indicates that the Firmware and Hardware support this. */ - ret = t4_read_sge_dbqtimers(adap, ARRAY_SIZE(adap->sge.dbqtimer_val), - adap->sge.dbqtimer_val); + params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DBQ_TIMERTICK)); + ret = t4_query_params(adap, adap->mbox, adap->pf, 0, + 1, params, val); + + if (!ret) { + adap->sge.dbqtimer_tick = val[0]; + ret = t4_read_sge_dbqtimers(adap, + ARRAY_SIZE(adap->sge.dbqtimer_val), + adap->sge.dbqtimer_val); + } + if (!ret) adap->flags |= SGE_DBQ_TIMER; -- cgit v1.2.3 From baff7b09ffa9055d54a366f26b02269ea579b268 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Thu, 14 Feb 2019 22:45:38 +0800 Subject: net: i825xx: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in i596_interrupt() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/i825xx/lib82596.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c index 2f7ae118217f..1274ad24d6af 100644 --- a/drivers/net/ethernet/i825xx/lib82596.c +++ b/drivers/net/ethernet/i825xx/lib82596.c @@ -1194,7 +1194,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) dma_unmap_single(dev->dev.parent, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); tx_cmd->cmd.command = 0; /* Mark free */ break; -- cgit v1.2.3 From d1441d4782f2d3d7b9596df8076a2f213a34dcf5 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Thu, 14 Feb 2019 22:50:58 +0800 Subject: net: xilinx: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/ll_temac_main.c | 2 +- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 2 +- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 15bb058db392..44efffbe7970 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -630,7 +630,7 @@ static void temac_start_xmit_done(struct net_device *ndev) dma_unmap_single(ndev->dev.parent, cur_p->phys, cur_p->len, DMA_TO_DEVICE); if (cur_p->app4) - dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); + dev_consume_skb_irq((struct sk_buff *)cur_p->app4); cur_p->app0 = 0; cur_p->app1 = 0; cur_p->app2 = 0; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 0789d8af7d72..ec7e7ec24ff9 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -595,7 +595,7 @@ static void axienet_start_xmit_done(struct net_device *ndev) (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK), DMA_TO_DEVICE); if (cur_p->app4) - dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); + dev_consume_skb_irq((struct sk_buff *)cur_p->app4); /*cur_p->phys = 0;*/ cur_p->app0 = 0; cur_p->app1 = 0; diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 639e3e99af46..b03a417d0073 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -581,7 +581,7 @@ static void xemaclite_tx_handler(struct net_device *dev) return; dev->stats.tx_bytes += lp->deferred_skb->len; - dev_kfree_skb_irq(lp->deferred_skb); + dev_consume_skb_irq(lp->deferred_skb); lp->deferred_skb = NULL; netif_trans_update(dev); /* prevent tx timeout */ netif_wake_queue(dev); -- cgit v1.2.3 From 1bba6de1a67f10270dd0f0951050d0470514c2a5 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Thu, 14 Feb 2019 22:52:28 +0800 Subject: net: packetengines: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/packetengines/hamachi.c | 2 +- drivers/net/ethernet/packetengines/yellowfin.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/packetengines/hamachi.c b/drivers/net/ethernet/packetengines/hamachi.c index c9529c29a0a7..eee883a2aa8d 100644 --- a/drivers/net/ethernet/packetengines/hamachi.c +++ b/drivers/net/ethernet/packetengines/hamachi.c @@ -1337,7 +1337,7 @@ static irqreturn_t hamachi_interrupt(int irq, void *dev_instance) leXX_to_cpu(hmp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); hmp->tx_skbuff[entry] = NULL; } hmp->tx_ring[entry].status_n_length = 0; diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c index 54224d1822e3..6f8d6584f809 100644 --- a/drivers/net/ethernet/packetengines/yellowfin.c +++ b/drivers/net/ethernet/packetengines/yellowfin.c @@ -925,7 +925,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) /* Free the original skb. */ pci_unmap_single(yp->pci_dev, le32_to_cpu(yp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); yp->tx_skbuff[entry] = NULL; } if (yp->tx_full && @@ -983,7 +983,7 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) pci_unmap_single(yp->pci_dev, yp->tx_ring[entry<<1].addr, skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); yp->tx_skbuff[entry] = 0; /* Mark status as empty. */ yp->tx_status[entry].tx_errs = 0; -- cgit v1.2.3 From 67633e78646c7be5e2e4bd1255da22dd4381c1e1 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Thu, 14 Feb 2019 22:53:30 +0800 Subject: net: arc_emac: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in arc_emac_tx_clean() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/arc/emac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index 4406325fdd9f..ff3d68532f5f 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -148,7 +148,7 @@ static void arc_emac_tx_clean(struct net_device *ndev) dma_unmap_len(tx_buff, len), DMA_TO_DEVICE); /* return the sk_buff to system */ - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); txbd->data = 0; txbd->info = 0; -- cgit v1.2.3 From 467d2fceafb6c1dc3cf444c86266a6c0334b1f3b Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Thu, 14 Feb 2019 22:55:14 +0800 Subject: net: 3com: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/3com/3c515.c | 4 ++-- drivers/net/ethernet/3com/3c59x.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c index b648e3f95c01..808abb6b3671 100644 --- a/drivers/net/ethernet/3com/3c515.c +++ b/drivers/net/ethernet/3com/3c515.c @@ -1177,7 +1177,7 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id) if (inl(ioaddr + DownListPtr) == isa_virt_to_bus(&lp->tx_ring[entry])) break; /* It still hasn't been processed. */ if (lp->tx_skbuff[entry]) { - dev_kfree_skb_irq(lp->tx_skbuff[entry]); + dev_consume_skb_irq(lp->tx_skbuff[entry]); lp->tx_skbuff[entry] = NULL; } dirty_tx++; @@ -1192,7 +1192,7 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id) #ifdef VORTEX_BUS_MASTER if (status & DMADone) { outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ - dev_kfree_skb_irq(lp->tx_skb); /* Release the transferred buffer */ + dev_consume_skb_irq(lp->tx_skb); /* Release the transferred buffer */ netif_wake_queue(dev); } #endif diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 40f421dbdf57..147051404194 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -2307,7 +2307,7 @@ _vortex_interrupt(int irq, struct net_device *dev) dma_unmap_single(vp->gendev, vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, DMA_TO_DEVICE); pkts_compl++; bytes_compl += vp->tx_skb->len; - dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */ + dev_consume_skb_irq(vp->tx_skb); /* Release the transferred buffer */ if (ioread16(ioaddr + TxFree) > 1536) { /* * AKPM: FIXME: I don't think we need this. If the queue was stopped due to @@ -2449,7 +2449,7 @@ _boomerang_interrupt(int irq, struct net_device *dev) #endif pkts_compl++; bytes_compl += skb->len; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); vp->tx_skbuff[entry] = NULL; } else { pr_debug("boomerang_interrupt: no skb!\n"); -- cgit v1.2.3 From e772261b53bc45f53693ae4514658cd376da9e56 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Thu, 14 Feb 2019 23:06:40 +0800 Subject: net: adaptec: starfire: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in intr_handler() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/ethernet/adaptec/starfire.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index 097467f44b0d..816540e6beac 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c @@ -1390,7 +1390,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) } } - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); } np->tx_done_q[np->tx_done].status = 0; np->tx_done = (np->tx_done + 1) % DONE_Q_SIZE; -- cgit v1.2.3 From 50f444aa50a4f3fab35a04f56d6bb83dc1e8c875 Mon Sep 17 00:00:00 2001 From: Robert Stonehouse Date: Thu, 14 Feb 2019 17:27:43 +0000 Subject: sfc: ensure recovery after allocation failures After failing to allocate a receive buffer the driver may fail to ever request additional allocations. EF10 NICs require new receive buffers to be pushed in batches of eight or more. The test for whether a slow fill should be scheduled failed to take account of this. There is little downside to *always* requesting a slow fill if we failed to allocate a buffer, so the condition has been removed completely. The timer that triggers the request for a refill has also been shortened. Signed-off-by: Robert Stonehouse Signed-off-by: Bert Kenward Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx.c | 2 +- drivers/net/ethernet/sfc/rx.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 3643015a55cf..bc655ffc9e02 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -915,7 +915,7 @@ rollback: void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue) { - mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100)); + mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(10)); } static bool efx_default_channel_want_txqs(struct efx_channel *channel) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 396ff01298cd..8702ab44d80b 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -360,8 +360,7 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, bool atomic) rc = efx_init_rx_buffers(rx_queue, atomic); if (unlikely(rc)) { /* Ensure that we don't leave the rx queue empty */ - if (rx_queue->added_count == rx_queue->removed_count) - efx_schedule_slow_fill(rx_queue); + efx_schedule_slow_fill(rx_queue); goto out; } } while ((space -= batch_size) >= batch_size); -- cgit v1.2.3 From 7e4c4330a3bc7f34f82b5bc370821e1e16d425fb Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:33 -0800 Subject: net/mlx5: Use consistent vport num argument type Use u16 for vport number, which matches how hardware refers to this argument throughout commands. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Signed-off-by: Eli Cohen Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 32 +++++++++++------------ drivers/net/ethernet/mellanox/mlx5/core/vport.c | 8 +++--- include/linux/mlx5/vport.h | 8 +++--- 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index a44ea7b85614..d7382892e81c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -52,7 +52,7 @@ enum { struct vport_addr { struct l2addr_node node; u8 action; - u32 vport; + u16 vport; struct mlx5_flow_handle *flow_rule; bool mpfs; /* UC MAC was added to MPFs */ /* A flag indicating that mac was added due to mc promiscuous vport */ @@ -115,7 +115,7 @@ static int modify_esw_vport_context_cmd(struct mlx5_core_dev *dev, u16 vport, return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); } -static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u32 vport, +static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport, u16 vlan, u8 qos, u8 set_flags) { u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {0}; @@ -152,7 +152,7 @@ static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u32 vport, /* E-Switch FDB */ static struct mlx5_flow_handle * -__esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule, +__esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule, u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN]) { int match_header = (is_zero_ether_addr(mac_c) ? 0 : @@ -215,7 +215,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule, } static struct mlx5_flow_handle * -esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport) +esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u16 vport) { u8 mac_c[ETH_ALEN]; @@ -224,7 +224,7 @@ esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport) } static struct mlx5_flow_handle * -esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport) +esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u16 vport) { u8 mac_c[ETH_ALEN]; u8 mac_v[ETH_ALEN]; @@ -237,7 +237,7 @@ esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport) } static struct mlx5_flow_handle * -esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u32 vport) +esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport) { u8 mac_c[ETH_ALEN]; u8 mac_v[ETH_ALEN]; @@ -377,7 +377,7 @@ typedef int (*vport_addr_action)(struct mlx5_eswitch *esw, static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) { u8 *mac = vaddr->node.addr; - u32 vport = vaddr->vport; + u16 vport = vaddr->vport; int err; /* Skip mlx5_mpfs_add_mac for PFs, @@ -409,7 +409,7 @@ fdb_add: static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) { u8 *mac = vaddr->node.addr; - u32 vport = vaddr->vport; + u16 vport = vaddr->vport; int err = 0; /* Skip mlx5_mpfs_del_mac for PFs, @@ -438,7 +438,7 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw, struct esw_mc_addr *esw_mc) { u8 *mac = vaddr->node.addr; - u32 vport_idx = 0; + u16 vport_idx = 0; for (vport_idx = 0; vport_idx < esw->total_vports; vport_idx++) { struct mlx5_vport *vport = &esw->vports[vport_idx]; @@ -485,7 +485,7 @@ static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) struct hlist_head *hash = esw->mc_table; struct esw_mc_addr *esw_mc; u8 *mac = vaddr->node.addr; - u32 vport = vaddr->vport; + u16 vport = vaddr->vport; if (!esw->fdb_table.legacy.fdb) return 0; @@ -525,7 +525,7 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) struct hlist_head *hash = esw->mc_table; struct esw_mc_addr *esw_mc; u8 *mac = vaddr->node.addr; - u32 vport = vaddr->vport; + u16 vport = vaddr->vport; if (!esw->fdb_table.legacy.fdb) return 0; @@ -564,7 +564,7 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) /* Apply vport UC/MC list to HW l2 table and FDB table */ static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw, - u32 vport_num, int list_type) + u16 vport_num, int list_type) { struct mlx5_vport *vport = &esw->vports[vport_num]; bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC; @@ -599,7 +599,7 @@ static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw, /* Sync vport UC/MC list from vport context */ static void esw_update_vport_addr_list(struct mlx5_eswitch *esw, - u32 vport_num, int list_type) + u16 vport_num, int list_type) { struct mlx5_vport *vport = &esw->vports[vport_num]; bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC; @@ -686,7 +686,7 @@ out: /* Sync vport UC/MC list from vport context * Must be called after esw_update_vport_addr_list */ -static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u32 vport_num) +static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_vport *vport = &esw->vports[vport_num]; struct l2addr_node *node; @@ -721,7 +721,7 @@ static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u32 vport_num) } /* Apply vport rx mode to HW FDB table */ -static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num, +static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u16 vport_num, bool promisc, bool mc_promisc) { struct esw_mc_addr *allmulti_addr = &esw->mc_promisc; @@ -764,7 +764,7 @@ promisc: } /* Sync vport rx mode from vport context */ -static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, u32 vport_num) +static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_vport *vport = &esw->vports[vport_num]; int promisc_all = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index 9b150ce9d315..9a928eb48522 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -255,7 +255,7 @@ int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu) EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu); int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev, - u32 vport, + u16 vport, enum mlx5_list_type list_type, u8 addr_list[][ETH_ALEN], int *list_size) @@ -373,7 +373,7 @@ int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev, EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mac_list); int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev, - u32 vport, + u16 vport, u16 vlans[], int *size) { @@ -526,7 +526,7 @@ int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid); int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, - u32 vport, u64 node_guid) + u16 vport, u64 node_guid) { int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); void *nic_vport_context; @@ -827,7 +827,7 @@ int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev, EXPORT_SYMBOL_GPL(mlx5_query_hca_vport_node_guid); int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev, - u32 vport, + u16 vport, int *promisc_uc, int *promisc_mc, int *promisc_all) diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index 9c694808c212..1654b911cdb2 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -60,7 +60,7 @@ int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev, u64 *system_image_guid); int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid); int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev, - u32 vport, u64 node_guid); + u16 vport, u64 node_guid); int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev, u16 *qkey_viol_cntr); int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport, @@ -78,7 +78,7 @@ int mlx5_query_hca_vport_system_image_guid(struct mlx5_core_dev *dev, int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev, u64 *node_guid); int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev, - u32 vport, + u16 vport, enum mlx5_list_type list_type, u8 addr_list[][ETH_ALEN], int *list_size); @@ -87,7 +87,7 @@ int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev, u8 addr_list[][ETH_ALEN], int list_size); int mlx5_query_nic_vport_promisc(struct mlx5_core_dev *mdev, - u32 vport, + u16 vport, int *promisc_uc, int *promisc_mc, int *promisc_all); @@ -96,7 +96,7 @@ int mlx5_modify_nic_vport_promisc(struct mlx5_core_dev *mdev, int promisc_mc, int promisc_all); int mlx5_query_nic_vport_vlans(struct mlx5_core_dev *dev, - u32 vport, + u16 vport, u16 vlans[], int *size); int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev, -- cgit v1.2.3 From f0666f1f22b5748e7caf87481a0869689f9f513d Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:34 -0800 Subject: IB/mlx5: Use unified register/load function for uplink and VF vports IB driver maintains different registration and load function calls for uplink and VF vports. This is not necessary as they only differ with each other on their profiles. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Reviewed-by: Mark Bloch Signed-off-by: Saeed Mahameed --- drivers/infiniband/hw/mlx5/ib_rep.c | 73 +++++++++---------------------------- drivers/infiniband/hw/mlx5/ib_rep.h | 10 +++-- drivers/infiniband/hw/mlx5/main.c | 26 ++++++------- 3 files changed, 37 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c index 46a9ddc8ca56..3fb22967c098 100644 --- a/drivers/infiniband/hw/mlx5/ib_rep.c +++ b/drivers/infiniband/hw/mlx5/ib_rep.c @@ -6,7 +6,7 @@ #include "ib_rep.h" #include "srq.h" -static const struct mlx5_ib_profile rep_profile = { +static const struct mlx5_ib_profile vf_rep_profile = { STAGE_CREATE(MLX5_IB_STAGE_INIT, mlx5_ib_stage_init_init, mlx5_ib_stage_init_cleanup), @@ -45,31 +45,18 @@ static const struct mlx5_ib_profile rep_profile = { NULL), }; -static int -mlx5_ib_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) -{ - struct mlx5_ib_dev *ibdev; - - ibdev = mlx5_ib_rep_to_dev(rep); - if (!__mlx5_ib_add(ibdev, ibdev->profile)) - return -EINVAL; - return 0; -} - -static void -mlx5_ib_nic_rep_unload(struct mlx5_eswitch_rep *rep) -{ - struct mlx5_ib_dev *ibdev; - - ibdev = mlx5_ib_rep_to_dev(rep); - __mlx5_ib_remove(ibdev, ibdev->profile, MLX5_IB_STAGE_MAX); -} - static int mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) { +#define FDB_UPLINK_VPORT 0xffff + const struct mlx5_ib_profile *profile; struct mlx5_ib_dev *ibdev; + if (rep->vport == FDB_UPLINK_VPORT) + profile = &uplink_rep_profile; + else + profile = &vf_rep_profile; + ibdev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*ibdev)); if (!ibdev) return -ENOMEM; @@ -78,7 +65,7 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) ibdev->mdev = dev; ibdev->num_ports = max(MLX5_CAP_GEN(dev, num_ports), MLX5_CAP_GEN(dev, num_vhca_ports)); - if (!__mlx5_ib_add(ibdev, &rep_profile)) + if (!__mlx5_ib_add(ibdev, profile)) return -EINVAL; rep->rep_if[REP_IB].priv = ibdev; @@ -105,15 +92,14 @@ static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep) return mlx5_ib_rep_to_dev(rep); } -static void mlx5_ib_rep_register_vf_vports(struct mlx5_ib_dev *dev) +void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev) { - struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; - int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev); + struct mlx5_eswitch *esw = mdev->priv.eswitch; + int total_vports = MLX5_TOTAL_VPORTS(mdev); + struct mlx5_eswitch_rep_if rep_if = {}; int vport; - for (vport = 1; vport < total_vfs; vport++) { - struct mlx5_eswitch_rep_if rep_if = {}; - + for (vport = 0; vport < total_vports; vport++) { rep_if.load = mlx5_ib_vport_rep_load; rep_if.unload = mlx5_ib_vport_rep_unload; rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev; @@ -121,39 +107,16 @@ static void mlx5_ib_rep_register_vf_vports(struct mlx5_ib_dev *dev) } } -static void mlx5_ib_rep_unregister_vf_vports(struct mlx5_ib_dev *dev) +void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev) { - struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; - int total_vfs = MLX5_TOTAL_VPORTS(dev->mdev); + struct mlx5_eswitch *esw = mdev->priv.eswitch; + int total_vports = MLX5_TOTAL_VPORTS(mdev); int vport; - for (vport = 1; vport < total_vfs; vport++) + for (vport = total_vports - 1; vport >= 0; vport--) mlx5_eswitch_unregister_vport_rep(esw, vport, REP_IB); } -void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev) -{ - struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; - struct mlx5_eswitch_rep_if rep_if = {}; - - rep_if.load = mlx5_ib_nic_rep_load; - rep_if.unload = mlx5_ib_nic_rep_unload; - rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev; - rep_if.priv = dev; - - mlx5_eswitch_register_vport_rep(esw, 0, &rep_if, REP_IB); - - mlx5_ib_rep_register_vf_vports(dev); -} - -void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev) -{ - struct mlx5_eswitch *esw = dev->mdev->priv.eswitch; - - mlx5_ib_rep_unregister_vf_vports(dev); /* VFs vports */ - mlx5_eswitch_unregister_vport_rep(esw, 0, REP_IB); /* UPLINK PF*/ -} - u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw) { return mlx5_eswitch_mode(esw); diff --git a/drivers/infiniband/hw/mlx5/ib_rep.h b/drivers/infiniband/hw/mlx5/ib_rep.h index 2ba73636a2fb..798d41e61fb4 100644 --- a/drivers/infiniband/hw/mlx5/ib_rep.h +++ b/drivers/infiniband/hw/mlx5/ib_rep.h @@ -10,14 +10,16 @@ #include "mlx5_ib.h" #ifdef CONFIG_MLX5_ESWITCH +extern const struct mlx5_ib_profile uplink_rep_profile; + u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw); struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw, int vport_index); struct mlx5_ib_dev *mlx5_ib_get_uplink_ibdev(struct mlx5_eswitch *esw); struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw, int vport_index); -void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev); -void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev); +void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev); +void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev); int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev, struct mlx5_ib_sq *sq); struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw, @@ -48,8 +50,8 @@ struct mlx5_eswitch_rep *mlx5_ib_vport_rep(struct mlx5_eswitch *esw, return NULL; } -static inline void mlx5_ib_register_vport_reps(struct mlx5_ib_dev *dev) {} -static inline void mlx5_ib_unregister_vport_reps(struct mlx5_ib_dev *dev) {} +static inline void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev) {} +static inline void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev) {} static inline int create_flow_rule_vport_sq(struct mlx5_ib_dev *dev, struct mlx5_ib_sq *sq) { diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 94fe253d4956..87ce62e44898 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -6386,7 +6386,7 @@ static const struct mlx5_ib_profile pf_profile = { mlx5_ib_stage_delay_drop_cleanup), }; -static const struct mlx5_ib_profile nic_rep_profile = { +const struct mlx5_ib_profile uplink_rep_profile = { STAGE_CREATE(MLX5_IB_STAGE_INIT, mlx5_ib_stage_init_init, mlx5_ib_stage_init_cleanup), @@ -6479,6 +6479,12 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) printk_once(KERN_INFO "%s", mlx5_version); + if (MLX5_ESWITCH_MANAGER(mdev) && + mlx5_ib_eswitch_mode(mdev->priv.eswitch) == SRIOV_OFFLOADS) { + mlx5_ib_register_vport_reps(mdev); + return mdev; + } + port_type_cap = MLX5_CAP_GEN(mdev, port_type); ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap); @@ -6493,14 +6499,6 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) dev->num_ports = max(MLX5_CAP_GEN(mdev, num_ports), MLX5_CAP_GEN(mdev, num_vhca_ports)); - if (MLX5_ESWITCH_MANAGER(mdev) && - mlx5_ib_eswitch_mode(mdev->priv.eswitch) == SRIOV_OFFLOADS) { - dev->rep = mlx5_ib_vport_rep(mdev->priv.eswitch, 0); - dev->profile = &nic_rep_profile; - mlx5_ib_register_vport_reps(dev); - return dev; - } - return __mlx5_ib_add(dev, &pf_profile); } @@ -6509,6 +6507,11 @@ static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context) struct mlx5_ib_multiport_info *mpi; struct mlx5_ib_dev *dev; + if (MLX5_ESWITCH_MANAGER(mdev) && context == mdev) { + mlx5_ib_unregister_vport_reps(mdev); + return; + } + if (mlx5_core_is_mp_slave(mdev)) { mpi = context; mutex_lock(&mlx5_ib_multiport_mutex); @@ -6520,10 +6523,7 @@ static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context) } dev = context; - if (dev->profile == &nic_rep_profile) - mlx5_ib_unregister_vport_reps(dev); - else - __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX); + __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX); ib_dealloc_device((struct ib_device *)dev); } -- cgit v1.2.3 From 591905ba96796e3b677b14fa79f27127bfaab4ab Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:35 -0800 Subject: net/mlx5: Introduce Mellanox SmartNIC and modify page management logic Mellanox's SmartNIC combines embedded CPU(e.g, ARM) processing power with advanced network offloads to accelerate a multitude of security, networking and storage applications. With the introduction of the SmartNIC, there is a new PCI function called Embedded CPU Physical Function(ECPF). And it's possible for a PF to get its ICM pages from the ECPF PCI function. Driver shall identify if it is running on such a function by reading a bit in the initialization segment. When firmware asks for pages, it would issue a page request event specifying how many pages it requests and for which function. That driver responds with a manage_pages command providing the requested pages along with an indication for which function it is providing these pages. The encoding before this patch was as follows: function_id == 0: pages are requested for the function receiving the EQE. function_id != 0: pages are requested for VF identified by the function_id value A new one bit field in the EQE identifies that pages are requested for the ECPF. The notion of page_supplier can be introduced here and to support that, manage pages and query pages were modified so firmware can distinguish the following cases: 1. Function provides pages for itself 2. PF provides pages for its VF 3. ECPF provides pages to itself 4. ECPF provides pages for another function This distinction is possible through the introduction of the bit "embedded_cpu_function" in query_pages, manage_pages and page request EQE. Signed-off-by: Bodong Wang Signed-off-by: Eli Cohen Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/ecpf.c | 9 ++++ drivers/net/ethernet/mellanox/mlx5/core/ecpf.h | 25 ++++++++++ drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 + .../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 2 +- .../net/ethernet/mellanox/mlx5/core/pagealloc.c | 54 +++++++++++++++------- drivers/net/ethernet/mellanox/mlx5/core/sriov.c | 2 +- include/linux/mlx5/device.h | 2 +- include/linux/mlx5/driver.h | 9 +++- include/linux/mlx5/mlx5_ifc.h | 12 +++-- 10 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/ecpf.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/ecpf.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 0257731e6d42..07965350b903 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -35,7 +35,7 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o # # Core extra # -mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o +mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o ecpf.o mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c new file mode 100644 index 000000000000..28b8c5c5c8c7 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#include "ecpf.h" + +bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev) +{ + return (ioread32be(&dev->iseg->initializing) >> MLX5_ECPU_BIT_NUM) & 1; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h new file mode 100644 index 000000000000..8b684f0ab48f --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef __MLX5_ECPF_H__ +#define __MLX5_ECPF_H__ + +#include +#include "mlx5_core.h" + +#ifdef CONFIG_MLX5_ESWITCH + +enum { + MLX5_ECPU_BIT_NUM = 23, +}; + +bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev); + +#else /* CONFIG_MLX5_ESWITCH */ + +static inline bool +mlx5_read_embedded_cpu(struct mlx5_core_dev *dev) { return false; } + +#endif /* CONFIG_MLX5_ESWITCH */ + +#endif /* __MLX5_ECPF_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 6d45518edbdc..08a3da2a8358 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -65,6 +65,7 @@ #include "lib/vxlan.h" #include "lib/devcom.h" #include "diag/fw_tracer.h" +#include "ecpf.h" MODULE_AUTHOR("Eli Cohen "); MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver"); @@ -898,6 +899,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, struct pci_dev *pdev = dev->pdev; int err; + dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev); mutex_lock(&dev->intf_state_mutex); if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n", diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index c68dcea5985b..b127044293b1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -121,7 +121,7 @@ int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, u32 modify_bitmask); int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, u32 element_id); -int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev); +int mlx5_wait_for_pages(struct mlx5_core_dev *dev, int *pages); u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev, struct ptp_system_timestamp *sts); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index a83b517b0714..41025387ff2c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -48,6 +48,7 @@ enum { struct mlx5_pages_req { struct mlx5_core_dev *dev; u16 func_id; + u8 ec_function; s32 npages; struct work_struct work; }; @@ -143,6 +144,7 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id, MLX5_SET(query_pages_in, in, op_mod, boot ? MLX5_QUERY_PAGES_IN_OP_MOD_BOOT_PAGES : MLX5_QUERY_PAGES_IN_OP_MOD_INIT_PAGES); + MLX5_SET(query_pages_in, in, embedded_cpu_function, mlx5_core_is_ecpf(dev)); err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); if (err) @@ -253,7 +255,8 @@ err_mapping: return err; } -static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id) +static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id, + bool ec_function) { u32 out[MLX5_ST_SZ_DW(manage_pages_out)] = {0}; u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {0}; @@ -262,6 +265,7 @@ static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id) MLX5_SET(manage_pages_in, in, opcode, MLX5_CMD_OP_MANAGE_PAGES); MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_CANT_GIVE); MLX5_SET(manage_pages_in, in, function_id, func_id); + MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function); err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); if (err) @@ -270,7 +274,7 @@ static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id) } static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, - int notify_fail) + int notify_fail, bool ec_function) { u32 out[MLX5_ST_SZ_DW(manage_pages_out)] = {0}; int inlen = MLX5_ST_SZ_BYTES(manage_pages_in); @@ -305,6 +309,7 @@ retry: MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_GIVE); MLX5_SET(manage_pages_in, in, function_id, func_id); MLX5_SET(manage_pages_in, in, input_num_entries, npages); + MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function); err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); if (err) { @@ -316,8 +321,11 @@ retry: dev->priv.fw_pages += npages; if (func_id) dev->priv.vfs_pages += npages; + else if (mlx5_core_is_ecpf(dev) && !ec_function) + dev->priv.peer_pf_pages += npages; - mlx5_core_dbg(dev, "err %d\n", err); + mlx5_core_dbg(dev, "npages %d, ec_function %d, func_id 0x%x, err %d\n", + npages, ec_function, func_id, err); kvfree(in); return 0; @@ -328,7 +336,7 @@ out_4k: out_free: kvfree(in); if (notify_fail) - page_notify_fail(dev, func_id); + page_notify_fail(dev, func_id, ec_function); return err; } @@ -364,7 +372,7 @@ static int reclaim_pages_cmd(struct mlx5_core_dev *dev, } static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages, - int *nclaimed) + int *nclaimed, bool ec_function) { int outlen = MLX5_ST_SZ_BYTES(manage_pages_out); u32 in[MLX5_ST_SZ_DW(manage_pages_in)] = {0}; @@ -385,6 +393,7 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages, MLX5_SET(manage_pages_in, in, op_mod, MLX5_PAGES_TAKE); MLX5_SET(manage_pages_in, in, function_id, func_id); MLX5_SET(manage_pages_in, in, input_num_entries, npages); + MLX5_SET(manage_pages_in, in, embedded_cpu_function, ec_function); mlx5_core_dbg(dev, "npages %d, outlen %d\n", npages, outlen); err = reclaim_pages_cmd(dev, in, sizeof(in), out, outlen); @@ -410,6 +419,8 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u32 func_id, int npages, dev->priv.fw_pages -= num_claimed; if (func_id) dev->priv.vfs_pages -= num_claimed; + else if (mlx5_core_is_ecpf(dev) && !ec_function) + dev->priv.peer_pf_pages -= num_claimed; out_free: kvfree(out); @@ -423,9 +434,10 @@ static void pages_work_handler(struct work_struct *work) int err = 0; if (req->npages < 0) - err = reclaim_pages(dev, req->func_id, -1 * req->npages, NULL); + err = reclaim_pages(dev, req->func_id, -1 * req->npages, NULL, + req->ec_function); else if (req->npages > 0) - err = give_pages(dev, req->func_id, req->npages, 1); + err = give_pages(dev, req->func_id, req->npages, 1, req->ec_function); if (err) mlx5_core_warn(dev, "%s fail %d\n", @@ -434,6 +446,10 @@ static void pages_work_handler(struct work_struct *work) kfree(req); } +enum { + EC_FUNCTION_MASK = 0x8000, +}; + static int req_pages_handler(struct notifier_block *nb, unsigned long type, void *data) { @@ -441,6 +457,7 @@ static int req_pages_handler(struct notifier_block *nb, struct mlx5_core_dev *dev; struct mlx5_priv *priv; struct mlx5_eqe *eqe; + bool ec_function; u16 func_id; s32 npages; @@ -450,6 +467,7 @@ static int req_pages_handler(struct notifier_block *nb, func_id = be16_to_cpu(eqe->data.req_pages.func_id); npages = be32_to_cpu(eqe->data.req_pages.num_pages); + ec_function = be16_to_cpu(eqe->data.req_pages.ec_function) & EC_FUNCTION_MASK; mlx5_core_dbg(dev, "page request for func 0x%x, npages %d\n", func_id, npages); req = kzalloc(sizeof(*req), GFP_ATOMIC); @@ -461,6 +479,7 @@ static int req_pages_handler(struct notifier_block *nb, req->dev = dev; req->func_id = func_id; req->npages = npages; + req->ec_function = ec_function; INIT_WORK(&req->work, pages_work_handler); queue_work(dev->priv.pg_wq, &req->work); return NOTIFY_OK; @@ -479,7 +498,7 @@ int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot) mlx5_core_dbg(dev, "requested %d %s pages for func_id 0x%x\n", npages, boot ? "boot" : "init", func_id); - return give_pages(dev, func_id, npages, 0); + return give_pages(dev, func_id, npages, 0, mlx5_core_is_ecpf(dev)); } enum { @@ -513,7 +532,7 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev) fwp = rb_entry(p, struct fw_page, rb_node); err = reclaim_pages(dev, fwp->func_id, optimal_reclaimed_pages(), - &nclaimed); + &nclaimed, mlx5_core_is_ecpf(dev)); if (err) { mlx5_core_warn(dev, "failed reclaiming pages (%d)\n", @@ -535,6 +554,9 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev) WARN(dev->priv.vfs_pages, "VFs FW pages counter is %d after reclaiming all pages\n", dev->priv.vfs_pages); + WARN(dev->priv.peer_pf_pages, + "Peer PF FW pages counter is %d after reclaiming all pages\n", + dev->priv.peer_pf_pages); return 0; } @@ -567,10 +589,10 @@ void mlx5_pagealloc_stop(struct mlx5_core_dev *dev) flush_workqueue(dev->priv.pg_wq); } -int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev) +int mlx5_wait_for_pages(struct mlx5_core_dev *dev, int *pages) { unsigned long end = jiffies + msecs_to_jiffies(MAX_RECLAIM_VFS_PAGES_TIME_MSECS); - int prev_vfs_pages = dev->priv.vfs_pages; + int prev_pages = *pages; /* In case of internal error we will free the pages manually later */ if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { @@ -578,16 +600,16 @@ int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev) return 0; } - mlx5_core_dbg(dev, "Waiting for %d pages from %s\n", prev_vfs_pages, + mlx5_core_dbg(dev, "Waiting for %d pages from %s\n", prev_pages, dev->priv.name); - while (dev->priv.vfs_pages) { + while (*pages) { if (time_after(jiffies, end)) { - mlx5_core_warn(dev, "aborting while there are %d pending pages\n", dev->priv.vfs_pages); + mlx5_core_warn(dev, "aborting while there are %d pending pages\n", *pages); return -ETIMEDOUT; } - if (dev->priv.vfs_pages < prev_vfs_pages) { + if (*pages < prev_pages) { end = jiffies + msecs_to_jiffies(MAX_RECLAIM_VFS_PAGES_TIME_MSECS); - prev_vfs_pages = dev->priv.vfs_pages; + prev_pages = *pages; } msleep(50); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c index 6e178030d8fb..7b23fa8d2d60 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c @@ -147,7 +147,7 @@ out: if (MLX5_ESWITCH_MANAGER(dev)) mlx5_eswitch_disable_sriov(dev->priv.eswitch); - if (mlx5_wait_for_vf_pages(dev)) + if (mlx5_wait_for_pages(dev, &dev->priv.vfs_pages)) mlx5_core_warn(dev, "timeout reclaiming VFs pages\n"); } diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 46223efa1877..f2070350f60a 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -591,7 +591,7 @@ struct mlx5_eqe_cmd { }; struct mlx5_eqe_page_req { - u8 rsvd0[2]; + __be16 ec_function; __be16 func_id; __be32 num_pages; __be32 rsvd1[5]; diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 039c9398614c..cce4e8293384 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -522,6 +522,7 @@ struct mlx5_priv { atomic_t reg_pages; struct list_head free_list; int vfs_pages; + int peer_pf_pages; struct mlx5_core_health health; @@ -652,6 +653,7 @@ struct mlx5_core_dev { u32 mcam[MLX5_ST_SZ_DW(mcam_reg)]; u32 fpga[MLX5_ST_SZ_DW(fpga_cap)]; u32 qcam[MLX5_ST_SZ_DW(qcam_reg)]; + u8 embedded_cpu; } caps; u64 sys_image_guid; phys_addr_t iseg_base; @@ -922,7 +924,7 @@ void mlx5_pagealloc_cleanup(struct mlx5_core_dev *dev); void mlx5_pagealloc_start(struct mlx5_core_dev *dev); void mlx5_pagealloc_stop(struct mlx5_core_dev *dev); void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, - s32 npages); + s32 npages, bool ec_function); int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot); int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev); void mlx5_register_debugfs(void); @@ -1076,6 +1078,11 @@ static inline int mlx5_core_is_pf(struct mlx5_core_dev *dev) return !(dev->priv.pci_dev_data & MLX5_PCI_DEV_IS_VF); } +static inline bool mlx5_core_is_ecpf(struct mlx5_core_dev *dev) +{ + return dev->caps.embedded_cpu; +} + #define MLX5_TOTAL_VPORTS(mdev) (1 + pci_sriov_get_totalvfs((mdev)->pdev)) #define MLX5_VPORT_MANAGER(mdev) \ (MLX5_CAP_GEN(mdev, vport_group_manager) && \ diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index c5c679390fbd..46799b4c8859 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -4441,7 +4441,8 @@ struct mlx5_ifc_query_pages_out_bits { u8 syndrome[0x20]; - u8 reserved_at_40[0x10]; + u8 embedded_cpu_function[0x1]; + u8 reserved_at_41[0xf]; u8 function_id[0x10]; u8 num_pages[0x20]; @@ -4460,7 +4461,8 @@ struct mlx5_ifc_query_pages_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x10]; + u8 embedded_cpu_function[0x1]; + u8 reserved_at_41[0xf]; u8 function_id[0x10]; u8 reserved_at_60[0x20]; @@ -5880,7 +5882,8 @@ struct mlx5_ifc_manage_pages_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x10]; + u8 embedded_cpu_function[0x1]; + u8 reserved_at_41[0xf]; u8 function_id[0x10]; u8 input_num_entries[0x20]; @@ -8749,7 +8752,8 @@ struct mlx5_ifc_initial_seg_bits { u8 initializing[0x1]; u8 reserved_at_fe1[0x4]; u8 nic_interface_supported[0x3]; - u8 reserved_at_fe8[0x18]; + u8 embedded_cpu[0x1]; + u8 reserved_at_fe9[0x17]; struct mlx5_ifc_health_buffer_bits health_buffer; -- cgit v1.2.3 From 22e939a91dcb9bd4b773f2a0c0cb4eb016679b49 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:36 -0800 Subject: net/mlx5: Update enable HCA dependency With the introduction of ECPF, we require that the ECPF driver will aways call enable/disable HCA for that PF in the same way a PF does this for its VFs. The PF is still responsible for calling enable and disable HCA for its VFs. To distinguish between the ECPF executing enable/disable HCA for itself or for the PF, it sets the embedded CPU function bit in the input params struct of these commands. When the bit is cleared and function ID is zero, it refers to the peer PF. Signed-off-by: Bodong Wang Signed-off-by: Eli Cohen Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/ecpf.c | 76 ++++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/ecpf.h | 4 ++ drivers/net/ethernet/mellanox/mlx5/core/main.c | 14 +++++ include/linux/mlx5/mlx5_ifc.h | 6 +- 4 files changed, 98 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c index 28b8c5c5c8c7..1bcf8b8f9713 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c @@ -7,3 +7,79 @@ bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev) { return (ioread32be(&dev->iseg->initializing) >> MLX5_ECPU_BIT_NUM) & 1; } + +static int mlx5_peer_pf_enable_hca(struct mlx5_core_dev *dev) +{ + u32 out[MLX5_ST_SZ_DW(enable_hca_out)] = {}; + u32 in[MLX5_ST_SZ_DW(enable_hca_in)] = {}; + + MLX5_SET(enable_hca_in, in, opcode, MLX5_CMD_OP_ENABLE_HCA); + MLX5_SET(enable_hca_in, in, function_id, 0); + MLX5_SET(enable_hca_in, in, embedded_cpu_function, 0); + return mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); +} + +static int mlx5_peer_pf_disable_hca(struct mlx5_core_dev *dev) +{ + u32 out[MLX5_ST_SZ_DW(disable_hca_out)] = {}; + u32 in[MLX5_ST_SZ_DW(disable_hca_in)] = {}; + + MLX5_SET(disable_hca_in, in, opcode, MLX5_CMD_OP_DISABLE_HCA); + MLX5_SET(disable_hca_in, in, function_id, 0); + MLX5_SET(enable_hca_in, in, embedded_cpu_function, 0); + return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); +} + +static int mlx5_peer_pf_init(struct mlx5_core_dev *dev) +{ + int err; + + err = mlx5_peer_pf_enable_hca(dev); + if (err) + mlx5_core_err(dev, "Failed to enable peer PF HCA err(%d)\n", + err); + + return err; +} + +static void mlx5_peer_pf_cleanup(struct mlx5_core_dev *dev) +{ + int err; + + err = mlx5_peer_pf_disable_hca(dev); + if (err) { + mlx5_core_err(dev, "Failed to disable peer PF HCA err(%d)\n", + err); + return; + } + + err = mlx5_wait_for_pages(dev, &dev->priv.peer_pf_pages); + if (err) + mlx5_core_warn(dev, "Timeout reclaiming peer PF pages err(%d)\n", + err); +} + +int mlx5_ec_init(struct mlx5_core_dev *dev) +{ + int err = 0; + + if (!mlx5_core_is_ecpf(dev)) + return 0; + + /* ECPF shall enable HCA for peer PF in the same way a PF + * does this for its VFs. + */ + err = mlx5_peer_pf_init(dev); + if (err) + return err; + + return 0; +} + +void mlx5_ec_cleanup(struct mlx5_core_dev *dev) +{ + if (!mlx5_core_is_ecpf(dev)) + return; + + mlx5_peer_pf_cleanup(dev); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h index 8b684f0ab48f..d3d7a00a02ac 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h @@ -14,11 +14,15 @@ enum { }; bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev); +int mlx5_ec_init(struct mlx5_core_dev *dev); +void mlx5_ec_cleanup(struct mlx5_core_dev *dev); #else /* CONFIG_MLX5_ESWITCH */ static inline bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev) { return false; } +static inline int mlx5_ec_init(struct mlx5_core_dev *dev) { return 0; } +static inline void mlx5_ec_cleanup(struct mlx5_core_dev *dev) {} #endif /* CONFIG_MLX5_ESWITCH */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 08a3da2a8358..40d591c8e76c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -612,6 +612,8 @@ int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id) MLX5_SET(enable_hca_in, in, opcode, MLX5_CMD_OP_ENABLE_HCA); MLX5_SET(enable_hca_in, in, function_id, func_id); + MLX5_SET(enable_hca_in, in, embedded_cpu_function, + dev->caps.embedded_cpu); return mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out)); } @@ -622,6 +624,8 @@ int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id) MLX5_SET(disable_hca_in, in, opcode, MLX5_CMD_OP_DISABLE_HCA); MLX5_SET(disable_hca_in, in, function_id, func_id); + MLX5_SET(enable_hca_in, in, embedded_cpu_function, + dev->caps.embedded_cpu); return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); } @@ -1071,6 +1075,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, goto err_sriov; } + err = mlx5_ec_init(dev); + if (err) { + dev_err(&pdev->dev, "Failed to init embedded CPU\n"); + goto err_ec; + } + if (mlx5_device_registered(dev)) { mlx5_attach_device(dev); } else { @@ -1088,6 +1098,9 @@ out: return 0; err_reg_dev: + mlx5_ec_cleanup(dev); + +err_ec: mlx5_sriov_detach(dev); err_sriov: @@ -1162,6 +1175,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, if (mlx5_device_registered(dev)) mlx5_detach_device(dev); + mlx5_ec_cleanup(dev); mlx5_sriov_detach(dev); mlx5_cleanup_fs(dev); mlx5_accel_ipsec_cleanup(dev); diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 46799b4c8859..1b6d5a563a3a 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -6061,7 +6061,8 @@ struct mlx5_ifc_enable_hca_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x10]; + u8 embedded_cpu_function[0x1]; + u8 reserved_at_41[0xf]; u8 function_id[0x10]; u8 reserved_at_60[0x20]; @@ -6105,7 +6106,8 @@ struct mlx5_ifc_disable_hca_in_bits { u8 reserved_at_20[0x10]; u8 op_mod[0x10]; - u8 reserved_at_40[0x10]; + u8 embedded_cpu_function[0x1]; + u8 reserved_at_41[0xf]; u8 function_id[0x10]; u8 reserved_at_60[0x20]; -- cgit v1.2.3 From c3a4e9f10714911486d09e7729195cc8fbedecd3 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:37 -0800 Subject: net/mlx5: Add query host params command The QUERY_HOST_PARAMS command is used by an Embedded CPU Physical Function (ECPF) driver to identify and retrieve information about the PF on the host side. E.g, number of virtual functions and PCI BDF. The number of VFs can be changed on the fly, a function is added to query current number of VFs and will be used in downstream patches. Signed-off-by: Bodong Wang Signed-off-by: Eli Cohen Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 2 ++ drivers/net/ethernet/mellanox/mlx5/core/ecpf.c | 27 +++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/ecpf.h | 4 +++ include/linux/mlx5/mlx5_ifc.h | 41 ++++++++++++++++++++++++++ 4 files changed, 74 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index a25a8c6f938e..46d70eb2d2f7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -316,6 +316,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, case MLX5_CMD_OP_DESTROY_GENERAL_OBJECT: case MLX5_CMD_OP_DEALLOC_MEMIC: case MLX5_CMD_OP_PAGE_FAULT_RESUME: + case MLX5_CMD_OP_QUERY_HOST_PARAMS: return MLX5_CMD_STAT_OK; case MLX5_CMD_OP_QUERY_HCA_CAP: @@ -627,6 +628,7 @@ const char *mlx5_command_str(int command) MLX5_COMMAND_STR_CASE(QUERY_MODIFY_HEADER_CONTEXT); MLX5_COMMAND_STR_CASE(ALLOC_MEMIC); MLX5_COMMAND_STR_CASE(DEALLOC_MEMIC); + MLX5_COMMAND_STR_CASE(QUERY_HOST_PARAMS); default: return "unknown command opcode"; } } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c index 1bcf8b8f9713..4746f2d28fb6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c @@ -83,3 +83,30 @@ void mlx5_ec_cleanup(struct mlx5_core_dev *dev) mlx5_peer_pf_cleanup(dev); } + +static int mlx5_query_host_params_context(struct mlx5_core_dev *dev, + u32 *out, int outlen) +{ + u32 in[MLX5_ST_SZ_DW(query_host_params_in)] = {}; + + MLX5_SET(query_host_params_in, in, opcode, + MLX5_CMD_OP_QUERY_HOST_PARAMS); + + return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); +} + +int mlx5_query_host_params_num_vfs(struct mlx5_core_dev *dev, int *num_vf) +{ + u32 out[MLX5_ST_SZ_DW(query_host_params_out)] = {}; + int err; + + err = mlx5_query_host_params_context(dev, out, sizeof(out)); + if (err) + return err; + + *num_vf = MLX5_GET(query_host_params_out, out, + host_params_context.host_num_of_vfs); + mlx5_core_dbg(dev, "host_num_of_vfs %d\n", *num_vf); + + return 0; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h index d3d7a00a02ac..346372df218f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.h @@ -16,6 +16,7 @@ enum { bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev); int mlx5_ec_init(struct mlx5_core_dev *dev); void mlx5_ec_cleanup(struct mlx5_core_dev *dev); +int mlx5_query_host_params_num_vfs(struct mlx5_core_dev *dev, int *num_vf); #else /* CONFIG_MLX5_ESWITCH */ @@ -23,6 +24,9 @@ static inline bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev) { return false; } static inline int mlx5_ec_init(struct mlx5_core_dev *dev) { return 0; } static inline void mlx5_ec_cleanup(struct mlx5_core_dev *dev) {} +static inline int +mlx5_query_host_params_num_vfs(struct mlx5_core_dev *dev, int *num_vf) +{ return -EOPNOTSUPP; } #endif /* CONFIG_MLX5_ESWITCH */ diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 1b6d5a563a3a..565046830559 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -142,6 +142,7 @@ enum { MLX5_CMD_OP_QUERY_XRQ_DC_PARAMS_ENTRY = 0x725, MLX5_CMD_OP_SET_XRQ_DC_PARAMS_ENTRY = 0x726, MLX5_CMD_OP_QUERY_XRQ_ERROR_PARAMS = 0x727, + MLX5_CMD_OP_QUERY_HOST_PARAMS = 0x740, MLX5_CMD_OP_QUERY_VPORT_STATE = 0x750, MLX5_CMD_OP_MODIFY_VPORT_STATE = 0x751, MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT = 0x752, @@ -9522,4 +9523,44 @@ struct mlx5_ifc_mtrc_ctrl_bits { u8 reserved_at_80[0x180]; }; +struct mlx5_ifc_host_params_context_bits { + u8 host_number[0x8]; + u8 reserved_at_8[0x8]; + u8 host_num_of_vfs[0x10]; + + u8 reserved_at_20[0x10]; + u8 host_pci_bus[0x10]; + + u8 reserved_at_40[0x10]; + u8 host_pci_device[0x10]; + + u8 reserved_at_60[0x10]; + u8 host_pci_function[0x10]; + + u8 reserved_at_80[0x180]; +}; + +struct mlx5_ifc_query_host_params_in_bits { + u8 opcode[0x10]; + u8 reserved_at_10[0x10]; + + u8 reserved_at_20[0x10]; + u8 op_mod[0x10]; + + u8 reserved_at_40[0x40]; +}; + +struct mlx5_ifc_query_host_params_out_bits { + u8 status[0x8]; + u8 reserved_at_8[0x18]; + + u8 syndrome[0x20]; + + u8 reserved_at_40[0x40]; + + struct mlx5_ifc_host_params_context_bits host_params_context; + + u8 reserved_at_280[0x180]; +}; + #endif /* MLX5_IFC_H */ -- cgit v1.2.3 From 7f0d11c7e0d08304de55b6a571a69166f3d54160 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:38 -0800 Subject: net/mlx5: Add host params change event In Embedded CPU (EC) configurations, the EC driver needs to know when the number of virtual functions change on the corresponding PF at the host side. This is required so the EC driver can create or destroy representor net devices that represent the VFs ports. Whenever a change in the number of VFs occurs, firmware will generate an event towards the EC which will trigger a work to complete the rest of the handling. The specifics of the handling will be introduced in a downstream patch. Signed-off-by: Bodong Wang Signed-off-by: Eli Cohen Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 3 +++ drivers/net/ethernet/mellanox/mlx5/core/events.c | 2 ++ include/linux/mlx5/device.h | 2 ++ include/linux/mlx5/driver.h | 5 +++++ 4 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 7092457705a2..5c02f9291799 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -530,6 +530,9 @@ static u64 gather_async_events_mask(struct mlx5_core_dev *dev) if (MLX5_CAP_GEN(dev, max_num_of_monitor_counters)) async_event_mask |= (1ull << MLX5_EVENT_TYPE_MONITOR_COUNTER); + if (mlx5_core_is_ecpf_esw_manager(dev)) + async_event_mask |= (1ull << MLX5_EVENT_TYPE_HOST_PARAMS_CHANGE); + return async_event_mask; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c index fbc42b7252a9..4f7f776d6332 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/events.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c @@ -103,6 +103,8 @@ static const char *eqe_type_str(u8 type) return "MLX5_EVENT_TYPE_STALL_EVENT"; case MLX5_EVENT_TYPE_CMD: return "MLX5_EVENT_TYPE_CMD"; + case MLX5_EVENT_TYPE_HOST_PARAMS_CHANGE: + return "MLX5_EVENT_TYPE_HOST_PARAMS_CHANGE"; case MLX5_EVENT_TYPE_PAGE_REQUEST: return "MLX5_EVENT_TYPE_PAGE_REQUEST"; case MLX5_EVENT_TYPE_PAGE_FAULT: diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index f2070350f60a..f93a5598b942 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -342,6 +342,8 @@ enum mlx5_event { MLX5_EVENT_TYPE_PAGE_FAULT = 0xc, MLX5_EVENT_TYPE_NIC_VPORT_CHANGE = 0xd, + MLX5_EVENT_TYPE_HOST_PARAMS_CHANGE = 0xe, + MLX5_EVENT_TYPE_DCT_DRAINED = 0x1c, MLX5_EVENT_TYPE_FPGA_ERROR = 0x20, diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index cce4e8293384..151563a12fc2 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -1083,6 +1083,11 @@ static inline bool mlx5_core_is_ecpf(struct mlx5_core_dev *dev) return dev->caps.embedded_cpu; } +static inline bool mlx5_core_is_ecpf_esw_manager(struct mlx5_core_dev *dev) +{ + return dev->caps.embedded_cpu && MLX5_CAP_GEN(dev, eswitch_manager); +} + #define MLX5_TOTAL_VPORTS(mdev) (1 + pci_sriov_get_totalvfs((mdev)->pdev)) #define MLX5_VPORT_MANAGER(mdev) \ (MLX5_CAP_GEN(mdev, vport_group_manager) && \ -- cgit v1.2.3 From b05af6aacdb920dc3bfd27d53ade7f680d43265c Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:40 -0800 Subject: net/mlx5: E-Switch, Normalize the name of uplink vport number Driver used to name uplink vport as FDB_UPLINK_VPORT, it's hard to comply with the same naming convention along with the introduction of other vports. Use MLX5_VPORT as the prefix for such vports and relocate the uplink vport definition to public header file for the benefits of both net and IB drivers. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/infiniband/hw/mlx5/ib_rep.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 22 +++++++++++----------- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +++--- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 8 +++----- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 2 -- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 14 +++++++------- include/linux/mlx5/vport.h | 4 ++++ 7 files changed, 30 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c index 3fb22967c098..99cae9a10195 100644 --- a/drivers/infiniband/hw/mlx5/ib_rep.c +++ b/drivers/infiniband/hw/mlx5/ib_rep.c @@ -3,6 +3,7 @@ * Copyright (c) 2018 Mellanox Technologies. All rights reserved. */ +#include #include "ib_rep.h" #include "srq.h" @@ -48,11 +49,10 @@ static const struct mlx5_ib_profile vf_rep_profile = { static int mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) { -#define FDB_UPLINK_VPORT 0xffff const struct mlx5_ib_profile *profile; struct mlx5_ib_dev *ibdev; - if (rep->vport == FDB_UPLINK_VPORT) + if (rep->vport == MLX5_VPORT_UPLINK) profile = &uplink_rep_profile; else profile = &vf_rep_profile; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 96cc0c6a4014..c78d21b2501e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -152,7 +152,7 @@ static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv) struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5_eswitch_rep *rep = rpriv->rep; - if (rep->vport == FDB_UPLINK_VPORT) + if (rep->vport == MLX5_VPORT_UPLINK) mlx5e_uplink_rep_update_hw_counters(priv); else mlx5e_vf_rep_update_hw_counters(priv); @@ -1207,7 +1207,7 @@ bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) return false; rep = rpriv->rep; - return (rep->vport == FDB_UPLINK_VPORT); + return (rep->vport == MLX5_VPORT_UPLINK); } static bool mlx5e_rep_has_offload_stats(const struct net_device *dev, int attr_id) @@ -1343,7 +1343,7 @@ static void mlx5e_build_rep_params(struct net_device *netdev) params->sw_mtu = netdev->mtu; /* SQ */ - if (rep->vport == FDB_UPLINK_VPORT) + if (rep->vport == MLX5_VPORT_UPLINK) params->log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE; else params->log_sq_size = MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE; @@ -1370,7 +1370,7 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev) struct mlx5_eswitch_rep *rep = rpriv->rep; struct mlx5_core_dev *mdev = priv->mdev; - if (rep->vport == FDB_UPLINK_VPORT) { + if (rep->vport == MLX5_VPORT_UPLINK) { SET_NETDEV_DEV(netdev, &priv->mdev->pdev->dev); netdev->netdev_ops = &mlx5e_netdev_ops_uplink_rep; /* we want a persistent mac for the uplink rep */ @@ -1402,7 +1402,7 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev) netdev->hw_features |= NETIF_F_TSO6; netdev->hw_features |= NETIF_F_RXCSUM; - if (rep->vport != FDB_UPLINK_VPORT) + if (rep->vport != MLX5_VPORT_UPLINK) netdev->features |= NETIF_F_VLAN_CHALLENGED; netdev->features |= netdev->hw_features; @@ -1555,7 +1555,7 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) return err; } - if (rpriv->rep->vport == FDB_UPLINK_VPORT) { + if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { uplink_priv = &rpriv->uplink_priv; /* init shared tc flow table */ @@ -1591,7 +1591,7 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv) for (tc = 0; tc < priv->profile->max_tc; tc++) mlx5e_destroy_tis(priv->mdev, priv->tisn[tc]); - if (rpriv->rep->vport == FDB_UPLINK_VPORT) { + if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { /* clean indirect TC block notifications */ unregister_netdevice_notifier(&rpriv->uplink_priv.netdevice_nb); mlx5e_rep_indr_clean_block_privs(rpriv); @@ -1710,7 +1710,7 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) rpriv->rep = rep; nch = mlx5e_get_max_num_channels(dev); - profile = (rep->vport == FDB_UPLINK_VPORT) ? &mlx5e_uplink_rep_profile : &mlx5e_vf_rep_profile; + profile = (rep->vport == MLX5_VPORT_UPLINK) ? &mlx5e_uplink_rep_profile : &mlx5e_vf_rep_profile; netdev = mlx5e_create_netdev(dev, profile, nch, rpriv); if (!netdev) { pr_warn("Failed to create representor netdev for vport %d\n", @@ -1723,7 +1723,7 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) rep->rep_if[REP_ETH].priv = rpriv; INIT_LIST_HEAD(&rpriv->vport_sqs_list); - if (rep->vport == FDB_UPLINK_VPORT) { + if (rep->vport == MLX5_VPORT_UPLINK) { err = mlx5e_create_mdev_resources(dev); if (err) goto err_destroy_netdev; @@ -1759,7 +1759,7 @@ err_detach_netdev: mlx5e_detach_netdev(netdev_priv(netdev)); err_destroy_mdev_resources: - if (rep->vport == FDB_UPLINK_VPORT) + if (rep->vport == MLX5_VPORT_UPLINK) mlx5e_destroy_mdev_resources(dev); err_destroy_netdev: @@ -1779,7 +1779,7 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep) unregister_netdev(netdev); mlx5e_rep_neigh_cleanup(rpriv); mlx5e_detach_netdev(priv); - if (rep->vport == FDB_UPLINK_VPORT) + if (rep->vport == MLX5_VPORT_UPLINK) mlx5e_destroy_mdev_resources(priv->mdev); mlx5e_destroy_netdev(priv); kfree(ppriv); /* mlx5e_rep_priv */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index cae6c6d48984..1a73e661056a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1834,7 +1834,7 @@ static int parse_cls_flower(struct mlx5e_priv *priv, if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) { rep = rpriv->rep; - if (rep->vport != FDB_UPLINK_VPORT && + if (rep->vport != MLX5_VPORT_UPLINK && (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE && esw->offloads.inline_mode < match_level)) { NL_SET_ERR_MSG_MOD(extack, @@ -2724,7 +2724,7 @@ static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv, int flags) static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow) { struct mlx5_esw_flow_attr *attr = flow->esw_attr; - bool is_rep_ingress = attr->in_rep->vport != FDB_UPLINK_VPORT && + bool is_rep_ingress = attr->in_rep->vport != MLX5_VPORT_UPLINK && flow->flags & MLX5E_TC_FLOW_INGRESS; bool act_is_encap = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT); @@ -2849,7 +2849,7 @@ static int mlx5e_tc_add_fdb_peer_flow(struct tc_cls_flower_offload *f, * original flow and packets redirected from uplink use the * peer mdev. */ - if (flow->esw_attr->in_rep->vport == FDB_UPLINK_VPORT) + if (flow->esw_attr->in_rep->vport == MLX5_VPORT_UPLINK) in_mdev = peer_priv->mdev; else in_mdev = priv->mdev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index d7382892e81c..0db56b4b7009 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -40,8 +40,6 @@ #include "eswitch.h" #include "fs_core.h" -#define UPLINK_VPORT 0xFFFF - enum { MLX5_ACTION_NONE = 0, MLX5_ACTION_ADD = 1, @@ -188,7 +186,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule, misc_parameters); mc_misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); - MLX5_SET(fte_match_set_misc, mv_misc, source_port, UPLINK_VPORT); + MLX5_SET(fte_match_set_misc, mv_misc, source_port, MLX5_VPORT_UPLINK); MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port); } @@ -499,7 +497,7 @@ static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) return -ENOMEM; esw_mc->uplink_rule = /* Forward MC MAC to Uplink */ - esw_fdb_set_vport_rule(esw, mac, UPLINK_VPORT); + esw_fdb_set_vport_rule(esw, mac, MLX5_VPORT_UPLINK); /* Add this multicast mac to all the mc promiscuous vports */ update_allmulti_vports(esw, vaddr, esw_mc); @@ -736,7 +734,7 @@ static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u16 vport_num, if (!allmulti_addr->uplink_rule) allmulti_addr->uplink_rule = esw_fdb_set_vport_allmulti_rule(esw, - UPLINK_VPORT); + MLX5_VPORT_UPLINK); allmulti_addr->refcnt++; } else if (vport->allmulti_rule) { mlx5_del_flow_rules(vport->allmulti_rule); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 9c89eea9b2c3..94da74b1e6ea 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -49,8 +49,6 @@ #define MLX5_MAX_MC_PER_VPORT(dev) \ (1 << MLX5_CAP_GEN(dev, log_max_current_mc_list)) -#define FDB_UPLINK_VPORT 0xffff - #define MLX5_MIN_BW_SHARE 1 #define MLX5_RATE_TO_BW_SHARE(rate, divider, limit) \ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 53065b6ae593..b0b1267eab07 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -359,15 +359,15 @@ static int esw_add_vlan_action_check(struct mlx5_esw_flow_attr *attr, in_rep = attr->in_rep; out_rep = attr->dests[0].rep; - if (push && in_rep->vport == FDB_UPLINK_VPORT) + if (push && in_rep->vport == MLX5_VPORT_UPLINK) goto out_notsupp; - if (pop && out_rep->vport == FDB_UPLINK_VPORT) + if (pop && out_rep->vport == MLX5_VPORT_UPLINK) goto out_notsupp; /* vport has vlan push configured, can't offload VF --> wire rules w.o it */ if (!push && !pop && fwd) - if (in_rep->vlan && out_rep->vport == FDB_UPLINK_VPORT) + if (in_rep->vlan && out_rep->vport == MLX5_VPORT_UPLINK) goto out_notsupp; /* protects against (1) setting rules with different vlans to push and @@ -409,7 +409,7 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw, if (!push && !pop && fwd) { /* tracks VF --> wire rules without vlan push action */ - if (attr->dests[0].rep->vport == FDB_UPLINK_VPORT) { + if (attr->dests[0].rep->vport == MLX5_VPORT_UPLINK) { vport->vlan_refcount++; attr->vlan_handled = true; } @@ -469,7 +469,7 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw, if (!push && !pop && fwd) { /* tracks VF --> wire rules without vlan push action */ - if (attr->dests[0].rep->vport == FDB_UPLINK_VPORT) + if (attr->dests[0].rep->vport == MLX5_VPORT_UPLINK) vport->vlan_refcount--; return 0; @@ -1227,7 +1227,7 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) ether_addr_copy(rep->hw_id, hw_id); } - offloads->vport_reps[0].vport = FDB_UPLINK_VPORT; + offloads->vport_reps[0].vport = MLX5_VPORT_UPLINK; return 0; } @@ -1811,7 +1811,7 @@ void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw, struct mlx5_esw_offload *offloads = &esw->offloads; struct mlx5_eswitch_rep *rep; - if (vport == FDB_UPLINK_VPORT) + if (vport == MLX5_VPORT_UPLINK) vport = UPLINK_REP_INDEX; rep = &offloads->vport_reps[vport]; diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index 1654b911cdb2..2e2928eacd97 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -42,6 +42,10 @@ enum { MLX5_CAP_INLINE_MODE_NOT_REQUIRED, }; +enum { + MLX5_VPORT_UPLINK = 0xffff +}; + u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport); int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport, u8 state); -- cgit v1.2.3 From bf3e4d387daed36aad2cfd4f493b07714ac0cd5e Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:41 -0800 Subject: net/mlx5: Relocate vport macros to the vport header file These are two macros in the driver general header which deal with the number of total vports and if a vport is vport manager. Such macros are vport entities, better to place them at the vport header file. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 1 + include/linux/mlx5/driver.h | 6 ------ include/linux/mlx5/vport.h | 7 +++++++ 4 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 5c02f9291799..bb6e5b5d9681 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_RFS_ACCEL diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 79f122b45def..b6a7bc8f667c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -32,6 +32,7 @@ #include #include +#include #include #include "mlx5_core.h" diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index 46e0aa52a58a..c5454f985e1d 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -1097,12 +1097,6 @@ static inline u16 mlx5_core_max_vfs(struct mlx5_core_dev *dev) return pci_sriov_get_totalvfs(dev->pdev); } -#define MLX5_TOTAL_VPORTS(mdev) (1 + mlx5_core_max_vfs(mdev)) -#define MLX5_VPORT_MANAGER(mdev) \ - (MLX5_CAP_GEN(mdev, vport_group_manager) && \ - (MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) && \ - mlx5_core_is_pf(mdev)) - static inline int mlx5_get_gid_table_len(u16 param) { if (param > 4) { diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index 2e2928eacd97..28f47e868fbc 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -36,6 +36,13 @@ #include #include +#define MLX5_TOTAL_VPORTS(mdev) (1 + mlx5_core_max_vfs(mdev)) + +#define MLX5_VPORT_MANAGER(mdev) \ + (MLX5_CAP_GEN(mdev, vport_group_manager) && \ + (MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) && \ + mlx5_core_is_pf(mdev)) + enum { MLX5_CAP_INLINE_MODE_L2, MLX5_CAP_INLINE_MODE_VPORT_CONTEXT, -- cgit v1.2.3 From cd7e4186af9d968559852b4eeb1039b3419cc590 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 12 Feb 2019 22:55:42 -0800 Subject: net/mlx5: E-Switch, Avoid magic numbers when initializing offloads mode When dealing with the offloads mode initialization, driver refers to the number of VFs and add magic number one (1) to take account of the uplink. This is not clear and will make the code less readable after adding other vports (e.g. host PF). As these are special vports compared to VF vports, add a helper macro to denote such special vports and eliminate the use of magic number. Moreover, when creating offloads flow table and groups, the driver reserves two more slots for UC and MC miss rules. Replace this magic number with a helper macro as well. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 2 +- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 25 +++++++++++++--------- include/linux/mlx5/vport.h | 4 +++- 3 files changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 0db56b4b7009..49a9e3877d2c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1638,7 +1638,7 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) } else { mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH); mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB); - err = esw_offloads_init(esw, nvfs + 1); + err = esw_offloads_init(esw, nvfs + MLX5_SPECIAL_VPORTS); } if (err) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index b0b1267eab07..1496e82b5108 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -46,6 +46,11 @@ enum { FDB_SLOW_PATH }; +/* There are two match-all miss flows, one for unicast dst mac and + * one for multicast. + */ +#define MLX5_ESW_MISS_FLOWS (2) + #define fdb_prio_table(esw, chain, prio, level) \ (esw)->fdb_table.offloads.fdb_prio[(chain)][(prio)][(level)] @@ -904,8 +909,8 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw, int nvports) esw->fdb_table.offloads.fdb_left[i] = ESW_POOLS[i] <= fdb_max ? ESW_SIZE / ESW_POOLS[i] : 0; - table_size = nvports * MAX_SQ_NVPORTS + MAX_PF_SQ + 2 + - esw->total_vports; + table_size = nvports * MAX_SQ_NVPORTS + MAX_PF_SQ + + MLX5_ESW_MISS_FLOWS + esw->total_vports; /* create the slow path fdb with encap set, so further table instances * can be created at run time while VFs are probed if the FW allows that. @@ -999,7 +1004,8 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw, int nvports) dmac[0] = 0x01; MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix); - MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix + 2); + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, + ix + MLX5_ESW_MISS_FLOWS); g = mlx5_create_flow_group(fdb, flow_group_in); if (IS_ERR(g)) { @@ -1048,7 +1054,7 @@ static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw) esw_destroy_offloads_fast_fdb_tables(esw); } -static int esw_create_offloads_table(struct mlx5_eswitch *esw) +static int esw_create_offloads_table(struct mlx5_eswitch *esw, int nvports) { struct mlx5_flow_table_attr ft_attr = {}; struct mlx5_core_dev *dev = esw->dev; @@ -1062,7 +1068,7 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw) return -EOPNOTSUPP; } - ft_attr.max_fte = dev->priv.sriov.num_vfs + 2; + ft_attr.max_fte = nvports + MLX5_ESW_MISS_FLOWS; ft_offloads = mlx5_create_flow_table(ns, &ft_attr); if (IS_ERR(ft_offloads)) { @@ -1082,16 +1088,15 @@ static void esw_destroy_offloads_table(struct mlx5_eswitch *esw) mlx5_destroy_flow_table(offloads->ft_offloads); } -static int esw_create_vport_rx_group(struct mlx5_eswitch *esw) +static int esw_create_vport_rx_group(struct mlx5_eswitch *esw, int nvports) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); struct mlx5_flow_group *g; - struct mlx5_priv *priv = &esw->dev->priv; u32 *flow_group_in; void *match_criteria, *misc; int err = 0; - int nvports = priv->sriov.num_vfs + 2; + nvports = nvports + MLX5_ESW_MISS_FLOWS; flow_group_in = kvzalloc(inlen, GFP_KERNEL); if (!flow_group_in) return -ENOMEM; @@ -1407,11 +1412,11 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int nvports) if (err) return err; - err = esw_create_offloads_table(esw); + err = esw_create_offloads_table(esw, nvports); if (err) goto create_ft_err; - err = esw_create_vport_rx_group(esw); + err = esw_create_vport_rx_group(esw, nvports); if (err) goto create_fg_err; diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index 28f47e868fbc..3bc05449ac39 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -36,7 +36,9 @@ #include #include -#define MLX5_TOTAL_VPORTS(mdev) (1 + mlx5_core_max_vfs(mdev)) +#define MLX5_VPORT_PF_PLACEHOLDER (1u) +#define MLX5_SPECIAL_VPORTS (MLX5_VPORT_PF_PLACEHOLDER) +#define MLX5_TOTAL_VPORTS(mdev) (MLX5_SPECIAL_VPORTS + mlx5_core_max_vfs(mdev)) #define MLX5_VPORT_MANAGER(mdev) \ (MLX5_CAP_GEN(mdev, vport_group_manager) && \ -- cgit v1.2.3 From bc4e12ffefdd886057eabe38135515690d0756a6 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Tue, 12 Feb 2019 22:55:43 -0800 Subject: net/mlx5: Refactor queries to speed fields in Port Type and Speed register This patch fascicles queries to speed related fields in Port Type and Speed register (PTYS) into a single API. I addition, this patch refactors functions which serves only Ethernet driver: remove the protocol type as an input parameter, move code from 'core' directory into 'en' directory and add 'eth' prefix to the function's name. The patch also encapsulates functions that are not used outside the Ethernet driver removes redundant include files. Signed-off-by: Aya Levin Reviewed-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- drivers/infiniband/hw/mlx5/main.c | 6 +- drivers/net/ethernet/mellanox/mlx5/core/en/port.c | 75 +++++++++++++-- drivers/net/ethernet/mellanox/mlx5/core/en/port.h | 12 +++ .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 23 ++--- drivers/net/ethernet/mellanox/mlx5/core/port.c | 106 --------------------- include/linux/mlx5/port.h | 11 --- 6 files changed, 91 insertions(+), 142 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 87ce62e44898..efd08b41126c 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -393,6 +393,7 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num, struct ib_port_attr *props) { struct mlx5_ib_dev *dev = to_mdev(device); + u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0}; struct mlx5_core_dev *mdev; struct net_device *ndev, *upper; enum ib_mtu ndev_ib_mtu; @@ -416,10 +417,11 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num, /* Possible bad flows are checked before filling out props so in case * of an error it will still be zeroed out. */ - err = mlx5_query_port_eth_proto_oper(mdev, ð_prot_oper, - mdev_port_num); + err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, + mdev_port_num); if (err) goto out; + eth_prot_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); props->active_width = IB_WIDTH_4X; props->active_speed = IB_SPEED_QDR; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c index 4a37713023be..9a1c2b2f87d8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c @@ -63,6 +63,67 @@ static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = { [MLX5E_50GBASE_KR2] = 50000, }; +int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, + struct mlx5e_port_eth_proto *eproto) +{ + u32 out[MLX5_ST_SZ_DW(ptys_reg)]; + int err; + + if (!eproto) + return -EINVAL; + + err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port); + if (err) + return err; + + eproto->cap = MLX5_GET(ptys_reg, out, eth_proto_capability); + eproto->admin = MLX5_GET(ptys_reg, out, eth_proto_admin); + eproto->oper = MLX5_GET(ptys_reg, out, eth_proto_oper); + return 0; +} + +void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status, + u8 *an_disable_cap, u8 *an_disable_admin) +{ + u32 out[MLX5_ST_SZ_DW(ptys_reg)]; + + *an_status = 0; + *an_disable_cap = 0; + *an_disable_admin = 0; + + if (mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, 1)) + return; + + *an_status = MLX5_GET(ptys_reg, out, an_status); + *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap); + *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin); +} + +int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable, + u32 proto_admin) +{ + u32 out[MLX5_ST_SZ_DW(ptys_reg)]; + u32 in[MLX5_ST_SZ_DW(ptys_reg)]; + u8 an_disable_admin; + u8 an_disable_cap; + u8 an_status; + + mlx5_port_query_eth_autoneg(dev, &an_status, &an_disable_cap, + &an_disable_admin); + if (!an_disable_cap && an_disable) + return -EPERM; + + memset(in, 0, sizeof(in)); + + MLX5_SET(ptys_reg, in, local_port, 1); + MLX5_SET(ptys_reg, in, an_disable_admin, an_disable); + MLX5_SET(ptys_reg, in, proto_mask, MLX5_PTYS_EN); + MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); + + return mlx5_core_access_reg(dev, in, sizeof(in), out, + sizeof(out), MLX5_REG_PTYS, 0, 1); +} + u32 mlx5e_port_ptys2speed(u32 eth_proto_oper) { unsigned long temp = eth_proto_oper; @@ -78,16 +139,14 @@ u32 mlx5e_port_ptys2speed(u32 eth_proto_oper) int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) { - u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {}; - u32 eth_proto_oper; + struct mlx5e_port_eth_proto eproto; int err; - err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1); + err = mlx5_port_query_eth_proto(mdev, 1, &eproto); if (err) return err; - eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); - *speed = mlx5e_port_ptys2speed(eth_proto_oper); + *speed = mlx5e_port_ptys2speed(eproto.oper); if (!(*speed)) err = -EINVAL; @@ -96,17 +155,17 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) { + struct mlx5e_port_eth_proto eproto; u32 max_speed = 0; - u32 proto_cap; int err; int i; - err = mlx5_query_port_proto_cap(mdev, &proto_cap, MLX5_PTYS_EN); + err = mlx5_port_query_eth_proto(mdev, 1, &eproto); if (err) return err; for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) - if (proto_cap & MLX5E_PROT_MASK(i)) + if (eproto.cap & MLX5E_PROT_MASK(i)) max_speed = max(max_speed, mlx5e_link_speed[i]); *speed = max_speed; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h index cd2160b8c9bf..4bdab8be10af 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h @@ -36,6 +36,18 @@ #include #include "en.h" +struct mlx5e_port_eth_proto { + u32 cap; + u32 admin; + u32 oper; +}; + +int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, + struct mlx5e_port_eth_proto *eproto); +void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status, + u8 *an_disable_cap, u8 *an_disable_admin); +int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable, + u32 proto_admin); u32 mlx5e_port_ptys2speed(u32 eth_proto_oper); int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index c9df08133718..c29e141d72fb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -882,7 +882,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, const struct ethtool_link_ksettings *link_ksettings) { struct mlx5_core_dev *mdev = priv->mdev; - u32 eth_proto_cap, eth_proto_admin; + struct mlx5e_port_eth_proto eproto; bool an_changes = false; u8 an_disable_admin; u8 an_disable_cap; @@ -898,14 +898,14 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) : mlx5e_port_speed2linkmodes(speed); - err = mlx5_query_port_proto_cap(mdev, ð_proto_cap, MLX5_PTYS_EN); + err = mlx5_port_query_eth_proto(mdev, 1, &eproto); if (err) { - netdev_err(priv->netdev, "%s: query port eth proto cap failed: %d\n", + netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n", __func__, err); goto out; } - link_modes = link_modes & eth_proto_cap; + link_modes = link_modes & eproto.cap; if (!link_modes) { netdev_err(priv->netdev, "%s: Not supported link mode(s) requested", __func__); @@ -913,24 +913,17 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, goto out; } - err = mlx5_query_port_proto_admin(mdev, ð_proto_admin, MLX5_PTYS_EN); - if (err) { - netdev_err(priv->netdev, "%s: query port eth proto admin failed: %d\n", - __func__, err); - goto out; - } - - mlx5_query_port_autoneg(mdev, MLX5_PTYS_EN, &an_status, - &an_disable_cap, &an_disable_admin); + mlx5_port_query_eth_autoneg(mdev, &an_status, &an_disable_cap, + &an_disable_admin); an_disable = link_ksettings->base.autoneg == AUTONEG_DISABLE; an_changes = ((!an_disable && an_disable_admin) || (an_disable && !an_disable_admin)); - if (!an_changes && link_modes == eth_proto_admin) + if (!an_changes && link_modes == eproto.admin) goto out; - mlx5_set_port_ptys(mdev, an_disable, link_modes, MLX5_PTYS_EN); + mlx5_port_set_eth_ptys(mdev, an_disable, link_modes); mlx5_toggle_port_link(mdev); out: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 2b82f35f4c35..b81542820528 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -30,10 +30,7 @@ * SOFTWARE. */ -#include -#include #include -#include #include "mlx5_core.h" int mlx5_core_access_reg(struct mlx5_core_dev *dev, void *data_in, @@ -157,44 +154,6 @@ int mlx5_set_port_beacon(struct mlx5_core_dev *dev, u16 beacon_duration) sizeof(out), MLX5_REG_MLCR, 0, 1); } -int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev, - u32 *proto_cap, int proto_mask) -{ - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; - int err; - - err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); - if (err) - return err; - - if (proto_mask == MLX5_PTYS_EN) - *proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability); - else - *proto_cap = MLX5_GET(ptys_reg, out, ib_proto_capability); - - return 0; -} -EXPORT_SYMBOL_GPL(mlx5_query_port_proto_cap); - -int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev, - u32 *proto_admin, int proto_mask) -{ - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; - int err; - - err = mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1); - if (err) - return err; - - if (proto_mask == MLX5_PTYS_EN) - *proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin); - else - *proto_admin = MLX5_GET(ptys_reg, out, ib_proto_admin); - - return 0; -} -EXPORT_SYMBOL_GPL(mlx5_query_port_proto_admin); - int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev, u8 *link_width_oper, u8 local_port) { @@ -211,23 +170,6 @@ int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev, } EXPORT_SYMBOL_GPL(mlx5_query_port_link_width_oper); -int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev, - u32 *proto_oper, u8 local_port) -{ - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; - int err; - - err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, - local_port); - if (err) - return err; - - *proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); - - return 0; -} -EXPORT_SYMBOL(mlx5_query_port_eth_proto_oper); - int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev, u8 *proto_oper, u8 local_port) { @@ -245,35 +187,6 @@ int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev, } EXPORT_SYMBOL(mlx5_query_port_ib_proto_oper); -int mlx5_set_port_ptys(struct mlx5_core_dev *dev, bool an_disable, - u32 proto_admin, int proto_mask) -{ - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; - u32 in[MLX5_ST_SZ_DW(ptys_reg)]; - u8 an_disable_admin; - u8 an_disable_cap; - u8 an_status; - - mlx5_query_port_autoneg(dev, proto_mask, &an_status, - &an_disable_cap, &an_disable_admin); - if (!an_disable_cap && an_disable) - return -EPERM; - - memset(in, 0, sizeof(in)); - - MLX5_SET(ptys_reg, in, local_port, 1); - MLX5_SET(ptys_reg, in, an_disable_admin, an_disable); - MLX5_SET(ptys_reg, in, proto_mask, proto_mask); - if (proto_mask == MLX5_PTYS_EN) - MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); - else - MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin); - - return mlx5_core_access_reg(dev, in, sizeof(in), out, - sizeof(out), MLX5_REG_PTYS, 0, 1); -} -EXPORT_SYMBOL_GPL(mlx5_set_port_ptys); - /* This function should be used after setting a port register only */ void mlx5_toggle_port_link(struct mlx5_core_dev *dev) { @@ -606,25 +519,6 @@ int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx, u8 *pfc_en_rx) } EXPORT_SYMBOL_GPL(mlx5_query_port_pfc); -void mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask, - u8 *an_status, - u8 *an_disable_cap, u8 *an_disable_admin) -{ - u32 out[MLX5_ST_SZ_DW(ptys_reg)]; - - *an_status = 0; - *an_disable_cap = 0; - *an_disable_admin = 0; - - if (mlx5_query_port_ptys(dev, out, sizeof(out), proto_mask, 1)) - return; - - *an_status = MLX5_GET(ptys_reg, out, an_status); - *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap); - *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin); -} -EXPORT_SYMBOL_GPL(mlx5_query_port_autoneg); - int mlx5_max_tc(struct mlx5_core_dev *mdev) { u8 num_tc = MLX5_CAP_GEN(mdev, max_tc) ? : 8; diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h index bf4bc01ffb0c..5be7eefa6d75 100644 --- a/include/linux/mlx5/port.h +++ b/include/linux/mlx5/port.h @@ -110,27 +110,16 @@ enum mlx5e_connector_type { int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps); int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys, int ptys_size, int proto_mask, u8 local_port); -int mlx5_query_port_proto_cap(struct mlx5_core_dev *dev, - u32 *proto_cap, int proto_mask); -int mlx5_query_port_proto_admin(struct mlx5_core_dev *dev, - u32 *proto_admin, int proto_mask); int mlx5_query_port_link_width_oper(struct mlx5_core_dev *dev, u8 *link_width_oper, u8 local_port); int mlx5_query_port_ib_proto_oper(struct mlx5_core_dev *dev, u8 *proto_oper, u8 local_port); -int mlx5_query_port_eth_proto_oper(struct mlx5_core_dev *dev, - u32 *proto_oper, u8 local_port); -int mlx5_set_port_ptys(struct mlx5_core_dev *dev, bool an_disable, - u32 proto_admin, int proto_mask); void mlx5_toggle_port_link(struct mlx5_core_dev *dev); int mlx5_set_port_admin_status(struct mlx5_core_dev *dev, enum mlx5_port_status status); int mlx5_query_port_admin_status(struct mlx5_core_dev *dev, enum mlx5_port_status *status); int mlx5_set_port_beacon(struct mlx5_core_dev *dev, u16 beacon_duration); -void mlx5_query_port_autoneg(struct mlx5_core_dev *dev, int proto_mask, - u8 *an_status, - u8 *an_disable_cap, u8 *an_disable_admin); int mlx5_set_port_mtu(struct mlx5_core_dev *dev, u16 mtu, u8 port); void mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, u16 *max_mtu, u8 port); -- cgit v1.2.3 From a08b4ed1373dc59e3e15029bc6f135ba0f53c9a7 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Tue, 12 Feb 2019 22:55:45 -0800 Subject: net/mlx5: Add support to ext_* fields introduced in Port Type and Speed register This patch exposes new link modes (including 50Gbps per lane), and ext_* fields which describes the new link modes in Port Type and Speed register (PTYS). Access functions, translation functions (speed <-> HW bits) and link max speed function were modified. Signed-off-by: Aya Levin Reviewed-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- drivers/infiniband/hw/mlx5/main.c | 3 +- drivers/net/ethernet/mellanox/mlx5/core/en/port.c | 85 ++++++++++++++++------ drivers/net/ethernet/mellanox/mlx5/core/en/port.h | 8 +- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 9 ++- include/linux/mlx5/port.h | 19 +++++ 5 files changed, 94 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index efd08b41126c..3677c00fa3bb 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -421,7 +421,8 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num, mdev_port_num); if (err) goto out; - eth_prot_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); + eth_prot_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, false, + eth_proto_oper); props->active_width = IB_WIDTH_4X; props->active_speed = IB_SPEED_QDR; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c index 9a1c2b2f87d8..122927f3a600 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c @@ -63,7 +63,31 @@ static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = { [MLX5E_50GBASE_KR2] = 50000, }; -int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, +static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = { + [MLX5E_SGMII_100M] = 100, + [MLX5E_1000BASE_X_SGMII] = 1000, + [MLX5E_5GBASE_R] = 5000, + [MLX5E_10GBASE_XFI_XAUI_1] = 10000, + [MLX5E_40GBASE_XLAUI_4_XLPPI_4] = 40000, + [MLX5E_25GAUI_1_25GBASE_CR_KR] = 25000, + [MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2] = 50000, + [MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR] = 50000, + [MLX5E_CAUI_4_100GBASE_CR4_KR4] = 100000, + [MLX5E_200GAUI_4_200GBASE_CR4_KR4] = 200000, + [MLX5E_400GAUI_8] = 400000, +}; + +static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev, + const u32 **arr, u32 *size) +{ + bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet); + + *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) : + ARRAY_SIZE(mlx5e_link_speed); + *arr = ext ? mlx5e_ext_link_speed : mlx5e_link_speed; +} + +int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext, struct mlx5e_port_eth_proto *eproto) { u32 out[MLX5_ST_SZ_DW(ptys_reg)]; @@ -72,13 +96,17 @@ int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, if (!eproto) return -EINVAL; + if (ext != MLX5_CAP_PCAM_FEATURE(dev, ptys_extended_ethernet)) + return -EOPNOTSUPP; + err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port); if (err) return err; - eproto->cap = MLX5_GET(ptys_reg, out, eth_proto_capability); - eproto->admin = MLX5_GET(ptys_reg, out, eth_proto_admin); - eproto->oper = MLX5_GET(ptys_reg, out, eth_proto_oper); + eproto->cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, + eth_proto_capability); + eproto->admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_admin); + eproto->oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper); return 0; } @@ -100,7 +128,7 @@ void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status, } int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable, - u32 proto_admin) + u32 proto_admin, bool ext) { u32 out[MLX5_ST_SZ_DW(ptys_reg)]; u32 in[MLX5_ST_SZ_DW(ptys_reg)]; @@ -118,38 +146,46 @@ int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable, MLX5_SET(ptys_reg, in, local_port, 1); MLX5_SET(ptys_reg, in, an_disable_admin, an_disable); MLX5_SET(ptys_reg, in, proto_mask, MLX5_PTYS_EN); - MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); + if (ext) + MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin); + else + MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); return mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out), MLX5_REG_PTYS, 0, 1); } -u32 mlx5e_port_ptys2speed(u32 eth_proto_oper) +u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper) { unsigned long temp = eth_proto_oper; + const u32 *table; u32 speed = 0; + u32 max_size; int i; - i = find_first_bit(&temp, MLX5E_LINK_MODES_NUMBER); - if (i < MLX5E_LINK_MODES_NUMBER) - speed = mlx5e_link_speed[i]; - + mlx5e_port_get_speed_arr(mdev, &table, &max_size); + i = find_first_bit(&temp, max_size); + if (i < max_size) + speed = table[i]; return speed; } int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) { struct mlx5e_port_eth_proto eproto; + bool ext; int err; - err = mlx5_port_query_eth_proto(mdev, 1, &eproto); + ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet); + err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto); if (err) - return err; + goto out; - *speed = mlx5e_port_ptys2speed(eproto.oper); + *speed = mlx5e_port_ptys2speed(mdev, eproto.oper); if (!(*speed)) err = -EINVAL; +out: return err; } @@ -157,31 +193,38 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) { struct mlx5e_port_eth_proto eproto; u32 max_speed = 0; + const u32 *table; + u32 max_size; + bool ext; int err; int i; - err = mlx5_port_query_eth_proto(mdev, 1, &eproto); + ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet); + err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto); if (err) return err; - for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) + mlx5e_port_get_speed_arr(mdev, &table, &max_size); + for (i = 0; i < max_size; ++i) if (eproto.cap & MLX5E_PROT_MASK(i)) - max_speed = max(max_speed, mlx5e_link_speed[i]); + max_speed = max(max_speed, table[i]); *speed = max_speed; return 0; } -u32 mlx5e_port_speed2linkmodes(u32 speed) +u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed) { u32 link_modes = 0; + const u32 *table; + u32 max_size; int i; - for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { - if (mlx5e_link_speed[i] == speed) + mlx5e_port_get_speed_arr(mdev, &table, &max_size); + for (i = 0; i < max_size; ++i) { + if (table[i] == speed) link_modes |= MLX5E_PROT_MASK(i); } - return link_modes; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h index 4bdab8be10af..70f536ec51c4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h @@ -42,16 +42,16 @@ struct mlx5e_port_eth_proto { u32 oper; }; -int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, +int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext, struct mlx5e_port_eth_proto *eproto); void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status, u8 *an_disable_cap, u8 *an_disable_admin); int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable, - u32 proto_admin); -u32 mlx5e_port_ptys2speed(u32 eth_proto_oper); + u32 proto_admin, bool ext); +u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper); int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); -u32 mlx5e_port_speed2linkmodes(u32 speed); +u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed); int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out); int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index c29e141d72fb..8343cf7d292c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -695,13 +695,14 @@ static void get_speed_duplex(struct net_device *netdev, u32 eth_proto_oper, struct ethtool_link_ksettings *link_ksettings) { + struct mlx5e_priv *priv = netdev_priv(netdev); u32 speed = SPEED_UNKNOWN; u8 duplex = DUPLEX_UNKNOWN; if (!netif_carrier_ok(netdev)) goto out; - speed = mlx5e_port_ptys2speed(eth_proto_oper); + speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper); if (!speed) { speed = SPEED_UNKNOWN; goto out; @@ -896,9 +897,9 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ? mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) : - mlx5e_port_speed2linkmodes(speed); + mlx5e_port_speed2linkmodes(mdev, speed); - err = mlx5_port_query_eth_proto(mdev, 1, &eproto); + err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto); if (err) { netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n", __func__, err); @@ -923,7 +924,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, if (!an_changes && link_modes == eproto.admin) goto out; - mlx5_port_set_eth_ptys(mdev, an_disable, link_modes); + mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, false); mlx5_toggle_port_link(mdev); out: diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h index 5be7eefa6d75..814fa194663b 100644 --- a/include/linux/mlx5/port.h +++ b/include/linux/mlx5/port.h @@ -92,6 +92,22 @@ enum mlx5e_link_mode { MLX5E_LINK_MODES_NUMBER, }; +enum mlx5e_ext_link_mode { + MLX5E_SGMII_100M = 0, + MLX5E_1000BASE_X_SGMII = 1, + MLX5E_5GBASE_R = 3, + MLX5E_10GBASE_XFI_XAUI_1 = 4, + MLX5E_40GBASE_XLAUI_4_XLPPI_4 = 5, + MLX5E_25GAUI_1_25GBASE_CR_KR = 6, + MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2 = 7, + MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR = 8, + MLX5E_CAUI_4_100GBASE_CR4_KR4 = 9, + MLX5E_100GAUI_2_100GBASE_CR2_KR2 = 10, + MLX5E_200GAUI_4_200GBASE_CR4_KR4 = 12, + MLX5E_400GAUI_8 = 15, + MLX5E_EXT_LINK_MODES_NUMBER, +}; + enum mlx5e_connector_type { MLX5E_PORT_UNKNOWN = 0, MLX5E_PORT_NONE = 1, @@ -106,6 +122,9 @@ enum mlx5e_connector_type { }; #define MLX5E_PROT_MASK(link_mode) (1 << link_mode) +#define MLX5_GET_ETH_PROTO(reg, out, ext, field) \ + (ext ? MLX5_GET(reg, out, ext_##field) : \ + MLX5_GET(reg, out, field)) int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps); int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys, -- cgit v1.2.3 From 08e8676f1607925adf36e399f0faa8ce3b10bb86 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Tue, 12 Feb 2019 22:55:46 -0800 Subject: IB/mlx5: Add support for 50Gbps per lane link modes Driver now supports new link modes: 50Gbps per lane support for 50G/100G/200G. This patch reads the correct field (legacy vs. extended) based on a FW indication bit, and adds a translation function (link modes to IB width and speed) to the new link modes. Signed-off-by: Aya Levin Reviewed-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- drivers/infiniband/hw/mlx5/main.c | 66 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 3677c00fa3bb..581ae11e2fc9 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -331,8 +331,8 @@ out: spin_unlock(&port->mp.mpi_lock); } -static int translate_eth_proto_oper(u32 eth_proto_oper, u8 *active_speed, - u8 *active_width) +static int translate_eth_legacy_proto_oper(u32 eth_proto_oper, u8 *active_speed, + u8 *active_width) { switch (eth_proto_oper) { case MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII): @@ -389,6 +389,61 @@ static int translate_eth_proto_oper(u32 eth_proto_oper, u8 *active_speed, return 0; } +static int translate_eth_ext_proto_oper(u32 eth_proto_oper, u8 *active_speed, + u8 *active_width) +{ + switch (eth_proto_oper) { + case MLX5E_PROT_MASK(MLX5E_SGMII_100M): + case MLX5E_PROT_MASK(MLX5E_1000BASE_X_SGMII): + *active_width = IB_WIDTH_1X; + *active_speed = IB_SPEED_SDR; + break; + case MLX5E_PROT_MASK(MLX5E_5GBASE_R): + *active_width = IB_WIDTH_1X; + *active_speed = IB_SPEED_DDR; + break; + case MLX5E_PROT_MASK(MLX5E_10GBASE_XFI_XAUI_1): + *active_width = IB_WIDTH_1X; + *active_speed = IB_SPEED_QDR; + break; + case MLX5E_PROT_MASK(MLX5E_40GBASE_XLAUI_4_XLPPI_4): + *active_width = IB_WIDTH_4X; + *active_speed = IB_SPEED_QDR; + break; + case MLX5E_PROT_MASK(MLX5E_25GAUI_1_25GBASE_CR_KR): + *active_width = IB_WIDTH_1X; + *active_speed = IB_SPEED_EDR; + break; + case MLX5E_PROT_MASK(MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2): + case MLX5E_PROT_MASK(MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR): + *active_width = IB_WIDTH_1X; + *active_speed = IB_SPEED_HDR; + break; + case MLX5E_PROT_MASK(MLX5E_100GAUI_2_100GBASE_CR2_KR2): + *active_width = IB_WIDTH_2X; + *active_speed = IB_SPEED_HDR; + break; + case MLX5E_PROT_MASK(MLX5E_200GAUI_4_200GBASE_CR4_KR4): + *active_width = IB_WIDTH_4X; + *active_speed = IB_SPEED_HDR; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int translate_eth_proto_oper(u32 eth_proto_oper, u8 *active_speed, + u8 *active_width, bool ext) +{ + return ext ? + translate_eth_ext_proto_oper(eth_proto_oper, active_speed, + active_width) : + translate_eth_legacy_proto_oper(eth_proto_oper, active_speed, + active_width); +} + static int mlx5_query_port_roce(struct ib_device *device, u8 port_num, struct ib_port_attr *props) { @@ -401,6 +456,7 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num, u16 qkey_viol_cntr; u32 eth_prot_oper; u8 mdev_port_num; + bool ext; int err; mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num); @@ -421,14 +477,14 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num, mdev_port_num); if (err) goto out; - eth_prot_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, false, - eth_proto_oper); + ext = MLX5_CAP_PCAM_FEATURE(dev->mdev, ptys_extended_ethernet); + eth_prot_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper); props->active_width = IB_WIDTH_4X; props->active_speed = IB_SPEED_QDR; translate_eth_proto_oper(eth_prot_oper, &props->active_speed, - &props->active_width); + &props->active_width, ext); props->port_cap_flags |= IB_PORT_CM_SUP; props->ip_gids = true; -- cgit v1.2.3 From f8ebfaf6684b03084858d8c55f81867e5171af08 Mon Sep 17 00:00:00 2001 From: Jan Sokolowski Date: Wed, 13 Feb 2019 18:07:29 +0100 Subject: net: bpf: remove XDP_QUERY_XSK_UMEM enumerator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit c9b47cc1fabc ("xsk: fix bug when trying to use both copy and zero-copy on one queue id") moved the umem query code to the AF_XDP core, and therefore removed the need to query the netdevice for a umem. This patch removes XDP_QUERY_XSK_UMEM and all code that implement that behavior, which is just dead code. Signed-off-by: Jan Sokolowski Acked-by: Björn Töpel Signed-off-by: Daniel Borkmann --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 --- drivers/net/ethernet/intel/i40e/i40e_xsk.c | 28 ---------------------- drivers/net/ethernet/intel/i40e/i40e_xsk.h | 2 -- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 --- .../net/ethernet/intel/ixgbe/ixgbe_txrx_common.h | 2 -- drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c | 17 ------------- include/linux/netdevice.h | 7 +++--- 7 files changed, 3 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 44856a84738d..5e74a5127849 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -12128,9 +12128,6 @@ static int i40e_xdp(struct net_device *dev, case XDP_QUERY_PROG: xdp->prog_id = vsi->xdp_prog ? vsi->xdp_prog->aux->id : 0; return 0; - case XDP_QUERY_XSK_UMEM: - return i40e_xsk_umem_query(vsi, &xdp->xsk.umem, - xdp->xsk.queue_id); case XDP_SETUP_XSK_UMEM: return i40e_xsk_umem_setup(vsi, xdp->xsk.umem, xdp->xsk.queue_id); diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index 96d849460d9b..e190a2c2b9ff 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -154,34 +154,6 @@ static int i40e_xsk_umem_disable(struct i40e_vsi *vsi, u16 qid) return 0; } -/** - * i40e_xsk_umem_query - Queries a certain ring/qid for its UMEM - * @vsi: Current VSI - * @umem: UMEM associated to the ring, if any - * @qid: Rx ring to associate UMEM to - * - * This function will store, if any, the UMEM associated to certain ring. - * - * Returns 0 on success, <0 on failure - **/ -int i40e_xsk_umem_query(struct i40e_vsi *vsi, struct xdp_umem **umem, - u16 qid) -{ - struct net_device *netdev = vsi->netdev; - struct xdp_umem *queried_umem; - - if (vsi->type != I40E_VSI_MAIN) - return -EINVAL; - - queried_umem = xdp_get_umem_from_qid(netdev, qid); - - if (!queried_umem) - return -EINVAL; - - *umem = queried_umem; - return 0; -} - /** * i40e_xsk_umem_setup - Enable/disassociate a UMEM to/from a ring/qid * @vsi: Current VSI diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.h b/drivers/net/ethernet/intel/i40e/i40e_xsk.h index 9038c5d5cf08..8cc0a2e7d9a2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.h +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.h @@ -10,8 +10,6 @@ struct zero_copy_allocator; int i40e_queue_pair_disable(struct i40e_vsi *vsi, int queue_pair); int i40e_queue_pair_enable(struct i40e_vsi *vsi, int queue_pair); -int i40e_xsk_umem_query(struct i40e_vsi *vsi, struct xdp_umem **umem, - u16 qid); int i40e_xsk_umem_setup(struct i40e_vsi *vsi, struct xdp_umem *umem, u16 qid); void i40e_zca_free(struct zero_copy_allocator *alloc, unsigned long handle); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index b53087a980ef..38c430b94ae3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -10280,9 +10280,6 @@ static int ixgbe_xdp(struct net_device *dev, struct netdev_bpf *xdp) xdp->prog_id = adapter->xdp_prog ? adapter->xdp_prog->aux->id : 0; return 0; - case XDP_QUERY_XSK_UMEM: - return ixgbe_xsk_umem_query(adapter, &xdp->xsk.umem, - xdp->xsk.queue_id); case XDP_SETUP_XSK_UMEM: return ixgbe_xsk_umem_setup(adapter, xdp->xsk.umem, xdp->xsk.queue_id); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h index 53d4089f5644..d93a690aff74 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_txrx_common.h @@ -30,8 +30,6 @@ void ixgbe_txrx_ring_enable(struct ixgbe_adapter *adapter, int ring); struct xdp_umem *ixgbe_xsk_umem(struct ixgbe_adapter *adapter, struct ixgbe_ring *ring); -int ixgbe_xsk_umem_query(struct ixgbe_adapter *adapter, struct xdp_umem **umem, - u16 qid); int ixgbe_xsk_umem_setup(struct ixgbe_adapter *adapter, struct xdp_umem *umem, u16 qid); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c index 65c3e2c979d4..98870707b51a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c @@ -174,23 +174,6 @@ static int ixgbe_xsk_umem_disable(struct ixgbe_adapter *adapter, u16 qid) return 0; } -int ixgbe_xsk_umem_query(struct ixgbe_adapter *adapter, struct xdp_umem **umem, - u16 qid) -{ - if (qid >= adapter->num_rx_queues) - return -EINVAL; - - if (adapter->xsk_umems) { - if (qid >= adapter->num_xsk_umems) - return -EINVAL; - *umem = adapter->xsk_umems[qid]; - return 0; - } - - *umem = NULL; - return 0; -} - int ixgbe_xsk_umem_setup(struct ixgbe_adapter *adapter, struct xdp_umem *umem, u16 qid) { diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1d95e634f3fe..6aedaf1e9a25 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -868,7 +868,6 @@ enum bpf_netdev_command { /* BPF program for offload callbacks, invoked at program load time. */ BPF_OFFLOAD_MAP_ALLOC, BPF_OFFLOAD_MAP_FREE, - XDP_QUERY_XSK_UMEM, XDP_SETUP_XSK_UMEM, }; @@ -895,10 +894,10 @@ struct netdev_bpf { struct { struct bpf_offloaded_map *offmap; }; - /* XDP_QUERY_XSK_UMEM, XDP_SETUP_XSK_UMEM */ + /* XDP_SETUP_XSK_UMEM */ struct { - struct xdp_umem *umem; /* out for query*/ - u16 queue_id; /* in for query */ + struct xdp_umem *umem; + u16 queue_id; } xsk; }; }; -- cgit v1.2.3 From 86b39a66b75f2f360eef56bdb5ac37d5068a9b7d Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Wed, 13 Feb 2019 10:52:34 -0600 Subject: net/mlx5: Correctly set LAG mode for ECPF When bonding is added, driver assumes that it's RoCE LAG if no VF is enabled. This is not enough for ECPF as the VF is enabled in host PF side. LAG should only choose RoCE mode when both slave devices meet conditions below: 1. E-Switch offloads mode is NONE. 2. No VF is enabled. Signed-off-by: Bodong Wang Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/lag.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index 2d223385dc81..04c5aca7f8c5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c @@ -343,6 +343,11 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) roce_lag = !mlx5_sriov_is_enabled(dev0) && !mlx5_sriov_is_enabled(dev1); +#ifdef CONFIG_MLX5_ESWITCH + roce_lag &= dev0->priv.eswitch->mode == SRIOV_NONE && + dev1->priv.eswitch->mode == SRIOV_NONE; +#endif + if (roce_lag) mlx5_lag_remove_ib_devices(ldev); -- cgit v1.2.3 From a1b3839ac4a4933c7c5167efd7b6b091130d11aa Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Thu, 8 Nov 2018 22:37:04 +0200 Subject: net/mlx5: E-Switch, Properly refer to the esw manager vport In SmartNIC mode, the eswitch manager is not necessarily the PF (vport 0). Use a helper function to get the correct eswitch manager vport number and cache on the eswitch instance for fast reference. Signed-off-by: Bodong Wang Signed-off-by: Eli Cohen Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 35 ++++++++++++++-------- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 10 +++++++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 7 +++-- include/linux/mlx5/vport.h | 2 ++ 4 files changed, 39 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 05830696abd8..9c622749dbde 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -378,16 +378,16 @@ static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) u16 vport = vaddr->vport; int err; - /* Skip mlx5_mpfs_add_mac for PFs, - * it is already done by the PF netdev in mlx5e_execute_l2_action + /* Skip mlx5_mpfs_add_mac for eswitch_managers, + * it is already done by its netdev in mlx5e_execute_l2_action */ - if (!vport) + if (esw->manager_vport == vport) goto fdb_add; err = mlx5_mpfs_add_mac(esw->dev, mac); if (err) { esw_warn(esw->dev, - "Failed to add L2 table mac(%pM) for vport(%d), err(%d)\n", + "Failed to add L2 table mac(%pM) for vport(0x%x), err(%d)\n", mac, vport, err); return err; } @@ -410,10 +410,10 @@ static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) u16 vport = vaddr->vport; int err = 0; - /* Skip mlx5_mpfs_del_mac for PFs, - * it is already done by the PF netdev in mlx5e_execute_l2_action + /* Skip mlx5_mpfs_del_mac for eswitch managerss, + * it is already done by its netdev in mlx5e_execute_l2_action */ - if (!vport || !vaddr->mpfs) + if (!vaddr->mpfs || esw->manager_vport == vport) goto fdb_del; err = mlx5_mpfs_del_mac(esw->dev, mac); @@ -1457,15 +1457,22 @@ static void esw_apply_vport_conf(struct mlx5_eswitch *esw, { int vport_num = vport->vport; - if (!vport_num) + if (esw->manager_vport == vport_num) return; mlx5_modify_vport_admin_state(esw->dev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, vport_num, vport->info.link_state); - mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, vport->info.mac); - mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, vport->info.node_guid); + + /* Host PF has its own mac/guid. */ + if (vport_num) { + mlx5_modify_nic_vport_mac_address(esw->dev, vport_num, + vport->info.mac); + mlx5_modify_nic_vport_node_guid(esw->dev, vport_num, + vport->info.node_guid); + } + modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, vport->info.qos, (vport->info.vlan || vport->info.qos)); @@ -1537,8 +1544,11 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, vport->enabled_events = enable_events; vport->enabled = true; - /* only PF is trusted by default */ - if (!vport_num) + /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well + * in smartNIC as it's a vport group manager. + */ + if (esw->manager_vport == vport_num || + (!vport_num && mlx5_core_is_ecpf(esw->dev))) vport->info.trusted = true; esw_vport_change_handle_locked(vport); @@ -1733,6 +1743,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) return -ENOMEM; esw->dev = dev; + esw->manager_vport = mlx5_eswitch_manager_vport(dev); esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq"); if (!esw->work_queue) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 0a3eee8746c1..959a9e28d08f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "lib/mpfs.h" @@ -204,6 +205,7 @@ struct mlx5_eswitch { struct mlx5_esw_offload offloads; int mode; int nvports; + u16 manager_vport; }; void esw_offloads_cleanup(struct mlx5_eswitch *esw, int nvports); @@ -363,6 +365,14 @@ bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, #define esw_debug(dev, format, ...) \ mlx5_core_dbg_mask(dev, MLX5_DEBUG_ESWITCH_MASK, format, ##__VA_ARGS__) + +/* The returned number is valid only when the dev is eswitch manager. */ +static inline u16 mlx5_eswitch_manager_vport(struct mlx5_core_dev *dev) +{ + return mlx5_core_is_ecpf_esw_manager(dev) ? + MLX5_VPORT_ECPF : MLX5_VPORT_PF; +} + #else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 9128b45f3f37..af2c44d31357 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -522,7 +522,8 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn); - MLX5_SET(fte_match_set_misc, misc, source_port, 0x0); /* source vport is 0 */ + /* source vport is the esw manager */ + MLX5_SET(fte_match_set_misc, misc, source_port, esw->manager_vport); misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn); @@ -567,7 +568,7 @@ static void peer_miss_rules_setup(struct mlx5_core_dev *peer_dev, source_eswitch_owner_vhca_id); dest->type = MLX5_FLOW_DESTINATION_TYPE_VPORT; - dest->vport.num = 0; + dest->vport.num = peer_dev->priv.eswitch->manager_vport; dest->vport.vhca_id = MLX5_CAP_GEN(peer_dev, vhca_id); dest->vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID; } @@ -666,7 +667,7 @@ static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw) dmac_c[0] = 0x01; dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; - dest.vport.num = 0; + dest.vport.num = esw->manager_vport; flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, spec, diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index 3bc05449ac39..b67bcc95ab5d 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -52,6 +52,8 @@ enum { }; enum { + MLX5_VPORT_PF = 0x0, + MLX5_VPORT_ECPF = 0xfffe, MLX5_VPORT_UPLINK = 0xffff }; -- cgit v1.2.3 From cbc44e76bfcdcaccd079487367593ee3f94d006d Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Fri, 1 Feb 2019 17:34:55 -0600 Subject: net/mlx5: E-Switch, Properly refer to host PF vport as other vport Commands referring to vports use the following scheme: 1. When referring to my own vport, put 0 in vport and 0 in other_vport. 2. When referring to another vport, put the vport number of the referred vport and put 1 in other_vport. It was assumed that driver is accessing other vport when vport number is greater than 0. With the above scheme, the case that ECPF eswitch manager is trying to access host PF vport will fall over with scheme 1 as the vport number is 0. This is apparently wrong as driver is trying to refer other vport. As such usage can only happen in the eswitch context, change relevant functions to provide other vport input properly. Signed-off-by: Bodong Wang Signed-off-by: Eli Cohen Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 6 ++++-- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 13 ++++++------- drivers/net/ethernet/mellanox/mlx5/core/vport.c | 10 ++++------ include/linux/mlx5/vport.h | 4 ++-- 4 files changed, 16 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 685f1975be58..f84889bbe2a0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1083,7 +1083,8 @@ static int mlx5e_vf_rep_open(struct net_device *dev) if (!mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, - rep->vport, MLX5_VPORT_ADMIN_STATE_UP)) + rep->vport, 1, + MLX5_VPORT_ADMIN_STATE_UP)) netif_carrier_on(dev); unlock: @@ -1101,7 +1102,8 @@ static int mlx5e_vf_rep_close(struct net_device *dev) mutex_lock(&priv->state_lock); mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, - rep->vport, MLX5_VPORT_ADMIN_STATE_DOWN); + rep->vport, 1, + MLX5_VPORT_ADMIN_STATE_DOWN); ret = mlx5e_close_locked(dev); mutex_unlock(&priv->state_lock); return ret; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 9c622749dbde..648c743cc947 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1462,7 +1462,7 @@ static void esw_apply_vport_conf(struct mlx5_eswitch *esw, mlx5_modify_vport_admin_state(esw->dev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, - vport_num, + vport_num, 1, vport->info.link_state); /* Host PF has its own mac/guid. */ @@ -1581,10 +1581,10 @@ static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num) esw_vport_change_handle_locked(vport); vport->enabled_events = 0; esw_vport_disable_qos(esw, vport_num); - if (vport_num && esw->mode == SRIOV_LEGACY) { + if (esw->mode == SRIOV_LEGACY) { mlx5_modify_vport_admin_state(esw->dev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, - vport_num, + vport_num, 1, MLX5_VPORT_ADMIN_STATE_DOWN); esw_vport_disable_egress_acl(esw, vport); esw_vport_disable_ingress_acl(esw, vport); @@ -1875,7 +1875,7 @@ int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, err = mlx5_modify_vport_admin_state(esw->dev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, - vport, link_state); + vport, 1, link_state); if (err) { mlx5_core_warn(esw->dev, "Failed to set vport %d link state, err = %d", @@ -2137,7 +2137,7 @@ static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev, !MLX5_CAP_GEN(dev, transmit_discard_vport_down)) return 0; - err = mlx5_query_vport_down_stats(dev, vport_idx, + err = mlx5_query_vport_down_stats(dev, vport_idx, 1, &rx_discard_vport_down, &tx_discard_vport_down); if (err) @@ -2174,8 +2174,7 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, MLX5_CMD_OP_QUERY_VPORT_COUNTER); MLX5_SET(query_vport_counter_in, in, op_mod, 0); MLX5_SET(query_vport_counter_in, in, vport_number, vport); - if (vport) - MLX5_SET(query_vport_counter_in, in, other_vport, 1); + MLX5_SET(query_vport_counter_in, in, other_vport, 1); memset(out, 0, outlen); err = mlx5_cmd_exec(esw->dev, in, sizeof(in), out, outlen); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index 9a928eb48522..ef95feca9961 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -64,7 +64,7 @@ u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport) } int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, - u16 vport, u8 state) + u16 vport, u8 other_vport, u8 state) { u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] = {0}; u32 out[MLX5_ST_SZ_DW(modify_vport_state_out)] = {0}; @@ -73,8 +73,7 @@ int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, MLX5_CMD_OP_MODIFY_VPORT_STATE); MLX5_SET(modify_vport_state_in, in, op_mod, opmod); MLX5_SET(modify_vport_state_in, in, vport_number, vport); - if (vport) - MLX5_SET(modify_vport_state_in, in, other_vport, 1); + MLX5_SET(modify_vport_state_in, in, other_vport, other_vport); MLX5_SET(modify_vport_state_in, in, admin_state, state); return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); @@ -1057,7 +1056,7 @@ free: EXPORT_SYMBOL_GPL(mlx5_core_query_vport_counter); int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport, - u64 *rx_discard_vport_down, + u8 other_vport, u64 *rx_discard_vport_down, u64 *tx_discard_vport_down) { u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {0}; @@ -1068,8 +1067,7 @@ int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport, MLX5_CMD_OP_QUERY_VNIC_ENV); MLX5_SET(query_vnic_env_in, in, op_mod, 0); MLX5_SET(query_vnic_env_in, in, vport_number, vport); - if (vport) - MLX5_SET(query_vnic_env_in, in, other_vport, 1); + MLX5_SET(query_vnic_env_in, in, other_vport, other_vport); err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out)); if (err) diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index b67bcc95ab5d..b7edcb1dadd8 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -59,7 +59,7 @@ enum { u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport); int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, - u16 vport, u8 state); + u16 vport, u8 other_vport, u8 state); int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev, u16 vport, u8 *addr); int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev, @@ -121,7 +121,7 @@ int mlx5_modify_nic_vport_vlans(struct mlx5_core_dev *dev, int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev); int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev); int mlx5_query_vport_down_stats(struct mlx5_core_dev *mdev, u16 vport, - u64 *rx_discard_vport_down, + u8 other_vport, u64 *rx_discard_vport_down, u64 *tx_discard_vport_down); int mlx5_core_query_vport_counter(struct mlx5_core_dev *dev, u8 other_vport, int vf, u8 port_num, void *out, -- cgit v1.2.3 From eca8cc3895358b4c35a3ed439537b8c08d7dabb3 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Thu, 7 Feb 2019 10:40:58 -0600 Subject: net/mlx5: E-Switch, Refactor offloads flow steering init/cleanup E-switch offloads mode initialize/cleanup multiple steering related entities (flow table/group). Refactor these operations to internal helper functions for better block design. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 43 ++++++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index af2c44d31357..19969d487a01 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -1404,7 +1404,7 @@ static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS); } -int esw_offloads_init(struct mlx5_eswitch *esw, int nvports) +static int esw_offloads_steering_init(struct mlx5_eswitch *esw, int nvports) { int err; @@ -1422,16 +1422,8 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int nvports) if (err) goto create_fg_err; - err = esw_offloads_load_reps(esw, nvports); - if (err) - goto err_reps; - - esw_offloads_devcom_init(esw); return 0; -err_reps: - esw_destroy_vport_rx_group(esw); - create_fg_err: esw_destroy_offloads_table(esw); @@ -1441,6 +1433,35 @@ create_ft_err: return err; } +static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw) +{ + esw_destroy_vport_rx_group(esw); + esw_destroy_offloads_table(esw); + esw_destroy_offloads_fdb_tables(esw); +} + +int esw_offloads_init(struct mlx5_eswitch *esw, int nvports) +{ + int err; + + mutex_init(&esw->fdb_table.offloads.fdb_prio_lock); + + err = esw_offloads_steering_init(esw, nvports); + if (err) + return err; + + err = esw_offloads_load_reps(esw, nvports); + if (err) + goto err_reps; + + esw_offloads_devcom_init(esw); + return 0; + +err_reps: + esw_offloads_steering_cleanup(esw); + return err; +} + static int esw_offloads_stop(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack) { @@ -1464,9 +1485,7 @@ void esw_offloads_cleanup(struct mlx5_eswitch *esw, int nvports) { esw_offloads_devcom_cleanup(esw); esw_offloads_unload_reps(esw, nvports); - esw_destroy_vport_rx_group(esw); - esw_destroy_offloads_table(esw); - esw_destroy_offloads_fdb_tables(esw); + esw_offloads_steering_cleanup(esw); } static int esw_mode_from_devlink(u16 mode, u16 *mlx5_mode) -- cgit v1.2.3 From c9b99abcf232f69ddff158b1f313fd7d2654414b Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Thu, 31 Jan 2019 14:40:53 -0600 Subject: net/mlx5: E-Switch, Split VF and special vports for offloads mode When driver is entering offloads mode, there are two major tasks to do: initialize flow steering and create representors. Flow steering should make sure enough flow table/group spaces are reserved for all reps. Representors will be created in a group, all or none. With the introduction of ECPF, flow steering should still reserve the same spaces. But, the representors are not always loaded/unloaded in a single piece. Once ECPF is in offloads mode, it will get the number of VF changing event from host PF. In such scenario, only the VF reps should be loaded/unloaded, not the reps for special vports (such as the uplink vport). Thus, when entering offloads mode, driver should specify the total number of reps, and the number of VF reps separately. When leaving offloads mode, the cleanup should use the information self-contained in eswitch such as number of VFs. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 7 ++- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 5 +- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 57 ++++++++++++++++------ include/linux/mlx5/vport.h | 1 + 4 files changed, 48 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 648c743cc947..be6c2931d2a0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1641,7 +1641,8 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) } else { mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH); mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB); - err = esw_offloads_init(esw, nvfs + MLX5_SPECIAL_VPORTS); + err = esw_offloads_init(esw, nvfs, + nvfs + MLX5_SPECIAL_VPORTS); } if (err) @@ -1683,7 +1684,6 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) { struct esw_mc_addr *mc_promisc; int old_mode; - int nvports; int i; if (!ESW_ALLOWED(esw) || esw->mode == SRIOV_NONE) @@ -1693,7 +1693,6 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) esw->enabled_vports, esw->mode); mc_promisc = &esw->mc_promisc; - nvports = esw->enabled_vports; if (esw->mode == SRIOV_LEGACY) mlx5_eq_notifier_unregister(esw->dev, &esw->nb); @@ -1709,7 +1708,7 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) if (esw->mode == SRIOV_LEGACY) esw_destroy_legacy_fdb_table(esw); else if (esw->mode == SRIOV_OFFLOADS) - esw_offloads_cleanup(esw, nvports); + esw_offloads_cleanup(esw); old_mode = esw->mode; esw->mode = SRIOV_NONE; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 959a9e28d08f..fd845e6c44d5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -208,8 +208,9 @@ struct mlx5_eswitch { u16 manager_vport; }; -void esw_offloads_cleanup(struct mlx5_eswitch *esw, int nvports); -int esw_offloads_init(struct mlx5_eswitch *esw, int nvports); +void esw_offloads_cleanup(struct mlx5_eswitch *esw); +int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports, + int total_nvports); void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw); int esw_offloads_init_reps(struct mlx5_eswitch *esw); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 19969d487a01..14f7ad67cfe4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -54,6 +54,8 @@ enum { #define fdb_prio_table(esw, chain, prio, level) \ (esw)->fdb_table.offloads.fdb_prio[(chain)][(prio)][(level)] +#define UPLINK_REP_INDEX 0 + static struct mlx5_flow_table * esw_get_prio_table(struct mlx5_eswitch *esw, u32 chain, u16 prio, int level); static void @@ -1239,19 +1241,28 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) return 0; } +static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw, + struct mlx5_eswitch_rep *rep, u8 rep_type) +{ + if (!rep->rep_if[rep_type].valid) + return; + + rep->rep_if[rep_type].unload(rep); +} + static void esw_offloads_unload_reps_type(struct mlx5_eswitch *esw, int nvports, u8 rep_type) { struct mlx5_eswitch_rep *rep; int vport; - for (vport = nvports - 1; vport >= 0; vport--) { + for (vport = nvports; vport >= MLX5_VPORT_FIRST_VF; vport--) { rep = &esw->offloads.vport_reps[vport]; - if (!rep->rep_if[rep_type].valid) - continue; - - rep->rep_if[rep_type].unload(rep); + __esw_offloads_unload_rep(esw, rep, rep_type); } + + rep = &esw->offloads.vport_reps[UPLINK_REP_INDEX]; + __esw_offloads_unload_rep(esw, rep, rep_type); } static void esw_offloads_unload_reps(struct mlx5_eswitch *esw, int nvports) @@ -1262,6 +1273,15 @@ static void esw_offloads_unload_reps(struct mlx5_eswitch *esw, int nvports) esw_offloads_unload_reps_type(esw, nvports, rep_type); } +static int __esw_offloads_load_rep(struct mlx5_eswitch *esw, + struct mlx5_eswitch_rep *rep, u8 rep_type) +{ + if (!rep->rep_if[rep_type].valid) + return 0; + + return rep->rep_if[rep_type].load(esw->dev, rep); +} + static int esw_offloads_load_reps_type(struct mlx5_eswitch *esw, int nvports, u8 rep_type) { @@ -1269,12 +1289,14 @@ static int esw_offloads_load_reps_type(struct mlx5_eswitch *esw, int nvports, int vport; int err; - for (vport = 0; vport < nvports; vport++) { - rep = &esw->offloads.vport_reps[vport]; - if (!rep->rep_if[rep_type].valid) - continue; + rep = &esw->offloads.vport_reps[UPLINK_REP_INDEX]; + err = __esw_offloads_load_rep(esw, rep, rep_type); + if (err) + goto out; - err = rep->rep_if[rep_type].load(esw->dev, rep); + for (vport = MLX5_VPORT_FIRST_VF; vport <= nvports; vport++) { + rep = &esw->offloads.vport_reps[vport]; + err = __esw_offloads_load_rep(esw, rep, rep_type); if (err) goto err_reps; } @@ -1283,6 +1305,7 @@ static int esw_offloads_load_reps_type(struct mlx5_eswitch *esw, int nvports, err_reps: esw_offloads_unload_reps_type(esw, vport, rep_type); +out: return err; } @@ -1440,17 +1463,18 @@ static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw) esw_destroy_offloads_fdb_tables(esw); } -int esw_offloads_init(struct mlx5_eswitch *esw, int nvports) +int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports, + int total_nvports) { int err; mutex_init(&esw->fdb_table.offloads.fdb_prio_lock); - err = esw_offloads_steering_init(esw, nvports); + err = esw_offloads_steering_init(esw, total_nvports); if (err) return err; - err = esw_offloads_load_reps(esw, nvports); + err = esw_offloads_load_reps(esw, vf_nvports); if (err) goto err_reps; @@ -1481,10 +1505,12 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, return err; } -void esw_offloads_cleanup(struct mlx5_eswitch *esw, int nvports) +void esw_offloads_cleanup(struct mlx5_eswitch *esw) { + u16 num_vfs = esw->dev->priv.sriov.num_vfs; + esw_offloads_devcom_cleanup(esw); - esw_offloads_unload_reps(esw, nvports); + esw_offloads_unload_reps(esw, num_vfs); esw_offloads_steering_cleanup(esw); } @@ -1822,7 +1848,6 @@ EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_rep); void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type) { -#define UPLINK_REP_INDEX 0 struct mlx5_esw_offload *offloads = &esw->offloads; struct mlx5_eswitch_rep *rep; diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index b7edcb1dadd8..755aeea19e1c 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -53,6 +53,7 @@ enum { enum { MLX5_VPORT_PF = 0x0, + MLX5_VPORT_FIRST_VF = 0x1, MLX5_VPORT_ECPF = 0xfffe, MLX5_VPORT_UPLINK = 0xffff }; -- cgit v1.2.3 From 879c8f84e3602961e441723aaaac372a44dfe588 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Mon, 28 Jan 2019 22:12:45 -0600 Subject: net/mlx5: E-Switch, Use getter and iterator to access vport/rep With only PF and VF, it is sufficient to have the vport/rep array index as the vport number. This is because PF and VF vports numbers are consecutive serial numbers. In downstream patches with introducing of ECPF and UPLINK vports, it's not consecutive any more. Use getter to get specific vport/rep, and use iterator to traversal a list of vport/rep. This hides the translation between array index and vport number, and provides flexibility of using different translation mechanism in the future. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Suggested-by: Saeed Mahameed Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 94 ++++++++++++++-------- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 75 +++++++++++------ 2 files changed, 113 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index be6c2931d2a0..d1454f18c0a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -68,6 +68,26 @@ enum { MC_ADDR_CHANGE | \ PROMISC_CHANGE) +/* The vport getter/iterator are only valid after esw->total_vports + * and vport->vport are initialized in mlx5_eswitch_init. + */ +#define mlx5_esw_for_all_vports(esw, i, vport) \ + for ((i) = MLX5_VPORT_PF; \ + (vport) = &(esw)->vports[i], \ + (i) < (esw)->total_vports; (i)++) + +#define mlx5_esw_for_each_vf_vport(esw, i, vport, nvfs) \ + for ((i) = MLX5_VPORT_FIRST_VF; \ + (vport) = &(esw)->vports[i], \ + (i) <= (nvfs); (i)++) + +static struct mlx5_vport *mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, + u16 vport_num) +{ + WARN_ON(vport_num > esw->total_vports - 1); + return &esw->vports[vport_num]; +} + static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport, u32 events_mask) { @@ -436,17 +456,18 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw, struct esw_mc_addr *esw_mc) { u8 *mac = vaddr->node.addr; - u16 vport_idx = 0; + struct mlx5_vport *vport; + u16 i, vport_num; - for (vport_idx = 0; vport_idx < esw->total_vports; vport_idx++) { - struct mlx5_vport *vport = &esw->vports[vport_idx]; + mlx5_esw_for_all_vports(esw, i, vport) { struct hlist_head *vport_hash = vport->mc_list; struct vport_addr *iter_vaddr = l2addr_hash_find(vport_hash, mac, struct vport_addr); + vport_num = vport->vport; if (IS_ERR_OR_NULL(vport->allmulti_rule) || - vaddr->vport == vport_idx) + vaddr->vport == vport_num) continue; switch (vaddr->action) { case MLX5_ACTION_ADD: @@ -458,14 +479,14 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw, if (!iter_vaddr) { esw_warn(esw->dev, "ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n", - mac, vport_idx); + mac, vport_num); continue; } - iter_vaddr->vport = vport_idx; + iter_vaddr->vport = vport_num; iter_vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, - vport_idx); + vport_num); iter_vaddr->mc_promisc = true; break; case MLX5_ACTION_DEL: @@ -564,7 +585,7 @@ static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw, u16 vport_num, int list_type) { - struct mlx5_vport *vport = &esw->vports[vport_num]; + struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC; vport_addr_action vport_addr_add; vport_addr_action vport_addr_del; @@ -599,7 +620,7 @@ static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw, static void esw_update_vport_addr_list(struct mlx5_eswitch *esw, u16 vport_num, int list_type) { - struct mlx5_vport *vport = &esw->vports[vport_num]; + struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC; u8 (*mac_list)[ETH_ALEN]; struct l2addr_node *node; @@ -686,7 +707,7 @@ out: */ static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u16 vport_num) { - struct mlx5_vport *vport = &esw->vports[vport_num]; + struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); struct l2addr_node *node; struct vport_addr *addr; struct hlist_head *hash; @@ -722,8 +743,8 @@ static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw, u16 vport_num) static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw, u16 vport_num, bool promisc, bool mc_promisc) { + struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); struct esw_mc_addr *allmulti_addr = &esw->mc_promisc; - struct mlx5_vport *vport = &esw->vports[vport_num]; if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc) goto promisc; @@ -764,7 +785,7 @@ promisc: /* Sync vport rx mode from vport context */ static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw, u16 vport_num) { - struct mlx5_vport *vport = &esw->vports[vport_num]; + struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); int promisc_all = 0; int promisc_uc = 0; int promisc_mc = 0; @@ -1341,8 +1362,8 @@ static void esw_destroy_tsar(struct mlx5_eswitch *esw) static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num, u32 initial_max_rate, u32 initial_bw_share) { + struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; - struct mlx5_vport *vport = &esw->vports[vport_num]; struct mlx5_core_dev *dev = esw->dev; void *vport_elem; int err = 0; @@ -1381,7 +1402,7 @@ static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num, static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num) { - struct mlx5_vport *vport = &esw->vports[vport_num]; + struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); int err = 0; if (!vport->qos.enabled) @@ -1400,8 +1421,8 @@ static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num) static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num, u32 max_rate, u32 bw_share) { + struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num); u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; - struct mlx5_vport *vport = &esw->vports[vport_num]; struct mlx5_core_dev *dev = esw->dev; void *vport_elem; u32 bitmask = 0; @@ -1518,10 +1539,10 @@ static void esw_vport_destroy_drop_counters(struct mlx5_vport *vport) mlx5_fc_destroy(dev, vport->egress.drop_counter); } -static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, +static void esw_enable_vport(struct mlx5_eswitch *esw, struct mlx5_vport *vport, int enable_events) { - struct mlx5_vport *vport = &esw->vports[vport_num]; + u16 vport_num = vport->vport; mutex_lock(&esw->state_lock); WARN_ON(vport->enabled); @@ -1558,9 +1579,10 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num, mutex_unlock(&esw->state_lock); } -static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num) +static void esw_disable_vport(struct mlx5_eswitch *esw, + struct mlx5_vport *vport) { - struct mlx5_vport *vport = &esw->vports[vport_num]; + u16 vport_num = vport->vport; if (!vport->enabled) return; @@ -1603,7 +1625,7 @@ static int eswitch_vport_event(struct notifier_block *nb, u16 vport_num; vport_num = be16_to_cpu(eqe->data.vport_change.vport_num); - vport = &esw->vports[vport_num]; + vport = mlx5_eswitch_get_vport(esw, vport_num); if (vport->enabled) queue_work(esw->work_queue, &vport->vport_change_handler); @@ -1615,6 +1637,7 @@ static int eswitch_vport_event(struct notifier_block *nb, int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) { + struct mlx5_vport *vport; int err; int i, enabled_events; @@ -1657,8 +1680,14 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) * 2. FDB/Eswitch is programmed by user space tools */ enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : 0; - for (i = 0; i <= nvfs; i++) - esw_enable_vport(esw, i, enabled_events); + + /* Enable PF vport */ + vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); + esw_enable_vport(esw, vport, enabled_events); + + /* Enable VF vports */ + mlx5_esw_for_each_vf_vport(esw, i, vport, nvfs) + esw_enable_vport(esw, vport, enabled_events); if (mode == SRIOV_LEGACY) { MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); @@ -1683,6 +1712,7 @@ abort: void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) { struct esw_mc_addr *mc_promisc; + struct mlx5_vport *vport; int old_mode; int i; @@ -1697,8 +1727,8 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) if (esw->mode == SRIOV_LEGACY) mlx5_eq_notifier_unregister(esw->dev, &esw->nb); - for (i = 0; i < esw->total_vports; i++) - esw_disable_vport(esw, i); + mlx5_esw_for_all_vports(esw, i, vport) + esw_disable_vport(esw, vport); if (mc_promisc && mc_promisc->uplink_rule) mlx5_del_flow_rules(mc_promisc->uplink_rule); @@ -1725,6 +1755,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) { int total_vports = MLX5_TOTAL_VPORTS(dev); struct mlx5_eswitch *esw; + struct mlx5_vport *vport; int vport_num; int err; @@ -1757,6 +1788,8 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) goto abort; } + esw->total_vports = total_vports; + err = esw_offloads_init_reps(esw); if (err) goto abort; @@ -1765,9 +1798,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) hash_init(esw->offloads.mod_hdr_tbl); mutex_init(&esw->state_lock); - for (vport_num = 0; vport_num < total_vports; vport_num++) { - struct mlx5_vport *vport = &esw->vports[vport_num]; - + mlx5_esw_for_all_vports(esw, vport_num, vport) { vport->vport = vport_num; vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; vport->dev = dev; @@ -1775,7 +1806,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) esw_vport_change_handler); } - esw->total_vports = total_vports; esw->enabled_vports = 0; esw->mode = SRIOV_NONE; esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE; @@ -2017,8 +2047,7 @@ static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw) u32 max_guarantee = 0; int i; - for (i = 0; i < esw->total_vports; i++) { - evport = &esw->vports[i]; + mlx5_esw_for_all_vports(esw, i, evport) { if (!evport->enabled || evport->info.min_rate < max_guarantee) continue; max_guarantee = evport->info.min_rate; @@ -2037,8 +2066,7 @@ static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider) int err; int i; - for (i = 0; i < esw->total_vports; i++) { - evport = &esw->vports[i]; + mlx5_esw_for_all_vports(esw, i, evport) { if (!evport->enabled) continue; vport_min_rate = evport->info.min_rate; @@ -2053,7 +2081,7 @@ static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider) if (bw_share == evport->qos.bw_share) continue; - err = esw_vport_qos_config(esw, i, vport_max_rate, + err = esw_vport_qos_config(esw, evport->vport, vport_max_rate, bw_share); if (!err) evport->qos.bw_share = bw_share; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 14f7ad67cfe4..4979c7ee0ad7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -56,6 +56,44 @@ enum { #define UPLINK_REP_INDEX 0 +/* The rep getter/iterator are only valid after esw->total_vports + * and vport->vport are initialized in mlx5_eswitch_init. + */ +#define mlx5_esw_for_all_reps(esw, i, rep) \ + for ((i) = MLX5_VPORT_PF; \ + (rep) = &(esw)->offloads.vport_reps[i], \ + (i) < (esw)->total_vports; (i)++) + +#define mlx5_esw_for_each_vf_rep(esw, i, rep, nvfs) \ + for ((i) = MLX5_VPORT_FIRST_VF; \ + (rep) = &(esw)->offloads.vport_reps[i], \ + (i) <= (nvfs); (i)++) + +#define mlx5_esw_for_each_vf_rep_reverse(esw, i, rep, nvfs) \ + for ((i) = (nvfs); \ + (rep) = &(esw)->offloads.vport_reps[i], \ + (i) >= MLX5_VPORT_FIRST_VF; (i)--) + +#define mlx5_esw_for_each_vf_vport(esw, vport, nvfs) \ + for ((vport) = MLX5_VPORT_FIRST_VF; \ + (vport) <= (nvfs); (vport)++) + +#define mlx5_esw_for_each_vf_vport_reverse(esw, vport, nvfs) \ + for ((vport) = (nvfs); \ + (vport) >= MLX5_VPORT_FIRST_VF; (vport)--) + +static struct mlx5_eswitch_rep *mlx5_eswitch_get_rep(struct mlx5_eswitch *esw, + u16 vport_num) +{ + u16 idx = vport_num; + + if (vport_num == MLX5_VPORT_UPLINK) + idx = UPLINK_REP_INDEX; + + WARN_ON(idx > esw->total_vports - 1); + return &esw->offloads.vport_reps[idx]; +} + static struct mlx5_flow_table * esw_get_prio_table(struct mlx5_eswitch *esw, u32 chain, u16 prio, int level); static void @@ -604,7 +642,7 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); - for (i = 1; i < nvports; i++) { + mlx5_esw_for_each_vf_vport(esw, i, mlx5_core_max_vfs(esw->dev)) { MLX5_SET(fte_match_set_misc, misc, source_port, i); flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, spec, &flow_act, &dest, 1); @@ -622,7 +660,8 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, return 0; add_flow_err: - for (i--; i > 0; i--) + nvports = --i; + mlx5_esw_for_each_vf_vport_reverse(esw, i, nvports) mlx5_del_flow_rules(flows[i]); kvfree(flows); alloc_flows_err: @@ -637,7 +676,7 @@ static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw) flows = esw->fdb_table.offloads.peer_miss_rules; - for (i = 1; i < esw->total_vports; i++) + mlx5_esw_for_each_vf_vport_reverse(esw, i, mlx5_core_max_vfs(esw->dev)) mlx5_del_flow_rules(flows[i]); kvfree(flows); @@ -1229,9 +1268,7 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) offloads = &esw->offloads; mlx5_query_nic_vport_mac_address(dev, 0, hw_id); - for (vport = 0; vport < total_vfs; vport++) { - rep = &offloads->vport_reps[vport]; - + mlx5_esw_for_all_reps(esw, vport, rep) { rep->vport = vport; ether_addr_copy(rep->hw_id, hw_id); } @@ -1256,12 +1293,10 @@ static void esw_offloads_unload_reps_type(struct mlx5_eswitch *esw, int nvports, struct mlx5_eswitch_rep *rep; int vport; - for (vport = nvports; vport >= MLX5_VPORT_FIRST_VF; vport--) { - rep = &esw->offloads.vport_reps[vport]; + mlx5_esw_for_each_vf_rep_reverse(esw, vport, rep, nvports) __esw_offloads_unload_rep(esw, rep, rep_type); - } - rep = &esw->offloads.vport_reps[UPLINK_REP_INDEX]; + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); __esw_offloads_unload_rep(esw, rep, rep_type); } @@ -1289,13 +1324,12 @@ static int esw_offloads_load_reps_type(struct mlx5_eswitch *esw, int nvports, int vport; int err; - rep = &esw->offloads.vport_reps[UPLINK_REP_INDEX]; + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); err = __esw_offloads_load_rep(esw, rep, rep_type); if (err) goto out; - for (vport = MLX5_VPORT_FIRST_VF; vport <= nvports; vport++) { - rep = &esw->offloads.vport_reps[vport]; + mlx5_esw_for_each_vf_rep(esw, vport, rep, nvports) { err = __esw_offloads_load_rep(esw, rep, rep_type); if (err) goto err_reps; @@ -1304,7 +1338,7 @@ static int esw_offloads_load_reps_type(struct mlx5_eswitch *esw, int nvports, return 0; err_reps: - esw_offloads_unload_reps_type(esw, vport, rep_type); + esw_offloads_unload_reps_type(esw, --vport, rep_type); out: return err; } @@ -1848,10 +1882,9 @@ EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_rep); void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type) { - struct mlx5_esw_offload *offloads = &esw->offloads; struct mlx5_eswitch_rep *rep; - rep = &offloads->vport_reps[UPLINK_REP_INDEX]; + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); return rep->rep_if[rep_type].priv; } @@ -1859,13 +1892,9 @@ void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw, int vport, u8 rep_type) { - struct mlx5_esw_offload *offloads = &esw->offloads; struct mlx5_eswitch_rep *rep; - if (vport == MLX5_VPORT_UPLINK) - vport = UPLINK_REP_INDEX; - - rep = &offloads->vport_reps[vport]; + rep = mlx5_eswitch_get_rep(esw, vport); if (rep->rep_if[rep_type].valid && rep->rep_if[rep_type].get_proto_dev) @@ -1876,13 +1905,13 @@ EXPORT_SYMBOL(mlx5_eswitch_get_proto_dev); void *mlx5_eswitch_uplink_get_proto_dev(struct mlx5_eswitch *esw, u8 rep_type) { - return mlx5_eswitch_get_proto_dev(esw, UPLINK_REP_INDEX, rep_type); + return mlx5_eswitch_get_proto_dev(esw, MLX5_VPORT_UPLINK, rep_type); } EXPORT_SYMBOL(mlx5_eswitch_uplink_get_proto_dev); struct mlx5_eswitch_rep *mlx5_eswitch_vport_rep(struct mlx5_eswitch *esw, int vport) { - return &esw->offloads.vport_reps[vport]; + return mlx5_eswitch_get_rep(esw, vport); } EXPORT_SYMBOL(mlx5_eswitch_vport_rep); -- cgit v1.2.3 From f121e0ea9586b2c937bf1ff9a0b682dc6424ce1d Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 29 Jan 2019 21:48:31 -0600 Subject: net/mlx5: E-Switch, Add state to eswitch vport representors Currently the eswitch vport reps have a valid indicator, which is set on register and unset on unregister. However, a rep can be loaded or not loaded when doing unregister, current driver checks if the vport of that rep is enabled as a flag to imply the rep is loaded. However, for ECPF, this is not valid as the host PF will enable the vports for its VFs instead. Add three states: {unregistered, registered, loaded}, with the following state changes across different operations: create: (none) -> unregistered reg: unregistered -> registered load: registered -> loaded unload: loaded -> registered unreg: registered -> unregistered Note that the state shall only be updated inside eswitch driver rather than individual drivers such as ETH or IB. Signed-off-by: Bodong Wang Signed-off-by: Or Gerlitz Suggested-by: Mark Bloch Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 31 +++++++++++++++------- include/linux/mlx5/eswitch.h | 8 +++++- 2 files changed, 29 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 4979c7ee0ad7..c6c9dad69ba8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -364,7 +364,7 @@ static int esw_set_global_vlan_pop(struct mlx5_eswitch *esw, u8 val) esw_debug(esw->dev, "%s applying global %s policy\n", __func__, val ? "pop" : "none"); for (vf_vport = 1; vf_vport < esw->enabled_vports; vf_vport++) { rep = &esw->offloads.vport_reps[vf_vport]; - if (!rep->rep_if[REP_ETH].valid) + if (rep->rep_if[REP_ETH].state != REP_LOADED) continue; err = __mlx5_eswitch_set_vport_vlan(esw, rep->vport, 0, 0, val); @@ -1256,7 +1256,7 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) struct mlx5_core_dev *dev = esw->dev; struct mlx5_esw_offload *offloads; struct mlx5_eswitch_rep *rep; - u8 hw_id[ETH_ALEN]; + u8 hw_id[ETH_ALEN], rep_type; int vport; esw->offloads.vport_reps = kcalloc(total_vfs, @@ -1271,6 +1271,9 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) mlx5_esw_for_all_reps(esw, vport, rep) { rep->vport = vport; ether_addr_copy(rep->hw_id, hw_id); + + for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) + rep->rep_if[rep_type].state = REP_UNREGISTERED; } offloads->vport_reps[0].vport = MLX5_VPORT_UPLINK; @@ -1281,10 +1284,11 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, u8 rep_type) { - if (!rep->rep_if[rep_type].valid) + if (rep->rep_if[rep_type].state != REP_LOADED) return; rep->rep_if[rep_type].unload(rep); + rep->rep_if[rep_type].state = REP_REGISTERED; } static void esw_offloads_unload_reps_type(struct mlx5_eswitch *esw, int nvports, @@ -1311,10 +1315,18 @@ static void esw_offloads_unload_reps(struct mlx5_eswitch *esw, int nvports) static int __esw_offloads_load_rep(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, u8 rep_type) { - if (!rep->rep_if[rep_type].valid) + int err = 0; + + if (rep->rep_if[rep_type].state != REP_REGISTERED) return 0; - return rep->rep_if[rep_type].load(esw->dev, rep); + err = rep->rep_if[rep_type].load(esw->dev, rep); + if (err) + return err; + + rep->rep_if[rep_type].state = REP_LOADED; + + return 0; } static int esw_offloads_load_reps_type(struct mlx5_eswitch *esw, int nvports, @@ -1861,7 +1873,7 @@ void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw, rep_if->get_proto_dev = __rep_if->get_proto_dev; rep_if->priv = __rep_if->priv; - rep_if->valid = true; + rep_if->state = REP_REGISTERED; } EXPORT_SYMBOL(mlx5_eswitch_register_vport_rep); @@ -1873,10 +1885,11 @@ void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw, rep = &offloads->vport_reps[vport_index]; - if (esw->mode == SRIOV_OFFLOADS && esw->vports[vport_index].enabled) + if (esw->mode == SRIOV_OFFLOADS && + rep->rep_if[rep_type].state == REP_LOADED) rep->rep_if[rep_type].unload(rep); - rep->rep_if[rep_type].valid = false; + rep->rep_if[rep_type].state = REP_UNREGISTERED; } EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_rep); @@ -1896,7 +1909,7 @@ void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw, rep = mlx5_eswitch_get_rep(esw, vport); - if (rep->rep_if[rep_type].valid && + if (rep->rep_if[rep_type].state == REP_LOADED && rep->rep_if[rep_type].get_proto_dev) return rep->rep_if[rep_type].get_proto_dev(rep); return NULL; diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h index fab5121ffb8f..e3dbc1bc0917 100644 --- a/include/linux/mlx5/eswitch.h +++ b/include/linux/mlx5/eswitch.h @@ -22,6 +22,12 @@ enum { NUM_REP_TYPES, }; +enum { + REP_UNREGISTERED, + REP_REGISTERED, + REP_LOADED, +}; + struct mlx5_eswitch_rep; struct mlx5_eswitch_rep_if { int (*load)(struct mlx5_core_dev *dev, @@ -29,7 +35,7 @@ struct mlx5_eswitch_rep_if { void (*unload)(struct mlx5_eswitch_rep *rep); void *(*get_proto_dev)(struct mlx5_eswitch_rep *rep); void *priv; - bool valid; + u8 state; }; struct mlx5_eswitch_rep { -- cgit v1.2.3 From 29d9fd7d5a667b120f8228da3d8a8d1b2382538d Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 29 Jan 2019 22:57:21 -0600 Subject: net/mlx5: E-Switch, Support load/unload reps of specific vport types Currently the driver loads and unloads all reps in an unbreakable group. However, with ECPF, the reps of special vports such as uplink and host PF should always be loaded in switchdev mode where the reps for VFs will be loaded on-demand and unloaded on no-demand. This is a pre-step for that change. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 109 ++++++++++++++++----- 1 file changed, 87 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index c6c9dad69ba8..7131d41796fb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -1291,25 +1291,47 @@ static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw, rep->rep_if[rep_type].state = REP_REGISTERED; } -static void esw_offloads_unload_reps_type(struct mlx5_eswitch *esw, int nvports, - u8 rep_type) +static void __unload_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type) { struct mlx5_eswitch_rep *rep; - int vport; - - mlx5_esw_for_each_vf_rep_reverse(esw, vport, rep, nvports) - __esw_offloads_unload_rep(esw, rep, rep_type); rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); __esw_offloads_unload_rep(esw, rep, rep_type); } -static void esw_offloads_unload_reps(struct mlx5_eswitch *esw, int nvports) +static void __unload_reps_vf_vport(struct mlx5_eswitch *esw, int nvports, + u8 rep_type) +{ + struct mlx5_eswitch_rep *rep; + int i; + + mlx5_esw_for_each_vf_rep_reverse(esw, i, rep, nvports) + __esw_offloads_unload_rep(esw, rep, rep_type); +} + +static void esw_offloads_unload_vf_reps(struct mlx5_eswitch *esw, int nvports) +{ + u8 rep_type = NUM_REP_TYPES; + + while (rep_type-- > 0) + __unload_reps_vf_vport(esw, nvports, rep_type); +} + +static void __unload_reps_all_vport(struct mlx5_eswitch *esw, int nvports, + u8 rep_type) +{ + __unload_reps_vf_vport(esw, nvports, rep_type); + + /* Special vports must be the last to unload. */ + __unload_reps_special_vport(esw, rep_type); +} + +static void esw_offloads_unload_all_reps(struct mlx5_eswitch *esw, int nvports) { u8 rep_type = NUM_REP_TYPES; while (rep_type-- > 0) - esw_offloads_unload_reps_type(esw, nvports, rep_type); + __unload_reps_all_vport(esw, nvports, rep_type); } static int __esw_offloads_load_rep(struct mlx5_eswitch *esw, @@ -1329,39 +1351,82 @@ static int __esw_offloads_load_rep(struct mlx5_eswitch *esw, return 0; } -static int esw_offloads_load_reps_type(struct mlx5_eswitch *esw, int nvports, - u8 rep_type) +static int __load_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type) { struct mlx5_eswitch_rep *rep; - int vport; int err; rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); err = __esw_offloads_load_rep(esw, rep, rep_type); - if (err) - goto out; + return err; +} - mlx5_esw_for_each_vf_rep(esw, vport, rep, nvports) { +static int __load_reps_vf_vport(struct mlx5_eswitch *esw, int nvports, + u8 rep_type) +{ + struct mlx5_eswitch_rep *rep; + int err, i; + + mlx5_esw_for_each_vf_rep(esw, i, rep, nvports) { err = __esw_offloads_load_rep(esw, rep, rep_type); if (err) - goto err_reps; + goto err_vf; } return 0; +err_vf: + __unload_reps_vf_vport(esw, --i, rep_type); + return err; +} + +static int esw_offloads_load_vf_reps(struct mlx5_eswitch *esw, int nvports) +{ + u8 rep_type = 0; + int err; + + for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) { + err = __load_reps_vf_vport(esw, nvports, rep_type); + if (err) + goto err_reps; + } + + return err; + err_reps: - esw_offloads_unload_reps_type(esw, --vport, rep_type); -out: + while (rep_type-- > 0) + __unload_reps_vf_vport(esw, nvports, rep_type); + return err; +} + +static int __load_reps_all_vport(struct mlx5_eswitch *esw, int nvports, + u8 rep_type) +{ + int err; + + /* Special vports must be loaded first. */ + err = __load_reps_special_vport(esw, rep_type); + if (err) + return err; + + err = __load_reps_vf_vport(esw, nvports, rep_type); + if (err) + goto err_vfs; + + return 0; + +err_vfs: + __unload_reps_special_vport(esw, rep_type); return err; } -static int esw_offloads_load_reps(struct mlx5_eswitch *esw, int nvports) +static int esw_offloads_load_all_reps(struct mlx5_eswitch *esw, int nvports) { u8 rep_type = 0; int err; for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) { - err = esw_offloads_load_reps_type(esw, nvports, rep_type); + err = __load_reps_all_vport(esw, nvports, rep_type); if (err) goto err_reps; } @@ -1370,7 +1435,7 @@ static int esw_offloads_load_reps(struct mlx5_eswitch *esw, int nvports) err_reps: while (rep_type-- > 0) - esw_offloads_unload_reps_type(esw, nvports, rep_type); + __unload_reps_all_vport(esw, nvports, rep_type); return err; } @@ -1520,7 +1585,7 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports, if (err) return err; - err = esw_offloads_load_reps(esw, vf_nvports); + err = esw_offloads_load_all_reps(esw, vf_nvports); if (err) goto err_reps; @@ -1556,7 +1621,7 @@ void esw_offloads_cleanup(struct mlx5_eswitch *esw) u16 num_vfs = esw->dev->priv.sriov.num_vfs; esw_offloads_devcom_cleanup(esw); - esw_offloads_unload_reps(esw, num_vfs); + esw_offloads_unload_all_reps(esw, num_vfs); esw_offloads_steering_cleanup(esw); } -- cgit v1.2.3 From f8e8fa0262eaf544490a11746c524333158ef0b6 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Thu, 31 Jan 2019 17:42:57 -0600 Subject: net/mlx5: E-Switch, Centralize repersentor reg/unreg to eswitch driver Eswitch has two users: IB and ETH. They both register repersentors when mlx5 interface is added, and unregister the repersentors when mlx5 interface is removed. Ideally, each driver should only deal with the entities which are unique to itself. However, current IB and ETH drivers have to perform the following eswitch operations: 1. When registering, specify how many vports to register. This number is the same for both drivers which is the total available vport numbers. 2. When unregistering, specify the number of registered vports to do unregister. Also, unload the repersentors which are already loaded. It's unnecessary for eswitch driver to hands out the control of above operations to individual driver users, as they're not unique to each driver. Instead, such operations should be centralized to eswitch driver. This consolidates eswitch control flow, and simplified IB and ETH driver. This patch doesn't change any functionality. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/infiniband/hw/mlx5/ib_rep.c | 20 ++++------ drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 19 +++------ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 45 +++++++++++----------- include/linux/mlx5/eswitch.h | 11 ++---- 4 files changed, 39 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c index 99cae9a10195..4700cffb5a00 100644 --- a/drivers/infiniband/hw/mlx5/ib_rep.c +++ b/drivers/infiniband/hw/mlx5/ib_rep.c @@ -95,26 +95,20 @@ static void *mlx5_ib_vport_get_proto_dev(struct mlx5_eswitch_rep *rep) void mlx5_ib_register_vport_reps(struct mlx5_core_dev *mdev) { struct mlx5_eswitch *esw = mdev->priv.eswitch; - int total_vports = MLX5_TOTAL_VPORTS(mdev); struct mlx5_eswitch_rep_if rep_if = {}; - int vport; - - for (vport = 0; vport < total_vports; vport++) { - rep_if.load = mlx5_ib_vport_rep_load; - rep_if.unload = mlx5_ib_vport_rep_unload; - rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev; - mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_IB); - } + + rep_if.load = mlx5_ib_vport_rep_load; + rep_if.unload = mlx5_ib_vport_rep_unload; + rep_if.get_proto_dev = mlx5_ib_vport_get_proto_dev; + + mlx5_eswitch_register_vport_reps(esw, &rep_if, REP_IB); } void mlx5_ib_unregister_vport_reps(struct mlx5_core_dev *mdev) { struct mlx5_eswitch *esw = mdev->priv.eswitch; - int total_vports = MLX5_TOTAL_VPORTS(mdev); - int vport; - for (vport = total_vports - 1; vport >= 0; vport--) - mlx5_eswitch_unregister_vport_rep(esw, vport, REP_IB); + mlx5_eswitch_unregister_vport_reps(esw, REP_IB); } u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index f84889bbe2a0..287d48e5b073 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1798,25 +1798,18 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep) void mlx5e_rep_register_vport_reps(struct mlx5_core_dev *mdev) { struct mlx5_eswitch *esw = mdev->priv.eswitch; - int total_vfs = MLX5_TOTAL_VPORTS(mdev); - int vport; + struct mlx5_eswitch_rep_if rep_if = {}; - for (vport = 0; vport < total_vfs; vport++) { - struct mlx5_eswitch_rep_if rep_if = {}; + rep_if.load = mlx5e_vport_rep_load; + rep_if.unload = mlx5e_vport_rep_unload; + rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev; - rep_if.load = mlx5e_vport_rep_load; - rep_if.unload = mlx5e_vport_rep_unload; - rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev; - mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_ETH); - } + mlx5_eswitch_register_vport_reps(esw, &rep_if, REP_ETH); } void mlx5e_rep_unregister_vport_reps(struct mlx5_core_dev *mdev) { struct mlx5_eswitch *esw = mdev->priv.eswitch; - int total_vfs = MLX5_TOTAL_VPORTS(mdev); - int vport; - for (vport = total_vfs - 1; vport >= 0; vport--) - mlx5_eswitch_unregister_vport_rep(esw, vport, REP_ETH); + mlx5_eswitch_unregister_vport_reps(esw, REP_ETH); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 7131d41796fb..b702b56c457e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -1923,40 +1923,39 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, u8 *encap) return 0; } -void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw, - int vport_index, - struct mlx5_eswitch_rep_if *__rep_if, - u8 rep_type) +void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw, + struct mlx5_eswitch_rep_if *__rep_if, + u8 rep_type) { - struct mlx5_esw_offload *offloads = &esw->offloads; struct mlx5_eswitch_rep_if *rep_if; + struct mlx5_eswitch_rep *rep; + int i; - rep_if = &offloads->vport_reps[vport_index].rep_if[rep_type]; - - rep_if->load = __rep_if->load; - rep_if->unload = __rep_if->unload; - rep_if->get_proto_dev = __rep_if->get_proto_dev; - rep_if->priv = __rep_if->priv; + mlx5_esw_for_all_reps(esw, i, rep) { + rep_if = &rep->rep_if[rep_type]; + rep_if->load = __rep_if->load; + rep_if->unload = __rep_if->unload; + rep_if->get_proto_dev = __rep_if->get_proto_dev; + rep_if->priv = __rep_if->priv; - rep_if->state = REP_REGISTERED; + rep_if->state = REP_REGISTERED; + } } -EXPORT_SYMBOL(mlx5_eswitch_register_vport_rep); +EXPORT_SYMBOL(mlx5_eswitch_register_vport_reps); -void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw, - int vport_index, u8 rep_type) +void mlx5_eswitch_unregister_vport_reps(struct mlx5_eswitch *esw, u8 rep_type) { - struct mlx5_esw_offload *offloads = &esw->offloads; + u16 max_vf = mlx5_core_max_vfs(esw->dev); struct mlx5_eswitch_rep *rep; + int i; - rep = &offloads->vport_reps[vport_index]; - - if (esw->mode == SRIOV_OFFLOADS && - rep->rep_if[rep_type].state == REP_LOADED) - rep->rep_if[rep_type].unload(rep); + if (esw->mode == SRIOV_OFFLOADS) + __unload_reps_all_vport(esw, max_vf, rep_type); - rep->rep_if[rep_type].state = REP_UNREGISTERED; + mlx5_esw_for_all_reps(esw, i, rep) + rep->rep_if[rep_type].state = REP_UNREGISTERED; } -EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_rep); +EXPORT_SYMBOL(mlx5_eswitch_unregister_vport_reps); void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type) { diff --git a/include/linux/mlx5/eswitch.h b/include/linux/mlx5/eswitch.h index e3dbc1bc0917..96d8435421de 100644 --- a/include/linux/mlx5/eswitch.h +++ b/include/linux/mlx5/eswitch.h @@ -46,13 +46,10 @@ struct mlx5_eswitch_rep { u32 vlan_refcount; }; -void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw, - int vport_index, - struct mlx5_eswitch_rep_if *rep_if, - u8 rep_type); -void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw, - int vport_index, - u8 rep_type); +void mlx5_eswitch_register_vport_reps(struct mlx5_eswitch *esw, + struct mlx5_eswitch_rep_if *rep_if, + u8 rep_type); +void mlx5_eswitch_unregister_vport_reps(struct mlx5_eswitch *esw, u8 rep_type); void *mlx5_eswitch_get_proto_dev(struct mlx5_eswitch *esw, int vport, u8 rep_type); -- cgit v1.2.3 From 5ae5162066d8e59e365678a9e76fc4d8f6b78d40 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Fri, 14 Dec 2018 09:33:22 -0600 Subject: net/mlx5: E-Switch, Assign a different position for uplink rep and vport In offloads mode, the current implementation puts the uplink representor at index zero of the vport reps array. It is not "natural" to place it at index 0 since we want to put the representor for vport 0 at index 0 with the introduction of SmartNIC. A separate patch will handle the case whether a rep is needed for vport 0 (PF vport). So, we want to have a different placeholder for uplink vport and representor. It was placed at the end of vport and rep array. Since vport number can no longer act as an index into the vport or representors arrays, use functions to map vport numbers to indices when accessing the vports or representors arrays, and vice versa. Signed-off-by: Bodong Wang Signed-off-by: Eli Cohen Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 11 +++++----- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 24 ++++++++++++++++++++++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 11 ++-------- include/linux/mlx5/vport.h | 11 +++++++--- 4 files changed, 40 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index d1454f18c0a7..bb7f72467df9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -84,8 +84,10 @@ enum { static struct mlx5_vport *mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num) { + u16 idx = mlx5_eswitch_vport_num_to_index(esw, vport_num); + WARN_ON(vport_num > esw->total_vports - 1); - return &esw->vports[vport_num]; + return &esw->vports[idx]; } static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport, @@ -1756,8 +1758,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) int total_vports = MLX5_TOTAL_VPORTS(dev); struct mlx5_eswitch *esw; struct mlx5_vport *vport; - int vport_num; - int err; + int err, i; if (!MLX5_VPORT_MANAGER(dev)) return 0; @@ -1798,8 +1799,8 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) hash_init(esw->offloads.mod_hdr_tbl); mutex_init(&esw->state_lock); - mlx5_esw_for_all_vports(esw, vport_num, vport) { - vport->vport = vport_num; + mlx5_esw_for_all_vports(esw, i, vport) { + vport->vport = mlx5_eswitch_index_to_vport_num(esw, i); vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; vport->dev = dev; INIT_WORK(&vport->vport_change_handler, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index fd845e6c44d5..2951c1296c3e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -374,6 +374,30 @@ static inline u16 mlx5_eswitch_manager_vport(struct mlx5_core_dev *dev) MLX5_VPORT_ECPF : MLX5_VPORT_PF; } +static inline int mlx5_eswitch_uplink_idx(struct mlx5_eswitch *esw) +{ + /* Uplink always locate at the last element of the array.*/ + return esw->total_vports - 1; +} + +static inline int mlx5_eswitch_vport_num_to_index(struct mlx5_eswitch *esw, + u16 vport_num) +{ + if (vport_num == MLX5_VPORT_UPLINK) + return mlx5_eswitch_uplink_idx(esw); + + return vport_num; +} + +static inline int mlx5_eswitch_index_to_vport_num(struct mlx5_eswitch *esw, + int index) +{ + if (index == mlx5_eswitch_uplink_idx(esw)) + return MLX5_VPORT_UPLINK; + + return index; +} + #else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index b702b56c457e..e787e9212174 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -85,10 +85,7 @@ enum { static struct mlx5_eswitch_rep *mlx5_eswitch_get_rep(struct mlx5_eswitch *esw, u16 vport_num) { - u16 idx = vport_num; - - if (vport_num == MLX5_VPORT_UPLINK) - idx = UPLINK_REP_INDEX; + u16 idx = mlx5_eswitch_vport_num_to_index(esw, vport_num); WARN_ON(idx > esw->total_vports - 1); return &esw->offloads.vport_reps[idx]; @@ -1254,7 +1251,6 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) { int total_vfs = MLX5_TOTAL_VPORTS(esw->dev); struct mlx5_core_dev *dev = esw->dev; - struct mlx5_esw_offload *offloads; struct mlx5_eswitch_rep *rep; u8 hw_id[ETH_ALEN], rep_type; int vport; @@ -1265,19 +1261,16 @@ int esw_offloads_init_reps(struct mlx5_eswitch *esw) if (!esw->offloads.vport_reps) return -ENOMEM; - offloads = &esw->offloads; mlx5_query_nic_vport_mac_address(dev, 0, hw_id); mlx5_esw_for_all_reps(esw, vport, rep) { - rep->vport = vport; + rep->vport = mlx5_eswitch_index_to_vport_num(esw, vport); ether_addr_copy(rep->hw_id, hw_id); for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) rep->rep_if[rep_type].state = REP_UNREGISTERED; } - offloads->vport_reps[0].vport = MLX5_VPORT_UPLINK; - return 0; } diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index 755aeea19e1c..134248c02786 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -36,9 +36,14 @@ #include #include -#define MLX5_VPORT_PF_PLACEHOLDER (1u) -#define MLX5_SPECIAL_VPORTS (MLX5_VPORT_PF_PLACEHOLDER) -#define MLX5_TOTAL_VPORTS(mdev) (MLX5_SPECIAL_VPORTS + mlx5_core_max_vfs(mdev)) +#define MLX5_VPORT_PF_PLACEHOLDER (1u) +#define MLX5_VPORT_UPLINK_PLACEHOLDER (1u) + +#define MLX5_SPECIAL_VPORTS (MLX5_VPORT_PF_PLACEHOLDER + \ + MLX5_VPORT_UPLINK_PLACEHOLDER) + +#define MLX5_TOTAL_VPORTS(mdev) (MLX5_SPECIAL_VPORTS + \ + mlx5_core_max_vfs(mdev)) #define MLX5_VPORT_MANAGER(mdev) \ (MLX5_CAP_GEN(mdev, vport_group_manager) && \ -- cgit v1.2.3 From 81cd229c294e2e416e9161d9286d34f3aaf19348 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Mon, 10 Dec 2018 11:59:33 -0600 Subject: net/mlx5: E-Switch, Consider ECPF vport depends on eswitch ownership ECPF connects to the eswitch through vport 0xfffe. ECPF may or may not be the eswitch manager depending on firmware configuration. 1. If ECPF is eswitch manager: ECPF will take over the eswitch manager responsibility. A rep of the host PF shall be created at the ECPF side for the eswitch manager to control. 2. If ECPF is not eswitch manager: host PF will be the eswitch manager, ECPF acts similar as a VF to the host PF. Host PF will be aware of the ECPF vport presence and control it's rep. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 8 ++- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 15 ++++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 79 +++++++++++++++++++++- include/linux/mlx5/driver.h | 5 ++ include/linux/mlx5/mlx5_ifc.h | 3 +- include/linux/mlx5/vport.h | 8 ++- 6 files changed, 110 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index bb7f72467df9..d2ab1ee19b2a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1667,7 +1667,7 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH); mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB); err = esw_offloads_init(esw, nvfs, - nvfs + MLX5_SPECIAL_VPORTS); + nvfs + MLX5_SPECIAL_VPORTS(esw->dev)); } if (err) @@ -1687,6 +1687,12 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); esw_enable_vport(esw, vport, enabled_events); + /* Enable ECPF vports */ + if (mlx5_ecpf_vport_exists(esw->dev)) { + vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF); + esw_enable_vport(esw, vport, enabled_events); + } + /* Enable VF vports */ mlx5_esw_for_each_vf_vport(esw, i, vport, nvfs) esw_enable_vport(esw, vport, enabled_events); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 2951c1296c3e..2baa0d71380c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -380,9 +380,20 @@ static inline int mlx5_eswitch_uplink_idx(struct mlx5_eswitch *esw) return esw->total_vports - 1; } +static inline int mlx5_eswitch_ecpf_idx(struct mlx5_eswitch *esw) +{ + return esw->total_vports - 2; +} + static inline int mlx5_eswitch_vport_num_to_index(struct mlx5_eswitch *esw, u16 vport_num) { + if (vport_num == MLX5_VPORT_ECPF) { + if (!mlx5_ecpf_vport_exists(esw->dev)) + esw_warn(esw->dev, "ECPF vport doesn't exist!\n"); + return mlx5_eswitch_ecpf_idx(esw); + } + if (vport_num == MLX5_VPORT_UPLINK) return mlx5_eswitch_uplink_idx(esw); @@ -392,6 +403,10 @@ static inline int mlx5_eswitch_vport_num_to_index(struct mlx5_eswitch *esw, static inline int mlx5_eswitch_index_to_vport_num(struct mlx5_eswitch *esw, int index) { + if (index == mlx5_eswitch_ecpf_idx(esw) && + mlx5_ecpf_vport_exists(esw->dev)) + return MLX5_VPORT_ECPF; + if (index == mlx5_eswitch_uplink_idx(esw)) return MLX5_VPORT_UPLINK; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index e787e9212174..84a33f8e3350 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -639,14 +639,35 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { + MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_PF); + flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, + spec, &flow_act, &dest, 1); + if (IS_ERR(flow)) { + err = PTR_ERR(flow); + goto add_pf_flow_err; + } + flows[MLX5_VPORT_PF] = flow; + } + + if (mlx5_ecpf_vport_exists(esw->dev)) { + MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_ECPF); + flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, + spec, &flow_act, &dest, 1); + if (IS_ERR(flow)) { + err = PTR_ERR(flow); + goto add_ecpf_flow_err; + } + flows[mlx5_eswitch_ecpf_idx(esw)] = flow; + } + mlx5_esw_for_each_vf_vport(esw, i, mlx5_core_max_vfs(esw->dev)) { MLX5_SET(fte_match_set_misc, misc, source_port, i); flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, spec, &flow_act, &dest, 1); if (IS_ERR(flow)) { err = PTR_ERR(flow); - esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err); - goto add_flow_err; + goto add_vf_flow_err; } flows[i] = flow; } @@ -656,10 +677,18 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, kvfree(spec); return 0; -add_flow_err: +add_vf_flow_err: nvports = --i; mlx5_esw_for_each_vf_vport_reverse(esw, i, nvports) mlx5_del_flow_rules(flows[i]); + + if (mlx5_ecpf_vport_exists(esw->dev)) + mlx5_del_flow_rules(flows[mlx5_eswitch_ecpf_idx(esw)]); +add_ecpf_flow_err: + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) + mlx5_del_flow_rules(flows[MLX5_VPORT_PF]); +add_pf_flow_err: + esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err); kvfree(flows); alloc_flows_err: kvfree(spec); @@ -676,6 +705,12 @@ static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw) mlx5_esw_for_each_vf_vport_reverse(esw, i, mlx5_core_max_vfs(esw->dev)) mlx5_del_flow_rules(flows[i]); + if (mlx5_ecpf_vport_exists(esw->dev)) + mlx5_del_flow_rules(flows[mlx5_eswitch_ecpf_idx(esw)]); + + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) + mlx5_del_flow_rules(flows[MLX5_VPORT_PF]); + kvfree(flows); } @@ -1288,6 +1323,16 @@ static void __unload_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type) { struct mlx5_eswitch_rep *rep; + if (mlx5_ecpf_vport_exists(esw->dev)) { + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF); + __esw_offloads_unload_rep(esw, rep, rep_type); + } + + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF); + __esw_offloads_unload_rep(esw, rep, rep_type); + } + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); __esw_offloads_unload_rep(esw, rep, rep_type); } @@ -1351,6 +1396,34 @@ static int __load_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type) rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); err = __esw_offloads_load_rep(esw, rep, rep_type); + if (err) + return err; + + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF); + err = __esw_offloads_load_rep(esw, rep, rep_type); + if (err) + goto err_pf; + } + + if (mlx5_ecpf_vport_exists(esw->dev)) { + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF); + err = __esw_offloads_load_rep(esw, rep, rep_type); + if (err) + goto err_ecpf; + } + + return 0; + +err_ecpf: + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF); + __esw_offloads_unload_rep(esw, rep, rep_type); + } + +err_pf: + rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); + __esw_offloads_unload_rep(esw, rep, rep_type); return err; } diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index c5454f985e1d..c2de50f02b33 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -1088,6 +1088,11 @@ static inline bool mlx5_core_is_ecpf_esw_manager(struct mlx5_core_dev *dev) return dev->caps.embedded_cpu && MLX5_CAP_GEN(dev, eswitch_manager); } +static inline bool mlx5_ecpf_vport_exists(struct mlx5_core_dev *dev) +{ + return mlx5_core_is_pf(dev) && MLX5_CAP_ESW(dev, ecpf_vport_exists); +} + #define MLX5_HOST_PF_MAX_VFS (127u) static inline u16 mlx5_core_max_vfs(struct mlx5_core_dev *dev) { diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 5decffe565fb..b7bb774b57b0 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -631,7 +631,8 @@ struct mlx5_ifc_e_switch_cap_bits { u8 vport_svlan_insert[0x1]; u8 vport_cvlan_insert_if_not_exist[0x1]; u8 vport_cvlan_insert_overwrite[0x1]; - u8 reserved_at_5[0x17]; + u8 reserved_at_5[0x16]; + u8 ecpf_vport_exists[0x1]; u8 counter_eswitch_affinity[0x1]; u8 merged_eswitch[0x1]; u8 nic_vport_node_guid_modify[0x1]; diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index 134248c02786..0eef548b9946 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -38,11 +38,13 @@ #define MLX5_VPORT_PF_PLACEHOLDER (1u) #define MLX5_VPORT_UPLINK_PLACEHOLDER (1u) +#define MLX5_VPORT_ECPF_PLACEHOLDER(mdev) (mlx5_ecpf_vport_exists(mdev)) -#define MLX5_SPECIAL_VPORTS (MLX5_VPORT_PF_PLACEHOLDER + \ - MLX5_VPORT_UPLINK_PLACEHOLDER) +#define MLX5_SPECIAL_VPORTS(mdev) (MLX5_VPORT_PF_PLACEHOLDER + \ + MLX5_VPORT_UPLINK_PLACEHOLDER + \ + MLX5_VPORT_ECPF_PLACEHOLDER(mdev)) -#define MLX5_TOTAL_VPORTS(mdev) (MLX5_SPECIAL_VPORTS + \ +#define MLX5_TOTAL_VPORTS(mdev) (MLX5_SPECIAL_VPORTS(mdev) + \ mlx5_core_max_vfs(mdev)) #define MLX5_VPORT_MANAGER(mdev) \ -- cgit v1.2.3 From a3888f33db9f55f401ad315481af251d168e57dd Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Tue, 29 Jan 2019 23:13:13 -0600 Subject: net/mlx5: E-Switch, Load/unload VF reps according to event from host PF When host PF changes the number of VFs, the ECPF esw driver will get a FW event. It should query the number of VFs enabled by host PF and update the VF reps accordingly. Note that host PF can't change the number of VFs dynamically, it has to reset the number of VFs to 0 before changing to a new positive number. The host event is registered when driver is moving to switchdev mode, and it's the last step to do in esw_offloads_init. It's unregistered and the work queue is flushed when driver quits from switchdev mode. In this way, the host event and devlink command are serialized. When driver is enabling switchdev mode, pay attention to the following two facts: 1. Host PF must not have VF initialized as the flow table in ECPF has ENCAP enabled as default. Such flow table can't be created with existing initialized VFs. 2. ECPF doesn't know how many VFs the host PF will enable, ECPF offloads flow steering shall create the flow table/groups based on the max number of VFs possibly supported by host PF. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 17 +++++- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 11 ++++ .../ethernet/mellanox/mlx5/core/eswitch_offloads.c | 71 +++++++++++++++++++++- 3 files changed, 96 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index d2ab1ee19b2a..e18af31336e6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -39,6 +39,7 @@ #include "lib/eq.h" #include "eswitch.h" #include "fs_core.h" +#include "ecpf.h" enum { MLX5_ACTION_NONE = 0, @@ -1639,6 +1640,7 @@ static int eswitch_vport_event(struct notifier_block *nb, int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) { + int vf_nvports = 0, total_nvports = 0; struct mlx5_vport *vport; int err; int i, enabled_events; @@ -1657,6 +1659,18 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) esw_info(esw->dev, "E-Switch enable SRIOV: nvfs(%d) mode (%d)\n", nvfs, mode); + if (mode == SRIOV_OFFLOADS) { + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { + err = mlx5_query_host_params_num_vfs(esw->dev, &vf_nvports); + if (err) + return err; + total_nvports = esw->total_vports; + } else { + vf_nvports = nvfs; + total_nvports = nvfs + MLX5_SPECIAL_VPORTS(esw->dev); + } + } + esw->mode = mode; mlx5_lag_update(esw->dev); @@ -1666,8 +1680,7 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) } else { mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH); mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB); - err = esw_offloads_init(esw, nvfs, - nvfs + MLX5_SPECIAL_VPORTS(esw->dev)); + err = esw_offloads_init(esw, vf_nvports, total_nvports); } if (err) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 2baa0d71380c..af5581a57e56 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -182,6 +182,16 @@ struct esw_mc_addr { /* SRIOV only */ u32 refcnt; }; +struct mlx5_host_work { + struct work_struct work; + struct mlx5_eswitch *esw; +}; + +struct mlx5_host_info { + struct mlx5_nb nb; + u16 num_vfs; +}; + struct mlx5_eswitch { struct mlx5_core_dev *dev; struct mlx5_nb nb; @@ -206,6 +216,7 @@ struct mlx5_eswitch { int mode; int nvports; u16 manager_vport; + struct mlx5_host_info host_info; }; void esw_offloads_cleanup(struct mlx5_eswitch *esw); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 84a33f8e3350..91c4095ac79e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -40,6 +40,8 @@ #include "en.h" #include "fs_core.h" #include "lib/devcom.h" +#include "ecpf.h" +#include "lib/eq.h" enum { FDB_FAST_PATH = 0, @@ -1640,6 +1642,57 @@ static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw) esw_destroy_offloads_fdb_tables(esw); } +static void esw_host_params_event_handler(struct work_struct *work) +{ + struct mlx5_host_work *host_work; + struct mlx5_eswitch *esw; + int err, num_vf = 0; + + host_work = container_of(work, struct mlx5_host_work, work); + esw = host_work->esw; + + err = mlx5_query_host_params_num_vfs(esw->dev, &num_vf); + if (err || num_vf == esw->host_info.num_vfs) + goto out; + + /* Number of VFs can only change from "0 to x" or "x to 0". */ + if (esw->host_info.num_vfs > 0) { + esw_offloads_unload_vf_reps(esw, esw->host_info.num_vfs); + } else { + err = esw_offloads_load_vf_reps(esw, num_vf); + + if (err) + goto out; + } + + esw->host_info.num_vfs = num_vf; + +out: + kfree(host_work); +} + +static int esw_host_params_event(struct notifier_block *nb, + unsigned long type, void *data) +{ + struct mlx5_host_work *host_work; + struct mlx5_host_info *host_info; + struct mlx5_eswitch *esw; + + host_work = kzalloc(sizeof(*host_work), GFP_ATOMIC); + if (!host_work) + return NOTIFY_DONE; + + host_info = mlx5_nb_cof(nb, struct mlx5_host_info, nb); + esw = container_of(host_info, struct mlx5_eswitch, host_info); + + host_work->esw = esw; + + INIT_WORK(&host_work->work, esw_host_params_event_handler); + queue_work(esw->work_queue, &host_work->work); + + return NOTIFY_OK; +} + int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports, int total_nvports) { @@ -1656,6 +1709,14 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int vf_nvports, goto err_reps; esw_offloads_devcom_init(esw); + + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { + MLX5_NB_INIT(&esw->host_info.nb, esw_host_params_event, + HOST_PARAMS_CHANGE); + mlx5_eq_notifier_register(esw->dev, &esw->host_info.nb); + esw->host_info.num_vfs = vf_nvports; + } + return 0; err_reps: @@ -1684,7 +1745,15 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, void esw_offloads_cleanup(struct mlx5_eswitch *esw) { - u16 num_vfs = esw->dev->priv.sriov.num_vfs; + u16 num_vfs; + + if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { + mlx5_eq_notifier_unregister(esw->dev, &esw->host_info.nb); + flush_workqueue(esw->work_queue); + num_vfs = esw->host_info.num_vfs; + } else { + num_vfs = esw->dev->priv.sriov.num_vfs; + } esw_offloads_devcom_cleanup(esw); esw_offloads_unload_all_reps(esw, num_vfs); -- cgit v1.2.3 From c96692fb8f3d0a161c6892ab9cc51a5e9992ccf2 Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Thu, 20 Dec 2018 17:28:06 -0600 Subject: net/mlx5: E-Switch, Allow transition to offloads mode for ECPF Currently, the e-switch driver requires going to legacy mode before changing to the offloads mode. This makes sense for regular case as the legacy mode is done by creating VFs. However, it's problematic when ECPF is the eswitch manager. In such case, ECPF will control the vports on peer host including the peer PF and VFs. But ECPF doesn't need and shall not create VFs as the VFs are created in the peer PF host. Grant ECPF the ability to change from none to the offloads mode. Note that currently the only way to go back to none mode is by unloading the ECPF driver. Signed-off-by: Bodong Wang Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 91c4095ac79e..f2260391be5b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -1250,7 +1250,8 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, { int err, err1, num_vfs = esw->dev->priv.sriov.num_vfs; - if (esw->mode != SRIOV_LEGACY) { + if (esw->mode != SRIOV_LEGACY && + !mlx5_core_is_ecpf_esw_manager(esw->dev)) { NL_SET_ERR_MSG_MOD(extack, "Can't set offloads mode, SRIOV legacy not enabled"); return -EINVAL; @@ -1846,7 +1847,8 @@ static int mlx5_devlink_eswitch_check(struct devlink *devlink) if(!MLX5_ESWITCH_MANAGER(dev)) return -EPERM; - if (dev->priv.eswitch->mode == SRIOV_NONE) + if (dev->priv.eswitch->mode == SRIOV_NONE && + !mlx5_core_is_ecpf_esw_manager(dev)) return -EOPNOTSUPP; return 0; -- cgit v1.2.3 From 59e6158acafa2fc80160d8a8241c2a715fe89cff Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 15 Feb 2019 15:11:53 +0000 Subject: mlxsw: core: fix spelling mistake "temprature" -> "temperature" There is a spelling mistake in several dev_err messages, fix these. Signed-off-by: Colin Ian King Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index f1ada4cdbd6b..6956bbebe2f1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -208,7 +208,7 @@ static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev, 1); err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); if (err) { - dev_err(dev, "Failed to query module temprature sensor\n"); + dev_err(dev, "Failed to query module temperature sensor\n"); return err; } @@ -251,7 +251,7 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, 1); err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); if (err) { - dev_err(dev, "Failed to query module temprature sensor\n"); + dev_err(dev, "Failed to query module temperature sensor\n"); return err; } @@ -291,7 +291,7 @@ mlxsw_hwmon_module_temp_critical_show(struct device *dev, err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, SFP_TEMP_HIGH_WARN, &temp); if (err) { - dev_err(dev, "Failed to query module temprature thresholds\n"); + dev_err(dev, "Failed to query module temperature thresholds\n"); return err; } @@ -314,7 +314,7 @@ mlxsw_hwmon_module_temp_emergency_show(struct device *dev, err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, SFP_TEMP_HIGH_ALARM, &temp); if (err) { - dev_err(dev, "Failed to query module temprature thresholds\n"); + dev_err(dev, "Failed to query module temperature thresholds\n"); return err; } -- cgit v1.2.3 From 0aa35a368933873dbab2d2ab54e5d05d3b089245 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 15 Feb 2019 19:22:25 +0100 Subject: s390/qeth: allow manual recovery when device is SOFTSETUP Once a qeth ccwgroup device is set online, it's also armed for internal recovery. So allow for testing that code path via sysfs, regardless of whether the interface is up or down. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 30f61608fa22..485a335669ba 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -316,7 +316,7 @@ static ssize_t qeth_dev_recover_store(struct device *dev, if (!card) return -EINVAL; - if (card->state != CARD_STATE_UP) + if (!qeth_card_hw_is_reachable(card)) return -EPERM; i = simple_strtoul(buf, &tmp, 16); -- cgit v1.2.3 From bb92d3f8667f674ae6b2150406f19b33d5ad5f85 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 15 Feb 2019 19:22:26 +0100 Subject: s390/qeth: use a static Output Queue array qeth dynamically allocates an array for storing pointers to its Output Queue structures. Switch this to a static array - we are currently limited to 4 Output Queues, so shrinking the qeth_qdio_info struct by just a few bytes doesn't justify the additional complexity. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 2 +- drivers/s390/net/qeth_core_main.c | 21 ++++++--------------- 2 files changed, 7 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 18696ffb662d..2ea5d7c0b94c 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -528,7 +528,7 @@ struct qeth_qdio_info { /* output */ int no_out_queues; - struct qeth_qdio_out_q **out_qs; + struct qeth_qdio_out_q *out_qs[QETH_MAX_QUEUES]; struct qdio_outbuf_state *out_bufstates; /* priority queueing */ diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 5ca934775c42..d01a4aded4cc 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2433,12 +2433,6 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card) goto out_freeinq; /* outbound */ - card->qdio.out_qs = - kcalloc(card->qdio.no_out_queues, - sizeof(struct qeth_qdio_out_q *), - GFP_KERNEL); - if (!card->qdio.out_qs) - goto out_freepool; for (i = 0; i < card->qdio.no_out_queues; ++i) { card->qdio.out_qs[i] = qeth_alloc_qdio_out_buf(); if (!card->qdio.out_qs[i]) @@ -2468,11 +2462,10 @@ out_freeoutqbufs: card->qdio.out_qs[i]->bufs[j] = NULL; } out_freeoutq: - while (i > 0) + while (i > 0) { qeth_free_output_queue(card->qdio.out_qs[--i]); - kfree(card->qdio.out_qs); - card->qdio.out_qs = NULL; -out_freepool: + card->qdio.out_qs[i] = NULL; + } qeth_free_buffer_pool(card); out_freeinq: qeth_free_qdio_queue(card->qdio.in_q); @@ -2501,11 +2494,9 @@ static void qeth_free_qdio_buffers(struct qeth_card *card) /* inbound buffer pool */ qeth_free_buffer_pool(card); /* free outbound qdio_qs */ - if (card->qdio.out_qs) { - for (i = 0; i < card->qdio.no_out_queues; i++) - qeth_free_output_queue(card->qdio.out_qs[i]); - kfree(card->qdio.out_qs); - card->qdio.out_qs = NULL; + for (i = 0; i < card->qdio.no_out_queues; i++) { + qeth_free_output_queue(card->qdio.out_qs[i]); + card->qdio.out_qs[i] = NULL; } } -- cgit v1.2.3 From 4326b5b4616bd6b4b1a1c09961a383b4fceed20c Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 15 Feb 2019 19:22:27 +0100 Subject: s390/qeth: reduce ethtool statistics Counting the number of function calls and the time spent in functions is best left to proper tracing facilities. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 29 ------------- drivers/s390/net/qeth_core_main.c | 85 ++++----------------------------------- drivers/s390/net/qeth_l2_main.c | 8 ---- drivers/s390/net/qeth_l3_main.c | 8 ---- 4 files changed, 7 insertions(+), 123 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 2ea5d7c0b94c..9928728649eb 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -126,30 +126,6 @@ struct qeth_perf_stats { unsigned int sc_dp_p; unsigned int sc_p_dp; - /* qdio_cq_handler: number of times called, time spent in */ - __u64 cq_start_time; - unsigned int cq_cnt; - unsigned int cq_time; - /* qdio_input_handler: number of times called, time spent in */ - __u64 inbound_start_time; - unsigned int inbound_cnt; - unsigned int inbound_time; - /* qeth_send_packet: number of times called, time spent in */ - __u64 outbound_start_time; - unsigned int outbound_cnt; - unsigned int outbound_time; - /* qdio_output_handler: number of times called, time spent in */ - __u64 outbound_handler_start_time; - unsigned int outbound_handler_cnt; - unsigned int outbound_handler_time; - /* number of calls to and time spent in do_QDIO for inbound queue */ - __u64 inbound_do_qdio_start_time; - unsigned int inbound_do_qdio_cnt; - unsigned int inbound_do_qdio_time; - /* number of calls to and time spent in do_QDIO for outbound queues */ - __u64 outbound_do_qdio_start_time; - unsigned int outbound_do_qdio_cnt; - unsigned int outbound_do_qdio_time; unsigned int large_send_bytes; unsigned int large_send_cnt; unsigned int sg_skbs_sent; @@ -859,11 +835,6 @@ static inline int qeth_get_elements_for_range(addr_t start, addr_t end) return PFN_UP(end) - PFN_DOWN(start); } -static inline int qeth_get_micros(void) -{ - return (int) (get_tod_clock() >> 12); -} - static inline int qeth_get_ip_version(struct sk_buff *skb) { struct vlan_ethhdr *veth = vlan_eth_hdr(skb); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d01a4aded4cc..e3127e232fb2 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3244,17 +3244,8 @@ static void qeth_queue_input_buffer(struct qeth_card *card, int index) * 'index') un-requeued -> this buffer is the first buffer that * will be requeued the next time */ - if (card->options.performance_stats) { - card->perf_stats.inbound_do_qdio_cnt++; - card->perf_stats.inbound_do_qdio_start_time = - qeth_get_micros(); - } rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, queue->next_buf_to_init, count); - if (card->options.performance_stats) - card->perf_stats.inbound_do_qdio_time += - qeth_get_micros() - - card->perf_stats.inbound_do_qdio_start_time; if (rc) { QETH_CARD_TEXT(card, 2, "qinberr"); } @@ -3407,22 +3398,12 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, } netif_trans_update(queue->card->dev); - if (queue->card->options.performance_stats) { - queue->card->perf_stats.outbound_do_qdio_cnt++; - queue->card->perf_stats.outbound_do_qdio_start_time = - qeth_get_micros(); - } qdio_flags = QDIO_FLAG_SYNC_OUTPUT; if (atomic_read(&queue->set_pci_flags_count)) qdio_flags |= QDIO_FLAG_PCI_OUT; atomic_add(count, &queue->used_buffers); - rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags, queue->queue_no, index, count); - if (queue->card->options.performance_stats) - queue->card->perf_stats.outbound_do_qdio_time += - qeth_get_micros() - - queue->card->perf_stats.outbound_do_qdio_start_time; if (rc) { queue->card->stats.tx_errors += count; /* ignore temporary SIGA errors without busy condition */ @@ -3529,7 +3510,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err, int rc; if (!qeth_is_cq(card, queue)) - goto out; + return; QETH_CARD_TEXT_(card, 5, "qcqhe%d", first_element); QETH_CARD_TEXT_(card, 5, "qcqhc%d", count); @@ -3538,12 +3519,7 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err, if (qdio_err) { netif_stop_queue(card->dev); qeth_schedule_recovery(card); - goto out; - } - - if (card->options.performance_stats) { - card->perf_stats.cq_cnt++; - card->perf_stats.cq_start_time = qeth_get_micros(); + return; } for (i = first_element; i < first_element + count; ++i) { @@ -3571,14 +3547,6 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err, } card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init + count) % QDIO_MAX_BUFFERS_PER_Q; - - if (card->options.performance_stats) { - int delta_t = qeth_get_micros(); - delta_t -= card->perf_stats.cq_start_time; - card->perf_stats.cq_time += delta_t; - } -out: - return; } static void qeth_qdio_input_handler(struct ccw_device *ccwdev, @@ -3614,11 +3582,7 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, qeth_schedule_recovery(card); return; } - if (card->options.performance_stats) { - card->perf_stats.outbound_handler_cnt++; - card->perf_stats.outbound_handler_start_time = - qeth_get_micros(); - } + for (i = first_element; i < (first_element + count); ++i) { int bidx = i % QDIO_MAX_BUFFERS_PER_Q; buffer = queue->bufs[bidx]; @@ -3664,9 +3628,6 @@ static void qeth_qdio_output_handler(struct ccw_device *ccwdev, qeth_check_outbound_queue(queue); netif_wake_queue(queue->card->dev); - if (card->options.performance_stats) - card->perf_stats.outbound_handler_time += qeth_get_micros() - - card->perf_stats.outbound_handler_start_time; } /* We cannot use outbound queue 3 for unicast packets on HiperSockets */ @@ -5319,11 +5280,6 @@ int qeth_poll(struct napi_struct *napi, int budget) int done; int new_budget = budget; - if (card->options.performance_stats) { - card->perf_stats.inbound_cnt++; - card->perf_stats.inbound_start_time = qeth_get_micros(); - } - while (1) { if (!card->rx.b_count) { card->rx.qdio_err = 0; @@ -5381,9 +5337,6 @@ int qeth_poll(struct napi_struct *napi, int budget) if (qdio_start_irq(card->data.ccwdev, 0)) napi_schedule(&card->napi); out: - if (card->options.performance_stats) - card->perf_stats.inbound_time += qeth_get_micros() - - card->perf_stats.inbound_start_time; return work_done; } EXPORT_SYMBOL_GPL(qeth_poll); @@ -5984,21 +5937,9 @@ static struct { /* 20 */{"queue 1 buffer usage"}, {"queue 2 buffer usage"}, {"queue 3 buffer usage"}, - {"rx poll time"}, - {"rx poll count"}, - {"rx do_QDIO time"}, - {"rx do_QDIO count"}, - {"tx handler time"}, - {"tx handler count"}, - {"tx time"}, -/* 30 */{"tx count"}, - {"tx do_QDIO time"}, - {"tx do_QDIO count"}, {"tx csum"}, {"tx lin"}, {"tx linfail"}, - {"cq handler count"}, - {"cq handler time"}, {"rx csum"} }; @@ -6046,22 +5987,10 @@ void qeth_core_get_ethtool_stats(struct net_device *dev, atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0; data[22] = (card->qdio.no_out_queues > 3) ? atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0; - data[23] = card->perf_stats.inbound_time; - data[24] = card->perf_stats.inbound_cnt; - data[25] = card->perf_stats.inbound_do_qdio_time; - data[26] = card->perf_stats.inbound_do_qdio_cnt; - data[27] = card->perf_stats.outbound_handler_time; - data[28] = card->perf_stats.outbound_handler_cnt; - data[29] = card->perf_stats.outbound_time; - data[30] = card->perf_stats.outbound_cnt; - data[31] = card->perf_stats.outbound_do_qdio_time; - data[32] = card->perf_stats.outbound_do_qdio_cnt; - data[33] = card->perf_stats.tx_csum; - data[34] = card->perf_stats.tx_lin; - data[35] = card->perf_stats.tx_linfail; - data[36] = card->perf_stats.cq_cnt; - data[37] = card->perf_stats.cq_time; - data[38] = card->perf_stats.rx_csum; + data[23] = card->perf_stats.tx_csum; + data[24] = card->perf_stats.tx_lin; + data[25] = card->perf_stats.tx_linfail; + data[26] = card->perf_stats.rx_csum; } EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index c566139da43d..8931dd6e2caa 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -632,11 +632,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, } queue = qeth_get_tx_queue(card, skb, ipv, cast_type); - - if (card->options.performance_stats) { - card->perf_stats.outbound_cnt++; - card->perf_stats.outbound_start_time = qeth_get_micros(); - } netif_stop_queue(dev); if (IS_OSN(card)) @@ -648,9 +643,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, if (!rc) { card->stats.tx_packets++; card->stats.tx_bytes += tx_bytes; - if (card->options.performance_stats) - card->perf_stats.outbound_time += qeth_get_micros() - - card->perf_stats.outbound_start_time; netif_wake_queue(dev); return NETDEV_TX_OK; } else if (rc == -EBUSY) { diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 8eb24c7f2750..012a290f1f4b 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2092,11 +2092,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, goto tx_drop; queue = qeth_get_tx_queue(card, skb, ipv, cast_type); - - if (card->options.performance_stats) { - card->perf_stats.outbound_cnt++; - card->perf_stats.outbound_start_time = qeth_get_micros(); - } netif_stop_queue(dev); if (ipv == 4 || IS_IQD(card)) @@ -2108,9 +2103,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, if (!rc) { card->stats.tx_packets++; card->stats.tx_bytes += tx_bytes; - if (card->options.performance_stats) - card->perf_stats.outbound_time += qeth_get_micros() - - card->perf_stats.outbound_start_time; netif_wake_queue(dev); return NETDEV_TX_OK; } else if (rc == -EBUSY) { -- cgit v1.2.3 From d896ac62d0160457913538f6e83fd386dc329a43 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 15 Feb 2019 19:22:28 +0100 Subject: s390/qeth: move ethtool code into its own file Most of this is self-contained code. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/Makefile | 2 +- drivers/s390/net/qeth_core.h | 12 +- drivers/s390/net/qeth_core_main.c | 317 +----------------------------------- drivers/s390/net/qeth_ethtool.c | 333 ++++++++++++++++++++++++++++++++++++++ drivers/s390/net/qeth_l2_main.c | 23 +-- drivers/s390/net/qeth_l3_main.c | 10 -- 6 files changed, 346 insertions(+), 351 deletions(-) create mode 100644 drivers/s390/net/qeth_ethtool.c (limited to 'drivers') diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index f2d6bbe57a6f..bc55ec316adb 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile @@ -9,7 +9,7 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o obj-$(CONFIG_LCS) += lcs.o -qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o +qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o qeth_ethtool.o obj-$(CONFIG_QETH) += qeth.o qeth_l2-y += qeth_l2_main.o qeth_l2_sys.o obj-$(CONFIG_QETH_L2) += qeth_l2.o diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 9928728649eb..5e08f112db13 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -922,6 +921,8 @@ static inline struct qeth_qdio_out_q *qeth_get_tx_queue(struct qeth_card *card, extern struct qeth_discipline qeth_l2_discipline; extern struct qeth_discipline qeth_l3_discipline; +extern const struct ethtool_ops qeth_ethtool_ops; +extern const struct ethtool_ops qeth_osn_ethtool_ops; extern const struct attribute_group *qeth_generic_attr_groups[]; extern const struct attribute_group *qeth_osn_attr_groups[]; extern const struct attribute_group qeth_device_attr_group; @@ -976,20 +977,15 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); int qeth_query_switch_attributes(struct qeth_card *card, struct qeth_switch_info *sw_info); +int qeth_query_card_info(struct qeth_card *card, + struct carrier_info *carrier_info); unsigned int qeth_count_elements(struct sk_buff *skb, unsigned int data_offset); int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, struct sk_buff *skb, struct qeth_hdr *hdr, unsigned int offset, unsigned int hd_len, int elements_needed); int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -int qeth_core_get_sset_count(struct net_device *, int); -void qeth_core_get_ethtool_stats(struct net_device *, - struct ethtool_stats *, u64 *); -void qeth_core_get_strings(struct net_device *, u32, u8 *); -void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); -int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *cmd); int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback); int qeth_configure_cq(struct qeth_card *, enum qeth_cq); int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index e3127e232fb2..96e4876a4daa 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4698,8 +4698,8 @@ static int qeth_query_card_info_cb(struct qeth_card *card, return 0; } -static int qeth_query_card_info(struct qeth_card *card, - struct carrier_info *carrier_info) +int qeth_query_card_info(struct qeth_card *card, + struct carrier_info *carrier_info) { struct qeth_cmd_buffer *iob; @@ -5623,7 +5623,10 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card) SET_NETDEV_DEV(dev, &card->gdev->dev); netif_carrier_off(dev); - if (!IS_OSN(card)) { + if (IS_OSN(card)) { + dev->ethtool_ops = &qeth_osn_ethtool_ops; + } else { + dev->ethtool_ops = &qeth_ethtool_ops; dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->hw_features |= NETIF_F_SG; dev->vlan_features |= NETIF_F_SG; @@ -5911,314 +5914,6 @@ int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } EXPORT_SYMBOL_GPL(qeth_do_ioctl); -static struct { - const char str[ETH_GSTRING_LEN]; -} qeth_ethtool_stats_keys[] = { -/* 0 */{"rx skbs"}, - {"rx buffers"}, - {"tx skbs"}, - {"tx buffers"}, - {"tx skbs no packing"}, - {"tx buffers no packing"}, - {"tx skbs packing"}, - {"tx buffers packing"}, - {"tx sg skbs"}, - {"tx buffer elements"}, -/* 10 */{"rx sg skbs"}, - {"rx sg frags"}, - {"rx sg page allocs"}, - {"tx large kbytes"}, - {"tx large count"}, - {"tx pk state ch n->p"}, - {"tx pk state ch p->n"}, - {"tx pk watermark low"}, - {"tx pk watermark high"}, - {"queue 0 buffer usage"}, -/* 20 */{"queue 1 buffer usage"}, - {"queue 2 buffer usage"}, - {"queue 3 buffer usage"}, - {"tx csum"}, - {"tx lin"}, - {"tx linfail"}, - {"rx csum"} -}; - -int qeth_core_get_sset_count(struct net_device *dev, int stringset) -{ - switch (stringset) { - case ETH_SS_STATS: - return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN); - default: - return -EINVAL; - } -} -EXPORT_SYMBOL_GPL(qeth_core_get_sset_count); - -void qeth_core_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct qeth_card *card = dev->ml_priv; - data[0] = card->stats.rx_packets - - card->perf_stats.initial_rx_packets; - data[1] = card->perf_stats.bufs_rec; - data[2] = card->stats.tx_packets - - card->perf_stats.initial_tx_packets; - data[3] = card->perf_stats.bufs_sent; - data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets - - card->perf_stats.skbs_sent_pack; - data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack; - data[6] = card->perf_stats.skbs_sent_pack; - data[7] = card->perf_stats.bufs_sent_pack; - data[8] = card->perf_stats.sg_skbs_sent; - data[9] = card->perf_stats.buf_elements_sent; - data[10] = card->perf_stats.sg_skbs_rx; - data[11] = card->perf_stats.sg_frags_rx; - data[12] = card->perf_stats.sg_alloc_page_rx; - data[13] = (card->perf_stats.large_send_bytes >> 10); - data[14] = card->perf_stats.large_send_cnt; - data[15] = card->perf_stats.sc_dp_p; - data[16] = card->perf_stats.sc_p_dp; - data[17] = QETH_LOW_WATERMARK_PACK; - data[18] = QETH_HIGH_WATERMARK_PACK; - data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers); - data[20] = (card->qdio.no_out_queues > 1) ? - atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0; - data[21] = (card->qdio.no_out_queues > 2) ? - atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0; - data[22] = (card->qdio.no_out_queues > 3) ? - atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0; - data[23] = card->perf_stats.tx_csum; - data[24] = card->perf_stats.tx_lin; - data[25] = card->perf_stats.tx_linfail; - data[26] = card->perf_stats.rx_csum; -} -EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); - -void qeth_core_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, &qeth_ethtool_stats_keys, - sizeof(qeth_ethtool_stats_keys)); - break; - default: - WARN_ON(1); - break; - } -} -EXPORT_SYMBOL_GPL(qeth_core_get_strings); - -void qeth_core_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct qeth_card *card = dev->ml_priv; - - strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3", - sizeof(info->driver)); - strlcpy(info->version, "1.0", sizeof(info->version)); - strlcpy(info->fw_version, card->info.mcl_level, - sizeof(info->fw_version)); - snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s", - CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card)); -} -EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo); - -/* Helper function to fill 'advertising' and 'supported' which are the same. */ -/* Autoneg and full-duplex are supported and advertised unconditionally. */ -/* Always advertise and support all speeds up to specified, and only one */ -/* specified port type. */ -static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, - int maxspeed, int porttype) -{ - ethtool_link_ksettings_zero_link_mode(cmd, supported); - ethtool_link_ksettings_zero_link_mode(cmd, advertising); - ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); - - ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); - ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); - - switch (porttype) { - case PORT_TP: - ethtool_link_ksettings_add_link_mode(cmd, supported, TP); - ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); - break; - case PORT_FIBRE: - ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); - ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); - break; - default: - ethtool_link_ksettings_add_link_mode(cmd, supported, TP); - ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); - WARN_ON_ONCE(1); - } - - /* partially does fall through, to also select lower speeds */ - switch (maxspeed) { - case SPEED_25000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 25000baseSR_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 25000baseSR_Full); - break; - case SPEED_10000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10000baseT_Full); - case SPEED_1000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 1000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 1000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 1000baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 1000baseT_Half); - case SPEED_100: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 100baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 100baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 100baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 100baseT_Half); - case SPEED_10: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Half); - /* end fallthrough */ - break; - default: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Half); - WARN_ON_ONCE(1); - } -} - -int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *cmd) -{ - struct qeth_card *card = netdev->ml_priv; - enum qeth_link_types link_type; - struct carrier_info carrier_info; - int rc; - - if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan)) - link_type = QETH_LINK_TYPE_10GBIT_ETH; - else - link_type = card->info.link_type; - - cmd->base.duplex = DUPLEX_FULL; - cmd->base.autoneg = AUTONEG_ENABLE; - cmd->base.phy_address = 0; - cmd->base.mdio_support = 0; - cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; - cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID; - - switch (link_type) { - case QETH_LINK_TYPE_FAST_ETH: - case QETH_LINK_TYPE_LANE_ETH100: - cmd->base.speed = SPEED_100; - cmd->base.port = PORT_TP; - break; - case QETH_LINK_TYPE_GBIT_ETH: - case QETH_LINK_TYPE_LANE_ETH1000: - cmd->base.speed = SPEED_1000; - cmd->base.port = PORT_FIBRE; - break; - case QETH_LINK_TYPE_10GBIT_ETH: - cmd->base.speed = SPEED_10000; - cmd->base.port = PORT_FIBRE; - break; - case QETH_LINK_TYPE_25GBIT_ETH: - cmd->base.speed = SPEED_25000; - cmd->base.port = PORT_FIBRE; - break; - default: - cmd->base.speed = SPEED_10; - cmd->base.port = PORT_TP; - } - qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port); - - /* Check if we can obtain more accurate information. */ - /* If QUERY_CARD_INFO command is not supported or fails, */ - /* just return the heuristics that was filled above. */ - rc = qeth_query_card_info(card, &carrier_info); - if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */ - return 0; - if (rc) /* report error from the hardware operation */ - return rc; - /* on success, fill in the information got from the hardware */ - - netdev_dbg(netdev, - "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n", - carrier_info.card_type, - carrier_info.port_mode, - carrier_info.port_speed); - - /* Update attributes for which we've obtained more authoritative */ - /* information, leave the rest the way they where filled above. */ - switch (carrier_info.card_type) { - case CARD_INFO_TYPE_1G_COPPER_A: - case CARD_INFO_TYPE_1G_COPPER_B: - cmd->base.port = PORT_TP; - qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port); - break; - case CARD_INFO_TYPE_1G_FIBRE_A: - case CARD_INFO_TYPE_1G_FIBRE_B: - cmd->base.port = PORT_FIBRE; - qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port); - break; - case CARD_INFO_TYPE_10G_FIBRE_A: - case CARD_INFO_TYPE_10G_FIBRE_B: - cmd->base.port = PORT_FIBRE; - qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port); - break; - } - - switch (carrier_info.port_mode) { - case CARD_INFO_PORTM_FULLDUPLEX: - cmd->base.duplex = DUPLEX_FULL; - break; - case CARD_INFO_PORTM_HALFDUPLEX: - cmd->base.duplex = DUPLEX_HALF; - break; - } - - switch (carrier_info.port_speed) { - case CARD_INFO_PORTS_10M: - cmd->base.speed = SPEED_10; - break; - case CARD_INFO_PORTS_100M: - cmd->base.speed = SPEED_100; - break; - case CARD_INFO_PORTS_1G: - cmd->base.speed = SPEED_1000; - break; - case CARD_INFO_PORTS_10G: - cmd->base.speed = SPEED_10000; - break; - case CARD_INFO_PORTS_25G: - cmd->base.speed = SPEED_25000; - break; - } - - return 0; -} -EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_link_ksettings); - static int qeth_start_csum_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c new file mode 100644 index 000000000000..a275f31150b2 --- /dev/null +++ b/drivers/s390/net/qeth_ethtool.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright IBM Corp. 2018 + */ + +#define KMSG_COMPONENT "qeth" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + +#include +#include "qeth_core.h" + +static struct { + const char str[ETH_GSTRING_LEN]; +} qeth_ethtool_stats_keys[] = { +/* 0 */{"rx skbs"}, + {"rx buffers"}, + {"tx skbs"}, + {"tx buffers"}, + {"tx skbs no packing"}, + {"tx buffers no packing"}, + {"tx skbs packing"}, + {"tx buffers packing"}, + {"tx sg skbs"}, + {"tx buffer elements"}, +/* 10 */{"rx sg skbs"}, + {"rx sg frags"}, + {"rx sg page allocs"}, + {"tx large kbytes"}, + {"tx large count"}, + {"tx pk state ch n->p"}, + {"tx pk state ch p->n"}, + {"tx pk watermark low"}, + {"tx pk watermark high"}, + {"queue 0 buffer usage"}, +/* 20 */{"queue 1 buffer usage"}, + {"queue 2 buffer usage"}, + {"queue 3 buffer usage"}, + {"tx csum"}, + {"tx lin"}, + {"tx linfail"}, + {"rx csum"} +}; + +static int qeth_get_sset_count(struct net_device *dev, int stringset) +{ + switch (stringset) { + case ETH_SS_STATS: + return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN); + default: + return -EINVAL; + } +} + +static void qeth_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct qeth_card *card = dev->ml_priv; + + data[0] = card->stats.rx_packets - + card->perf_stats.initial_rx_packets; + data[1] = card->perf_stats.bufs_rec; + data[2] = card->stats.tx_packets - + card->perf_stats.initial_tx_packets; + data[3] = card->perf_stats.bufs_sent; + data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets + - card->perf_stats.skbs_sent_pack; + data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack; + data[6] = card->perf_stats.skbs_sent_pack; + data[7] = card->perf_stats.bufs_sent_pack; + data[8] = card->perf_stats.sg_skbs_sent; + data[9] = card->perf_stats.buf_elements_sent; + data[10] = card->perf_stats.sg_skbs_rx; + data[11] = card->perf_stats.sg_frags_rx; + data[12] = card->perf_stats.sg_alloc_page_rx; + data[13] = (card->perf_stats.large_send_bytes >> 10); + data[14] = card->perf_stats.large_send_cnt; + data[15] = card->perf_stats.sc_dp_p; + data[16] = card->perf_stats.sc_p_dp; + data[17] = QETH_LOW_WATERMARK_PACK; + data[18] = QETH_HIGH_WATERMARK_PACK; + data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers); + data[20] = (card->qdio.no_out_queues > 1) ? + atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0; + data[21] = (card->qdio.no_out_queues > 2) ? + atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0; + data[22] = (card->qdio.no_out_queues > 3) ? + atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0; + data[23] = card->perf_stats.tx_csum; + data[24] = card->perf_stats.tx_lin; + data[25] = card->perf_stats.tx_linfail; + data[26] = card->perf_stats.rx_csum; +} + +static void qeth_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, &qeth_ethtool_stats_keys, + sizeof(qeth_ethtool_stats_keys)); + break; + default: + WARN_ON(1); + break; + } +} + +static void qeth_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct qeth_card *card = dev->ml_priv; + + strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3", + sizeof(info->driver)); + strlcpy(info->version, "1.0", sizeof(info->version)); + strlcpy(info->fw_version, card->info.mcl_level, + sizeof(info->fw_version)); + snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s", + CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card)); +} + +/* Helper function to fill 'advertising' and 'supported' which are the same. */ +/* Autoneg and full-duplex are supported and advertised unconditionally. */ +/* Always advertise and support all speeds up to specified, and only one */ +/* specified port type. */ +static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, + int maxspeed, int porttype) +{ + ethtool_link_ksettings_zero_link_mode(cmd, supported); + ethtool_link_ksettings_zero_link_mode(cmd, advertising); + ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising); + + ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); + + switch (porttype) { + case PORT_TP: + ethtool_link_ksettings_add_link_mode(cmd, supported, TP); + ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); + break; + case PORT_FIBRE: + ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); + ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); + break; + default: + ethtool_link_ksettings_add_link_mode(cmd, supported, TP); + ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); + WARN_ON_ONCE(1); + } + + /* partially does fall through, to also select lower speeds */ + switch (maxspeed) { + case SPEED_25000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 25000baseSR_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 25000baseSR_Full); + break; + case SPEED_10000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10000baseT_Full); + /* fall through */ + case SPEED_1000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseT_Half); + /* fall through */ + case SPEED_100: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Half); + /* fall through */ + case SPEED_10: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Half); + break; + default: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Half); + WARN_ON_ONCE(1); + } +} + + +static int qeth_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct qeth_card *card = netdev->ml_priv; + enum qeth_link_types link_type; + struct carrier_info carrier_info; + int rc; + + if (IS_IQD(card) || IS_VM_NIC(card)) + link_type = QETH_LINK_TYPE_10GBIT_ETH; + else + link_type = card->info.link_type; + + cmd->base.duplex = DUPLEX_FULL; + cmd->base.autoneg = AUTONEG_ENABLE; + cmd->base.phy_address = 0; + cmd->base.mdio_support = 0; + cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; + cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID; + + switch (link_type) { + case QETH_LINK_TYPE_FAST_ETH: + case QETH_LINK_TYPE_LANE_ETH100: + cmd->base.speed = SPEED_100; + cmd->base.port = PORT_TP; + break; + case QETH_LINK_TYPE_GBIT_ETH: + case QETH_LINK_TYPE_LANE_ETH1000: + cmd->base.speed = SPEED_1000; + cmd->base.port = PORT_FIBRE; + break; + case QETH_LINK_TYPE_10GBIT_ETH: + cmd->base.speed = SPEED_10000; + cmd->base.port = PORT_FIBRE; + break; + case QETH_LINK_TYPE_25GBIT_ETH: + cmd->base.speed = SPEED_25000; + cmd->base.port = PORT_FIBRE; + break; + default: + cmd->base.speed = SPEED_10; + cmd->base.port = PORT_TP; + } + qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port); + + /* Check if we can obtain more accurate information. */ + /* If QUERY_CARD_INFO command is not supported or fails, */ + /* just return the heuristics that was filled above. */ + rc = qeth_query_card_info(card, &carrier_info); + if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */ + return 0; + if (rc) /* report error from the hardware operation */ + return rc; + /* on success, fill in the information got from the hardware */ + + netdev_dbg(netdev, + "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n", + carrier_info.card_type, + carrier_info.port_mode, + carrier_info.port_speed); + + /* Update attributes for which we've obtained more authoritative */ + /* information, leave the rest the way they where filled above. */ + switch (carrier_info.card_type) { + case CARD_INFO_TYPE_1G_COPPER_A: + case CARD_INFO_TYPE_1G_COPPER_B: + cmd->base.port = PORT_TP; + qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port); + break; + case CARD_INFO_TYPE_1G_FIBRE_A: + case CARD_INFO_TYPE_1G_FIBRE_B: + cmd->base.port = PORT_FIBRE; + qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port); + break; + case CARD_INFO_TYPE_10G_FIBRE_A: + case CARD_INFO_TYPE_10G_FIBRE_B: + cmd->base.port = PORT_FIBRE; + qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port); + break; + } + + switch (carrier_info.port_mode) { + case CARD_INFO_PORTM_FULLDUPLEX: + cmd->base.duplex = DUPLEX_FULL; + break; + case CARD_INFO_PORTM_HALFDUPLEX: + cmd->base.duplex = DUPLEX_HALF; + break; + } + + switch (carrier_info.port_speed) { + case CARD_INFO_PORTS_10M: + cmd->base.speed = SPEED_10; + break; + case CARD_INFO_PORTS_100M: + cmd->base.speed = SPEED_100; + break; + case CARD_INFO_PORTS_1G: + cmd->base.speed = SPEED_1000; + break; + case CARD_INFO_PORTS_10G: + cmd->base.speed = SPEED_10000; + break; + case CARD_INFO_PORTS_25G: + cmd->base.speed = SPEED_25000; + break; + } + + return 0; +} + +const struct ethtool_ops qeth_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_strings = qeth_get_strings, + .get_ethtool_stats = qeth_get_ethtool_stats, + .get_sset_count = qeth_get_sset_count, + .get_drvinfo = qeth_get_drvinfo, + .get_link_ksettings = qeth_get_link_ksettings, +}; + +const struct ethtool_ops qeth_osn_ethtool_ops = { + .get_strings = qeth_get_strings, + .get_ethtool_stats = qeth_get_ethtool_stats, + .get_sset_count = qeth_get_sset_count, + .get_drvinfo = qeth_get_drvinfo, +}; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 8931dd6e2caa..dbcba77fd94c 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -696,22 +696,6 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) unregister_netdev(card->dev); } -static const struct ethtool_ops qeth_l2_ethtool_ops = { - .get_link = ethtool_op_get_link, - .get_strings = qeth_core_get_strings, - .get_ethtool_stats = qeth_core_get_ethtool_stats, - .get_sset_count = qeth_core_get_sset_count, - .get_drvinfo = qeth_core_get_drvinfo, - .get_link_ksettings = qeth_core_ethtool_get_link_ksettings, -}; - -static const struct ethtool_ops qeth_l2_osn_ops = { - .get_strings = qeth_core_get_strings, - .get_ethtool_stats = qeth_core_get_ethtool_stats, - .get_sset_count = qeth_core_get_sset_count, - .get_drvinfo = qeth_core_get_drvinfo, -}; - static const struct net_device_ops qeth_l2_netdev_ops = { .ndo_open = qeth_open, .ndo_stop = qeth_stop, @@ -735,13 +719,10 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) card->dev->priv_flags |= IFF_UNICAST_FLT; card->dev->netdev_ops = &qeth_l2_netdev_ops; - if (card->info.type == QETH_CARD_TYPE_OSN) { - card->dev->ethtool_ops = &qeth_l2_osn_ops; + if (IS_OSN(card)) card->dev->flags |= IFF_NOARP; - } else { - card->dev->ethtool_ops = &qeth_l2_ethtool_ops; + else card->dev->needed_headroom = sizeof(struct qeth_hdr); - } if (IS_OSM(card)) { card->dev->features |= NETIF_F_VLAN_CHALLENGED; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 012a290f1f4b..40c7d53f5512 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2117,15 +2117,6 @@ tx_drop: return NETDEV_TX_OK; } -static const struct ethtool_ops qeth_l3_ethtool_ops = { - .get_link = ethtool_op_get_link, - .get_strings = qeth_core_get_strings, - .get_ethtool_stats = qeth_core_get_ethtool_stats, - .get_sset_count = qeth_core_get_sset_count, - .get_drvinfo = qeth_core_get_drvinfo, - .get_link_ksettings = qeth_core_ethtool_get_link_ksettings, -}; - /* * we need NOARP for IPv4 but we want neighbor solicitation for IPv6. Setting * NOARP on the netdevice is no option because it also turns off neighbor @@ -2247,7 +2238,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok) return -ENODEV; card->dev->needed_headroom = headroom; - card->dev->ethtool_ops = &qeth_l3_ethtool_ops; card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; -- cgit v1.2.3 From b0abc4f5df76ceed497ffd959fd7839f9cd38a07 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 15 Feb 2019 19:22:29 +0100 Subject: s390/qeth: overhaul ethtool statistics Accumulate per-TX queue statistics, and increase their size to 64 bit. Don't bother with enabling/disabling the statistics, the overhead is negligible. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 90 ++++++++++++---------- drivers/s390/net/qeth_core_main.c | 127 ++++++++++++++++--------------- drivers/s390/net/qeth_core_sys.c | 39 +++++----- drivers/s390/net/qeth_ethtool.c | 152 +++++++++++++++++++++----------------- drivers/s390/net/qeth_l2_main.c | 28 +++---- drivers/s390/net/qeth_l3_main.c | 36 ++++----- 6 files changed, 256 insertions(+), 216 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 5e08f112db13..c0c46be0b251 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -34,6 +34,8 @@ #include #include +#include + #include "qeth_core_mpc.h" /** @@ -112,35 +114,6 @@ static inline u32 qeth_get_device_id(struct ccw_device *cdev) #define CCW_DEVID(cdev) (qeth_get_device_id(cdev)) #define CARD_DEVID(card) (CCW_DEVID(CARD_RDEV(card))) -/** - * card stuff - */ -struct qeth_perf_stats { - unsigned int bufs_rec; - unsigned int bufs_sent; - unsigned int buf_elements_sent; - - unsigned int skbs_sent_pack; - unsigned int bufs_sent_pack; - - unsigned int sc_dp_p; - unsigned int sc_p_dp; - unsigned int large_send_bytes; - unsigned int large_send_cnt; - unsigned int sg_skbs_sent; - /* initial values when measuring starts */ - unsigned long initial_rx_packets; - unsigned long initial_tx_packets; - /* inbound scatter gather data */ - unsigned int sg_skbs_rx; - unsigned int sg_frags_rx; - unsigned int sg_alloc_page_rx; - unsigned int tx_csum; - unsigned int tx_lin; - unsigned int tx_linfail; - unsigned int rx_csum; -}; - /* Routing stuff */ struct qeth_routing_info { enum qeth_routing_types type; @@ -470,10 +443,54 @@ enum qeth_out_q_states { QETH_OUT_Q_LOCKED_FLUSH, }; +#define QETH_CARD_STAT_ADD(_c, _stat, _val) ((_c)->stats._stat += (_val)) +#define QETH_CARD_STAT_INC(_c, _stat) QETH_CARD_STAT_ADD(_c, _stat, 1) + +#define QETH_TXQ_STAT_ADD(_q, _stat, _val) ((_q)->stats._stat += (_val)) +#define QETH_TXQ_STAT_INC(_q, _stat) QETH_TXQ_STAT_ADD(_q, _stat, 1) + +struct qeth_card_stats { + u64 rx_bufs; + u64 rx_skb_csum; + u64 rx_sg_skbs; + u64 rx_sg_frags; + u64 rx_sg_alloc_page; + + /* rtnl_link_stats64 */ + u64 rx_packets; + u64 rx_bytes; + u64 rx_errors; + u64 rx_dropped; + u64 rx_multicast; + u64 tx_errors; +}; + +struct qeth_out_q_stats { + u64 bufs; + u64 bufs_pack; + u64 buf_elements; + u64 skbs_pack; + u64 skbs_sg; + u64 skbs_csum; + u64 skbs_tso; + u64 skbs_linearized; + u64 skbs_linearized_fail; + u64 tso_bytes; + u64 packing_mode_switch; + + /* rtnl_link_stats64 */ + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; + u64 tx_dropped; + u64 tx_carrier_errors; +}; + struct qeth_qdio_out_q { struct qdio_buffer *qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q]; struct qdio_outbuf_state *bufstates; /* convenience pointer */ + struct qeth_out_q_stats stats; int queue_no; struct qeth_card *card; atomic_t state; @@ -677,7 +694,6 @@ struct qeth_card_options { struct qeth_vnicc_info vnicc; /* VNICC options */ int fake_broadcast; enum qeth_discipline_id layer; - int performance_stats; int rx_sg_cb; enum qeth_ipa_isolation_modes isolation; enum qeth_ipa_isolation_modes prev_isolation; @@ -753,8 +769,7 @@ struct qeth_card { struct qeth_channel data; struct net_device *dev; - struct net_device_stats stats; - + struct qeth_card_stats stats; struct qeth_card_info info; struct qeth_token token; struct qeth_seqno seqno; @@ -777,7 +792,6 @@ struct qeth_card { struct list_head cmd_waiter_list; /* QDIO buffer handling */ struct qeth_qdio_info qdio; - struct qeth_perf_stats perf_stats; int read_or_write_problem; struct qeth_osn_info osn_info; struct qeth_discipline *discipline; @@ -858,8 +872,7 @@ static inline void qeth_rx_csum(struct qeth_card *card, struct sk_buff *skb, if ((card->dev->features & NETIF_F_RXCSUM) && (flags & QETH_HDR_EXT_CSUM_TRANSP_REQ)) { skb->ip_summed = CHECKSUM_UNNECESSARY; - if (card->options.performance_stats) - card->perf_stats.rx_csum++; + QETH_CARD_STAT_INC(card, rx_skb_csum); } else { skb->ip_summed = CHECKSUM_NONE; } @@ -966,7 +979,6 @@ void qeth_clear_working_pool_list(struct qeth_card *); void qeth_clear_cmd_buffers(struct qeth_channel *); void qeth_clear_qdio_buffers(struct qeth_card *); void qeth_setadp_promisc_mode(struct qeth_card *); -struct net_device_stats *qeth_get_stats(struct net_device *); int qeth_setadpparms_change_macaddr(struct qeth_card *); void qeth_tx_timeout(struct net_device *); void qeth_prepare_control_data(struct qeth_card *, int, @@ -1002,14 +1014,16 @@ netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t); netdev_features_t qeth_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features); +void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats); int qeth_open(struct net_device *dev); int qeth_stop(struct net_device *dev); int qeth_vm_request_mac(struct qeth_card *card); int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type, - void (*fill_header)(struct qeth_card *card, struct qeth_hdr *hdr, - struct sk_buff *skb, int ipv, int cast_type, + void (*fill_header)(struct qeth_qdio_out_q *queue, + struct qeth_hdr *hdr, struct sk_buff *skb, + int ipv, int cast_type, unsigned int data_len)); /* exports for OSN */ diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 96e4876a4daa..6d93bb48b1d9 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2703,8 +2703,7 @@ static struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry( } else { free_page((unsigned long)entry->elements[i]); entry->elements[i] = page_address(page); - if (card->options.performance_stats) - card->perf_stats.sg_alloc_page_rx++; + QETH_CARD_STAT_INC(card, rx_sg_alloc_page); } } } @@ -3180,7 +3179,7 @@ static int qeth_check_qdio_errors(struct qeth_card *card, buf->element[14].sflags); QETH_CARD_TEXT_(card, 2, " qerr=%X", qdio_error); if ((buf->element[15].sflags) == 0x12) { - card->stats.rx_dropped++; + QETH_CARD_STAT_INC(card, rx_dropped); return 0; } else return 1; @@ -3322,8 +3321,7 @@ static void qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) >= QETH_HIGH_WATERMARK_PACK){ /* switch non-PACKING -> PACKING */ QETH_CARD_TEXT(queue->card, 6, "np->pack"); - if (queue->card->options.performance_stats) - queue->card->perf_stats.sc_dp_p++; + QETH_TXQ_STAT_INC(queue, packing_mode_switch); queue->do_pack = 1; } } @@ -3342,8 +3340,7 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) <= QETH_LOW_WATERMARK_PACK) { /* switch PACKING -> non-PACKING */ QETH_CARD_TEXT(queue->card, 6, "pack->np"); - if (queue->card->options.performance_stats) - queue->card->perf_stats.sc_p_dp++; + QETH_TXQ_STAT_INC(queue, packing_mode_switch); queue->do_pack = 0; return qeth_prep_flush_pack_buffer(queue); } @@ -3397,6 +3394,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, } } + QETH_TXQ_STAT_ADD(queue, bufs, count); netif_trans_update(queue->card->dev); qdio_flags = QDIO_FLAG_SYNC_OUTPUT; if (atomic_read(&queue->set_pci_flags_count)) @@ -3405,7 +3403,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags, queue->queue_no, index, count); if (rc) { - queue->card->stats.tx_errors += count; + QETH_TXQ_STAT_ADD(queue, tx_errors, count); /* ignore temporary SIGA errors without busy condition */ if (rc == -ENOBUFS) return; @@ -3420,8 +3418,6 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, qeth_schedule_recovery(queue->card); return; } - if (queue->card->options.performance_stats) - queue->card->perf_stats.bufs_sent += count; } static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) @@ -3452,10 +3448,8 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) if (!flush_cnt && !atomic_read(&queue->set_pci_flags_count)) flush_cnt += qeth_prep_flush_pack_buffer(queue); - if (queue->card->options.performance_stats && - q_was_packing) - queue->card->perf_stats.bufs_sent_pack += - flush_cnt; + if (q_was_packing) + QETH_TXQ_STAT_ADD(queue, bufs_pack, flush_cnt); if (flush_cnt) qeth_flush_buffers(queue, index, flush_cnt); atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); @@ -3748,11 +3742,12 @@ EXPORT_SYMBOL_GPL(qeth_count_elements); * The number of needed buffer elements is returned in @elements. * Error to create the hdr is indicated by returning with < 0. */ -static int qeth_add_hw_header(struct qeth_card *card, struct sk_buff *skb, - struct qeth_hdr **hdr, unsigned int hdr_len, - unsigned int proto_len, unsigned int *elements) +static int qeth_add_hw_header(struct qeth_qdio_out_q *queue, + struct sk_buff *skb, struct qeth_hdr **hdr, + unsigned int hdr_len, unsigned int proto_len, + unsigned int *elements) { - const unsigned int max_elements = QETH_MAX_BUFFER_ELEMENTS(card); + const unsigned int max_elements = QETH_MAX_BUFFER_ELEMENTS(queue->card); const unsigned int contiguous = proto_len ? proto_len : 1; unsigned int __elements; addr_t start, end; @@ -3791,15 +3786,12 @@ check_layout: } rc = skb_linearize(skb); - if (card->options.performance_stats) { - if (rc) - card->perf_stats.tx_linfail++; - else - card->perf_stats.tx_lin++; - } - if (rc) + if (rc) { + QETH_TXQ_STAT_INC(queue, skbs_linearized_fail); return rc; + } + QETH_TXQ_STAT_INC(queue, skbs_linearized); /* Linearization changed the layout, re-evaluate: */ goto check_layout; } @@ -3923,9 +3915,8 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, QETH_CARD_TEXT(queue->card, 6, "fillbfnp"); } else { QETH_CARD_TEXT(queue->card, 6, "fillbfpa"); - if (queue->card->options.performance_stats) - queue->card->perf_stats.skbs_sent_pack++; + QETH_TXQ_STAT_INC(queue, skbs_pack); /* If the buffer still has free elements, keep using it. */ if (buf->next_element_to_fill < QETH_MAX_BUFFER_ELEMENTS(queue->card)) @@ -4039,8 +4030,8 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, } out: /* at this point the queue is UNLOCKED again */ - if (queue->card->options.performance_stats && do_pack) - queue->card->perf_stats.bufs_sent_pack += flush_count; + if (do_pack) + QETH_TXQ_STAT_ADD(queue, bufs_pack, flush_count); return rc; } @@ -4064,8 +4055,9 @@ static void qeth_fill_tso_ext(struct qeth_hdr_tso *hdr, int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, struct qeth_qdio_out_q *queue, int ipv, int cast_type, - void (*fill_header)(struct qeth_card *card, struct qeth_hdr *hdr, - struct sk_buff *skb, int ipv, int cast_type, + void (*fill_header)(struct qeth_qdio_out_q *queue, + struct qeth_hdr *hdr, struct sk_buff *skb, + int ipv, int cast_type, unsigned int data_len)) { unsigned int proto_len, hw_hdr_len; @@ -4090,7 +4082,7 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, if (rc) return rc; - push_len = qeth_add_hw_header(card, skb, &hdr, hw_hdr_len, proto_len, + push_len = qeth_add_hw_header(queue, skb, &hdr, hw_hdr_len, proto_len, &elements); if (push_len < 0) return push_len; @@ -4100,7 +4092,7 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, data_offset = push_len + proto_len; } memset(hdr, 0, hw_hdr_len); - fill_header(card, hdr, skb, ipv, cast_type, frame_len); + fill_header(queue, hdr, skb, ipv, cast_type, frame_len); if (is_tso) qeth_fill_tso_ext((struct qeth_hdr_tso *) hdr, frame_len - proto_len, skb, proto_len); @@ -4117,14 +4109,12 @@ int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, } if (!rc) { - if (card->options.performance_stats) { - card->perf_stats.buf_elements_sent += elements; - if (is_sg) - card->perf_stats.sg_skbs_sent++; - if (is_tso) { - card->perf_stats.large_send_bytes += frame_len; - card->perf_stats.large_send_cnt++; - } + QETH_TXQ_STAT_ADD(queue, buf_elements, elements); + if (is_sg) + QETH_TXQ_STAT_INC(queue, skbs_sg); + if (is_tso) { + QETH_TXQ_STAT_INC(queue, skbs_tso); + QETH_TXQ_STAT_ADD(queue, tso_bytes, frame_len); } } else { if (!push_len) @@ -4183,18 +4173,6 @@ void qeth_setadp_promisc_mode(struct qeth_card *card) } EXPORT_SYMBOL_GPL(qeth_setadp_promisc_mode); -struct net_device_stats *qeth_get_stats(struct net_device *dev) -{ - struct qeth_card *card; - - card = dev->ml_priv; - - QETH_CARD_TEXT(card, 5, "getstat"); - - return &card->stats; -} -EXPORT_SYMBOL_GPL(qeth_get_stats); - static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { @@ -4388,7 +4366,7 @@ void qeth_tx_timeout(struct net_device *dev) card = dev->ml_priv; QETH_CARD_TEXT(card, 4, "txtimeo"); - card->stats.tx_errors++; + QETH_CARD_STAT_INC(card, tx_errors); qeth_schedule_recovery(card); } EXPORT_SYMBOL_GPL(qeth_tx_timeout); @@ -5246,7 +5224,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, QETH_CARD_TEXT(card, 4, "unexeob"); QETH_CARD_HEX(card, 2, buffer, sizeof(void *)); dev_kfree_skb_any(skb); - card->stats.rx_errors++; + QETH_CARD_STAT_INC(card, rx_errors); return NULL; } element++; @@ -5258,16 +5236,17 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, } *__element = element; *__offset = offset; - if (use_rx_sg && card->options.performance_stats) { - card->perf_stats.sg_skbs_rx++; - card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags; + if (use_rx_sg) { + QETH_CARD_STAT_INC(card, rx_sg_skbs); + QETH_CARD_STAT_ADD(card, rx_sg_frags, + skb_shinfo(skb)->nr_frags); } return skb; no_mem: if (net_ratelimit()) { QETH_CARD_TEXT(card, 2, "noskbmem"); } - card->stats.rx_dropped++; + QETH_CARD_STAT_INC(card, rx_dropped); return NULL; } EXPORT_SYMBOL_GPL(qeth_core_get_next_skb); @@ -5308,8 +5287,7 @@ int qeth_poll(struct napi_struct *napi, int budget) done = 1; if (done) { - if (card->options.performance_stats) - card->perf_stats.bufs_rec++; + QETH_CARD_STAT_INC(card, rx_bufs); qeth_put_buffer_pool_entry(card, buffer->pool_entry); qeth_queue_input_buffer(card, card->rx.b_index); @@ -6223,6 +6201,33 @@ netdev_features_t qeth_features_check(struct sk_buff *skb, } EXPORT_SYMBOL_GPL(qeth_features_check); +void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +{ + struct qeth_card *card = dev->ml_priv; + struct qeth_qdio_out_q *queue; + unsigned int i; + + QETH_CARD_TEXT(card, 5, "getstat"); + + stats->rx_packets = card->stats.rx_packets; + stats->rx_bytes = card->stats.rx_bytes; + stats->rx_errors = card->stats.rx_errors; + stats->rx_dropped = card->stats.rx_dropped; + stats->multicast = card->stats.rx_multicast; + stats->tx_errors = card->stats.tx_errors; + + for (i = 0; i < card->qdio.no_out_queues; i++) { + queue = card->qdio.out_qs[i]; + + stats->tx_packets += queue->stats.tx_packets; + stats->tx_bytes += queue->stats.tx_bytes; + stats->tx_errors += queue->stats.tx_errors; + stats->tx_dropped += queue->stats.tx_dropped; + stats->tx_carrier_errors += queue->stats.tx_carrier_errors; + } +} +EXPORT_SYMBOL_GPL(qeth_get_stats64); + int qeth_open(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 485a335669ba..8b223cc2c19b 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -336,35 +336,36 @@ static ssize_t qeth_dev_performance_stats_show(struct device *dev, if (!card) return -EINVAL; - return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0); + return sprintf(buf, "1\n"); } static ssize_t qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qeth_card *card = dev_get_drvdata(dev); - char *tmp; - int i, rc = 0; + struct qeth_qdio_out_q *queue; + unsigned int i; + bool reset; + int rc; if (!card) return -EINVAL; - mutex_lock(&card->conf_mutex); - i = simple_strtoul(buf, &tmp, 16); - if ((i == 0) || (i == 1)) { - if (i == card->options.performance_stats) - goto out; - card->options.performance_stats = i; - if (i == 0) - memset(&card->perf_stats, 0, - sizeof(struct qeth_perf_stats)); - card->perf_stats.initial_rx_packets = card->stats.rx_packets; - card->perf_stats.initial_tx_packets = card->stats.tx_packets; - } else - rc = -EINVAL; -out: - mutex_unlock(&card->conf_mutex); - return rc ? rc : count; + rc = kstrtobool(buf, &reset); + if (rc) + return rc; + + if (reset) { + memset(&card->stats, 0, sizeof(card->stats)); + for (i = 0; i < card->qdio.no_out_queues; i++) { + queue = card->qdio.out_qs[i]; + if (!queue) + break; + memset(&queue->stats, 0, sizeof(queue->stats)); + } + } + + return count; } static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show, diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c index a275f31150b2..9ce5ef5fcf7a 100644 --- a/drivers/s390/net/qeth_ethtool.c +++ b/drivers/s390/net/qeth_ethtool.c @@ -9,43 +9,82 @@ #include #include "qeth_core.h" -static struct { - const char str[ETH_GSTRING_LEN]; -} qeth_ethtool_stats_keys[] = { -/* 0 */{"rx skbs"}, - {"rx buffers"}, - {"tx skbs"}, - {"tx buffers"}, - {"tx skbs no packing"}, - {"tx buffers no packing"}, - {"tx skbs packing"}, - {"tx buffers packing"}, - {"tx sg skbs"}, - {"tx buffer elements"}, -/* 10 */{"rx sg skbs"}, - {"rx sg frags"}, - {"rx sg page allocs"}, - {"tx large kbytes"}, - {"tx large count"}, - {"tx pk state ch n->p"}, - {"tx pk state ch p->n"}, - {"tx pk watermark low"}, - {"tx pk watermark high"}, - {"queue 0 buffer usage"}, -/* 20 */{"queue 1 buffer usage"}, - {"queue 2 buffer usage"}, - {"queue 3 buffer usage"}, - {"tx csum"}, - {"tx lin"}, - {"tx linfail"}, - {"rx csum"} + +#define QETH_TXQ_STAT(_name, _stat) { \ + .name = _name, \ + .offset = offsetof(struct qeth_out_q_stats, _stat) \ +} + +#define QETH_CARD_STAT(_name, _stat) { \ + .name = _name, \ + .offset = offsetof(struct qeth_card_stats, _stat) \ +} + +struct qeth_stats { + char name[ETH_GSTRING_LEN]; + unsigned int offset; +}; + +static const struct qeth_stats txq_stats[] = { + QETH_TXQ_STAT("IO buffers", bufs), + QETH_TXQ_STAT("IO buffer elements", buf_elements), + QETH_TXQ_STAT("packed IO buffers", bufs_pack), + QETH_TXQ_STAT("skbs", tx_packets), + QETH_TXQ_STAT("packed skbs", skbs_pack), + QETH_TXQ_STAT("SG skbs", skbs_sg), + QETH_TXQ_STAT("HW csum skbs", skbs_csum), + QETH_TXQ_STAT("TSO skbs", skbs_tso), + QETH_TXQ_STAT("linearized skbs", skbs_linearized), + QETH_TXQ_STAT("linearized+error skbs", skbs_linearized_fail), + QETH_TXQ_STAT("TSO bytes", tso_bytes), + QETH_TXQ_STAT("Packing mode switches", packing_mode_switch), +}; + +static const struct qeth_stats card_stats[] = { + QETH_CARD_STAT("rx0 IO buffers", rx_bufs), + QETH_CARD_STAT("rx0 HW csum skbs", rx_skb_csum), + QETH_CARD_STAT("rx0 SG skbs", rx_sg_skbs), + QETH_CARD_STAT("rx0 SG page frags", rx_sg_frags), + QETH_CARD_STAT("rx0 SG page allocs", rx_sg_alloc_page), }; +#define TXQ_STATS_LEN ARRAY_SIZE(txq_stats) +#define CARD_STATS_LEN ARRAY_SIZE(card_stats) + +static void qeth_add_stat_data(u64 **dst, void *src, + const struct qeth_stats stats[], + unsigned int size) +{ + unsigned int i; + char *stat; + + for (i = 0; i < size; i++) { + stat = (char *)src + stats[i].offset; + **dst = *(u64 *)stat; + (*dst)++; + } +} + +static void qeth_add_stat_strings(u8 **data, const char *prefix, + const struct qeth_stats stats[], + unsigned int size) +{ + unsigned int i; + + for (i = 0; i < size; i++) { + snprintf(*data, ETH_GSTRING_LEN, "%s%s", prefix, stats[i].name); + *data += ETH_GSTRING_LEN; + } +} + static int qeth_get_sset_count(struct net_device *dev, int stringset) { + struct qeth_card *card = dev->ml_priv; + switch (stringset) { case ETH_SS_STATS: - return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN); + return CARD_STATS_LEN + + card->qdio.no_out_queues * TXQ_STATS_LEN; default: return -EINVAL; } @@ -55,48 +94,29 @@ static void qeth_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data) { struct qeth_card *card = dev->ml_priv; + unsigned int i; - data[0] = card->stats.rx_packets - - card->perf_stats.initial_rx_packets; - data[1] = card->perf_stats.bufs_rec; - data[2] = card->stats.tx_packets - - card->perf_stats.initial_tx_packets; - data[3] = card->perf_stats.bufs_sent; - data[4] = card->stats.tx_packets - card->perf_stats.initial_tx_packets - - card->perf_stats.skbs_sent_pack; - data[5] = card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack; - data[6] = card->perf_stats.skbs_sent_pack; - data[7] = card->perf_stats.bufs_sent_pack; - data[8] = card->perf_stats.sg_skbs_sent; - data[9] = card->perf_stats.buf_elements_sent; - data[10] = card->perf_stats.sg_skbs_rx; - data[11] = card->perf_stats.sg_frags_rx; - data[12] = card->perf_stats.sg_alloc_page_rx; - data[13] = (card->perf_stats.large_send_bytes >> 10); - data[14] = card->perf_stats.large_send_cnt; - data[15] = card->perf_stats.sc_dp_p; - data[16] = card->perf_stats.sc_p_dp; - data[17] = QETH_LOW_WATERMARK_PACK; - data[18] = QETH_HIGH_WATERMARK_PACK; - data[19] = atomic_read(&card->qdio.out_qs[0]->used_buffers); - data[20] = (card->qdio.no_out_queues > 1) ? - atomic_read(&card->qdio.out_qs[1]->used_buffers) : 0; - data[21] = (card->qdio.no_out_queues > 2) ? - atomic_read(&card->qdio.out_qs[2]->used_buffers) : 0; - data[22] = (card->qdio.no_out_queues > 3) ? - atomic_read(&card->qdio.out_qs[3]->used_buffers) : 0; - data[23] = card->perf_stats.tx_csum; - data[24] = card->perf_stats.tx_lin; - data[25] = card->perf_stats.tx_linfail; - data[26] = card->perf_stats.rx_csum; + qeth_add_stat_data(&data, &card->stats, card_stats, CARD_STATS_LEN); + for (i = 0; i < card->qdio.no_out_queues; i++) + qeth_add_stat_data(&data, &card->qdio.out_qs[i]->stats, + txq_stats, TXQ_STATS_LEN); } static void qeth_get_strings(struct net_device *dev, u32 stringset, u8 *data) { + struct qeth_card *card = dev->ml_priv; + char prefix[ETH_GSTRING_LEN] = ""; + unsigned int i; + switch (stringset) { case ETH_SS_STATS: - memcpy(data, &qeth_ethtool_stats_keys, - sizeof(qeth_ethtool_stats_keys)); + qeth_add_stat_strings(&data, prefix, card_stats, + CARD_STATS_LEN); + for (i = 0; i < card->qdio.no_out_queues; i++) { + snprintf(prefix, ETH_GSTRING_LEN, "tx%u ", i); + qeth_add_stat_strings(&data, prefix, txq_stats, + TXQ_STATS_LEN); + } break; default: WARN_ON(1); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index dbcba77fd94c..b1280a155953 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -174,9 +174,9 @@ static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb) return RTN_UNICAST; } -static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, - struct sk_buff *skb, int ipv, int cast_type, - unsigned int data_len) +static void qeth_l2_fill_header(struct qeth_qdio_out_q *queue, + struct qeth_hdr *hdr, struct sk_buff *skb, + int ipv, int cast_type, unsigned int data_len) { struct vlan_ethhdr *veth = vlan_eth_hdr(skb); @@ -188,8 +188,7 @@ static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2; if (skb->ip_summed == CHECKSUM_PARTIAL) { qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv); - if (card->options.performance_stats) - card->perf_stats.tx_csum++; + QETH_TXQ_STAT_INC(queue, skbs_csum); } } @@ -369,8 +368,8 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, } work_done++; budget--; - card->stats.rx_packets++; - card->stats.rx_bytes += len; + QETH_CARD_STAT_INC(card, rx_packets); + QETH_CARD_STAT_ADD(card, rx_bytes, len); } return work_done; } @@ -626,12 +625,13 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, int tx_bytes = skb->len; int rc; + queue = qeth_get_tx_queue(card, skb, ipv, cast_type); + if (card->state != CARD_STATE_UP) { - card->stats.tx_carrier_errors++; + QETH_TXQ_STAT_INC(queue, tx_carrier_errors); goto tx_drop; } - queue = qeth_get_tx_queue(card, skb, ipv, cast_type); netif_stop_queue(dev); if (IS_OSN(card)) @@ -641,8 +641,8 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, qeth_l2_fill_header); if (!rc) { - card->stats.tx_packets++; - card->stats.tx_bytes += tx_bytes; + QETH_TXQ_STAT_INC(queue, tx_packets); + QETH_TXQ_STAT_ADD(queue, tx_bytes, tx_bytes); netif_wake_queue(dev); return NETDEV_TX_OK; } else if (rc == -EBUSY) { @@ -650,8 +650,8 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, } /* else fall through */ tx_drop: - card->stats.tx_dropped++; - card->stats.tx_errors++; + QETH_TXQ_STAT_INC(queue, tx_dropped); + QETH_TXQ_STAT_INC(queue, tx_errors); dev_kfree_skb_any(skb); netif_wake_queue(dev); return NETDEV_TX_OK; @@ -699,7 +699,7 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) static const struct net_device_ops qeth_l2_netdev_ops = { .ndo_open = qeth_open, .ndo_stop = qeth_stop, - .ndo_get_stats = qeth_get_stats, + .ndo_get_stats64 = qeth_get_stats64, .ndo_start_xmit = qeth_l2_hard_start_xmit, .ndo_features_check = qeth_features_check, .ndo_validate_addr = qeth_l2_validate_addr, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 40c7d53f5512..07c3149e228c 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1315,12 +1315,11 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, ip_eth_mc_map(ip_hdr(skb)->daddr, tg_addr); else ipv6_eth_mc_map(&ipv6_hdr(skb)->daddr, tg_addr); - - card->stats.multicast++; + QETH_CARD_STAT_INC(card, rx_multicast); break; case QETH_CAST_BROADCAST: ether_addr_copy(tg_addr, card->dev->broadcast); - card->stats.multicast++; + QETH_CARD_STAT_INC(card, rx_multicast); break; default: if (card->options.sniffer) @@ -1401,8 +1400,8 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, } work_done++; budget--; - card->stats.rx_packets++; - card->stats.rx_bytes += len; + QETH_CARD_STAT_INC(card, rx_packets); + QETH_CARD_STAT_ADD(card, rx_bytes, len); } return work_done; } @@ -1945,12 +1944,13 @@ static u8 qeth_l3_cast_type_to_flag(int cast_type) return QETH_CAST_UNICAST; } -static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, - struct sk_buff *skb, int ipv, int cast_type, - unsigned int data_len) +static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue, + struct qeth_hdr *hdr, struct sk_buff *skb, + int ipv, int cast_type, unsigned int data_len) { struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3; struct vlan_ethhdr *veth = vlan_eth_hdr(skb); + struct qeth_card *card = queue->card; hdr->hdr.l3.length = data_len; @@ -1972,8 +1972,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, /* some HW requires combined L3+L4 csum offload: */ if (ipv == 4) hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_HDR_REQ; - if (card->options.performance_stats) - card->perf_stats.tx_csum++; + QETH_TXQ_STAT_INC(queue, skbs_csum); } } @@ -2074,6 +2073,8 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, int tx_bytes = skb->len; int rc; + queue = qeth_get_tx_queue(card, skb, ipv, cast_type); + if (IS_IQD(card)) { if (card->options.sniffer) goto tx_drop; @@ -2084,14 +2085,13 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, } if (card->state != CARD_STATE_UP) { - card->stats.tx_carrier_errors++; + QETH_TXQ_STAT_INC(queue, tx_carrier_errors); goto tx_drop; } if (cast_type == RTN_BROADCAST && !card->info.broadcast_capable) goto tx_drop; - queue = qeth_get_tx_queue(card, skb, ipv, cast_type); netif_stop_queue(dev); if (ipv == 4 || IS_IQD(card)) @@ -2101,8 +2101,8 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, qeth_l3_fill_header); if (!rc) { - card->stats.tx_packets++; - card->stats.tx_bytes += tx_bytes; + QETH_TXQ_STAT_INC(queue, tx_packets); + QETH_TXQ_STAT_ADD(queue, tx_bytes, tx_bytes); netif_wake_queue(dev); return NETDEV_TX_OK; } else if (rc == -EBUSY) { @@ -2110,8 +2110,8 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, } /* else fall through */ tx_drop: - card->stats.tx_dropped++; - card->stats.tx_errors++; + QETH_TXQ_STAT_INC(queue, tx_dropped); + QETH_TXQ_STAT_INC(queue, tx_errors); dev_kfree_skb_any(skb); netif_wake_queue(dev); return NETDEV_TX_OK; @@ -2153,7 +2153,7 @@ static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb, static const struct net_device_ops qeth_l3_netdev_ops = { .ndo_open = qeth_open, .ndo_stop = qeth_stop, - .ndo_get_stats = qeth_get_stats, + .ndo_get_stats64 = qeth_get_stats64, .ndo_start_xmit = qeth_l3_hard_start_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_rx_mode = qeth_l3_set_rx_mode, @@ -2168,7 +2168,7 @@ static const struct net_device_ops qeth_l3_netdev_ops = { static const struct net_device_ops qeth_l3_osa_netdev_ops = { .ndo_open = qeth_open, .ndo_stop = qeth_stop, - .ndo_get_stats = qeth_get_stats, + .ndo_get_stats64 = qeth_get_stats64, .ndo_start_xmit = qeth_l3_hard_start_xmit, .ndo_features_check = qeth_l3_osa_features_check, .ndo_validate_addr = eth_validate_addr, -- cgit v1.2.3 From 1b4d5e1c617e7c11a0461470122ab7723f99906c Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 15 Feb 2019 19:22:30 +0100 Subject: s390/qeth: add support for ETHTOOL_GRINGPARAM Implement a trivial callback that exposes the queue sizes. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_ethtool.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c index 9ce5ef5fcf7a..93a53fed4cf8 100644 --- a/drivers/s390/net/qeth_ethtool.c +++ b/drivers/s390/net/qeth_ethtool.c @@ -102,6 +102,22 @@ static void qeth_get_ethtool_stats(struct net_device *dev, txq_stats, TXQ_STATS_LEN); } +static void qeth_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *param) +{ + struct qeth_card *card = dev->ml_priv; + + param->rx_max_pending = QDIO_MAX_BUFFERS_PER_Q; + param->rx_mini_max_pending = 0; + param->rx_jumbo_max_pending = 0; + param->tx_max_pending = QDIO_MAX_BUFFERS_PER_Q; + + param->rx_pending = card->qdio.in_buf_pool.buf_count; + param->rx_mini_pending = 0; + param->rx_jumbo_pending = 0; + param->tx_pending = QDIO_MAX_BUFFERS_PER_Q; +} + static void qeth_get_strings(struct net_device *dev, u32 stringset, u8 *data) { struct qeth_card *card = dev->ml_priv; @@ -338,6 +354,7 @@ static int qeth_get_link_ksettings(struct net_device *netdev, const struct ethtool_ops qeth_ethtool_ops = { .get_link = ethtool_op_get_link, + .get_ringparam = qeth_get_ringparam, .get_strings = qeth_get_strings, .get_ethtool_stats = qeth_get_ethtool_stats, .get_sset_count = qeth_get_sset_count, -- cgit v1.2.3 From 8024cc9e854a8e3c6ced6731905caeb1e0037f5a Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Fri, 15 Feb 2019 19:22:31 +0100 Subject: s390/qeth: split out OSN netdev ops Rather than special-casing OSN in a number of places, just give this device type its own netdev_ops structure. When setting up the OSN net_device, also skip the handling of the various HW offloads (eg TSO). The device shouldn't be advertising any of them, and the OSN code paths in qeth don't have support for them. In particular RX VLAN filtering is not supported, so don't hook up those callbacks in the netdev_ops. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 3 --- drivers/s390/net/qeth_core_mpc.h | 1 + drivers/s390/net/qeth_l2_main.c | 32 ++++++++++++++++++++------------ 3 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6d93bb48b1d9..4708df39f129 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5850,9 +5850,6 @@ int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if (!card) return -ENODEV; - if (card->info.type == QETH_CARD_TYPE_OSN) - return -EPERM; - switch (cmd) { case SIOC_QETH_ADP_SET_SNMP_CONTROL: rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data); diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 4b1690380ebe..f8c5d4a9be13 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -81,6 +81,7 @@ enum qeth_card_types { #define IS_OSD(card) ((card)->info.type == QETH_CARD_TYPE_OSD) #define IS_OSM(card) ((card)->info.type == QETH_CARD_TYPE_OSM) #define IS_OSN(card) ((card)->info.type == QETH_CARD_TYPE_OSN) +#define IS_OSX(card) ((card)->info.type == QETH_CARD_TYPE_OSX) #define IS_VM_NIC(card) ((card)->info.guestlan) #define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18 diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index b1280a155953..2c9714215775 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -425,7 +425,7 @@ static int qeth_l2_validate_addr(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; - if (IS_OSN(card) || (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) + if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED) return eth_validate_addr(dev); QETH_CARD_TEXT(card, 4, "nomacadr"); @@ -441,9 +441,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) QETH_CARD_TEXT(card, 3, "setmac"); - if (card->info.type == QETH_CARD_TYPE_OSN || - card->info.type == QETH_CARD_TYPE_OSM || - card->info.type == QETH_CARD_TYPE_OSX) { + if (IS_OSM(card) || IS_OSX(card)) { QETH_CARD_TEXT(card, 3, "setmcTYP"); return -EOPNOTSUPP; } @@ -537,9 +535,6 @@ static void qeth_l2_set_rx_mode(struct net_device *dev) int i; int rc; - if (card->info.type == QETH_CARD_TYPE_OSN) - return; - QETH_CARD_TEXT(card, 3, "setmulti"); spin_lock_bh(&card->mclock); @@ -713,16 +708,28 @@ static const struct net_device_ops qeth_l2_netdev_ops = { .ndo_set_features = qeth_set_features }; +static const struct net_device_ops qeth_osn_netdev_ops = { + .ndo_open = qeth_open, + .ndo_stop = qeth_stop, + .ndo_get_stats64 = qeth_get_stats64, + .ndo_start_xmit = qeth_l2_hard_start_xmit, + .ndo_validate_addr = eth_validate_addr, + .ndo_tx_timeout = qeth_tx_timeout, +}; + static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) { int rc; - card->dev->priv_flags |= IFF_UNICAST_FLT; - card->dev->netdev_ops = &qeth_l2_netdev_ops; - if (IS_OSN(card)) + if (IS_OSN(card)) { + card->dev->netdev_ops = &qeth_osn_netdev_ops; card->dev->flags |= IFF_NOARP; - else - card->dev->needed_headroom = sizeof(struct qeth_hdr); + goto add_napi; + } + + card->dev->needed_headroom = sizeof(struct qeth_hdr); + card->dev->netdev_ops = &qeth_l2_netdev_ops; + card->dev->priv_flags |= IFF_UNICAST_FLT; if (IS_OSM(card)) { card->dev->features |= NETIF_F_VLAN_CHALLENGED; @@ -764,6 +771,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) PAGE_SIZE * (QDIO_MAX_ELEMENTS_PER_BUFFER - 1)); } +add_napi: netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT); rc = register_netdev(card->dev); if (!rc && carrier_ok) -- cgit v1.2.3 From f186a82b10dc229f9cd1e9f27f90cb0ce86e879d Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Thu, 14 Feb 2019 17:03:44 +0100 Subject: net: stmmac: use correct define to get rx timestamp on GMAC4 In dwmac4_wrback_get_rx_timestamp_status we looking for a RX timestamp. For that receive descriptors are handled and so we should use defines related to receive descriptors. It'll no change the functional behavior as RDES3_RDES1_VALID=TDES3_RS1V=BIT(26) but it makes code easier to read. Signed-off-by: Alexandre Torgue Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index 20299f6f65fc..90045fffd393 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -268,7 +268,7 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, void *next_desc, int ret = -EINVAL; /* Get the status from normal w/b descriptor */ - if (likely(p->des3 & TDES3_RS1V)) { + if (likely(le32_to_cpu(p->des3) & RDES3_RDES1_VALID)) { if (likely(le32_to_cpu(p->des1) & RDES1_TIMESTAMP_AVAILABLE)) { int i = 0; -- cgit v1.2.3 From 9a5dc8af441668a3db7fdcd927cb288be62c0a2e Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 17 Feb 2019 10:29:19 +0100 Subject: net: phy: add genphy_c45_an_config_aneg C45 configuration of 10/100 and multi-giga bit auto negotiation advertisement is standardized. Configuration of 1000Base-T however appears to be vendor specific. Move the generic code out of the Marvell driver into the common phy-c45.c file. v2: - change function name to genphy_c45_an_config_aneg Signed-off-by: Andrew Lunn [hkallweit1@gmail.com: use new helper linkmode_adv_to_mii_10gbt_adv_t and split patch] Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/phy.h | 1 + 2 files changed, 45 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 7af5fa81daf6..e17672bd180e 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -74,6 +74,50 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced); +/** + * genphy_c45_an_config_aneg - configure advertisement registers + * @phydev: target phy_device struct + * + * Configure advertisement registers based on modes set in phydev->advertising + * + * Returns negative errno code on failure, 0 if advertisement didn't change, + * or 1 if advertised modes changed. + */ +int genphy_c45_an_config_aneg(struct phy_device *phydev) +{ + int changed = 0, ret; + u32 adv; + + linkmode_and(phydev->advertising, phydev->advertising, + phydev->supported); + + adv = linkmode_adv_to_mii_adv_t(phydev->advertising); + + ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_100BASE4 | + ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, + adv); + if (ret < 0) + return ret; + if (ret > 0) + changed = 1; + + adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); + + ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV10G | + MDIO_AN_10GBT_CTRL_ADV5G | + MDIO_AN_10GBT_CTRL_ADV2_5G, + adv); + if (ret < 0) + return ret; + if (ret > 0) + changed = 1; + + return changed; +} +EXPORT_SYMBOL_GPL(genphy_c45_an_config_aneg); + /** * genphy_c45_an_disable_aneg - disable auto-negotiation * @phydev: target phy_device struct diff --git a/include/linux/phy.h b/include/linux/phy.h index bf1070c2a53b..3db507e68191 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1101,6 +1101,7 @@ int genphy_c45_read_link(struct phy_device *phydev); int genphy_c45_read_lpa(struct phy_device *phydev); int genphy_c45_read_pma(struct phy_device *phydev); int genphy_c45_pma_setup_forced(struct phy_device *phydev); +int genphy_c45_an_config_aneg(struct phy_device *phydev); int genphy_c45_an_disable_aneg(struct phy_device *phydev); int genphy_c45_read_mdix(struct phy_device *phydev); int genphy_c45_pma_read_abilities(struct phy_device *phydev); -- cgit v1.2.3 From 3de97f3c630850caf0fff67555bbe3f7ba61c308 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 17 Feb 2019 10:30:45 +0100 Subject: net: phy: marvell10g: use genphy_c45_an_config_aneg Use new function genphy_c45_config_aneg() in mv3310_config_aneg(). v2: - add a comment regarding 1000BaseT vendor registers v3: - rebased Signed-off-by: Andrew Lunn [hkallweit1@gmail.com: patch splitted] Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 496805c0ddfe..8955740832cc 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -279,18 +279,15 @@ static int mv3310_config_aneg(struct phy_device *phydev) return genphy_c45_an_disable_aneg(phydev); } - linkmode_and(phydev->advertising, phydev->advertising, - phydev->supported); - - ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_100BASE4 | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, - linkmode_adv_to_mii_adv_t(phydev->advertising)); + ret = genphy_c45_an_config_aneg(phydev); if (ret < 0) return ret; if (ret > 0) changed = true; + /* Clause 45 has no standardized support for 1000BaseT, therefore + * use vendor registers for this mode. + */ reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000, ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg); @@ -299,20 +296,6 @@ static int mv3310_config_aneg(struct phy_device *phydev) if (ret > 0) changed = true; - /* 10G control register */ - if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, - phydev->advertising)) - reg = MDIO_AN_10GBT_CTRL_ADV10G; - else - reg = 0; - - ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV10G, reg); - if (ret < 0) - return ret; - if (ret > 0) - changed = true; - if (changed) ret = genphy_c45_restart_aneg(phydev); -- cgit v1.2.3 From 3ce2a027ae4e3ede876da6913641ad37c33b698b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 17 Feb 2019 10:32:29 +0100 Subject: net: phy: marvell10g: check for newly set aneg Even if the advertisement registers content didn't change, we may have just switched to aneg, and therefore have to trigger an aneg restart. This matches the behavior of genphy_config_aneg(). Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 8955740832cc..b83eb19cf8bb 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -296,6 +296,16 @@ static int mv3310_config_aneg(struct phy_device *phydev) if (ret > 0) changed = true; + if (!changed) { + /* Configure and restart aneg if it wasn't set before */ + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); + if (ret < 0) + return ret; + + if (!(ret & MDIO_AN_CTRL1_ENABLE)) + changed = 1; + } + if (changed) ret = genphy_c45_restart_aneg(phydev); -- cgit v1.2.3 From 6a79507cfe94c7729207659501ff88914b3eb198 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Thu, 14 Feb 2019 20:22:55 +0000 Subject: mlxsw: core: Extend thermal module with per QSFP module thermal zones Add a dedicated thermal zone for each QSFP/SFP module. The current temperature is obtained from the module's temperature sensor and the trip points are set based on the warning and critical thresholds read from the module. A cooling device (fan) is bound to all the thermal zones. The thermal zone governor is set to user space in order to avoid collisions between thermal zones. For example, one thermal zone might want to increase the speed of the fan, whereas another one would like to decrease it. Deferring this decision to user space allows the user to the take the most suitable decision. Signed-off-by: Vadim Pasternak Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 400 +++++++++++++++++++++ 1 file changed, 400 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 821fef2e2230..0b85c7252f9e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -9,8 +9,10 @@ #include #include #include +#include #include "core.h" +#include "core_env.h" #define MLXSW_THERMAL_POLL_INT 1000 /* ms */ #define MLXSW_THERMAL_SLOW_POLL_INT 20000 /* ms */ @@ -19,6 +21,8 @@ #define MLXSW_THERMAL_ASIC_TEMP_HOT 105000 /* 105C */ #define MLXSW_THERMAL_ASIC_TEMP_CRIT 110000 /* 110C */ #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */ +#define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2) +#define MLXSW_THERMAL_ZONE_MAX_NAME 16 #define MLXSW_THERMAL_MAX_STATE 10 #define MLXSW_THERMAL_MAX_DUTY 255 /* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values @@ -36,6 +40,13 @@ static char * const mlxsw_thermal_external_allowed_cdev[] = { "mlxreg_fan", }; +enum mlxsw_thermal_trips { + MLXSW_THERMAL_TEMP_TRIP_NORM, + MLXSW_THERMAL_TEMP_TRIP_HIGH, + MLXSW_THERMAL_TEMP_TRIP_HOT, + MLXSW_THERMAL_TEMP_TRIP_CRIT, +}; + struct mlxsw_thermal_trip { int type; int temp; @@ -80,6 +91,16 @@ static const struct mlxsw_thermal_trip default_thermal_trips[] = { /* Make sure all trips are writable */ #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1) +struct mlxsw_thermal; + +struct mlxsw_thermal_module { + struct mlxsw_thermal *parent; + struct thermal_zone_device *tzdev; + struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; + enum thermal_device_mode mode; + int module; +}; + struct mlxsw_thermal { struct mlxsw_core *core; const struct mlxsw_bus_info *bus_info; @@ -89,6 +110,8 @@ struct mlxsw_thermal { u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; enum thermal_device_mode mode; + struct mlxsw_thermal_module *tz_module_arr; + unsigned int tz_module_num; }; static inline u8 mlxsw_state_to_duty(int state) @@ -122,6 +145,57 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal, return -ENODEV; } +static void +mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz) +{ + tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0; + tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0; + tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0; + tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = 0; +} + +static int +mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, + struct mlxsw_thermal_module *tz) +{ + int crit_temp, emerg_temp; + int err; + + err = mlxsw_env_module_temp_thresholds_get(core, tz->module, + SFP_TEMP_HIGH_WARN, + &crit_temp); + if (err) + return err; + + err = mlxsw_env_module_temp_thresholds_get(core, tz->module, + SFP_TEMP_HIGH_ALARM, + &emerg_temp); + if (err) + return err; + + /* According to the system thermal requirements, the thermal zones are + * defined with four trip points. The critical and emergency + * temperature thresholds, provided by QSFP module are set as "active" + * and "hot" trip points, "normal" and "critical" trip points are + * derived from "active" and "hot" by subtracting or adding double + * hysteresis value. + */ + if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT) + tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp - + MLXSW_THERMAL_MODULE_TEMP_SHIFT; + else + tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp; + tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp; + tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp; + if (emerg_temp > crit_temp) + tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp + + MLXSW_THERMAL_MODULE_TEMP_SHIFT; + else + tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp; + + return 0; +} + static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev, struct thermal_cooling_device *cdev) { @@ -291,6 +365,204 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = { .set_trip_hyst = mlxsw_thermal_set_trip_hyst, }; +static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, + struct thermal_cooling_device *cdev) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + struct mlxsw_thermal *thermal = tz->parent; + int i, j, err; + + /* If the cooling device is one of ours bind it */ + if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0) + return 0; + + for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) { + const struct mlxsw_thermal_trip *trip = &tz->trips[i]; + + err = thermal_zone_bind_cooling_device(tzdev, i, cdev, + trip->max_state, + trip->min_state, + THERMAL_WEIGHT_DEFAULT); + if (err < 0) + goto err_bind_cooling_device; + } + return 0; + +err_bind_cooling_device: + for (j = i - 1; j >= 0; j--) + thermal_zone_unbind_cooling_device(tzdev, j, cdev); + return err; +} + +static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, + struct thermal_cooling_device *cdev) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + struct mlxsw_thermal *thermal = tz->parent; + int i; + int err; + + /* If the cooling device is one of ours unbind it */ + if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0) + return 0; + + for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) { + err = thermal_zone_unbind_cooling_device(tzdev, i, cdev); + WARN_ON(err); + } + return err; +} + +static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev, + enum thermal_device_mode *mode) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + + *mode = tz->mode; + + return 0; +} + +static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev, + enum thermal_device_mode mode) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + struct mlxsw_thermal *thermal = tz->parent; + + mutex_lock(&tzdev->lock); + + if (mode == THERMAL_DEVICE_ENABLED) + tzdev->polling_delay = thermal->polling_delay; + else + tzdev->polling_delay = 0; + + mutex_unlock(&tzdev->lock); + + tz->mode = mode; + thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); + + return 0; +} + +static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, + int *p_temp) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + struct mlxsw_thermal *thermal = tz->parent; + struct device *dev = thermal->bus_info->dev; + char mtbr_pl[MLXSW_REG_MTBR_LEN]; + u16 temp; + int err; + + /* Read module temperature. */ + mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + + tz->module, 1); + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtbr), mtbr_pl); + if (err) + return err; + + mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL); + /* Update temperature. */ + switch (temp) { + case MLXSW_REG_MTBR_NO_CONN: /* fall-through */ + case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */ + case MLXSW_REG_MTBR_INDEX_NA: /* fall-through */ + case MLXSW_REG_MTBR_BAD_SENS_INFO: + temp = 0; + break; + default: + temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp); + /* Reset all trip point. */ + mlxsw_thermal_module_trips_reset(tz); + /* Update trip points. */ + err = mlxsw_thermal_module_trips_update(dev, thermal->core, + tz); + if (err) + return err; + break; + } + + *p_temp = (int) temp; + return 0; +} + +static int +mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip, + enum thermal_trip_type *p_type) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + + if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) + return -EINVAL; + + *p_type = tz->trips[trip].type; + return 0; +} + +static int +mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev, + int trip, int *p_temp) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + + if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) + return -EINVAL; + + *p_temp = tz->trips[trip].temp; + return 0; +} + +static int +mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev, + int trip, int temp) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + + if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS || + temp > tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp) + return -EINVAL; + + tz->trips[trip].temp = temp; + return 0; +} + +static int +mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip, + int *p_hyst) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + + *p_hyst = tz->trips[trip].hyst; + return 0; +} + +static int +mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip, + int hyst) +{ + struct mlxsw_thermal_module *tz = tzdev->devdata; + + tz->trips[trip].hyst = hyst; + return 0; +} + +static struct thermal_zone_params mlxsw_thermal_module_params = { + .governor_name = "user_space", +}; + +static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { + .bind = mlxsw_thermal_module_bind, + .unbind = mlxsw_thermal_module_unbind, + .get_mode = mlxsw_thermal_module_mode_get, + .set_mode = mlxsw_thermal_module_mode_set, + .get_temp = mlxsw_thermal_module_temp_get, + .get_trip_type = mlxsw_thermal_module_trip_type_get, + .get_trip_temp = mlxsw_thermal_module_trip_temp_get, + .set_trip_temp = mlxsw_thermal_module_trip_temp_set, + .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, + .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, +}; + static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, unsigned long *p_state) { @@ -391,6 +663,123 @@ static const struct thermal_cooling_device_ops mlxsw_cooling_ops = { .set_cur_state = mlxsw_thermal_set_cur_state, }; +static int +mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) +{ + char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; + int err; + + snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d", + module_tz->module + 1); + module_tz->tzdev = thermal_zone_device_register(tz_name, + MLXSW_THERMAL_NUM_TRIPS, + MLXSW_THERMAL_TRIP_MASK, + module_tz, + &mlxsw_thermal_module_ops, + &mlxsw_thermal_module_params, + 0, 0); + if (IS_ERR(module_tz->tzdev)) { + err = PTR_ERR(module_tz->tzdev); + return err; + } + + return 0; +} + +static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev) +{ + thermal_zone_device_unregister(tzdev); +} + +static int +mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core, + struct mlxsw_thermal *thermal, u8 local_port) +{ + struct mlxsw_thermal_module *module_tz; + char pmlp_pl[MLXSW_REG_PMLP_LEN]; + u8 width, module; + int err; + + mlxsw_reg_pmlp_pack(pmlp_pl, local_port); + err = mlxsw_reg_query(core, MLXSW_REG(pmlp), pmlp_pl); + if (err) + return err; + + width = mlxsw_reg_pmlp_width_get(pmlp_pl); + if (!width) + return 0; + + module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); + module_tz = &thermal->tz_module_arr[module]; + module_tz->module = module; + module_tz->parent = thermal; + memcpy(module_tz->trips, default_thermal_trips, + sizeof(thermal->trips)); + /* Initialize all trip point. */ + mlxsw_thermal_module_trips_reset(module_tz); + /* Update trip point according to the module data. */ + err = mlxsw_thermal_module_trips_update(dev, core, module_tz); + if (err) + return err; + + thermal->tz_module_num++; + + return 0; +} + +static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz) +{ + if (module_tz && module_tz->tzdev) { + mlxsw_thermal_module_tz_fini(module_tz->tzdev); + module_tz->tzdev = NULL; + } +} + +static int +mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core, + struct mlxsw_thermal *thermal) +{ + unsigned int module_count = mlxsw_core_max_ports(core); + int i, err; + + thermal->tz_module_arr = kcalloc(module_count, + sizeof(*thermal->tz_module_arr), + GFP_KERNEL); + if (!thermal->tz_module_arr) + return -ENOMEM; + + for (i = 1; i < module_count; i++) { + err = mlxsw_thermal_module_init(dev, core, thermal, i); + if (err) + goto err_unreg_tz_module_arr; + } + + for (i = 0; i < thermal->tz_module_num; i++) { + err = mlxsw_thermal_module_tz_init(&thermal->tz_module_arr[i]); + if (err) + goto err_unreg_tz_module_arr; + } + + return 0; + +err_unreg_tz_module_arr: + for (i = module_count - 1; i >= 0; i--) + mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]); + kfree(thermal->tz_module_arr); + return err; +} + +static void +mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal) +{ + unsigned int module_count = mlxsw_core_max_ports(thermal->core); + int i; + + for (i = module_count - 1; i >= 0; i--) + mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]); + kfree(thermal->tz_module_arr); +} + int mlxsw_thermal_init(struct mlxsw_core *core, const struct mlxsw_bus_info *bus_info, struct mlxsw_thermal **p_thermal) @@ -477,9 +866,19 @@ int mlxsw_thermal_init(struct mlxsw_core *core, goto err_unreg_cdevs; } + err = mlxsw_thermal_modules_init(dev, core, thermal); + if (err) + goto err_unreg_tzdev; + thermal->mode = THERMAL_DEVICE_ENABLED; *p_thermal = thermal; return 0; + +err_unreg_tzdev: + if (thermal->tzdev) { + thermal_zone_device_unregister(thermal->tzdev); + thermal->tzdev = NULL; + } err_unreg_cdevs: for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) if (thermal->cdevs[i]) @@ -493,6 +892,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) { int i; + mlxsw_thermal_modules_fini(thermal); if (thermal->tzdev) { thermal_zone_device_unregister(thermal->tzdev); thermal->tzdev = NULL; -- cgit v1.2.3 From a2703de7094211a77f458638289381b2955e0a5d Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 14 Feb 2019 22:15:31 +0100 Subject: net: phy: improve phy_resolve_aneg_linkmode We have the settings array of modes which is sorted based on aneg priority. Instead of checking each mode manually let's simply iterate over the sorted settings. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-core.c | 43 +++++++------------------------------------ 1 file changed, 7 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index de58a59815d5..5016cd5fd7c7 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -421,45 +421,16 @@ void of_set_phy_eee_broken(struct phy_device *phydev) void phy_resolve_aneg_linkmode(struct phy_device *phydev) { __ETHTOOL_DECLARE_LINK_MODE_MASK(common); + int i; linkmode_and(common, phydev->lp_advertising, phydev->advertising); - if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, common)) { - phydev->speed = SPEED_10000; - phydev->duplex = DUPLEX_FULL; - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, - common)) { - phydev->speed = SPEED_5000; - phydev->duplex = DUPLEX_FULL; - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - common)) { - phydev->speed = SPEED_2500; - phydev->duplex = DUPLEX_FULL; - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - common)) { - phydev->speed = SPEED_1000; - phydev->duplex = DUPLEX_FULL; - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, - common)) { - phydev->speed = SPEED_1000; - phydev->duplex = DUPLEX_HALF; - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, - common)) { - phydev->speed = SPEED_100; - phydev->duplex = DUPLEX_FULL; - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, - common)) { - phydev->speed = SPEED_100; - phydev->duplex = DUPLEX_HALF; - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, - common)) { - phydev->speed = SPEED_10; - phydev->duplex = DUPLEX_FULL; - } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, - common)) { - phydev->speed = SPEED_10; - phydev->duplex = DUPLEX_HALF; - } + for (i = 0; i < ARRAY_SIZE(settings); i++) + if (test_bit(settings[i].bit, common)) { + phydev->speed = settings[i].speed; + phydev->duplex = settings[i].duplex; + break; + } if (phydev->duplex == DUPLEX_FULL) { phydev->pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, -- cgit v1.2.3 From 5502b218e00161efd20ff1a789f51a332f13f8cd Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Thu, 14 Feb 2019 22:16:27 +0100 Subject: net: phy: use phy_resolve_aneg_linkmode in genphy_read_status Now that we have phy_resolve_aneg_linkmode() we can make genphy_read_status() much simpler. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index a752de2fff5e..7e71124bb20e 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1746,8 +1746,6 @@ int genphy_read_status(struct phy_device *phydev) int err; int lpa; int lpagb = 0; - int common_adv; - int common_adv_gb = 0; /* Update the link, but return if there was an error */ err = genphy_update_link(phydev); @@ -1779,7 +1777,6 @@ int genphy_read_status(struct phy_device *phydev) mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, lpagb); - common_adv_gb = lpagb & adv << 2; } lpa = phy_read(phydev, MII_LPA); @@ -1792,31 +1789,12 @@ int genphy_read_status(struct phy_device *phydev) if (adv < 0) return adv; - common_adv = lpa & adv; - phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; phydev->pause = 0; phydev->asym_pause = 0; - if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) { - phydev->speed = SPEED_1000; - - if (common_adv_gb & LPA_1000FULL) - phydev->duplex = DUPLEX_FULL; - } else if (common_adv & (LPA_100FULL | LPA_100HALF)) { - phydev->speed = SPEED_100; - - if (common_adv & LPA_100FULL) - phydev->duplex = DUPLEX_FULL; - } else - if (common_adv & LPA_10FULL) - phydev->duplex = DUPLEX_FULL; - - if (phydev->duplex == DUPLEX_FULL) { - phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; - phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; - } + phy_resolve_aneg_linkmode(phydev); } else { int bmcr = phy_read(phydev, MII_BMCR); -- cgit v1.2.3 From 5c5696f3df2acbe738526c7ba76ab7dd38e9ba49 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 14 Feb 2019 13:40:46 -0800 Subject: nfp: devlink: allow flashing the device via devlink Devlink now allows updating device flash. Implement this callback. Compared to ethtool update we no longer have to release the networking locks - devlink doesn't take them. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 10 ++++++ drivers/net/ethernet/netronome/nfp/nfp_main.c | 41 ++++++++++++++++++++++ drivers/net/ethernet/netronome/nfp/nfp_main.h | 2 ++ .../net/ethernet/netronome/nfp/nfp_net_ethtool.c | 35 ++---------------- 4 files changed, 56 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index 080a301f379e..db2da99f6aa7 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -330,6 +330,15 @@ err_close_nsp: return err; } +static int +nfp_devlink_flash_update(struct devlink *devlink, const char *path, + const char *component, struct netlink_ext_ack *extack) +{ + if (component) + return -EOPNOTSUPP; + return nfp_flash_update_common(devlink_priv(devlink), path, extack); +} + const struct devlink_ops nfp_devlink_ops = { .port_split = nfp_devlink_port_split, .port_unsplit = nfp_devlink_port_unsplit, @@ -338,6 +347,7 @@ const struct devlink_ops nfp_devlink_ops = { .eswitch_mode_get = nfp_devlink_eswitch_mode_get, .eswitch_mode_set = nfp_devlink_eswitch_mode_set, .info_get = nfp_devlink_info_get, + .flash_update = nfp_devlink_flash_update, }; int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.c b/drivers/net/ethernet/netronome/nfp/nfp_main.c index 6c10e8d119e4..f4c8776e42b6 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.c @@ -300,6 +300,47 @@ static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs) return nfp_pcie_sriov_enable(pdev, num_vfs); } +int nfp_flash_update_common(struct nfp_pf *pf, const char *path, + struct netlink_ext_ack *extack) +{ + struct device *dev = &pf->pdev->dev; + const struct firmware *fw; + struct nfp_nsp *nsp; + int err; + + nsp = nfp_nsp_open(pf->cpp); + if (IS_ERR(nsp)) { + err = PTR_ERR(nsp); + if (extack) + NL_SET_ERR_MSG_MOD(extack, "can't access NSP"); + else + dev_err(dev, "Failed to access the NSP: %d\n", err); + return err; + } + + err = request_firmware_direct(&fw, path, dev); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "unable to read flash file from disk"); + goto exit_close_nsp; + } + + dev_info(dev, "Please be patient while writing flash image: %s\n", + path); + + err = nfp_nsp_write_flash(nsp, fw); + if (err < 0) + goto exit_release_fw; + dev_info(dev, "Finished writing flash image\n"); + err = 0; + +exit_release_fw: + release_firmware(fw); +exit_close_nsp: + nfp_nsp_close(nsp); + return err; +} + static const struct firmware * nfp_net_fw_request(struct pci_dev *pdev, struct nfp_pf *pf, const char *name) { diff --git a/drivers/net/ethernet/netronome/nfp/nfp_main.h b/drivers/net/ethernet/netronome/nfp/nfp_main.h index a3613a2e0aa5..b7211f200d22 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_main.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_main.h @@ -164,6 +164,8 @@ nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt, unsigned int min_size, struct nfp_cpp_area **area); int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length, void *out_data, u64 out_length); +int nfp_flash_update_common(struct nfp_pf *pf, const char *path, + struct netlink_ext_ack *extack); enum nfp_dump_diag { NFP_DUMP_NSP_DIAG = 0, diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index cb9c512abc76..8f189149efc5 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -1237,11 +1237,8 @@ static int nfp_net_set_channels(struct net_device *netdev, static int nfp_net_flash_device(struct net_device *netdev, struct ethtool_flash *flash) { - const struct firmware *fw; struct nfp_app *app; - struct nfp_nsp *nsp; - struct device *dev; - int err; + int ret; if (flash->region != ETHTOOL_FLASH_ALL_REGIONS) return -EOPNOTSUPP; @@ -1250,39 +1247,13 @@ nfp_net_flash_device(struct net_device *netdev, struct ethtool_flash *flash) if (!app) return -EOPNOTSUPP; - dev = &app->pdev->dev; - - nsp = nfp_nsp_open(app->cpp); - if (IS_ERR(nsp)) { - err = PTR_ERR(nsp); - dev_err(dev, "Failed to access the NSP: %d\n", err); - return err; - } - - err = request_firmware_direct(&fw, flash->data, dev); - if (err) - goto exit_close_nsp; - - dev_info(dev, "Please be patient while writing flash image: %s\n", - flash->data); dev_hold(netdev); rtnl_unlock(); - - err = nfp_nsp_write_flash(nsp, fw); - if (err < 0) { - dev_err(dev, "Flash write failed: %d\n", err); - goto exit_rtnl_lock; - } - dev_info(dev, "Finished writing flash image\n"); - -exit_rtnl_lock: + ret = nfp_flash_update_common(app->pf, flash->data, NULL); rtnl_lock(); dev_put(netdev); - release_firmware(fw); -exit_close_nsp: - nfp_nsp_close(nsp); - return err; + return ret; } static const struct ethtool_ops nfp_net_ethtool_ops = { -- cgit v1.2.3 From 0496743b202ac0f2710ae243a493118ca5096c04 Mon Sep 17 00:00:00 2001 From: Pieter Jansen van Vuuren Date: Thu, 14 Feb 2019 14:37:16 -0800 Subject: nfp: flower: fix masks for tcp and ip flags fields Check mask fields of tcp and ip flags when setting the corresponding mask flag used in hardware. Fixes: 8f2566225ae2 ("flow_offload: add flow_rule and flow_match") Signed-off-by: Pieter Jansen van Vuuren Reviewed-by: John Hurley Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/flower/match.c | 35 +++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/flower/match.c b/drivers/net/ethernet/netronome/nfp/flower/match.c index 1279fa5da9e1..e03c8ef2c28c 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/match.c +++ b/drivers/net/ethernet/netronome/nfp/flower/match.c @@ -172,46 +172,51 @@ nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext, } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) { + u16 tcp_flags, tcp_flags_mask; struct flow_match_tcp match; - u16 tcp_flags; flow_rule_match_tcp(rule, &match); tcp_flags = be16_to_cpu(match.key->flags); + tcp_flags_mask = be16_to_cpu(match.mask->flags); - if (tcp_flags & TCPHDR_FIN) { + if (tcp_flags & TCPHDR_FIN) ext->flags |= NFP_FL_TCP_FLAG_FIN; + if (tcp_flags_mask & TCPHDR_FIN) msk->flags |= NFP_FL_TCP_FLAG_FIN; - } - if (tcp_flags & TCPHDR_SYN) { + + if (tcp_flags & TCPHDR_SYN) ext->flags |= NFP_FL_TCP_FLAG_SYN; + if (tcp_flags_mask & TCPHDR_SYN) msk->flags |= NFP_FL_TCP_FLAG_SYN; - } - if (tcp_flags & TCPHDR_RST) { + + if (tcp_flags & TCPHDR_RST) ext->flags |= NFP_FL_TCP_FLAG_RST; + if (tcp_flags_mask & TCPHDR_RST) msk->flags |= NFP_FL_TCP_FLAG_RST; - } - if (tcp_flags & TCPHDR_PSH) { + + if (tcp_flags & TCPHDR_PSH) ext->flags |= NFP_FL_TCP_FLAG_PSH; + if (tcp_flags_mask & TCPHDR_PSH) msk->flags |= NFP_FL_TCP_FLAG_PSH; - } - if (tcp_flags & TCPHDR_URG) { + + if (tcp_flags & TCPHDR_URG) ext->flags |= NFP_FL_TCP_FLAG_URG; + if (tcp_flags_mask & TCPHDR_URG) msk->flags |= NFP_FL_TCP_FLAG_URG; - } } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { struct flow_match_control match; flow_rule_match_control(rule, &match); - if (match.key->flags & FLOW_DIS_IS_FRAGMENT) { + if (match.key->flags & FLOW_DIS_IS_FRAGMENT) ext->flags |= NFP_FL_IP_FRAGMENTED; + if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) msk->flags |= NFP_FL_IP_FRAGMENTED; - } - if (match.key->flags & FLOW_DIS_FIRST_FRAG) { + if (match.key->flags & FLOW_DIS_FIRST_FRAG) ext->flags |= NFP_FL_IP_FRAG_FIRST; + if (match.mask->flags & FLOW_DIS_FIRST_FRAG) msk->flags |= NFP_FL_IP_FRAG_FIRST; - } } } -- cgit v1.2.3 From a0bc653b1d48671caa9d22a44ff98050f8efd3ea Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 15 Feb 2019 02:36:47 +0000 Subject: net: dsa: bcm_sf2: Remove set but not used variables 'v6_spec, v6_m_spec' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/dsa/bcm_sf2_cfp.c: In function 'bcm_sf2_cfp_ipv6_rule_set': drivers/net/dsa/bcm_sf2_cfp.c:606:40: warning: variable 'v6_m_spec' set but not used [-Wunused-but-set-variable] drivers/net/dsa/bcm_sf2_cfp.c:606:30: warning: variable 'v6_spec' set but not used [-Wunused-but-set-variable] It not used any more after commit e4f7ef54cbd8 ("dsa: bcm_sf2: use flow_rule infrastructure") Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2_cfp.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c index 0b9ca4bdf47e..e6234d209787 100644 --- a/drivers/net/dsa/bcm_sf2_cfp.c +++ b/drivers/net/dsa/bcm_sf2_cfp.c @@ -603,7 +603,6 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, unsigned int queue_num, struct ethtool_rx_flow_spec *fs) { - struct ethtool_tcpip6_spec *v6_spec, *v6_m_spec; struct ethtool_rx_flow_spec_input input = {}; unsigned int slice_num, rule_index[2]; const struct cfp_udf_layout *layout; @@ -618,13 +617,9 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, switch (fs->flow_type & ~FLOW_EXT) { case TCP_V6_FLOW: ip_proto = IPPROTO_TCP; - v6_spec = &fs->h_u.tcp_ip6_spec; - v6_m_spec = &fs->m_u.tcp_ip6_spec; break; case UDP_V6_FLOW: ip_proto = IPPROTO_UDP; - v6_spec = &fs->h_u.udp_ip6_spec; - v6_m_spec = &fs->m_u.udp_ip6_spec; break; default: return -EINVAL; -- cgit v1.2.3 From 56425638839cfb038adeba3fb5ff6a4466ec37f9 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Fri, 15 Feb 2019 09:33:47 +0100 Subject: net: phy: marvell10g: Don't explicitly set Pause and Asym_Pause The PHY core expects PHY drivers not to set Pause and Asym_Pause bits, unless the driver only wants to specify one of them due to HW limitation. In the case of the Marvell10g driver, we don't need to set them. Signed-off-by: Maxime Chevallier Suggested-by: Andrew Lunn Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index b83eb19cf8bb..f9e0a2fc0277 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -242,9 +242,6 @@ static int mv3310_config_init(struct phy_device *phydev) phydev->interface != PHY_INTERFACE_MODE_10GKR) return -ENODEV; - __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported); - __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported); - if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) { val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); if (val < 0) -- cgit v1.2.3 From 3edaded89649d042ef4060cecc42f5599f3054b6 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 16 Feb 2019 01:48:09 +0000 Subject: net: sgi: use GFP_ATOMIC under spin lock The function meth_init_tx_ring() is called from meth_tx_timeout(), in which spin_lock is held, so we should use GFP_ATOMIC instead. Fixes: 8d4c28fbc284 ("meth: pass struct device to DMA API functions") Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/sgi/meth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c index f425ab528224..f1271402ca21 100644 --- a/drivers/net/ethernet/sgi/meth.c +++ b/drivers/net/ethernet/sgi/meth.c @@ -214,7 +214,7 @@ static int meth_init_tx_ring(struct meth_private *priv) { /* Init TX ring */ priv->tx_ring = dma_alloc_coherent(&priv->pdev->dev, - TX_RING_BUFFER_SIZE, &priv->tx_ring_dma, GFP_KERNEL); + TX_RING_BUFFER_SIZE, &priv->tx_ring_dma, GFP_ATOMIC); if (!priv->tx_ring) return -ENOMEM; -- cgit v1.2.3 From e511f17b1fb40248e63677a6ab81a29b9b32080d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 16 Feb 2019 08:15:52 +0000 Subject: net: hns3: make function hclge_set_all_vf_rst() static Fixes the following sparse warning: drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c:2431:5: warning: symbol 'hclge_set_all_vf_rst' was not declared. Should it be static? Fixes: aa5c4f175be6 ("net: hns3: add reset handling for VF when doing PF reset") Signed-off-by: Wei Yongjun Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 0a64c7f2dc6c..75ec3094bbf9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2599,7 +2599,7 @@ static int hclge_set_vf_rst(struct hclge_dev *hdev, int func_id, bool reset) return hclge_cmd_send(&hdev->hw, &desc, 1); } -int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) +static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) { int i; -- cgit v1.2.3 From 761f1e9f99b2cec66397db59a8f77ff6cbbfa536 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 4 Feb 2019 19:03:10 +0000 Subject: Bluetooth: remove redundant zero check on count Variable count is never zero inside the loop so the check if count is zero is redundant and can be removed. Fix this. Detected by CoverityScan, CID#1466880 ("Logically dead code") Signed-off-by: Colin Ian King Signed-off-by: Marcel Holtmann --- drivers/bluetooth/h4_recv.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/h4_recv.h b/drivers/bluetooth/h4_recv.h index 307d82166f48..87ccaceadba7 100644 --- a/drivers/bluetooth/h4_recv.h +++ b/drivers/bluetooth/h4_recv.h @@ -67,9 +67,6 @@ static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev, while (count) { int i, len; - if (!count) - break; - if (!skb) { for (i = 0; i < pkts_count; i++) { if (buffer[0] != (&pkts[i])->type) -- cgit v1.2.3 From f9558270b85c865131586fad48d0ecf5b1ea597d Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Mon, 4 Feb 2019 20:36:41 +0530 Subject: Bluetooth: hci_qca: use wait_until_sent() for power pulses wcn3990 requires a power pulse to turn ON/OFF along with regulators. Sometimes we are observing the power pulses are sent out with some time delay, due to queuing these commands. This is causing synchronization issues with chip, which intern delay the chip setup or may end up with communication issues. Signed-off-by: Balakrishna Godavarthi Reviewed-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 53ac5ade532b..9a1c0a71b460 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -60,6 +60,7 @@ #define IBS_WAKE_RETRANS_TIMEOUT_MS 100 #define IBS_TX_IDLE_TIMEOUT_MS 2000 #define BAUDRATE_SETTLE_TIMEOUT_MS 300 +#define POWER_PULSE_TRANS_TIMEOUT_MS 100 /* susclk rate */ #define SUSCLK_RATE_32KHZ 32768 @@ -1013,11 +1014,10 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed) hci_uart_set_baudrate(hu, speed); } -static int qca_send_power_pulse(struct hci_dev *hdev, u8 cmd) +static int qca_send_power_pulse(struct hci_uart *hu, u8 cmd) { - struct hci_uart *hu = hci_get_drvdata(hdev); - struct qca_data *qca = hu->priv; - struct sk_buff *skb; + int ret; + int timeout = msecs_to_jiffies(POWER_PULSE_TRANS_TIMEOUT_MS); /* These power pulses are single byte command which are sent * at required baudrate to wcn3990. On wcn3990, we have an external @@ -1029,19 +1029,17 @@ static int qca_send_power_pulse(struct hci_dev *hdev, u8 cmd) * save power. Disabling hardware flow control is mandatory while * sending power pulses to SoC. */ - bt_dev_dbg(hdev, "sending power pulse %02x to SoC", cmd); - - skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL); - if (!skb) - return -ENOMEM; + bt_dev_dbg(hu->hdev, "sending power pulse %02x to controller", cmd); + serdev_device_write_flush(hu->serdev); hci_uart_set_flow_control(hu, true); + ret = serdev_device_write_buf(hu->serdev, &cmd, sizeof(cmd)); + if (ret < 0) { + bt_dev_err(hu->hdev, "failed to send power pulse %02x", cmd); + return ret; + } - skb_put_u8(skb, cmd); - hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; - - skb_queue_tail(&qca->txq, skb); - hci_uart_tx_wakeup(hu); + serdev_device_wait_until_sent(hu->serdev, timeout); /* Wait for 100 uS for SoC to settle down */ usleep_range(100, 200); @@ -1116,7 +1114,6 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) static int qca_wcn3990_init(struct hci_uart *hu) { - struct hci_dev *hdev = hu->hdev; struct qca_serdev *qcadev; int ret; @@ -1139,12 +1136,12 @@ static int qca_wcn3990_init(struct hci_uart *hu) /* Forcefully enable wcn3990 to enter in to boot mode. */ host_set_baudrate(hu, 2400); - ret = qca_send_power_pulse(hdev, QCA_WCN3990_POWEROFF_PULSE); + ret = qca_send_power_pulse(hu, QCA_WCN3990_POWEROFF_PULSE); if (ret) return ret; qca_set_speed(hu, QCA_INIT_SPEED); - ret = qca_send_power_pulse(hdev, QCA_WCN3990_POWERON_PULSE); + ret = qca_send_power_pulse(hu, QCA_WCN3990_POWERON_PULSE); if (ret) return ret; @@ -1277,13 +1274,8 @@ static const struct qca_vreg_data qca_soc_data = { static void qca_power_shutdown(struct hci_uart *hu) { - struct serdev_device *serdev = hu->serdev; - unsigned char cmd = QCA_WCN3990_POWEROFF_PULSE; - host_set_baudrate(hu, 2400); - hci_uart_set_flow_control(hu, true); - serdev_device_write_buf(serdev, &cmd, sizeof(cmd)); - hci_uart_set_flow_control(hu, false); + qca_send_power_pulse(hu, QCA_WCN3990_POWEROFF_PULSE); qca_power_setup(hu, false); } -- cgit v1.2.3 From 78e8fa2972e5583bdda8103925217f5e1215b767 Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Mon, 4 Feb 2019 20:36:42 +0530 Subject: Bluetooth: hci_qca: Deassert RTS while baudrate change command This patch will help to stop frame reassembly errors while changing the baudrate. This is because host send a change baudrate request command to the chip with 115200 bps, Whereas chip will change their UART clocks to the enable for new baudrate and sends the response for the change request command with newer baudrate, On host side we are still operating in 115200 bps which results of reading garbage data. Here we are pulling RTS line, so that chip we will wait to send data to host until host change its baudrate. Signed-off-by: Balakrishna Godavarthi Tested-by: Matthias Kaehlcke Reviewed-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 9a1c0a71b460..e3cf0dbfc89d 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -964,7 +964,6 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; struct sk_buff *skb; - struct qca_serdev *qcadev; u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; if (baudrate > QCA_BAUDRATE_3200000) @@ -978,13 +977,6 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) return -ENOMEM; } - /* Disabling hardware flow control is mandatory while - * sending change baudrate request to wcn3990 SoC. - */ - qcadev = serdev_device_get_drvdata(hu->serdev); - if (qcadev->btsoc_type == QCA_WCN3990) - hci_uart_set_flow_control(hu, true); - /* Assign commands to change baudrate and packet type. */ skb_put_data(skb, cmd, sizeof(cmd)); hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; @@ -1000,9 +992,6 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS)); set_current_state(TASK_RUNNING); - if (qcadev->btsoc_type == QCA_WCN3990) - hci_uart_set_flow_control(hu, false); - return 0; } @@ -1089,7 +1078,8 @@ static int qca_check_speeds(struct hci_uart *hu) static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) { unsigned int speed, qca_baudrate; - int ret; + struct qca_serdev *qcadev; + int ret = 0; if (speed_type == QCA_INIT_SPEED) { speed = qca_get_speed(hu, QCA_INIT_SPEED); @@ -1100,16 +1090,27 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) if (!speed) return 0; + /* Disable flow control for wcn3990 to deassert RTS while + * changing the baudrate of chip and host. + */ + qcadev = serdev_device_get_drvdata(hu->serdev); + if (qcadev->btsoc_type == QCA_WCN3990) + hci_uart_set_flow_control(hu, true); + qca_baudrate = qca_get_baudrate_value(speed); bt_dev_dbg(hu->hdev, "Set UART speed to %d", speed); ret = qca_set_baudrate(hu->hdev, qca_baudrate); if (ret) - return ret; + goto error; host_set_baudrate(hu, speed); + +error: + if (qcadev->btsoc_type == QCA_WCN3990) + hci_uart_set_flow_control(hu, false); } - return 0; + return ret; } static int qca_wcn3990_init(struct hci_uart *hu) -- cgit v1.2.3 From 035a960e7a279a59d74585105dcd263559d74f24 Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Mon, 4 Feb 2019 20:36:43 +0530 Subject: Bluetooth: hci_qca: Disable IBS state machine and flush Tx buffer During hci down we observed IBS sleep commands are queued in the Tx buffer and hci_uart_write_work is sending data to the chip which is not required as the chip is powered off. This patch will disable IBS and flush the Tx buffer before we turn off the chip. Signed-off-by: Balakrishna Godavarthi Reviewed-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index e3cf0dbfc89d..5e03504c4e0c 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -771,16 +771,17 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb) /* Prepend skb with frame type */ memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); + spin_lock_irqsave(&qca->hci_ibs_lock, flags); + /* Don't go to sleep in middle of patch download or * Out-Of-Band(GPIOs control) sleep is selected. */ if (!test_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags)) { skb_queue_tail(&qca->txq, skb); + spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); return 0; } - spin_lock_irqsave(&qca->hci_ibs_lock, flags); - /* Act according to current state */ switch (qca->tx_ibs_state) { case HCI_IBS_TX_AWAKE: @@ -1275,6 +1276,18 @@ static const struct qca_vreg_data qca_soc_data = { static void qca_power_shutdown(struct hci_uart *hu) { + struct qca_data *qca = hu->priv; + unsigned long flags; + + /* From this point we go into power off state. But serial port is + * still open, stop queueing the IBS data and flush all the buffered + * data in skb's. + */ + spin_lock_irqsave(&qca->hci_ibs_lock, flags); + clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); + qca_flush(hu); + spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); + host_set_baudrate(hu, 2400); qca_send_power_pulse(hu, QCA_WCN3990_POWEROFF_PULSE); qca_power_setup(hu, false); -- cgit v1.2.3 From 32a7b4cbe93b0a0ef7e63d31ca69ce54736c4412 Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Wed, 6 Feb 2019 12:54:16 -0500 Subject: Bluetooth: hci_ldisc: Initialize hci_dev before open() The hci_dev struct hdev is referenced in work queues and timers started by open() in some protocols. This creates a race between the initialization function and the work or timer which can result hdev being dereferenced while it is still null. The syzbot report contains a reliable reproducer which causes a null pointer dereference of hdev in hci_uart_write_work() by making the memory allocation for hdev fail. To fix this, ensure hdev is valid from before calling a protocol's open() until after calling a protocol's close(). Reported-by: syzbot+257790c15bcdef6fe00c@syzkaller.appspotmail.com Signed-off-by: Jeremy Cline Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ldisc.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index fbf7b4df23ab..4918fefc4a6f 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -207,11 +207,11 @@ void hci_uart_init_work(struct work_struct *work) err = hci_register_dev(hu->hdev); if (err < 0) { BT_ERR("Can't register HCI device"); + clear_bit(HCI_UART_PROTO_READY, &hu->flags); + hu->proto->close(hu); hdev = hu->hdev; hu->hdev = NULL; hci_free_dev(hdev); - clear_bit(HCI_UART_PROTO_READY, &hu->flags); - hu->proto->close(hu); return; } @@ -616,6 +616,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, static int hci_uart_register_dev(struct hci_uart *hu) { struct hci_dev *hdev; + int err; BT_DBG(""); @@ -659,11 +660,22 @@ static int hci_uart_register_dev(struct hci_uart *hu) else hdev->dev_type = HCI_PRIMARY; + /* Only call open() for the protocol after hdev is fully initialized as + * open() (or a timer/workqueue it starts) may attempt to reference it. + */ + err = hu->proto->open(hu); + if (err) { + hu->hdev = NULL; + hci_free_dev(hdev); + return err; + } + if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) return 0; if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); + hu->proto->close(hu); hu->hdev = NULL; hci_free_dev(hdev); return -ENODEV; @@ -683,17 +695,12 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) if (!p) return -EPROTONOSUPPORT; - err = p->open(hu); - if (err) - return err; - hu->proto = p; set_bit(HCI_UART_PROTO_READY, &hu->flags); err = hci_uart_register_dev(hu); if (err) { clear_bit(HCI_UART_PROTO_READY, &hu->flags); - p->close(hu); return err; } -- cgit v1.2.3 From adf5d73056d185eff31a04aa91f5cb0a2ae22152 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 15 Feb 2019 07:19:34 +0800 Subject: Bluetooth: mediatek: trivial typo fix add a trivial typo fix from speicfic to specific Fixes: 7237c4c9ec92 ("Bluetooth: mediatek: Add protocol support for MediaTek serial devices") Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtkuart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index 4593baff2bc9..b8ea011b82d8 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -107,7 +107,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen, * Complete as with usual HCI command flow control. * * After sending the command, wait for BTMTKUART_TX_WAIT_VND_EVT - * state to be cleared. The driver speicfic event receive routine + * state to be cleared. The driver specific event receive routine * will clear that state and with that indicate completion of the * WMT command. */ -- cgit v1.2.3 From 77f328dbc6cf42f22c691a164958a5452142a542 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 15 Feb 2019 07:19:35 +0800 Subject: Bluetooth: mediatek: fix up an error path to restore bdev->tx_state Restore bdev->tx_state with clearing bit BTMTKUART_TX_WAIT_VND_EVT when there is an error on waiting for the corresponding event. Fixes: 7237c4c9ec92 ("Bluetooth: mediatek: Add protocol support for MediaTek serial devices") Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtkuart.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index b8ea011b82d8..9f8177b216b6 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -115,11 +115,13 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen, TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT); if (err == -EINTR) { bt_dev_err(hdev, "Execution of wmt command interrupted"); + clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); return err; } if (err) { bt_dev_err(hdev, "Execution of wmt command timed out"); + clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); return -ETIMEDOUT; } -- cgit v1.2.3 From 88e5f366a1903bfb717ad37a72f4657dae4d81da Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 15 Feb 2019 07:19:36 +0800 Subject: Bluetooth: mediatek: pass a pointer to mtk_hci_wmt_sync Pass a structure pointer to mtk_hci_wmt_sync rather than several arguments to avoid take up additional stack area and be better to read the code. Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtkuart.c | 63 ++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index 9f8177b216b6..4451b1db139a 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -58,6 +58,14 @@ struct mtk_hci_wmt_cmd { u8 data[256]; } __packed; +struct btmtk_hci_wmt_params { + u8 op; + u8 flag; + u16 dlen; + const void *data; + u32 *status; +}; + struct btmtkuart_dev { struct hci_dev *hdev; struct serdev_device *serdev; @@ -74,8 +82,8 @@ struct btmtkuart_dev { u16 stp_dlen; }; -static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen, - const void *param) +static int mtk_hci_wmt_sync(struct hci_dev *hdev, + struct btmtk_hci_wmt_params *wmt_params) { struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); struct mtk_hci_wmt_cmd wc; @@ -83,16 +91,16 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen, u32 hlen; int err; - hlen = sizeof(*hdr) + plen; + hlen = sizeof(*hdr) + wmt_params->dlen; if (hlen > 255) return -EINVAL; hdr = (struct mtk_wmt_hdr *)&wc; hdr->dir = 1; - hdr->op = op; - hdr->dlen = cpu_to_le16(plen + 1); - hdr->flag = flag; - memcpy(wc.data, param, plen); + hdr->op = wmt_params->op; + hdr->dlen = cpu_to_le16(wmt_params->dlen + 1); + hdr->flag = wmt_params->flag; + memcpy(wc.data, wmt_params->data, wmt_params->dlen); set_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state); @@ -130,6 +138,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, u8 op, u8 flag, u16 plen, static int mtk_setup_fw(struct hci_dev *hdev) { + struct btmtk_hci_wmt_params wmt_params; const struct firmware *fw; const u8 *fw_ptr; size_t fw_size; @@ -155,6 +164,9 @@ static int mtk_setup_fw(struct hci_dev *hdev) fw_ptr += 30; flag = 1; + wmt_params.op = MTK_WMT_PATCH_DWNLD; + wmt_params.status = NULL; + while (fw_size > 0) { dlen = min_t(int, 250, fw_size); @@ -164,8 +176,11 @@ static int mtk_setup_fw(struct hci_dev *hdev) else if (fw_size < fw->size - 30) flag = 2; - err = mtk_hci_wmt_sync(hdev, MTK_WMT_PATCH_DWNLD, flag, dlen, - fw_ptr); + wmt_params.flag = flag; + wmt_params.dlen = dlen; + wmt_params.data = fw_ptr; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); if (err < 0) { bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", err); @@ -469,6 +484,7 @@ static int btmtkuart_flush(struct hci_dev *hdev) static int btmtkuart_setup(struct hci_dev *hdev) { + struct btmtk_hci_wmt_params wmt_params; u8 param = 0x1; int err = 0; @@ -477,16 +493,27 @@ static int btmtkuart_setup(struct hci_dev *hdev) if (err < 0) return err; - /* Activate function the firmware providing to */ - err = mtk_hci_wmt_sync(hdev, MTK_WMT_RST, 0x4, 0, 0); + wmt_params.op = MTK_WMT_RST; + wmt_params.flag = 4; + wmt_params.dlen = 0; + wmt_params.data = NULL; + wmt_params.status = NULL; + + /* Activate funciton the firmware providing to */ + err = mtk_hci_wmt_sync(hdev, &wmt_params); if (err < 0) { bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); return err; } /* Enable Bluetooth protocol */ - err = mtk_hci_wmt_sync(hdev, MTK_WMT_FUNC_CTRL, 0x0, sizeof(param), - ¶m); + wmt_params.op = MTK_WMT_FUNC_CTRL; + wmt_params.flag = 0; + wmt_params.dlen = sizeof(param); + wmt_params.data = ¶m; + wmt_params.status = NULL; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); if (err < 0) { bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); return err; @@ -497,12 +524,18 @@ static int btmtkuart_setup(struct hci_dev *hdev) static int btmtkuart_shutdown(struct hci_dev *hdev) { + struct btmtk_hci_wmt_params wmt_params; u8 param = 0x0; int err; /* Disable the device */ - err = mtk_hci_wmt_sync(hdev, MTK_WMT_FUNC_CTRL, 0x0, sizeof(param), - ¶m); + wmt_params.op = MTK_WMT_FUNC_CTRL; + wmt_params.flag = 0; + wmt_params.dlen = sizeof(param); + wmt_params.data = ¶m; + wmt_params.status = NULL; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); if (err < 0) { bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err); return err; -- cgit v1.2.3 From e0b67035a90b58d01f911fed77b6e3da153da66e Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Fri, 15 Feb 2019 07:19:37 +0800 Subject: Bluetooth: mediatek: update the common setup between MT7622 and other devices Update the setup sequence on MT7622 to apply the same flow with MT7663U and MT7668U USB [1] as much as possible. These additional commands are required to parse the corresponding event to determine what current state the Bluetooth device is on and thus it's necessary to extend mtk_hci_wmt_sync to support the reading status in the same patch. [1] http://lists.infradead.org/pipermail/linux-mediatek/2019-January/017074.html Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtkuart.c | 204 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 190 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index 4451b1db139a..e73b1013ba73 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +38,17 @@ enum { MTK_WMT_PATCH_DWNLD = 0x1, MTK_WMT_FUNC_CTRL = 0x6, - MTK_WMT_RST = 0x7 + MTK_WMT_RST = 0x7, + MTK_WMT_SEMAPHORE = 0x17, +}; + +enum { + BTMTK_WMT_INVALID, + BTMTK_WMT_PATCH_UNDONE, + BTMTK_WMT_PATCH_DONE, + BTMTK_WMT_ON_UNDONE, + BTMTK_WMT_ON_DONE, + BTMTK_WMT_ON_PROGRESS, }; struct mtk_stp_hdr { @@ -58,6 +69,24 @@ struct mtk_hci_wmt_cmd { u8 data[256]; } __packed; +struct btmtk_hci_wmt_evt { + struct hci_event_hdr hhdr; + struct mtk_wmt_hdr whdr; +} __packed; + +struct btmtk_hci_wmt_evt_funcc { + struct btmtk_hci_wmt_evt hwhdr; + __be16 status; +} __packed; + +struct btmtk_tci_sleep { + u8 mode; + __le16 duration; + __le16 host_duration; + u8 host_wakeup_pin; + u8 time_compensation; +} __packed; + struct btmtk_hci_wmt_params { u8 op; u8 flag; @@ -76,6 +105,7 @@ struct btmtkuart_dev { struct sk_buff_head txq; struct sk_buff *rx_skb; + struct sk_buff *evt_skb; u8 stp_pad[6]; u8 stp_cursor; @@ -86,9 +116,11 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, struct btmtk_hci_wmt_params *wmt_params) { struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); + struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc; + u32 hlen, status = BTMTK_WMT_INVALID; + struct btmtk_hci_wmt_evt *wmt_evt; struct mtk_hci_wmt_cmd wc; struct mtk_wmt_hdr *hdr; - u32 hlen; int err; hlen = sizeof(*hdr) + wmt_params->dlen; @@ -133,7 +165,41 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev, return -ETIMEDOUT; } - return 0; + /* Parse and handle the return WMT event */ + wmt_evt = (struct btmtk_hci_wmt_evt *)bdev->evt_skb->data; + if (wmt_evt->whdr.op != hdr->op) { + bt_dev_err(hdev, "Wrong op received %d expected %d", + wmt_evt->whdr.op, hdr->op); + err = -EIO; + goto err_free_skb; + } + + switch (wmt_evt->whdr.op) { + case MTK_WMT_SEMAPHORE: + if (wmt_evt->whdr.flag == 2) + status = BTMTK_WMT_PATCH_UNDONE; + else + status = BTMTK_WMT_PATCH_DONE; + break; + case MTK_WMT_FUNC_CTRL: + wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt; + if (be16_to_cpu(wmt_evt_funcc->status) == 0x404) + status = BTMTK_WMT_ON_DONE; + else if (be16_to_cpu(wmt_evt_funcc->status) == 0x420) + status = BTMTK_WMT_ON_PROGRESS; + else + status = BTMTK_WMT_ON_UNDONE; + break; + } + + if (wmt_params->status) + *wmt_params->status = status; + +err_free_skb: + kfree_skb(bdev->evt_skb); + bdev->evt_skb = NULL; + + return err; } static int mtk_setup_fw(struct hci_dev *hdev) @@ -184,13 +250,29 @@ static int mtk_setup_fw(struct hci_dev *hdev) if (err < 0) { bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)", err); - break; + goto free_fw; } fw_size -= dlen; fw_ptr += dlen; } + wmt_params.op = MTK_WMT_RST; + wmt_params.flag = 4; + wmt_params.dlen = 0; + wmt_params.data = NULL; + wmt_params.status = NULL; + + /* Activate funciton the firmware providing to */ + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); + goto free_fw; + } + + /* Wait a few moments for firmware activation done */ + usleep_range(10000, 12000); + free_fw: release_firmware(fw); return err; @@ -209,7 +291,20 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb) if (hdr->evt == 0xe4) hdr->evt = HCI_EV_VENDOR; + /* When someone waits for the WMT event, the skb is being cloned + * and being processed the events from there then. + */ + if (test_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state)) { + bdev->evt_skb = skb_clone(skb, GFP_KERNEL); + if (!bdev->evt_skb) { + err = -ENOMEM; + goto err_out; + } + } + err = hci_recv_frame(hdev, skb); + if (err < 0) + goto err_free_skb; if (hdr->evt == HCI_EV_VENDOR) { if (test_and_clear_bit(BTMTKUART_TX_WAIT_VND_EVT, @@ -220,6 +315,13 @@ static int btmtkuart_recv_event(struct hci_dev *hdev, struct sk_buff *skb) } } + return 0; + +err_free_skb: + kfree_skb(bdev->evt_skb); + bdev->evt_skb = NULL; + +err_out: return err; } @@ -482,28 +584,79 @@ static int btmtkuart_flush(struct hci_dev *hdev) return 0; } +static int btmtkuart_func_query(struct hci_dev *hdev) +{ + struct btmtk_hci_wmt_params wmt_params; + int status, err; + u8 param = 0; + + /* Query whether the function is enabled */ + wmt_params.op = MTK_WMT_FUNC_CTRL; + wmt_params.flag = 4; + wmt_params.dlen = sizeof(param); + wmt_params.data = ¶m; + wmt_params.status = &status; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to query function status (%d)", err); + return err; + } + + return status; +} + static int btmtkuart_setup(struct hci_dev *hdev) { struct btmtk_hci_wmt_params wmt_params; + ktime_t calltime, delta, rettime; + struct btmtk_tci_sleep tci_sleep; + unsigned long long duration; + struct sk_buff *skb; + int err, status; u8 param = 0x1; - int err = 0; - /* Setup a firmware which the device definitely requires */ - err = mtk_setup_fw(hdev); - if (err < 0) - return err; + calltime = ktime_get(); - wmt_params.op = MTK_WMT_RST; - wmt_params.flag = 4; + /* Query whether the firmware is already download */ + wmt_params.op = MTK_WMT_SEMAPHORE; + wmt_params.flag = 1; wmt_params.dlen = 0; wmt_params.data = NULL; - wmt_params.status = NULL; + wmt_params.status = &status; - /* Activate funciton the firmware providing to */ err = mtk_hci_wmt_sync(hdev, &wmt_params); if (err < 0) { - bt_dev_err(hdev, "Failed to send wmt rst (%d)", err); + bt_dev_err(hdev, "Failed to query firmware status (%d)", err); + return err; + } + + if (status == BTMTK_WMT_PATCH_DONE) { + bt_dev_info(hdev, "Firmware already downloaded"); + goto ignore_setup_fw; + } + + /* Setup a firmware which the device definitely requires */ + err = mtk_setup_fw(hdev); + if (err < 0) return err; + +ignore_setup_fw: + /* Query whether the device is already enabled */ + err = readx_poll_timeout(btmtkuart_func_query, hdev, status, + status < 0 || status != BTMTK_WMT_ON_PROGRESS, + 2000, 5000000); + /* -ETIMEDOUT happens */ + if (err < 0) + return err; + + /* The other errors happen in btusb_mtk_func_query */ + if (status < 0) + return status; + + if (status == BTMTK_WMT_ON_DONE) { + bt_dev_info(hdev, "function already on"); + goto ignore_func_on; } /* Enable Bluetooth protocol */ @@ -519,6 +672,29 @@ static int btmtkuart_setup(struct hci_dev *hdev) return err; } +ignore_func_on: + /* Apply the low power environment setup */ + tci_sleep.mode = 0x5; + tci_sleep.duration = cpu_to_le16(0x640); + tci_sleep.host_duration = cpu_to_le16(0x640); + tci_sleep.host_wakeup_pin = 0; + tci_sleep.time_compensation = 0; + + skb = __hci_cmd_sync(hdev, 0xfc7a, sizeof(tci_sleep), &tci_sleep, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "Failed to apply low power setting (%d)", err); + return err; + } + kfree_skb(skb); + + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + duration = (unsigned long long)ktime_to_ns(delta) >> 10; + + bt_dev_info(hdev, "Device setup in %llu usecs", duration); + return 0; } -- cgit v1.2.3 From 06662264ce2ad6810af4233424d501036a273223 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 30 Jan 2019 17:02:13 +0100 Subject: mt76x02: use mask for vifs Use vif_mask to count interfaces to allow to set mac address in HW if there is only one interface and report error if we create interface with wrong BSSID resulting in already used index. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02.h | 2 ++ drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 11 +++++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6d96766a6ed3..be077443bdb0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -73,6 +73,8 @@ struct mt76x02_dev { struct mutex phy_mutex; + u16 vif_mask; + u8 txdone_seq; DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 062614ad0d51..c9340096c187 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -309,6 +309,15 @@ mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) if (vif->type == NL80211_IFTYPE_STATION) idx += 8; + if (dev->vif_mask & BIT(idx)) + return -EBUSY; + + /* Allow to change address in HW if we create first interface. */ + if (!dev->vif_mask && !ether_addr_equal(dev->mt76.macaddr, vif->addr)) + mt76x02_mac_setaddr(dev, vif->addr); + + dev->vif_mask |= BIT(idx); + mt76x02_vif_init(dev, vif, idx); return 0; } @@ -318,8 +327,10 @@ void mt76x02_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mt76x02_dev *dev = hw->priv; + struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; mt76_txq_remove(&dev->mt76, vif->txq); + dev->vif_mask &= ~BIT(mvif->idx); } EXPORT_SYMBOL_GPL(mt76x02_remove_interface); -- cgit v1.2.3 From f9a043c582193cc6e2ab26ac36630432a4521508 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 30 Jan 2019 17:02:14 +0100 Subject: mt76x02: use commmon add interface for mt76x2u Since we now support mt76x2u feature to allow set mac address when creating interface in common code we can use it for mt76x2u. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02.h | 3 +-- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 6 +++--- drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 15 +-------------- 3 files changed, 5 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index be077443bdb0..6d9d9ddacc32 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -130,8 +130,7 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev); -void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, - unsigned int idx); + int mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void mt76x02_remove_interface(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index c9340096c187..18434b06e706 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -268,8 +268,9 @@ void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(mt76x02_sta_remove); -void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, - unsigned int idx) +static void +mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, + unsigned int idx) { struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv; struct mt76_txq *mtxq; @@ -282,7 +283,6 @@ void mt76x02_vif_init(struct mt76x02_dev *dev, struct ieee80211_vif *vif, mt76_txq_init(&dev->mt76, vif->txq); } -EXPORT_SYMBOL_GPL(mt76x02_vif_init); int mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 286c7f451090..5256c6f879a7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -46,19 +46,6 @@ static void mt76x2u_stop(struct ieee80211_hw *hw) mutex_unlock(&dev->mt76.mutex); } -static int mt76x2u_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct mt76x02_dev *dev = hw->priv; - unsigned int idx = 8; - - if (!ether_addr_equal(dev->mt76.macaddr, vif->addr)) - mt76x02_mac_setaddr(dev, vif->addr); - - mt76x02_vif_init(dev, vif, idx); - return 0; -} - static int mt76x2u_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) @@ -125,7 +112,7 @@ const struct ieee80211_ops mt76x2u_ops = { .tx = mt76x02_tx, .start = mt76x2u_start, .stop = mt76x2u_stop, - .add_interface = mt76x2u_add_interface, + .add_interface = mt76x02_add_interface, .remove_interface = mt76x02_remove_interface, .sta_state = mt76_sta_state, .set_key = mt76x02_set_key, -- cgit v1.2.3 From 0b2d27e5b82c78ac98a1106b3387910c643ee09c Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 30 Jan 2019 17:02:15 +0100 Subject: mt76x02: initialize mutli bss mode when set up address BSSID is not strtirct related with beaconing (for example we can have 2 STA vifs) and more related with MAC address, so initaize BSSID when setting MAC address. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 15 ++++++++++++++- drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 13 ++----------- drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c | 4 +--- 4 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 63fa27d2c404..ae1727e433f3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -548,8 +548,11 @@ mt76x02_mac_process_rate(struct mt76x02_dev *dev, return 0; } -void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr) +void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr) { + static const u8 null_addr[ETH_ALEN] = {}; + int i; + ether_addr_copy(dev->mt76.macaddr, addr); if (!is_valid_ether_addr(dev->mt76.macaddr)) { @@ -563,6 +566,16 @@ void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr) mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->mt76.macaddr + 4) | FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff)); + + mt76_wr(dev, MT_MAC_BSSID_DW0, + get_unaligned_le32(dev->mt76.macaddr)); + mt76_wr(dev, MT_MAC_BSSID_DW1, + get_unaligned_le16(dev->mt76.macaddr + 4) | + FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 APs + 8 STAs */ + MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); + + for (i = 0; i < 16; i++) + mt76x02_mac_set_bssid(dev, i, null_addr); } EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 940c07f665cd..76e564b8f5da 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -191,7 +191,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, void mt76x02_mac_set_tx_protection(struct mt76x02_dev *dev, bool legacy_prot, int ht_mode); void mt76x02_mac_set_rts_thresh(struct mt76x02_dev *dev, u32 val); -void mt76x02_mac_setaddr(struct mt76x02_dev *dev, u8 *addr); +void mt76x02_mac_setaddr(struct mt76x02_dev *dev, const u8 *addr); void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta, int len); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 18434b06e706..1ecd4ef83c82 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -668,16 +668,8 @@ static void mt76x02_set_beacon_offsets(struct mt76x02_dev *dev) void mt76x02_init_beacon_config(struct mt76x02_dev *dev) { - static const u8 null_addr[ETH_ALEN] = {}; int i; - mt76_wr(dev, MT_MAC_BSSID_DW0, - get_unaligned_le32(dev->mt76.macaddr)); - mt76_wr(dev, MT_MAC_BSSID_DW1, - get_unaligned_le16(dev->mt76.macaddr + 4) | - FIELD_PREP(MT_MAC_BSSID_DW1_MBSS_MODE, 3) | /* 8 beacons */ - MT_MAC_BSSID_DW1_MBSS_LOCAL_BIT); - /* Fire a pre-TBTT interrupt 8 ms before TBTT */ mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, 8 << 4); @@ -687,10 +679,9 @@ void mt76x02_init_beacon_config(struct mt76x02_dev *dev) mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); - for (i = 0; i < 8; i++) { - mt76x02_mac_set_bssid(dev, i, null_addr); + for (i = 0; i < 8; i++) mt76x02_mac_set_beacon(dev, i, NULL); - } + mt76x02_set_beacon_offsets(dev); } EXPORT_SYMBOL_GPL(mt76x02_init_beacon_config); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 4347d5e7a915..0ccaa64d97ec 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -119,9 +119,7 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) mt76_wr(dev, MT_MCU_CLOCK_CTL, 0x1401); mt76_clear(dev, MT_FCE_L2_STUFF, MT_FCE_L2_STUFF_WR_MPDU_LEN_EN); - mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr)); - mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4)); - + mt76x02_mac_setaddr(dev, macaddr); mt76x02_init_beacon_config(dev); if (!hard) return 0; -- cgit v1.2.3 From 39834c1293ca6bfd1456b8d0063e7bd76f94eaf1 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 30 Jan 2019 17:02:16 +0100 Subject: mt76x02: minor beaconing init changes Disable BEACON timer during init and configure interrupt registers only for mmio devices. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 1ecd4ef83c82..4bc0520da1c6 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -670,13 +670,19 @@ void mt76x02_init_beacon_config(struct mt76x02_dev *dev) { int i; - /* Fire a pre-TBTT interrupt 8 ms before TBTT */ - mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, - 8 << 4); - mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER, - MT_DFS_GP_INTERVAL); - mt76_wr(dev, MT_INT_TIMER_EN, 0); + if (mt76_is_mmio(dev)) { + /* Fire a pre-TBTT interrupt 8 ms before TBTT */ + mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, + 8 << 4); + mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER, + MT_DFS_GP_INTERVAL); + mt76_wr(dev, MT_INT_TIMER_EN, 0); + } + mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | + MT_BEACON_TIME_CFG_SYNC_MODE | + MT_BEACON_TIME_CFG_TBTT_EN | + MT_BEACON_TIME_CFG_BEACON_TX)); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); for (i = 0; i < 8; i++) -- cgit v1.2.3 From b08ca4dc95bf3605335c0c7fdcfd8be62f3b08b1 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 30 Jan 2019 17:02:17 +0100 Subject: mt76x02: init beacon config for mt76x2u Initialize beaconing also on mt76x2u. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 0be3784f44fb..3737e9fa8295 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -207,11 +207,7 @@ int mt76x2u_init_hardware(struct mt76x02_dev *dev) mt76x02_mac_shared_key_setup(dev, i, k, NULL); } - mt76_clear(dev, MT_BEACON_TIME_CFG, - MT_BEACON_TIME_CFG_TIMER_EN | - MT_BEACON_TIME_CFG_SYNC_MODE | - MT_BEACON_TIME_CFG_TBTT_EN | - MT_BEACON_TIME_CFG_BEACON_TX); + mt76x02_init_beacon_config(dev); mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x583f); -- cgit v1.2.3 From dbb2b22b11cc085e088d37cdc65764b9668e8c3f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 30 Jan 2019 17:02:18 +0100 Subject: mt76: beaconing fixes for USB Configure beaconing on USB devices without PS buffering support. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 29 ++++++++++++++++++++--- drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 8 ++----- 3 files changed, 30 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index ae1727e433f3..2dc80ea26752 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -1060,8 +1060,9 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, return 0; } -void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, - u8 vif_idx, bool val) +static void +__mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, + bool val, struct sk_buff *skb) { u8 old_mask = dev->beacon_mask; bool en; @@ -1069,6 +1070,8 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, if (val) { dev->beacon_mask |= BIT(vif_idx); + if (skb) + mt76x02_mac_set_beacon(dev, vif_idx, skb); } else { dev->beacon_mask &= ~BIT(vif_idx); mt76x02_mac_set_beacon(dev, vif_idx, NULL); @@ -1079,14 +1082,34 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, en = dev->beacon_mask; - mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en); reg = MT_BEACON_TIME_CFG_BEACON_TX | MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_TIMER_EN; mt76_rmw(dev, MT_BEACON_TIME_CFG, reg, reg * en); + if (mt76_is_usb(dev)) + return; + + mt76_rmw_field(dev, MT_INT_TIMER_EN, MT_INT_TIMER_EN_PRE_TBTT_EN, en); if (en) mt76x02_irq_enable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); else mt76x02_irq_disable(dev, MT_INT_PRE_TBTT | MT_INT_TBTT); } + +void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, + struct ieee80211_vif *vif, bool val) +{ + u8 vif_idx = ((struct mt76x02_vif *)vif->drv_priv)->idx; + struct sk_buff *skb = NULL; + + if (mt76_is_mmio(dev)) + tasklet_disable(&dev->pre_tbtt_tasklet); + else if (val) + skb = ieee80211_beacon_get(mt76_hw(dev), vif); + + __mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb); + + if (mt76_is_mmio(dev)) + tasklet_enable(&dev->pre_tbtt_tasklet); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 76e564b8f5da..3b04b1bd0abd 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -204,8 +204,8 @@ void mt76x02_mac_work(struct work_struct *work); void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr); int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, struct sk_buff *skb); -void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, u8 vif_idx, - bool val); +void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, + struct ieee80211_vif *vif, bool val); void mt76x02_edcca_init(struct mt76x02_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 4bc0520da1c6..724b13d91898 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -705,12 +705,8 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) mt76x02_mac_set_bssid(dev, mvif->idx, info->bssid); - if (changed & BSS_CHANGED_BEACON_ENABLED) { - tasklet_disable(&dev->pre_tbtt_tasklet); - mt76x02_mac_set_beacon_enable(dev, mvif->idx, - info->enable_beacon); - tasklet_enable(&dev->pre_tbtt_tasklet); - } + if (changed & BSS_CHANGED_BEACON_ENABLED) + mt76x02_mac_set_beacon_enable(dev, vif, info->enable_beacon); if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) mt76x02_mac_set_tx_protection(dev, info->use_cts_prot, -- cgit v1.2.3 From 2bd7f3d2a93a20448e5c68eacbc925c4594640b4 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 30 Jan 2019 17:02:19 +0100 Subject: mt76x02: enable support for IBSS and MESH Since we implement beconing on USB now, similar interfaces should be supported for USB as are for MMIO. Tested only on IBSS mode and AP mode (not enabled due to lack of PS buffering). Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 724b13d91898..87ed00768bc7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -140,10 +140,16 @@ void mt76x02_init_device(struct mt76x02_dev *dev) hw->max_rate_tries = 1; hw->extra_tx_headroom = 2; + wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_ADHOC); + if (mt76_is_usb(dev)) { hw->extra_tx_headroom += sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN; - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); } else { INIT_DELAYED_WORK(&dev->wdt_work, mt76x02_wdt_work); @@ -152,18 +158,9 @@ void mt76x02_init_device(struct mt76x02_dev *dev) wiphy->reg_notifier = mt76x02_regd_notifier; wiphy->iface_combinations = mt76x02_if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb); - wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_ADHOC); - + wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; - wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); - /* init led callbacks */ if (IS_ENABLED(CONFIG_MT76_LEDS)) { dev->mt76.led_cdev.brightness_set = @@ -172,6 +169,8 @@ void mt76x02_init_device(struct mt76x02_dev *dev) } } + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + hw->sta_data_size = sizeof(struct mt76x02_sta); hw->vif_data_size = sizeof(struct mt76x02_vif); -- cgit v1.2.3 From b29e46b76552c2b1a76344602a0bcdc8ba8629da Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 5 Feb 2019 15:06:34 +0100 Subject: mt76x0: eeprom: fix VHT mcs{8,9} rate power offset Fix rate power configuration for VHT mcs 8 and 9 in mt76x0_get_tx_power_per_rate. Moreover use the rate power offset used for HT/VHT mcs 6 even for HT/VHT mcs 7 Fixes: b37bbc8c8251 ("mt76x0: remove eeprom dependency from mt76x0_set_tx_power_per_rate") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index b2cabce1d74d..64f96567bae9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -189,7 +189,7 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 8 : 0x126; val = mt76x02_eeprom_get(dev, addr); t->ht[4] = t->ht[5] = t->vht[4] = t->vht[5] = s6_to_s8(val); - t->ht[6] = t->vht[6] = s6_to_s8(val >> 8); + t->ht[6] = t->ht[7] = t->vht[6] = t->vht[7] = s6_to_s8(val >> 8); /* ht-vht mcs 1ss 0, 1, 2, 3 stbc */ addr = is_2ghz ? MT_EE_TX_POWER_BYRATE_BASE + 14 : 0xec; @@ -205,8 +205,8 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) /* vht mcs 8, 9 5GHz */ val = mt76x02_eeprom_get(dev, 0x132); - t->vht[7] = s6_to_s8(val); - t->vht[8] = s6_to_s8(val >> 8); + t->vht[8] = s6_to_s8(val); + t->vht[9] = s6_to_s8(val >> 8); delta = mt76x0_tssi_enabled(dev) ? 0 : mt76x0_get_delta(dev); mt76x02_add_rate_power_offset(t, delta); -- cgit v1.2.3 From 9df0fab9d1cad3cbdd47683e5b4f3c7c09a91bd3 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 4 Feb 2019 17:51:27 +0100 Subject: mt76: move mt76_mcu_msg_alloc in mt76-core Move mt76_mcu_msg_alloc in mt76-core module and remove duplicated code. mt76_mcu_msg_alloc will be reused adding support for mt7603 driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Makefile | 3 +- drivers/net/wireless/mediatek/mt76/mcu.c | 36 ++++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 4 +++ drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c | 12 -------- drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h | 6 ++++ .../net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | 17 +--------- 6 files changed, 49 insertions(+), 29 deletions(-) create mode 100644 drivers/net/wireless/mediatek/mt76/mcu.c (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 1a45cb30f39f..fa7a44edd02d 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -4,7 +4,8 @@ obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o mt76-y := \ - mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o + mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ + tx.o agg-rx.o mcu.o mt76-usb-y := usb.o usb_trace.o usb_mcu.o diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c new file mode 100644 index 000000000000..f4c38ec78654 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 Lorenzo Bianconi + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "mt76.h" + +struct sk_buff * +mt76_mcu_msg_alloc(const void *data, int head_len, + int data_len, int tail_len) +{ + struct sk_buff *skb; + + skb = alloc_skb(head_len + data_len + tail_len, + GFP_KERNEL); + if (!skb) + return NULL; + + skb_reserve(skb, head_len); + if (data && data_len) + skb_put_data(skb, data, data_len); + + return skb; +} +EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 2bb9db4ed80a..155d981d1328 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -751,6 +751,10 @@ void mt76u_stop_queues(struct mt76_dev *dev); void mt76u_stop_stat_wk(struct mt76_dev *dev); void mt76u_queues_deinit(struct mt76_dev *dev); +struct sk_buff * +mt76_mcu_msg_alloc(const void *data, int head_len, + int data_len, int tail_len); + void mt76u_mcu_complete_urb(struct urb *urb); int mt76u_mcu_init_rx(struct mt76_dev *dev); void mt76u_mcu_deinit(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index b7f4edb729e3..d184551b9845 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -21,18 +21,6 @@ #include "mt76x02_mcu.h" -static struct sk_buff *mt76x02_mcu_msg_alloc(const void *data, int len) -{ - struct sk_buff *skb; - - skb = alloc_skb(len, GFP_KERNEL); - if (!skb) - return NULL; - memcpy(skb_put(skb, len), data, len); - - return skb; -} - static struct sk_buff * mt76x02_mcu_get_response(struct mt76x02_dev *dev, unsigned long expires) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h index 7e4004120102..a7b0d3e5df1d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.h @@ -96,6 +96,12 @@ struct mt76x02_patch_header { u8 pad[2]; }; +static inline struct sk_buff * +mt76x02_mcu_msg_alloc(const void *data, int len) +{ + return mt76_mcu_msg_alloc(data, 0, len, 0); +} + int mt76x02_mcu_cleanup(struct mt76x02_dev *dev); int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param); int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index 6db789f90269..ff070f8fbc61 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -28,21 +28,6 @@ #define MT_TX_CPU_FROM_FCE_CPU_DESC_IDX 0x09a8 -static struct sk_buff * -mt76x02u_mcu_msg_alloc(const void *data, int len) -{ - struct sk_buff *skb; - - skb = alloc_skb(MT_CMD_HDR_LEN + len + 8, GFP_KERNEL); - if (!skb) - return NULL; - - skb_reserve(skb, MT_CMD_HDR_LEN); - skb_put_data(skb, data, len); - - return skb; -} - static void mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len) { @@ -166,7 +151,7 @@ mt76x02u_mcu_send_msg(struct mt76_dev *dev, int cmd, const void *data, struct sk_buff *skb; int err; - skb = mt76x02u_mcu_msg_alloc(data, len); + skb = mt76_mcu_msg_alloc(data, MT_CMD_HDR_LEN, len, 8); if (!skb) return -ENOMEM; -- cgit v1.2.3 From 680abb25f71caf3871c8619bee3bbc3818dcd3a7 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 4 Feb 2019 17:51:28 +0100 Subject: mt76: move mt76_mcu_get_response in mt76-core Move mt76_mcu_get_response in mt76-core module and remove duplicated code. mt76_mcu_get_response will be reused adding support for mt7603 driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mcu.c | 17 +++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 2 ++ drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c | 17 +---------------- 3 files changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index f4c38ec78654..0fd71a97a197 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -34,3 +34,20 @@ mt76_mcu_msg_alloc(const void *data, int head_len, return skb; } EXPORT_SYMBOL_GPL(mt76_mcu_msg_alloc); + +/* mmio */ +struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, + unsigned long expires) +{ + unsigned long timeout; + + if (!time_is_after_jiffies(expires)) + return NULL; + + timeout = expires - jiffies; + wait_event_timeout(dev->mmio.mcu.wait, + !skb_queue_empty(&dev->mmio.mcu.res_q), + timeout); + return skb_dequeue(&dev->mmio.mcu.res_q); +} +EXPORT_SYMBOL_GPL(mt76_mcu_get_response); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 155d981d1328..534e418c6d80 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -754,6 +754,8 @@ void mt76u_queues_deinit(struct mt76_dev *dev); struct sk_buff * mt76_mcu_msg_alloc(const void *data, int head_len, int data_len, int tail_len); +struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, + unsigned long expires); void mt76u_mcu_complete_urb(struct urb *urb); int mt76u_mcu_init_rx(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index d184551b9845..b44d128f6f93 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -21,21 +21,6 @@ #include "mt76x02_mcu.h" -static struct sk_buff * -mt76x02_mcu_get_response(struct mt76x02_dev *dev, unsigned long expires) -{ - unsigned long timeout; - - if (!time_is_after_jiffies(expires)) - return NULL; - - timeout = expires - jiffies; - wait_event_timeout(dev->mt76.mmio.mcu.wait, - !skb_queue_empty(&dev->mt76.mmio.mcu.res_q), - timeout); - return skb_dequeue(&dev->mt76.mmio.mcu.res_q); -} - static int mt76x02_tx_queue_mcu(struct mt76x02_dev *dev, enum mt76_txq_id qid, struct sk_buff *skb, int cmd, int seq) @@ -94,7 +79,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, u32 *rxfce; bool check_seq = false; - skb = mt76x02_mcu_get_response(dev, expires); + skb = mt76_mcu_get_response(&dev->mt76, expires); if (!skb) { dev_err(mdev->dev, "MCU message %d (seq %d) timed out\n", cmd, -- cgit v1.2.3 From c07a49d475b427e33d15780364bdeb64507d338a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 4 Feb 2019 17:51:29 +0100 Subject: mt76: move mt76_mcu_rx_event in mt76-core Move mt76_mcu_rx_event i mt76-core module and remove duplicated code. mt76_mcu_rx_event will be reused adding support for mt7603 driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mcu.c | 7 +++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 3 +-- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mcu.c b/drivers/net/wireless/mediatek/mt76/mcu.c index 0fd71a97a197..dbb57b593a87 100644 --- a/drivers/net/wireless/mediatek/mt76/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mcu.c @@ -51,3 +51,10 @@ struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, return skb_dequeue(&dev->mmio.mcu.res_q); } EXPORT_SYMBOL_GPL(mt76_mcu_get_response); + +void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb) +{ + skb_queue_tail(&dev->mmio.mcu.res_q, skb); + wake_up(&dev->mmio.mcu.wait); +} +EXPORT_SYMBOL_GPL(mt76_mcu_rx_event); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 534e418c6d80..a6cc9a2ff97e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -754,6 +754,7 @@ void mt76u_queues_deinit(struct mt76_dev *dev); struct sk_buff * mt76_mcu_msg_alloc(const void *data, int head_len, int data_len, int tail_len); +void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index a5413a309a0a..7861a832940b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -58,8 +58,7 @@ void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, if (q == MT_RXQ_MCU) { /* this is used just by mmio code */ - skb_queue_tail(&mdev->mmio.mcu.res_q, skb); - wake_up(&mdev->mmio.mcu.wait); + mt76_mcu_rx_event(&dev->mt76, skb); return; } -- cgit v1.2.3 From 6f02aeabc9c5113f56828742ace975f91d5b9470 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 5 Feb 2019 16:52:25 +0100 Subject: mt76x0: mcu: remove useless commented configuration Remove useless commented out configuration in mt76x0u_load_firmware routine Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c index f391d2d21fbc..4a282761ca58 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c @@ -140,12 +140,6 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev) FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20)); mt76x02u_mcu_fw_reset(dev); usleep_range(5000, 6000); -/* - mt76x0_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN | - MT_PBF_CFG_TX1Q_EN | - MT_PBF_CFG_TX2Q_EN | - MT_PBF_CFG_TX3Q_EN)); -*/ mt76_wr(dev, MT_FCE_PSE_CTRL, 1); -- cgit v1.2.3 From 5ed31128782cbb2a687a3d958473aa5bd05ff2fb Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 7 Feb 2019 11:10:57 +0100 Subject: mt76: move mt76_dma_tx_queue_skb_raw in mt76-core module Move mt76_dma_tx_queue_skb_raw routine in dma.c and add the corresponding entry in mt76_queue_ops data structure. mt76_dma_tx_queue_skb_raw will be reused adding support for mt7603 driver Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 25 +++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 4 +++ drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c | 40 +++++------------------- 3 files changed, 37 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index e769c8a555dd..ac1da2ee01a6 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -242,6 +242,30 @@ mt76_dma_kick_queue(struct mt76_dev *dev, struct mt76_queue *q) iowrite32(q->head, &q->regs->cpu_idx); } +static int +mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, enum mt76_txq_id qid, + struct sk_buff *skb, u32 tx_info) +{ + struct mt76_queue *q = &dev->q_tx[qid]; + struct mt76_queue_buf buf; + dma_addr_t addr; + + addr = dma_map_single(dev->dev, skb->data, skb->len, + DMA_TO_DEVICE); + if (dma_mapping_error(dev->dev, addr)) + return -ENOMEM; + + buf.addr = addr; + buf.len = skb->len; + + spin_lock_bh(&q->lock); + mt76_dma_add_buf(dev, q, &buf, 1, tx_info, skb, NULL); + mt76_dma_kick_queue(dev, q); + spin_unlock_bh(&q->lock); + + return 0; +} + int mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) @@ -523,6 +547,7 @@ static const struct mt76_queue_ops mt76_dma_ops = { .init = mt76_dma_init, .alloc = mt76_dma_alloc_queue, .add_buf = mt76_dma_add_buf, + .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw, .tx_queue_skb = mt76_dma_tx_queue_skb, .tx_cleanup = mt76_dma_tx_cleanup, .rx_reset = mt76_dma_rx_reset, diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index a6cc9a2ff97e..1d761b45a172 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -157,6 +157,9 @@ struct mt76_queue_ops { struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta); + int (*tx_queue_skb_raw)(struct mt76_dev *dev, enum mt76_txq_id qid, + struct sk_buff *skb, u32 tx_info); + void *(*dequeue)(struct mt76_dev *dev, struct mt76_queue *q, bool flush, int *len, u32 *info, bool *more); @@ -563,6 +566,7 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76)) #define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_add_buf(dev, ...) (dev)->mt76.queue_ops->add_buf(&((dev)->mt76), __VA_ARGS__) +#define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index b44d128f6f93..4752c104abf3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -21,43 +21,13 @@ #include "mt76x02_mcu.h" -static int -mt76x02_tx_queue_mcu(struct mt76x02_dev *dev, enum mt76_txq_id qid, - struct sk_buff *skb, int cmd, int seq) -{ - struct mt76_queue *q = &dev->mt76.q_tx[qid]; - struct mt76_queue_buf buf; - dma_addr_t addr; - u32 tx_info; - - tx_info = MT_MCU_MSG_TYPE_CMD | - FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) | - FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) | - FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | - FIELD_PREP(MT_MCU_MSG_LEN, skb->len); - - addr = dma_map_single(dev->mt76.dev, skb->data, skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(dev->mt76.dev, addr)) - return -ENOMEM; - - buf.addr = addr; - buf.len = skb->len; - - spin_lock_bh(&q->lock); - mt76_queue_add_buf(dev, q, &buf, 1, tx_info, skb, NULL); - mt76_queue_kick(dev, q); - spin_unlock_bh(&q->lock); - - return 0; -} - int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int len, bool wait_resp) { struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); unsigned long expires = jiffies + HZ; struct sk_buff *skb; + u32 tx_info; int ret; u8 seq; @@ -71,7 +41,13 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, if (!seq) seq = ++mdev->mmio.mcu.msg_seq & 0xf; - ret = mt76x02_tx_queue_mcu(dev, MT_TXQ_MCU, skb, cmd, seq); + tx_info = MT_MCU_MSG_TYPE_CMD | + FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) | + FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) | + FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | + FIELD_PREP(MT_MCU_MSG_LEN, skb->len); + + ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, tx_info); if (ret) goto out; -- cgit v1.2.3 From e6287c337c30a1e7f3e697887534a75b1713a538 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 7 Feb 2019 11:14:34 +0100 Subject: mt76: remove add_buf pointer in mt76_queue_ops Remove add_buf function pointer in mt76_queue_ops data structure since it is no longer used Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 1 - drivers/net/wireless/mediatek/mt76/mt76.h | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index ac1da2ee01a6..bfbfc0c2ec29 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -546,7 +546,6 @@ mt76_dma_init(struct mt76_dev *dev) static const struct mt76_queue_ops mt76_dma_ops = { .init = mt76_dma_init, .alloc = mt76_dma_alloc_queue, - .add_buf = mt76_dma_add_buf, .tx_queue_skb_raw = mt76_dma_tx_queue_skb_raw, .tx_queue_skb = mt76_dma_tx_queue_skb, .tx_cleanup = mt76_dma_tx_cleanup, diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 1d761b45a172..3894d72d4016 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -565,7 +565,6 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_init_queues(dev) (dev)->mt76.queue_ops->init(&((dev)->mt76)) #define mt76_queue_alloc(dev, ...) (dev)->mt76.queue_ops->alloc(&((dev)->mt76), __VA_ARGS__) -#define mt76_queue_add_buf(dev, ...) (dev)->mt76.queue_ops->add_buf(&((dev)->mt76), __VA_ARGS__) #define mt76_tx_queue_skb_raw(dev, ...) (dev)->mt76.queue_ops->tx_queue_skb_raw(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_rx_reset(dev, ...) (dev)->mt76.queue_ops->rx_reset(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) -- cgit v1.2.3 From 128b75bf5cf93bca71da740d3cb623c1febb6bf6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 31 Jan 2019 21:01:24 +0100 Subject: mt76: fix software encryption issues Software encrypted packets can be passed not just through the drv_tx callback, but also through the intermediate tx queue. In order to deal with that, move the override to mt76x02_mac_write_txwi and also take care of filling in the per-packet rate information Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 7 +++++++ drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c | 9 +-------- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 2dc80ea26752..6bd7f87644a4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -291,6 +291,13 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, memset(txwi, 0, sizeof(*txwi)); + if (!info->control.hw_key && wcid && wcid->hw_key_idx != 0xff && + ieee80211_has_protected(hdr->frame_control)) { + wcid = NULL; + ieee80211_get_tx_rates(info->control.vif, sta, skb, + info->control.rates, 1); + } + if (wcid) txwi->wcid = wcid->idx; else diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c index 7861a832940b..94f47248c59f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_txrx.c @@ -22,7 +22,6 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, struct sk_buff *skb) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct mt76x02_dev *dev = hw->priv; struct ieee80211_vif *vif = info->control.vif; @@ -33,13 +32,7 @@ void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, msta = (struct mt76x02_sta *)control->sta->drv_priv; wcid = &msta->wcid; - /* sw encrypted frames */ - if (!info->control.hw_key && wcid->hw_key_idx != 0xff && - ieee80211_has_protected(hdr->frame_control)) - control->sta = NULL; - } - - if (vif && !control->sta) { + } else if (vif) { struct mt76x02_vif *mvif; mvif = (struct mt76x02_vif *)vif->drv_priv; -- cgit v1.2.3 From 1564fa92fbf92abdc5bb82c006956826718ced5e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 3 Feb 2019 13:52:12 +0100 Subject: mt76: mt76x2: avoid running DPD calibration if tx is blocked Doing so could lead to hangs Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index e2ee5e498da7..1848e8ab2e21 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -241,7 +241,7 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev) t.offset1 = txp.chain[1].tssi_offset; mt76x2_mcu_tssi_comp(dev, &t); - if (t.pa_mode || dev->cal.dpd_cal_done) + if (t.pa_mode || dev->cal.dpd_cal_done || dev->ed_tx_blocked) return; usleep_range(10000, 20000); -- cgit v1.2.3 From 20c06572c1910f2735cb8cc1fd5d413824a387ae Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 3 Feb 2019 13:59:06 +0100 Subject: mt76: explicitly disable energy detect cca during scan Avoid reusing the previous channel's tx blocking state Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 6 ++++-- drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c | 6 ++++-- 5 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 1117cdc15b04..cb70b04d38a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -1006,14 +1006,16 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev, /* enable vco */ mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); - if (scan) + if (scan) { + mt76x02_edcca_init(dev, false); return 0; + } mt76x02_init_agc_gain(dev); mt76x0_phy_calibrate(dev, false); mt76x0_phy_set_txpower(dev); - mt76x02_edcca_init(dev); + mt76x02_edcca_init(dev, true); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 19fdcab746a0..e4649103efd4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -886,7 +886,7 @@ mt76x02_dfs_set_domain(struct mt76x02_dev *dev, tasklet_disable(&dfs_pd->dfs_tasklet); dev->ed_monitor = region == NL80211_DFS_ETSI; - mt76x02_edcca_init(dev); + mt76x02_edcca_init(dev, true); dfs_pd->region = region; mt76x02_dfs_init_params(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 6bd7f87644a4..636e69a7a407 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -891,12 +891,12 @@ mt76x02_edcca_tx_enable(struct mt76x02_dev *dev, bool enable) dev->ed_tx_blocked = !enable; } -void mt76x02_edcca_init(struct mt76x02_dev *dev) +void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) { dev->ed_trigger = 0; dev->ed_silent = 0; - if (dev->ed_monitor) { + if (dev->ed_monitor && enable) { struct ieee80211_channel *chan = dev->mt76.chandef.chan; u8 ed_th = chan->band == NL80211_BAND_5GHZ ? 0x0e : 0x20; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h index 3b04b1bd0abd..6b1f25d2f64c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h @@ -207,5 +207,5 @@ int mt76x02_mac_set_beacon(struct mt76x02_dev *dev, u8 vif_idx, void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, struct ieee80211_vif *vif, bool val); -void mt76x02_edcca_init(struct mt76x02_dev *dev); +void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 65ed62229a5b..97ec575699d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -240,8 +240,10 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F); - if (scan) + if (scan) { + mt76x02_edcca_init(dev, false); return 0; + } mt76x2_phy_channel_calibrate(dev, true); mt76x02_init_agc_gain(dev); @@ -254,7 +256,7 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, 0x38); } - mt76x02_edcca_init(dev); + mt76x02_edcca_init(dev, true); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); -- cgit v1.2.3 From 2e4050240a6ba96b95c778b6710fbdfadac0ba2e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 3 Feb 2019 14:13:06 +0100 Subject: mt76: run MAC work every 100ms ED/CCA Tx blocking checks need to be run every 100 ms in order to avoid triggering too late and keeping tx blocking on for too long Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 1472c8699b29..6992b3d7dfec 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -30,7 +30,7 @@ static int mt76x0e_start(struct ieee80211_hw *hw) mt76x02_mac_start(dev); mt76x0_phy_calibrate(dev, true); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 3987adaaf2bd..91d8afd9a0ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -118,7 +118,7 @@ static int mt76x0u_start(struct ieee80211_hw *hw) mt76x0_phy_calibrate(dev, true); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6d9d9ddacc32..7e405297028f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -27,6 +27,7 @@ #include "mt76x02_dma.h" #define MT_CALIBRATE_INTERVAL HZ +#define MT_MAC_WORK_INTERVAL (HZ / 10) #define MT_WATCHDOG_TIME (HZ / 10) #define MT_TX_HANG_TH 10 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 636e69a7a407..89c7368cbd52 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -929,7 +929,7 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev) u32 val, busy; val = mt76_rr(dev, MT_ED_CCA_TIMER); - busy = (val * 100) / jiffies_to_usecs(MT_CALIBRATE_INTERVAL); + busy = (val * 100) / jiffies_to_usecs(MT_MAC_WORK_INTERVAL); busy = min_t(u32, busy, 100); if (busy > MT_EDCCA_TH) { @@ -975,7 +975,7 @@ void mt76x02_mac_work(struct work_struct *work) mt76_tx_status_check(&dev->mt76, NULL, false); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); } void mt76x02_mac_set_bssid(struct mt76x02_dev *dev, u8 idx, const u8 *addr) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 06a26a152ba4..878ce92405ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -33,7 +33,7 @@ mt76x2_start(struct ieee80211_hw *hw) goto out; ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); ieee80211_queue_delayed_work(mt76_hw(dev), &dev->wdt_work, MT_WATCHDOG_TIME); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 5256c6f879a7..10633b8de8e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -28,7 +28,7 @@ static int mt76x2u_start(struct ieee80211_hw *hw) goto out; ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, - MT_CALIBRATE_INTERVAL); + MT_MAC_WORK_INTERVAL); set_bit(MT76_STATE_RUNNING, &dev->mt76.state); out: -- cgit v1.2.3 From c15b7cef2af8ea2dfac61af5f4f2b27aaed8d7e6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 3 Feb 2019 14:15:58 +0100 Subject: mt76: clear CCA timer stats in mt76x02_edcca_init Avoid triggering too early Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 89c7368cbd52..aecf514bb89b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -919,6 +919,9 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) } } mt76x02_edcca_tx_enable(dev, true); + + /* clear previous CCA timer value */ + mt76_rr(dev, MT_ED_CCA_TIMER); } EXPORT_SYMBOL_GPL(mt76x02_edcca_init); -- cgit v1.2.3 From ccdaf7b4f22f50dcd1e0af39f3712677195b8351 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 3 Feb 2019 14:41:22 +0100 Subject: mt76: measure the time between mt76x02_edcca_check runs Based on system load and time needed by other calibration runs, the time between dev->mac_work runs can vary quite a bit. Calculate busy time based on the actual time difference in order to avoid potentially over-estimating busy time, which could lead to unnecessary tx blocking. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 7e405297028f..3464b4ca2ea8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -117,6 +117,7 @@ struct mt76x02_dev { bool ed_monitor; u8 ed_trigger; u8 ed_silent; + ktime_t ed_time; }; extern struct ieee80211_rate mt76x02_rates[12]; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index aecf514bb89b..462ac030c08a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -922,6 +922,7 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) /* clear previous CCA timer value */ mt76_rr(dev, MT_ED_CCA_TIMER); + dev->ed_time = ktime_get_boottime(); } EXPORT_SYMBOL_GPL(mt76x02_edcca_init); @@ -929,10 +930,16 @@ EXPORT_SYMBOL_GPL(mt76x02_edcca_init); #define MT_EDCCA_BLOCK_TH 2 static void mt76x02_edcca_check(struct mt76x02_dev *dev) { - u32 val, busy; + ktime_t cur_time; + u32 active, val, busy; + cur_time = ktime_get_boottime(); val = mt76_rr(dev, MT_ED_CCA_TIMER); - busy = (val * 100) / jiffies_to_usecs(MT_MAC_WORK_INTERVAL); + + active = ktime_to_us(ktime_sub(cur_time, dev->ed_time)); + dev->ed_time = cur_time; + + busy = (val * 100) / active; busy = min_t(u32, busy, 100); if (busy > MT_EDCCA_TH) { -- cgit v1.2.3 From f1906fb24901460fdc0ba7c8bbfe416fb705c8a6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 3 Feb 2019 20:35:31 +0100 Subject: mt76: increase ED/CCA tx block threshold Block only when the busy time reaches 92%, as lower values can be reached with heavy 802.11 traffic as well. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 462ac030c08a..bf39624c9b98 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -926,7 +926,7 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) } EXPORT_SYMBOL_GPL(mt76x02_edcca_init); -#define MT_EDCCA_TH 90 +#define MT_EDCCA_TH 92 #define MT_EDCCA_BLOCK_TH 2 static void mt76x02_edcca_check(struct mt76x02_dev *dev) { -- cgit v1.2.3 From c0f7b25ab8d33adbead530dfc54b999fb69d5ede Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 31 Jan 2019 17:55:54 +0100 Subject: mt76: move alloc_device common code in mt76_alloc_device Move mt76x{0,2} alloc_device common code in mt76_alloc_device and remove duplicated code Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 7 ++++++- drivers/net/wireless/mediatek/mt76/mt76.h | 5 +++-- drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 5 +---- drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c | 5 ++--- drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c | 5 ++--- 5 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index ee3b65a14870..c7abf4f54867 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -269,7 +269,9 @@ mt76_check_sband(struct mt76_dev *dev, int band) } struct mt76_dev * -mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops) +mt76_alloc_device(struct device *pdev, unsigned int size, + const struct ieee80211_ops *ops, + const struct mt76_driver_ops *drv_ops) { struct ieee80211_hw *hw; struct mt76_dev *dev; @@ -280,6 +282,9 @@ mt76_alloc_device(unsigned int size, const struct ieee80211_ops *ops) dev = hw->priv; dev->hw = hw; + dev->dev = pdev; + dev->drv = drv_ops; + spin_lock_init(&dev->rx_lock); spin_lock_init(&dev->lock); spin_lock_init(&dev->cc_lock); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 3894d72d4016..e9cc108e60d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -585,8 +585,9 @@ mt76_channel_state(struct mt76_dev *dev, struct ieee80211_channel *c) return &msband->chan[idx]; } -struct mt76_dev *mt76_alloc_device(unsigned int size, - const struct ieee80211_ops *ops); +struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, + const struct ieee80211_ops *ops, + const struct mt76_driver_ops *drv_ops); int mt76_register_device(struct mt76_dev *dev, bool vht, struct ieee80211_rate *rates, int n_rates); void mt76_unregister_device(struct mt76_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 87b575fe1c74..34db3ec24e6e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -270,13 +270,10 @@ mt76x0_alloc_device(struct device *pdev, struct mt76x02_dev *dev; struct mt76_dev *mdev; - mdev = mt76_alloc_device(sizeof(*dev), ops); + mdev = mt76_alloc_device(pdev, sizeof(*dev), ops, drv_ops); if (!mdev) return NULL; - mdev->dev = pdev; - mdev->drv = drv_ops; - dev = container_of(mdev, struct mt76x02_dev, mt76); mutex_init(&dev->phy_mutex); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 0ccaa64d97ec..d5816c7f359f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -329,13 +329,12 @@ struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev) struct mt76x02_dev *dev; struct mt76_dev *mdev; - mdev = mt76_alloc_device(sizeof(*dev), &mt76x2_ops); + mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt76x2_ops, + &drv_ops); if (!mdev) return NULL; dev = container_of(mdev, struct mt76x02_dev, mt76); - mdev->dev = pdev; - mdev->drv = &drv_ops; return dev; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 3737e9fa8295..11ce106391e1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -147,13 +147,12 @@ struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev) struct mt76x02_dev *dev; struct mt76_dev *mdev; - mdev = mt76_alloc_device(sizeof(*dev), &mt76x2u_ops); + mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt76x2u_ops, + &drv_ops); if (!mdev) return NULL; dev = container_of(mdev, struct mt76x02_dev, mt76); - mdev->dev = pdev; - mdev->drv = &drv_ops; return dev; } -- cgit v1.2.3 From 3bfaa974de302cb453999d94a3fd22269fe9b293 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 31 Jan 2019 17:55:55 +0100 Subject: mt76x2u: remove mt76x2u_alloc_device routine Remove mt76x2u_alloc_device since it just runs mt76_alloc_device. Move mt76_alloc_device call in mt76x2u_probe Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76x2/mt76x2u.h | 1 - drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 24 ++++++++++++++++------ .../net/wireless/mediatek/mt76/mt76x2/usb_init.c | 23 --------------------- 3 files changed, 18 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h index 0b0075411b34..787cdfdf5db5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h @@ -29,7 +29,6 @@ extern const struct ieee80211_ops mt76x2u_ops; -struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev); int mt76x2u_register_device(struct mt76x02_dev *dev); int mt76x2u_init_hardware(struct mt76x02_dev *dev); void mt76x2u_cleanup(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index 4d1788eb3812..f81a85e96922 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -36,24 +36,36 @@ static const struct usb_device_id mt76x2u_device_table[] = { static int mt76x2u_probe(struct usb_interface *intf, const struct usb_device_id *id) { + static const struct mt76_driver_ops drv_ops = { + .tx_prepare_skb = mt76x02u_tx_prepare_skb, + .tx_complete_skb = mt76x02u_tx_complete_skb, + .tx_status_data = mt76x02_tx_status_data, + .rx_skb = mt76x02_queue_rx_skb, + .sta_add = mt76x02_sta_add, + .sta_remove = mt76x02_sta_remove, + }; struct usb_device *udev = interface_to_usbdev(intf); struct mt76x02_dev *dev; + struct mt76_dev *mdev; int err; - dev = mt76x2u_alloc_device(&intf->dev); - if (!dev) + mdev = mt76_alloc_device(&intf->dev, sizeof(*dev), &mt76x2u_ops, + &drv_ops); + if (!mdev) return -ENOMEM; + dev = container_of(mdev, struct mt76x02_dev, mt76); + udev = usb_get_dev(udev); usb_reset_device(udev); - mt76x02u_init_mcu(&dev->mt76); - err = mt76u_init(&dev->mt76, intf); + mt76x02u_init_mcu(mdev); + err = mt76u_init(mdev, intf); if (err < 0) goto err; - dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); - dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); + mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); + dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); err = mt76x2u_register_device(dev); if (err < 0) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 11ce106391e1..006e430e374e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -134,29 +134,6 @@ static int mt76x2u_init_eeprom(struct mt76x02_dev *dev) return 0; } -struct mt76x02_dev *mt76x2u_alloc_device(struct device *pdev) -{ - static const struct mt76_driver_ops drv_ops = { - .tx_prepare_skb = mt76x02u_tx_prepare_skb, - .tx_complete_skb = mt76x02u_tx_complete_skb, - .tx_status_data = mt76x02_tx_status_data, - .rx_skb = mt76x02_queue_rx_skb, - .sta_add = mt76x02_sta_add, - .sta_remove = mt76x02_sta_remove, - }; - struct mt76x02_dev *dev; - struct mt76_dev *mdev; - - mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt76x2u_ops, - &drv_ops); - if (!mdev) - return NULL; - - dev = container_of(mdev, struct mt76x02_dev, mt76); - - return dev; -} - int mt76x2u_init_hardware(struct mt76x02_dev *dev) { int i, k, err; -- cgit v1.2.3 From fa2355265c52b883cf115a617ad793aa16249db2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 31 Jan 2019 17:55:56 +0100 Subject: mt76x0: remove mt76x0u_alloc_device routine Remove mt76x0u_alloc_device since it just runs mt76_alloc_device. Move mt76_alloc_device call in mt76x0u_probe and in mt76x0e_probe Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 19 ------------------- drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h | 4 ---- drivers/net/wireless/mediatek/mt76/mt76x0/pci.c | 17 +++++++++++------ drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 22 +++++++++++++--------- 4 files changed, 24 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 34db3ec24e6e..820632e40c1b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -262,25 +262,6 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev) } EXPORT_SYMBOL_GPL(mt76x0_init_hardware); -struct mt76x02_dev * -mt76x0_alloc_device(struct device *pdev, - const struct mt76_driver_ops *drv_ops, - const struct ieee80211_ops *ops) -{ - struct mt76x02_dev *dev; - struct mt76_dev *mdev; - - mdev = mt76_alloc_device(pdev, sizeof(*dev), ops, drv_ops); - if (!mdev) - return NULL; - - dev = container_of(mdev, struct mt76x02_dev, mt76); - mutex_init(&dev->phy_mutex); - - return dev; -} -EXPORT_SYMBOL_GPL(mt76x0_alloc_device); - int mt76x0_register_device(struct mt76x02_dev *dev) { int ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h index 46629f61673b..51fbd75dff31 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h @@ -50,10 +50,6 @@ static inline bool is_mt7630(struct mt76x02_dev *dev) } /* Init */ -struct mt76x02_dev * -mt76x0_alloc_device(struct device *pdev, - const struct mt76_driver_ops *drv_ops, - const struct ieee80211_ops *ops); int mt76x0_init_hardware(struct mt76x02_dev *dev); int mt76x0_register_device(struct mt76x02_dev *dev); void mt76x0_chip_onoff(struct mt76x02_dev *dev, bool enable, bool reset); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c index 6992b3d7dfec..f302162036d0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c @@ -174,6 +174,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) .sta_remove = mt76x02_sta_remove, }; struct mt76x02_dev *dev; + struct mt76_dev *mdev; int ret; ret = pcim_enable_device(pdev); @@ -190,16 +191,20 @@ mt76x0e_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; - dev = mt76x0_alloc_device(&pdev->dev, &drv_ops, &mt76x0e_ops); - if (!dev) + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x0e_ops, + &drv_ops); + if (!mdev) return -ENOMEM; - mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); + dev = container_of(mdev, struct mt76x02_dev, mt76); + mutex_init(&dev->phy_mutex); - dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); - dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); + mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]); - ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler, + mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); + dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); + + ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto error; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 91d8afd9a0ed..2f259bc0ad9e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -233,14 +233,18 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, }; struct usb_device *usb_dev = interface_to_usbdev(usb_intf); struct mt76x02_dev *dev; + struct mt76_dev *mdev; u32 asic_rev, mac_rev; int ret; - dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops, - &mt76x0u_ops); - if (!dev) + mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops, + &drv_ops); + if (!mdev) return -ENOMEM; + dev = container_of(mdev, struct mt76x02_dev, mt76); + mutex_init(&dev->phy_mutex); + /* Quirk for Archer T1U */ if (id->driver_info) dev->no_2ghz = true; @@ -250,27 +254,27 @@ static int mt76x0u_probe(struct usb_interface *usb_intf, usb_set_intfdata(usb_intf, dev); - mt76x02u_init_mcu(&dev->mt76); - ret = mt76u_init(&dev->mt76, usb_intf); + mt76x02u_init_mcu(mdev); + ret = mt76u_init(mdev, usb_intf); if (ret) goto err; /* Disable the HW, otherwise MCU fail to initalize on hot reboot */ mt76x0_chip_onoff(dev, false, false); - if (!mt76x02_wait_for_mac(&dev->mt76)) { + if (!mt76x02_wait_for_mac(mdev)) { ret = -ETIMEDOUT; goto err; } asic_rev = mt76_rr(dev, MT_ASIC_VERSION); mac_rev = mt76_rr(dev, MT_MAC_CSR0); - dev_info(dev->mt76.dev, "ASIC revision: %08x MAC revision: %08x\n", + dev_info(mdev->dev, "ASIC revision: %08x MAC revision: %08x\n", asic_rev, mac_rev); /* Note: vendor driver skips this check for MT76X0U */ if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL)) - dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n"); + dev_warn(mdev->dev, "Warning: eFUSE not present\n"); ret = mt76x0u_register_device(dev); if (ret < 0) @@ -282,7 +286,7 @@ err: usb_set_intfdata(usb_intf, NULL); usb_put_dev(interface_to_usbdev(usb_intf)); - ieee80211_free_hw(dev->mt76.hw); + ieee80211_free_hw(mdev->hw); return ret; } -- cgit v1.2.3 From ecd25b547d96fe64b8bf67623e773cec29b690c1 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 31 Jan 2019 17:55:57 +0100 Subject: mt76x2: remove mt76x2_alloc_device routine Remove mt76x2_alloc_device since it just runs mt76_alloc_device. Move mt76_alloc_device call in mt76x2_probe Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h | 1 - drivers/net/wireless/mediatek/mt76/mt76x2/pci.c | 26 +++++++++++++++++----- .../net/wireless/mediatek/mt76/mt76x2/pci_init.c | 26 ---------------------- 3 files changed, 20 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h index 28ec19acf9db..6c619f1c65c9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h @@ -49,7 +49,6 @@ static inline bool mt76x2_channel_silent(struct mt76x02_dev *dev) extern const struct ieee80211_ops mt76x2_ops; -struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev); int mt76x2_register_device(struct mt76x02_dev *dev); void mt76x2_phy_power_on(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c index 92432fe97312..6274655e1f7e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c @@ -30,7 +30,19 @@ static const struct pci_device_id mt76pci_device_table[] = { static int mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { + static const struct mt76_driver_ops drv_ops = { + .txwi_size = sizeof(struct mt76x02_txwi), + .update_survey = mt76x02_update_channel, + .tx_prepare_skb = mt76x02_tx_prepare_skb, + .tx_complete_skb = mt76x02_tx_complete_skb, + .rx_skb = mt76x02_queue_rx_skb, + .rx_poll_complete = mt76x02_rx_poll_complete, + .sta_ps = mt76x02_sta_ps, + .sta_add = mt76x02_sta_add, + .sta_remove = mt76x02_sta_remove, + }; struct mt76x02_dev *dev; + struct mt76_dev *mdev; int ret; ret = pcim_enable_device(pdev); @@ -47,17 +59,19 @@ mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; - dev = mt76x2_alloc_device(&pdev->dev); - if (!dev) + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt76x2_ops, + &drv_ops); + if (!mdev) return -ENOMEM; - mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); + dev = container_of(mdev, struct mt76x02_dev, mt76); + mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]); mt76x2_reset_wlan(dev, false); - dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); - dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); + mdev->rev = mt76_rr(dev, MT_ASIC_VERSION); + dev_info(mdev->dev, "ASIC revision: %08x\n", mdev->rev); - ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x02_irq_handler, + ret = devm_request_irq(mdev->dev, pdev->irq, mt76x02_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto error; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index d5816c7f359f..d4e3d7c11d74 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -313,32 +313,6 @@ void mt76x2_cleanup(struct mt76x02_dev *dev) mt76x02_mcu_cleanup(dev); } -struct mt76x02_dev *mt76x2_alloc_device(struct device *pdev) -{ - static const struct mt76_driver_ops drv_ops = { - .txwi_size = sizeof(struct mt76x02_txwi), - .update_survey = mt76x02_update_channel, - .tx_prepare_skb = mt76x02_tx_prepare_skb, - .tx_complete_skb = mt76x02_tx_complete_skb, - .rx_skb = mt76x02_queue_rx_skb, - .rx_poll_complete = mt76x02_rx_poll_complete, - .sta_ps = mt76x02_sta_ps, - .sta_add = mt76x02_sta_add, - .sta_remove = mt76x02_sta_remove, - }; - struct mt76x02_dev *dev; - struct mt76_dev *mdev; - - mdev = mt76_alloc_device(pdev, sizeof(*dev), &mt76x2_ops, - &drv_ops); - if (!mdev) - return NULL; - - dev = container_of(mdev, struct mt76x02_dev, mt76); - - return dev; -} - int mt76x2_register_device(struct mt76x02_dev *dev) { int ret; -- cgit v1.2.3 From bceac167b00fbc2f5e93eecd578179a467863d85 Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Mon, 11 Feb 2019 10:13:41 +0800 Subject: mt76: change the return type of mt76_dma_attach() There is no need to retun 0 in mt76_dma_attach(), so switch it to void. Signed-off-by: Ryder Lee Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/dma.c | 3 +-- drivers/net/wireless/mediatek/mt76/dma.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index bfbfc0c2ec29..6eedc0ec7661 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -553,10 +553,9 @@ static const struct mt76_queue_ops mt76_dma_ops = { .kick = mt76_dma_kick_queue, }; -int mt76_dma_attach(struct mt76_dev *dev) +void mt76_dma_attach(struct mt76_dev *dev) { dev->queue_ops = &mt76_dma_ops; - return 0; } EXPORT_SYMBOL_GPL(mt76_dma_attach); diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h index 357cc356342d..e3292df5e9b2 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.h +++ b/drivers/net/wireless/mediatek/mt76/dma.h @@ -54,7 +54,7 @@ enum mt76_mcu_evt_type { EVT_EVENT_DFS_DETECT_RSP, }; -int mt76_dma_attach(struct mt76_dev *dev); +void mt76_dma_attach(struct mt76_dev *dev); void mt76_dma_cleanup(struct mt76_dev *dev); #endif -- cgit v1.2.3 From 0bee1ff6922d2ba704b41911423d3d7b7322956f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 28 Jan 2019 10:31:12 +0100 Subject: mt76x0: phy: report target_power in debugfs Initialize target_power variable in mt76x0_phy_set_txpower in order to report target_power in debugfs Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index cb70b04d38a5..3dfcad552be0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -855,6 +855,7 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t); mt76x02_add_rate_power_offset(t, -info); + dev->target_power = info; mt76x02_phy_set_txpower(dev, info, info); } -- cgit v1.2.3 From 1ffe410ee3bd445383b737739012d9d85283eb73 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 28 Jan 2019 10:31:13 +0100 Subject: mt76x0: init: introduce mt76x0_init_txpower routine Add mt76x0_init_txpower in order to initialize max_power per channel at device bootstrap. Modify mt76x0_get_tx_power_per_rate and mt76x0_get_power_info signature in order to compute tx power for non-operating channels Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c | 10 ++++---- drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h | 7 ++++-- drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 29 ++++++++++++++++++++-- drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 4 +-- 4 files changed, 39 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c index 64f96567bae9..ab6dfc026acb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c @@ -152,11 +152,11 @@ static s8 mt76x0_get_delta(struct mt76x02_dev *dev) return mt76x02_rate_power_val(val); } -void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) +void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev, + struct ieee80211_channel *chan, + struct mt76_rate_power *t) { - struct ieee80211_channel *chan = dev->mt76.chandef.chan; bool is_2ghz = chan->band == NL80211_BAND_2GHZ; - struct mt76_rate_power *t = &dev->mt76.rate_power; u16 val, addr; s8 delta; @@ -212,7 +212,8 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev) mt76x02_add_rate_power_offset(t, delta); } -void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp) +void mt76x0_get_power_info(struct mt76x02_dev *dev, + struct ieee80211_channel *chan, s8 *tp) { struct mt76x0_chan_map { u8 chan; @@ -226,7 +227,6 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp) { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 }, { 167, 34 }, { 171, 36 }, { 175, 38 }, }; - struct ieee80211_channel *chan = dev->mt76.chandef.chan; u8 offset, addr; int i, idx = 0; u16 data; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h index 42b259f90b6d..7f73034a23b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h @@ -25,8 +25,11 @@ struct mt76x02_dev; int mt76x0_eeprom_init(struct mt76x02_dev *dev); void mt76x0_read_rx_gain(struct mt76x02_dev *dev); -void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev); -void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp); +void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev, + struct ieee80211_channel *chan, + struct mt76_rate_power *t); +void mt76x0_get_power_info(struct mt76x02_dev *dev, + struct ieee80211_channel *chan, s8 *tp); static inline s8 s6_to_s8(u32 val) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index 820632e40c1b..a529ce111c20 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -18,6 +18,7 @@ #include "eeprom.h" #include "mcu.h" #include "initvals.h" +#include "../mt76x02_phy.h" static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband) { @@ -262,6 +263,25 @@ int mt76x0_init_hardware(struct mt76x02_dev *dev) } EXPORT_SYMBOL_GPL(mt76x0_init_hardware); +static void +mt76x0_init_txpower(struct mt76x02_dev *dev, + struct ieee80211_supported_band *sband) +{ + struct ieee80211_channel *chan; + struct mt76_rate_power t; + s8 tp; + int i; + + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; + + mt76x0_get_tx_power_per_rate(dev, chan, &t); + mt76x0_get_power_info(dev, chan, &tp); + + chan->max_power = (mt76x02_get_max_rate_power(&t) + tp) / 2; + } +} + int mt76x0_register_device(struct mt76x02_dev *dev) { int ret; @@ -274,9 +294,14 @@ int mt76x0_register_device(struct mt76x02_dev *dev) if (ret) return ret; - /* overwrite unsupported features */ - if (dev->mt76.cap.has_5ghz) + if (dev->mt76.cap.has_5ghz) { + /* overwrite unsupported features */ mt76x0_vht_cap_mask(&dev->mt76.sband_5g.sband); + mt76x0_init_txpower(dev, &dev->mt76.sband_5g.sband); + } + + if (dev->mt76.cap.has_2ghz) + mt76x0_init_txpower(dev, &dev->mt76.sband_2g.sband); mt76x02_init_debugfs(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 3dfcad552be0..3467a32f5fda 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -847,8 +847,8 @@ void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) struct mt76_rate_power *t = &dev->mt76.rate_power; s8 info; - mt76x0_get_tx_power_per_rate(dev); - mt76x0_get_power_info(dev, &info); + mt76x0_get_tx_power_per_rate(dev, dev->mt76.chandef.chan, t); + mt76x0_get_power_info(dev, dev->mt76.chandef.chan, &info); mt76x02_add_rate_power_offset(t, info); mt76x02_limit_rate_power(t, dev->mt76.txpower_conf); -- cgit v1.2.3 From 5de4db8fcb6d6fc7d9064c22841211790c0ab81b Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 11 Feb 2019 09:16:14 +0100 Subject: mt76x02u: use usb_bulk_msg to upload firmware We don't need to send firmware data asynchronously, much simpler is just use synchronous usb_bulk_msg(). Tested-by: Lorenzo Bianconi Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 13 ++++++ .../net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | 52 +++++++--------------- drivers/net/wireless/mediatek/mt76/usb.c | 1 - 3 files changed, 29 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index e9cc108e60d3..13f6febc9b0f 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -736,6 +736,19 @@ static inline bool mt76u_check_sg(struct mt76_dev *dev) udev->speed == USB_SPEED_WIRELESS)); } +static inline int +mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout) +{ + struct usb_interface *intf = to_usb_interface(dev->dev); + struct usb_device *udev = interface_to_usbdev(intf); + struct mt76_usb *usb = &dev->usb; + unsigned int pipe; + int sent; + + pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); + return usb_bulk_msg(udev, pipe, data, len, &sent, timeout); +} + int mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, void *buf, size_t len); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index ff070f8fbc61..64c777298cee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -106,18 +106,14 @@ static int __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd, bool wait_resp) { - struct usb_interface *intf = to_usb_interface(dev->dev); - struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; - unsigned int pipe; - int ret, sent; + int ret; u8 seq = 0; u32 info; if (test_bit(MT76_REMOVED, &dev->state)) return 0; - pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); if (wait_resp) { seq = ++usb->mcu.msg_seq & 0xf; if (!seq) @@ -131,7 +127,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, if (ret) return ret; - ret = usb_bulk_msg(udev, pipe, skb->data, skb->len, &sent, 500); + ret = mt76u_bulk_msg(dev, skb->data, skb->len, 500); if (ret) return ret; @@ -253,14 +249,12 @@ void mt76x02u_mcu_fw_reset(struct mt76x02_dev *dev) EXPORT_SYMBOL_GPL(mt76x02u_mcu_fw_reset); static int -__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, +__mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data, const void *fw_data, int len, u32 dst_addr) { - u8 *data = sg_virt(&buf->urb->sg[0]); - DECLARE_COMPLETION_ONSTACK(cmpl); __le32 info; u32 val; - int err; + int err, data_len; info = cpu_to_le32(FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | FIELD_PREP(MT_MCU_MSG_LEN, len) | @@ -276,25 +270,12 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE, MT_FCE_DMA_LEN, len << 16); - buf->len = MT_CMD_HDR_LEN + len + sizeof(info); - err = mt76u_submit_buf(&dev->mt76, USB_DIR_OUT, - MT_EP_OUT_INBAND_CMD, - buf, GFP_KERNEL, - mt76u_mcu_complete_urb, &cmpl); - if (err < 0) - return err; - - if (!wait_for_completion_timeout(&cmpl, - msecs_to_jiffies(1000))) { - dev_err(dev->mt76.dev, "firmware upload timed out\n"); - usb_kill_urb(buf->urb); - return -ETIMEDOUT; - } + data_len = MT_CMD_HDR_LEN + len + sizeof(info); - if (mt76u_urb_error(buf->urb)) { - dev_err(dev->mt76.dev, "firmware upload failed: %d\n", - buf->urb->status); - return buf->urb->status; + err = mt76u_bulk_msg(&dev->mt76, data, data_len, 1000); + if (err) { + dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err); + return err; } val = mt76_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX); @@ -307,17 +288,16 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, int data_len, u32 max_payload, u32 offset) { - int err, len, pos = 0, max_len = max_payload - 8; - struct mt76u_buf buf; + int len, err = 0, pos = 0, max_len = max_payload - 8; + u8 *buf; - err = mt76u_buf_alloc(&dev->mt76, &buf, 1, max_payload, max_payload, - GFP_KERNEL); - if (err < 0) - return err; + buf = kmalloc(max_payload, GFP_KERNEL); + if (!buf) + return -ENOMEM; while (data_len > 0) { len = min_t(int, data_len, max_len); - err = __mt76x02u_mcu_fw_send_data(dev, &buf, data + pos, + err = __mt76x02u_mcu_fw_send_data(dev, buf, data + pos, len, offset + pos); if (err < 0) break; @@ -326,7 +306,7 @@ int mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, const void *data, pos += len; usleep_range(5000, 10000); } - mt76u_buf_free(&buf); + kfree(buf); return err; } diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 6a2507524c6c..018a8cf0941e 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -326,7 +326,6 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen); } -EXPORT_SYMBOL_GPL(mt76u_buf_alloc); void mt76u_buf_free(struct mt76u_buf *buf) { -- cgit v1.2.3 From bdba48d57a5509a6531e162394f157250d893aaf Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 10 Feb 2019 22:49:13 +0100 Subject: mt76: usb: fix possible NULL pointer dereference in mt76u_mcu_deinit Fix possible NULL pointer dereference in mt76u_mcu_deinit routine that can occur if initialization path fails before calling mt76u_mcu_init_rx Fixes: ee676cd5017c ("mt76: add driver code for MT76x2u based devices") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb_mcu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c index 036be4163e69..9527e1216f3d 100644 --- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/usb_mcu.c @@ -48,9 +48,11 @@ EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx); void mt76u_mcu_deinit(struct mt76_dev *dev) { - struct mt76_usb *usb = &dev->usb; + struct mt76u_buf *buf = &dev->usb.mcu.res; - usb_kill_urb(usb->mcu.res.urb); - mt76u_buf_free(&usb->mcu.res); + if (buf->urb) { + usb_kill_urb(buf->urb); + mt76u_buf_free(buf); + } } EXPORT_SYMBOL_GPL(mt76u_mcu_deinit); -- cgit v1.2.3 From cb83585e1121bd6d6c039cf09fa32380bf8b6258 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 10 Feb 2019 22:49:14 +0100 Subject: mt76: usb: fix possible memory leak in mt76u_buf_free Move q->ndesc initialization before the for loop in mt76u_alloc_rx since otherwise allocated urbs will not be freed in mt76u_buf_free Double-check scatterlist pointer in mt76u_buf_free Fixes: b40b15e1521f ("mt76: add usb support to mt76 layer") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 018a8cf0941e..aee5ff124055 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -330,10 +330,16 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, void mt76u_buf_free(struct mt76u_buf *buf) { struct urb *urb = buf->urb; + struct scatterlist *sg; int i; - for (i = 0; i < urb->num_sgs; i++) - skb_free_frag(sg_virt(&urb->sg[i])); + for (i = 0; i < urb->num_sgs; i++) { + sg = &urb->sg[i]; + if (!sg) + continue; + + skb_free_frag(sg_virt(sg)); + } usb_free_urb(buf->urb); } EXPORT_SYMBOL_GPL(mt76u_buf_free); @@ -537,7 +543,8 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) nsgs = 1; } - for (i = 0; i < MT_NUM_RX_ENTRIES; i++) { + q->ndesc = MT_NUM_RX_ENTRIES; + for (i = 0; i < q->ndesc; i++) { err = mt76u_buf_alloc(dev, &q->entry[i].ubuf, nsgs, q->buf_size, SKB_WITH_OVERHEAD(q->buf_size), @@ -545,7 +552,6 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) if (err < 0) return err; } - q->ndesc = MT_NUM_RX_ENTRIES; return mt76u_submit_rx_buffers(dev); } -- cgit v1.2.3 From b3098121c42caaf3aea239b8655cf52d45be116f Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sun, 10 Feb 2019 22:49:15 +0100 Subject: mt76: usb: do not run mt76u_queues_deinit twice Do not call mt76u_queues_deinit routine in mt76u_alloc_queues error path since it will be run in mt76x0u_register_device or mt76x2u_register_device error path. Current implementation triggers the following kernel warning: [ 67.005516] WARNING: CPU: 2 PID: 761 at lib/refcount.c:187 refcount_sub_and_test_checked+0xa4/0xb8 [ 67.019513] refcount_t: underflow; use-after-free. [ 67.099872] Hardware name: BCM2835 [ 67.106268] Backtrace: [ 67.111584] [<8010c91c>] (dump_backtrace) from [<8010cc00>] (show_stack+0x20/0x24) [ 67.124974] r6:60000013 r5:ffffffff r4:00000000 r3:a50bade6 [ 67.132226] [<8010cbe0>] (show_stack) from [<807ca5f4>] (dump_stack+0xc8/0x114) [ 67.141225] [<807ca52c>] (dump_stack) from [<8011e65c>] (__warn+0xf4/0x120) [ 67.149849] r9:000000bb r8:804d0138 r7:00000009 r6:8099dc84 r5:00000000 r4:b66c7b58 [ 67.160767] [<8011e568>] (__warn) from [<8011e6d0>] (warn_slowpath_fmt+0x48/0x50) [ 67.171436] r9:7f65e128 r8:80d1419c r7:80c0bac4 r6:b97b3044 r5:b7368e00 r4:00000000 [ 67.182433] [<8011e68c>] (warn_slowpath_fmt) from [<804d0138>] (refcount_sub_and_test_checked+0xa4/0xb8) [ 67.195221] r3:80c91c25 r2:8099dc94 [ 67.200370] r4:00000000 [ 67.204397] [<804d0094>] (refcount_sub_and_test_checked) from [<804d0164>] (refcount_dec_and_test_checked+0x18/0x1c) [ 67.218046] r4:b7368e00 r3:00000001 [ 67.223125] [<804d014c>] (refcount_dec_and_test_checked) from [<805db49c>] (usb_free_urb+0x20/0x4c) [ 67.235358] [<805db47c>] (usb_free_urb) from [<7f639804>] (mt76u_buf_free+0x98/0xac [mt76_usb]) [ 67.247302] r4:00000001 r3:00000001 [ 67.252468] [<7f63976c>] (mt76u_buf_free [mt76_usb]) from [<7f639ef8>] (mt76u_queues_deinit+0x44/0x100 [mt76_usb]) [ 67.266102] r8:b8fe8600 r7:b5dac480 r6:b5dace20 r5:00000001 r4:00000000 r3:00000080 [ 67.277132] [<7f639eb4>] (mt76u_queues_deinit [mt76_usb]) from [<7f65c040>] (mt76x0u_cleanup+0x40/0x4c [mt76x0u]) [ 67.290737] r7:b5dac480 r6:b8fe8600 r5:ffffffea r4:b5dace20 [ 67.298069] [<7f65c000>] (mt76x0u_cleanup [mt76x0u]) from [<7f65c564>] (mt76x0u_probe+0x1f0/0x354 [mt76x0u]) [ 67.311174] r4:b5dace20 r3:00000000 [ 67.316312] [<7f65c374>] (mt76x0u_probe [mt76x0u]) from [<805e0b6c>] (usb_probe_interface+0x104/0x240) [ 67.328915] r7:00000000 r6:7f65e034 r5:b6634800 r4:b8fe8620 [ 67.336276] [<805e0a68>] (usb_probe_interface) from [<8056a8bc>] (really_probe+0x224/0x2f8) [ 67.347965] r10:b65f0a00 r9:00000019 r8:7f65e034 r7:80d3e124 r6:00000000 r5:80d3e120 [ 67.359175] r4:b8fe8620 r3:805e0a68 [ 67.364384] [<8056a698>] (really_probe) from [<8056ab60>] (driver_probe_device+0x6c/0x180) [ 67.375974] r10:b65f0a00 r9:7f65e2c0 r8:b8fe8620 r7:00000000 r6:7f65e034 r5:7f65e034 [ 67.387170] r4:b8fe8620 r3:00000000 [ 67.392378] [<8056aaf4>] (driver_probe_device) from [<8056ad54>] (__driver_attach+0xe0/0xe4) [ 67.404097] r9:7f65e2c0 r8:7f65d22c r7:00000000 r6:b8fe8654 r5:7f65e034 r4:b8fe8620 [ 67.415122] [<8056ac74>] (__driver_attach) from [<8056880c>] (bus_for_each_dev+0x68/0xa0) [ 67.426628] r6:8056ac74 r5:7f65e034 r4:00000000 r3:00000027 [ 67.434017] [<805687a4>] (bus_for_each_dev) from [<8056a1cc>] (driver_attach+0x28/0x30) [ 67.445394] r6:80c6ddc8 r5:b7368f80 r4:7f65e034 [ 67.451703] [<8056a1a4>] (driver_attach) from [<80569c24>] (bus_add_driver+0x194/0x21c) [ 67.463081] [<80569a90>] (bus_add_driver) from [<8056b504>] (driver_register+0x8c/0x124) [ 67.474560] r7:80c6ddc8 r6:7f65e034 r5:00000000 r4:7f65e034 [ 67.481964] [<8056b478>] (driver_register) from [<805df510>] (usb_register_driver+0x74/0x140) [ 67.493901] r5:00000000 r4:7f65e000 [ 67.499131] [<805df49c>] (usb_register_driver) from [<7f661024>] (mt76x0_driver_init+0x24/0x1000 [mt76x0u]) [ 67.512258] r9:00000001 r8:7f65e308 r7:00000000 r6:80c08d48 r5:7f661000 r4:7f65e2c0 [ 67.523404] [<7f661000>] (mt76x0_driver_init [mt76x0u]) from [<80102f6c>] (do_one_initcall+0x4c/0x210) [ 67.536142] [<80102f20>] (do_one_initcall) from [<801ae63c>] (do_init_module+0x6c/0x21c) [ 67.547639] r8:7f65e308 r7:80c08d48 r6:b65f0ac0 r5:7f65e2c0 r4:7f65e2c0 [ 67.556129] [<801ae5d0>] (do_init_module) from [<801ad68c>] (load_module+0x1d10/0x2304) Fixes: b40b15e1521f ("mt76: add usb support to mt76 layer") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index aee5ff124055..d2c30a280c3a 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -843,16 +843,9 @@ int mt76u_alloc_queues(struct mt76_dev *dev) err = mt76u_alloc_rx(dev); if (err < 0) - goto err; - - err = mt76u_alloc_tx(dev); - if (err < 0) - goto err; + return err; - return 0; -err: - mt76u_queues_deinit(dev); - return err; + return mt76u_alloc_tx(dev); } EXPORT_SYMBOL_GPL(mt76u_alloc_queues); -- cgit v1.2.3 From 63a7de5dfbfd4d3d96b0e7420d69ff8ac9b4d51a Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 12 Feb 2019 14:42:39 +0100 Subject: mt76: usb: move mt76u_check_sg in usb.c Move mt76u_check_sg routine in usb.c and introduce sg_en variable in mt76_usb in order to check if scatter-gather is supported by mt76u layer Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 11 +---------- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c | 2 +- drivers/net/wireless/mediatek/mt76/usb.c | 14 +++++++++++++- 4 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 13f6febc9b0f..0eb9152c5d18 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -379,6 +379,7 @@ struct mt76_usb { u16 out_max_packet; u8 in_ep[__MT_EP_IN_MAX]; u16 in_max_packet; + bool sg_en; struct mt76u_mcu { struct mutex mutex; @@ -726,16 +727,6 @@ static inline u8 q2ep(u8 qid) return qid + 1; } -static inline bool mt76u_check_sg(struct mt76_dev *dev) -{ - struct usb_interface *intf = to_usb_interface(dev->dev); - struct usb_device *udev = interface_to_usbdev(intf); - - return (udev->bus->sg_tablesize > 0 && - (udev->bus->no_sg_constraint || - udev->speed == USB_SPEED_WIRELESS)); -} - static inline int mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index 2f259bc0ad9e..da9d05f6074d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -206,7 +206,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) goto out_err; /* check hw sg support in order to enable AMSDU */ - if (mt76u_check_sg(&dev->mt76)) + if (dev->mt76.usb.sg_en) hw->max_tx_fragments = MT_SG_MAX_SIZE; else hw->max_tx_fragments = 1; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 006e430e374e..090aaf71b3ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -228,7 +228,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) goto fail; /* check hw sg support in order to enable AMSDU */ - if (mt76u_check_sg(&dev->mt76)) + if (dev->mt76.usb.sg_en) hw->max_tx_fragments = MT_SG_MAX_SIZE; else hw->max_tx_fragments = 1; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index d2c30a280c3a..78b31b9ba8ad 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -241,6 +241,16 @@ mt76u_rd_rp(struct mt76_dev *dev, u32 base, return mt76u_req_rd_rp(dev, base, data, n); } +static bool mt76u_check_sg(struct mt76_dev *dev) +{ + struct usb_interface *intf = to_usb_interface(dev->dev); + struct usb_device *udev = interface_to_usbdev(intf); + + return (udev->bus->sg_tablesize > 0 && + (udev->bus->no_sg_constraint || + udev->speed == USB_SPEED_WIRELESS)); +} + static int mt76u_set_endpoints(struct usb_interface *intf, struct mt76_usb *usb) @@ -535,7 +545,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) if (!q->entry) return -ENOMEM; - if (mt76u_check_sg(dev)) { + if (dev->usb.sg_en) { q->buf_size = MT_RX_BUF_SIZE; nsgs = MT_SG_MAX_SIZE; } else { @@ -880,6 +890,8 @@ int mt76u_init(struct mt76_dev *dev, dev->bus = &mt76u_ops; dev->queue_ops = &usb_queue_ops; + usb->sg_en = mt76u_check_sg(dev); + return mt76u_set_endpoints(intf, usb); } EXPORT_SYMBOL_GPL(mt76u_init); -- cgit v1.2.3 From d704d16f201ab75d9e348ab932b76d2c924fd472 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 12 Feb 2019 14:42:40 +0100 Subject: mt76: usb: do not use sg buffers for mcu messages Do not use scatter-gather buffers for mcu commands. Introduce mt76u_buf_alloc and mt76u_buf_alloc_sg routines. Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 3 +- .../net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | 3 +- drivers/net/wireless/mediatek/mt76/usb.c | 38 ++++++++++++++++++---- drivers/net/wireless/mediatek/mt76/usb_mcu.c | 5 ++- 4 files changed, 36 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 0eb9152c5d18..f55dc621e060 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -87,6 +87,7 @@ struct mt76u_buf { struct mt76_dev *dev; struct urb *urb; size_t len; + void *buf; bool done; }; @@ -748,7 +749,7 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req, int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); void mt76u_deinit(struct mt76_dev *dev); int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, - int nsgs, int len, int sglen, gfp_t gfp); + int len, int data_len, gfp_t gfp); void mt76u_buf_free(struct mt76u_buf *buf); int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, struct mt76u_buf *buf, gfp_t gfp, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index 64c777298cee..e469e383cb88 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -63,9 +63,9 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) struct mt76_usb *usb = &dev->usb; struct mt76u_buf *buf = &usb->mcu.res; struct urb *urb = buf->urb; + u8 *data = buf->buf; int i, ret; u32 rxfce; - u8 *data; for (i = 0; i < 5; i++) { if (!wait_for_completion_timeout(&usb->mcu.cmpl, @@ -75,7 +75,6 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) if (urb->status) return -EIO; - data = sg_virt(&urb->sg[0]); if (usb->mcu.rp) mt76x02u_multiple_mcu_reads(dev, data + 4, urb->actual_length - 8); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 78b31b9ba8ad..e32ec89781c6 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -319,8 +319,9 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, return i ? : -ENOMEM; } -int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, - int nsgs, int len, int sglen, gfp_t gfp) +static int +mt76u_buf_alloc_sg(struct mt76_dev *dev, struct mt76u_buf *buf, + int nsgs, int len, int sglen, gfp_t gfp) { buf->urb = usb_alloc_urb(0, gfp); if (!buf->urb) @@ -337,6 +338,25 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen); } +int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, + int len, int data_len, gfp_t gfp) +{ + struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; + + buf->urb = usb_alloc_urb(0, gfp); + if (!buf->urb) + return -ENOMEM; + + buf->buf = page_frag_alloc(&q->rx_page, len, gfp); + if (!buf->buf) + return -ENOMEM; + + buf->len = data_len; + buf->dev = dev; + + return 0; +} + void mt76u_buf_free(struct mt76u_buf *buf) { struct urb *urb = buf->urb; @@ -350,6 +370,9 @@ void mt76u_buf_free(struct mt76u_buf *buf) skb_free_frag(sg_virt(sg)); } + if (buf->buf) + skb_free_frag(buf->buf); + usb_free_urb(buf->urb); } EXPORT_SYMBOL_GPL(mt76u_buf_free); @@ -360,6 +383,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, { struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(intf); + u8 *data = buf->urb->num_sgs ? NULL : buf->buf; unsigned int pipe; if (dir == USB_DIR_IN) @@ -367,7 +391,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, else pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]); - usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, buf->len, + usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len, complete_fn, context); trace_submit_urb(dev, buf->urb); @@ -555,10 +579,10 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) q->ndesc = MT_NUM_RX_ENTRIES; for (i = 0; i < q->ndesc; i++) { - err = mt76u_buf_alloc(dev, &q->entry[i].ubuf, - nsgs, q->buf_size, - SKB_WITH_OVERHEAD(q->buf_size), - GFP_KERNEL); + err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf, + nsgs, q->buf_size, + SKB_WITH_OVERHEAD(q->buf_size), + GFP_KERNEL); if (err < 0) return err; } diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c index 9527e1216f3d..72c8607da4b4 100644 --- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/usb_mcu.c @@ -29,9 +29,8 @@ int mt76u_mcu_init_rx(struct mt76_dev *dev) struct mt76_usb *usb = &dev->usb; int err; - err = mt76u_buf_alloc(dev, &usb->mcu.res, 1, - MCU_RESP_URB_SIZE, MCU_RESP_URB_SIZE, - GFP_KERNEL); + err = mt76u_buf_alloc(dev, &usb->mcu.res, MCU_RESP_URB_SIZE, + MCU_RESP_URB_SIZE, GFP_KERNEL); if (err < 0) return err; -- cgit v1.2.3 From f752294946ae79aa610dda08413e3d5721faed27 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 12 Feb 2019 14:42:41 +0100 Subject: mt76: usb: use a linear buffer for tx/rx datapath if sg is not supported Use linear fragment and not a single usb scatter-gather buffer in mt76u {tx,rx} datapath if the usb controller has sg data length constraints Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 87 ++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index e32ec89781c6..0970a53d6ed5 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -432,10 +432,11 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) } static int -mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) +mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - u8 *data = sg_virt(&urb->sg[0]); + struct urb *urb = buf->urb; + u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf; int data_len, len, nsgs = 1; struct sk_buff *skb; @@ -446,7 +447,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) if (len < 0) return 0; - data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN); + data_len = urb->num_sgs ? urb->sg[0].length : buf->len; + data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN); if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size)) return 0; @@ -458,7 +460,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb) __skb_put(skb, data_len); len -= data_len; - while (len > 0) { + while (len > 0 && urb->num_sgs) { data_len = min_t(int, len, urb->sg[nsgs].length); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, sg_page(&urb->sg[nsgs]), @@ -503,12 +505,26 @@ out: spin_unlock_irqrestore(&q->lock, flags); } +static int +mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, + struct mt76u_buf *buf, int nsgs) +{ + if (dev->usb.sg_en) { + return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size, + SKB_WITH_OVERHEAD(q->buf_size)); + } else { + buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, + GFP_ATOMIC); + return buf->buf ? 0 : -ENOMEM; + } +} + static void mt76u_rx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int err, nsgs, buf_len = q->buf_size; struct mt76u_buf *buf; + int err, count; rcu_read_lock(); @@ -517,11 +533,9 @@ static void mt76u_rx_tasklet(unsigned long data) if (!buf) break; - nsgs = mt76u_process_rx_entry(dev, buf->urb); - if (nsgs > 0) { - err = mt76u_fill_rx_sg(dev, buf, nsgs, - buf_len, - SKB_WITH_OVERHEAD(buf_len)); + count = mt76u_process_rx_entry(dev, buf); + if (count > 0) { + err = mt76u_refill_rx(dev, q, buf, count); if (err < 0) break; } @@ -559,7 +573,7 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers); static int mt76u_alloc_rx(struct mt76_dev *dev) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - int i, err, nsgs; + int i, err; spin_lock_init(&q->rx_page_lock); spin_lock_init(&q->lock); @@ -569,20 +583,19 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) if (!q->entry) return -ENOMEM; - if (dev->usb.sg_en) { - q->buf_size = MT_RX_BUF_SIZE; - nsgs = MT_SG_MAX_SIZE; - } else { - q->buf_size = PAGE_SIZE; - nsgs = 1; - } - + q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; q->ndesc = MT_NUM_RX_ENTRIES; for (i = 0; i < q->ndesc; i++) { - err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf, - nsgs, q->buf_size, - SKB_WITH_OVERHEAD(q->buf_size), - GFP_KERNEL); + if (dev->usb.sg_en) + err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf, + MT_SG_MAX_SIZE, q->buf_size, + SKB_WITH_OVERHEAD(q->buf_size), + GFP_KERNEL); + else + err = mt76u_buf_alloc(dev, &q->entry[i].ubuf, + q->buf_size, + SKB_WITH_OVERHEAD(q->buf_size), + GFP_KERNEL); if (err < 0) return err; } @@ -730,7 +743,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, { struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(intf); - u8 ep = q2ep(q->hw_idx); + u8 *data = NULL, ep = q2ep(q->hw_idx); struct mt76u_buf *buf; u16 idx = q->tail; unsigned int pipe; @@ -747,12 +760,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, buf = &q->entry[idx].ubuf; buf->done = false; - err = mt76u_tx_build_sg(skb, buf->urb); - if (err < 0) - return err; + if (dev->usb.sg_en) { + err = mt76u_tx_build_sg(skb, buf->urb); + if (err < 0) + return err; + } else { + data = skb->data; + } pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]); - usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, skb->len, + usb_fill_bulk_urb(buf->urb, udev, pipe, data, skb->len, mt76u_complete_tx, buf); q->tail = (q->tail + 1) % q->ndesc; @@ -788,10 +805,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) { struct mt76u_buf *buf; struct mt76_queue *q; - size_t size; int i, j; - size = MT_SG_MAX_SIZE * sizeof(struct scatterlist); for (i = 0; i < IEEE80211_NUM_ACS; i++) { q = &dev->q_tx[i]; spin_lock_init(&q->lock); @@ -813,9 +828,15 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) if (!buf->urb) return -ENOMEM; - buf->urb->sg = devm_kzalloc(dev->dev, size, GFP_KERNEL); - if (!buf->urb->sg) - return -ENOMEM; + if (dev->usb.sg_en) { + size_t size = MT_SG_MAX_SIZE * + sizeof(struct scatterlist); + + buf->urb->sg = devm_kzalloc(dev->dev, size, + GFP_KERNEL); + if (!buf->urb->sg) + return -ENOMEM; + } } } return 0; -- cgit v1.2.3 From c2908a0dfd7ab13381f09fde636f1429d4bb5eaa Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 12 Feb 2019 14:42:42 +0100 Subject: mt76: usb: introduce disable_usb_sg parameter Add disable_usb_sg module parameter to disable scatter-gather on demand Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 0970a53d6ed5..c9f095c1f161 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -22,6 +22,10 @@ #define MT_VEND_REQ_MAX_RETRY 10 #define MT_VEND_REQ_TOUT_MS 300 +static bool disable_usb_sg; +module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644); +MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support"); + /* should be called with usb_ctrl_mtx locked */ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req, u8 req_type, u16 val, u16 offset, @@ -246,7 +250,7 @@ static bool mt76u_check_sg(struct mt76_dev *dev) struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(intf); - return (udev->bus->sg_tablesize > 0 && + return (!disable_usb_sg && udev->bus->sg_tablesize > 0 && (udev->bus->no_sg_constraint || udev->speed == USB_SPEED_WIRELESS)); } -- cgit v1.2.3 From 4bfff1ec2599d737470daa3b80711fbc2e8ccfd2 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 12 Feb 2019 00:45:55 +0100 Subject: mt76: usb: use dev_err_ratelimited instead of dev_err in mt76u_complete_rx During device removal the driver can report multiple error messages. Use dev_err_ratelimited instead of dev_err to display urb errors Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index c9f095c1f161..78191968b4fa 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -492,7 +492,8 @@ static void mt76u_complete_rx(struct urb *urb) case -ENOENT: return; default: - dev_err(dev->dev, "rx urb failed: %d\n", urb->status); + dev_err_ratelimited(dev->dev, "rx urb failed: %d\n", + urb->status); /* fall through */ case 0: break; -- cgit v1.2.3 From 3eeb7c062d88cd3d9a7c0deac71bb1b48ac99c30 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 12 Feb 2019 10:24:42 +0100 Subject: mt76x02u: remove bogus check and comment padding In mt76x02u_skb_dma_info() pad is always non-zero. Patch removes bogus check and add comments to the function. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c index 098d05e109e7..43f07461c8d3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c @@ -49,7 +49,12 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) FIELD_PREP(MT_TXD_INFO_DPORT, port) | flags; put_unaligned_le32(info, skb_push(skb, sizeof(info))); + /* Add zero pad of 4 - 7 bytes */ pad = round_up(skb->len, 4) + 4 - skb->len; + + /* First packet of a A-MSDU burst keeps track of the whole burst + * length, need to update lenght of it and the last packet. + */ skb_walk_frags(skb, iter) { last = iter; if (!iter->next) { @@ -59,11 +64,10 @@ int mt76x02u_skb_dma_info(struct sk_buff *skb, int port, u32 flags) } } - if (unlikely(pad)) { - if (skb_pad(last, pad)) - return -ENOMEM; - __skb_put(last, pad); - } + if (skb_pad(last, pad)) + return -ENOMEM; + __skb_put(last, pad); + return 0; } -- cgit v1.2.3 From d0ff23c1107e8c6ddc7534cafb65844b292b1540 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 12 Feb 2019 15:36:24 +0000 Subject: mt76: Use the correct hweight8() function mt76_init_stream_cap() and mt76_get_txpower() call __sw_hweight8() directly, but that's only defined if CONFIG_GENERIC_HWEIGHT is enabled. The function that works on all architectures is hweight8(). Fixes: 551e1ef4d291 ("mt76: add mt76_init_stream_cap routine") Fixes: 9313faacbb4e ("mt76: move mt76x02_get_txpower to mt76 core") Signed-off-by: Ben Hutchings Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index c7abf4f54867..82e9f78ef328 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -124,7 +124,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev, bool vht) { struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; - int i, nstream = __sw_hweight8(dev->antenna_mask); + int i, nstream = hweight8(dev->antenna_mask); struct ieee80211_sta_vht_cap *vht_cap; u16 mcs_map = 0; @@ -726,7 +726,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int *dbm) { struct mt76_dev *dev = hw->priv; - int n_chains = __sw_hweight8(dev->antenna_mask); + int n_chains = hweight8(dev->antenna_mask); *dbm = dev->txpower_cur / 2; -- cgit v1.2.3 From b231cd7f557d59b7922a3b8dc29ef1f23338f1fc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 25 Jan 2019 15:10:52 +0100 Subject: mt76: fix tx status timeout processing Remove bogus check for MT_PACKET_ID_NO_ACK in mt76_tx_status_skb_get, which is already handled in callers and turns timeout calls into no-ops Do not clean up pending status items on reordering of tx status information if the timeout is not reached yet Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/tx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index ef38e8626da9..5a349fe3e576 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -205,9 +205,6 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, { struct sk_buff *skb, *tmp; - if (pktid == MT_PACKET_ID_NO_ACK) - return NULL; - skb_queue_walk_safe(&dev->status_list, skb, tmp) { struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); @@ -217,7 +214,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, if (cb->pktid == pktid) return skb; - if (!pktid && + if (pktid >= 0 && !time_after(jiffies, cb->jiffies + MT_TX_STATUS_SKB_TIMEOUT)) continue; -- cgit v1.2.3 From 906d2d3f874a54183df5a609fda180adf0462428 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 25 Jan 2019 17:59:06 +0100 Subject: mt76: fix corrupted software generated tx CCMP PN Since ccmp_pn is u8 *, the second half needs to start at array index 4 instead of 0. Fixes a connection stall after a certain amount of traffic Fixes: 23405236460b9 ("mt76: fix transmission of encrypted management frames") Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index bf39624c9b98..eab713723b7e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -314,7 +314,7 @@ void mt76x02_mac_write_txwi(struct mt76x02_dev *dev, struct mt76x02_txwi *txwi, ccmp_pn[6] = pn >> 32; ccmp_pn[7] = pn >> 40; txwi->iv = *((__le32 *)&ccmp_pn[0]); - txwi->eiv = *((__le32 *)&ccmp_pn[1]); + txwi->eiv = *((__le32 *)&ccmp_pn[4]); } spin_lock_bh(&dev->mt76.lock); -- cgit v1.2.3 From f2f6a47b504b8fe19922e835231552a01ef30e01 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 25 Jan 2019 18:00:11 +0100 Subject: mt76: fix resetting software IV flag on key delete It needs to be unset instead of set Fixes: 23405236460b9 ("mt76: fix transmission of encrypted management frames") Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 87ed00768bc7..11b5f664f5b1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -431,7 +431,7 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, } else { if (idx == wcid->hw_key_idx) { wcid->hw_key_idx = -1; - wcid->sw_iv = true; + wcid->sw_iv = false; } key = NULL; -- cgit v1.2.3 From 9f688473408b6334c5da5ec085f9ea1954675fe7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 18 Feb 2019 20:29:11 +0100 Subject: mt76: mt76x2: simplify per-chain signal strength handling There is no need to use a for loop here, supported chips can only support up to 2 chains. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index eab713723b7e..be2979f34f31 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -608,7 +608,7 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, u16 rate = le16_to_cpu(rxwi->rate); u16 tid_sn = le16_to_cpu(rxwi->tid_sn); bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST); - int i, pad_len = 0, nstreams = dev->mt76.chainmask & 0xf; + int pad_len = 0, nstreams = dev->mt76.chainmask & 0xf; s8 signal; u8 pn_len; u8 wcid; @@ -668,12 +668,13 @@ int mt76x02_mac_process_rx(struct mt76x02_dev *dev, struct sk_buff *skb, status->chains = BIT(0); signal = mt76x02_mac_get_rssi(dev, rxwi->rssi[0], 0); - for (i = 0; i < nstreams; i++) { - status->chains |= BIT(i); - status->chain_signal[i] = mt76x02_mac_get_rssi(dev, - rxwi->rssi[i], - i); - signal = max_t(s8, signal, status->chain_signal[i]); + status->chain_signal[0] = signal; + if (nstreams > 1) { + status->chains |= BIT(1); + status->chain_signal[1] = mt76x02_mac_get_rssi(dev, + rxwi->rssi[1], + 1); + signal = max_t(s8, signal, status->chain_signal[1]); } status->signal = signal; status->freq = dev->mt76.chandef.chan->center_freq; -- cgit v1.2.3 From ed95799bd47480cc0571749ed1d2d85813163107 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 18 Feb 2019 15:35:25 +0900 Subject: net: hamradio: remove unused hweight*() defines This file does not use hweight*() at all, and the definition is surrounded by #if 0 ... #endif. Signed-off-by: Masahiro Yamada Signed-off-by: David S. Miller --- drivers/net/hamradio/baycom_ser_fdx.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c index 190f66c88479..ed0841630990 100644 --- a/drivers/net/hamradio/baycom_ser_fdx.c +++ b/drivers/net/hamradio/baycom_ser_fdx.c @@ -203,32 +203,6 @@ static inline void ser12_set_divisor(struct net_device *dev, */ } -/* --------------------------------------------------------------------- */ - -#if 0 -static inline unsigned int hweight16(unsigned int w) - __attribute__ ((unused)); -static inline unsigned int hweight8(unsigned int w) - __attribute__ ((unused)); - -static inline unsigned int hweight16(unsigned int w) -{ - unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555); - res = (res & 0x3333) + ((res >> 2) & 0x3333); - res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); - return (res & 0x00FF) + ((res >> 8) & 0x00FF); -} - -static inline unsigned int hweight8(unsigned int w) -{ - unsigned short res = (w & 0x55) + ((w >> 1) & 0x55); - res = (res & 0x33) + ((res >> 2) & 0x33); - return (res & 0x0F) + ((res >> 4) & 0x0F); -} -#endif - -/* --------------------------------------------------------------------- */ - static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timespec64 *ts, unsigned char curs) { int timediff; -- cgit v1.2.3 From 31ef5b0eef2afb2df23728f2b88f0c245617f258 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Mon, 18 Feb 2019 07:19:44 +0000 Subject: mlxsw: spectrum: Change IP2ME CPU policer rate and burst size values The IP2ME packet trap is triggered by packets hitting local routes. After evaluating current defaults used by the driver it was decided to reduce the amount of traffic generated by this trap to 1Kpps and increase the burst size. This is inline with similarly deployed systems. Signed-off-by: Shalom Toledo Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index abac923a8d04..bc349d8ca08a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3739,8 +3739,8 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core) burst_size = 7; break; case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME: - rate = 4 * 1024; - burst_size = 4; + rate = 1024; + burst_size = 7; break; default: continue; -- cgit v1.2.3 From 780feae7eb69388c8d8b661cda6706b0dc0f642b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 16 Feb 2019 10:59:35 +0800 Subject: mdio_bus: Fix PTR_ERR() usage after initialization to constant Fix coccinelle warning: ./drivers/net/phy/mdio_bus.c:51:5-12: ERROR: PTR_ERR applied after initialization to constant on line 44 ./drivers/net/phy/mdio_bus.c:52:5-12: ERROR: PTR_ERR applied after initialization to constant on line 44 fix this by using IS_ERR before PTR_ERR Fixes: bafbdd527d56 ("phylib: Add device reset GPIO support") Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 3d313585c9c1..debc74c90307 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -48,11 +48,12 @@ static int mdiobus_register_gpiod(struct mdio_device *mdiodev) gpiod = fwnode_get_named_gpiod(&mdiodev->dev.of_node->fwnode, "reset-gpios", 0, GPIOD_OUT_LOW, "PHY reset"); - if (PTR_ERR(gpiod) == -ENOENT || - PTR_ERR(gpiod) == -ENOSYS) - gpiod = NULL; - else if (IS_ERR(gpiod)) - return PTR_ERR(gpiod); + if (IS_ERR(gpiod)) { + if (PTR_ERR(gpiod) == -ENOENT || PTR_ERR(gpiod) == -ENOSYS) + gpiod = NULL; + else + return PTR_ERR(gpiod); + } mdiodev->reset = gpiod; -- cgit v1.2.3 From eb160971af7a2cd807a76adea44e924ebfa05708 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 16 Feb 2019 10:20:15 +0100 Subject: r8169: remove unneeded mmiowb barriers writex() has implicit barriers, that's what makes it different from writex_relaxed(). Therefore these calls to mmiowb() can be removed. This patch was recently reverted due to a dependency with another problematic patch. But because it didn't contribute to the problem it was rebased and can be resubmitted. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 10bab1f7150a..c29dde064078 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1288,13 +1288,11 @@ static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr) static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) { RTL_W16(tp, IntrStatus, bits); - mmiowb(); } static void rtl_irq_disable(struct rtl8169_private *tp) { RTL_W16(tp, IntrMask, 0); - mmiowb(); } #define RTL_EVENT_NAPI_RX (RxOK | RxErr) @@ -6251,8 +6249,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, RTL_W8(tp, TxPoll, NPQ); - mmiowb(); - if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) { /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must * not miss a ring update when it notices a stopped queue. @@ -6597,9 +6593,7 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) if (work_done < budget) { napi_complete_done(napi, work_done); - rtl_irq_enable(tp); - mmiowb(); } return work_done; -- cgit v1.2.3 From bf9d787ba7ea87c5c676a73a0ba191edd5a0341a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 16 Feb 2019 17:53:10 +0800 Subject: liquidio: using NULL instead of plain integer Fix following warning: drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c:1453:35: warning: Using plain integer as NULL pointer drivers/net/ethernet/cavium/liquidio/lio_main.c:2910:23: warning: Using plain integer as NULL pointer Signed-off-by: YueHaibing Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c | 2 +- drivers/net/ethernet/cavium/liquidio/lio_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c index 9f4f3c1d5043..43d11c38b38a 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c @@ -1450,7 +1450,7 @@ void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx, mbox_cmd.recv_len = 0; mbox_cmd.recv_status = 0; mbox_cmd.fn = NULL; - mbox_cmd.fn_arg = 0; + mbox_cmd.fn_arg = NULL; ether_addr_copy(mbox_cmd.msg.s.params, mac); mbox_cmd.q_no = vfidx * oct->sriov_info.rings_per_vf; octeon_mbox_write(oct, &mbox_cmd); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index e97e6754ee09..9b7819fdc9de 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -2907,7 +2907,7 @@ static int liquidio_set_vf_spoofchk(struct net_device *netdev, int vfidx, nctrl.ncmd.s.param2 = enable; nctrl.ncmd.s.more = 0; nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; - nctrl.cb_fn = 0; + nctrl.cb_fn = NULL; retval = octnet_send_nic_ctrl_pkt(oct, &nctrl); -- cgit v1.2.3 From 96c2be34e6ceb8141015daac1a749aafce95e1bd Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 16 Feb 2019 17:26:50 +0100 Subject: net: phy: use mii_10gbt_stat_mod_linkmode_lpa_t in genphy_c45_read_lpa Use mii_10gbt_stat_mod_linkmode_lpa_t() in genphy_c45_read_lpa() to simplify the code. Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index e17672bd180e..1cf5e8ae46de 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -248,15 +248,7 @@ int genphy_c45_read_lpa(struct phy_device *phydev) if (val < 0) return val; - if (val & MDIO_AN_10GBT_STAT_LP2_5G) - linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - phydev->lp_advertising); - if (val & MDIO_AN_10GBT_STAT_LP5G) - linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, - phydev->lp_advertising); - if (val & MDIO_AN_10GBT_STAT_LP10G) - linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, - phydev->lp_advertising); + mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, val); return 0; } -- cgit v1.2.3 From c9b747dbc2036c917b1067fbb78dc38b105c4454 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 18 Feb 2019 12:19:54 +0000 Subject: bnx2x: Remove set but not used variable 'mfw_vn' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c: In function 'bnx2x_get_hwinfo': drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c:11940:10: warning: variable 'mfw_vn' set but not used [-Wunused-but-set-variable] It's never used since introduction. Signed-off-by: YueHaibing Acked-by: Sudarsana Reddy Kalluru Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 0cec82450e19..626b491f7674 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -11998,7 +11998,7 @@ static void validate_set_si_mode(struct bnx2x *bp) static int bnx2x_get_hwinfo(struct bnx2x *bp) { int /*abs*/func = BP_ABS_FUNC(bp); - int vn, mfw_vn; + int vn; u32 val = 0, val2 = 0; int rc = 0; @@ -12083,12 +12083,10 @@ static int bnx2x_get_hwinfo(struct bnx2x *bp) /* * Initialize MF configuration */ - bp->mf_ov = 0; bp->mf_mode = 0; bp->mf_sub_mode = 0; vn = BP_VN(bp); - mfw_vn = BP_FW_MB_IDX(bp); if (!CHIP_IS_E1(bp) && !BP_NOMCP(bp)) { BNX2X_DEV_INFO("shmem2base 0x%x, size %d, mfcfg offset %d\n", -- cgit v1.2.3 From d27a76fa5a666eee9e892ea1abaed97374d6bfc3 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:08 -0600 Subject: rtlwifi: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/base.c | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/base.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/cam.c | 27 +++--------------------- drivers/net/wireless/realtek/rtlwifi/cam.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/core.c | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/core.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/debug.c | 25 ++-------------------- drivers/net/wireless/realtek/rtlwifi/debug.h | 25 ++-------------------- drivers/net/wireless/realtek/rtlwifi/efuse.c | 27 +++--------------------- drivers/net/wireless/realtek/rtlwifi/efuse.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/pci.c | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/pci.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/ps.c | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/ps.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/rc.c | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/rc.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/regd.c | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/regd.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/stats.c | 27 +++--------------------- drivers/net/wireless/realtek/rtlwifi/stats.h | 26 ++--------------------- drivers/net/wireless/realtek/rtlwifi/usb.c | 24 ++------------------- drivers/net/wireless/realtek/rtlwifi/usb.h | 24 ++------------------- drivers/net/wireless/realtek/rtlwifi/wifi.h | 26 ++--------------------- 24 files changed, 51 insertions(+), 570 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 137b68ae457e..672c0b73cb65 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "wifi.h" #include "rc.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h index a7ae40eaa3cd..99565ad09cdc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.h +++ b/drivers/net/wireless/realtek/rtlwifi/base.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_BASE_H__ #define __RTL_BASE_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/cam.c b/drivers/net/wireless/realtek/rtlwifi/cam.c index f7a7dcbf945e..bf0e0bb1f99b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/cam.c +++ b/drivers/net/wireless/realtek/rtlwifi/cam.c @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #include "wifi.h" #include "cam.h" #include diff --git a/drivers/net/wireless/realtek/rtlwifi/cam.h b/drivers/net/wireless/realtek/rtlwifi/cam.h index e2e647d511c1..2461fa9afda0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/cam.h +++ b/drivers/net/wireless/realtek/rtlwifi/cam.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_CAM_H_ #define __RTL_CAM_H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index ce23339bf9fb..0913f02b7ff1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "wifi.h" #include "core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/core.h b/drivers/net/wireless/realtek/rtlwifi/core.h index 782ac2fc4b28..7447ff456710 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.h +++ b/drivers/net/wireless/realtek/rtlwifi/core.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_CORE_H__ #define __RTL_CORE_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c index 8186650efc56..a051de16284d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/debug.c +++ b/drivers/net/wireless/realtek/rtlwifi/debug.c @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "wifi.h" #include "cam.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h index ad6834af618b..b1d51d135680 100644 --- a/drivers/net/wireless/realtek/rtlwifi/debug.h +++ b/drivers/net/wireless/realtek/rtlwifi/debug.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_DEBUG_H__ #define __RTL_DEBUG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c index 9729e51fce38..3b2b603ca871 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.c +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * Tmis program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * Tmis program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * Tme full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #include "wifi.h" #include "efuse.h" #include "pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.h b/drivers/net/wireless/realtek/rtlwifi/efuse.h index dfa31c13fc7a..d3643577ff86 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.h +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_EFUSE_H_ #define __RTL_EFUSE_H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index 5d1fda16fc8c..48ca52102cef 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "wifi.h" #include "core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h index 3fb56c845a61..866861626a0a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.h +++ b/drivers/net/wireless/realtek/rtlwifi/pci.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_PCI_H__ #define __RTL_PCI_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c index 479a4cfc245d..dca70d239760 100644 --- a/drivers/net/wireless/realtek/rtlwifi/ps.c +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "wifi.h" #include "base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.h b/drivers/net/wireless/realtek/rtlwifi/ps.h index 0df2b5203030..aaa2ed2bbe16 100644 --- a/drivers/net/wireless/realtek/rtlwifi/ps.h +++ b/drivers/net/wireless/realtek/rtlwifi/ps.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __REALTEK_RTL_PCI_PS_H__ #define __REALTEK_RTL_PCI_PS_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h index 17ce0cb2c35c..db1765c6fef6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h +++ b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_PWRSEQCMD_H__ #define __RTL8723E_PWRSEQCMD_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c index 6c78c6dabbdf..8fa76eab61d2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "wifi.h" #include "base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.h b/drivers/net/wireless/realtek/rtlwifi/rc.h index f29643d60d6b..1c0a17370093 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rc.h +++ b/drivers/net/wireless/realtek/rtlwifi/rc.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_RC_H__ #define __RTL_RC_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index 1bf3eb25c1da..a1f58034642c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "wifi.h" #include "regd.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.h b/drivers/net/wireless/realtek/rtlwifi/regd.h index f7f15bce35dd..3ba068511e34 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.h +++ b/drivers/net/wireless/realtek/rtlwifi/regd.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_REGD_H__ #define __RTL_REGD_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/stats.c b/drivers/net/wireless/realtek/rtlwifi/stats.c index 61700fa05570..504ca587a16a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/stats.c +++ b/drivers/net/wireless/realtek/rtlwifi/stats.c @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #include "wifi.h" #include "stats.h" #include diff --git a/drivers/net/wireless/realtek/rtlwifi/stats.h b/drivers/net/wireless/realtek/rtlwifi/stats.h index bd0108f93182..581590729b0f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/stats.h +++ b/drivers/net/wireless/realtek/rtlwifi/stats.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_STATS_H__ #define __RTL_STATS_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 2ac5004d7a40..749752421931 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -1,25 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "wifi.h" #include "core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h index c91cec04bfaf..30a21508cfa2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.h +++ b/drivers/net/wireless/realtek/rtlwifi/usb.h @@ -1,25 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_USB_H__ #define __RTL_USB_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 87bc21bb5e8b..2065e4369179 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL_WIFI_H__ #define __RTL_WIFI_H__ -- cgit v1.2.3 From 8c0863125229bb2d6f76d2546c0fb7bcc4662261 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:09 -0600 Subject: rtlwifi: btcoex: Replace old-style license information The old-style license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../realtek/rtlwifi/btcoexist/halbt_precomp.h | 25 ++-------------- .../realtek/rtlwifi/btcoexist/halbtc8192e2ant.c | 35 ++-------------------- .../realtek/rtlwifi/btcoexist/halbtc8192e2ant.h | 27 ++--------------- .../realtek/rtlwifi/btcoexist/halbtc8723b1ant.c | 26 ++-------------- .../realtek/rtlwifi/btcoexist/halbtc8723b1ant.h | 27 ++--------------- .../realtek/rtlwifi/btcoexist/halbtc8723b2ant.c | 27 ++--------------- .../realtek/rtlwifi/btcoexist/halbtc8723b2ant.h | 27 ++--------------- .../realtek/rtlwifi/btcoexist/halbtc8821a1ant.c | 26 ++-------------- .../realtek/rtlwifi/btcoexist/halbtc8821a1ant.h | 26 ++-------------- .../realtek/rtlwifi/btcoexist/halbtc8821a2ant.c | 26 ++-------------- .../realtek/rtlwifi/btcoexist/halbtc8821a2ant.h | 26 ++-------------- .../rtlwifi/btcoexist/halbtc8822bwifionly.c | 17 ++--------- .../rtlwifi/btcoexist/halbtc8822bwifionly.h | 17 ++--------- .../realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 26 ++-------------- .../realtek/rtlwifi/btcoexist/halbtcoutsrc.h | 27 ++--------------- .../wireless/realtek/rtlwifi/btcoexist/rtl_btc.c | 27 ++--------------- .../wireless/realtek/rtlwifi/btcoexist/rtl_btc.h | 25 ++-------------- 17 files changed, 42 insertions(+), 395 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h index 02dff4c3f664..602cac41c910 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - ******************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2007-2011 Realtek Corporation.*/ #ifndef __HALBT_PRECOMP_H__ #define __HALBT_PRECOMP_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c index f22fec093f1d..3ebc7c93b1e9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c @@ -1,36 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -/************************************************************** - * Description: - * - * This file is for RTL8192E Co-exist mechanism - * - * History - * 2012/11/15 Cosa first check in. - * - **************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2012 Realtek Corporation.*/ /************************************************************** * include files diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h index b8c95c7afc06..41ac0d5dcc9c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2012 Realtek Corporation.*/ + /***************************************************************** * The following is for 8192E 2Ant BT Co-exist definition *****************************************************************/ diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c index 59553db020ef..5f5739904edf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2012 Realtek Corporation.*/ /*************************************************************** * Description: diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h index 934f27893c16..9d41e11388ad 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2012 Realtek Corporation.*/ + /********************************************************************** * The following is for 8723B 1ANT BT Co-exist definition **********************************************************************/ diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c index 6597f7cb3411..9f7b9af5bdcd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2012 Realtek Corporation.*/ + /*************************************************************** * Description: * diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h index aa24da402fb9..08aad6ef4046 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2012 Realtek Corporation.*/ + #ifndef _HAL8723B_2_ANT #define _HAL8723B_2_ANT diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c index b5d65872db84..fa5b73f81c57 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2012 Realtek Corporation.*/ /************************************************************** * Description: diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h index a498ff5b1b9c..a63fb79a971a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2012 Realtek Corporation.*/ /*=========================================== * The following is for 8821A 1ANT BT Co-exist definition diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c index 01a9d303603b..e9e211fda264 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2012 Realtek Corporation.*/ /************************************************************ * Description: diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h index ce3e58c4e660..3df0ee8bd37b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2012 Realtek Corporation.*/ /*=========================================== * The following is for 8821A 2Ant BT Co-exist definition diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c index 951b8c1e0153..145d6f9c017a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.c @@ -1,17 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2016-2017 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2016-2017 Realtek Corporation.*/ + #include "halbt_precomp.h" void ex_hal8822b_wifi_only_hw_config(struct wifi_only_cfg *wifionlycfg) diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h index 6ec356542eea..5fc66cea74b2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8822bwifionly.h @@ -1,17 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2016-2017 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2016-2017 Realtek Corporation.*/ + #ifndef __INC_HAL8822BWIFIONLYHWCFG_H #define __INC_HAL8822BWIFIONLYHWCFG_H diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index d748aab66aa2..2ac0481b29ef 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - ******************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2007-2013 Realtek Corporation.*/ #include "halbt_precomp.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h index 9eae87d19120..ee9aeddf1ebc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __HALBTC_OUT_SRC_H__ #define __HALBTC_OUT_SRC_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c index cce4a37ea408..0e509c33e9e6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ + #include "../wifi.h" #include #include diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h index 8c996055de71..bf2cf8505aca 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL_BTC_H__ #define __RTL_BTC_H__ -- cgit v1.2.3 From fbb352862190e215ab90e8d2e7505ec108045ed8 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:10 -0600 Subject: rtlwifi: rtl8188ee: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8188ee/def.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/dm.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/dm.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/fw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/fw.h | 25 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8188ee/hw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/hw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/led.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/led.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/phy.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/phy.h | 26 ++------------------ .../wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c | 26 ++------------------ .../wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/reg.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/rf.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/rf.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/sw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/sw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/table.c | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8188ee/table.h | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8188ee/trx.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8188ee/trx.h | 26 ++------------------ 22 files changed, 44 insertions(+), 531 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h index 45c866d3ca88..9fb3a22f6c9e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92C_DEF_H__ #define __RTL92C_DEF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c index e05af7d60830..85360353f557 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h index 50f26a9a97db..eb8090caeec2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL88E_DM_H__ #define __RTL88E_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c index 63874512598b..203e7b574e84 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h index b884c30c7b37..39ddb7afea9d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92C__FW__H__ #define __RTL92C__FW__H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c index cfc8762c55f4..454bab38b165 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h index 214cd2a32018..fd09b0712d17 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92CE_HW_H__ #define __RTL92CE_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c index df3e214460db..4ef6d5907521 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h index 4b325b75faaf..67d3dc389ba0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92CE_LED_H__ #define __RTL92CE_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c index 14a256062614..96d8f25b120f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h index b29bd77210f4..8157ef419eeb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92C_PHY_H__ #define __RTL92C_PHY_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c index 02013df968a0..d69497bf5d19 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../pwrseqcmd.h" #include "pwrseq.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h index 8379a3e5198c..42e222c1795f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL8723E_PWRSEQ_H__ #define __RTL8723E_PWRSEQ_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h index 0c0d64aea651..0fc8db8916fa 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92C_REG_H__ #define __RTL92C_REG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c index 30798b12a363..0f401ad92c2e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h index 0eca030e3238..05e27b40b2a9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92C_RF_H__ #define __RTL92C_RF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c index 8c15ffd3568b..eab48fed61ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h index 22398c3753a6..1407151503f8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92CE_SW_H__ #define __RTL92CE_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c index 68bcb7fe6a65..a3c312c3ed9a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "table.h" u32 RTL8188EEPHY_REG_1TARRAY[] = { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h index 403c4ddd236f..df6065602401 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92CE_TABLE__H_ #define __RTL92CE_TABLE__H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 14dcb0816bc0..79a335f43133 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h index 127ba977206f..c29d9bfa5bd4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2013 Realtek Corporation.*/ #ifndef __RTL92CE_TRX_H__ #define __RTL92CE_TRX_H__ -- cgit v1.2.3 From e7011369180408cfc72b5ac4b20d0a4199681d75 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:11 -0600 Subject: rtlwifi: rtl8192com: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192c/dm_common.c | 26 ++-------------------- .../wireless/realtek/rtlwifi/rtl8192c/dm_common.h | 26 ++-------------------- .../wireless/realtek/rtlwifi/rtl8192c/fw_common.c | 26 ++-------------------- .../wireless/realtek/rtlwifi/rtl8192c/fw_common.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192c/main.c | 26 ++-------------------- .../wireless/realtek/rtlwifi/rtl8192c/phy_common.c | 26 ++-------------------- .../wireless/realtek/rtlwifi/rtl8192c/phy_common.h | 26 ++-------------------- 7 files changed, 14 insertions(+), 168 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c index 0b5a06ffa482..2f633118c717 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include #include "dm_common.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h index 441604ff5858..5315c7f21fc4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92COMMON_DM_H__ #define __RTL92COMMON_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c index f3bff66e85d0..cd9610d0f198 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h index c5fa14bda387..888d9fc94bc2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C__FW__COMMON__H__ #define __RTL92C__FW__COMMON__H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c index 889bd1301154..e8af1952d243 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c index 7c6e5d91439d..083791b705dc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../rtl8192ce/reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h index d11261e05a2e..b088a38456c7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_PHY_COMMON_H__ #define __RTL92C_PHY_COMMON_H__ -- cgit v1.2.3 From 0770f718458ed93fe593b887fb7481c30999bea5 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:12 -0600 Subject: rtlwifi: rtl8192ce: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8192ce/def.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/dm.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/dm.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/hw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/led.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/led.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/phy.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/phy.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/reg.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/rf.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/rf.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/sw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/sw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/table.c | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192ce/table.h | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192ce/trx.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ce/trx.h | 26 ++------------------ 18 files changed, 36 insertions(+), 436 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h index d2005d7e9ad2..147bf2407f8f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_DEF_H__ #define __RTL92C_DEF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c index 2c8205e46be4..a3e2c8a60967 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h index 9761d0ca31b0..f6feaf51b860 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_DM_H__ #define __RTL92C_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index 4a81e0ef4b8e..6d6b6f7597a6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h index 6711ea1a75d9..fa1049d16cb7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CE_HW_H__ #define __RTL92CE_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c index 7edf5af9046e..d6933d36ada2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h index f6edb9cd9b67..97ab1e00af5f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CE_LED_H__ #define __RTL92CE_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c index 7c6d7fc1ef9a..b9dbef748c7f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h index 93f3bc0197b4..dbb1aed495ef 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_PHY_H__ #define __RTL92C_PHY_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h index 9e3b58a5d2bb..36fe27aef751 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_REG_H__ #define __RTL92C_REG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c index e68ed7f37c79..895b3c42233a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h index 22c5e6f51331..6fa70224d2d4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_RF_H__ #define __RTL92C_RF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c index 71a6761d3648..a9c0111444bc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h index 9a1c89cbbda1..f2d121a60159 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CE_SW_H__ #define __RTL92CE_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c index 98b06d48a2dd..e258b0803699 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "table.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h index 51e4e07396a6..473af27f80d9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CE_TABLE__H_ #define __RTL92CE_TABLE__H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index d36e0060cc7a..fbf3133a0fd5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h index 91f0bd6b752f..fb1d4444a52f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CE_TRX_H__ #define __RTL92CE_TRX_H__ -- cgit v1.2.3 From b44febedbb8dcc2463e21613b411344fff0b1f27 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:13 -0600 Subject: rtlwifi: rtl8192cu: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8192cu/def.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/dm.c | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/dm.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/hw.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/led.c | 24 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192cu/led.h | 24 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192cu/mac.c | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/mac.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/phy.c | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/phy.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/reg.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/rf.c | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/rf.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/sw.c | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/sw.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/table.c | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/table.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.c | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.h | 26 ++-------------------- 20 files changed, 40 insertions(+), 476 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h index 316fe9990b6d..91e4427ab022 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../rtl8192ce/def.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c index 00fc0685317a..9d1167ff3b50 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h index ce71433792e3..2befc2f4e3fd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../rtl8192ce/dm.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index 1e60f70481f5..f1932d7ca969 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h index ebd168400d45..dfba2c2849b3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CU_HW_H__ #define __RTL92CU_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c index 66d2784de67d..51b8afd40d75 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c @@ -1,25 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../usb.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h index 551deb8afb6f..3fc1e7c8f78b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h @@ -1,25 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CU_LED_H__ #define __RTL92CU_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c index 5657b1e34ad0..cc2ba74bff81 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * -****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h index 8573b7e257d9..62eb3c5adec1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_MAC_H__ #define __RTL92C_MAC_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c index f068dd5317a7..ad8366e7d3a6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h index a422c4db1a41..a3cc980c42fe 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../rtl8192ce/phy.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h index 8185886daa8e..b4b6cde23341 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h @@ -1,26 +1,4 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../rtl8192ce/reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c index cf551785eb08..b65de8874b16 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h index 07aec0b20cc9..2661e5f8f6da 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CU_RF_H__ #define __RTL92CU_RF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c index 43e021b49260..c1c34dca39d2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h index 4ea2cb225580..662440c4cdc9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CU_SW_H__ #define __RTL92CU_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c index b3ac981d88c6..88fb556b80e9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "table.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h index 851bf53d246c..f7c873df3c2c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CU_TABLE__H_ #define __RTL92CU_TABLE__H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index 9ab56827124e..7c32f9d2d69f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../usb.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h index 15a66c547287..d176b0ba6ae6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CU_TRX_H__ #define __RTL92CU_TRX_H__ -- cgit v1.2.3 From 5bd4f692e0eba585674c58f68b8ff62c21468a2f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:14 -0600 Subject: rtlwifi: rtl8192de: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8192de/def.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/dm.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/dm.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/fw.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/fw.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/hw.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/hw.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/led.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/led.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/phy.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/phy.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/reg.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/rf.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/rf.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/sw.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/sw.h | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/table.c | 27 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/table.h | 27 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/trx.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192de/trx.h | 26 ++------------------- 20 files changed, 40 insertions(+), 482 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h index cb7b9b727e3a..fa33b05db052 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92D_DEF_H__ #define __RTL92D_DEF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c index ac6d554b67c8..f7670710f475 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h index 5d346ec366ce..ef39874e2439 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_DM_H__ #define __RTL92C_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c index 75bfa9dfef4a..98da9525a15e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h index 6b435236a28e..bd8ea6d66dff 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92D__FW__H__ #define __RTL92D__FW__H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c index 80123fd97221..603edc399e14 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h index e6c702e69ecf..ea495216d394 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92DE_HW_H__ #define __RTL92DE_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c index 8851038c9eba..2b76a025deb8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h index 9874519704d3..7599c7e5ecc3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CE_LED_H__ #define __RTL92CE_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c index de98d88199d6..2b30a820f45f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h index 58b56b523dbe..8d07c783a023 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92D_PHY_H__ #define __RTL92D_PHY_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h index d4c4e76a9244..77a3a8f0fa02 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92D_REG_H__ #define __RTL92D_REG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c index 021d3c538ac2..915a36f7af5e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h index c650a8dcdb26..4e646cc9ebc0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92D_RF_H__ #define __RTL92D_RF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c index d5ba2bace79b..99e5cd9a5c86 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h index fd7d036e9abc..19db4ce30e44 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92DE_SW_H__ #define __RTL92DE_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c index 4badb183cf35..9b35c65d91f2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c @@ -1,28 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - * Created on 2010/12/23, 6:38 - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h index 7fefc483ec28..2a45082f441f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h @@ -1,28 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - * Created on 2010/ 5/18, 1:41 - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92DE_TABLE__H_ #define __RTL92DE_TABLE__H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c index d7b023cf7400..cb19c6871fe4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h index f7f776539438..36820070fd76 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92DE_TRX_H__ #define __RTL92DE_TRX_H__ -- cgit v1.2.3 From 647f21b10292408ea2420f9179fdaeca4512495b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:15 -0600 Subject: rtlwifi: rtl8192ee: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8192ee/def.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/dm.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/dm.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/fw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/fw.h | 25 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8192ee/hw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/hw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/led.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/led.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/phy.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/phy.h | 26 ++------------------ .../wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c | 26 ++------------------ .../wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/reg.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/rf.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/rf.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/sw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/sw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/table.c | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192ee/table.h | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192ee/trx.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8192ee/trx.h | 26 ++------------------ 22 files changed, 44 insertions(+), 531 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h index 9f7e7bb8610b..fe1b7cdab1d5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_DEF_H__ #define __RTL92E_DEF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c index faed6e2dedf6..648f9108ed4b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h index 107d5a488fa8..ec48e5671b5b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_DM_H__ #define __RTL92E_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c index 84a0d0eb72e1..7c5b54b71a92 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h index 6a2fbf20d579..cbfecea232a3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E__FW__H__ #define __RTL92E__FW__H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c index 3f2295fdb02d..53011c2a44f5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h index 3a63bec9b0cc..fc224392615f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_HW_H__ #define __RTL92E_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c index 96c64785108b..78202ad4036e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h index 8ef640a2ef7f..6d775e14846f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_LED_H__ #define __RTL92E_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c index 8b072ee8e0d5..222abc41669c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h index 49bd0e554c65..1a5dbc628379 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_PHY_H__ #define __RTL92E_PHY_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c index 1a701d007f0c..515c1c3d6b43 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "pwrseq.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h index c570801508cc..2ae8347f7ebb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_PWRSEQ_H__ #define __RTL92E_PWRSEQ_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h index 1eaa1fab550d..0164e006f43e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_REG_H__ #define __RTL92E_REG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c index bc76a91da762..6b8ef680dc57 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h index 039c0133ad6b..d7b391599926 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_RF_H__ #define __RTL92E_RF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c index 9ea62599ecbb..b6ee7dae5943 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h index 21433d0332d0..36e29a2da0fd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_SW_H__ #define __RTL92E_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c index abcdd0670fd8..fb66f610bf5d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "table.h" u32 RTL8192EE_PHY_REG_ARRAY[] = { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h index bff9df88815d..0bc7ef58c3b9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_TABLE__H_ #define __RTL92E_TABLE__H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c index 14d6e3fc5767..91d44430fd8a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h index 45df3e79f490..a9e5e620a653 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL92E_TRX_H__ #define __RTL92E_TRX_H__ -- cgit v1.2.3 From 6f3fcdc88e535b919f829bc30adb42834da54480 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:16 -0600 Subject: rtlwifi: rtl8192se: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8192se/def.h | 27 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/dm.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/dm.h | 27 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/fw.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/fw.h | 27 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/hw.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/hw.h | 27 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/led.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/led.h | 27 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/phy.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/phy.h | 27 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/reg.h | 27 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/rf.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/rf.h | 27 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/sw.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/sw.h | 25 +++----------------- .../net/wireless/realtek/rtlwifi/rtl8192se/table.c | 27 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/table.h | 20 +++------------- .../net/wireless/realtek/rtlwifi/rtl8192se/trx.c | 26 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8192se/trx.h | 27 +++------------------- 20 files changed, 51 insertions(+), 472 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h index b5ba0554a0cd..bb6b60814762 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __REALTEK_92S_DEF_H__ #define __REALTEK_92S_DEF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c index 44f510a94b09..a6e4384ceea1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h index 3af07efed73a..b8efcd8df3e5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __RTL_92S_DM_H__ #define __RTL_92S_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c index e7b1d7c0f542..790124b7e0da 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h index 5827aa32cef0..0cba71f793e9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __REALTEK_FIRMWARE92S_H__ #define __REALTEK_FIRMWARE92S_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c index 30dea7b9bc17..4242d166c73c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h index fa836ceefc8f..5edbc1ecd261 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __REALTEK_PCI92SE_HW_H__ #define __REALTEK_PCI92SE_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c index 33c307aca911..2d18bc1ee480 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h index 90e265d9ffc6..c9e481a8d943 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __REALTEK_PCI92SE_LED_H__ #define __REALTEK_PCI92SE_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c index 86cb853f7169..37a8a57bca3f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h index 7a3b6b623872..b8b5f097b67b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __RTL92S_PHY_H__ #define __RTL92S_PHY_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h index 5d445c2afcf3..dfaaf61b3b17 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __REALTEK_92S_REG_H__ #define __REALTEK_92S_REG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c index ea5b8ec45ec9..a37855f57e76 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h index e9ba283d05ad..a5959a228a35 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __INC_RTL92S_RF_H #define __INC_RTL92S_RF_H diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c index d55554b7fa9a..d1d84e7d47a4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h index af449d6714e6..a31efba0e6b5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h @@ -1,25 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __REALTEK_PCI92SE_SW_H__ #define __REALTEK_PCI92SE_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c index 162578f05c85..776e28e99d53 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c @@ -1,28 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - * Created on 2010/ 5/18, 1:41 - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "table.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h index aa3c7687d226..4fd09f11f5bc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h @@ -1,20 +1,6 @@ -/****************************************************************************** - * Copyright(c) 2008 - 2012 Realtek Corporation. All rights reserved. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * - * Larry Finger - * - ******************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __INC_HAL8192SE_FW_IMG_H #define __INC_HAL8192SE_FW_IMG_H diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c index e1904c39f147..7f3894b24482 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h index 81a5445c04a3..90aa12fc6a7f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #ifndef __REALTEK_PCI92SE_TRX_H__ #define __REALTEK_PCI92SE_TRX_H__ -- cgit v1.2.3 From 48fa0b4d58dc8846e45343b2cfb77c84042ae0b2 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:17 -0600 Subject: rtlwifi: rtl8723ae: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8723ae/btc.h | 25 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8723ae/def.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/dm.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/dm.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/fw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/fw.h | 25 ++----------------- .../realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c | 26 ++------------------ .../realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h | 25 ++----------------- .../wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c | 27 +++------------------ .../wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h | 25 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8723ae/hw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/hw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/led.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/led.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/phy.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/phy.h | 26 ++------------------ .../wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c | 26 ++------------------ .../wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/reg.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/rf.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/rf.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/sw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/sw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/table.c | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8723ae/table.h | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8723ae/trx.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723ae/trx.h | 26 ++------------------ 27 files changed, 55 insertions(+), 648 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h index 06c448c010fd..20a67dcc59cb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h @@ -1,26 +1,5 @@ -/****************************************************************************** - ** - ** Copyright(c) 2009-2012 Realtek Corporation. - ** - ** This program is free software; you can redistribute it and/or modify it - ** under the terms of version 2 of the GNU General Public License as - ** published by the Free Software Foundation. - ** - ** This program is distributed in the hope that it will be useful, but WITHOUT - ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - ** more details. - ** - ** The full GNU General Public License is included in this distribution in the - ** file called LICENSE. - ** - ** Contact Information: - ** wlanfae - ** Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - ** Hsinchu 300, Taiwan. - ** Larry Finger - ** - ******************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_BTC_H__ #define __RTL8723E_BTC_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h index 847544817549..586fe70a38e9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_DEF_H__ #define __RTL8723E_DEF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c index acfd54c6f8dd..514891ea2c64 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h index a113780af08a..bcad516f0d28 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_DM_H__ #define __RTL8723E_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c index bf9859f74b6f..be451a6f7dbe 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h index 2e668fcfc5c2..5c843736de8d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C__FW__H__ #define __RTL92C__FW__H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c index 5aac45d5a974..3ac31ec26517 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "hal_bt_coexist.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h index 45719fdcb067..0455a3712f3e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_HAL_BT_COEXIST_H__ #define __RTL8723E_HAL_BT_COEXIST_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c index 788de88ab1ee..a6b31dae5691 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c @@ -1,27 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ + #include "hal_btc.h" #include "../pci.h" #include "phy.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h index 756868897d8b..620677128f11 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_HAL_BTC_H__ #define __RTL8723E_HAL_BTC_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c index f783e4a8083d..ddebedb8d122 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h index c76e453f4f43..cf55f45d0779 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_HW_H__ #define __RTL8723E_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c index d567b0df0e9f..5e503dbc463b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h index c22b19f542a6..9f85845d23cd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92CE_LED_H__ #define __RTL92CE_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c index 3f3327878b51..b4f7b079cd97 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h index b85f5c7c5c01..6aa72b5b4359 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL92C_PHY_H__ #define __RTL92C_PHY_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c index 2f7f81af8a55..041e3113a500 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../pwrseqcmd.h" #include "pwrseq.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h index e6c3aac3e9fd..c747c5ea20f9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_PWRSEQ_H__ #define __RTL8723E_PWRSEQ_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h index 30938cd9fce5..8696614c7cdd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_REG_H__ #define __RTL8723E_REG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c index 89958b64b52d..9058527a7f94 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h index 7b44ebc0fac9..b445cfe65bf4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_RF_H__ #define __RTL8723E_RF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 3103151dda2b..0d9c0ccf1dc5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h index 46478780d262..200ce39a0dd7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_SW_H__ #define __RTL8723E_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c index 1bbee0bfac23..d895694be023 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "table.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h index a044f3c456fa..4897dbc73b9f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_TABLE__H_ #define __RTL8723E_TABLE__H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c index d461d0c9631f..e7368920f80a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h index d592b08d4ac8..4a19ea76b290 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2012 Realtek Corporation.*/ #ifndef __RTL8723E_TRX_H__ #define __RTL8723E_TRX_H__ -- cgit v1.2.3 From 93121c03e0ce4a393808ec620bed5b17e6e1981d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:18 -0600 Subject: rtlwifi: rtl8723be: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8723be/def.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/dm.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/dm.h | 23 ++---------------- .../net/wireless/realtek/rtlwifi/rtl8723be/fw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/fw.h | 25 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/hw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/led.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/led.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/phy.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/phy.h | 26 ++------------------ .../wireless/realtek/rtlwifi/rtl8723be/pwrseq.c | 26 ++------------------ .../wireless/realtek/rtlwifi/rtl8723be/pwrseq.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/reg.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/rf.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/rf.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/sw.h | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/table.c | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8723be/table.h | 28 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8723be/trx.c | 26 ++------------------ .../net/wireless/realtek/rtlwifi/rtl8723be/trx.h | 26 ++------------------ 22 files changed, 44 insertions(+), 528 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h index 5e5403d69220..f4886c868df8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_DEF_H__ #define __RTL8723BE_DEF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c index 47e87a21ae27..ef355aa88117 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h index f752a2cad63d..c4f36e951747 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h @@ -1,24 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_DM_H__ #define __RTL8723BE_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c index f2441fbb92f1..4d7fa27f55ca 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h index 948d28646364..97ea77464139 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE__FW__H__ #define __RTL8723BE__FW__H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index b4f3f91b590e..7a9891a41d70 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h index ae856a19e81a..eb797e9bb931 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_HW_H__ #define __RTL8723BE_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c index 4f7890d62c21..525f2c47da5b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h index c57de379ee8d..8ac59374b632 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_LED_H__ #define __RTL8723BE_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c index 11f94b1a436f..aa8a0950fcea 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h index 9021d4745ab7..a59813ea7c72 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_PHY_H__ #define __RTL8723BE_PHY_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c index a1bb1f6116fb..95adac66676e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../pwrseqcmd.h" #include "pwrseq.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h index 3367cfbc9502..57eac4864184 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_PWRSEQ_H__ #define __RTL8723BE_PWRSEQ_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h index 95c4f8e206c7..28fd22b2a792 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_REG_H__ #define __RTL8723BE_REG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c index 48491454b878..af72e489e31c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h index f423e157020f..81537a1a4fdf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_RF_H__ #define __RTL8723BE_RF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c index c9f7b042d9c6..00e6254bf82b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h index a7b25e769950..6ecacf9fbfd7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_SW_H__ #define __RTL8723BE_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c index 160fee8333ae..5864be89d187 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include #include "table.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h index 1deaffe22251..cf0c8d58cea1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_TABLE__H_ #define __RTL8723BE_TABLE__H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c index 9f8dfb5af774..48b1179e9f0e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h index 609f7ad7f787..11e75a4e68bd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __RTL8723BE_TRX_H__ #define __RTL8723BE_TRX_H__ -- cgit v1.2.3 From 2a7274ee12cc390de092bfdb741cc0a2ca9f109d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:19 -0600 Subject: rtlwifi: rtl8723_common: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../realtek/rtlwifi/rtl8723com/dm_common.c | 26 ++-------------------- .../realtek/rtlwifi/rtl8723com/dm_common.h | 26 ++-------------------- .../realtek/rtlwifi/rtl8723com/fw_common.c | 26 ++-------------------- .../realtek/rtlwifi/rtl8723com/fw_common.h | 26 ++-------------------- .../net/wireless/realtek/rtlwifi/rtl8723com/main.c | 26 ++-------------------- .../realtek/rtlwifi/rtl8723com/phy_common.c | 26 ++-------------------- .../realtek/rtlwifi/rtl8723com/phy_common.h | 26 ++-------------------- 7 files changed, 14 insertions(+), 168 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c index 064340641913..46ab90332eb7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "dm_common.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h index 5c1b94ce2f86..6300be65aba0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __DM_COMMON_H__ #define __DM_COMMON_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c index 521039c5d4ce..18ce2856a91b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h index 77c25a976233..b527fcbbdf08 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __FW_COMMON_H__ #define __FW_COMMON_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c index 9014a94fac6a..f5a9ecbf7363 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c index 43d24e1ee5e6..aae14c68bf69 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #include "../wifi.h" #include "phy_common.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h index 83b891a9adb8..edf1c52f0ee2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2014 Realtek Corporation.*/ #ifndef __PHY_COMMON__ #define __PHY_COMMON__ -- cgit v1.2.3 From 03f3dd37f0957a4268ff09415fb96a6dc2f9f151 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 13:59:20 -0600 Subject: rtlwifi: rtl8821ae: Replace old-style license information The traditional license information is replaced by the SPDX form. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8821ae/def.h | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/dm.c | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/dm.h | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/fw.c | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/fw.h | 25 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/hw.h | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/led.c | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/led.h | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/phy.c | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/phy.h | 26 ++----------------- .../wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c | 26 ++----------------- .../wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/reg.h | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/rf.c | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/rf.h | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/sw.c | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/sw.h | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/table.c | 29 +++------------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/table.h | 28 ++------------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/trx.c | 26 ++----------------- .../net/wireless/realtek/rtlwifi/rtl8821ae/trx.h | 26 ++----------------- 22 files changed, 45 insertions(+), 531 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h index 3fe3aaa5fe3c..827bc5f35d2a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_DEF_H__ #define __RTL8821AE_DEF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c index 3be8c88971e2..49d05b631ba1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../wifi.h" #include "../base.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h index 625a6bbb21fc..35493b03c8ad 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_DM_H__ #define __RTL8821AE_DM_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c index d868a034659f..b677bd4a844f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h index 99c902ff0b84..e11e496b7277 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h @@ -1,26 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE__FW__H__ #define __RTL8821AE__FW__H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index ba258318ee9f..e786aa89d4b0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h index e2ab783a2ad9..fb0fb3a501d9 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_HW_H__ #define __RTL8821AE_HW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c index 405c7541b386..dd7553e80ab1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h index 038e64e18ae8..249a37a8d9db 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_LED_H__ #define __RTL8821AE_LED_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index a75451c246fd..7b80a2b4bbe1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h index 1285e1adfe9d..799b7cfed542 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_PHY_H__ #define __RTL8821AE_PHY_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c index 9ddf78a187dd..1e7b3c770ac2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../pwrseqcmd.h" #include "pwrseq.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h index 6dd575435c63..d6f3cbab4abc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_PWRSEQ_H__ #define __RTL8821AE_PWRSEQ_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h index db8bc8a2de61..85e73a0686fa 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_REG_H__ #define __RTL8821AE_REG_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c index 95489f41f8a0..a6e56872e063 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../wifi.h" #include "reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h index efd22bd0b139..6e3c8bfb2048 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_RF_H__ #define __RTL8821AE_RF_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c index 77f6401021c9..eec7c4ecf3ad 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../wifi.h" #include "../core.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h index d001e7ce3052..9d7610f84b20 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_SW_H__ #define __RTL8821AE_SW_H__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c index f87f9d03b9fa..8ed77d769592 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c @@ -1,29 +1,6 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ + #include #include "table.h" u32 RTL8812AE_PHY_REG_ARRAY[] = { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h index 36c2388b60bc..540159c25078 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h @@ -1,29 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_TABLE__H_ #define __RTL8821AE_TABLE__H_ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c index 0f2b7c619918..db5e628b17ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #include "../wifi.h" #include "../pci.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h index 4ff0968dba81..a3feecad645d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h @@ -1,27 +1,5 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2009-2010 Realtek Corporation.*/ #ifndef __RTL8821AE_TRX_H__ #define __RTL8821AE_TRX_H__ -- cgit v1.2.3 From e703c5dd2d69eaa10ac94814a56931422367a1ba Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 16:36:37 -0600 Subject: rtlwifi: Remove CamelCase variables from base code There are a number of CamelCase variables remaining in the source files of modules rtl_pci, rtl_usb, and rtlwifi. The following checkpatch excettions are also fixed: for_kalle1/0001-rtlwifi-Remove-CamelCase-variables-from-base-code.patch ----------------------------------------------------------------------- CHECK: Unnecessary parentheses around 'rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] != rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]' #68: FILE: drivers/net/wireless/realtek/rtlwifi/efuse.c:377: + if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]) || + (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i + 1] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i + 1])) { CHECK: Unnecessary parentheses around 'rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i + 1] != rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i + 1]' #68: FILE: drivers/net/wireless/realtek/rtlwifi/efuse.c:377: + if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]) || + (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i + 1] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i + 1])) { WARNING: line over 80 characters #70: FILE: drivers/net/wireless/realtek/rtlwifi/efuse.c:379: + (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i + 1] != CHECK: No space is necessary after a cast #186: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c:396: + status->rx_is40mhzpacket = (bool) GET_RX_DESC_BW(pdesc); CHECK: No space is necessary after a cast #208: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c:335: + stats->rx_is40mhzpacket = (bool) GET_RX_DESC_BW(pdesc); CHECK: No space is necessary after a cast #243: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c:301: + stats->rx_is40mhzpacket = (bool) GET_RX_DESC_BW(pdesc); CHECK: No space is necessary after a cast #252: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c:368: + stats.rx_is40mhzpacket = (bool) GET_RX_DESC_BW(rxdesc); CHECK: No space is necessary after a cast #265: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c:475: + stats->rx_is40mhzpacket = (bool) GET_RX_DESC_BW(pdesc); WARNING: Unnecessary space before function pointer arguments #455: FILE: drivers/net/wireless/realtek/rtlwifi/wifi.h:1462: + void (*writen_sync) (struct rtl_priv *rtlpriv, u32 addr, void *buf, WARNING: Unnecessary space before function pointer arguments #483: FILE: drivers/net/wireless/realtek/rtlwifi/wifi.h:2257: + void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pdesc, Note that not all checkpatch exceptions are addressed. Those will be handled in later patches. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/debug.h | 2 +- drivers/net/wireless/realtek/rtlwifi/efuse.c | 44 +++++++++++----------- drivers/net/wireless/realtek/rtlwifi/efuse.h | 2 +- drivers/net/wireless/realtek/rtlwifi/regd.c | 8 ++-- .../net/wireless/realtek/rtlwifi/rtl8188ee/trx.c | 4 +- .../net/wireless/realtek/rtlwifi/rtl8192ce/trx.c | 4 +- .../net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | 2 +- .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.c | 4 +- .../net/wireless/realtek/rtlwifi/rtl8192de/trx.c | 2 +- .../net/wireless/realtek/rtlwifi/rtl8192ee/trx.c | 2 +- .../net/wireless/realtek/rtlwifi/rtl8192se/trx.c | 4 +- .../net/wireless/realtek/rtlwifi/rtl8723ae/trx.c | 4 +- .../net/wireless/realtek/rtlwifi/rtl8723be/trx.c | 4 +- drivers/net/wireless/realtek/rtlwifi/usb.c | 6 +-- drivers/net/wireless/realtek/rtlwifi/usb.h | 2 +- drivers/net/wireless/realtek/rtlwifi/wifi.h | 26 ++++++------- 16 files changed, 60 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h index b1d51d135680..69f169d4d4ae 100644 --- a/drivers/net/wireless/realtek/rtlwifi/debug.h +++ b/drivers/net/wireless/realtek/rtlwifi/debug.h @@ -136,7 +136,7 @@ enum dbgp_flag_e { FEEPROM = 11, FPWR = 12, FDM = 13, - FDBGCtrl = 14, + FDBGCTRL = 14, FC2H = 15, FBT = 16, FINIT = 17, diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c index 3b2b603ca871..de0437b3cb95 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.c +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c @@ -365,20 +365,20 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 section_idx, i, Base; + u8 section_idx, i, base; u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used; bool wordchanged, result = true; for (section_idx = 0; section_idx < 16; section_idx++) { - Base = section_idx * 8; + base = section_idx * 8; wordchanged = false; for (i = 0; i < 8; i = i + 2) { - if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] != - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i]) || - (rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i + 1] != - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i + - 1])) { + if (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i] || + rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i + 1] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i + + 1]) { words_need++; wordchanged = true; } @@ -519,7 +519,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw) } EXPORT_SYMBOL(rtl_efuse_shadow_map_update); -void efuse_force_write_vendor_Id(struct ieee80211_hw *hw) +void efuse_force_write_vendor_id(struct ieee80211_hw *hw) { u8 tmpdata[8] = { 0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF }; @@ -1111,7 +1111,7 @@ void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 tempval; - u16 tmpV16; + u16 tmpv16; if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { @@ -1120,31 +1120,31 @@ void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69); } else { - tmpV16 = + tmpv16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL]); - if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { - tmpV16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V]; + if (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { + tmpv16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V]; rtl_write_word(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL], - tmpV16); + tmpv16); } } - tmpV16 = rtl_read_word(rtlpriv, + tmpv16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN]); - if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) { - tmpV16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR]; + if (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) { + tmpv16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR]; rtl_write_word(rtlpriv, - rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16); + rtlpriv->cfg->maps[SYS_FUNC_EN], tmpv16); } - tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]); - if ((!(tmpV16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) || - (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) { - tmpV16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] | + tmpv16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]); + if ((!(tmpv16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) || + (!(tmpv16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) { + tmpv16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] | rtlpriv->cfg->maps[EFUSE_ANA8M]); rtl_write_word(rtlpriv, - rtlpriv->cfg->maps[SYS_CLK], tmpV16); + rtlpriv->cfg->maps[SYS_CLK], tmpv16); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.h b/drivers/net/wireless/realtek/rtlwifi/efuse.h index d3643577ff86..1ec59f439382 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.h +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.h @@ -85,7 +85,7 @@ void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, bool efuse_shadow_update(struct ieee80211_hw *hw); bool efuse_shadow_update_chk(struct ieee80211_hw *hw); void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw); -void efuse_force_write_vendor_Id(struct ieee80211_hw *hw); +void efuse_force_write_vendor_id(struct ieee80211_hw *hw); void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx); void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate); int rtl_get_hwinfo(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv, diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index a1f58034642c..c7048830decd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -4,7 +4,7 @@ #include "wifi.h" #include "regd.h" -static struct country_code_to_enum_rd allCountries[] = { +static struct country_code_to_enum_rd all_countries[] = { {COUNTRY_CODE_FCC, "US"}, {COUNTRY_CODE_IC, "US"}, {COUNTRY_CODE_ETSI, "EC"}, @@ -369,9 +369,9 @@ static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode) { int i; - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (allCountries[i].countrycode == countrycode) - return &allCountries[i]; + for (i = 0; i < ARRAY_SIZE(all_countries); i++) { + if (all_countries[i].countrycode == countrycode) + return &all_countries[i]; } return NULL; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 79a335f43133..106011a24827 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -393,7 +393,7 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, (GET_RX_DESC_FAGGR(pdesc) == 1)); if (status->packet_report_type == NORMAL_RX) status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + status->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc); status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate); @@ -420,7 +420,7 @@ bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, if (status->crc) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (status->rx_is40Mhzpacket) + if (status->rx_is40mhzpacket) rx_status->bw = RATE_INFO_BW_40; if (status->is_ht) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index fbf3133a0fd5..b08fb1bf6709 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -332,7 +332,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) && (GET_RX_DESC_FAGGR(pdesc) == 1)); stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); - stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc); stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc->rxmcs); @@ -346,7 +346,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, if (stats->crc) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (stats->rx_is40Mhzpacket) + if (stats->rx_is40mhzpacket) rx_status->bw = RATE_INFO_BW_40; if (stats->is_ht) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index f1932d7ca969..c96863082669 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -1331,7 +1331,7 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw) _rtl92cu_set_media_status(hw, opmode); rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - if (rtlusb->disableHWSM) + if (rtlusb->disablehwsm) _CardDisableHWSM(hw); else _CardDisableWithoutHWSM(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index 7c32f9d2d69f..646819759de6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -298,7 +298,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) && (GET_RX_DESC_FAGGR(pdesc) == 1)); stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); - stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc); stats->is_ht = (bool)GET_RX_DESC_RX_HT(pdesc); rx_status->freq = hw->conf.chandef.chan->center_freq; rx_status->band = hw->conf.chandef.chan->band; @@ -365,7 +365,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1) && (GET_RX_DESC_FAGGR(rxdesc) == 1)); stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc); - stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc); + stats.rx_is40mhzpacket = (bool)GET_RX_DESC_BW(rxdesc); stats.is_ht = (bool)GET_RX_DESC_RX_HT(rxdesc); /* TODO: is center_freq changed when doing scan? */ /* TODO: Shall we add protection or just skip those two step? */ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c index cb19c6871fe4..d162884a9e00 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c @@ -472,7 +472,7 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) && (GET_RX_DESC_FAGGR(pdesc) == 1)); stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); - stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc); stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); rx_status->freq = hw->conf.chandef.chan->center_freq; rx_status->band = hw->conf.chandef.chan->band; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c index 91d44430fd8a..09cf8180e4ff 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c @@ -371,7 +371,7 @@ bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, if (status->crc) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (status->rx_is40Mhzpacket) + if (status->rx_is40mhzpacket) rx_status->bw = RATE_INFO_BW_40; if (status->is_ht) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c index 7f3894b24482..efb432c6d785 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c @@ -253,7 +253,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, stats->isfirst_ampdu = (bool) ((GET_RX_STATUS_DESC_PAGGR(pdesc) == 1) && (GET_RX_STATUS_DESC_FAGGR(pdesc) == 1)); stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc); - stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc); + stats->rx_is40mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc); stats->is_ht = (bool)GET_RX_STATUS_DESC_RX_HT(pdesc); stats->is_cck = SE_RX_HAL_IS_CCK_RATE(pdesc); @@ -266,7 +266,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, if (stats->crc) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (stats->rx_is40Mhzpacket) + if (stats->rx_is40mhzpacket) rx_status->bw = RATE_INFO_BW_40; if (stats->is_ht) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c index e7368920f80a..90dc91b0d35b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c @@ -280,7 +280,7 @@ bool rtl8723e_rx_query_desc(struct ieee80211_hw *hw, status->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) && (GET_RX_DESC_FAGGR(pdesc) == 1)); status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->rx_is40Mhzpacket = (bool)GET_RX_DESC_BW(pdesc); + status->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc); status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); status->is_cck = RX_HAL_IS_CCK_RATE(status->rate); @@ -294,7 +294,7 @@ bool rtl8723e_rx_query_desc(struct ieee80211_hw *hw, if (status->crc) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (status->rx_is40Mhzpacket) + if (status->rx_is40mhzpacket) rx_status->bw = RATE_INFO_BW_40; if (status->is_ht) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c index 48b1179e9f0e..9ada9a06c6ea 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c @@ -316,7 +316,7 @@ bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw, status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); status->isfirst_ampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->rx_is40Mhzpacket = (bool)GET_RX_DESC_BW(pdesc); + status->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc); status->bandwidth = (u8)GET_RX_DESC_BW(pdesc); status->macid = GET_RX_DESC_MACID(pdesc); status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); @@ -350,7 +350,7 @@ bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw, if (status->crc) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (status->rx_is40Mhzpacket) + if (status->rx_is40mhzpacket) rx_status->bw = RATE_INFO_BW_40; if (status->is_ht) diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 749752421931..525f72bad433 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -194,7 +194,7 @@ static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val) _usb_write_async(to_usb_device(dev), addr, val, 4); } -static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, +static void _usb_writen_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len) { struct device *dev = rtlpriv->io.dev; @@ -229,7 +229,7 @@ static void _rtl_usb_io_handler_init(struct device *dev, rtlpriv->io.read8_sync = _usb_read8_sync; rtlpriv->io.read16_sync = _usb_read16_sync; rtlpriv->io.read32_sync = _usb_read32_sync; - rtlpriv->io.writeN_sync = _usb_writeN_sync; + rtlpriv->io.writen_sync = _usb_writen_sync; } static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) @@ -393,7 +393,7 @@ static void rtl_usb_init_sw(struct ieee80211_hw *hw) rtlusb->irq_mask[0] = 0xFFFFFFFF; /* HIMR_EX - turn all on */ rtlusb->irq_mask[1] = 0xFFFFFFFF; - rtlusb->disableHWSM = true; + rtlusb->disablehwsm = true; } static void _rtl_rx_completed(struct urb *urb); diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h index 30a21508cfa2..09bbcdbe0dbf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.h +++ b/drivers/net/wireless/realtek/rtlwifi/usb.h @@ -84,7 +84,7 @@ struct rtl_usb { /* Bcn control register setting */ u32 reg_bcn_ctrl_val; /* for 88/92cu card disable */ - u8 disableHWSM; + u8 disablehwsm; /*QOS & EDCA */ enum acm_method acm_method; /* irq . HIMR,HIMR_EX */ diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 2065e4369179..1ad71fb0ebf2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -241,7 +241,7 @@ struct rtlwifi_firmware_header { u8 date; u8 hour; u8 minute; - __le16 ramcodeSize; + __le16 ramcodesize; __le16 rsvd2; __le32 svnindex; __le32 rsvd3; @@ -443,11 +443,11 @@ enum hw_variables { HW_VAR_MCS_RATE_AVAILABLE = 0x1f, HW_VAR_AC_PARAM = 0x20, HW_VAR_ACM_CTRL = 0x21, - HW_VAR_DIS_Req_Qsize = 0x22, + HW_VAR_DIS_REQ_QSIZE = 0x22, HW_VAR_CCX_CHNL_LOAD = 0x23, HW_VAR_CCX_NOISE_HISTOGRAM = 0x24, HW_VAR_CCX_CLM_NHM = 0x25, - HW_VAR_TxOPLimit = 0x26, + HW_VAR_TXOPLIMIT = 0x26, HW_VAR_TURBO_MODE = 0x27, HW_VAR_RF_STATE = 0x28, HW_VAR_RF_OFF_BY_HW = 0x29, @@ -500,7 +500,7 @@ enum hw_variables { HW_VAR_BCN_VALID = 0x55, HW_VAR_FWLPS_RF_ON = 0x56, HW_VAR_DUAL_TSF_RST = 0x57, - HW_VAR_SWITCH_EPHY_WoWLAN = 0x58, + HW_VAR_SWITCH_EPHY_WOWLAN = 0x58, HW_VAR_INT_MIGRATION = 0x59, HW_VAR_INT_AC = 0x5a, HW_VAR_RF_TIMING = 0x5b, @@ -792,8 +792,8 @@ enum _fw_ps_mode { FW_PS_UAPSD_MODE = 6, FW_PS_IBSS_MODE = 7, FW_PS_WWLAN_MODE = 8, - FW_PS_PM_Radio_Off = 9, - FW_PS_PM_Card_Disable = 10, + FW_PS_PM_RADIO_OFF = 9, + FW_PS_PM_CARD_DISABLE = 10, }; enum rt_psmode { @@ -827,8 +827,8 @@ enum rtl_led_pin { /*QoS related.*/ /*acm implementation method.*/ enum acm_method { - eAcmWay0_SwAndHw = 0, - eAcmWay1_HW = 1, + EACMWAY0_SWANDHW = 0, + EACMWAY1_HW = 1, EACMWAY2_SW = 2, }; @@ -1459,7 +1459,7 @@ struct rtl_io { void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val); void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val); - void (*writeN_sync) (struct rtl_priv *rtlpriv, u32 addr, void *buf, + void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf, u16 len); u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); @@ -1876,7 +1876,7 @@ struct rtl_dm { struct rtl_efuse { const struct rtl_efuse_ops *efuse_ops; - bool autoLoad_ok; + bool autoload_ok; bool bootfromefuse; u16 max_physical_size; @@ -2103,7 +2103,7 @@ struct rtl_stats { u8 rx_bufshift; bool isampdu; bool isfirst_ampdu; - bool rx_is40Mhzpacket; + bool rx_is40mhzpacket; u8 rx_packet_bw; u32 rx_pwdb_all; u8 rx_mimo_signalstrength[4]; /*in 0~100 index */ @@ -2254,8 +2254,8 @@ struct rtl_hal_ops { struct ieee80211_sta *sta, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); - void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, - u32 buffer_len, bool bIsPsPoll); + void (*fill_fake_txdesc)(struct ieee80211_hw *hw, u8 *pdesc, + u32 buffer_len, bool bsspspoll); void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, bool lastseg, struct sk_buff *skb); -- cgit v1.2.3 From 2171def56daffc73a3073741dca9113b724b444d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 16:36:38 -0600 Subject: rtlwifi: btcoexist: Remove CamelCase variable File halbt_precomp.h contains the only CamelCase value, namely GetDefaultAdapter, but that macro is never used, thus it is deleted. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h index 602cac41c910..30a25480752d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h @@ -28,8 +28,6 @@ #include "halbtc8821a2ant.h" #include "halbtc8821a1ant.h" -#define GetDefaultAdapter(padapter) padapter - #define BIT0 0x00000001 #define BIT1 0x00000002 #define BIT2 0x00000004 -- cgit v1.2.3 From d420110635adc295ca9e9a61b79603964ef1f373 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 16:36:39 -0600 Subject: rtlwifi: rtl8188ee: Remove CamelCase variable This driver contains one instance of a CamelCase variable, namely IS_81xxC_VENDOR_UMC_A_CUT. This macro is never used, thus it is deleted. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h index 9fb3a22f6c9e..fa2e1b063f68 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h @@ -101,9 +101,6 @@ #define IS_92C_SERIAL(version) \ ((IS_81XXC(version) && IS_2T2R(version)) ? true : false) -#define IS_81xxC_VENDOR_UMC_A_CUT(version) \ - (IS_81XXC(version) ? ((IS_CHIP_VENDOR_UMC(version)) ? \ - ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) : false) #define IS_81XXC_VENDOR_UMC_B_CUT(version) \ (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \ ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true \ -- cgit v1.2.3 From ff9704538e6dd8d652e98317ab3dc06c7a017e58 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 16:36:40 -0600 Subject: rtlwifi: rtl8192{c,u}: Remove CamelCase variables This patch affects modules rtl8192ce, rtl8192cu, and rtl8192com. The following checkpatch exceptions are also fixed: CHECK: No space is necessary after a cast #237: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c:90: + (u8 *) (&rfstate)); CHECK: No space is necessary after a cast #744: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c:329: + pwr_val[i] = (u8) ((writeval & (0x7f << CHECK: No space is necessary after a cast #784: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c:365: + (u8) writeval); CHECK: spaces preferred around that '/' (ctx:VxV) #963: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c:513: + txqpageunit = txqpagenum/outepnum; ^ CHECK: Unnecessary parentheses around 'outepnum > 1' #975: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c:521: + if ((outepnum > 1) && (txqremaininpage)) CHECK: Alignment should match open parenthesis #1059: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c:617: +static void _rtl92cu_init_chipn_two_out_ep_priority(struct ieee80211_hw *hw, bool wmm_enable, ERROR: "foo * bar" should be "foo *bar" #1940: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c:591: +void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc, Note that not all checkpatch exceptions are addressed. Those will be handled in later patches. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../wireless/realtek/rtlwifi/rtl8192c/dm_common.h | 4 +- .../wireless/realtek/rtlwifi/rtl8192c/fw_common.c | 14 +- .../wireless/realtek/rtlwifi/rtl8192c/phy_common.c | 24 +- .../wireless/realtek/rtlwifi/rtl8192c/phy_common.h | 6 +- .../net/wireless/realtek/rtlwifi/rtl8192ce/dm.h | 4 +- .../net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 42 ++-- .../net/wireless/realtek/rtlwifi/rtl8192ce/phy.c | 10 +- .../net/wireless/realtek/rtlwifi/rtl8192ce/phy.h | 6 +- .../net/wireless/realtek/rtlwifi/rtl8192ce/reg.h | 59 +++-- .../net/wireless/realtek/rtlwifi/rtl8192ce/rf.c | 112 ++++----- .../net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | 276 ++++++++++----------- .../net/wireless/realtek/rtlwifi/rtl8192cu/hw.h | 4 +- .../net/wireless/realtek/rtlwifi/rtl8192cu/led.c | 6 +- .../net/wireless/realtek/rtlwifi/rtl8192cu/phy.c | 16 +- .../net/wireless/realtek/rtlwifi/rtl8192cu/rf.c | 112 ++++----- .../net/wireless/realtek/rtlwifi/rtl8192cu/table.c | 8 +- .../net/wireless/realtek/rtlwifi/rtl8192cu/table.h | 16 +- .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.c | 58 ++--- .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.h | 4 +- 19 files changed, 390 insertions(+), 391 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h index 5315c7f21fc4..c4ce9fc96163 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h @@ -27,7 +27,7 @@ #define DM_DIG_FA_TH1 0x100 #define DM_DIG_FA_TH2 0x200 -#define RXPATHSELECTION_SS_TH_lOW 30 +#define RXPATHSELECTION_SS_TH_LOW 30 #define RXPATHSELECTION_DIFF_TH 18 #define DM_RATR_STA_INIT 0 @@ -38,7 +38,7 @@ #define CTS2SELF_THVAL 30 #define REGC38_TH 20 -#define WAIOTTHVal 25 +#define WAIOTTHVAL 25 #define TXHIGHPWRLEVEL_NORMAL 0 #define TXHIGHPWRLEVEL_LEVEL1 1 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c index cd9610d0f198..6af72799e09c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c @@ -57,27 +57,27 @@ static void _rtl92c_write_fw(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); is_version_b = IS_NORMAL_CHIP(version); if (is_version_b) { - u32 pageNums, remainsize; + u32 pagenums, remainsize; u32 page, offset; if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) rtl_fill_dummy(bufferptr, &size); - pageNums = size / FW_8192C_PAGE_SIZE; + pagenums = size / FW_8192C_PAGE_SIZE; remainsize = size % FW_8192C_PAGE_SIZE; - if (pageNums > 4) + if (pagenums > 4) pr_err("Page numbers should not greater then 4\n"); - for (page = 0; page < pageNums; page++) { + for (page = 0; page < pagenums; page++) { offset = page * FW_8192C_PAGE_SIZE; rtl_fw_page_write(hw, page, (bufferptr + offset), FW_8192C_PAGE_SIZE); } if (remainsize) { - offset = pageNums * FW_8192C_PAGE_SIZE; - page = pageNums; + offset = pagenums * FW_8192C_PAGE_SIZE; + page = pagenums; rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize); } @@ -96,7 +96,7 @@ static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) do { value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && - (!(value32 & FWDL_ChkSum_rpt))); + (!(value32 & FWDL_CHKSUM_RPT))); if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { pr_err("chksum report fail! REG_MCUFWDL:0x%08x .\n", diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c index 083791b705dc..c6a3ed441c3f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c @@ -217,7 +217,7 @@ bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile); -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, +void _rtl92c_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data) { @@ -371,7 +371,7 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, rtlphy->pwrgroup_cnt++; } } -EXPORT_SYMBOL(_rtl92c_store_pwrIndex_diffrate_offset); +EXPORT_SYMBOL(_rtl92c_store_pwrindex_diffrate_offset); void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) { @@ -430,10 +430,10 @@ void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = RFPGA0_XB_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; @@ -1098,19 +1098,19 @@ static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw, static void _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw, u32 *addareg, bool is_patha_on, bool is2t) { - u32 pathOn; + u32 pathon; u32 i; - pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; + pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; if (false == is2t) { - pathOn = 0x0bdb25a0; + pathon = 0x0bdb25a0; rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); } else { - rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn); + rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); } for (i = 1; i < IQK_ADDA_REG_NUM; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn); + rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); } static void _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw, @@ -1339,7 +1339,7 @@ static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, if (is_hal_stop(rtlhal)) { rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01); - rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); } if (is2t) { if (bmain) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h index b088a38456c7..75afa6253ad0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h @@ -22,9 +22,9 @@ #define LOOP_LIMIT 5 #define MAX_STALL_TIME 50 -#define AntennaDiversityValue 0x80 +#define ANTENNADIVERSITYVALUE 0x80 #define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 +#define RESET_CNT_LIMIT 3 #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 @@ -220,7 +220,7 @@ void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data); bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, +void _rtl92c_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h index f6feaf51b860..eab42c1bd470 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h @@ -22,7 +22,7 @@ #define DM_DIG_FA_TH1 0x100 #define DM_DIG_FA_TH2 0x200 -#define RXPATHSELECTION_SS_TH_lOW 30 +#define RXPATHSELECTION_SS_TH_LOW 30 #define RXPATHSELECTION_DIFF_TH 18 #define DM_RATR_STA_INIT 0 @@ -33,7 +33,7 @@ #define CTS2SELF_THVAL 30 #define REGC38_TH 20 -#define WAIOTTHVal 25 +#define WAIOTTHVAL 25 #define TXHIGHPWRLEVEL_NORMAL 0 #define TXHIGHPWRLEVEL_LEVEL1 1 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index 6d6b6f7597a6..5cf5a85d1376 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c @@ -82,13 +82,13 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; break; case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfState; + enum rf_pwrstate rfstate; u32 val_rcr; rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, - (u8 *) (&rfState)); - if (rfState == ERFOFF) { + (u8 *)(&rfstate)); + if (rfstate == ERFOFF) { *((bool *) (val)) = true; } else { val_rcr = rtl_read_dword(rtlpriv, REG_RCR); @@ -314,13 +314,13 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) if (acm) { switch (e_aci) { case AC0_BE: - acm_ctrl |= AcmHw_BeqEn; + acm_ctrl |= ACMHW_BEQEN; break; case AC2_VI: - acm_ctrl |= AcmHw_ViqEn; + acm_ctrl |= ACMHW_VIQEN; break; case AC3_VO: - acm_ctrl |= AcmHw_VoqEn; + acm_ctrl |= ACMHW_VOQEN; break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, @@ -331,13 +331,13 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } else { switch (e_aci) { case AC0_BE: - acm_ctrl &= (~AcmHw_BeqEn); + acm_ctrl &= (~ACMHW_BEQEN); break; case AC2_VI: - acm_ctrl &= (~AcmHw_ViqEn); + acm_ctrl &= (~ACMHW_VIQEN); break; case AC3_VO: - acm_ctrl &= (~AcmHw_VoqEn); + acm_ctrl &= (~ACMHW_VOQEN); break; default: pr_err("switch case %#x not processed\n", @@ -562,23 +562,23 @@ static bool _rtl92ce_llt_table_init(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); unsigned short i; u8 txpktbuf_bndy; - u8 maxPage; + u8 maxpage; bool status; #if LLT_CONFIG == 1 - maxPage = 255; + maxpage = 255; txpktbuf_bndy = 252; #elif LLT_CONFIG == 2 - maxPage = 127; + maxpage = 127; txpktbuf_bndy = 124; #elif LLT_CONFIG == 3 - maxPage = 255; + maxpage = 255; txpktbuf_bndy = 174; #elif LLT_CONFIG == 4 - maxPage = 255; + maxpage = 255; txpktbuf_bndy = 246; #elif LLT_CONFIG == 5 - maxPage = 255; + maxpage = 255; txpktbuf_bndy = 246; #endif @@ -617,13 +617,13 @@ static bool _rtl92ce_llt_table_init(struct ieee80211_hw *hw) if (true != status) return status; - for (i = txpktbuf_bndy; i < maxPage; i++) { + for (i = txpktbuf_bndy; i < maxpage; i++) { status = _rtl92ce_llt_write(hw, i, (i + 1)); if (true != status) return status; } - status = _rtl92ce_llt_write(hw, maxPage, txpktbuf_bndy); + status = _rtl92ce_llt_write(hw, maxpage, txpktbuf_bndy); if (true != status) return status; @@ -876,7 +876,7 @@ void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw) u8 sec_reg_value; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + "PairwiseENcAlgorithm = %d GroupEncAlgorithm = %d\n", rtlpriv->sec.pairwise_enc_algorithm, rtlpriv->sec.group_enc_algorithm); @@ -886,11 +886,11 @@ void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw) return; } - sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable; + sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TxUseDK; - sec_reg_value |= SCR_RxUseDK; + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; } sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c index b9dbef748c7f..8d18210dd5c8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c @@ -82,7 +82,7 @@ bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | - FEN_BB_GLB_RSTn | FEN_BBRSTB); + FEN_BB_GLB_RSTN | FEN_BBRSTB); rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); @@ -214,7 +214,7 @@ bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, for (i = 0; i < phy_regarray_pg_len; i = i + 3) { rtl_addr_delay(phy_regarray_table_pg[i]); - _rtl92c_store_pwrIndex_diffrate_offset(hw, + _rtl92c_store_pwrindex_diffrate_offset(hw, phy_regarray_table_pg[i], phy_regarray_table_pg[i + 1], phy_regarray_table_pg[i + 2]); @@ -442,13 +442,13 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, if ((ppsc->rfpwr_state == ERFOFF) && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { bool rtstatus; - u32 InitializeCount = 0; + u32 initializecount = 0; do { - InitializeCount++; + initializecount++; RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "IPS Set eRf nic enable\n"); rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (InitializeCount < 10)); + } while (!rtstatus && (initializecount < 10)); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); } else { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h index dbb1aed495ef..7582a162bd11 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h @@ -22,9 +22,9 @@ #define LOOP_LIMIT 5 #define MAX_STALL_TIME 50 -#define AntennaDiversityValue 0x80 +#define ANTENNADIVERSITYVALUE 0x80 #define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 +#define RESET_CNT_LIMIT 3 #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 @@ -100,7 +100,7 @@ void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, enum radio_path rfpath, u32 offset, u32 data); -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, +void _rtl92c_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h index 36fe27aef751..431277ef1c98 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h @@ -680,7 +680,7 @@ #define PWC_EV12V BIT(15) #define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTn BIT(1) +#define FEN_BB_GLB_RSTN BIT(1) #define FEN_USBA BIT(2) #define FEN_UPLL BIT(3) #define FEN_USBD BIT(4) @@ -700,7 +700,7 @@ #define PFM_ALDN BIT(1) #define PFM_LDKP BIT(2) #define PFM_WOWL BIT(3) -#define EnPDN BIT(4) +#define ENPDN BIT(4) #define PDN_PL BIT(5) #define APFM_ONMAC BIT(8) #define APFM_OFF BIT(9) @@ -815,19 +815,19 @@ #define LDOE25_EN BIT(31) #define RSM_EN BIT(0) -#define Timer_EN BIT(4) +#define TIMER_EN BIT(4) #define TRSW0EN BIT(2) #define TRSW1EN BIT(3) #define EROM_EN BIT(4) -#define EnBT BIT(5) -#define EnUart BIT(8) -#define Uart_910 BIT(9) -#define EnPMAC BIT(10) +#define ENBT BIT(5) +#define ENUART BIT(8) +#define UART_910 BIT(9) +#define ENPMAC BIT(10) #define SIC_SWRST BIT(11) -#define EnSIC BIT(12) +#define ENSIC BIT(12) #define SIC_23 BIT(13) -#define EnHDP BIT(14) +#define ENHDP BIT(14) #define SIC_LBK BIT(15) #define LED0PL BIT(4) @@ -836,7 +836,7 @@ #define MCUFWDL_EN BIT(0) #define MCUFWDL_RDY BIT(1) -#define FWDL_ChkSum_rpt BIT(2) +#define FWDL_CHKSUM_RPT BIT(2) #define MACINI_RDY BIT(3) #define BBINI_RDY BIT(4) #define RFINI_RDY BIT(5) @@ -1054,13 +1054,13 @@ #define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) #define DIS_TSF_UDT0_TEST_CHIP BIT(5) -#define AcmHw_HwEn BIT(0) -#define AcmHw_BeqEn BIT(1) -#define AcmHw_ViqEn BIT(2) -#define AcmHw_VoqEn BIT(3) -#define AcmHw_BeqStatus BIT(4) -#define AcmHw_ViqStatus BIT(5) -#define AcmHw_VoqStatus BIT(6) +#define ACMHW_HWEN BIT(0) +#define ACMHW_BEQEN BIT(1) +#define ACMHW_VIQEN BIT(2) +#define ACMHW_VOQEN BIT(3) +#define ACMHW_BEQSTATUS BIT(4) +#define ACMHW_VIQSTATUS BIT(5) +#define ACMHW_VOQSTATUS BIT(6) #define APSDOFF BIT(6) #define APSDOFF_STATUS BIT(7) @@ -1099,7 +1099,7 @@ #define BM_DATA_EN BIT(17) #define MFBEN BIT(22) #define LSIGEN BIT(23) -#define EnMBID BIT(24) +#define ENMBID BIT(24) #define APP_BASSN BIT(27) #define APP_PHYSTS BIT(28) #define APP_ICV BIT(29) @@ -1128,12 +1128,12 @@ #define RXERR_RPT_RST BIT(27) #define _RXERR_RPT_SEL(type) ((type) << 28) -#define SCR_TxUseDK BIT(0) -#define SCR_RxUseDK BIT(1) -#define SCR_TxEncEnable BIT(2) -#define SCR_RxDecEnable BIT(3) -#define SCR_SKByA2 BIT(4) -#define SCR_NoSKMC BIT(5) +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXDECENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) #define SCR_TXBCUSEDK BIT(6) #define SCR_RXBCUSEDK BIT(7) @@ -1186,7 +1186,7 @@ #define RPMAC_CCKPLCPHEADER 0x144 #define RPMAC_CCKCRC16 0x148 #define RPMAC_OFDMRXCRC32OK 0x170 -#define RPMAC_OFDMRXCRC32Er 0x174 +#define RPMAC_OFDMRXCRC32ER 0x174 #define RPMAC_OFDMRXPARITYER 0x178 #define RPMAC_OFDMRXCRC8ER 0x17c #define RPMAC_CCKCRXRC16ER 0x180 @@ -1224,8 +1224,8 @@ #define RFPGA0_XAB_RFINTERFACESW 0x870 #define RFPGA0_XCD_RFINTERFACESW 0x874 -#define rFPGA0_XAB_RFPARAMETER 0x878 -#define rFPGA0_XCD_RFPARAMETER 0x87c +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c #define RFPGA0_ANALOGPARAMETER1 0x880 #define RFPGA0_ANALOGPARAMETER2 0x884 @@ -1499,8 +1499,8 @@ #define BCCKTXCRC16 0xffff #define BCCKTXSTATUS 0x1 #define BOFDMTXSTATUS 0x2 -#define IS_BB_REG_OFFSET_92S(_Offset) \ - ((_Offset >= 0x800) && (_Offset <= 0xfff)) +#define IS_BB_REG_OFFSET_92S(_offset) \ + (((_offset) >= 0x800) && ((_offset) <= 0xfff)) #define BRFMOD 0x1 #define BJAPANMODE 0x2 @@ -1693,7 +1693,6 @@ #define BCCK_RF_EXTEND 0x20000000 #define BCCK_RXAGC_SATLEVEL 0x1f000000 #define BCCK_RXAGC_SATCOUNT 0xe0 -#define bCCKRxRFSettle 0x1f #define BCCK_FIXED_RXAGC 0x8000 #define BCCK_ANTENNA_POLARITY 0x2000 #define BCCK_TXFILTER_TYPE 0x0c00 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c index 895b3c42233a..713859488744 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c @@ -128,18 +128,18 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 powerBase0, powerBase1; + u32 powerbase0, powerbase1; u8 legacy_pwrdiff, ht20_pwrdiff; u8 i, powerlevel[2]; for (i = 0; i < 2; i++) { powerlevel[i] = ppowerlevel[i]; legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; - powerBase0 = powerlevel[i] + legacy_pwrdiff; + powerbase0 = powerlevel[i] + legacy_pwrdiff; - powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | - (powerBase0 << 8) | powerBase0; - *(ofdmbase + i) = powerBase0; + powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | + (powerbase0 << 8) | powerbase0; + *(ofdmbase + i) = powerbase0; RTPRINT(rtlpriv, FPHY, PHY_TXPWR, " [OFDM power base index rf(%c) = 0x%x]\n", i == 0 ? 'A' : 'B', *(ofdmbase + i)); @@ -150,11 +150,11 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; powerlevel[i] += ht20_pwrdiff; } - powerBase1 = powerlevel[i]; - powerBase1 = (powerBase1 << 24) | - (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; + powerbase1 = powerlevel[i]; + powerbase1 = (powerbase1 << 24) | + (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; - *(mcsbase + i) = powerBase1; + *(mcsbase + i) = powerbase1; RTPRINT(rtlpriv, FPHY, PHY_TXPWR, " [MCS power base index rf(%c) = 0x%x]\n", @@ -164,37 +164,37 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, u8 channel, u8 index, - u32 *powerBase0, - u32 *powerBase1, + u32 *powerbase0, + u32 *powerbase1, u32 *p_outwriteval) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 i, chnlgroup = 0, pwr_diff_limit[4]; - u32 writeVal, customer_limit, rf; + u32 writeval, customer_limit, rf; for (rf = 0; rf < 2; rf++) { switch (rtlefuse->eeprom_regulatory) { case 0: chnlgroup = 0; - writeVal = rtlphy->mcs_offset[chnlgroup][index + + writeval = rtlphy->mcs_offset[chnlgroup][index + (rf ? 8 : 0)] - + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "RTK better performance, writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; case 1: if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - writeVal = ((index < 2) ? powerBase0[rf] : - powerBase1[rf]); + writeval = ((index < 2) ? powerbase0[rf] : + powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 40MHz, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "Realtek regulatory, 40MHz, writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); } else { if (rtlphy->pwrgroup_cnt == 1) chnlgroup = 0; @@ -209,23 +209,23 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, chnlgroup++; } - writeVal = rtlphy->mcs_offset[chnlgroup] + writeval = rtlphy->mcs_offset[chnlgroup] [index + (rf ? 8 : 0)] + ((index < 2) ? - powerBase0[rf] : - powerBase1[rf]); + powerbase0[rf] : + powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); } break; case 2: - writeVal = - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + writeval = + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "Better regulatory, writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; case 3: chnlgroup = 0; @@ -275,36 +275,36 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, "Customer's limit rf(%c) = 0x%x\n", rf == 0 ? 'A' : 'B', customer_limit); - writeVal = customer_limit + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + writeval = customer_limit + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeVal rf(%c)= 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "Customer, writeval rf(%c)= 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; default: chnlgroup = 0; - writeVal = rtlphy->mcs_offset[chnlgroup] + writeval = rtlphy->mcs_offset[chnlgroup] [index + (rf ? 8 : 0)] - + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeVal rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "RTK better performance, writeval rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; } if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) - writeVal = writeVal - 0x06060606; + writeval = writeval - 0x06060606; else if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT2) - writeVal = writeVal - 0x0c0c0c0c; - *(p_outwriteval + rf) = writeVal; + writeval = writeval - 0x0c0c0c0c; + *(p_outwriteval + rf) = writeval; } } static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *pValue) + u8 index, u32 *value) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -320,29 +320,29 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 }; u8 i, rf, pwr_val[4]; - u32 writeVal; + u32 writeval; u16 regoffset; for (rf = 0; rf < 2; rf++) { - writeVal = pValue[rf]; + writeval = value[rf]; for (i = 0; i < 4; i++) { - pwr_val[i] = (u8) ((writeVal & (0x7f << + pwr_val[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8)); if (pwr_val[i] > RF6052_MAX_TX_PWR) pwr_val[i] = RF6052_MAX_TX_PWR; } - writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | (pwr_val[1] << 8) | pwr_val[0]; if (rf == 0) regoffset = regoffset_a[index]; else regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal); + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeVal); + "Set 0x%x = %08x\n", regoffset, writeval); if (((get_rf_type(rtlphy) == RF_2T2R) && (regoffset == RTXAGC_A_MCS15_MCS12 || @@ -351,7 +351,7 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, (regoffset == RTXAGC_A_MCS07_MCS04 || regoffset == RTXAGC_B_MCS07_MCS04))) { - writeVal = pwr_val[3]; + writeval = pwr_val[3]; if (regoffset == RTXAGC_A_MCS15_MCS12 || regoffset == RTXAGC_A_MCS07_MCS04) regoffset = 0xc90; @@ -360,9 +360,9 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, regoffset = 0xc98; for (i = 0; i < 3; i++) { - writeVal = (writeVal > 6) ? (writeVal - 6) : 0; + writeval = (writeval > 6) ? (writeval - 6) : 0; rtl_write_byte(rtlpriv, (u32) (regoffset + i), - (u8) writeVal); + (u8)writeval); } } } @@ -371,20 +371,20 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, u8 *ppowerlevel, u8 channel) { - u32 writeVal[2], powerBase0[2], powerBase1[2]; + u32 writeval[2], powerbase0[2], powerbase1[2]; u8 index; rtl92c_phy_get_power_base(hw, ppowerlevel, - channel, &powerBase0[0], &powerBase1[0]); + channel, &powerbase0[0], &powerbase1[0]); for (index = 0; index < 6; index++) { _rtl92c_get_txpower_writeval_by_regulatory(hw, channel, index, - &powerBase0[0], - &powerBase1[0], - &writeVal[0]); + &powerbase0[0], + &powerbase1[0], + &writeval[0]); - _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]); + _rtl92c_write_ofdm_power_reg(hw, index, &writeval[0]); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index c96863082669..52ee713d50f5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -31,9 +31,9 @@ static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) rtlphy->hwparam_tables[MAC_REG].pdata = RTL8192CUMAC_2T_ARRAY; if (IS_HIGHT_PA(rtlefuse->board_type)) { rtlphy->hwparam_tables[PHY_REG_PG].length = - RTL8192CUPHY_REG_Array_PG_HPLength; + RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH; rtlphy->hwparam_tables[PHY_REG_PG].pdata = - RTL8192CUPHY_REG_Array_PG_HP; + RTL8192CUPHY_REG_ARRAY_PG_HP; } else { rtlphy->hwparam_tables[PHY_REG_PG].length = RTL8192CUPHY_REG_ARRAY_PGLENGTH; @@ -60,21 +60,21 @@ static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) /* 1T */ if (IS_HIGHT_PA(rtlefuse->board_type)) { rtlphy->hwparam_tables[PHY_REG_1T].length = - RTL8192CUPHY_REG_1T_HPArrayLength; + RTL8192CUPHY_REG_1T_HPARRAYLENGTH; rtlphy->hwparam_tables[PHY_REG_1T].pdata = - RTL8192CUPHY_REG_1T_HPArray; + RTL8192CUPHY_REG_1T_HPARRAY; rtlphy->hwparam_tables[RADIOA_1T].length = - RTL8192CURadioA_1T_HPArrayLength; + RTL8192CURADIOA_1T_HPARRAYLENGTH; rtlphy->hwparam_tables[RADIOA_1T].pdata = - RTL8192CURadioA_1T_HPArray; + RTL8192CURADIOA_1T_HPARRAY; rtlphy->hwparam_tables[RADIOB_1T].length = RTL8192CURADIOB_1TARRAYLENGTH; rtlphy->hwparam_tables[RADIOB_1T].pdata = RTL8192CU_RADIOB_1TARRAY; rtlphy->hwparam_tables[AGCTAB_1T].length = - RTL8192CUAGCTAB_1T_HPArrayLength; + RTL8192CUAGCTAB_1T_HPARRAYLENGTH; rtlphy->hwparam_tables[AGCTAB_1T].pdata = - Rtl8192CUAGCTAB_1T_HPArray; + RTL8192CUAGCTAB_1T_HPARRAY; } else { rtlphy->hwparam_tables[PHY_REG_1T].length = RTL8192CUPHY_REG_1TARRAY_LENGTH; @@ -301,16 +301,16 @@ static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents) { struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 boardType; + u8 boardtype; if (IS_NORMAL_CHIP(rtlhal->version)) { - boardType = ((contents[EEPROM_RF_OPT1]) & + boardtype = ((contents[EEPROM_RF_OPT1]) & BOARD_TYPE_NORMAL_MASK) >> 5; /*bit[7:5]*/ } else { - boardType = contents[EEPROM_RF_OPT4]; - boardType &= BOARD_TYPE_TEST_MASK; + boardtype = contents[EEPROM_RF_OPT4]; + boardtype &= BOARD_TYPE_TEST_MASK; } - rtlefuse->board_type = boardType; + rtlefuse->board_type = boardtype; if (IS_HIGHT_PA(rtlefuse->board_type)) rtlefuse->external_pa = 1; pr_info("Board Type %x\n", rtlefuse->board_type); @@ -420,7 +420,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) u16 value16; u8 value8; /* polling autoload done. */ - u32 pollingCount = 0; + u32 pollingcount = 0; do { if (rtl_read_byte(rtlpriv, REG_APS_FSMCO) & PFM_ALDN) { @@ -428,7 +428,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) "Autoload Done!\n"); break; } - if (pollingCount++ > 100) { + if (pollingcount++ > 100) { pr_err("Failed to polling REG_APS_FSMCO[PFM_ALDN] done!\n"); return -ENODEV; } @@ -452,7 +452,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, value8); } /* auto enable WLAN */ - pollingCount = 0; + pollingcount = 0; value16 = rtl_read_word(rtlpriv, REG_APS_FSMCO); value16 |= APFM_ONMAC; rtl_write_word(rtlpriv, REG_APS_FSMCO, value16); @@ -461,7 +461,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) pr_info("MAC auto ON okay!\n"); break; } - if (pollingCount++ > 1000) { + if (pollingcount++ > 1000) { pr_err("Failed to polling REG_APS_FSMCO[APFM_ONMAC] done!\n"); return -ENODEV; } @@ -473,12 +473,12 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) value16 &= ~ISO_DIOR; rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, value16); /* Reconsider when to do this operation after asking HWSD. */ - pollingCount = 0; + pollingcount = 0; rtl_write_byte(rtlpriv, REG_APSD_CTRL, (rtl_read_byte(rtlpriv, REG_APSD_CTRL) & ~BIT(6))); do { - pollingCount++; - } while ((pollingCount < 200) && + pollingcount++; + } while ((pollingcount < 200) && (rtl_read_byte(rtlpriv, REG_APSD_CTRL) & BIT(7))); /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ value16 = rtl_read_word(rtlpriv, REG_CR); @@ -495,60 +495,60 @@ static void _rtl92cu_init_queue_reserved_page(struct ieee80211_hw *hw, { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool isChipN = IS_NORMAL_CHIP(rtlhal->version); - u32 outEPNum = (u32)out_ep_num; - u32 numHQ = 0; - u32 numLQ = 0; - u32 numNQ = 0; - u32 numPubQ; + bool ischipn = IS_NORMAL_CHIP(rtlhal->version); + u32 outepnum = (u32)out_ep_num; + u32 numhq = 0; + u32 numlq = 0; + u32 numnq = 0; + u32 numpubq; u32 value32; u8 value8; - u32 txQPageNum, txQPageUnit, txQRemainPage; + u32 txqpagenum, txqpageunit, txqremaininpage; if (!wmm_enable) { - numPubQ = (isChipN) ? CHIP_B_PAGE_NUM_PUBQ : + numpubq = (ischipn) ? CHIP_B_PAGE_NUM_PUBQ : CHIP_A_PAGE_NUM_PUBQ; - txQPageNum = TX_TOTAL_PAGE_NUMBER - numPubQ; + txqpagenum = TX_TOTAL_PAGE_NUMBER - numpubq; - txQPageUnit = txQPageNum/outEPNum; - txQRemainPage = txQPageNum % outEPNum; + txqpageunit = txqpagenum / outepnum; + txqremaininpage = txqpagenum % outepnum; if (queue_sel & TX_SELE_HQ) - numHQ = txQPageUnit; + numhq = txqpageunit; if (queue_sel & TX_SELE_LQ) - numLQ = txQPageUnit; + numlq = txqpageunit; /* HIGH priority queue always present in the configuration of * 2 out-ep. Remainder pages have assigned to High queue */ - if ((outEPNum > 1) && (txQRemainPage)) - numHQ += txQRemainPage; + if (outepnum > 1 && txqremaininpage) + numhq += txqremaininpage; /* NOTE: This step done before writting REG_RQPN. */ - if (isChipN) { + if (ischipn) { if (queue_sel & TX_SELE_NQ) - numNQ = txQPageUnit; - value8 = (u8)_NPQ(numNQ); + numnq = txqpageunit; + value8 = (u8)_NPQ(numnq); rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); } } else { /* for WMM ,number of out-ep must more than or equal to 2! */ - numPubQ = isChipN ? WMM_CHIP_B_PAGE_NUM_PUBQ : + numpubq = ischipn ? WMM_CHIP_B_PAGE_NUM_PUBQ : WMM_CHIP_A_PAGE_NUM_PUBQ; if (queue_sel & TX_SELE_HQ) { - numHQ = isChipN ? WMM_CHIP_B_PAGE_NUM_HPQ : + numhq = ischipn ? WMM_CHIP_B_PAGE_NUM_HPQ : WMM_CHIP_A_PAGE_NUM_HPQ; } if (queue_sel & TX_SELE_LQ) { - numLQ = isChipN ? WMM_CHIP_B_PAGE_NUM_LPQ : + numlq = ischipn ? WMM_CHIP_B_PAGE_NUM_LPQ : WMM_CHIP_A_PAGE_NUM_LPQ; } /* NOTE: This step done before writting REG_RQPN. */ - if (isChipN) { + if (ischipn) { if (queue_sel & TX_SELE_NQ) - numNQ = WMM_CHIP_B_PAGE_NUM_NPQ; - value8 = (u8)_NPQ(numNQ); + numnq = WMM_CHIP_B_PAGE_NUM_NPQ; + value8 = (u8)_NPQ(numnq); rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); } } /* TX DMA */ - value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN; + value32 = _HPQ(numhq) | _LPQ(numlq) | _PUBQ(numpubq) | LD_RQPN; rtl_write_dword(rtlpriv, REG_RQPN, value32); } @@ -575,20 +575,20 @@ static void _rtl92c_init_trx_buffer(struct ieee80211_hw *hw, bool wmm_enable) rtl_write_byte(rtlpriv, REG_PBP, value8); } -static void _rtl92c_init_chipN_reg_priority(struct ieee80211_hw *hw, u16 beQ, - u16 bkQ, u16 viQ, u16 voQ, - u16 mgtQ, u16 hiQ) +static void _rtl92c_init_chipn_reg_priority(struct ieee80211_hw *hw, u16 beq, + u16 bkq, u16 viq, u16 voq, + u16 mgtq, u16 hiq) { struct rtl_priv *rtlpriv = rtl_priv(hw); u16 value16 = (rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0x7); - value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) | - _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) | - _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ); + value16 |= _TXDMA_BEQ_MAP(beq) | _TXDMA_BKQ_MAP(bkq) | + _TXDMA_VIQ_MAP(viq) | _TXDMA_VOQ_MAP(voq) | + _TXDMA_MGQ_MAP(mgtq) | _TXDMA_HIQ_MAP(hiq); rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, value16); } -static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw, +static void _rtl92cu_init_chipn_one_out_ep_priority(struct ieee80211_hw *hw, bool wmm_enable, u8 queue_sel) { @@ -608,96 +608,96 @@ static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw, WARN_ON(1); /* Shall not reach here! */ break; } - _rtl92c_init_chipN_reg_priority(hw, value, value, value, value, + _rtl92c_init_chipn_reg_priority(hw, value, value, value, value, value, value); pr_info("Tx queue select: 0x%02x\n", queue_sel); } -static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw, - bool wmm_enable, - u8 queue_sel) +static void _rtl92cu_init_chipn_two_out_ep_priority(struct ieee80211_hw *hw, + bool wmm_enable, + u8 queue_sel) { - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; - u16 uninitialized_var(valueHi); - u16 uninitialized_var(valueLow); + u16 beq, bkq, viq, voq, mgtq, hiq; + u16 uninitialized_var(valuehi); + u16 uninitialized_var(valuelow); switch (queue_sel) { case (TX_SELE_HQ | TX_SELE_LQ): - valueHi = QUEUE_HIGH; - valueLow = QUEUE_LOW; + valuehi = QUEUE_HIGH; + valuelow = QUEUE_LOW; break; case (TX_SELE_NQ | TX_SELE_LQ): - valueHi = QUEUE_NORMAL; - valueLow = QUEUE_LOW; + valuehi = QUEUE_NORMAL; + valuelow = QUEUE_LOW; break; case (TX_SELE_HQ | TX_SELE_NQ): - valueHi = QUEUE_HIGH; - valueLow = QUEUE_NORMAL; + valuehi = QUEUE_HIGH; + valuelow = QUEUE_NORMAL; break; default: WARN_ON(1); break; } if (!wmm_enable) { - beQ = valueLow; - bkQ = valueLow; - viQ = valueHi; - voQ = valueHi; - mgtQ = valueHi; - hiQ = valueHi; + beq = valuelow; + bkq = valuelow; + viq = valuehi; + voq = valuehi; + mgtq = valuehi; + hiq = valuehi; } else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */ - beQ = valueHi; - bkQ = valueLow; - viQ = valueLow; - voQ = valueHi; - mgtQ = valueHi; - hiQ = valueHi; + beq = valuehi; + bkq = valuelow; + viq = valuelow; + voq = valuehi; + mgtq = valuehi; + hiq = valuehi; } - _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ); + _rtl92c_init_chipn_reg_priority(hw, beq, bkq, viq, voq, mgtq, hiq); pr_info("Tx queue select: 0x%02x\n", queue_sel); } -static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw, +static void _rtl92cu_init_chipn_three_out_ep_priority(struct ieee80211_hw *hw, bool wmm_enable, u8 queue_sel) { - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; + u16 beq, bkq, viq, voq, mgtq, hiq; if (!wmm_enable) { /* typical setting */ - beQ = QUEUE_LOW; - bkQ = QUEUE_LOW; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; + beq = QUEUE_LOW; + bkq = QUEUE_LOW; + viq = QUEUE_NORMAL; + voq = QUEUE_HIGH; + mgtq = QUEUE_HIGH; + hiq = QUEUE_HIGH; } else { /* for WMM */ - beQ = QUEUE_LOW; - bkQ = QUEUE_NORMAL; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; + beq = QUEUE_LOW; + bkq = QUEUE_NORMAL; + viq = QUEUE_NORMAL; + voq = QUEUE_HIGH; + mgtq = QUEUE_HIGH; + hiq = QUEUE_HIGH; } - _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ); + _rtl92c_init_chipn_reg_priority(hw, beq, bkq, viq, voq, mgtq, hiq); pr_info("Tx queue select :0x%02x..\n", queue_sel); } -static void _rtl92cu_init_chipN_queue_priority(struct ieee80211_hw *hw, +static void _rtl92cu_init_chipn_queue_priority(struct ieee80211_hw *hw, bool wmm_enable, u8 out_ep_num, u8 queue_sel) { switch (out_ep_num) { case 1: - _rtl92cu_init_chipN_one_out_ep_priority(hw, wmm_enable, + _rtl92cu_init_chipn_one_out_ep_priority(hw, wmm_enable, queue_sel); break; case 2: - _rtl92cu_init_chipN_two_out_ep_priority(hw, wmm_enable, + _rtl92cu_init_chipn_two_out_ep_priority(hw, wmm_enable, queue_sel); break; case 3: - _rtl92cu_init_chipN_three_out_ep_priority(hw, wmm_enable, + _rtl92cu_init_chipn_three_out_ep_priority(hw, wmm_enable, queue_sel); break; default: @@ -706,7 +706,7 @@ static void _rtl92cu_init_chipN_queue_priority(struct ieee80211_hw *hw, } } -static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw, +static void _rtl92cu_init_chipt_queue_priority(struct ieee80211_hw *hw, bool wmm_enable, u8 out_ep_num, u8 queue_sel) @@ -748,10 +748,10 @@ static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw, { struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); if (IS_NORMAL_CHIP(rtlhal->version)) - _rtl92cu_init_chipN_queue_priority(hw, wmm_enable, out_ep_num, + _rtl92cu_init_chipn_queue_priority(hw, wmm_enable, out_ep_num, queue_sel); else - _rtl92cu_init_chipT_queue_priority(hw, wmm_enable, out_ep_num, + _rtl92cu_init_chipt_queue_priority(hw, wmm_enable, out_ep_num, queue_sel); } @@ -867,10 +867,10 @@ void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw) "not open sw encryption\n"); return; } - sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable; + sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TxUseDK; - sec_reg_value |= SCR_RxUseDK; + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; } if (IS_NORMAL_CHIP(rtlhal->version)) sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); @@ -899,7 +899,7 @@ static void _rtl92cu_hw_configure(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlusb->reg_bcn_ctrl_val); } -static void _InitPABias(struct ieee80211_hw *hw) +static void _initpabias(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -995,14 +995,14 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) rtl92c_phy_lc_calibrate(hw); } _rtl92cu_hw_configure(hw); - _InitPABias(hw); + _initpabias(hw); rtl92c_dm_init(hw); exit: local_irq_restore(flags); return err; } -static void _DisableRFAFEAndResetBB(struct ieee80211_hw *hw) +static void disable_rfafeandresetbb(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); /************************************** @@ -1012,20 +1012,20 @@ c. APSD_CTRL 0x600[7:0] = 0x40 d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine ***************************************/ - u8 eRFPath = 0, value8 = 0; + u8 erfpath = 0, value8 = 0; rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, (enum radio_path)eRFPath, 0x0, MASKBYTE0, 0x0); + rtl_set_rfreg(hw, (enum radio_path)erfpath, 0x0, MASKBYTE0, 0x0); value8 |= APSDOFF; rtl_write_byte(rtlpriv, REG_APSD_CTRL, value8); /*0x40*/ value8 = 0; - value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn); + value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTN); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8);/*0x16*/ - value8 &= (~FEN_BB_GLB_RSTn); + value8 &= (~FEN_BB_GLB_RSTN); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8); /*0x14*/ } -static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM) +static void _resetdigitalprocedure1(struct ieee80211_hw *hw, bool withouthwsm) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -1076,7 +1076,7 @@ static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM) rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x54); rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); } - if (bWithoutHWSM) { + if (withouthwsm) { /***************************** Without HW auto state machine g.SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock @@ -1091,7 +1091,7 @@ static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM) } } -static void _ResetDigitalProcedure2(struct ieee80211_hw *hw) +static void _resetdigitalprocedure2(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); /***************************** @@ -1103,7 +1103,7 @@ m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL+1, 0x82); } -static void _DisableGPIO(struct ieee80211_hw *hw) +static void _disablegpio(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); /*************************************** @@ -1133,13 +1133,13 @@ n. LEDCFG 0x4C[15:0] = 0x8080 rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); } -static void _DisableAnalog(struct ieee80211_hw *hw, bool bWithoutHWSM) +static void disable_analog(struct ieee80211_hw *hw, bool withouthwsm) { struct rtl_priv *rtlpriv = rtl_priv(hw); u16 value16 = 0; u8 value8 = 0; - if (bWithoutHWSM) { + if (withouthwsm) { /***************************** n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power @@ -1162,30 +1162,30 @@ i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); } -static void _CardDisableHWSM(struct ieee80211_hw *hw) +static void carddisable_hwsm(struct ieee80211_hw *hw) { /* ==== RF Off Sequence ==== */ - _DisableRFAFEAndResetBB(hw); + disable_rfafeandresetbb(hw); /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure1(hw, false); + _resetdigitalprocedure1(hw, false); /* ==== Pull GPIO PIN to balance level and LED control ====== */ - _DisableGPIO(hw); + _disablegpio(hw); /* ==== Disable analog sequence === */ - _DisableAnalog(hw, false); + disable_analog(hw, false); } -static void _CardDisableWithoutHWSM(struct ieee80211_hw *hw) +static void carddisablewithout_hwsm(struct ieee80211_hw *hw) { /*==== RF Off Sequence ==== */ - _DisableRFAFEAndResetBB(hw); + disable_rfafeandresetbb(hw); /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure1(hw, true); + _resetdigitalprocedure1(hw, true); /* ==== Pull GPIO PIN to balance level and LED control ====== */ - _DisableGPIO(hw); + _disablegpio(hw); /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure2(hw); + _resetdigitalprocedure2(hw); /* ==== Disable analog sequence === */ - _DisableAnalog(hw, true); + disable_analog(hw, true); } static void _rtl92cu_set_bcn_ctrl_reg(struct ieee80211_hw *hw, @@ -1332,9 +1332,9 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw) rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); if (rtlusb->disablehwsm) - _CardDisableHWSM(hw); + carddisable_hwsm(hw); else - _CardDisableWithoutHWSM(hw); + carddisablewithout_hwsm(hw); /* after power off we should do iqk again */ rtlpriv->phy.iqk_initialized = false; @@ -1476,12 +1476,12 @@ void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; break; case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfState; + enum rf_pwrstate rfstate; u32 val_rcr; rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, - (u8 *)(&rfState)); - if (rfState == ERFOFF) { + (u8 *)(&rfstate)); + if (rfstate == ERFOFF) { *((bool *) (val)) = true; } else { val_rcr = rtl_read_dword(rtlpriv, REG_RCR); @@ -1608,7 +1608,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) &e_aci); } else { u8 sifstime = 0; - u8 u1bAIFS; + u8 u1baifs; if (IS_WIRELESS_MODE_A(wirelessmode) || IS_WIRELESS_MODE_N_24G(wirelessmode) || @@ -1616,15 +1616,15 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) sifstime = 16; else sifstime = 10; - u1bAIFS = sifstime + (2 * val[0]); + u1baifs = sifstime + (2 * val[0]); rtl_write_byte(rtlpriv, REG_EDCA_VO_PARAM, - u1bAIFS); + u1baifs); rtl_write_byte(rtlpriv, REG_EDCA_VI_PARAM, - u1bAIFS); + u1baifs); rtl_write_byte(rtlpriv, REG_EDCA_BE_PARAM, - u1bAIFS); + u1baifs); rtl_write_byte(rtlpriv, REG_EDCA_BK_PARAM, - u1bAIFS); + u1baifs); } break; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h index dfba2c2849b3..0ccc47e36652 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h @@ -49,14 +49,14 @@ /* should be renamed and moved to another file */ enum _BOARD_TYPE_8192CUSB { BOARD_USB_DONGLE = 0, /* USB dongle */ - BOARD_USB_High_PA = 1, /* USB dongle - high power PA */ + BOARD_USB_HIGH_PA = 1, /* USB dongle - high power PA */ BOARD_MINICARD = 2, /* Minicard */ BOARD_USB_SOLO = 3, /* USB solo-Slim module */ BOARD_USB_COMBO = 4, /* USB Combo-Slim module */ }; #define IS_HIGHT_PA(boardtype) \ - ((boardtype == BOARD_USB_High_PA) ? true : false) + ((boardtype == BOARD_USB_HIGH_PA) ? true : false) #define RTL92C_DRIVER_INFO_SIZE 4 void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c index 51b8afd40d75..cc13a4a8f856 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c @@ -14,7 +14,7 @@ static void _rtl92cu_init_led(struct ieee80211_hw *hw, pled->ledon = false; } -static void _rtl92cu_deInit_led(struct rtl_led *pled) +static void rtl92cu_deinit_led(struct rtl_led *pled) { } @@ -88,8 +88,8 @@ void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - _rtl92cu_deInit_led(&rtlpriv->ledctl.sw_led0); - _rtl92cu_deInit_led(&rtlpriv->ledctl.sw_led1); + rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led0); + rtl92cu_deinit_led(&rtlpriv->ledctl.sw_led1); } static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c index ad8366e7d3a6..9cd028cb2239 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c @@ -103,7 +103,7 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | - FEN_BB_GLB_RSTn | FEN_BBRSTB); + FEN_BB_GLB_RSTN | FEN_BBRSTB); regval32 = rtl_read_dword(rtlpriv, 0x87c); rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31))); rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); @@ -121,7 +121,7 @@ bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) u32 arraylength; u32 *ptrarray; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_ARRAY\n"); arraylength = rtlphy->hwparam_tables[MAC_REG].length ; ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata; RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CUMAC_2T_ARRAY\n"); @@ -159,7 +159,7 @@ bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, phy_regarray_table[i + 1]); udelay(1); RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + "The phy_regarray_table[0] is %x Rtl819XPHY_REGARRAY[1] is %x\n", phy_regarray_table[i], phy_regarray_table[i + 1]); } @@ -169,7 +169,7 @@ bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, agctab_array_table[i + 1]); udelay(1); RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + "The agctab_array_table[0] is %x Rtl819XPHY_REGARRAY[1] is %x\n", agctab_array_table[i], agctab_array_table[i + 1]); } @@ -192,7 +192,7 @@ bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, if (configtype == BASEBAND_CONFIG_PHY_REG) { for (i = 0; i < phy_regarray_pg_len; i = i + 3) { rtl_addr_delay(phy_regarray_table_pg[i]); - _rtl92c_store_pwrIndex_diffrate_offset(hw, + _rtl92c_store_pwrindex_diffrate_offset(hw, phy_regarray_table_pg[i], phy_regarray_table_pg[i + 1], phy_regarray_table_pg[i + 2]); @@ -386,14 +386,14 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, if ((ppsc->rfpwr_state == ERFOFF) && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { bool rtstatus; - u32 InitializeCount = 0; + u32 init_count = 0; do { - InitializeCount++; + init_count++; RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "IPS Set eRf nic enable\n"); rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (InitializeCount < 10)); + } while (!rtstatus && (init_count < 10)); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); } else { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c index b65de8874b16..f3a336e0ea98 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c @@ -126,17 +126,17 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 powerBase0, powerBase1; + u32 powerbase0, powerbase1; u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0; u8 i, powerlevel[2]; for (i = 0; i < 2; i++) { powerlevel[i] = ppowerlevel[i]; legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; - powerBase0 = powerlevel[i] + legacy_pwrdiff; - powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | - (powerBase0 << 8) | powerBase0; - *(ofdmbase + i) = powerBase0; + powerbase0 = powerlevel[i] + legacy_pwrdiff; + powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | + (powerbase0 << 8) | powerbase0; + *(ofdmbase + i) = powerbase0; RTPRINT(rtlpriv, FPHY, PHY_TXPWR, " [OFDM power base index rf(%c) = 0x%x]\n", i == 0 ? 'A' : 'B', *(ofdmbase + i)); @@ -146,10 +146,10 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; powerlevel[i] += ht20_pwrdiff; } - powerBase1 = powerlevel[i]; - powerBase1 = (powerBase1 << 24) | - (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; - *(mcsbase + i) = powerBase1; + powerbase1 = powerlevel[i]; + powerbase1 = (powerbase1 << 24) | + (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; + *(mcsbase + i) = powerbase1; RTPRINT(rtlpriv, FPHY, PHY_TXPWR, " [MCS power base index rf(%c) = 0x%x]\n", i == 0 ? 'A' : 'B', *(mcsbase + i)); @@ -158,26 +158,26 @@ static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, u8 channel, u8 index, - u32 *powerBase0, - u32 *powerBase1, + u32 *powerbase0, + u32 *powerbase1, u32 *p_outwriteval) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); u8 i, chnlgroup = 0, pwr_diff_limit[4]; - u32 writeVal, customer_limit, rf; + u32 writeval, customer_limit, rf; for (rf = 0; rf < 2; rf++) { switch (rtlefuse->eeprom_regulatory) { case 0: chnlgroup = 0; - writeVal = rtlphy->mcs_offset + writeval = rtlphy->mcs_offset [chnlgroup][index + (rf ? 8 : 0)] - + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance,writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "RTK better performance,writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; case 1: if (rtlphy->pwrgroup_cnt == 1) @@ -195,20 +195,20 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, else chnlgroup += 4; } - writeVal = rtlphy->mcs_offset[chnlgroup][index + + writeval = rtlphy->mcs_offset[chnlgroup][index + (rf ? 8 : 0)] + - ((index < 2) ? powerBase0[rf] : - powerBase1[rf]); + ((index < 2) ? powerbase0[rf] : + powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; case 2: - writeVal = ((index < 2) ? powerBase0[rf] : - powerBase1[rf]); + writeval = ((index < 2) ? powerbase0[rf] : + powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory,writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "Better regulatory,writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; case 3: chnlgroup = 0; @@ -253,36 +253,36 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, RTPRINT(rtlpriv, FPHY, PHY_TXPWR, "Customer's limit rf(%c) = 0x%x\n", rf == 0 ? 'A' : 'B', customer_limit); - writeVal = customer_limit + ((index < 2) ? - powerBase0[rf] : powerBase1[rf]); + writeval = customer_limit + ((index < 2) ? + powerbase0[rf] : powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeVal rf(%c)= 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "Customer, writeval rf(%c)= 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; default: chnlgroup = 0; - writeVal = rtlphy->mcs_offset[chnlgroup] + writeval = rtlphy->mcs_offset[chnlgroup] [index + (rf ? 8 : 0)] + ((index < 2) ? - powerBase0[rf] : powerBase1[rf]); + powerbase0[rf] : powerbase1[rf]); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeValrf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); + "RTK better performance, writevalrf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); break; } if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_LEVEL1) - writeVal = 0x14141414; + writeval = 0x14141414; else if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_LEVEL2) - writeVal = 0x00000000; + writeval = 0x00000000; if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) - writeVal = writeVal - 0x06060606; - *(p_outwriteval + rf) = writeVal; + writeval = writeval - 0x06060606; + *(p_outwriteval + rf) = writeval; } } static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *pValue) + u8 index, u32 *value) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -297,33 +297,33 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 }; u8 i, rf, pwr_val[4]; - u32 writeVal; + u32 writeval; u16 regoffset; for (rf = 0; rf < 2; rf++) { - writeVal = pValue[rf]; + writeval = value[rf]; for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >> + pwr_val[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8)); if (pwr_val[i] > RF6052_MAX_TX_PWR) pwr_val[i] = RF6052_MAX_TX_PWR; } - writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | (pwr_val[1] << 8) | pwr_val[0]; if (rf == 0) regoffset = regoffset_a[index]; else regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal); + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeVal); + "Set 0x%x = %08x\n", regoffset, writeval); if (((get_rf_type(rtlphy) == RF_2T2R) && (regoffset == RTXAGC_A_MCS15_MCS12 || regoffset == RTXAGC_B_MCS15_MCS12)) || ((get_rf_type(rtlphy) != RF_2T2R) && (regoffset == RTXAGC_A_MCS07_MCS04 || regoffset == RTXAGC_B_MCS07_MCS04))) { - writeVal = pwr_val[3]; + writeval = pwr_val[3]; if (regoffset == RTXAGC_A_MCS15_MCS12 || regoffset == RTXAGC_A_MCS07_MCS04) regoffset = 0xc90; @@ -332,13 +332,13 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, regoffset = 0xc98; for (i = 0; i < 3; i++) { if (i != 2) - writeVal = (writeVal > 8) ? - (writeVal - 8) : 0; + writeval = (writeval > 8) ? + (writeval - 8) : 0; else - writeVal = (writeVal > 6) ? - (writeVal - 6) : 0; + writeval = (writeval > 6) ? + (writeval - 6) : 0; rtl_write_byte(rtlpriv, (u32)(regoffset + i), - (u8)writeVal); + (u8)writeval); } } } @@ -347,18 +347,18 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, u8 *ppowerlevel, u8 channel) { - u32 writeVal[2], powerBase0[2], powerBase1[2]; + u32 writeval[2], powerbase0[2], powerbase1[2]; u8 index = 0; rtl92c_phy_get_power_base(hw, ppowerlevel, - channel, &powerBase0[0], &powerBase1[0]); + channel, &powerbase0[0], &powerbase1[0]); for (index = 0; index < 6; index++) { _rtl92c_get_txpower_writeval_by_regulatory(hw, channel, index, - &powerBase0[0], - &powerBase1[0], - &writeVal[0]); - _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]); + &powerbase0[0], + &powerbase1[0], + &writeval[0]); + _rtl92c_write_ofdm_power_reg(hw, index, &writeval[0]); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c index 88fb556b80e9..addeac90ee0c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c @@ -1247,7 +1247,7 @@ u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH] = { 0xc78, 0x621f001e, }; -u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength] = { +u32 RTL8192CUPHY_REG_1T_HPARRAY[RTL8192CUPHY_REG_1T_HPARRAYLENGTH] = { 0x024, 0x0011800f, 0x028, 0x00ffdb83, 0x040, 0x000c0004, @@ -1439,7 +1439,7 @@ u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength] = { 0xf00, 0x00000300, }; -u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength] = { +u32 RTL8192CUPHY_REG_ARRAY_PG_HP[RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH] = { 0xe00, 0xffffffff, 0x06080808, 0xe04, 0xffffffff, 0x00040406, 0xe08, 0x0000ff00, 0x00000000, @@ -1554,7 +1554,7 @@ u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength] = { 0x868, 0xffffffff, 0x00000000, }; -u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength] = { +u32 RTL8192CURADIOA_1T_HPARRAY[RTL8192CURADIOA_1T_HPARRAYLENGTH] = { 0x000, 0x00030159, 0x001, 0x00031284, 0x002, 0x00098000, @@ -1698,7 +1698,7 @@ u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength] = { 0x000, 0x00030159, }; -u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength] = { +u32 RTL8192CUAGCTAB_1T_HPARRAY[RTL8192CUAGCTAB_1T_HPARRAYLENGTH] = { 0xc78, 0x7b000001, 0xc78, 0x7b010001, 0xc78, 0x7b020001, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h index f7c873df3c2c..efc89f7db80f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h @@ -31,15 +31,15 @@ extern u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH]; #define RTL8192CUAGCTAB_1TARRAYLENGTH 320 extern u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH]; -#define RTL8192CUPHY_REG_1T_HPArrayLength 378 -extern u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength]; +#define RTL8192CUPHY_REG_1T_HPARRAYLENGTH 378 +extern u32 RTL8192CUPHY_REG_1T_HPARRAY[RTL8192CUPHY_REG_1T_HPARRAYLENGTH]; -#define RTL8192CUPHY_REG_Array_PG_HPLength 336 -extern u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength]; +#define RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH 336 +extern u32 RTL8192CUPHY_REG_ARRAY_PG_HP[RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH]; -#define RTL8192CURadioA_1T_HPArrayLength 282 -extern u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength]; -#define RTL8192CUAGCTAB_1T_HPArrayLength 320 -extern u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength]; +#define RTL8192CURADIOA_1T_HPARRAYLENGTH 282 +extern u32 RTL8192CURADIOA_1T_HPARRAY[RTL8192CURADIOA_1T_HPARRAYLENGTH]; +#define RTL8192CUAGCTAB_1T_HPARRAYLENGTH 320 +extern u32 RTL8192CUAGCTAB_1T_HPARRAY[RTL8192CUAGCTAB_1T_HPARRAYLENGTH]; #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index 646819759de6..4293d0640310 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -14,7 +14,7 @@ #include "trx.h" #include "../rtl8192c/fw_common.h" -static int _ConfigVerTOutEP(struct ieee80211_hw *hw) +static int configvertoutep(struct ieee80211_hw *hw) { u8 ep_cfg, txqsele; u8 ep_nums = 0; @@ -47,7 +47,7 @@ static int _ConfigVerTOutEP(struct ieee80211_hw *hw) return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; } -static int _ConfigVerNOutEP(struct ieee80211_hw *hw) +static int configvernoutep(struct ieee80211_hw *hw) { u8 ep_cfg; u8 ep_nums = 0; @@ -76,7 +76,7 @@ static int _ConfigVerNOutEP(struct ieee80211_hw *hw) return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; } -static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB, +static void twooutepmapping(struct ieee80211_hw *hw, bool is_chip8, bool bwificfg, struct rtl_ep_map *ep_map) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -104,7 +104,7 @@ static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB, } } -static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool bwificfg, +static void threeoutepmapping(struct ieee80211_hw *hw, bool bwificfg, struct rtl_ep_map *ep_map) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -131,7 +131,7 @@ static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool bwificfg, } } -static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) +static void oneoutepmapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) { ep_map->ep_mapping[RTL_TXQ_BE] = 2; ep_map->ep_mapping[RTL_TXQ_BK] = 2; @@ -144,27 +144,27 @@ static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) static int _out_ep_mapping(struct ieee80211_hw *hw) { int err = 0; - bool bIsChipN, bwificfg = false; + bool ischipn, bwificfg = false; struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); struct rtl_ep_map *ep_map = &(rtlusb->ep_map); - bIsChipN = IS_NORMAL_CHIP(rtlhal->version); + ischipn = IS_NORMAL_CHIP(rtlhal->version); switch (rtlusb->out_ep_nums) { case 2: - _TwoOutEpMapping(hw, bIsChipN, bwificfg, ep_map); + twooutepmapping(hw, ischipn, bwificfg, ep_map); break; case 3: /* Test chip doesn't support three out EPs. */ - if (!bIsChipN) { + if (!ischipn) { err = -EINVAL; goto err_out; } - _ThreeOutEpMapping(hw, bIsChipN, ep_map); + threeoutepmapping(hw, ischipn, ep_map); break; case 1: - _OneOutEpMapping(hw, ep_map); + oneoutepmapping(hw, ep_map); break; default: err = -EINVAL; @@ -180,9 +180,9 @@ int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); int error = 0; if (likely(IS_NORMAL_CHIP(rtlhal->version))) - error = _ConfigVerNOutEP(hw); + error = configvernoutep(hw); else - error = _ConfigVerTOutEP(hw); + error = configvertoutep(hw); if (error) goto err_out; error = _out_ep_mapping(hw); @@ -588,28 +588,28 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n"); } -void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, - u32 buffer_len, bool bIsPsPoll) +void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc, + u32 buffer_len, bool is_pspoll) { /* Clear all status */ - memset(pDesc, 0, RTL_TX_HEADER_SIZE); - SET_TX_DESC_FIRST_SEG(pDesc, 1); /* bFirstSeg; */ - SET_TX_DESC_LAST_SEG(pDesc, 1); /* bLastSeg; */ - SET_TX_DESC_OFFSET(pDesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */ - SET_TX_DESC_PKT_SIZE(pDesc, buffer_len); /* Buffer size + command hdr */ - SET_TX_DESC_QUEUE_SEL(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */ + memset(pdesc, 0, RTL_TX_HEADER_SIZE); + SET_TX_DESC_FIRST_SEG(pdesc, 1); /* bFirstSeg; */ + SET_TX_DESC_LAST_SEG(pdesc, 1); /* bLastSeg; */ + SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */ + SET_TX_DESC_PKT_SIZE(pdesc, buffer_len); /* Buffer size + command hdr */ + SET_TX_DESC_QUEUE_SEL(pdesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */ /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error * vlaue by Hw. */ - if (bIsPsPoll) { - SET_TX_DESC_NAV_USE_HDR(pDesc, 1); + if (is_pspoll) { + SET_TX_DESC_NAV_USE_HDR(pdesc, 1); } else { - SET_TX_DESC_HWSEQ_EN(pDesc, 1); /* Hw set sequence number */ - SET_TX_DESC_PKT_ID(pDesc, 0x100); /* set bit3 to 1. */ + SET_TX_DESC_HWSEQ_EN(pdesc, 1); /* Hw set sequence number */ + SET_TX_DESC_PKT_ID(pdesc, 0x100); /* set bit3 to 1. */ } - SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */ - SET_TX_DESC_OWN(pDesc, 1); - SET_TX_DESC_TX_RATE(pDesc, DESC_RATE1M); - _rtl_tx_desc_checksum(pDesc); + SET_TX_DESC_USE_RATE(pdesc, 1); /* use data rate which is set by Sw */ + SET_TX_DESC_OWN(pdesc, 1); + SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); + _rtl_tx_desc_checksum(pdesc); } void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h index d176b0ba6ae6..439ced0e18fa 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h @@ -375,8 +375,8 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 queue_index, struct rtl_tcb_desc *tcb_desc); -void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, - u32 buffer_len, bool bIsPsPoll); +void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc, + u32 buffer_len, bool ispspoll); void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool b_firstseg, bool b_lastseg, struct sk_buff *skb); -- cgit v1.2.3 From b83faeda028bf361db9c796396e710d5fb1337b0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 16:36:41 -0600 Subject: rtlwifi: rtl8188de: Remove CamelCase variables If a macro is in CamelCase, it it converted to upper case. Variables and routine names are converted to lower case. The following checkpatch exceptions are also fixed: CHECK: No space is necessary after a cast #211: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c:109: + (u8 *) (&rfstate)); CHECK: No space is necessary after a cast #241: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c:277: + ptmp_byte = (u8 *) (®toset) + index; Note that not all checkpatch exceptions are addressed. Those will be handled in later patches. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8192de/dm.c | 24 ++++---- .../net/wireless/realtek/rtlwifi/rtl8192de/dm.h | 2 +- .../net/wireless/realtek/rtlwifi/rtl8192de/fw.c | 16 ++--- .../net/wireless/realtek/rtlwifi/rtl8192de/hw.c | 66 ++++++++++----------- .../net/wireless/realtek/rtlwifi/rtl8192de/phy.c | 68 +++++++++++----------- .../net/wireless/realtek/rtlwifi/rtl8192de/reg.h | 28 ++++----- 6 files changed, 102 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c index f7670710f475..7cc86bb387a1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c @@ -842,7 +842,7 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( else rf = 1; if (thermalvalue) { - ele_d = rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD) & MASKOFDM_D; for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { @@ -850,13 +850,13 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n", - ROFDM0_XATxIQIMBALANCE, + ROFDM0_XATXIQIMBALANCE, ele_d, ofdm_index_old[0]); break; } } if (is2t) { - ele_d = rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, + ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD) & MASKOFDM_D; for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { if (ele_d == @@ -865,7 +865,7 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "Initial pathB ele_d reg 0x%x = 0x%lx, ofdm_index = 0x%x\n", - ROFDM0_XBTxIQIMBALANCE, ele_d, + ROFDM0_XBTXIQIMBALANCE, ele_d, ofdm_index_old[1]); break; } @@ -1037,11 +1037,11 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( * regC94, element B is always 0 */ value32 = (ele_d << 22) | ((ele_c & 0x3F) << 16) | ele_a; - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, value32); value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XCTxAFE, MASKH4BITS, + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32); value32 = ((val_x * ele_d) >> 7) & 0x01; @@ -1049,11 +1049,11 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( value32); } else { - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, ofdmswing_table [(u8)ofdm_index[0]]); - rtl_set_bbreg(hw, ROFDM0_XCTxAFE, MASKH4BITS, + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00); rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00); @@ -1150,21 +1150,21 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( ((ele_c & 0x3F) << 16) | ele_a; rtl_set_bbreg(hw, - ROFDM0_XBTxIQIMBALANCE, + ROFDM0_XBTXIQIMBALANCE, MASKDWORD, value32); value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XDTxAFE, + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32); value32 = ((val_x * ele_d) >> 7) & 0x01; rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), value32); } else { rtl_set_bbreg(hw, - ROFDM0_XBTxIQIMBALANCE, + ROFDM0_XBTXIQIMBALANCE, MASKDWORD, ofdmswing_table [(u8) ofdm_index[1]]); - rtl_set_bbreg(hw, ROFDM0_XDTxAFE, + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, 0x00); rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), 0x00); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h index ef39874e2439..939cc45bfebd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h @@ -22,7 +22,7 @@ #define DM_DIG_FA_TH1 0x400 #define DM_DIG_FA_TH2 0x600 -#define RXPATHSELECTION_SS_TH_lOW 30 +#define RXPATHSELECTION_SS_TH_LOW 30 #define RXPATHSELECTION_DIFF_TH 18 #define DM_RATR_STA_INIT 0 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c index 98da9525a15e..2064813f9381 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c @@ -75,7 +75,7 @@ static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw) do { value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) && - (!(value32 & FWDL_ChkSum_rpt))); + (!(value32 & FWDL_CHKSUM_RPT))); if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) { pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n", value32); @@ -599,7 +599,7 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) struct sk_buff *skb = NULL; u32 totalpacketlen; bool rtstatus; - u8 u1RsvdPageLoc[3] = { 0 }; + u8 u1rsvdpageloc[3] = { 0 }; bool dlok = false; u8 *beacon; u8 *p_pspoll; @@ -618,7 +618,7 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); /*-------------------------------------------------------- (3) null data ---------------------------------------------------------*/ @@ -626,7 +626,7 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); /*--------------------------------------------------------- (4) probe response ----------------------------------------------------------*/ @@ -634,14 +634,14 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); totalpacketlen = TOTAL_RESERVED_PKT_LEN; RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL", &reserved_page_packet[0], totalpacketlen); RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL", - u1RsvdPageLoc, 3); + u1rsvdpageloc, 3); skb = dev_alloc_skb(totalpacketlen); if (!skb) { dlok = false; @@ -656,9 +656,9 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Set RSVD page location to Fw\n"); RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE", u1RsvdPageLoc, 3); + "H2C_RSVDPAGE", u1rsvdpageloc, 3); rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE, - sizeof(u1RsvdPageLoc), u1RsvdPageLoc); + sizeof(u1rsvdpageloc), u1rsvdpageloc); } else RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "Set RSVD page location to Fw FAIL!!!!!!\n"); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c index 603edc399e14..c7f29a9be50d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c @@ -102,12 +102,12 @@ void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; break; case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfState; + enum rf_pwrstate rfstate; u32 val_rcr; rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, - (u8 *) (&rfState)); - if (rfState == ERFOFF) { + (u8 *)(&rfstate)); + if (rfstate == ERFOFF) { *((bool *) (val)) = true; } else { val_rcr = rtl_read_dword(rtlpriv, REG_RCR); @@ -258,23 +258,23 @@ void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } case HW_VAR_AMPDU_FACTOR: { u8 factor_toset; - u32 regtoSet; + u32 regtoset; u8 *ptmp_byte = NULL; u8 index; if (rtlhal->macphymode == DUALMAC_DUALPHY) - regtoSet = 0xb9726641; + regtoset = 0xb9726641; else if (rtlhal->macphymode == DUALMAC_SINGLEPHY) - regtoSet = 0x66626641; + regtoset = 0x66626641; else - regtoSet = 0xb972a841; + regtoset = 0xb972a841; factor_toset = *val; if (factor_toset <= 3) { factor_toset = (1 << (factor_toset + 2)); if (factor_toset > 0xf) factor_toset = 0xf; for (index = 0; index < 4; index++) { - ptmp_byte = (u8 *) (®toSet) + index; + ptmp_byte = (u8 *)(®toset) + index; if ((*ptmp_byte & 0xf0) > (factor_toset << 4)) *ptmp_byte = (*ptmp_byte & 0x0f) @@ -283,7 +283,7 @@ void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) *ptmp_byte = (*ptmp_byte & 0xf0) | (factor_toset); } - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoSet); + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoset); RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, "Set HW_VAR_AMPDU_FACTOR: %#x\n", factor_toset); @@ -509,18 +509,18 @@ static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); unsigned short i; u8 txpktbuf_bndy; - u8 maxPage; + u8 maxpage; bool status; u32 value32; /* High+low page number */ u8 value8; /* normal page number */ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) { - maxPage = 255; + maxpage = 255; txpktbuf_bndy = 246; value8 = 0; value32 = 0x80bf0d29; } else { - maxPage = 127; + maxpage = 127; txpktbuf_bndy = 123; value8 = 0; value32 = 0x80750005; @@ -576,14 +576,14 @@ static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw) /* This ring buffer is used as beacon buffer if we */ /* config this MAC as two MAC transfer. */ /* Otherwise used as local loopback buffer. */ - for (i = txpktbuf_bndy; i < maxPage; i++) { + for (i = txpktbuf_bndy; i < maxpage; i++) { status = _rtl92de_llt_write(hw, i, (i + 1)); if (true != status) return status; } /* Let last entry point to the start entry of ring buffer */ - status = _rtl92de_llt_write(hw, maxPage, txpktbuf_bndy); + status = _rtl92de_llt_write(hw, maxpage, txpktbuf_bndy); if (true != status) return status; @@ -1393,13 +1393,13 @@ void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, } static void _rtl92de_readpowervalue_fromprom(struct txpower_info *pwrinfo, - u8 *rom_content, bool autoLoadfail) + u8 *rom_content, bool autoloadfail) { u32 rfpath, eeaddr, group, offset1, offset2; u8 i; memset(pwrinfo, 0, sizeof(struct txpower_info)); - if (autoLoadfail) { + if (autoloadfail) { for (group = 0; group < CHANNEL_GROUP_MAX; group++) { for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { if (group < CHANNEL_GROUP_MAX_2G) { @@ -1541,7 +1541,7 @@ static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw, struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct txpower_info pwrinfo; u8 tempval[2], i, pwr, diff; - u32 ch, rfPath, group; + u32 ch, rfpath, group; _rtl92de_readpowervalue_fromprom(&pwrinfo, hwinfo, autoload_fail); if (!autoload_fail) { @@ -1621,25 +1621,25 @@ static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw, "Delta_IQK = 0x%x Delta_LCK = 0x%x\n", rtlefuse->delta_iqk, rtlefuse->delta_lck); - for (rfPath = 0; rfPath < RF6052_MAX_PATH; rfPath++) { + for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { group = rtl92d_get_chnlgroup_fromarray((u8) ch); if (ch < CHANNEL_MAX_NUMBER_2G) - rtlefuse->txpwrlevel_cck[rfPath][ch] = - pwrinfo.cck_index[rfPath][group]; - rtlefuse->txpwrlevel_ht40_1s[rfPath][ch] = - pwrinfo.ht40_1sindex[rfPath][group]; - rtlefuse->txpwr_ht20diff[rfPath][ch] = - pwrinfo.ht20indexdiff[rfPath][group]; - rtlefuse->txpwr_legacyhtdiff[rfPath][ch] = - pwrinfo.ofdmindexdiff[rfPath][group]; - rtlefuse->pwrgroup_ht20[rfPath][ch] = - pwrinfo.ht20maxoffset[rfPath][group]; - rtlefuse->pwrgroup_ht40[rfPath][ch] = - pwrinfo.ht40maxoffset[rfPath][group]; - pwr = pwrinfo.ht40_1sindex[rfPath][group]; - diff = pwrinfo.ht40_2sindexdiff[rfPath][group]; - rtlefuse->txpwrlevel_ht40_2s[rfPath][ch] = + rtlefuse->txpwrlevel_cck[rfpath][ch] = + pwrinfo.cck_index[rfpath][group]; + rtlefuse->txpwrlevel_ht40_1s[rfpath][ch] = + pwrinfo.ht40_1sindex[rfpath][group]; + rtlefuse->txpwr_ht20diff[rfpath][ch] = + pwrinfo.ht20indexdiff[rfpath][group]; + rtlefuse->txpwr_legacyhtdiff[rfpath][ch] = + pwrinfo.ofdmindexdiff[rfpath][group]; + rtlefuse->pwrgroup_ht20[rfpath][ch] = + pwrinfo.ht20maxoffset[rfpath][group]; + rtlefuse->pwrgroup_ht40[rfpath][ch] = + pwrinfo.ht40maxoffset[rfpath][group]; + pwr = pwrinfo.ht40_1sindex[rfpath][group]; + diff = pwrinfo.ht40_2sindexdiff[rfpath][group]; + rtlefuse->txpwrlevel_ht40_2s[rfpath][ch] = (pwr > diff) ? (pwr - diff) : 0; } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c index 2b30a820f45f..0ae6371b6318 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c @@ -484,16 +484,16 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; /* Tx AFE control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATxIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTxIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTxIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTxIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; /* Tx AFE control 2 */ - rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE; - rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTxAFE; - rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTxAFE; - rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE; + rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; /* Tranceiver LSSI Readback SI mode */ rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; @@ -742,7 +742,7 @@ bool rtl92d_phy_bb_config(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_RF_CTRL, value | RF_EN | RF_RSTB | RF_SDMRSTB); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA | - FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB); + FEN_DIO_PCIE | FEN_BB_GLB_RSTN | FEN_BBRSTB); rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); if (!(IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))) { regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); @@ -1458,11 +1458,11 @@ static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw, u8 result = 0; u8 i; u8 retrycount = 2; - u32 TxOKBit = BIT(28), RxOKBit = BIT(27); + u32 TXOKBIT = BIT(28), RXOKBIT = BIT(27); if (rtlhal->interfaceindex == 1) { /* PHY1 */ - TxOKBit = BIT(31); - RxOKBit = BIT(30); + TXOKBIT = BIT(31); + RXOKBIT = BIT(30); } RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK!\n"); /* path-A IQK setting */ @@ -1504,7 +1504,7 @@ static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw, RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe9c = 0x%x\n", rege9c); regea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xea4 = 0x%x\n", regea4); - if (!(regeac & TxOKBit) && + if (!(regeac & TXOKBIT) && (((rege94 & 0x03FF0000) >> 16) != 0x142)) { result |= 0x01; } else { /* if Tx not OK, ignore Rx */ @@ -1514,7 +1514,7 @@ static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw, } /* if Tx is OK, check whether Rx is OK */ - if (!(regeac & RxOKBit) && + if (!(regeac & RXOKBIT) && (((regea4 & 0x03FF0000) >> 16) != 0x132)) { result |= 0x02; break; @@ -2143,7 +2143,7 @@ static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw, if (final_candidate == 0xFF) { return; } else if (iqk_ok) { - oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD) >> 22) & 0x3FF; /* OFDM0_D */ val_x = result[final_candidate][0]; if ((val_x & 0x00000200) != 0) @@ -2152,7 +2152,7 @@ static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw, RTPRINT(rtlpriv, FINIT, INIT_IQK, "X = 0x%x, tx0_a = 0x%x, oldval_0 0x%x\n", val_x, tx0_a, oldval_0); - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x3FF, tx0_a); + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), ((val_x * oldval_0 >> 7) & 0x1)); val_y = result[final_candidate][1]; @@ -2166,15 +2166,15 @@ static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw, RTPRINT(rtlpriv, FINIT, INIT_IQK, "Y = 0x%lx, tx0_c = 0x%lx\n", val_y, tx0_c); - rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, ((tx0_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x003F0000, + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, (tx0_c & 0x3F)); if (is2t) rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(26), ((val_y * oldval_0 >> 7) & 0x1)); RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xC80 = 0x%x\n", - rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD)); if (txonly) { RTPRINT(rtlpriv, FINIT, INIT_IQK, "only Tx OK\n"); @@ -2202,7 +2202,7 @@ static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw, if (final_candidate == 0xFF) { return; } else if (iqk_ok) { - oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, + oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD) >> 22) & 0x3FF; val_x = result[final_candidate][4]; if ((val_x & 0x00000200) != 0) @@ -2210,7 +2210,7 @@ static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw, tx1_a = (val_x * oldval_1) >> 8; RTPRINT(rtlpriv, FINIT, INIT_IQK, "X = 0x%x, tx1_a = 0x%x\n", val_x, tx1_a); - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x3FF, tx1_a); + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a); rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), ((val_x * oldval_1 >> 7) & 0x1)); val_y = result[final_candidate][5]; @@ -2221,9 +2221,9 @@ static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw, tx1_c = (val_y * oldval_1) >> 8; RTPRINT(rtlpriv, FINIT, INIT_IQK, "Y = 0x%lx, tx1_c = 0x%lx\n", val_y, tx1_c); - rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, ((tx1_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x003F0000, + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000, (tx1_c & 0x3F)); rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30), ((val_y * oldval_1 >> 7) & 0x1)); @@ -3064,13 +3064,13 @@ bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, if ((ppsc->rfpwr_state == ERFOFF) && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { bool rtstatus; - u32 InitializeCount = 0; + u32 initializecount = 0; do { - InitializeCount++; + initializecount++; RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "IPS Set eRf nic enable\n"); rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (InitializeCount < 10)); + } while (!rtstatus && (initializecount < 10)); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); @@ -3365,9 +3365,9 @@ void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw) /* 5G LAN ON */ rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0xa); /* TX BB gain shift*1,Just for testchip,0xc80,0xc88 */ - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, 0x40000100); - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD, 0x40000100); if (rtlhal->macphymode == DUALMAC_DUALPHY) { rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, @@ -3421,16 +3421,16 @@ void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw) rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0x0); /* TX BB gain shift,Just for testchip,0xc80,0xc88 */ if (rtlefuse->internal_pa_5g[0]) - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, 0x2d4000b5); else - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, 0x20000080); if (rtlefuse->internal_pa_5g[1]) - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD, 0x2d4000b5); else - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD, 0x20000080); if (rtlhal->macphymode == DUALMAC_DUALPHY) { rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, @@ -3459,10 +3459,10 @@ void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw) /* update IQK related settings */ rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, MASKDWORD, 0x40000100); rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, MASKDWORD, 0x40000100); - rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, 0x00); + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, 0x00); rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30) | BIT(28) | BIT(26) | BIT(24), 0x00); - rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, 0x00); + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, 0x00); rtl_set_bbreg(hw, 0xca0, 0xF0000000, 0x00); rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, 0x00); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h index 77a3a8f0fa02..2783d7e7b227 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h @@ -730,7 +730,7 @@ /* SYS_FUNC_EN */ #define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTn BIT(1) +#define FEN_BB_GLB_RSTN BIT(1) #define FEN_USBA BIT(2) #define FEN_UPLL BIT(3) #define FEN_USBD BIT(4) @@ -751,7 +751,7 @@ #define PFM_ALDN BIT(1) #define PFM_LDKP BIT(2) #define PFM_WOWL BIT(3) -#define EnPDN BIT(4) +#define ENPDN BIT(4) #define PDN_PL BIT(5) #define APFM_ONMAC BIT(8) #define APFM_OFF BIT(9) @@ -888,7 +888,7 @@ /* MCUFWDL */ #define MCUFWDL_EN BIT(0) #define MCUFWDL_RDY BIT(1) -#define FWDL_ChkSum_rpt BIT(2) +#define FWDL_CHKSUM_RPT BIT(2) #define MACINI_RDY BIT(3) #define BBINI_RDY BIT(4) #define RFINI_RDY BIT(5) @@ -1011,7 +1011,7 @@ #define RFPGA0_XA_LSSIPARAMETER 0x840 #define RFPGA0_XB_LSSIPARAMETER 0x844 -#define RFPGA0_RFWAkEUPPARAMETER 0x850 +#define RFPGA0_RFWAKEUPPARAMETER 0x850 #define RFPGA0_RFSLEEPUPPARAMETER 0x854 #define RFPGA0_XAB_SWITCHCONTROL 0x858 @@ -1113,14 +1113,14 @@ #define ROFDM0_AGCRSSITABLE 0xc78 #define ROFDM0_HTSTFAGC 0xc7c -#define ROFDM0_XATxIQIMBALANCE 0xc80 -#define ROFDM0_XATxAFE 0xc84 -#define ROFDM0_XBTxIQIMBALANCE 0xc88 -#define ROFDM0_XBTxAFE 0xc8c -#define ROFDM0_XCTxIQIMBALANCE 0xc90 -#define ROFDM0_XCTxAFE 0xc94 -#define ROFDM0_XDTxIQIMBALANCE 0xc98 -#define ROFDM0_XDTxAFE 0xc9c +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c #define ROFDM0_RXHPPARAMETER 0xce0 #define ROFDM0_TXPSEUDONOISEWGT 0xce4 @@ -1164,7 +1164,7 @@ #define ROFDM_AGCREPORT 0xdd0 #define ROFDM_RXSNR 0xdd4 #define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIGReport 0xddc +#define ROFDM_SIGREPORT 0xddc /* 8. PageE(0xE00) */ #define RTXAGC_A_RATE18_06 0xe00 @@ -1206,7 +1206,7 @@ #define RF_IPA 0x15 #define RF_POW_ABILITY 0x17 #define RF_MODE_AG 0x18 -#define rRfChannel 0x18 +#define rfchannel 0x18 #define RF_CHNLBW 0x18 #define RF_TOP 0x19 -- cgit v1.2.3 From 2a83ad1fe330b3c0c93062e886be23b2be3a1180 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 16:36:42 -0600 Subject: rtlwifi: rtl8192se: Remove CamelCase variables If a macro is in CamelCase, it it converted to upper case. Variables and routine names are converted to lower case. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8192se/dm.h | 2 +- .../net/wireless/realtek/rtlwifi/rtl8192se/fw.c | 4 +- .../net/wireless/realtek/rtlwifi/rtl8192se/fw.h | 6 +-- .../net/wireless/realtek/rtlwifi/rtl8192se/hw.c | 22 +++++----- .../net/wireless/realtek/rtlwifi/rtl8192se/phy.c | 44 ++++++++++---------- .../net/wireless/realtek/rtlwifi/rtl8192se/reg.h | 48 +++++++++++----------- 6 files changed, 63 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h index b8efcd8df3e5..b9c5a92c2bd0 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h @@ -58,7 +58,7 @@ enum dm_ratr_sta { #define DM_DIG_HIGH_PWR_THRESH_HIGH 75 #define DM_DIG_HIGH_PWR_THRESH_LOW 70 -#define DM_DIG_MIN_Netcore 0x12 +#define DM_DIG_MIN_NETCORE 0x12 void rtl92s_dm_watchdog(struct ieee80211_hw *hw); void rtl92s_dm_init(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c index 790124b7e0da..faa307a0b148 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c @@ -547,14 +547,14 @@ static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, return true; } -void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode) +void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct h2c_set_pwrmode_parm pwrmode; u16 max_wakeup_period = 0; - pwrmode.mode = Mode; + pwrmode.mode = mode; pwrmode.flag_low_traffic_en = 0; pwrmode.flag_lpnav_en = 0; pwrmode.flag_rf_low_snr_en = 0; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h index 0cba71f793e9..99c6f7eefd85 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h @@ -276,7 +276,7 @@ enum fw_h2c_cmd { H2C_JOINBSS_CMD, H2C_DISCONNECT_CMD, /*15*/ H2C_CREATEBSS_CMD, - H2C_SETOPMode_CMD, + H2C_SETOPMODE_CMD, H2C_SITESURVEY_CMD, H2C_SETAUTH_CMD, H2C_SETKEY_CMD, /*20*/ @@ -315,10 +315,10 @@ enum fw_h2c_cmd { /* The following macros are used for FW * CMD map and parameter updated. */ -#define FW_CMD_IO_CLR(rtlpriv, _Bit) \ +#define FW_CMD_IO_CLR(rtlpriv, _bit) \ do { \ udelay(1000); \ - rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \ + rtlpriv->rtlhal.fwcmd_iomap &= (~_bit); \ } while (0) #define FW_CMD_IO_UPDATE(rtlpriv, _val) \ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c index 4242d166c73c..6d6e8994460d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c @@ -236,7 +236,7 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&( mac->ac[0].aifs)); u8 acm = p_aci_aifsn->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, AcmHwCtrl); + u8 acm_ctrl = rtl_read_byte(rtlpriv, ACMHWCTRL); acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); @@ -244,13 +244,13 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) if (acm) { switch (e_aci) { case AC0_BE: - acm_ctrl |= AcmHw_BeqEn; + acm_ctrl |= ACMHW_BEQEN; break; case AC2_VI: - acm_ctrl |= AcmHw_ViqEn; + acm_ctrl |= ACMHW_VIQEN; break; case AC3_VO: - acm_ctrl |= AcmHw_VoqEn; + acm_ctrl |= ACMHW_VOQEN; break; default: RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, @@ -261,13 +261,13 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } else { switch (e_aci) { case AC0_BE: - acm_ctrl &= (~AcmHw_BeqEn); + acm_ctrl &= (~ACMHW_BEQEN); break; case AC2_VI: - acm_ctrl &= (~AcmHw_ViqEn); + acm_ctrl &= (~ACMHW_VIQEN); break; case AC3_VO: - acm_ctrl &= (~AcmHw_VoqEn); + acm_ctrl &= (~ACMHW_VOQEN); break; default: pr_err("switch case %#x not processed\n", @@ -278,7 +278,7 @@ void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, "HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl); - rtl_write_byte(rtlpriv, AcmHwCtrl, acm_ctrl); + rtl_write_byte(rtlpriv, ACMHWCTRL, acm_ctrl); break; } case HW_VAR_RCR:{ @@ -847,7 +847,7 @@ static void _rtl92se_macconfig_after_fwdownload(struct ieee80211_hw *hw) /* 10. Power Save Control Register (Offset: 0x0260 - 0x02DF) */ /* 11. General Purpose Register (Offset: 0x02E0 - 0x02FF) */ /* 12. Host Interrupt Status Register (Offset: 0x0300 - 0x030F) */ - /* 13. Test Mode and Debug Control Register (Offset: 0x0310 - 0x034F) */ + /* 13. Test mode and Debug Control Register (Offset: 0x0310 - 0x034F) */ /* 14. Set driver info, we only accept PHY status now. */ rtl_write_byte(rtlpriv, RXDRVINFO_SZ, 4); @@ -1619,7 +1619,7 @@ void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, rtl92se_enable_interrupt(hw); } -static void _rtl8192se_get_IC_Inferiority(struct ieee80211_hw *hw) +static void _rtl8192se_get_ic_inferiority(struct ieee80211_hw *hw) { struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -1682,7 +1682,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) if (rtlefuse->autoload_failflag) return; - _rtl8192se_get_IC_Inferiority(hw); + _rtl8192se_get_ic_inferiority(hw); /* Read IC Version && Channel Plan */ /* VID, DID SE 0xA-D */ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c index 37a8a57bca3f..d5c0eb462315 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c @@ -527,13 +527,13 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { bool rtstatus; - u32 InitializeCount = 0; + u32 initializecount = 0; do { - InitializeCount++; + initializecount++; RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, "IPS Set eRf nic enable\n"); rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (InitializeCount < 10)); + } while (!rtstatus && (initializecount < 10)); RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); @@ -913,7 +913,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) if (!rtstatus) { pr_err("Write BB Reg Fail!!\n"); - goto phy_BB8190_Config_ParaFile_Fail; + goto phy_bb8190_config_parafile_fail; } /* 2. If EEPROM or EFUSE autoload OK, We must config by @@ -926,7 +926,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) } if (!rtstatus) { pr_err("_rtl92s_phy_bb_config_parafile(): BB_PG Reg Fail!!\n"); - goto phy_BB8190_Config_ParaFile_Fail; + goto phy_bb8190_config_parafile_fail; } /* 3. BB AGC table Initialization */ @@ -934,7 +934,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) if (!rtstatus) { pr_err("%s(): AGC Table Fail\n", __func__); - goto phy_BB8190_Config_ParaFile_Fail; + goto phy_bb8190_config_parafile_fail; } /* Check if the CCK HighPower is turned ON. */ @@ -942,7 +942,7 @@ static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) rtlphy->cck_high_power = (bool)(rtl92s_phy_query_bb_reg(hw, RFPGA0_XA_HSSIPARAMETER2, 0x200)); -phy_BB8190_Config_ParaFile_Fail: +phy_bb8190_config_parafile_fail: return rtstatus; } @@ -1007,13 +1007,13 @@ bool rtl92s_phy_mac_config(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); u32 i; u32 arraylength; - u32 *ptraArray; + u32 *ptrarray; arraylength = MAC_2T_ARRAYLENGTH; - ptraArray = rtl8192semac_2t_array; + ptrarray = rtl8192semac_2t_array; for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptraArray[i], (u8)ptraArray[i + 1]); + rtl_write_byte(rtlpriv, ptrarray[i], (u8)ptrarray[i + 1]); return true; } @@ -1106,7 +1106,7 @@ void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) } static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, - u8 *cckpowerlevel, u8 *ofdmpowerLevel) + u8 *cckpowerlevel, u8 *ofdmpowerlevel) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); @@ -1122,15 +1122,15 @@ static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, /* 2. OFDM for 1T or 2T */ if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { /* Read HT 40 OFDM TX power */ - ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index]; - ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index]; + ofdmpowerlevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index]; + ofdmpowerlevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index]; } else if (rtlphy->rf_type == RF_2T2R) { /* Read HT 40 OFDM TX power */ - ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; - ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; + ofdmpowerlevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; + ofdmpowerlevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; } else { - ofdmpowerLevel[0] = 0; - ofdmpowerLevel[1] = 0; + ofdmpowerlevel[0] = 0; + ofdmpowerlevel[1] = 0; } } @@ -1149,7 +1149,7 @@ void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); /* [0]:RF-A, [1]:RF-B */ - u8 cckpowerlevel[2], ofdmpowerLevel[2]; + u8 cckpowerlevel[2], ofdmpowerlevel[2]; if (!rtlefuse->txpwr_fromeprom) return; @@ -1161,18 +1161,18 @@ void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel) * 1. For CCK. * 2. For OFDM 1T or 2T */ _rtl92s_phy_get_txpower_index(hw, channel, &cckpowerlevel[0], - &ofdmpowerLevel[0]); + &ofdmpowerlevel[0]); RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Channel-%d, cckPowerLevel (A / B) = 0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n", channel, cckpowerlevel[0], cckpowerlevel[1], - ofdmpowerLevel[0], ofdmpowerLevel[1]); + ofdmpowerlevel[0], ofdmpowerlevel[1]); _rtl92s_phy_ccxpower_indexcheck(hw, channel, &cckpowerlevel[0], - &ofdmpowerLevel[0]); + &ofdmpowerlevel[0]); rtl92s_phy_rf6052_set_ccktxpower(hw, cckpowerlevel[0]); - rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerLevel[0], channel); + rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerlevel[0], channel); } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h index dfaaf61b3b17..45f968e0e57c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h @@ -169,7 +169,7 @@ #define BCNTCFG 0x01E0 #define CWRR 0x01E2 #define ACMAVG 0x01E4 -#define AcmHwCtrl 0x01E7 +#define ACMHWCTRL 0x01E7 #define VO_ADMTM 0x01E8 #define VI_ADMTM 0x01EC #define BE_ADMTM 0x01F0 @@ -235,7 +235,7 @@ #define INTA_MASK 0x0300 #define ISR 0x0308 -/* 13. Test Mode and Debug Control Registers */ +/* 13. Test mode and Debug Control Registers */ #define DBG_PORT_SWITCH 0x003A #define BIST 0x0310 #define DBS 0x0314 @@ -325,9 +325,9 @@ #define SYS_SWHW_SEL BIT(14) #define SYS_FWHW_SEL BIT(15) -#define CmdEEPROM_En BIT(5) -#define CmdEERPOMSEL BIT(4) -#define Cmd9346CR_9356SEL BIT(4) +#define CMDEEPROM_EN BIT(5) +#define CMDEERPOMSEL BIT(4) +#define CMD9346CR_9356SEL BIT(4) #define AFE_MBEN BIT(1) #define AFE_BGEN BIT(0) @@ -348,9 +348,9 @@ #define APLL_EN BIT(0) -#define AFR_CardBEn BIT(0) +#define AFR_CARDBEN BIT(0) #define AFR_CLKRUN_SEL BIT(1) -#define AFR_FuncRegEn BIT(2) +#define AFR_FUNCREGEN BIT(2) #define APSDOFF_STATUS BIT(15) #define APSDOFF BIT(14) @@ -366,13 +366,13 @@ #define HCI_RXDMA_EN BIT(3) #define HCI_TXDMA_EN BIT(2) -#define StopHCCA BIT(6) -#define StopHigh BIT(5) -#define StopMgt BIT(4) -#define StopVO BIT(3) -#define StopVI BIT(2) -#define StopBE BIT(1) -#define StopBK BIT(0) +#define STOPHCCA BIT(6) +#define STOPHIGH BIT(5) +#define STOPMGT BIT(4) +#define STOPVO BIT(3) +#define STOPVI BIT(2) +#define STOPBE BIT(1) +#define STOPBK BIT(0) #define LBK_NORMAL 0x00 #define LBK_MAC_LB (BIT(0) | BIT(1) | BIT(3)) @@ -384,7 +384,7 @@ #define TXDMAPRE2FULL BIT(23) #define DISCW BIT(20) #define TCRICV BIT(19) -#define CfendForm BIT(17) +#define cfendform BIT(17) #define TCRCRC BIT(16) #define FAKE_IMEM_EN BIT(15) #define TSFRST BIT(9) @@ -509,7 +509,7 @@ #define RRSR_MCS5 BIT(17) #define RRSR_MCS6 BIT(18) #define RRSR_MCS7 BIT(19) -#define BRSR_AckShortPmb BIT(23) +#define BRSR_ACKSHORTPMB BIT(23) #define RATR_1M 0x00000001 #define RATR_2M 0x00000002 @@ -560,13 +560,13 @@ #define AC_PARAM_ECW_MIN_OFFSET 8 #define AC_PARAM_AIFS_OFFSET 0 -#define AcmHw_HwEn BIT(0) -#define AcmHw_BeqEn BIT(1) -#define AcmHw_ViqEn BIT(2) -#define AcmHw_VoqEn BIT(3) -#define AcmHw_BeqStatus BIT(4) -#define AcmHw_ViqStatus BIT(5) -#define AcmHw_VoqStatus BIT(6) +#define ACMHW_HWEN BIT(0) +#define ACMHW_BEQEN BIT(1) +#define ACMHW_VIQEN BIT(2) +#define ACMHW_VOQEN BIT(3) +#define ACMHW_BEQSTATUS BIT(4) +#define ACMHW_VIQSTATUS BIT(5) +#define ACMHW_VOQSTATUS BIT(6) #define RETRY_LIMIT_SHORT_SHIFT 8 #define RETRY_LIMIT_LONG_SHIFT 0 @@ -824,7 +824,7 @@ #define TCR_SAT BIT(24) #define RCR_MXDMA_OFFSET 8 #define RCR_FIFO_OFFSET 13 -#define RCR_OnlyErlPkt BIT(31) +#define RCR_ONLYERLPKT BIT(31) #define CWR 0xDC #define RETRYCTR 0xDE -- cgit v1.2.3 From 92a1aa25c7820123c8486a854812b20e24226d3c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 16:36:43 -0600 Subject: rtlwifi: rtl8723{be,ae}: Remove CamelCase variables If a macro is in CamelCase, it it converted to upper case. Variables and routine names are converted to lower case. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h | 2 +- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c | 8 ++++---- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c | 2 +- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h | 2 +- .../net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h | 18 +++++++++--------- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c | 2 +- drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 14 +++++++------- 7 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h index 586fe70a38e9..42958df6b5d4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h @@ -94,7 +94,7 @@ #define IS_VENDOR_8723A_B_CUT(version) ((IS_8723_SERIES(version))\ ? ((GET_CVID_CUT_VERSION(version) == \ B_CUT_VERSION) ? true : false) : false) -#define IS_81xxC_VENDOR_UMC_B_CUT(version) ((IS_CHIP_VENDOR_UMC(version))\ +#define IS_81XXC_VENDOR_UMC_B_CUT(version) ((IS_CHIP_VENDOR_UMC(version))\ ? ((GET_CVID_CUT_VERSION(version) == \ B_CUT_VERSION) ? true : false) : false) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c index ddebedb8d122..6bab162e1bb8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c @@ -676,7 +676,7 @@ static bool _rtl8712e_init_mac(struct ieee80211_hw *hw) /* HW Power on sequence */ if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, Rtl8723_NIC_ENABLE_FLOW)) + PWR_INTF_PCI_MSK, RTL8723_NIC_ENABLE_FLOW)) return false; bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2); @@ -966,7 +966,7 @@ int rtl8723e_hw_init(struct ieee80211_hw *hw) if (IS_VENDOR_UMC_A_CUT(rtlhal->version)) { rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); - } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { + } else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE); rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31); rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425); @@ -1262,7 +1262,7 @@ static void _rtl8723e_poweroff_adapter(struct ieee80211_hw *hw) /* Combo (PCIe + USB) Card and PCIe-MF Card */ /* 1. Run LPS WL RFOFF flow */ rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, Rtl8723_NIC_LPS_ENTER_FLOW); + PWR_INTF_PCI_MSK, RTL8723_NIC_LPS_ENTER_FLOW); /* 2. 0x1F[7:0] = 0 */ /* turn off RF */ @@ -1282,7 +1282,7 @@ static void _rtl8723e_poweroff_adapter(struct ieee80211_hw *hw) /* HW card disable configuration. */ rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, Rtl8723_NIC_DISABLE_FLOW); + PWR_INTF_PCI_MSK, RTL8723_NIC_DISABLE_FLOW); /* Reset MCU IO Wrapper */ u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c index b4f7b079cd97..54a3aec1dfa7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c @@ -883,7 +883,7 @@ static void _rtl8723e_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel) struct rtl_phy *rtlphy = &rtlpriv->phy; struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { + if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { if (channel == 6 && rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h index 6aa72b5b4359..98bfe02f66d5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h @@ -26,7 +26,7 @@ #define MAX_STALL_TIME 50 #define ANTENNADIVERSITYVALUE 0x80 #define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 +#define reset_cnt_limit 3 #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h index c747c5ea20f9..d9247a8f3039 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h @@ -305,14 +305,14 @@ extern struct wlan_pwr_cfg rtl8723A_leave_lps_flow [RTL8723A_TRANS_LPS_TO_ACT_STEPS + RTL8723A_TRANS_END_STEPS]; /* RTL8723 Power Configuration CMDs for PCIe interface */ -#define Rtl8723_NIC_PWR_ON_FLOW rtl8723A_power_on_flow -#define Rtl8723_NIC_RF_OFF_FLOW rtl8723A_radio_off_flow -#define Rtl8723_NIC_DISABLE_FLOW rtl8723A_card_disable_flow -#define Rtl8723_NIC_ENABLE_FLOW rtl8723A_card_enable_flow -#define Rtl8723_NIC_SUSPEND_FLOW rtl8723A_suspend_flow -#define Rtl8723_NIC_RESUME_FLOW rtl8723A_resume_flow -#define Rtl8723_NIC_PDN_FLOW rtl8723A_hwpdn_flow -#define Rtl8723_NIC_LPS_ENTER_FLOW rtl8723A_enter_lps_flow -#define Rtl8723_NIC_LPS_LEAVE_FLOW rtl8723A_leave_lps_flow +#define RTL8723_NIC_PWR_ON_FLOW rtl8723A_power_on_flow +#define RTL8723_NIC_RF_OFF_FLOW rtl8723A_radio_off_flow +#define RTL8723_NIC_DISABLE_FLOW rtl8723A_card_disable_flow +#define RTL8723_NIC_ENABLE_FLOW rtl8723A_card_enable_flow +#define RTL8723_NIC_SUSPEND_FLOW rtl8723A_suspend_flow +#define RTL8723_NIC_RESUME_FLOW rtl8723A_resume_flow +#define RTL8723_NIC_PDN_FLOW rtl8723A_hwpdn_flow +#define RTL8723_NIC_LPS_ENTER_FLOW rtl8723A_enter_lps_flow +#define RTL8723_NIC_LPS_LEAVE_FLOW rtl8723A_leave_lps_flow #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c index 0d9c0ccf1dc5..4b370410c83c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -153,7 +153,7 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw) return 1; } - if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) + if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) fw_name = "rtlwifi/rtl8723fw_B.bin"; rtlpriv->max_fw_size = 0x6000; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index 7a9891a41d70..979e5bfe5f45 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -297,12 +297,12 @@ void rtl8723be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; break; case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfState; + enum rf_pwrstate rfstate; u32 val_rcr; rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, - (u8 *)(&rfState)); - if (rfState == ERFOFF) { + (u8 *)(&rfstate)); + if (rfstate == ERFOFF) { *((bool *)(val)) = true; } else { val_rcr = rtl_read_dword(rtlpriv, REG_RCR); @@ -742,10 +742,10 @@ static bool _rtl8723be_llt_table_init(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); unsigned short i; u8 txpktbuf_bndy; - u8 maxPage; + u8 maxpage; bool status; - maxPage = 255; + maxpage = 255; txpktbuf_bndy = 245; rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, @@ -770,13 +770,13 @@ static bool _rtl8723be_llt_table_init(struct ieee80211_hw *hw) if (!status) return status; - for (i = txpktbuf_bndy; i < maxPage; i++) { + for (i = txpktbuf_bndy; i < maxpage; i++) { status = _rtl8723be_llt_write(hw, i, (i + 1)); if (!status) return status; } - status = _rtl8723be_llt_write(hw, maxPage, txpktbuf_bndy); + status = _rtl8723be_llt_write(hw, maxpage, txpktbuf_bndy); if (!status) return status; -- cgit v1.2.3 From 9c66a7e5d39c410a5da1bec868d3b1442e0b5f17 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Feb 2019 16:36:44 -0600 Subject: rtlwifi: rtl8821ae: Remove CamelCase variables If a macro is in CamelCase, it it converted to upper case. Variables and routine names are converted to lower case. The following checkpatch exceptions are also fixed: WARNING: line over 80 characters #316: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c:1751: + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1rsvdpageloc2, GTKEXT_PG); CHECK: spaces preferred around that '+' (ctx:VxV) #357: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c:2591: + (eeaddr+1), hwinfo[eeaddr+1]); ^ CHECK: spaces preferred around that '+' (ctx:VxV) #357: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c:2591: + (eeaddr+1), hwinfo[eeaddr+1]); ^ CHECK: spaces preferred around that '+' (ctx:VxV) #358: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c:2592: + if (0xFF == hwinfo[eeaddr+1]) /*YJ,add,120316*/ ^ WARNING: Comparisons should place the constant on the right side of the test #358: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c:2592: + if (0xFF == hwinfo[eeaddr+1]) /*YJ,add,120316*/ CHECK: spaces preferred around that '&' (ctx:VxV) #501: FILE: drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c:2666: + pwrinfo24g->bw40_diff[rfpath][txcount] = (hwinfo[eeaddr]&0xf0) >> 4; ^ Note that not all checkpatch exceptions are addressed. Those will be handled in later patches. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- .../net/wireless/realtek/rtlwifi/rtl8821ae/dm.h | 10 +- .../net/wireless/realtek/rtlwifi/rtl8821ae/fw.c | 102 ++++----- .../net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | 234 ++++++++++----------- .../net/wireless/realtek/rtlwifi/rtl8821ae/phy.c | 132 ++++++------ .../net/wireless/realtek/rtlwifi/rtl8821ae/phy.h | 4 +- .../net/wireless/realtek/rtlwifi/rtl8821ae/reg.h | 34 +-- .../net/wireless/realtek/rtlwifi/rtl8821ae/table.c | 184 ++++++++-------- 7 files changed, 350 insertions(+), 350 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h index 35493b03c8ad..137ed735d80d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h @@ -70,11 +70,11 @@ #define DM_REG_CCK_CCA_CNT_11N 0xA60 #define DM_REG_BB_PWR_SAV4_11N 0xA74 /*PAGE B */ -#define DM_REG_LNA_SWITCH_11N 0xB2C -#define DM_REG_PATH_SWITCH_11N 0xB30 -#define DM_REG_RSSI_CTRL_11N 0xB38 -#define DM_REG_CONFIG_ANTA_11N 0xB68 -#define DM_REG_RSSI_BT_11N 0xB9C +#define DM_REG_LNA_SWITCH_11N 0XB2C +#define DM_REG_PATH_SWITCH_11N 0XB30 +#define DM_REG_RSSI_CTRL_11N 0XB38 +#define DM_REG_CONFIG_ANTA_11N 0XB68 +#define DM_REG_RSSI_BT_11N 0XB9C /*PAGE C */ #define DM_REG_OFDM_FA_HOLDC_11N 0xC00 #define DM_REG_RX_PATH_11N 0xC04 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c index b677bd4a844f..dc0eb692088f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c @@ -822,9 +822,9 @@ static u8 reserved_page_packet_8821[TOTAL_RESERVED_PKT_LEN_8821] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* page 3: qos null data */ - 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7, + 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -855,9 +855,9 @@ static u8 reserved_page_packet_8821[TOTAL_RESERVED_PKT_LEN_8821] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* page 4: BT qos null data */ - 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7, + 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -889,9 +889,9 @@ static u8 reserved_page_packet_8821[TOTAL_RESERVED_PKT_LEN_8821] = { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* page 5~7 is for wowlan */ /* page 5: ARP resp */ - 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7, + 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00, 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00, @@ -993,7 +993,7 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = { /* page 0: beacon */ 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x60, 0x00, + 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x20, 0x04, 0x00, 0x03, 0x32, 0x31, 0x35, 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C, @@ -1056,8 +1056,8 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* page 1: ps-poll */ - 0xA4, 0x10, 0x09, 0xC0, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0xA4, 0x10, 0x09, 0xC0, 0x84, 0xC9, 0XB2, 0xA7, + 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1121,9 +1121,9 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* page 2: null data */ - 0x48, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0x48, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7, + 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1186,9 +1186,9 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* page 3: Qos null data */ - 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7, + 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1251,9 +1251,9 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* page 4: BT Qos null data */ - 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7, + 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1317,9 +1317,9 @@ static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* page 5~7 is for wowlan */ /* page 5: ARP resp */ - 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0XB2, 0xA7, + 0XB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0XB2, 0xA7, 0XB3, 0x6E, 0x00, 0x00, 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00, @@ -1521,8 +1521,8 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, struct sk_buff *skb = NULL; u32 totalpacketlen; bool rtstatus; - u8 u1RsvdPageLoc[5] = { 0 }; - u8 u1RsvdPageLoc2[7] = { 0 }; + u8 u1rsvdpageloc[5] = { 0 }; + u8 u1rsvdpageloc2[7] = { 0 }; bool b_dlok = false; u8 *beacon; u8 *p_pspoll; @@ -1552,7 +1552,7 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); /*-------------------------------------------------------- * (3) null data @@ -1563,7 +1563,7 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); /*--------------------------------------------------------- * (4) Qos null data @@ -1574,7 +1574,7 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1RsvdPageLoc, QOSNULL_PG); + SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOSNULL_PG); /*--------------------------------------------------------- * (5) BT Qos null data @@ -1585,7 +1585,7 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr); SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1RsvdPageLoc, BT_QOSNULL_PG); + SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOSNULL_PG); if (!dl_whole_packets) { totalpacketlen = 512 * (BT_QOSNULL_PG + 1) - 40; @@ -1600,20 +1600,20 @@ void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_HDR_ADDRESS2(arpresp, mac->mac_addr); SET_80211_HDR_ADDRESS3(arpresp, mac->bssid); - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1RsvdPageLoc2, ARPRESP_PG); + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1rsvdpageloc2, ARPRESP_PG); /*--------------------------------------------------------- * (7) Remote Wake Ctrl *---------------------------------------------------------- */ - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1RsvdPageLoc2, + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1rsvdpageloc2, REMOTE_PG); /*--------------------------------------------------------- * (8) GTK Ext Memory *---------------------------------------------------------- */ - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1RsvdPageLoc2, GTKEXT_PG); + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1rsvdpageloc2, GTKEXT_PG); totalpacketlen = TOTAL_RESERVED_PKT_LEN_8812 - 40; @@ -1632,14 +1632,14 @@ out: if (!b_dl_finished && b_dlok) { RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 5); + "H2C_RSVDPAGE:\n", u1rsvdpageloc, 5); rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RSVDPAGE, - sizeof(u1RsvdPageLoc), u1RsvdPageLoc); + sizeof(u1rsvdpageloc), u1rsvdpageloc); if (dl_whole_packets) { RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "wowlan H2C_RSVDPAGE:\n", u1RsvdPageLoc2, 7); + "wowlan H2C_RSVDPAGE:\n", u1rsvdpageloc2, 7); rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_RSVDPAGE, - sizeof(u1RsvdPageLoc2), u1RsvdPageLoc2); + sizeof(u1rsvdpageloc2), u1rsvdpageloc2); } } @@ -1656,8 +1656,8 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, struct sk_buff *skb = NULL; u32 totalpacketlen; bool rtstatus; - u8 u1RsvdPageLoc[5] = { 0 }; - u8 u1RsvdPageLoc2[7] = { 0 }; + u8 u1rsvdpageloc[5] = { 0 }; + u8 u1rsvdpageloc2[7] = { 0 }; bool b_dlok = false; u8 *beacon; u8 *p_pspoll; @@ -1687,7 +1687,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); /*-------------------------------------------------------- * (3) null data @@ -1698,7 +1698,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); /*--------------------------------------------------------- * (4) Qos null data @@ -1709,7 +1709,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1RsvdPageLoc, QOSNULL_PG); + SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1rsvdpageloc, QOSNULL_PG); /*--------------------------------------------------------- * (5) Qos null data @@ -1720,7 +1720,7 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_HDR_ADDRESS2(btqosnull, mac->mac_addr); SET_80211_HDR_ADDRESS3(btqosnull, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1RsvdPageLoc, BT_QOSNULL_PG); + SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1rsvdpageloc, BT_QOSNULL_PG); if (!dl_whole_packets) { totalpacketlen = 256 * (BT_QOSNULL_PG + 1) - 40; @@ -1735,20 +1735,20 @@ void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, SET_80211_HDR_ADDRESS2(arpresp, mac->mac_addr); SET_80211_HDR_ADDRESS3(arpresp, mac->bssid); - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1RsvdPageLoc2, ARPRESP_PG); + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1rsvdpageloc2, ARPRESP_PG); /*--------------------------------------------------------- * (7) Remote Wake Ctrl *---------------------------------------------------------- */ - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1RsvdPageLoc2, + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1rsvdpageloc2, REMOTE_PG); /*--------------------------------------------------------- * (8) GTK Ext Memory *---------------------------------------------------------- */ - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1RsvdPageLoc2, GTKEXT_PG); + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1rsvdpageloc2, GTKEXT_PG); totalpacketlen = TOTAL_RESERVED_PKT_LEN_8821 - 40; @@ -1770,16 +1770,16 @@ out: RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Set RSVD page location to Fw.\n"); RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 5); + "H2C_RSVDPAGE:\n", u1rsvdpageloc, 5); rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RSVDPAGE, - sizeof(u1RsvdPageLoc), u1RsvdPageLoc); + sizeof(u1rsvdpageloc), u1rsvdpageloc); if (dl_whole_packets) { RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "wowlan H2C_RSVDPAGE:\n", - u1RsvdPageLoc2, 7); + u1rsvdpageloc2, 7); rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_RSVDPAGE, - sizeof(u1RsvdPageLoc2), - u1RsvdPageLoc2); + sizeof(u1rsvdpageloc2), + u1rsvdpageloc2); } } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index e786aa89d4b0..198d419ebb9c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -2584,50 +2584,50 @@ static void _rtl8821ae_read_power_value_fromprom(struct ieee80211_hw *hw, u8 *hwinfo) { struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 rfPath, eeAddr = EEPROM_TX_PWR_INX, group, TxCount = 0; + u32 rfpath, eeaddr = EEPROM_TX_PWR_INX, group, txcount = 0; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "hal_ReadPowerValueFromPROM8821ae(): hwinfo[0x%x]=0x%x\n", - (eeAddr+1), hwinfo[eeAddr+1]); - if (0xFF == hwinfo[eeAddr+1]) /*YJ,add,120316*/ + (eeaddr + 1), hwinfo[eeaddr + 1]); + if (hwinfo[eeaddr + 1] == 0xFF) /*YJ,add,120316*/ autoload_fail = true; if (autoload_fail) { RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "auto load fail : Use Default value!\n"); - for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) { + for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) { /*2.4G default value*/ for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pwrinfo24g->index_cck_base[rfPath][group] = 0x2D; - pwrinfo24g->index_bw40_base[rfPath][group] = 0x2D; + pwrinfo24g->index_cck_base[rfpath][group] = 0x2D; + pwrinfo24g->index_bw40_base[rfpath][group] = 0x2D; } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrinfo24g->bw20_diff[rfPath][0] = 0x02; - pwrinfo24g->ofdm_diff[rfPath][0] = 0x04; + for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { + if (txcount == 0) { + pwrinfo24g->bw20_diff[rfpath][0] = 0x02; + pwrinfo24g->ofdm_diff[rfpath][0] = 0x04; } else { - pwrinfo24g->bw20_diff[rfPath][TxCount] = 0xFE; - pwrinfo24g->bw40_diff[rfPath][TxCount] = 0xFE; - pwrinfo24g->cck_diff[rfPath][TxCount] = 0xFE; - pwrinfo24g->ofdm_diff[rfPath][TxCount] = 0xFE; + pwrinfo24g->bw20_diff[rfpath][txcount] = 0xFE; + pwrinfo24g->bw40_diff[rfpath][txcount] = 0xFE; + pwrinfo24g->cck_diff[rfpath][txcount] = 0xFE; + pwrinfo24g->ofdm_diff[rfpath][txcount] = 0xFE; } } /*5G default value*/ for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) - pwrinfo5g->index_bw40_base[rfPath][group] = 0x2A; - - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrinfo5g->ofdm_diff[rfPath][0] = 0x04; - pwrinfo5g->bw20_diff[rfPath][0] = 0x00; - pwrinfo5g->bw80_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw160_diff[rfPath][0] = 0xFE; + pwrinfo5g->index_bw40_base[rfpath][group] = 0x2A; + + for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { + if (txcount == 0) { + pwrinfo5g->ofdm_diff[rfpath][0] = 0x04; + pwrinfo5g->bw20_diff[rfpath][0] = 0x00; + pwrinfo5g->bw80_diff[rfpath][0] = 0xFE; + pwrinfo5g->bw160_diff[rfpath][0] = 0xFE; } else { - pwrinfo5g->ofdm_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw20_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw40_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw80_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw160_diff[rfPath][0] = 0xFE; + pwrinfo5g->ofdm_diff[rfpath][0] = 0xFE; + pwrinfo5g->bw20_diff[rfpath][0] = 0xFE; + pwrinfo5g->bw40_diff[rfpath][0] = 0xFE; + pwrinfo5g->bw80_diff[rfpath][0] = 0xFE; + pwrinfo5g->bw160_diff[rfpath][0] = 0xFE; } } } @@ -2636,112 +2636,112 @@ static void _rtl8821ae_read_power_value_fromprom(struct ieee80211_hw *hw, rtl_priv(hw)->efuse.txpwr_fromeprom = true; - for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) { + for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) { /*2.4G default value*/ for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pwrinfo24g->index_cck_base[rfPath][group] = hwinfo[eeAddr++]; - if (pwrinfo24g->index_cck_base[rfPath][group] == 0xFF) - pwrinfo24g->index_cck_base[rfPath][group] = 0x2D; + pwrinfo24g->index_cck_base[rfpath][group] = hwinfo[eeaddr++]; + if (pwrinfo24g->index_cck_base[rfpath][group] == 0xFF) + pwrinfo24g->index_cck_base[rfpath][group] = 0x2D; } for (group = 0 ; group < MAX_CHNL_GROUP_24G - 1; group++) { - pwrinfo24g->index_bw40_base[rfPath][group] = hwinfo[eeAddr++]; - if (pwrinfo24g->index_bw40_base[rfPath][group] == 0xFF) - pwrinfo24g->index_bw40_base[rfPath][group] = 0x2D; + pwrinfo24g->index_bw40_base[rfpath][group] = hwinfo[eeaddr++]; + if (pwrinfo24g->index_bw40_base[rfpath][group] == 0xFF) + pwrinfo24g->index_bw40_base[rfpath][group] = 0x2D; } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrinfo24g->bw40_diff[rfPath][TxCount] = 0; + for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { + if (txcount == 0) { + pwrinfo24g->bw40_diff[rfpath][txcount] = 0; /*bit sign number to 8 bit sign number*/ - pwrinfo24g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; - if (pwrinfo24g->bw20_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->bw20_diff[rfPath][TxCount] |= 0xF0; + pwrinfo24g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; + if (pwrinfo24g->bw20_diff[rfpath][txcount] & BIT(3)) + pwrinfo24g->bw20_diff[rfpath][txcount] |= 0xF0; /*bit sign number to 8 bit sign number*/ - pwrinfo24g->ofdm_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo24g->ofdm_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->ofdm_diff[rfPath][TxCount] |= 0xF0; + pwrinfo24g->ofdm_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); + if (pwrinfo24g->ofdm_diff[rfpath][txcount] & BIT(3)) + pwrinfo24g->ofdm_diff[rfpath][txcount] |= 0xF0; - pwrinfo24g->cck_diff[rfPath][TxCount] = 0; - eeAddr++; + pwrinfo24g->cck_diff[rfpath][txcount] = 0; + eeaddr++; } else { - pwrinfo24g->bw40_diff[rfPath][TxCount] = (hwinfo[eeAddr]&0xf0) >> 4; - if (pwrinfo24g->bw40_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->bw40_diff[rfPath][TxCount] |= 0xF0; + pwrinfo24g->bw40_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; + if (pwrinfo24g->bw40_diff[rfpath][txcount] & BIT(3)) + pwrinfo24g->bw40_diff[rfpath][txcount] |= 0xF0; - pwrinfo24g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo24g->bw20_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->bw20_diff[rfPath][TxCount] |= 0xF0; + pwrinfo24g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); + if (pwrinfo24g->bw20_diff[rfpath][txcount] & BIT(3)) + pwrinfo24g->bw20_diff[rfpath][txcount] |= 0xF0; - eeAddr++; + eeaddr++; - pwrinfo24g->ofdm_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; - if (pwrinfo24g->ofdm_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->ofdm_diff[rfPath][TxCount] |= 0xF0; + pwrinfo24g->ofdm_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; + if (pwrinfo24g->ofdm_diff[rfpath][txcount] & BIT(3)) + pwrinfo24g->ofdm_diff[rfpath][txcount] |= 0xF0; - pwrinfo24g->cck_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo24g->cck_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->cck_diff[rfPath][TxCount] |= 0xF0; + pwrinfo24g->cck_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); + if (pwrinfo24g->cck_diff[rfpath][txcount] & BIT(3)) + pwrinfo24g->cck_diff[rfpath][txcount] |= 0xF0; - eeAddr++; + eeaddr++; } } /*5G default value*/ for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) { - pwrinfo5g->index_bw40_base[rfPath][group] = hwinfo[eeAddr++]; - if (pwrinfo5g->index_bw40_base[rfPath][group] == 0xFF) - pwrinfo5g->index_bw40_base[rfPath][group] = 0xFE; + pwrinfo5g->index_bw40_base[rfpath][group] = hwinfo[eeaddr++]; + if (pwrinfo5g->index_bw40_base[rfpath][group] == 0xFF) + pwrinfo5g->index_bw40_base[rfpath][group] = 0xFE; } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrinfo5g->bw40_diff[rfPath][TxCount] = 0; + for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { + if (txcount == 0) { + pwrinfo5g->bw40_diff[rfpath][txcount] = 0; - pwrinfo5g->bw20_diff[rfPath][0] = (hwinfo[eeAddr] & 0xf0) >> 4; - if (pwrinfo5g->bw20_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw20_diff[rfPath][TxCount] |= 0xF0; + pwrinfo5g->bw20_diff[rfpath][0] = (hwinfo[eeaddr] & 0xf0) >> 4; + if (pwrinfo5g->bw20_diff[rfpath][txcount] & BIT(3)) + pwrinfo5g->bw20_diff[rfpath][txcount] |= 0xF0; - pwrinfo5g->ofdm_diff[rfPath][0] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo5g->ofdm_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->ofdm_diff[rfPath][TxCount] |= 0xF0; + pwrinfo5g->ofdm_diff[rfpath][0] = (hwinfo[eeaddr] & 0x0f); + if (pwrinfo5g->ofdm_diff[rfpath][txcount] & BIT(3)) + pwrinfo5g->ofdm_diff[rfpath][txcount] |= 0xF0; - eeAddr++; + eeaddr++; } else { - pwrinfo5g->bw40_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; - if (pwrinfo5g->bw40_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw40_diff[rfPath][TxCount] |= 0xF0; + pwrinfo5g->bw40_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; + if (pwrinfo5g->bw40_diff[rfpath][txcount] & BIT(3)) + pwrinfo5g->bw40_diff[rfpath][txcount] |= 0xF0; - pwrinfo5g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo5g->bw20_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw20_diff[rfPath][TxCount] |= 0xF0; + pwrinfo5g->bw20_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); + if (pwrinfo5g->bw20_diff[rfpath][txcount] & BIT(3)) + pwrinfo5g->bw20_diff[rfpath][txcount] |= 0xF0; - eeAddr++; + eeaddr++; } } - pwrinfo5g->ofdm_diff[rfPath][1] = (hwinfo[eeAddr] & 0xf0) >> 4; - pwrinfo5g->ofdm_diff[rfPath][2] = (hwinfo[eeAddr] & 0x0f); + pwrinfo5g->ofdm_diff[rfpath][1] = (hwinfo[eeaddr] & 0xf0) >> 4; + pwrinfo5g->ofdm_diff[rfpath][2] = (hwinfo[eeaddr] & 0x0f); - eeAddr++; + eeaddr++; - pwrinfo5g->ofdm_diff[rfPath][3] = (hwinfo[eeAddr] & 0x0f); + pwrinfo5g->ofdm_diff[rfpath][3] = (hwinfo[eeaddr] & 0x0f); - eeAddr++; + eeaddr++; - for (TxCount = 1; TxCount < MAX_TX_COUNT; TxCount++) { - if (pwrinfo5g->ofdm_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->ofdm_diff[rfPath][TxCount] |= 0xF0; + for (txcount = 1; txcount < MAX_TX_COUNT; txcount++) { + if (pwrinfo5g->ofdm_diff[rfpath][txcount] & BIT(3)) + pwrinfo5g->ofdm_diff[rfpath][txcount] |= 0xF0; } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - pwrinfo5g->bw80_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; + for (txcount = 0; txcount < MAX_TX_COUNT; txcount++) { + pwrinfo5g->bw80_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0xf0) >> 4; /* 4bit sign number to 8 bit sign number */ - if (pwrinfo5g->bw80_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw80_diff[rfPath][TxCount] |= 0xF0; + if (pwrinfo5g->bw80_diff[rfpath][txcount] & BIT(3)) + pwrinfo5g->bw80_diff[rfpath][txcount] |= 0xF0; /* 4bit sign number to 8 bit sign number */ - pwrinfo5g->bw160_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo5g->bw160_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw160_diff[rfPath][TxCount] |= 0xF0; + pwrinfo5g->bw160_diff[rfpath][txcount] = (hwinfo[eeaddr] & 0x0f); + if (pwrinfo5g->bw160_diff[rfpath][txcount] & BIT(3)) + pwrinfo5g->bw160_diff[rfpath][txcount] |= 0xF0; - eeAddr++; + eeaddr++; } } } @@ -2908,8 +2908,8 @@ static void _rtl8812ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, struct rtl_hal *rtlhal = rtl_hal(rtlpriv); if (!autoload_fail) { - rtlhal->pa_type_2g = hwinfo[0xBC]; - rtlhal->lna_type_2g = hwinfo[0xBD]; + rtlhal->pa_type_2g = hwinfo[0XBC]; + rtlhal->lna_type_2g = hwinfo[0XBD]; if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) { rtlhal->pa_type_2g = 0; rtlhal->lna_type_2g = 0; @@ -2921,8 +2921,8 @@ static void _rtl8812ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, (rtlhal->lna_type_2g & BIT(3))) ? 1 : 0; - rtlhal->pa_type_5g = hwinfo[0xBC]; - rtlhal->lna_type_5g = hwinfo[0xBF]; + rtlhal->pa_type_5g = hwinfo[0XBC]; + rtlhal->lna_type_5g = hwinfo[0XBF]; if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) { rtlhal->pa_type_5g = 0; rtlhal->lna_type_5g = 0; @@ -2947,18 +2947,18 @@ static void _rtl8812ae_read_amplifier_type(struct ieee80211_hw *hw, u8 *hwinfo, struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 ext_type_pa_2g_a = (hwinfo[0xBD] & BIT(2)) >> 2; /* 0xBD[2] */ - u8 ext_type_pa_2g_b = (hwinfo[0xBD] & BIT(6)) >> 6; /* 0xBD[6] */ - u8 ext_type_pa_5g_a = (hwinfo[0xBF] & BIT(2)) >> 2; /* 0xBF[2] */ - u8 ext_type_pa_5g_b = (hwinfo[0xBF] & BIT(6)) >> 6; /* 0xBF[6] */ - /* 0xBD[1:0] */ - u8 ext_type_lna_2g_a = (hwinfo[0xBD] & (BIT(1) | BIT(0))) >> 0; - /* 0xBD[5:4] */ - u8 ext_type_lna_2g_b = (hwinfo[0xBD] & (BIT(5) | BIT(4))) >> 4; - /* 0xBF[1:0] */ - u8 ext_type_lna_5g_a = (hwinfo[0xBF] & (BIT(1) | BIT(0))) >> 0; - /* 0xBF[5:4] */ - u8 ext_type_lna_5g_b = (hwinfo[0xBF] & (BIT(5) | BIT(4))) >> 4; + u8 ext_type_pa_2g_a = (hwinfo[0XBD] & BIT(2)) >> 2; /* 0XBD[2] */ + u8 ext_type_pa_2g_b = (hwinfo[0XBD] & BIT(6)) >> 6; /* 0XBD[6] */ + u8 ext_type_pa_5g_a = (hwinfo[0XBF] & BIT(2)) >> 2; /* 0XBF[2] */ + u8 ext_type_pa_5g_b = (hwinfo[0XBF] & BIT(6)) >> 6; /* 0XBF[6] */ + /* 0XBD[1:0] */ + u8 ext_type_lna_2g_a = (hwinfo[0XBD] & (BIT(1) | BIT(0))) >> 0; + /* 0XBD[5:4] */ + u8 ext_type_lna_2g_b = (hwinfo[0XBD] & (BIT(5) | BIT(4))) >> 4; + /* 0XBF[1:0] */ + u8 ext_type_lna_5g_a = (hwinfo[0XBF] & (BIT(1) | BIT(0))) >> 0; + /* 0XBF[5:4] */ + u8 ext_type_lna_5g_b = (hwinfo[0XBF] & (BIT(5) | BIT(4))) >> 4; _rtl8812ae_read_pa_type(hw, hwinfo, autoload_fail); @@ -2986,8 +2986,8 @@ static void _rtl8821ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, struct rtl_hal *rtlhal = rtl_hal(rtlpriv); if (!autoload_fail) { - rtlhal->pa_type_2g = hwinfo[0xBC]; - rtlhal->lna_type_2g = hwinfo[0xBD]; + rtlhal->pa_type_2g = hwinfo[0XBC]; + rtlhal->lna_type_2g = hwinfo[0XBD]; if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) { rtlhal->pa_type_2g = 0; rtlhal->lna_type_2g = 0; @@ -2995,8 +2995,8 @@ static void _rtl8821ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, rtlhal->external_pa_2g = (rtlhal->pa_type_2g & BIT(5)) ? 1 : 0; rtlhal->external_lna_2g = (rtlhal->lna_type_2g & BIT(7)) ? 1 : 0; - rtlhal->pa_type_5g = hwinfo[0xBC]; - rtlhal->lna_type_5g = hwinfo[0xBF]; + rtlhal->pa_type_5g = hwinfo[0XBC]; + rtlhal->lna_type_5g = hwinfo[0XBF]; if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) { rtlhal->pa_type_5g = 0; rtlhal->lna_type_5g = 0; @@ -4011,10 +4011,10 @@ void rtl8821ae_add_wowlan_pattern(struct ieee80211_hw *hw, rtl_write_byte(rtlpriv, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT); for (addr = 0; addr < WKFMCAM_ADDR_NUM; addr++) { /* Set Rx packet buffer offset. - * RxBufer pointer increases 1, + * RXBufer pointer increases 1, * we can access 8 bytes in Rx packet buffer. * CAM start offset (unit: 1 byte) = index*WKFMCAM_SIZE - * RxBufer addr = (CAM start offset + + * RXBufer addr = (CAM start offset + * per entry offset of a WKFM CAM)/8 * * index: The index of the wake up frame mask * * WKFMCAM_SIZE: the total size of one WKFM CAM diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c index 7b80a2b4bbe1..408af144098e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -453,7 +453,7 @@ u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, const s8 auto_temp = -1; RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "===> PHY_GetTxBBSwing_8812A, bbSwing_2G: %d, bbSwing_5G: %d,autoload_failflag=%d.\n", + "===> PHY_GetTXBBSwing_8812A, bbSwing_2G: %d, bbSwing_5G: %d,autoload_failflag=%d.\n", (int)swing_2g, (int)swing_5g, (int)rtlefuse->autoload_failflag); @@ -534,7 +534,7 @@ u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, swing_a = (swing & 0x3) >> 0; /* 0xC6/C7[1:0] */ swing_b = (swing & 0xC) >> 2; /* 0xC6/C7[3:2] */ RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "===> PHY_GetTxBBSwing_8812A, swingA: 0x%X, swingB: 0x%X\n", + "===> PHY_GetTXBBSwing_8812A, swingA: 0x%X, swingB: 0x%X\n", swing_a, swing_b); /* 3 Path-A */ @@ -592,7 +592,7 @@ u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, } RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "<=== PHY_GetTxBBSwing_8812A, out = 0x%X\n", out); + "<=== PHY_GetTXBBSwing_8812A, out = 0x%X\n", out); return out; } @@ -1056,52 +1056,52 @@ static void _rtl8821ae_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &rtlpriv->phy; - u16 rawValue = 0; + u16 rawvalue = 0; u8 base = 0, path = 0; for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) { - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][0] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][0] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, CCK, RF_1TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][2] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][2] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, OFDM, RF_1TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][4] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][4] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS0_MCS7, RF_1TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][6] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][6] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS8_MCS15, RF_2TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][8] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][8] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][11] >> 8) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][11] >> 8) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][2] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][2] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, OFDM, RF_1TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][4] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][4] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, HT_MCS0_MCS7, RF_1TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][6] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][6] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, HT_MCS8_MCS15, RF_2TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][8] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][8] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base); - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][11] >> 8) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][11] >> 8) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base); } } @@ -1358,7 +1358,7 @@ static void _rtl8812ae_phy_convert_txpower_limit_to_power_index(struct ieee80211 } RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "TxPwrLimit_2_4G[regulation %d][bw %d][rateSection %d][channel %d] = %d\n(TxPwrLimit in dBm %d - BW40PwrLmt2_4G[channel %d][rfPath %d] %d)\n", + "TxPwrLimit_2_4G[regulation %d][bw %d][rateSection %d][channel %d] = %d\n(TxPwrLimit in dBm %d - BW40PwrLmt2_4G[channel %d][rfpath %d] %d)\n", regulation, bw, rate_section, channel, rtlphy->txpwr_limit_2_4g[regulation][bw] [rate_section][channel][rf_path], (temp_pwrlmt == 63) @@ -1423,7 +1423,7 @@ static void _rtl8812ae_phy_convert_txpower_limit_to_power_index(struct ieee80211 } RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "TxPwrLimit_5G[regulation %d][bw %d][rateSection %d][channel %d] =%d\n(TxPwrLimit in dBm %d - BW40PwrLmt5G[chnl group %d][rfPath %d] %d)\n", + "TxPwrLimit_5G[regulation %d][bw %d][rateSection %d][channel %d] =%d\n(TxPwrLimit in dBm %d - BW40PwrLmt5G[chnl group %d][rfpath %d] %d)\n", regulation, bw, rate_section, channel, rtlphy->txpwr_limit_5g[regulation] [bw][rate_section][channel][rf_path], @@ -1473,106 +1473,106 @@ static void _rtl8821ae_phy_convert_txpower_dbm_to_relative_value(struct ieee8021 { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 base = 0, rfPath = 0; + u8 base = 0, rfpath = 0; - for (rfPath = RF90_PATH_A; rfPath <= RF90_PATH_B; ++rfPath) { - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, CCK); + for (rfpath = RF90_PATH_A; rfpath <= RF90_PATH_B; ++rfpath) { + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_1TX, CCK); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][0], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][0], 0, 3, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, OFDM); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_1TX, OFDM); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][1], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][1], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][2], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][2], 0, 3, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, HT_MCS0_MCS7); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_1TX, HT_MCS0_MCS7); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][3], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][3], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][4], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][4], 0, 3, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_2TX, HT_MCS8_MCS15); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_2TX, HT_MCS8_MCS15); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][5], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][5], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][6], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][6], 0, 3, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, VHT_1SSMCS0_1SSMCS9); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_1TX, VHT_1SSMCS0_1SSMCS9); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][7], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][7], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][8], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][8], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][9], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][9], 0, 1, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_2TX, VHT_2SSMCS0_2SSMCS9); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, RF_2TX, VHT_2SSMCS0_2SSMCS9); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][9], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][9], 2, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][10], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][10], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][11], + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][11], 0, 3, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, OFDM); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_1TX, OFDM); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][1], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][1], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][2], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][2], 0, 3, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, HT_MCS0_MCS7); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_1TX, HT_MCS0_MCS7); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][3], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][3], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][4], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][4], 0, 3, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_2TX, HT_MCS8_MCS15); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_2TX, HT_MCS8_MCS15); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][5], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_2TX][5], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][6], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_2TX][6], 0, 3, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, VHT_1SSMCS0_1SSMCS9); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_1TX, VHT_1SSMCS0_1SSMCS9); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][7], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][7], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][8], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][8], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][9], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][9], 0, 1, base); - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_2TX, VHT_2SSMCS0_2SSMCS9); + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfpath, RF_2TX, VHT_2SSMCS0_2SSMCS9); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][9], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_1TX][9], 2, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][10], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_2TX][10], 0, 3, base); _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][11], + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfpath][RF_2TX][11], 0, 3, base); } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h index 799b7cfed542..35b7d0f70125 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h @@ -37,9 +37,9 @@ #define LOOP_LIMIT 5 #define MAX_STALL_TIME 50 -#define AntennaDiversityValue 0x80 +#define ANTENNADIVERSITYVALUE 0x80 #define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 +#define RESET_CNT_LIMIT 3 #define IQK_ADDA_REG_NUM 16 #define IQK_MAC_REG_NUM 4 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h index 85e73a0686fa..7d833b72c7ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h @@ -674,7 +674,7 @@ #define EEPROM_CHANNEL_PLAN_TELEC 0x8 #define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 #define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_NCC 0XB #define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 #define EEPROM_CID_DEFAULT 0x0 @@ -696,10 +696,10 @@ #define EEPROM_TX_PWR_INX 0x10 -#define EEPROM_CHANNELPLAN 0xB8 -#define EEPROM_XTAL_8821AE 0xB9 -#define EEPROM_THERMAL_METER 0xBA -#define EEPROM_IQK_LCK_88E 0xBB +#define EEPROM_CHANNELPLAN 0XB8 +#define EEPROM_XTAL_8821AE 0XB9 +#define EEPROM_THERMAL_METER 0XBA +#define EEPROM_IQK_LCK_88E 0XBB #define EEPROM_RF_BOARD_OPTION 0xC1 #define EEPROM_RF_FEATURE_OPTION_88E 0xC2 @@ -993,7 +993,7 @@ #define _LBMODE(x) (((x) & 0xF) << 24) #define MASK_LBMODE 0xF000000 #define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB +#define LOOPBACK_IMMEDIATELY 0XB #define LOOPBACK_MAC_DELAY 0x3 #define LOOPBACK_PHY 0x1 #define LOOPBACK_DMA 0x7 @@ -1408,7 +1408,7 @@ #define RCCK0_FACOUNTERUPPER 0xa58 #define RCCK0_CCA_CNT 0xa60 -/* PageB(0xB00) */ +/* PageB(0XB00) */ #define RPDP_ANTA 0xb00 #define RPDP_ANTA_4 0xb04 #define RPDP_ANTA_8 0xb08 @@ -1455,16 +1455,16 @@ #define RPM_RX3_ANTB 0xbf8 /*RSSI Dump*/ -#define RA_RSSI_DUMP 0xBF0 -#define RB_RSSI_DUMP 0xBF1 -#define RS1_RX_EVM_DUMP 0xBF4 -#define RS2_RX_EVM_DUMP 0xBF5 -#define RA_RX_SNR_DUMP 0xBF6 -#define RB_RX_SNR_DUMP 0xBF7 -#define RA_CFO_SHORT_DUMP 0xBF8 -#define RB_CFO_SHORT_DUMP 0xBFA -#define RA_CFO_LONG_DUMP 0xBEC -#define RB_CFO_LONG_DUMP 0xBEE +#define RA_RSSI_DUMP 0XBF0 +#define RB_RSSI_DUMP 0XBF1 +#define RS1_RX_EVM_DUMP 0XBF4 +#define RS2_RX_EVM_DUMP 0XBF5 +#define RA_RX_SNR_DUMP 0XBF6 +#define RB_RX_SNR_DUMP 0XBF7 +#define RA_CFO_SHORT_DUMP 0XBF8 +#define RB_CFO_SHORT_DUMP 0XBFA +#define RA_CFO_LONG_DUMP 0XBEC +#define RB_CFO_LONG_DUMP 0XBEE /*Page C*/ #define ROFDM0_LSTF 0xc00 diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c index 8ed77d769592..85093b3e5373 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c @@ -111,30 +111,30 @@ u32 RTL8812AE_PHY_REG_ARRAY[] = { 0xA7C, 0x225B0606, 0xA80, 0x218075B2, 0xA84, 0x001F8C80, - 0xB00, 0x03100000, - 0xB04, 0x0000B000, - 0xB08, 0xAE0201EB, - 0xB0C, 0x01003207, - 0xB10, 0x00009807, - 0xB14, 0x01000000, - 0xB18, 0x00000002, - 0xB1C, 0x00000002, - 0xB20, 0x0000001F, - 0xB24, 0x03020100, - 0xB28, 0x07060504, - 0xB2C, 0x0B0A0908, - 0xB30, 0x0F0E0D0C, - 0xB34, 0x13121110, - 0xB38, 0x17161514, - 0xB3C, 0x0000003A, - 0xB40, 0x00000000, - 0xB44, 0x00000000, - 0xB48, 0x13000032, - 0xB4C, 0x48080000, - 0xB50, 0x00000000, - 0xB54, 0x00000000, - 0xB58, 0x00000000, - 0xB5C, 0x00000000, + 0XB00, 0x03100000, + 0XB04, 0x0000B000, + 0XB08, 0xAE0201EB, + 0XB0C, 0x01003207, + 0XB10, 0x00009807, + 0XB14, 0x01000000, + 0XB18, 0x00000002, + 0XB1C, 0x00000002, + 0XB20, 0x0000001F, + 0XB24, 0x03020100, + 0XB28, 0x07060504, + 0XB2C, 0x0B0A0908, + 0XB30, 0x0F0E0D0C, + 0XB34, 0x13121110, + 0XB38, 0x17161514, + 0XB3C, 0x0000003A, + 0XB40, 0x00000000, + 0XB44, 0x00000000, + 0XB48, 0x13000032, + 0XB4C, 0x48080000, + 0XB50, 0x00000000, + 0XB54, 0x00000000, + 0XB58, 0x00000000, + 0XB5C, 0x00000000, 0xC00, 0x00000007, 0xC04, 0x00042020, 0xC08, 0x80410231, @@ -174,7 +174,7 @@ u32 RTL8812AE_PHY_REG_ARRAY[] = { 0xC68, 0x59791979, 0xA0000000, 0x00000000, 0xC68, 0x59799979, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0xC6C, 0x59795979, 0xC70, 0x19795979, 0xC74, 0x19795979, @@ -344,30 +344,30 @@ u32 RTL8821AE_PHY_REG_ARRAY[] = { 0xA7C, 0x225B0606, 0xA80, 0x21805490, 0xA84, 0x001F0000, - 0xB00, 0x03100040, - 0xB04, 0x0000B000, - 0xB08, 0xAE0201EB, - 0xB0C, 0x01003207, - 0xB10, 0x00009807, - 0xB14, 0x01000000, - 0xB18, 0x00000002, - 0xB1C, 0x00000002, - 0xB20, 0x0000001F, - 0xB24, 0x03020100, - 0xB28, 0x07060504, - 0xB2C, 0x0B0A0908, - 0xB30, 0x0F0E0D0C, - 0xB34, 0x13121110, - 0xB38, 0x17161514, - 0xB3C, 0x0000003A, - 0xB40, 0x00000000, - 0xB44, 0x00000000, - 0xB48, 0x13000032, - 0xB4C, 0x48080000, - 0xB50, 0x00000000, - 0xB54, 0x00000000, - 0xB58, 0x00000000, - 0xB5C, 0x00000000, + 0XB00, 0x03100040, + 0XB04, 0x0000B000, + 0XB08, 0xAE0201EB, + 0XB0C, 0x01003207, + 0XB10, 0x00009807, + 0XB14, 0x01000000, + 0XB18, 0x00000002, + 0XB1C, 0x00000002, + 0XB20, 0x0000001F, + 0XB24, 0x03020100, + 0XB28, 0x07060504, + 0XB2C, 0x0B0A0908, + 0XB30, 0x0F0E0D0C, + 0XB34, 0x13121110, + 0XB38, 0x17161514, + 0XB3C, 0x0000003A, + 0XB40, 0x00000000, + 0XB44, 0x00000000, + 0XB48, 0x13000032, + 0XB4C, 0x48080000, + 0XB50, 0x00000000, + 0XB54, 0x00000000, + 0XB58, 0x00000000, + 0XB5C, 0x00000000, 0xC00, 0x00000007, 0xC04, 0x00042020, 0xC08, 0x80410231, @@ -498,12 +498,12 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x086, 0x00014B3A, 0xA0000000, 0x00000000, 0x086, 0x00014B38, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x80000004, 0x00000000, 0x40000000, 0x00000000, 0x08B, 0x00080180, 0xA0000000, 0x00000000, 0x08B, 0x00087180, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0B1, 0x0001FC1A, 0x0B3, 0x000F0810, 0x0B4, 0x0001A78D, @@ -534,7 +534,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x03B, 0x00018248, 0x03B, 0x00010240, 0x03B, 0x00008240, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000100, 0x80000002, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0000A4EE, @@ -560,7 +560,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x034, 0x000024E7, 0x034, 0x0000146B, 0x034, 0x0000006D, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x0EF, 0x000020A2, 0x0DF, 0x00000080, @@ -689,7 +689,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x034, 0x000428C5, 0x034, 0x000418C2, 0x034, 0x000408C0, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x80000008, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0002A0B2, 0x034, 0x000290AF, @@ -726,7 +726,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x034, 0x000228C5, 0x034, 0x000218C2, 0x034, 0x000208C0, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x80000008, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0000A0B2, 0x034, 0x000090AF, @@ -763,7 +763,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x034, 0x000028C9, 0x034, 0x000018C6, 0x034, 0x000008C3, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x80000008, 0x00000000, 0x40000000, 0x00000000, 0x018, 0x0001712A, @@ -801,7 +801,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x035, 0x000401D8, 0x035, 0x000481D8, 0x035, 0x000501D8, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x80000008, 0x00000000, 0x40000000, 0x00000000, 0x018, 0x0001712A, @@ -848,7 +848,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x036, 0x000CCC35, 0x036, 0x000D4C35, 0x036, 0x000DCC35, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x0EF, 0x00000008, 0x80000008, 0x00000000, 0x40000000, 0x00000000, @@ -863,7 +863,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x03C, 0x000002A8, 0x03C, 0x000005A2, 0x03C, 0x00000880, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x018, 0x0001712A, 0x0EF, 0x00000002, @@ -887,7 +887,7 @@ u32 RTL8812AE_RADIOA_ARRAY[] = { 0x063, 0x000114EB, 0x064, 0x000196AC, 0x065, 0x000911D7, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x008, 0x00008400, 0x01C, 0x000739D2, 0x0B4, 0x0001E78D, @@ -912,12 +912,12 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x086, 0x00014B3A, 0xA0000000, 0x00000000, 0x086, 0x00014B38, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x80000004, 0x00000000, 0x40000000, 0x00000000, 0x08B, 0x00080180, 0xA0000000, 0x00000000, 0x08B, 0x00087180, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x018, 0x00000006, 0x0EF, 0x00002000, 0x80000001, 0x00000000, 0x40000000, 0x00000000, @@ -944,7 +944,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x03B, 0x00018248, 0x03B, 0x00010240, 0x03B, 0x00008240, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000100, 0x80000002, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0000A4EE, @@ -970,7 +970,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x034, 0x000024E7, 0x034, 0x0000146B, 0x034, 0x0000006D, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x0EF, 0x000020A2, 0x0DF, 0x00000080, @@ -1099,7 +1099,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x034, 0x000428C5, 0x034, 0x000418C2, 0x034, 0x000408C0, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x80000008, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0002A0B2, 0x034, 0x000290AF, @@ -1136,7 +1136,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x034, 0x000228C5, 0x034, 0x000218C2, 0x034, 0x000208C0, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x80000008, 0x00000000, 0x40000000, 0x00000000, 0x034, 0x0000A0B2, 0x034, 0x000090AF, @@ -1173,7 +1173,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x034, 0x000028C9, 0x034, 0x000018C6, 0x034, 0x000008C3, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x80000008, 0x00000000, 0x40000000, 0x00000000, 0x018, 0x0001712A, @@ -1214,7 +1214,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x035, 0x000481D8, 0x035, 0x000501D8, 0x0EF, 0x00000000, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x80000008, 0x00000000, 0x40000000, 0x00000000, 0x018, 0x0001712A, 0x0EF, 0x00000010, @@ -1260,7 +1260,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x036, 0x000CCC35, 0x036, 0x000D4C35, 0x036, 0x000DCC35, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x0EF, 0x00000008, 0x80000008, 0x00000000, 0x40000000, 0x00000000, @@ -1275,7 +1275,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x03C, 0x000002A8, 0x03C, 0x000005A2, 0x03C, 0x00000880, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x0EF, 0x00000000, 0x018, 0x0001712A, 0x0EF, 0x00000002, @@ -1304,7 +1304,7 @@ u32 RTL8812AE_RADIOB_ARRAY[] = { 0x063, 0x000114EB, 0x064, 0x000196AC, 0x065, 0x000911D7, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x008, 0x00008400, }; @@ -1910,7 +1910,7 @@ u32 RTL8812AE_MAC_REG_ARRAY[] = { 0x011, 0x00000066, 0xA0000000, 0x00000000, 0x011, 0x0000005A, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x025, 0x0000000F, 0x072, 0x00000000, 0x420, 0x00000080, @@ -2314,7 +2314,7 @@ u32 RTL8812AE_AGC_TAB_ARRAY[] = { 0x81C, 0x417A0001, 0x81C, 0x417C0001, 0x81C, 0x417E0001, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0x80000004, 0x00000000, 0x40000000, 0x00000000, 0x81C, 0xFC800001, 0x81C, 0xFB820001, @@ -2445,7 +2445,7 @@ u32 RTL8812AE_AGC_TAB_ARRAY[] = { 0x81C, 0x01FA0001, 0x81C, 0x01FC0001, 0x81C, 0x01FE0001, - 0xB0000000, 0x00000000, + 0XB0000000, 0x00000000, 0xC50, 0x00000022, 0xC50, 0x00000020, 0xE50, 0x00000022, @@ -2455,24 +2455,24 @@ u32 RTL8812AE_AGC_TAB_ARRAY[] = { u32 RTL8812AE_AGC_TAB_1TARRAYLEN = ARRAY_SIZE(RTL8812AE_AGC_TAB_ARRAY); u32 RTL8821AE_AGC_TAB_ARRAY[] = { - 0x81C, 0xBF000001, - 0x81C, 0xBF020001, - 0x81C, 0xBF040001, - 0x81C, 0xBF060001, - 0x81C, 0xBE080001, - 0x81C, 0xBD0A0001, - 0x81C, 0xBC0C0001, - 0x81C, 0xBA0E0001, - 0x81C, 0xB9100001, - 0x81C, 0xB8120001, - 0x81C, 0xB7140001, - 0x81C, 0xB6160001, - 0x81C, 0xB5180001, - 0x81C, 0xB41A0001, - 0x81C, 0xB31C0001, - 0x81C, 0xB21E0001, - 0x81C, 0xB1200001, - 0x81C, 0xB0220001, + 0x81C, 0XBF000001, + 0x81C, 0XBF020001, + 0x81C, 0XBF040001, + 0x81C, 0XBF060001, + 0x81C, 0XBE080001, + 0x81C, 0XBD0A0001, + 0x81C, 0XBC0C0001, + 0x81C, 0XBA0E0001, + 0x81C, 0XB9100001, + 0x81C, 0XB8120001, + 0x81C, 0XB7140001, + 0x81C, 0XB6160001, + 0x81C, 0XB5180001, + 0x81C, 0XB41A0001, + 0x81C, 0XB31C0001, + 0x81C, 0XB21E0001, + 0x81C, 0XB1200001, + 0x81C, 0XB0220001, 0x81C, 0xAF240001, 0x81C, 0xAE260001, 0x81C, 0xAD280001, -- cgit v1.2.3 From 1b5e2423164b3670e8bc9174e4762d297990deff Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 14 Feb 2019 13:43:47 +0100 Subject: brcmfmac: assure SSID length from firmware is limited The SSID length as received from firmware should not exceed IEEE80211_MAX_SSID_LEN as that would result in heap overflow. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index b5e291ed9496..012275fc3bf7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3507,6 +3507,8 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, } netinfo = brcmf_get_netinfo_array(pfn_result); + if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN) + netinfo->SSID_len = IEEE80211_MAX_SSID_LEN; memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len); cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len; cfg->wowl.nd->n_channels = 1; -- cgit v1.2.3 From a4176ec356c73a46c07c181c6d04039fafa34a9f Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 14 Feb 2019 13:43:48 +0100 Subject: brcmfmac: add subtype check for event handling in data path For USB there is no separate channel being used to pass events from firmware to the host driver and as such are passed over the data path. In order to detect mock event messages an additional check is needed on event subtype. This check is added conditionally using unlikely() keyword. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 5 +++-- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h | 16 ++++++++++++---- .../net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index e772c0845638..a368ba6e7344 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -519,7 +519,8 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event) } else { /* Process special event packets */ if (handle_event) - brcmf_fweh_process_skb(ifp->drvr, skb); + brcmf_fweh_process_skb(ifp->drvr, skb, + BCMILCP_SUBTYPE_VENDOR_LONG); brcmf_netif_rx(ifp, skb); } @@ -536,7 +537,7 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb) if (brcmf_rx_hdrpull(drvr, skb, &ifp)) return; - brcmf_fweh_process_skb(ifp->drvr, skb); + brcmf_fweh_process_skb(ifp->drvr, skb, 0); brcmu_pkt_buf_free_skb(skb); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h index 31f3e8e83a21..7027243db17e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h @@ -211,7 +211,7 @@ enum brcmf_fweh_event_code { */ #define BRCM_OUI "\x00\x10\x18" #define BCMILCP_BCM_SUBTYPE_EVENT 1 - +#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 /** * struct brcm_ethhdr - broadcom specific ether header. @@ -334,10 +334,10 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing); static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, - struct sk_buff *skb) + struct sk_buff *skb, u16 stype) { struct brcmf_event *event_packet; - u16 usr_stype; + u16 subtype, usr_stype; /* only process events when protocol matches */ if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL)) @@ -346,8 +346,16 @@ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, if ((skb->len + ETH_HLEN) < sizeof(*event_packet)) return; - /* check for BRCM oui match */ event_packet = (struct brcmf_event *)skb_mac_header(skb); + + /* check subtype if needed */ + if (unlikely(stype)) { + subtype = get_unaligned_be16(&event_packet->hdr.subtype); + if (subtype != stype) + return; + } + + /* check for BRCM oui match */ if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0], sizeof(event_packet->hdr.oui))) return; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 4e8397a0cbc8..ee922b052561 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -1116,7 +1116,7 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) skb->protocol = eth_type_trans(skb, ifp->ndev); - brcmf_fweh_process_skb(ifp->drvr, skb); + brcmf_fweh_process_skb(ifp->drvr, skb, 0); exit: brcmu_pkt_buf_free_skb(skb); -- cgit v1.2.3 From aaf6a5e86e36766abbeedf220462bde8031f9a72 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 14 Feb 2019 13:43:49 +0100 Subject: brcmfmac: create debugfs files for bus-specific layer Since we moved the drivers debugfs directory under ieee80211 debugfs the debugfs entries need to be added after wiphy_register() has been called. For most part that has been done accordingly, but for the debugfs entries added by SDIO it was not and failed silently. This patch fixes that by adding a bus-layer callback for it. Fixes: 856d5a011c86 ("brcmfmac: allocate struct brcmf_pub instance using wiphy_new()") Reported-by: Russel King Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++++++++++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 1 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 12 +++++++----- 3 files changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index c4965184cdf3..3d441c5c745c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -90,6 +90,7 @@ struct brcmf_bus_ops { int (*get_memdump)(struct device *dev, void *data, size_t len); int (*get_fwname)(struct device *dev, const char *ext, unsigned char *fw_name); + void (*debugfs_create)(struct device *dev); }; @@ -235,6 +236,15 @@ int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext, return bus->ops->get_fwname(bus->dev, ext, fw_name); } +static inline +void brcmf_bus_debugfs_create(struct brcmf_bus *bus) +{ + if (!bus->ops->debugfs_create) + return; + + return bus->ops->debugfs_create(bus->dev); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index a368ba6e7344..9d911ddefe82 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -1156,6 +1156,7 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops) brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read); brcmf_feat_debugfs_create(drvr); brcmf_proto_debugfs_create(drvr); + brcmf_bus_debugfs_create(bus_if); return 0; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 0cd5b8d970d7..5f9de618c679 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3143,9 +3143,12 @@ static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data) return 0; } -static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) +static void brcmf_sdio_debugfs_create(struct device *dev) { - struct brcmf_pub *drvr = bus->sdiodev->bus_if->drvr; + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pub *drvr = bus_if->drvr; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio *bus = sdiodev->bus; struct dentry *dentry = brcmf_debugfs_get_devdir(drvr); if (IS_ERR_OR_NULL(dentry)) @@ -3165,7 +3168,7 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) return 0; } -static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) +static void brcmf_sdio_debugfs_create(struct device *dev) { } #endif /* DEBUG */ @@ -3477,8 +3480,6 @@ static int brcmf_sdio_bus_preinit(struct device *dev) if (bus->rxbuf) bus->rxblen = value; - brcmf_sdio_debugfs_create(bus); - /* the commands below use the terms tx and rx from * a device perspective, ie. bus:txglom affects the * bus transfers from device to host. @@ -4088,6 +4089,7 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { .get_ramsize = brcmf_sdio_bus_get_ramsize, .get_memdump = brcmf_sdio_bus_get_memdump, .get_fwname = brcmf_sdio_get_fwname, + .debugfs_create = brcmf_sdio_debugfs_create }; #define BRCMF_SDIO_FW_CODE 0 -- cgit v1.2.3 From 92d3b88b1029c46f9bf27302c502dc0e3541805b Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 14 Feb 2019 13:43:50 +0100 Subject: brcmfmac: disable MBSS feature for bcm4330 device The MBSS feature was already disabled for bcm43362 as it resulted in a beacon with BRCM_TEST_SSID regardless user configuration in hostapd. Now the same has been reported for bcm4330 so disable the feature for this device as well. Reported-by: Russell King Tested-by: Christopher Martin Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index b91b7ecbfedf..072c51c953a5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -272,9 +272,15 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) BIT(BRCMF_FEAT_WOWL_GTK); } } - /* MBSS does not work for 43362 */ - if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID) + /* MBSS does not work for all chips */ + switch (drvr->bus_if->chip) { + case BRCM_CC_4330_CHIP_ID: + case BRCM_CC_43362_CHIP_ID: ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS); + break; + default: + break; + } brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode"); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable"); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MFP, "mfp"); -- cgit v1.2.3 From 4ab2cf03da91785f2c34d79a302e53da06928bc1 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 14 Feb 2019 13:43:51 +0100 Subject: brcmfmac: check and dump trap info during sdio probe When the firmware crashes during the probe sequence we provide little information on what really failed. This patch checks the sdpcm shared location and show the trap information if a firmware trap has happened. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 59 +++++++++++++++------- 1 file changed, 40 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 5f9de618c679..4d104ab80fd8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -2999,21 +2999,35 @@ static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus, if (error < 0) return error; - seq_printf(seq, - "dongle trap info: type 0x%x @ epc 0x%08x\n" - " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" - " lr 0x%08x pc 0x%08x offset 0x%x\n" - " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" - " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", - le32_to_cpu(tr.type), le32_to_cpu(tr.epc), - le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), - le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), - le32_to_cpu(tr.pc), sh->trap_addr, - le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), - le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), - le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), - le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); - + if (seq) + seq_printf(seq, + "dongle trap info: type 0x%x @ epc 0x%08x\n" + " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" + " lr 0x%08x pc 0x%08x offset 0x%x\n" + " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" + " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", + le32_to_cpu(tr.type), le32_to_cpu(tr.epc), + le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), + le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), + le32_to_cpu(tr.pc), sh->trap_addr, + le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), + le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), + le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), + le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); + else + pr_debug("dongle trap info: type 0x%x @ epc 0x%08x\n" + " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" + " lr 0x%08x pc 0x%08x offset 0x%x\n" + " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" + " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", + le32_to_cpu(tr.type), le32_to_cpu(tr.epc), + le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), + le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), + le32_to_cpu(tr.pc), sh->trap_addr, + le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), + le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), + le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), + le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); return 0; } @@ -3067,8 +3081,10 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) else if (sh.flags & SDPCM_SHARED_ASSERT) brcmf_err("assertion in dongle\n"); - if (sh.flags & SDPCM_SHARED_TRAP) + if (sh.flags & SDPCM_SHARED_TRAP) { brcmf_err("firmware trap in dongle\n"); + brcmf_sdio_trap_info(NULL, bus, &sh); + } return 0; } @@ -4199,7 +4215,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, } else { /* Disable F2 again */ sdio_disable_func(sdiod->func2); - goto release; + goto checkdied; } if (brcmf_chip_sr_capable(bus->ci)) { @@ -4220,8 +4236,10 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, } /* If we didn't come up, turn off backplane clock */ - if (err != 0) + if (err != 0) { brcmf_sdio_clkctl(bus, CLK_NONE, false); + goto checkdied; + } sdio_release_host(sdiod->func1); @@ -4235,12 +4253,15 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, err = brcmf_attach(sdiod->dev, sdiod->settings); if (err != 0) { brcmf_err("brcmf_attach failed\n"); - goto fail; + sdio_claim_host(sdiod->func1); + goto checkdied; } /* ready */ return; +checkdied: + brcmf_sdio_checkdied(bus); release: sdio_release_host(sdiod->func1); fail: -- cgit v1.2.3 From a250c91c1762e85c736e67cb4a9a95ebae72e62d Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 14 Feb 2019 13:43:52 +0100 Subject: brcmfmac: use chipname in brcmf_fw_alloc_request() for error path as well The local variable chipname is string representation of chip id and revision which is printed in the good flow of brcmf_fw_alloc_request(). Also use it for the error path, ie. for unknown/unsupported devices. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index cf1ddf988476..8209a42dea72 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -719,8 +719,10 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev, break; } + brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname)); + if (i == table_size) { - brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev); + brcmf_err("Unknown chip %s\n", chipname); return NULL; } @@ -729,8 +731,6 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev, if (!fwreq) return NULL; - brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname)); - brcmf_info("using %s for chip %s\n", mapping_table[i].fw_base, chipname); -- cgit v1.2.3 From c988b78244df8216902e20de536434e2f474a37e Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 8 Feb 2019 15:24:39 +0100 Subject: brcmfmac: print firmware reported ring status errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firmware is capable of reporting ring status. It's used e.g. to signal some problem with a specific ring setup. This patch adds support for printing ring & error number which may be useful for debugging setup issues. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index ee922b052561..0da0a68f47cb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -134,6 +134,14 @@ struct msgbuf_completion_hdr { __le16 flow_ring_id; }; +/* Data struct for the MSGBUF_TYPE_RING_STATUS */ +struct msgbuf_ring_status { + struct msgbuf_common_hdr msg; + struct msgbuf_completion_hdr compl_hdr; + __le16 write_idx; + __le32 rsvd0[5]; +}; + struct msgbuf_rx_event { struct msgbuf_common_hdr msg; struct msgbuf_completion_hdr compl_hdr; @@ -1180,6 +1188,19 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) brcmf_netif_rx(ifp, skb); } +static void brcmf_msgbuf_process_ring_status(struct brcmf_msgbuf *msgbuf, + void *buf) +{ + struct msgbuf_ring_status *ring_status = buf; + int err; + + err = le16_to_cpu(ring_status->compl_hdr.status); + if (err) { + int ring = le16_to_cpu(ring_status->compl_hdr.flow_ring_id); + + brcmf_err("Firmware reported ring %d error: %d\n", ring, err); + } +} static void brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf, @@ -1241,6 +1262,10 @@ static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf) msg = (struct msgbuf_common_hdr *)buf; switch (msg->msgtype) { + case MSGBUF_TYPE_RING_STATUS: + brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RING_STATUS\n"); + brcmf_msgbuf_process_ring_status(msgbuf, buf); + break; case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT: brcmf_dbg(MSGBUF, "MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT\n"); brcmf_msgbuf_process_flow_ring_create_response(msgbuf, buf); -- cgit v1.2.3 From f4e183293b871c96c0220dcc549d5ca4c72628ad Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 11 Feb 2019 23:04:53 +0100 Subject: brcmfmac: improve code handling bandwidth of firmware reported channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) Use switch to simplify/improve the code & avoid some duplication 2) Add warning for unsupported values Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 012275fc3bf7..7afdc1827a50 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6051,11 +6051,18 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, /* assuming the chanspecs order is HT20, * HT40 upper, HT40 lower, and VHT80. */ - if (ch.bw == BRCMU_CHAN_BW_80) { + switch (ch.bw) { + case BRCMU_CHAN_BW_80: channel->flags &= ~IEEE80211_CHAN_NO_80MHZ; - } else if (ch.bw == BRCMU_CHAN_BW_40) { + break; + case BRCMU_CHAN_BW_40: brcmf_update_bw40_channel_flag(channel, &ch); - } else { + break; + default: + wiphy_warn(wiphy, "Firmware reported unsupported bandwidth %d\n", + ch.bw); + /* fall through */ + case BRCMU_CHAN_BW_20: /* enable the channel and disable other bandwidths * for now as mentioned order assure they are enabled * for subsequent chanspecs. -- cgit v1.2.3 From 30519cbe339a45bd11a57ca8ece07f4f6a1cda2e Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 11 Feb 2019 23:04:54 +0100 Subject: brcmfmac: support firmware reporting 160 MHz channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far 160 MHz channels were treated as 20 MHz ones which was breaking support for 40/80 MHz due to the brcmf_construct_chaninfo() logic and its assumptions. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 7afdc1827a50..d8fd15ad4151 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6052,6 +6052,9 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, * HT40 upper, HT40 lower, and VHT80. */ switch (ch.bw) { + case BRCMU_CHAN_BW_160: + channel->flags &= ~IEEE80211_CHAN_NO_160MHZ; + break; case BRCMU_CHAN_BW_80: channel->flags &= ~IEEE80211_CHAN_NO_80MHZ; break; -- cgit v1.2.3 From 16e646768396339b3d354985b99bcd3f1f195a7d Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Feb 2019 15:45:54 +0100 Subject: brcmfmac: rework bphy_err() to take struct brcmf_pub argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This macro will be used in more places not just the cfg80211.c. It makes sense to pass some common struct to it as "struct wiphy" is mostly referenced in cfg80211 code only. A very common one (used above the bus abstraction layer) is struct brcmf_pub. Many functions already keep reference to it which will make using bphy_err() simpler. It should also allow extending that macro's logic if it's ever needed. This improves code recently added in the commit 3ef005b82e2a ("brcmfmac: add bphy_err() and use it in the cfg80211.c"). Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 510 +++++++++++---------- .../wireless/broadcom/brcm80211/brcmfmac/debug.h | 4 +- 2 files changed, 281 insertions(+), 233 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index d8fd15ad4151..e92f6351bd22 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -457,7 +457,7 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key, static int send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; int err; struct brcmf_wsec_key_le key_le; @@ -469,7 +469,7 @@ send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key) sizeof(key_le)); if (err) - bphy_err(wiphy, "wsec_key error (%d)\n", err); + bphy_err(drvr, "wsec_key error (%d)\n", err); return err; } @@ -509,7 +509,7 @@ static int brcmf_get_first_free_bsscfgidx(struct brcmf_pub *drvr) static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_mbss_ssid_le mbss_ssid_le; int bsscfgidx; int err; @@ -526,7 +526,7 @@ static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp) err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le, sizeof(mbss_ssid_le)); if (err < 0) - bphy_err(wiphy, "setting ssid failed %d\n", err); + bphy_err(drvr, "setting ssid failed %d\n", err); return err; } @@ -544,6 +544,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_cfg80211_vif *vif; int err; @@ -569,7 +570,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, BRCMF_VIF_EVENT_TIMEOUT); brcmf_cfg80211_arm_vif_event(cfg, NULL); if (!err) { - bphy_err(wiphy, "timeout occurred\n"); + bphy_err(drvr, "timeout occurred\n"); err = -EIO; goto fail; } @@ -577,7 +578,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, /* interface created in firmware */ ifp = vif->ifp; if (!ifp) { - bphy_err(wiphy, "no if pointer provided\n"); + bphy_err(drvr, "no if pointer provided\n"); err = -ENOENT; goto fail; } @@ -585,7 +586,7 @@ struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1); err = brcmf_net_attach(ifp, true); if (err) { - bphy_err(wiphy, "Registering netdevice failed\n"); + bphy_err(drvr, "Registering netdevice failed\n"); free_netdev(ifp->ndev); goto fail; } @@ -616,13 +617,15 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, enum nl80211_iftype type, struct vif_params *params) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct wireless_dev *wdev; int err; brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); if (err) { - bphy_err(wiphy, "iface validation failed: err=%d\n", err); + bphy_err(drvr, "iface validation failed: err=%d\n", err); return ERR_PTR(err); } switch (type) { @@ -647,7 +650,7 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, } if (IS_ERR(wdev)) - bphy_err(wiphy, "add iface %s type %d failed: err=%d\n", name, + bphy_err(drvr, "add iface %s type %d failed: err=%d\n", name, type, (int)PTR_ERR(wdev)); else brcmf_cfg80211_update_proto_addr_mode(wdev); @@ -663,13 +666,13 @@ static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc) void brcmf_set_mpc(struct brcmf_if *ifp, int mpc) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; s32 err = 0; if (check_vif_up(ifp->vif)) { err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc); if (err) { - bphy_err(wiphy, "fail to set mpc\n"); + bphy_err(drvr, "fail to set mpc\n"); return; } brcmf_dbg(INFO, "MPC : %d\n", mpc); @@ -680,7 +683,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, bool aborted, bool fw_abort) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_scan_params_le params_le; struct cfg80211_scan_request *scan_request; u64 reqid; @@ -715,7 +718,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, ¶ms_le, sizeof(params_le)); if (err) - bphy_err(wiphy, "Scan abort failed\n"); + bphy_err(drvr, "Scan abort failed\n"); } brcmf_scan_config_mpc(ifp, 1); @@ -760,6 +763,7 @@ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy, struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct net_device *ndev = wdev->netdev; struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; int ret; int err; @@ -767,7 +771,7 @@ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy, err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0); if (err) { - bphy_err(wiphy, "interface_remove failed %d\n", err); + bphy_err(drvr, "interface_remove failed %d\n", err); goto err_unarm; } @@ -775,7 +779,7 @@ static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy, ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL, BRCMF_VIF_EVENT_TIMEOUT); if (!ret) { - bphy_err(wiphy, "timeout occurred\n"); + bphy_err(drvr, "timeout occurred\n"); err = -EIO; goto err_unarm; } @@ -838,6 +842,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_vif *vif = ifp->vif; + struct brcmf_pub *drvr = cfg->pub; s32 infra = 0; s32 ap = 0; s32 err = 0; @@ -877,13 +882,13 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, } err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type); if (err) { - bphy_err(wiphy, "iface validation failed: err=%d\n", err); + bphy_err(drvr, "iface validation failed: err=%d\n", err); return err; } switch (type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_WDS: - bphy_err(wiphy, "type (%d) : currently we do not support this type\n", + bphy_err(drvr, "type (%d) : currently we do not support this type\n", type); return -EOPNOTSUPP; case NL80211_IFTYPE_ADHOC: @@ -912,7 +917,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, } else { err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra); if (err) { - bphy_err(wiphy, "WLC_SET_INFRA error (%d)\n", err); + bphy_err(drvr, "WLC_SET_INFRA error (%d)\n", err); err = -EAGAIN; goto done; } @@ -1003,7 +1008,7 @@ static s32 brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, struct cfg80211_scan_request *request) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + offsetof(struct brcmf_escan_params_le, params_le); struct brcmf_escan_params_le *params; @@ -1035,7 +1040,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, if (err == -EBUSY) brcmf_dbg(INFO, "system busy : escan canceled\n"); else - bphy_err(wiphy, "error (%d)\n", err); + bphy_err(drvr, "error (%d)\n", err); } kfree(params); @@ -1072,6 +1077,7 @@ static s32 brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_cfg80211_vif *vif; s32 err = 0; @@ -1081,22 +1087,22 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) return -EIO; if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { - bphy_err(wiphy, "Scanning already: status (%lu)\n", + bphy_err(drvr, "Scanning already: status (%lu)\n", cfg->scan_status); return -EAGAIN; } if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) { - bphy_err(wiphy, "Scanning being aborted: status (%lu)\n", + bphy_err(drvr, "Scanning being aborted: status (%lu)\n", cfg->scan_status); return -EAGAIN; } if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { - bphy_err(wiphy, "Scanning suppressed: status (%lu)\n", + bphy_err(drvr, "Scanning suppressed: status (%lu)\n", cfg->scan_status); return -EAGAIN; } if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) { - bphy_err(wiphy, "Connecting: status (%lu)\n", vif->sme_state); + bphy_err(drvr, "Connecting: status (%lu)\n", vif->sme_state); return -EAGAIN; } @@ -1130,7 +1136,7 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) return 0; scan_out: - bphy_err(wiphy, "scan error (%d)\n", err); + bphy_err(drvr, "scan error (%d)\n", err); clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); cfg->scan_request = NULL; return err; @@ -1139,12 +1145,12 @@ scan_out: static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) { struct brcmf_if *ifp = netdev_priv(ndev); - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; s32 err = 0; err = brcmf_fil_iovar_int_set(ifp, "rtsthresh", rts_threshold); if (err) - bphy_err(wiphy, "Error (%d)\n", err); + bphy_err(drvr, "Error (%d)\n", err); return err; } @@ -1152,13 +1158,13 @@ static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold) { struct brcmf_if *ifp = netdev_priv(ndev); - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; s32 err = 0; err = brcmf_fil_iovar_int_set(ifp, "fragthresh", frag_threshold); if (err) - bphy_err(wiphy, "Error (%d)\n", err); + bphy_err(drvr, "Error (%d)\n", err); return err; } @@ -1166,13 +1172,13 @@ static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold) static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) { struct brcmf_if *ifp = netdev_priv(ndev); - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; s32 err = 0; u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL); err = brcmf_fil_cmd_int_set(ifp, cmd, retry); if (err) { - bphy_err(wiphy, "cmd (%d) , error (%d)\n", cmd, err); + bphy_err(drvr, "cmd (%d) , error (%d)\n", cmd, err); return err; } return err; @@ -1248,7 +1254,7 @@ static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e) static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_wsec_pmk_le pmk; int i, err; @@ -1262,7 +1268,7 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len) err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK, &pmk, sizeof(pmk)); if (err < 0) - bphy_err(wiphy, "failed to change PSK in firmware (len=%u)\n", + bphy_err(drvr, "failed to change PSK in firmware (len=%u)\n", pmk_len); return err; @@ -1271,7 +1277,7 @@ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len) static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; s32 err = 0; brcmf_dbg(TRACE, "Enter\n"); @@ -1281,7 +1287,7 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason) err = brcmf_fil_cmd_data_set(vif->ifp, BRCMF_C_DISASSOC, NULL, 0); if (err) { - bphy_err(wiphy, "WLC_DISASSOC failed (%d)\n", err); + bphy_err(drvr, "WLC_DISASSOC failed (%d)\n", err); } if ((vif->wdev.iftype == NL80211_IFTYPE_STATION) || (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) @@ -1305,6 +1311,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; + struct brcmf_pub *drvr = cfg->pub; struct brcmf_join_params join_params; size_t join_params_size = 0; s32 err = 0; @@ -1369,7 +1376,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec); if (err) { - bphy_err(wiphy, "wsec failed (%d)\n", err); + bphy_err(drvr, "wsec failed (%d)\n", err); goto done; } @@ -1381,7 +1388,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd); if (err) { - bphy_err(wiphy, "WLC_SET_BCNPRD failed (%d)\n", err); + bphy_err(drvr, "WLC_SET_BCNPRD failed (%d)\n", err); goto done; } @@ -1426,7 +1433,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL, target_channel); if (err) { - bphy_err(wiphy, "WLC_SET_CHANNEL failed (%d)\n", err); + bphy_err(drvr, "WLC_SET_CHANNEL failed (%d)\n", err); goto done; } } else @@ -1438,7 +1445,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, join_params_size); if (err) { - bphy_err(wiphy, "WLC_SET_SSID failed (%d)\n", err); + bphy_err(drvr, "WLC_SET_SSID failed (%d)\n", err); goto done; } @@ -1475,8 +1482,8 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_if *ifp = netdev_priv(ndev); - struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1490,7 +1497,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val); err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val); if (err) { - bphy_err(wiphy, "set wpa_auth failed (%d)\n", err); + bphy_err(drvr, "set wpa_auth failed (%d)\n", err); return err; } sec = &profile->sec; @@ -1502,8 +1509,8 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_if *ifp = netdev_priv(ndev); - struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1525,7 +1532,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, err = brcmf_fil_bsscfg_int_set(ifp, "auth", val); if (err) { - bphy_err(wiphy, "set auth failed (%d)\n", err); + bphy_err(drvr, "set auth failed (%d)\n", err); return err; } sec = &profile->sec; @@ -1538,8 +1545,8 @@ brcmf_set_wsec_mode(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_if *ifp = netdev_priv(ndev); - struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_cfg80211_security *sec; s32 pval = 0; s32 gval = 0; @@ -1562,7 +1569,7 @@ brcmf_set_wsec_mode(struct net_device *ndev, pval = AES_ENABLED; break; default: - bphy_err(wiphy, "invalid cipher pairwise (%d)\n", + bphy_err(drvr, "invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]); return -EINVAL; } @@ -1583,7 +1590,7 @@ brcmf_set_wsec_mode(struct net_device *ndev, gval = AES_ENABLED; break; default: - bphy_err(wiphy, "invalid cipher group (%d)\n", + bphy_err(drvr, "invalid cipher group (%d)\n", sme->crypto.cipher_group); return -EINVAL; } @@ -1599,7 +1606,7 @@ brcmf_set_wsec_mode(struct net_device *ndev, wsec = pval | gval; err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); if (err) { - bphy_err(wiphy, "error (%d)\n", err); + bphy_err(drvr, "error (%d)\n", err); return err; } @@ -1614,8 +1621,8 @@ static s32 brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_if *ifp = netdev_priv(ndev); - struct wiphy *wiphy = ifp->drvr->wiphy; struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; + struct brcmf_pub *drvr = ifp->drvr; s32 val; s32 err; const struct brcmf_tlv *rsn_ie; @@ -1633,7 +1640,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "wpa_auth", &val); if (err) { - bphy_err(wiphy, "could not get wpa_auth (%d)\n", err); + bphy_err(drvr, "could not get wpa_auth (%d)\n", err); return err; } if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { @@ -1647,7 +1654,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA_AUTH_PSK; break; default: - bphy_err(wiphy, "invalid cipher group (%d)\n", + bphy_err(drvr, "invalid cipher group (%d)\n", sme->crypto.cipher_group); return -EINVAL; } @@ -1678,7 +1685,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA2_AUTH_PSK | WPA2_AUTH_FT; break; default: - bphy_err(wiphy, "invalid cipher group (%d)\n", + bphy_err(drvr, "invalid cipher group (%d)\n", sme->crypto.cipher_group); return -EINVAL; } @@ -1725,7 +1732,7 @@ skip_mfp_config: brcmf_dbg(CONN, "setting wpa_auth to %d\n", val); err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val); if (err) { - bphy_err(wiphy, "could not set wpa_auth (%d)\n", err); + bphy_err(drvr, "could not set wpa_auth (%d)\n", err); return err; } @@ -1737,7 +1744,7 @@ brcmf_set_sharedkey(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_if *ifp = netdev_priv(ndev); - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); struct brcmf_cfg80211_security *sec; struct brcmf_wsec_key key; @@ -1764,7 +1771,7 @@ brcmf_set_sharedkey(struct net_device *ndev, key.len = (u32) sme->key_len; key.index = (u32) sme->key_idx; if (key.len > sizeof(key.data)) { - bphy_err(wiphy, "Too long key length (%u)\n", key.len); + bphy_err(drvr, "Too long key length (%u)\n", key.len); return -EINVAL; } memcpy(key.data, sme->key, key.len); @@ -1777,7 +1784,7 @@ brcmf_set_sharedkey(struct net_device *ndev, key.algo = CRYPTO_ALGO_WEP128; break; default: - bphy_err(wiphy, "Invalid algorithm (%d)\n", + bphy_err(drvr, "Invalid algorithm (%d)\n", sme->crypto.ciphers_pairwise[0]); return -EINVAL; } @@ -1794,7 +1801,7 @@ brcmf_set_sharedkey(struct net_device *ndev, val = WL_AUTH_SHARED_KEY; /* shared key */ err = brcmf_fil_bsscfg_int_set(ifp, "auth", val); if (err) - bphy_err(wiphy, "set auth failed (%d)\n", err); + bphy_err(drvr, "set auth failed (%d)\n", err); } return err; } @@ -1814,7 +1821,7 @@ enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, static void brcmf_set_join_pref(struct brcmf_if *ifp, struct cfg80211_bss_selection *bss_select) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_join_pref_params join_pref_params[2]; enum nl80211_band band; int err, i = 0; @@ -1853,7 +1860,7 @@ static void brcmf_set_join_pref(struct brcmf_if *ifp, err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, sizeof(join_pref_params)); if (err) - bphy_err(wiphy, "Set join_pref error (%d)\n", err); + bphy_err(drvr, "Set join_pref error (%d)\n", err); } static s32 @@ -1864,6 +1871,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; struct ieee80211_channel *chan = sme->channel; + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_join_params join_params; size_t join_params_size; const struct brcmf_tlv *rsn_ie; @@ -1880,7 +1888,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, return -EIO; if (!sme->ssid) { - bphy_err(wiphy, "Invalid ssid\n"); + bphy_err(drvr, "Invalid ssid\n"); return -EOPNOTSUPP; } @@ -1909,7 +1917,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); if (err) - bphy_err(wiphy, "Set Assoc REQ IE Failed\n"); + bphy_err(drvr, "Set Assoc REQ IE Failed\n"); else brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n"); @@ -1930,32 +1938,32 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_set_wpa_version(ndev, sme); if (err) { - bphy_err(wiphy, "wl_set_wpa_version failed (%d)\n", err); + bphy_err(drvr, "wl_set_wpa_version failed (%d)\n", err); goto done; } sme->auth_type = brcmf_war_auth_type(ifp, sme->auth_type); err = brcmf_set_auth_type(ndev, sme); if (err) { - bphy_err(wiphy, "wl_set_auth_type failed (%d)\n", err); + bphy_err(drvr, "wl_set_auth_type failed (%d)\n", err); goto done; } err = brcmf_set_wsec_mode(ndev, sme); if (err) { - bphy_err(wiphy, "wl_set_set_cipher failed (%d)\n", err); + bphy_err(drvr, "wl_set_set_cipher failed (%d)\n", err); goto done; } err = brcmf_set_key_mgmt(ndev, sme); if (err) { - bphy_err(wiphy, "wl_set_key_mgmt failed (%d)\n", err); + bphy_err(drvr, "wl_set_key_mgmt failed (%d)\n", err); goto done; } err = brcmf_set_sharedkey(ndev, sme); if (err) { - bphy_err(wiphy, "brcmf_set_sharedkey failed (%d)\n", err); + bphy_err(drvr, "brcmf_set_sharedkey failed (%d)\n", err); goto done; } @@ -1972,7 +1980,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, /* enable firmware supplicant for this interface */ err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); if (err < 0) { - bphy_err(wiphy, "failed to enable fw supplicant\n"); + bphy_err(drvr, "failed to enable fw supplicant\n"); goto done; } } @@ -2067,7 +2075,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, join_params_size); if (err) - bphy_err(wiphy, "BRCMF_C_SET_SSID failed (%d)\n", err); + bphy_err(drvr, "BRCMF_C_SET_SSID failed (%d)\n", err); done: if (err) @@ -2080,8 +2088,10 @@ static s32 brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; + struct brcmf_pub *drvr = cfg->pub; struct brcmf_scb_val_le scbval; s32 err = 0; @@ -2098,7 +2108,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC, &scbval, sizeof(scbval)); if (err) - bphy_err(wiphy, "error (%d)\n", err); + bphy_err(drvr, "error (%d)\n", err); brcmf_dbg(TRACE, "Exit\n"); return err; @@ -2111,6 +2121,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct net_device *ndev = cfg_to_ndev(cfg); struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; s32 err; s32 disable; u32 qdbm = 127; @@ -2125,7 +2136,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, case NL80211_TX_POWER_LIMITED: case NL80211_TX_POWER_FIXED: if (mbm < 0) { - bphy_err(wiphy, "TX_POWER_FIXED - dbm is negative\n"); + bphy_err(drvr, "TX_POWER_FIXED - dbm is negative\n"); err = -EINVAL; goto done; } @@ -2135,7 +2146,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, qdbm |= WL_TXPWR_OVERRIDE; break; default: - bphy_err(wiphy, "Unsupported type %d\n", type); + bphy_err(drvr, "Unsupported type %d\n", type); err = -EINVAL; goto done; } @@ -2143,11 +2154,11 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, disable = WL_RADIO_SW_DISABLE << 16; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable); if (err) - bphy_err(wiphy, "WLC_SET_RADIO error (%d)\n", err); + bphy_err(drvr, "WLC_SET_RADIO error (%d)\n", err); err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm); if (err) - bphy_err(wiphy, "qtxpower error (%d)\n", err); + bphy_err(drvr, "qtxpower error (%d)\n", err); done: brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE); @@ -2158,7 +2169,9 @@ static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, s32 *dbm) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev); + struct brcmf_pub *drvr = cfg->pub; s32 qdbm = 0; s32 err; @@ -2168,7 +2181,7 @@ brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm); if (err) { - bphy_err(wiphy, "error (%d)\n", err); + bphy_err(drvr, "error (%d)\n", err); goto done; } *dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4; @@ -2183,6 +2196,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool unicast, bool multicast) { struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = ifp->drvr; u32 index; u32 wsec; s32 err = 0; @@ -2194,7 +2208,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); if (err) { - bphy_err(wiphy, "WLC_GET_WSEC error (%d)\n", err); + bphy_err(drvr, "WLC_GET_WSEC error (%d)\n", err); goto done; } @@ -2204,7 +2218,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_KEY_PRIMARY, index); if (err) - bphy_err(wiphy, "error (%d)\n", err); + bphy_err(drvr, "error (%d)\n", err); } done: brcmf_dbg(TRACE, "Exit\n"); @@ -2253,7 +2267,9 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_wsec_key *key; s32 val; s32 wsec; @@ -2268,7 +2284,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) { /* we ignore this key index in this case */ - bphy_err(wiphy, "invalid key index (%d)\n", key_idx); + bphy_err(drvr, "invalid key index (%d)\n", key_idx); return -EINVAL; } @@ -2277,7 +2293,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, mac_addr); if (params->key_len > sizeof(key->data)) { - bphy_err(wiphy, "Too long key length (%u)\n", params->key_len); + bphy_err(drvr, "Too long key length (%u)\n", params->key_len); return -EINVAL; } @@ -2331,7 +2347,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n"); break; default: - bphy_err(wiphy, "Invalid cipher (0x%x)\n", params->cipher); + bphy_err(drvr, "Invalid cipher (0x%x)\n", params->cipher); err = -EINVAL; goto done; } @@ -2342,13 +2358,13 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); if (err) { - bphy_err(wiphy, "get wsec error (%d)\n", err); + bphy_err(drvr, "get wsec error (%d)\n", err); goto done; } wsec |= val; err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); if (err) { - bphy_err(wiphy, "set wsec error (%d)\n", err); + bphy_err(drvr, "set wsec error (%d)\n", err); goto done; } @@ -2363,9 +2379,11 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, void (*callback)(void *cookie, struct key_params *params)) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct key_params params; struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; + struct brcmf_pub *drvr = cfg->pub; struct brcmf_cfg80211_security *sec; s32 wsec; s32 err = 0; @@ -2379,7 +2397,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); if (err) { - bphy_err(wiphy, "WLC_GET_WSEC error (%d)\n", err); + bphy_err(drvr, "WLC_GET_WSEC error (%d)\n", err); /* Ignore this error, may happen during DISASSOC */ err = -EAGAIN; goto done; @@ -2400,7 +2418,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n"); } else { - bphy_err(wiphy, "Invalid algo (0x%x)\n", wsec); + bphy_err(drvr, "Invalid algo (0x%x)\n", wsec); err = -EINVAL; goto done; } @@ -2430,7 +2448,7 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, static void brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; s32 err; u8 key_idx; struct brcmf_wsec_key *key; @@ -2447,18 +2465,18 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp) err = send_key_to_dongle(ifp, key); if (err) { - bphy_err(wiphy, "Setting WEP key failed (%d)\n", err); + bphy_err(drvr, "Setting WEP key failed (%d)\n", err); return; } err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); if (err) { - bphy_err(wiphy, "get wsec error (%d)\n", err); + bphy_err(drvr, "get wsec error (%d)\n", err); return; } wsec |= WEP_ENABLED; err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); if (err) - bphy_err(wiphy, "set wsec error (%d)\n", err); + bphy_err(drvr, "set wsec error (%d)\n", err); } static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si) @@ -2484,7 +2502,7 @@ static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si) static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; struct { __le32 len; struct brcmf_bss_info_le bss_le; @@ -2500,7 +2518,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); if (err) { - bphy_err(wiphy, "Failed to get bss info (%d)\n", err); + bphy_err(drvr, "Failed to get bss info (%d)\n", err); goto out_kfree; } si->filled |= BIT_ULL(NL80211_STA_INFO_BSS_PARAM); @@ -2522,7 +2540,7 @@ static s32 brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, struct station_info *sinfo) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_scb_val_le scbval; struct brcmf_pktcnt_le pktcnt; s32 err; @@ -2532,7 +2550,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, /* Get the current tx rate */ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); if (err < 0) { - bphy_err(wiphy, "BRCMF_C_GET_RATE error (%d)\n", err); + bphy_err(drvr, "BRCMF_C_GET_RATE error (%d)\n", err); return err; } sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); @@ -2542,7 +2560,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, &scbval, sizeof(scbval)); if (err) { - bphy_err(wiphy, "BRCMF_C_GET_RSSI error (%d)\n", err); + bphy_err(drvr, "BRCMF_C_GET_RSSI error (%d)\n", err); return err; } rssi = le32_to_cpu(scbval.val); @@ -2552,7 +2570,7 @@ brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_GET_PKTCNTS, &pktcnt, sizeof(pktcnt)); if (err) { - bphy_err(wiphy, "BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err); + bphy_err(drvr, "BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err); return err; } sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS) | @@ -2571,7 +2589,9 @@ static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_scb_val_le scb_val; s32 err = 0; struct brcmf_sta_info_le sta_info_le; @@ -2600,7 +2620,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, &sta_info_le, sizeof(sta_info_le)); if (err < 0) { - bphy_err(wiphy, "GET STA INFO failed, %d\n", err); + bphy_err(drvr, "GET STA INFO failed, %d\n", err); goto done; } } @@ -2669,7 +2689,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, &scb_val, sizeof(scb_val)); if (err) { - bphy_err(wiphy, "Could not get rssi (%d)\n", + bphy_err(drvr, "Could not get rssi (%d)\n", err); goto done; } else { @@ -2691,6 +2711,7 @@ brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev, { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; s32 err; brcmf_dbg(TRACE, "Enter, idx %d\n", idx); @@ -2701,7 +2722,7 @@ brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev, &cfg->assoclist, sizeof(cfg->assoclist)); if (err) { - bphy_err(wiphy, "BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n", + bphy_err(drvr, "BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n", err); cfg->assoclist.count = 0; return -EOPNOTSUPP; @@ -2722,6 +2743,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, s32 err = 0; struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; brcmf_dbg(TRACE, "Enter\n"); @@ -2750,9 +2772,9 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm); if (err) { if (err == -ENODEV) - bphy_err(wiphy, "net_device is not ready yet\n"); + bphy_err(drvr, "net_device is not ready yet\n"); else - bphy_err(wiphy, "error (%d)\n", err); + bphy_err(drvr, "error (%d)\n", err); } done: brcmf_dbg(TRACE, "Exit\n"); @@ -2763,6 +2785,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, struct brcmf_bss_info_le *bi) { struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; struct cfg80211_bss *bss; enum nl80211_band band; struct brcmu_chan ch; @@ -2775,7 +2798,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, struct cfg80211_inform_bss bss_data = {}; if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) { - bphy_err(wiphy, "Bss info is larger than buffer. Discarding\n"); + bphy_err(drvr, "Bss info is larger than buffer. Discarding\n"); return 0; } @@ -2834,7 +2857,7 @@ next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss) static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_scan_results *bss_list; struct brcmf_bss_info_le *bi = NULL; /* must be initialized */ s32 err = 0; @@ -2843,7 +2866,7 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg) bss_list = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; if (bss_list->count != 0 && bss_list->version != BRCMF_BSS_INFO_VERSION) { - bphy_err(wiphy, "Version %d != WL_BSS_INFO_VERSION\n", + bphy_err(drvr, "Version %d != WL_BSS_INFO_VERSION\n", bss_list->version); return -EOPNOTSUPP; } @@ -2861,6 +2884,7 @@ static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const u8 *bssid) { struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; struct ieee80211_channel *notify_channel; struct brcmf_bss_info_le *bi = NULL; struct ieee80211_supported_band *band; @@ -2888,7 +2912,7 @@ static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); if (err) { - bphy_err(wiphy, "WLC_GET_BSS_INFO failed: %d\n", err); + bphy_err(drvr, "WLC_GET_BSS_INFO failed: %d\n", err); goto CleanUp; } @@ -2942,7 +2966,7 @@ CleanUp: static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_bss_info_le *bi; const struct brcmf_tlv *tim; u16 beacon_interval; @@ -2959,7 +2983,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX); if (err) { - bphy_err(wiphy, "Could not get bss info %d\n", err); + bphy_err(drvr, "Could not get bss info %d\n", err); goto update_bss_info_out; } @@ -2984,7 +3008,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, u32 var; err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var); if (err) { - bphy_err(wiphy, "wl dtim_assoc failed (%d)\n", err); + bphy_err(drvr, "wl dtim_assoc failed (%d)\n", err); goto update_bss_info_out; } dtim_period = (u8)var; @@ -3022,10 +3046,10 @@ static void brcmf_escan_timeout(struct timer_list *t) { struct brcmf_cfg80211_info *cfg = from_timer(cfg, t, escan_timeout); - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; if (cfg->int_escan_map || cfg->scan_request) { - bphy_err(wiphy, "timer expired\n"); + bphy_err(drvr, "timer expired\n"); schedule_work(&cfg->escan_timeout_work); } } @@ -3073,8 +3097,8 @@ static s32 brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, const struct brcmf_event_msg *e, void *data) { - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_cfg80211_info *cfg = drvr->config; s32 status; struct brcmf_escan_result_le *escan_result_le; u32 escan_buflen; @@ -3091,7 +3115,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, goto exit; if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { - bphy_err(wiphy, "scan not ready, bsscfgidx=%d\n", + bphy_err(drvr, "scan not ready, bsscfgidx=%d\n", ifp->bsscfgidx); return -EPERM; } @@ -3099,24 +3123,24 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, if (status == BRCMF_E_STATUS_PARTIAL) { brcmf_dbg(SCAN, "ESCAN Partial result\n"); if (e->datalen < sizeof(*escan_result_le)) { - bphy_err(wiphy, "invalid event data length\n"); + bphy_err(drvr, "invalid event data length\n"); goto exit; } escan_result_le = (struct brcmf_escan_result_le *) data; if (!escan_result_le) { - bphy_err(wiphy, "Invalid escan result (NULL pointer)\n"); + bphy_err(drvr, "Invalid escan result (NULL pointer)\n"); goto exit; } escan_buflen = le32_to_cpu(escan_result_le->buflen); if (escan_buflen > BRCMF_ESCAN_BUF_SIZE || escan_buflen > e->datalen || escan_buflen < sizeof(*escan_result_le)) { - bphy_err(wiphy, "Invalid escan buffer length: %d\n", + bphy_err(drvr, "Invalid escan buffer length: %d\n", escan_buflen); goto exit; } if (le16_to_cpu(escan_result_le->bss_count) != 1) { - bphy_err(wiphy, "Invalid bss_count %d: ignoring\n", + bphy_err(drvr, "Invalid bss_count %d: ignoring\n", escan_result_le->bss_count); goto exit; } @@ -3132,7 +3156,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, bi_length = le32_to_cpu(bss_info_le->length); if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) { - bphy_err(wiphy, "Ignoring invalid bss_info length: %d\n", + bphy_err(drvr, "Ignoring invalid bss_info length: %d\n", bi_length); goto exit; } @@ -3141,7 +3165,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, BIT(NL80211_IFTYPE_ADHOC))) { if (le16_to_cpu(bss_info_le->capability) & WLAN_CAPABILITY_IBSS) { - bphy_err(wiphy, "Ignoring IBSS result\n"); + bphy_err(drvr, "Ignoring IBSS result\n"); goto exit; } } @@ -3149,7 +3173,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, list = (struct brcmf_scan_results *) cfg->escan_info.escan_buf; if (bi_length > BRCMF_ESCAN_BUF_SIZE - list->buflen) { - bphy_err(wiphy, "Buffer is too small: ignoring\n"); + bphy_err(drvr, "Buffer is too small: ignoring\n"); goto exit; } @@ -3308,7 +3332,8 @@ static s32 brcmf_notify_sched_scan_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, void *data) { - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_cfg80211_info *cfg = drvr->config; struct brcmf_pno_net_info_le *netinfo, *netinfo_start; struct cfg80211_scan_request *request = NULL; struct wiphy *wiphy = cfg_to_wiphy(cfg); @@ -3341,14 +3366,14 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE); brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count); if (!result_count) { - bphy_err(wiphy, "FALSE PNO Event. (pfn_count == 0)\n"); + bphy_err(drvr, "FALSE PNO Event. (pfn_count == 0)\n"); goto out_err; } netinfo_start = brcmf_get_netinfo_array(pfn_result); datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result); if (datalen < result_count * sizeof(*netinfo)) { - bphy_err(wiphy, "insufficient event data\n"); + bphy_err(drvr, "insufficient event data\n"); goto out_err; } @@ -3395,14 +3420,15 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_sched_scan_request *req) { - struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n", req->n_match_sets, req->n_ssids); if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { - bphy_err(wiphy, "Scanning suppressed: status=%lu\n", + bphy_err(drvr, "Scanning suppressed: status=%lu\n", cfg->scan_status); return -EAGAIN; } @@ -3481,8 +3507,8 @@ static s32 brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, void *data) { - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_cfg80211_info *cfg = drvr->config; struct brcmf_pno_scanresults_le *pfn_result; struct brcmf_pno_net_info_le *netinfo; @@ -3501,7 +3527,7 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, } if (le32_to_cpu(pfn_result->count) < 1) { - bphy_err(wiphy, "Invalid result count, expected 1 (%d)\n", + bphy_err(drvr, "Invalid result count, expected 1 (%d)\n", le32_to_cpu(pfn_result->count)); return -EINVAL; } @@ -3531,6 +3557,7 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_wowl_wakeind_le wake_ind_le; struct cfg80211_wowlan_wakeup wakeup_data; struct cfg80211_wowlan_wakeup *wakeup; @@ -3541,7 +3568,7 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp) err = brcmf_fil_iovar_data_get(ifp, "wowl_wakeind", &wake_ind_le, sizeof(wake_ind_le)); if (err) { - bphy_err(wiphy, "Get wowl_wakeind failed, err = %d\n", err); + bphy_err(drvr, "Get wowl_wakeind failed, err = %d\n", err); return; } @@ -3582,7 +3609,7 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp) cfg->wowl.nd_data_completed, BRCMF_ND_INFO_TIMEOUT); if (!timeout) - bphy_err(wiphy, "No result for wowl net detect\n"); + bphy_err(drvr, "No result for wowl net detect\n"); else wakeup_data.net_detect = cfg->wowl.nd_info; } @@ -3771,6 +3798,7 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0]; + struct brcmf_pub *drvr = cfg->pub; s32 err; u32 npmk, i; @@ -3790,7 +3818,7 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, cfg->pmk_list.npmk = cpu_to_le32(npmk); } } else { - bphy_err(wiphy, "Too many PMKSA entries cached %d\n", npmk); + bphy_err(drvr, "Too many PMKSA entries cached %d\n", npmk); return -EINVAL; } @@ -3813,6 +3841,7 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0]; + struct brcmf_pub *drvr = cfg->pub; s32 err; u32 npmk, i; @@ -3836,7 +3865,7 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, memset(&pmk[i], 0, sizeof(*pmk)); cfg->pmk_list.npmk = cpu_to_le32(npmk - 1); } else { - bphy_err(wiphy, "Cache entry not found\n"); + bphy_err(drvr, "Cache entry not found\n"); return -EINVAL; } @@ -3868,20 +3897,20 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; s32 err; s32 wpa_val; /* set auth */ err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0); if (err < 0) { - bphy_err(wiphy, "auth error %d\n", err); + bphy_err(drvr, "auth error %d\n", err); return err; } /* set wsec */ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0); if (err < 0) { - bphy_err(wiphy, "wsec error %d\n", err); + bphy_err(drvr, "wsec error %d\n", err); return err; } /* set upper-layer auth */ @@ -3891,7 +3920,7 @@ static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) wpa_val = WPA_AUTH_DISABLED; err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_val); if (err < 0) { - bphy_err(wiphy, "wpa_auth error %d\n", err); + bphy_err(drvr, "wpa_auth error %d\n", err); return err; } @@ -3911,7 +3940,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, const struct brcmf_vs_tlv *wpa_ie, bool is_rsn_ie) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; u32 auth = 0; /* d11 open authentication */ u16 count; s32 err = 0; @@ -3942,13 +3971,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, /* check for multicast cipher suite */ if (offset + WPA_IE_MIN_OUI_LEN > len) { err = -EINVAL; - bphy_err(wiphy, "no multicast cipher suite\n"); + bphy_err(drvr, "no multicast cipher suite\n"); goto exit; } if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { err = -EINVAL; - bphy_err(wiphy, "ivalid OUI\n"); + bphy_err(drvr, "ivalid OUI\n"); goto exit; } offset += TLV_OUI_LEN; @@ -3970,7 +3999,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, break; default: err = -EINVAL; - bphy_err(wiphy, "Invalid multi cast cipher info\n"); + bphy_err(drvr, "Invalid multi cast cipher info\n"); goto exit; } @@ -3981,13 +4010,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, /* Check for unicast suite(s) */ if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) { err = -EINVAL; - bphy_err(wiphy, "no unicast cipher suite\n"); + bphy_err(drvr, "no unicast cipher suite\n"); goto exit; } for (i = 0; i < count; i++) { if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { err = -EINVAL; - bphy_err(wiphy, "ivalid OUI\n"); + bphy_err(drvr, "ivalid OUI\n"); goto exit; } offset += TLV_OUI_LEN; @@ -4005,7 +4034,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, pval |= AES_ENABLED; break; default: - bphy_err(wiphy, "Invalid unicast security info\n"); + bphy_err(drvr, "Invalid unicast security info\n"); } offset++; } @@ -4015,13 +4044,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, /* Check for auth key management suite(s) */ if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) { err = -EINVAL; - bphy_err(wiphy, "no auth key mgmt suite\n"); + bphy_err(drvr, "no auth key mgmt suite\n"); goto exit; } for (i = 0; i < count; i++) { if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { err = -EINVAL; - bphy_err(wiphy, "ivalid OUI\n"); + bphy_err(drvr, "ivalid OUI\n"); goto exit; } offset += TLV_OUI_LEN; @@ -4049,7 +4078,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, wpa_auth |= WPA2_AUTH_1X_SHA256; break; default: - bphy_err(wiphy, "Invalid key mgmt info\n"); + bphy_err(drvr, "Invalid key mgmt info\n"); } offset++; } @@ -4091,7 +4120,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable", wme_bss_disable); if (err < 0) { - bphy_err(wiphy, "wme_bss_disable error %d\n", err); + bphy_err(drvr, "wme_bss_disable error %d\n", err); goto exit; } @@ -4105,7 +4134,7 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, &data[offset], WPA_IE_MIN_OUI_LEN); if (err < 0) { - bphy_err(wiphy, "bip error %d\n", err); + bphy_err(drvr, "bip error %d\n", err); goto exit; } } @@ -4116,13 +4145,13 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, /* set auth */ err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth); if (err < 0) { - bphy_err(wiphy, "auth error %d\n", err); + bphy_err(drvr, "auth error %d\n", err); goto exit; } /* set wsec */ err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); if (err < 0) { - bphy_err(wiphy, "wsec error %d\n", err); + bphy_err(drvr, "wsec error %d\n", err); goto exit; } /* Configure MFP, this needs to go after wsec otherwise the wsec command @@ -4131,14 +4160,14 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) { err = brcmf_fil_bsscfg_int_set(ifp, "mfp", mfp); if (err < 0) { - bphy_err(wiphy, "mfp error %d\n", err); + bphy_err(drvr, "mfp error %d\n", err); goto exit; } } /* set upper-layer auth */ err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth); if (err < 0) { - bphy_err(wiphy, "wpa_auth error %d\n", err); + bphy_err(drvr, "wpa_auth error %d\n", err); goto exit; } @@ -4224,8 +4253,8 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, const u8 *vndr_ie_buf, u32 vndr_ie_len) { + struct brcmf_pub *drvr; struct brcmf_if *ifp; - struct wiphy *wiphy; struct vif_saved_ie *saved_ie; s32 err = 0; u8 *iovar_ie_buf; @@ -4246,7 +4275,7 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, if (!vif) return -ENODEV; ifp = vif->ifp; - wiphy = ifp->drvr->wiphy; + drvr = ifp->drvr; saved_ie = &vif->saved_ie; brcmf_dbg(TRACE, "bsscfgidx %d, pktflag : 0x%02X\n", ifp->bsscfgidx, @@ -4278,13 +4307,13 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, break; default: err = -EPERM; - bphy_err(wiphy, "not suitable type\n"); + bphy_err(drvr, "not suitable type\n"); goto exit; } if (vndr_ie_len > mgmt_ie_buf_len) { err = -ENOMEM; - bphy_err(wiphy, "extra IE size too big\n"); + bphy_err(drvr, "extra IE size too big\n"); goto exit; } @@ -4345,7 +4374,7 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, /* verify remained buf size before copy data */ if (remained_buf_len < (vndrie_info->vndrie.len + VNDR_IE_VSIE_OFFSET)) { - bphy_err(wiphy, "no space in mgmt_ie_buf: len left %d", + bphy_err(drvr, "no space in mgmt_ie_buf: len left %d", remained_buf_len); break; } @@ -4377,7 +4406,7 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf, total_ie_buf_len); if (err) - bphy_err(wiphy, "vndr ie set error : %d\n", err); + bphy_err(drvr, "vndr ie set error : %d\n", err); } exit: @@ -4405,14 +4434,14 @@ static s32 brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif, struct cfg80211_beacon_data *beacon) { - struct wiphy *wiphy = vif->ifp->drvr->wiphy; + struct brcmf_pub *drvr = vif->ifp->drvr; s32 err; /* Set Beacon IEs to FW */ err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG, beacon->tail, beacon->tail_len); if (err) { - bphy_err(wiphy, "Set Beacon IE Failed\n"); + bphy_err(drvr, "Set Beacon IE Failed\n"); return err; } brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n"); @@ -4422,7 +4451,7 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif, beacon->proberesp_ies, beacon->proberesp_ies_len); if (err) - bphy_err(wiphy, "Set Probe Resp IE Failed\n"); + bphy_err(drvr, "Set Probe Resp IE Failed\n"); else brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n"); @@ -4436,6 +4465,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, s32 ie_offset; struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; const struct brcmf_tlv *ssid_ie; const struct brcmf_tlv *country_ie; struct brcmf_ssid_le ssid_le; @@ -4531,7 +4561,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, is_11d); if (err < 0) { - bphy_err(wiphy, "Regulatory Set Error, %d\n", + bphy_err(drvr, "Regulatory Set Error, %d\n", err); goto exit; } @@ -4540,7 +4570,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, settings->beacon_interval); if (err < 0) { - bphy_err(wiphy, "Beacon Interval Set Error, %d\n", + bphy_err(drvr, "Beacon Interval Set Error, %d\n", err); goto exit; } @@ -4549,7 +4579,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD, settings->dtim_period); if (err < 0) { - bphy_err(wiphy, "DTIM Interval Set Error, %d\n", + bphy_err(drvr, "DTIM Interval Set Error, %d\n", err); goto exit; } @@ -4560,7 +4590,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, !brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB))) { err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); if (err < 0) { - bphy_err(wiphy, "BRCMF_C_DOWN error %d\n", + bphy_err(drvr, "BRCMF_C_DOWN error %d\n", err); goto exit; } @@ -4569,7 +4599,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1); if (err < 0) { - bphy_err(wiphy, "SET INFRA error %d\n", err); + bphy_err(drvr, "SET INFRA error %d\n", err); goto exit; } } else if (WARN_ON(supports_11d && (is_11d != ifp->vif->is_11d))) { @@ -4585,7 +4615,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1); if (err < 0) { - bphy_err(wiphy, "setting AP mode failed %d\n", + bphy_err(drvr, "setting AP mode failed %d\n", err); goto exit; } @@ -4595,14 +4625,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, */ err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec); if (err < 0) { - bphy_err(wiphy, "Set Channel failed: chspec=%d, %d\n", + bphy_err(drvr, "Set Channel failed: chspec=%d, %d\n", chanspec, err); goto exit; } } err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); if (err < 0) { - bphy_err(wiphy, "BRCMF_C_UP error (%d)\n", err); + bphy_err(drvr, "BRCMF_C_UP error (%d)\n", err); goto exit; } /* On DOWN the firmware removes the WEP keys, reconfigure @@ -4617,14 +4647,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, sizeof(join_params)); if (err < 0) { - bphy_err(wiphy, "SET SSID error (%d)\n", err); + bphy_err(drvr, "SET SSID error (%d)\n", err); goto exit; } if (settings->hidden_ssid) { err = brcmf_fil_iovar_int_set(ifp, "closednet", 1); if (err) { - bphy_err(wiphy, "closednet error (%d)\n", err); + bphy_err(drvr, "closednet error (%d)\n", err); goto exit; } } @@ -4633,14 +4663,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, } else if (dev_role == NL80211_IFTYPE_P2P_GO) { err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec); if (err < 0) { - bphy_err(wiphy, "Set Channel failed: chspec=%d, %d\n", + bphy_err(drvr, "Set Channel failed: chspec=%d, %d\n", chanspec, err); goto exit; } err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le, sizeof(ssid_le)); if (err < 0) { - bphy_err(wiphy, "setting ssid failed %d\n", err); + bphy_err(drvr, "setting ssid failed %d\n", err); goto exit; } bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx); @@ -4648,7 +4678,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, sizeof(bss_enable)); if (err < 0) { - bphy_err(wiphy, "bss_enable config failed %d\n", err); + bphy_err(drvr, "bss_enable config failed %d\n", err); goto exit; } @@ -4671,7 +4701,9 @@ exit: static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = cfg->pub; s32 err; struct brcmf_fil_bss_enable_le bss_enable; struct brcmf_join_params join_params; @@ -4696,13 +4728,13 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, sizeof(join_params)); if (err < 0) - bphy_err(wiphy, "SET SSID error (%d)\n", err); + bphy_err(drvr, "SET SSID error (%d)\n", err); err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); if (err < 0) - bphy_err(wiphy, "BRCMF_C_DOWN error %d\n", err); + bphy_err(drvr, "BRCMF_C_DOWN error %d\n", err); err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0); if (err < 0) - bphy_err(wiphy, "setting AP mode failed %d\n", err); + bphy_err(drvr, "setting AP mode failed %d\n", err); if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) brcmf_fil_iovar_int_set(ifp, "mbss", 0); brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, @@ -4710,7 +4742,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) /* Bring device back up so it can be used again */ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); if (err < 0) - bphy_err(wiphy, "BRCMF_C_UP error %d\n", err); + bphy_err(drvr, "BRCMF_C_UP error %d\n", err); brcmf_vif_clear_mgmt_ies(ifp->vif); } else { @@ -4719,7 +4751,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, sizeof(bss_enable)); if (err < 0) - bphy_err(wiphy, "bss_enable config failed %d\n", err); + bphy_err(drvr, "bss_enable config failed %d\n", err); } brcmf_set_mpc(ifp, 1); brcmf_configure_arp_nd_offload(ifp, true); @@ -4748,6 +4780,7 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_scb_val_le scbval; struct brcmf_if *ifp = netdev_priv(ndev); s32 err; @@ -4767,7 +4800,7 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scbval)); if (err) - bphy_err(wiphy, "SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", + bphy_err(drvr, "SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); brcmf_dbg(TRACE, "Exit\n"); @@ -4778,6 +4811,8 @@ static int brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_parameters *params) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_if *ifp = netdev_priv(ndev); s32 err; @@ -4798,7 +4833,7 @@ brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_DEAUTHORIZE, (void *)mac, ETH_ALEN); if (err < 0) - bphy_err(wiphy, "Setting SCB (de-)authorize failed, %d\n", err); + bphy_err(drvr, "Setting SCB (de-)authorize failed, %d\n", err); return err; } @@ -4828,6 +4863,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct ieee80211_channel *chan = params->chan; + struct brcmf_pub *drvr = cfg->pub; const u8 *buf = params->buf; size_t len = params->len; const struct ieee80211_mgmt *mgmt; @@ -4848,7 +4884,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, mgmt = (const struct ieee80211_mgmt *)buf; if (!ieee80211_is_mgmt(mgmt->frame_control)) { - bphy_err(wiphy, "Driver only allows MGMT packet type\n"); + bphy_err(drvr, "Driver only allows MGMT packet type\n"); return -EPERM; } @@ -4879,13 +4915,13 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, GFP_KERNEL); } else if (ieee80211_is_action(mgmt->frame_control)) { if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) { - bphy_err(wiphy, "invalid action frame length\n"); + bphy_err(drvr, "invalid action frame length\n"); err = -EINVAL; goto exit; } af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); if (af_params == NULL) { - bphy_err(wiphy, "unable to allocate frame\n"); + bphy_err(drvr, "unable to allocate frame\n"); err = -ENOMEM; goto exit; } @@ -4936,6 +4972,7 @@ brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, u64 cookie) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_cfg80211_vif *vif; int err = 0; @@ -4943,7 +4980,7 @@ brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; if (vif == NULL) { - bphy_err(wiphy, "No p2p device available for probe response\n"); + bphy_err(drvr, "No p2p device available for probe response\n"); err = -ENODEV; goto exit; } @@ -4958,6 +4995,7 @@ static int brcmf_cfg80211_get_channel(struct wiphy *wiphy, { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct net_device *ndev = wdev->netdev; + struct brcmf_pub *drvr = cfg->pub; struct brcmf_if *ifp; struct brcmu_chan ch; enum nl80211_band band = 0; @@ -4971,7 +5009,7 @@ static int brcmf_cfg80211_get_channel(struct wiphy *wiphy, err = brcmf_fil_iovar_int_get(ifp, "chanspec", &chanspec); if (err) { - bphy_err(wiphy, "chanspec failed (%d)\n", err); + bphy_err(drvr, "chanspec failed (%d)\n", err); return err; } @@ -5093,6 +5131,8 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *ndev, const u8 *peer, enum nl80211_tdls_operation oper) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_if *ifp; struct brcmf_tdls_iovar_le info; int ret = 0; @@ -5110,7 +5150,7 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy, ret = brcmf_fil_iovar_data_set(ifp, "tdls_endpoint", &info, sizeof(info)); if (ret < 0) - bphy_err(wiphy, "tdls_endpoint iovar failed: ret=%d\n", ret); + bphy_err(drvr, "tdls_endpoint iovar failed: ret=%d\n", ret); return ret; } @@ -5121,6 +5161,8 @@ brcmf_cfg80211_update_conn_params(struct wiphy *wiphy, struct cfg80211_connect_params *sme, u32 changed) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_if *ifp; int err; @@ -5131,7 +5173,7 @@ brcmf_cfg80211_update_conn_params(struct wiphy *wiphy, err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); if (err) - bphy_err(wiphy, "Set Assoc REQ IE Failed\n"); + bphy_err(drvr, "Set Assoc REQ IE Failed\n"); else brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n"); @@ -5143,6 +5185,8 @@ static int brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_gtk_rekey_data *gtk) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_gtk_keyinfo_le gtk_le; int ret; @@ -5157,7 +5201,7 @@ brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev, ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", >k_le, sizeof(gtk_le)); if (ret < 0) - bphy_err(wiphy, "gtk_key_info iovar failed: ret=%d\n", ret); + bphy_err(drvr, "gtk_key_info iovar failed: ret=%d\n", ret); return ret; } @@ -5389,7 +5433,7 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_cfg80211_assoc_ielen_le *assoc_info; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); u32 req_len; @@ -5401,7 +5445,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_iovar_data_get(ifp, "assoc_info", cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { - bphy_err(wiphy, "could not get assoc info (%d)\n", err); + bphy_err(drvr, "could not get assoc info (%d)\n", err); return err; } assoc_info = @@ -5413,7 +5457,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { - bphy_err(wiphy, "could not get assoc req (%d)\n", err); + bphy_err(drvr, "could not get assoc req (%d)\n", err); return err; } conn_info->req_ie_len = req_len; @@ -5429,7 +5473,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { - bphy_err(wiphy, "could not get assoc resp (%d)\n", err); + bphy_err(drvr, "could not get assoc resp (%d)\n", err); return err; } conn_info->resp_ie_len = resp_len; @@ -5556,7 +5600,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; static int generation; u32 event = e->event_code; u32 reason = e->reason; @@ -5574,7 +5618,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) && (reason == BRCMF_E_STATUS_SUCCESS)) { if (!data) { - bphy_err(wiphy, "No IEs present in ASSOC/REASSOC_IND\n"); + bphy_err(drvr, "No IEs present in ASSOC/REASSOC_IND\n"); return -EINVAL; } @@ -5866,7 +5910,7 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event) static s32 brcmf_dongle_roam(struct brcmf_if *ifp) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; s32 err; u32 bcn_timeout; __le32 roamtrigger[2]; @@ -5879,7 +5923,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp) bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON; err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout); if (err) { - bphy_err(wiphy, "bcn_timeout error (%d)\n", err); + bphy_err(drvr, "bcn_timeout error (%d)\n", err); goto roam_setup_done; } @@ -5891,7 +5935,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp) err = brcmf_fil_iovar_int_set(ifp, "roam_off", ifp->drvr->settings->roamoff); if (err) { - bphy_err(wiphy, "roam_off error (%d)\n", err); + bphy_err(drvr, "roam_off error (%d)\n", err); goto roam_setup_done; } @@ -5900,7 +5944,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp) err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER, (void *)roamtrigger, sizeof(roamtrigger)); if (err) { - bphy_err(wiphy, "WLC_SET_ROAM_TRIGGER error (%d)\n", err); + bphy_err(drvr, "WLC_SET_ROAM_TRIGGER error (%d)\n", err); goto roam_setup_done; } @@ -5909,7 +5953,7 @@ static s32 brcmf_dongle_roam(struct brcmf_if *ifp) err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA, (void *)roam_delta, sizeof(roam_delta)); if (err) { - bphy_err(wiphy, "WLC_SET_ROAM_DELTA error (%d)\n", err); + bphy_err(drvr, "WLC_SET_ROAM_DELTA error (%d)\n", err); goto roam_setup_done; } @@ -5920,26 +5964,26 @@ roam_setup_done: static s32 brcmf_dongle_scantime(struct brcmf_if *ifp) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; s32 err = 0; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, BRCMF_SCAN_CHANNEL_TIME); if (err) { - bphy_err(wiphy, "Scan assoc time error (%d)\n", err); + bphy_err(drvr, "Scan assoc time error (%d)\n", err); goto dongle_scantime_out; } err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, BRCMF_SCAN_UNASSOC_TIME); if (err) { - bphy_err(wiphy, "Scan unassoc time error (%d)\n", err); + bphy_err(drvr, "Scan unassoc time error (%d)\n", err); goto dongle_scantime_out; } err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME, BRCMF_SCAN_PASSIVE_TIME); if (err) { - bphy_err(wiphy, "Scan passive time error (%d)\n", err); + bphy_err(drvr, "Scan passive time error (%d)\n", err); goto dongle_scantime_out; } @@ -5972,7 +6016,8 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap[]) { struct wiphy *wiphy = cfg_to_wiphy(cfg); - struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); + struct brcmf_pub *drvr = cfg->pub; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); struct ieee80211_supported_band *band; struct ieee80211_channel *channel; struct brcmf_chanspec_list *list; @@ -5993,7 +6038,7 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf, BRCMF_DCMD_MEDLEN); if (err) { - bphy_err(wiphy, "get chanspecs error (%d)\n", err); + bphy_err(drvr, "get chanspecs error (%d)\n", err); goto fail_pbuf; } @@ -6016,7 +6061,7 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, } else if (ch.band == BRCMU_CHAN_BAND_5G) { band = wiphy->bands[NL80211_BAND_5GHZ]; } else { - bphy_err(wiphy, "Invalid channel Spec. 0x%x.\n", + bphy_err(drvr, "Invalid channel Spec. 0x%x.\n", ch.chspec); continue; } @@ -6040,7 +6085,7 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, /* It seems firmware supports some channel we never * considered. Something new in IEEE standard? */ - bphy_err(wiphy, "Ignoring unexpected firmware channel %d\n", + bphy_err(drvr, "Ignoring unexpected firmware channel %d\n", ch.control_ch_num); continue; } @@ -6097,8 +6142,8 @@ fail_pbuf: static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); - struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); + struct brcmf_pub *drvr = cfg->pub; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); struct ieee80211_supported_band *band; struct brcmf_fil_bwcap_le band_bwcap; struct brcmf_chanspec_list *list; @@ -6144,7 +6189,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf, BRCMF_DCMD_MEDLEN); if (err) { - bphy_err(wiphy, "get chanspecs error (%d)\n", err); + bphy_err(drvr, "get chanspecs error (%d)\n", err); kfree(pbuf); return err; } @@ -6175,7 +6220,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) { - struct wiphy *wiphy = ifp->drvr->wiphy; + struct brcmf_pub *drvr = ifp->drvr; u32 band, mimo_bwcap; int err; @@ -6211,7 +6256,7 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT; break; default: - bphy_err(wiphy, "invalid mimo_bw_cap value\n"); + bphy_err(drvr, "invalid mimo_bw_cap value\n"); } } @@ -6286,7 +6331,8 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band, static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) { - struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); + struct brcmf_pub *drvr = cfg->pub; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); struct wiphy *wiphy = cfg_to_wiphy(cfg); u32 nmode = 0; u32 vhtmode = 0; @@ -6303,7 +6349,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); if (err) { - bphy_err(wiphy, "nmode error (%d)\n", err); + bphy_err(drvr, "nmode error (%d)\n", err); } else { brcmf_get_bwcap(ifp, bw_cap); } @@ -6313,7 +6359,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain); if (err) { - bphy_err(wiphy, "rxchain error (%d)\n", err); + bphy_err(drvr, "rxchain error (%d)\n", err); nchain = 1; } else { for (nchain = 0; rxchain; nchain++) @@ -6323,7 +6369,7 @@ static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) err = brcmf_construct_chaninfo(cfg, bw_cap); if (err) { - bphy_err(wiphy, "brcmf_construct_chaninfo failed (%d)\n", err); + bphy_err(drvr, "brcmf_construct_chaninfo failed (%d)\n", err); return err; } @@ -6530,12 +6576,13 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp) { #ifdef CONFIG_PM struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_pub *drvr = cfg->pub; struct wiphy_wowlan_support *wowl; wowl = kmemdup(&brcmf_wowlan_support, sizeof(brcmf_wowlan_support), GFP_KERNEL); if (!wowl) { - bphy_err(wiphy, "only support basic wowlan features\n"); + bphy_err(drvr, "only support basic wowlan features\n"); wiphy->wowlan = &brcmf_wowlan_support; return; } @@ -6632,7 +6679,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, &bandlist, sizeof(bandlist)); if (err) { - bphy_err(wiphy, "could not obtain band info: err=%d\n", err); + bphy_err(drvr, "could not obtain band info: err=%d\n", err); return err; } /* first entry in bandlist is number of bands */ @@ -6681,7 +6728,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) { - struct wiphy *wiphy = cfg_to_wiphy(cfg); + struct brcmf_pub *drvr = cfg->pub; struct net_device *ndev; struct wireless_dev *wdev; struct brcmf_if *ifp; @@ -6719,7 +6766,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1); if (err) { - bphy_err(wiphy, "failed to set frameburst mode\n"); + bphy_err(drvr, "failed to set frameburst mode\n"); goto default_conf_out; } @@ -6900,6 +6947,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_fil_country_le ccreq; s32 err; int i; @@ -6911,7 +6959,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, /* ignore non-ISO3166 country codes */ for (i = 0; i < 2; i++) if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { - bphy_err(wiphy, "not an ISO3166 code (0x%02x 0x%02x)\n", + bphy_err(drvr, "not an ISO3166 code (0x%02x 0x%02x)\n", req->alpha2[0], req->alpha2[1]); return; } @@ -6921,7 +6969,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq)); if (err) { - bphy_err(wiphy, "Country code iovar returned err = %d\n", err); + bphy_err(drvr, "Country code iovar returned err = %d\n", err); return; } @@ -6931,7 +6979,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq)); if (err) { - bphy_err(wiphy, "Firmware rejected country setting\n"); + bphy_err(drvr, "Firmware rejected country setting\n"); return; } brcmf_setup_wiphybands(cfg); @@ -6977,13 +7025,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, u16 *cap = NULL; if (!ndev) { - bphy_err(wiphy, "ndev is invalid\n"); + bphy_err(drvr, "ndev is invalid\n"); return NULL; } cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); if (!cfg) { - bphy_err(wiphy, "Could not allocate wiphy device\n"); + bphy_err(drvr, "Could not allocate wiphy device\n"); return NULL; } @@ -7004,7 +7052,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, err = wl_init_priv(cfg); if (err) { - bphy_err(wiphy, "Failed to init iwm_priv (%d)\n", err); + bphy_err(drvr, "Failed to init iwm_priv (%d)\n", err); brcmf_free_vif(vif); goto wiphy_out; } @@ -7013,7 +7061,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, /* determine d11 io type before wiphy setup */ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type); if (err) { - bphy_err(wiphy, "Failed to get D11 version (%d)\n", err); + bphy_err(drvr, "Failed to get D11 version (%d)\n", err); goto priv_out; } cfg->d11inf.io_type = (u8)io_type; @@ -7047,13 +7095,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, #endif err = wiphy_register(wiphy); if (err < 0) { - bphy_err(wiphy, "Could not register wiphy device (%d)\n", err); + bphy_err(drvr, "Could not register wiphy device (%d)\n", err); goto priv_out; } err = brcmf_setup_wiphybands(cfg); if (err) { - bphy_err(wiphy, "Setting wiphy bands failed (%d)\n", err); + bphy_err(drvr, "Setting wiphy bands failed (%d)\n", err); goto wiphy_unreg_out; } @@ -7071,24 +7119,24 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, err = brcmf_fweh_activate_events(ifp); if (err) { - bphy_err(wiphy, "FWEH activation failed (%d)\n", err); + bphy_err(drvr, "FWEH activation failed (%d)\n", err); goto wiphy_unreg_out; } err = brcmf_p2p_attach(cfg, p2pdev_forced); if (err) { - bphy_err(wiphy, "P2P initialisation failed (%d)\n", err); + bphy_err(drvr, "P2P initialisation failed (%d)\n", err); goto wiphy_unreg_out; } err = brcmf_btcoex_attach(cfg); if (err) { - bphy_err(wiphy, "BT-coex initialisation failed (%d)\n", err); + bphy_err(drvr, "BT-coex initialisation failed (%d)\n", err); brcmf_p2p_detach(&cfg->p2p); goto wiphy_unreg_out; } err = brcmf_pno_attach(cfg); if (err) { - bphy_err(wiphy, "PNO initialisation failed (%d)\n", err); + bphy_err(drvr, "PNO initialisation failed (%d)\n", err); brcmf_btcoex_detach(cfg); brcmf_p2p_detach(&cfg->p2p); goto wiphy_unreg_out; @@ -7108,7 +7156,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, /* (re-) activate FWEH event handling */ err = brcmf_fweh_activate_events(ifp); if (err) { - bphy_err(wiphy, "FWEH activation failed (%d)\n", err); + bphy_err(drvr, "FWEH activation failed (%d)\n", err); goto detach; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h index 3cf853c84a9e..2998726b62c3 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h @@ -62,12 +62,12 @@ void __brcmf_err(struct brcmf_bus *bus, const char *func, const char *fmt, ...); } while (0) #endif -#define bphy_err(wiphy, fmt, ...) \ +#define bphy_err(drvr, fmt, ...) \ do { \ if (IS_ENABLED(CONFIG_BRCMDBG) || \ IS_ENABLED(CONFIG_BRCM_TRACING) || \ net_ratelimit()) \ - wiphy_err(wiphy, "%s: " fmt, __func__, \ + wiphy_err((drvr)->wiphy, "%s: " fmt, __func__, \ ##__VA_ARGS__); \ } while (0) -- cgit v1.2.3 From e4d1b2716b8859199c28f2ac5f984bd05a146a6b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 18 Feb 2019 08:08:46 +0000 Subject: brcmfmac: remove set but not used variable 'old_state' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c: In function 'brcmf_usb_state_change': drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:578:6: warning: variable 'old_state' set but not used [-Wunused-but-set-variable] It's never used and can be removed. Signed-off-by: YueHaibing Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 50830c4341a3..e9cbfd077710 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -575,7 +575,6 @@ static void brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state) { struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus; - int old_state; brcmf_dbg(USB, "Enter, current state=%d, new state=%d\n", devinfo->bus_pub.state, state); @@ -583,7 +582,6 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state) if (devinfo->bus_pub.state == state) return; - old_state = devinfo->bus_pub.state; devinfo->bus_pub.state = state; /* update state of upper layer */ -- cgit v1.2.3 From e8242ad03883f86519869c136772c4c51338a80c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 9 Feb 2019 12:00:09 +0300 Subject: rsi: fix a typo in a debug message There is a \b (backspace) character in the message that wasn't intended. Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 2c12f0102328..b4527e609896 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -286,7 +286,7 @@ static void rsi_mac80211_cancel_hw_scan(struct ieee80211_hw *hw, common->bgscan_en = false; info.aborted = false; ieee80211_scan_completed(adapter->hw, &info); - rsi_dbg(INFO_ZONE, "Back ground scan cancelled\b\n"); + rsi_dbg(INFO_ZONE, "Back ground scan cancelled\n"); } common->hwscan = NULL; mutex_unlock(&common->mutex); -- cgit v1.2.3 From b9c767fdde6138b945fce386eb481e34a080b7d5 Mon Sep 17 00:00:00 2001 From: Siva Rebbagondla Date: Tue, 12 Feb 2019 16:58:34 +0530 Subject: rsi: fix spelling mistakes Trivial fixes to spelling mistakes in various files in rsi folder. Signed-off-by: Siva Rebbagondla Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_debugfs.c | 8 ++++---- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 2 +- drivers/net/wireless/rsi/rsi_91x_mgmt.c | 8 ++++---- drivers/net/wireless/rsi/rsi_91x_sdio.c | 4 ++-- drivers/net/wireless/rsi/rsi_91x_usb.c | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_debugfs.c b/drivers/net/wireless/rsi/rsi_91x_debugfs.c index d0c35f3e2012..c71b41e45423 100644 --- a/drivers/net/wireless/rsi/rsi_91x_debugfs.c +++ b/drivers/net/wireless/rsi/rsi_91x_debugfs.c @@ -59,7 +59,7 @@ static int rsi_sdio_stats_read(struct seq_file *seq, void *data) } /** - * rsi_sdio_stats_open() - This funtion calls single open function of seq_file + * rsi_sdio_stats_open() - This function calls single open function of seq_file * to open file and read contents from it. * @inode: Pointer to the inode structure. * @file: Pointer to the file structure. @@ -93,7 +93,7 @@ static int rsi_version_read(struct seq_file *seq, void *data) } /** - * rsi_version_open() - This funtion calls single open function of seq_file to + * rsi_version_open() - This function calls single open function of seq_file to * open file and read contents from it. * @inode: Pointer to the inode structure. * @file: Pointer to the file structure. @@ -178,7 +178,7 @@ static int rsi_stats_read(struct seq_file *seq, void *data) } /** - * rsi_stats_open() - This funtion calls single open function of seq_file to + * rsi_stats_open() - This function calls single open function of seq_file to * open file and read contents from it. * @inode: Pointer to the inode structure. * @file: Pointer to the file structure. @@ -207,7 +207,7 @@ static int rsi_debug_zone_read(struct seq_file *seq, void *data) } /** - * rsi_debug_read() - This funtion calls single open function of seq_file to + * rsi_debug_read() - This function calls single open function of seq_file to * open file and read contents from it. * @inode: Pointer to the inode structure. * @file: Pointer to the file structure. diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index b4527e609896..831046e760f8 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -1338,7 +1338,7 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw, } /** - * rsi_indicate_pkt_to_os() - This function sends recieved packet to mac80211. + * rsi_indicate_pkt_to_os() - This function sends received packet to mac80211. * @common: Pointer to the driver private structure. * @skb: Pointer to the socket buffer structure. * diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 4c2c776fc86d..8c17842ac507 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -409,8 +409,8 @@ static int rsi_load_radio_caps(struct rsi_common *common) * rsi_mgmt_pkt_to_core() - This function is the entry point for Mgmt module. * @common: Pointer to the driver private structure. * @msg: Pointer to received packet. - * @msg_len: Length of the recieved packet. - * @type: Type of recieved packet. + * @msg_len: Length of the received packet. + * @type: Type of received packet. * * Return: 0 on success, -1 on failure. */ @@ -1547,7 +1547,7 @@ int rsi_send_ps_request(struct rsi_hw *adapter, bool enable, } /** - * rsi_set_antenna() - This fuction send antenna configuration request + * rsi_set_antenna() - This function send antenna configuration request * to device * * @common: Pointer to the driver private structure. @@ -1955,7 +1955,7 @@ int rsi_handle_card_ready(struct rsi_common *common, u8 *msg) /** * rsi_mgmt_pkt_recv() - This function processes the management packets - * recieved from the hardware. + * received from the hardware. * @common: Pointer to the driver private structure. * @msg: Pointer to the received packet. * diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 764ad06cf910..3430d7a0899e 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -138,7 +138,7 @@ static int rsi_issue_sdiocommand(struct sdio_func *func, } /** - * rsi_handle_interrupt() - This function is called upon the occurence + * rsi_handle_interrupt() - This function is called upon the occurrence * of an interrupt. * @function: Pointer to the sdio_func structure. * @@ -875,7 +875,7 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter, goto fail; } - rsi_dbg(INIT_ZONE, "%s: Setup card succesfully\n", __func__); + rsi_dbg(INIT_ZONE, "%s: Setup card successfully\n", __func__); status = rsi_init_sdio_slave_regs(adapter); if (status) { diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index d31f9cd1ae90..ac0ef5ea6ffb 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -252,7 +252,7 @@ static int rsi_usb_reg_write(struct usb_device *usbdev, /** * rsi_rx_done_handler() - This function is called when a packet is received - * from USB stack. This is callback to recieve done. + * from USB stack. This is callback to receive done. * @urb: Received URB. * * Return: None. -- cgit v1.2.3 From 6f6e4f98ee52b2159a61f31bd6052783e9af2c09 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 18 Feb 2019 07:51:56 +0000 Subject: rsi: remove set but not used variables 'info, vif' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/rsi/rsi_91x_main.c: In function 'rsi_prepare_skb': drivers/net/wireless/rsi/rsi_91x_main.c:127:24: warning: variable 'vif' set but not used [-Wunused-but-set-variable] drivers/net/wireless/rsi/rsi_91x_main.c:124:28: warning: variable 'info' set but not used [-Wunused-but-set-variable] They're not used any more since 160ee2a11ce0 ("rsi: fill rx_params only once.") Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_main.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c index ca3a55ed72e4..29d83049c5f5 100644 --- a/drivers/net/wireless/rsi/rsi_91x_main.c +++ b/drivers/net/wireless/rsi/rsi_91x_main.c @@ -121,11 +121,8 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common, u32 pkt_len, u8 extended_desc) { - struct ieee80211_tx_info *info; struct sk_buff *skb = NULL; u8 payload_offset; - struct ieee80211_vif *vif; - struct ieee80211_hdr *wh; if (WARN(!pkt_len, "%s: Dummy pkt received", __func__)) return NULL; @@ -144,10 +141,7 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common, payload_offset = (extended_desc + FRAME_DESC_SZ); skb_put(skb, pkt_len); memcpy((skb->data), (buffer + payload_offset), skb->len); - wh = (struct ieee80211_hdr *)skb->data; - vif = rsi_get_vif(common->priv, wh->addr1); - info = IEEE80211_SKB_CB(skb); return skb; } -- cgit v1.2.3 From 744972b2c4d2f62e5a1dde28404ec0f359726771 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 10 Feb 2019 20:47:35 +0100 Subject: libertas_tf: lower the debug level of command trace Logging each and every command response is way too much for INFO level. Silence this, unless CONFIG_LIBERTAS_THINFIRM_DEBUG has been enabled. Signed-off-by: Lubomir Rintel Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/cmd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c index 909ac3685010..64b147dd2432 100644 --- a/drivers/net/wireless/marvell/libertas_tf/cmd.c +++ b/drivers/net/wireless/marvell/libertas_tf/cmd.c @@ -737,10 +737,9 @@ int lbtf_process_rx_command(struct lbtf_private *priv) respcmd = le16_to_cpu(resp->command); result = le16_to_cpu(resp->result); - if (net_ratelimit()) - pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n", - respcmd, le16_to_cpu(resp->seqnum), - le16_to_cpu(resp->size)); + lbtf_deb_cmd("libertastf: cmd response 0x%04x, seq %d, size %d\n", + respcmd, le16_to_cpu(resp->seqnum), + le16_to_cpu(resp->size)); if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { spin_unlock_irqrestore(&priv->driver_lock, flags); -- cgit v1.2.3 From 607076a904c435f2677fadaadd4af546279db68b Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 10 Feb 2019 20:47:49 +0100 Subject: libertas_tf: don't set URB_ZERO_PACKET on IN USB transfer It doesn't make sense and the USB core warns on each submit of such URB, easily flooding the message buffer with tracebacks. Analogous issue was fixed in regular libertas driver in commit 6528d8804780 ("libertas: don't set URB_ZERO_PACKET on IN USB transfer"). Cc: stable@vger.kernel.org Signed-off-by: Lubomir Rintel Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/if_usb.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c index 789337ea676a..6ede6168bd85 100644 --- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c +++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c @@ -433,8 +433,6 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, skb_tail_pointer(skb), MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); - cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; - lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC); -- cgit v1.2.3 From c7a5682ded7e68146c00f2bc30020ef0de152ece Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 10 Feb 2019 20:48:11 +0100 Subject: libertas_tf: move the banner to a more appropriate place Also, turn it to a dev_info() to make checkpatch.pl happy. Signed-off-by: Lubomir Rintel Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index a7cb7d06e5e6..63f86001700a 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c @@ -318,7 +318,6 @@ static int lbtf_op_start(struct ieee80211_hw *hw) goto err_prog_firmware; } - printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n"); lbtf_deb_leave(LBTF_DEB_MACOPS); return 0; @@ -649,6 +648,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) if (ieee80211_register_hw(hw)) goto err_init_adapter; + dev_info(dmdev, "libertastf: Marvell WLAN 802.11 thinfirm adapter\n"); goto done; err_init_adapter: -- cgit v1.2.3 From b723dbb313f09d238738dae5efd6d7c52f0fe25e Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 10 Feb 2019 20:48:22 +0100 Subject: libertas_tf: fix signal reporting Instead of exposing the signal-to-noise ration, calculate the actual signal level taking the noise floor into account. Also, flip the SIGNAL_DBM bit on, so that mac80211 exposes the signal level along with the station info in scan results. This fills NetworkManager's "nmcli d wifi output" output with colors, bars and joy. Signed-off-by: Lubomir Rintel Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index 63f86001700a..4c5684e22112 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c @@ -562,7 +562,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) stats.flag |= RX_FLAG_FAILED_FCS_CRC; stats.freq = priv->cur_freq; stats.band = NL80211_BAND_2GHZ; - stats.signal = prxpd->snr; + stats.signal = prxpd->snr - prxpd->nf; priv->noise = prxpd->nf; /* Marvell rate index has a hole at value 4 */ if (prxpd->rx_rate > 4) @@ -626,6 +626,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) hw->queues = 1; ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(hw, SIGNAL_DBM); hw->extra_tx_headroom = sizeof(struct txpd); memcpy(priv->channels, lbtf_channels, sizeof(lbtf_channels)); memcpy(priv->rates, lbtf_rates, sizeof(lbtf_rates)); -- cgit v1.2.3 From e97cb6ea71b03e13449726d57f2409f66e531180 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 13 Feb 2019 01:49:17 +0000 Subject: libertas_tf: remove set but not used variable 'flags' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/marvell/libertas_tf/main.c: In function 'lbtf_rx': drivers/net/wireless/marvell/libertas_tf/main.c:554:15: warning: variable 'flags' set but not used [-Wunused-but-set-variable] It never used and can be removed. Signed-off-by: YueHaibing Acked-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index 4c5684e22112..f048b57043c6 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c @@ -550,7 +550,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) struct ieee80211_rx_status stats; struct rxpd *prxpd; int need_padding; - unsigned int flags; struct ieee80211_hdr *hdr; lbtf_deb_enter(LBTF_DEB_RX); @@ -571,7 +570,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) skb_pull(skb, sizeof(struct rxpd)); hdr = (struct ieee80211_hdr *)skb->data; - flags = le32_to_cpu(*(__le32 *)(skb->data + 4)); need_padding = ieee80211_is_data_qos(hdr->frame_control); need_padding ^= ieee80211_has_a4(hdr->frame_control); -- cgit v1.2.3 From 65a576e27309120e0621f54d5c81eb9128bd56be Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 13 Feb 2019 15:59:38 +0200 Subject: mwifiex: Fix NL80211_TX_POWER_LIMITED NL80211_TX_POWER_LIMITED was treated as NL80211_TX_POWER_AUTOMATIC, which is the opposite of what should happen and can cause nasty regulatory problems. if/else converted to a switch without default to make gcc warn on unhandled enum values. Signed-off-by: Adrian Bunk Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 13 +++++++++++-- drivers/net/wireless/marvell/mwifiex/ioctl.h | 1 + drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 11 +++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 1467af22e394..9ef0fc108641 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -376,11 +376,20 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, struct mwifiex_power_cfg power_cfg; int dbm = MBM_TO_DBM(mbm); - if (type == NL80211_TX_POWER_FIXED) { + switch (type) { + case NL80211_TX_POWER_FIXED: power_cfg.is_power_auto = 0; + power_cfg.is_power_fixed = 1; power_cfg.power_level = dbm; - } else { + break; + case NL80211_TX_POWER_LIMITED: + power_cfg.is_power_auto = 0; + power_cfg.is_power_fixed = 0; + power_cfg.power_level = dbm; + break; + case NL80211_TX_POWER_AUTOMATIC: power_cfg.is_power_auto = 1; + break; } priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 48e154e1865d..0dd592ea6e83 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h @@ -267,6 +267,7 @@ struct mwifiex_ds_encrypt_key { struct mwifiex_power_cfg { u32 is_power_auto; + u32 is_power_fixed; u32 power_level; }; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index b454b5f85503..ebc0e41e5d3b 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -688,6 +688,9 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET); if (!power_cfg->is_power_auto) { + u16 dbm_min = power_cfg->is_power_fixed ? + dbm : priv->min_tx_power_level; + txp_cfg->mode = cpu_to_le32(1); pg_tlv = (struct mwifiex_types_power_group *) (buf + sizeof(struct host_cmd_ds_txpwr_cfg)); @@ -702,7 +705,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, pg->last_rate_code = 0x03; pg->modulation_class = MOD_CLASS_HR_DSSS; pg->power_step = 0; - pg->power_min = (s8) dbm; + pg->power_min = (s8) dbm_min; pg->power_max = (s8) dbm; pg++; /* Power group for modulation class OFDM */ @@ -710,7 +713,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, pg->last_rate_code = 0x07; pg->modulation_class = MOD_CLASS_OFDM; pg->power_step = 0; - pg->power_min = (s8) dbm; + pg->power_min = (s8) dbm_min; pg->power_max = (s8) dbm; pg++; /* Power group for modulation class HTBW20 */ @@ -718,7 +721,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, pg->last_rate_code = 0x20; pg->modulation_class = MOD_CLASS_HT; pg->power_step = 0; - pg->power_min = (s8) dbm; + pg->power_min = (s8) dbm_min; pg->power_max = (s8) dbm; pg->ht_bandwidth = HT_BW_20; pg++; @@ -727,7 +730,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, pg->last_rate_code = 0x20; pg->modulation_class = MOD_CLASS_HT; pg->power_step = 0; - pg->power_min = (s8) dbm; + pg->power_min = (s8) dbm_min; pg->power_max = (s8) dbm; pg->ht_bandwidth = HT_BW_40; } -- cgit v1.2.3 From 6f21ab30469d670de620f758330aca9f3433f693 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 14 Feb 2019 16:31:29 -0800 Subject: mwifiex: don't advertise IBSS features without FW support As it is, doing something like # iw phy phy0 interface add foobar type ibss on a firmware that doesn't have ad-hoc support just yields failures of HostCmd_CMD_SET_BSS_MODE, which happened to return a '-1' error code (-EPERM? not really right...) and sometimes may even crash the firmware along the way. Let's parse the firmware capability flag while registering the wiphy, so we don't allow attempting IBSS at all, and we get a proper -EOPNOTSUPP from nl80211 instead. Fixes: e267e71e68ae ("mwifiex: Disable adhoc feature based on firmware capability") Signed-off-by: Brian Norris Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 9ef0fc108641..c46f0a54a0c7 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -4319,11 +4319,13 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->mgmt_stypes = mwifiex_mgmt_stypes; wiphy->max_remain_on_channel_duration = 5000; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_AP); + if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info)) + wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); + wiphy->bands[NL80211_BAND_2GHZ] = &mwifiex_band_2ghz; if (adapter->config_bands & BAND_A) wiphy->bands[NL80211_BAND_5GHZ] = &mwifiex_band_5ghz; @@ -4383,11 +4385,13 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1; wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; - wiphy->features |= NL80211_FEATURE_HT_IBSS | - NL80211_FEATURE_INACTIVITY_TIMER | + wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER | NL80211_FEATURE_LOW_PRIORITY_SCAN | NL80211_FEATURE_NEED_OBSS_SCAN; + if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info)) + wiphy->features |= NL80211_FEATURE_HT_IBSS; + if (ISSUPP_RANDOM_MAC(adapter->fw_cap_info)) wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | -- cgit v1.2.3 From 25f87d8b63b8f2cfe21e7c59a5e90b6e0ba595f0 Mon Sep 17 00:00:00 2001 From: Keyur Patel Date: Sun, 17 Feb 2019 11:25:45 -0500 Subject: orinoco : Replace function name in string with __func__ Replace hard coded function name with __func__, to improve robustness and to conform to the Linux kernel coding style. Issue found using checkpatch. Signed-off-by: Keyur Patel Signed-off-by: Kalle Valo --- drivers/net/wireless/intersil/orinoco/mic.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intersil/orinoco/mic.c b/drivers/net/wireless/intersil/orinoco/mic.c index 709d9ab3e7bc..67b0c05afbdb 100644 --- a/drivers/net/wireless/intersil/orinoco/mic.c +++ b/drivers/net/wireless/intersil/orinoco/mic.c @@ -18,16 +18,16 @@ int orinoco_mic_init(struct orinoco_private *priv) { priv->tx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0); if (IS_ERR(priv->tx_tfm_mic)) { - printk(KERN_DEBUG "orinoco_mic_init: could not allocate " - "crypto API michael_mic\n"); + printk(KERN_DEBUG "%s: could not allocate " + "crypto API michael_mic\n", __func__); priv->tx_tfm_mic = NULL; return -ENOMEM; } priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0); if (IS_ERR(priv->rx_tfm_mic)) { - printk(KERN_DEBUG "orinoco_mic_init: could not allocate " - "crypto API michael_mic\n"); + printk(KERN_DEBUG "%s: could not allocate " + "crypto API michael_mic\n", __func__); priv->rx_tfm_mic = NULL; return -ENOMEM; } @@ -52,7 +52,7 @@ int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key, int err; if (tfm_michael == NULL) { - printk(KERN_WARNING "orinoco_mic: tfm_michael == NULL\n"); + printk(KERN_WARNING "%s: tfm_michael == NULL\n", __func__); return -1; } -- cgit v1.2.3 From b9b81d152cfbce6c99dd5f07156b61c41f98ac05 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 18 Feb 2019 07:52:26 +0000 Subject: rtl818x_pci: Remove set but not used variables 'io_addr, mem_addr' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c: In function 'rtl8180_probe': drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c:1727:15: warning: variable 'io_addr' set but not used [-Wunused-but-set-variable] drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c:1726:16: warning: variable 'mem_addr' set but not used [-Wunused-but-set-variable] They're never used since introduction. Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c index e2b1bfbcfbd4..d5f65372356b 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c @@ -1723,8 +1723,8 @@ static int rtl8180_probe(struct pci_dev *pdev, { struct ieee80211_hw *dev; struct rtl8180_priv *priv; - unsigned long mem_addr, mem_len; - unsigned int io_addr, io_len; + unsigned long mem_len; + unsigned int io_len; int err; const char *chip_name, *rf_name = NULL; u32 reg; @@ -1743,9 +1743,7 @@ static int rtl8180_probe(struct pci_dev *pdev, goto err_disable_dev; } - io_addr = pci_resource_start(pdev, 0); io_len = pci_resource_len(pdev, 0); - mem_addr = pci_resource_start(pdev, 1); mem_len = pci_resource_len(pdev, 1); if (mem_len < sizeof(struct rtl818x_csr) || -- cgit v1.2.3 From dc76bb1e12e967097048f63a76c3ff8a4f02a3b6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 18 Feb 2019 12:31:54 +0300 Subject: carl9170: clean up a clamp() call The parameter order for clamp is supposed to be clamp(value, low, high). When we write it in this order it's equivalent to min(head->plcp[3] & 0x7f, 75) which works in this context where the min is zero. But it's not a correct use of the API. Signed-off-by: Dan Carpenter Acked-by: Christian Lamparter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/carl9170/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index f7c2f19e81c1..8e154f6364a3 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -427,7 +427,7 @@ static int carl9170_rx_mac_status(struct ar9170 *ar, if (head->plcp[6] & 0x80) status->enc_flags |= RX_ENC_FLAG_SHORT_GI; - status->rate_idx = clamp(0, 75, head->plcp[3] & 0x7f); + status->rate_idx = clamp(head->plcp[3] & 0x7f, 0, 75); status->encoding = RX_ENC_HT; break; -- cgit v1.2.3 From 17ae2acd1a6f5148edd80d84194e5d7c80be360e Mon Sep 17 00:00:00 2001 From: Tomislav Požega Date: Wed, 13 Feb 2019 11:09:12 +0100 Subject: rt2x00: remove unneeded check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove band check from rf53xx channel config routine since all chips using it are single band. Signed-off-by: Tomislav Požega Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 103 ++++++++++++------------- 1 file changed, 50 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 7f813f6f8792..0165e274a884 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -2966,6 +2966,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, struct channel_info *info) { u8 rfcsr; + int idx = rf->channel-1; rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); @@ -3003,60 +3004,56 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, rt2800_freq_cal_mode1(rt2x00dev); - if (rf->channel <= 14) { - int idx = rf->channel-1; - - if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { - if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { - /* r55/r59 value array of channel 1~14 */ - static const char r55_bt_rev[] = {0x83, 0x83, - 0x83, 0x73, 0x73, 0x63, 0x53, 0x53, - 0x53, 0x43, 0x43, 0x43, 0x43, 0x43}; - static const char r59_bt_rev[] = {0x0e, 0x0e, - 0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07}; - - rt2800_rfcsr_write(rt2x00dev, 55, - r55_bt_rev[idx]); - rt2800_rfcsr_write(rt2x00dev, 59, - r59_bt_rev[idx]); - } else { - static const char r59_bt[] = {0x8b, 0x8b, 0x8b, - 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89, - 0x88, 0x88, 0x86, 0x85, 0x84}; - - rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]); - } + if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { + if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { + /* r55/r59 value array of channel 1~14 */ + static const char r55_bt_rev[] = {0x83, 0x83, + 0x83, 0x73, 0x73, 0x63, 0x53, 0x53, + 0x53, 0x43, 0x43, 0x43, 0x43, 0x43}; + static const char r59_bt_rev[] = {0x0e, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07}; + + rt2800_rfcsr_write(rt2x00dev, 55, + r55_bt_rev[idx]); + rt2800_rfcsr_write(rt2x00dev, 59, + r59_bt_rev[idx]); } else { - if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { - static const char r55_nonbt_rev[] = {0x23, 0x23, - 0x23, 0x23, 0x13, 0x13, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; - static const char r59_nonbt_rev[] = {0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x06, 0x05, 0x04, 0x04}; - - rt2800_rfcsr_write(rt2x00dev, 55, - r55_nonbt_rev[idx]); - rt2800_rfcsr_write(rt2x00dev, 59, - r59_nonbt_rev[idx]); - } else if (rt2x00_rt(rt2x00dev, RT5390) || - rt2x00_rt(rt2x00dev, RT5392) || - rt2x00_rt(rt2x00dev, RT6352)) { - static const char r59_non_bt[] = {0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, - 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86}; - - rt2800_rfcsr_write(rt2x00dev, 59, - r59_non_bt[idx]); - } else if (rt2x00_rt(rt2x00dev, RT5350)) { - static const char r59_non_bt[] = {0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, - 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06}; - - rt2800_rfcsr_write(rt2x00dev, 59, - r59_non_bt[idx]); - } + static const char r59_bt[] = {0x8b, 0x8b, 0x8b, + 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89, + 0x88, 0x88, 0x86, 0x85, 0x84}; + + rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]); + } + } else { + if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { + static const char r55_nonbt_rev[] = {0x23, 0x23, + 0x23, 0x23, 0x13, 0x13, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; + static const char r59_nonbt_rev[] = {0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x06, 0x05, 0x04, 0x04}; + + rt2800_rfcsr_write(rt2x00dev, 55, + r55_nonbt_rev[idx]); + rt2800_rfcsr_write(rt2x00dev, 59, + r59_nonbt_rev[idx]); + } else if (rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392) || + rt2x00_rt(rt2x00dev, RT6352)) { + static const char r59_non_bt[] = {0x8f, 0x8f, + 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, + 0x8a, 0x88, 0x88, 0x87, 0x87, 0x86}; + + rt2800_rfcsr_write(rt2x00dev, 59, + r59_non_bt[idx]); + } else if (rt2x00_rt(rt2x00dev, RT5350)) { + static const char r59_non_bt[] = {0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, + 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06}; + + rt2800_rfcsr_write(rt2x00dev, 59, + r59_non_bt[idx]); } } } -- cgit v1.2.3 From 5991a2ecd070ce5ef646b4e8e0bc8d99110604ed Mon Sep 17 00:00:00 2001 From: Tomislav Požega Date: Wed, 13 Feb 2019 11:09:13 +0100 Subject: rt2x00: remove confusing AGC register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Register 66 was causing issues on RT6352 if set to the same value as in MTK driver. With 1c reg value device was working fine in both HT20 and HT40 modes. Signed-off-by: Tomislav Požega Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 0165e274a884..f420b6af1f2a 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -3983,11 +3983,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_bbp_write(rt2x00dev, 196, reg); /* AGC init */ - if (rt2x00_rt(rt2x00dev, RT6352)) - reg = 0x04; - else - reg = rf->channel <= 14 ? 0x1c : 0x24; - + reg = rf->channel <= 14 ? 0x1c : 0x24; reg += 2 * rt2x00dev->lna_gain; rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); -- cgit v1.2.3 From 9ad3b55654455258a9463384edb40077439d879f Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 13 Feb 2019 11:09:14 +0100 Subject: rt2800: enable TX_PIN_CFG_LNA_PE_ bits per band Do not enable TX_PIN_CFG_LNA_PE_A* bits for 2.4GHz band and vice versa TX_PIN_CFG_LNA_PE_G* bits for 5GHz. Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index f420b6af1f2a..0c956a7f7a71 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -3893,18 +3893,24 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, switch (rt2x00dev->default_ant.rx_chain_num) { case 3: /* Turn on tertiary LNAs */ - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, + rf->channel > 14); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, + rf->channel <= 14); /* fall-through */ case 2: /* Turn on secondary LNAs */ - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, + rf->channel > 14); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, + rf->channel <= 14); /* fall-through */ case 1: /* Turn on primary LNAs */ - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, + rf->channel > 14); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, + rf->channel <= 14); break; } -- cgit v1.2.3 From 7aca14885edeab536a8cbe1e7cfeadd4c3310b9b Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 13 Feb 2019 11:09:15 +0100 Subject: rt2800: enable TX_PIN_CFG_RFRX_EN only for MT7620 The TX_PIN_CFG_RFRX_EN bit was not set on other devices than MT7620, restore old behavaviour since setting this bit maight not be correct for older devices. Fixes: 41977e86c984 ("rt2x00: add support for MT7620") Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 0c956a7f7a71..6886e09c0b27 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -3858,10 +3858,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, if (rt2x00_rt(rt2x00dev, RT3572)) rt2800_rfcsr_write(rt2x00dev, 8, 0); - if (rt2x00_rt(rt2x00dev, RT6352)) + if (rt2x00_rt(rt2x00dev, RT6352)) { tx_pin = rt2800_register_read(rt2x00dev, TX_PIN_CFG); - else + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFRX_EN, 1); + } else { tx_pin = 0; + } switch (rt2x00dev->default_ant.tx_chain_num) { case 3: @@ -3916,7 +3918,6 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFRX_EN, 1); /* mt7620 */ rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); -- cgit v1.2.3 From c7ff1bfeaf1ca69e3e401be211b55d1738d0c5fc Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 13 Feb 2019 11:09:16 +0100 Subject: rt2800: comment and simplify AGC init for RT6352 We do not need separate lines for calculating register values. Also add comment that value is different than in vendor driver. Suggested-by: Daniel Golle Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 6886e09c0b27..a03b5284a050 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -3989,9 +3989,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_bbp_write(rt2x00dev, 195, 141); rt2800_bbp_write(rt2x00dev, 196, reg); - /* AGC init */ - reg = rf->channel <= 14 ? 0x1c : 0x24; - reg += 2 * rt2x00dev->lna_gain; + /* AGC init. + * Despite the vendor driver using different values here for + * RT6352 chip, we use 0x1c for now. This may have to be changed + * once TSSI got implemented. + */ + reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2*rt2x00dev->lna_gain; rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); rt2800_iq_calibrate(rt2x00dev, rf->channel); -- cgit v1.2.3 From 3293ec232123e9a648ec5b02225cd32091ae243f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 19 Feb 2019 05:31:12 -0500 Subject: bnxt_en: Update firmware interface spec. to 1.10.0.47. Firmware error recover is the major change in this spec. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 196 +++++++++++++++++++++++--- 1 file changed, 177 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index 0a0995894ddb..b6c610339501 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -1,7 +1,7 @@ /* Broadcom NetXtreme-C/E network driver. * * Copyright (c) 2014-2016 Broadcom Corporation - * Copyright (c) 2016-2018 Broadcom Limited + * Copyright (c) 2016-2019 Broadcom Limited * * 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 @@ -98,6 +98,7 @@ struct hwrm_short_input { struct cmd_nums { __le16 req_type; #define HWRM_VER_GET 0x0UL + #define HWRM_ERROR_RECOVERY_QCFG 0xcUL #define HWRM_FUNC_DRV_IF_CHANGE 0xdUL #define HWRM_FUNC_BUF_UNRGTR 0xeUL #define HWRM_FUNC_VF_CFG 0xfUL @@ -221,6 +222,7 @@ struct cmd_nums { #define HWRM_CFA_METER_PROFILE_CFG 0xf7UL #define HWRM_CFA_METER_INSTANCE_ALLOC 0xf8UL #define HWRM_CFA_METER_INSTANCE_FREE 0xf9UL + #define HWRM_CFA_METER_INSTANCE_CFG 0xfaUL #define HWRM_CFA_VFR_ALLOC 0xfdUL #define HWRM_CFA_VFR_FREE 0xfeUL #define HWRM_CFA_VF_PAIR_ALLOC 0x100UL @@ -269,6 +271,7 @@ struct cmd_nums { #define HWRM_ENGINE_CKV_FLUSH 0x133UL #define HWRM_ENGINE_CKV_RNG_GET 0x134UL #define HWRM_ENGINE_CKV_KEY_GEN 0x135UL + #define HWRM_ENGINE_CKV_KEY_LABEL_CFG 0x136UL #define HWRM_ENGINE_QG_CONFIG_QUERY 0x13cUL #define HWRM_ENGINE_QG_QUERY 0x13dUL #define HWRM_ENGINE_QG_METER_PROFILE_CONFIG_QUERY 0x13eUL @@ -296,6 +299,7 @@ struct cmd_nums { #define HWRM_ENGINE_NQ_ALLOC 0x162UL #define HWRM_ENGINE_NQ_FREE 0x163UL #define HWRM_ENGINE_ON_DIE_RQE_CREDITS 0x164UL + #define HWRM_ENGINE_FUNC_QCFG 0x165UL #define HWRM_FUNC_RESOURCE_QCAPS 0x190UL #define HWRM_FUNC_VF_RESOURCE_CFG 0x191UL #define HWRM_FUNC_BACKING_STORE_QCAPS 0x192UL @@ -379,15 +383,15 @@ struct hwrm_err_output { }; #define HWRM_NA_SIGNATURE ((__le32)(-1)) #define HWRM_MAX_REQ_LEN 128 -#define HWRM_MAX_RESP_LEN 280 +#define HWRM_MAX_RESP_LEN 704 #define HW_HASH_INDEX_SIZE 0x80 #define HW_HASH_KEY_SIZE 40 #define HWRM_RESP_VALID_KEY 1 #define HWRM_VERSION_MAJOR 1 #define HWRM_VERSION_MINOR 10 #define HWRM_VERSION_UPDATE 0 -#define HWRM_VERSION_RSVD 35 -#define HWRM_VERSION_STR "1.10.0.35" +#define HWRM_VERSION_RSVD 47 +#define HWRM_VERSION_STR "1.10.0.47" /* hwrm_ver_get_input (size:192b/24B) */ struct hwrm_ver_get_input { @@ -580,6 +584,7 @@ struct hwrm_async_event_cmpl { #define ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL #define ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE 0x7UL #define ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY 0x8UL + #define ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY 0x9UL #define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD 0x10UL #define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD 0x11UL #define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_FLR_PROC_CMPLT 0x12UL @@ -595,6 +600,9 @@ struct hwrm_async_event_cmpl { #define ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION 0x37UL #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_CACHE_FLUSH_REQ 0x38UL #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_CACHE_FLUSH_DONE 0x39UL + #define ASYNC_EVENT_CMPL_EVENT_ID_TCP_FLAG_ACTION_CHANGE 0x3aUL + #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_FLOW_ACTIVE 0x3bUL + #define ASYNC_EVENT_CMPL_EVENT_ID_EEM_CFG_CHANGE 0x3cUL #define ASYNC_EVENT_CMPL_EVENT_ID_FW_TRACE_MSG 0xfeUL #define ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR 0xffUL #define ASYNC_EVENT_CMPL_EVENT_ID_LAST ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR @@ -724,6 +732,30 @@ struct hwrm_async_event_cmpl_reset_notify { #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_DELAY_IN_100MS_TICKS_SFT 16 }; +/* hwrm_async_event_cmpl_error_recovery (size:128b/16B) */ +struct hwrm_async_event_cmpl_error_recovery { + __le16 type; + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_MASK 0x3fUL + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_SFT 0 + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_HWRM_ASYNC_EVENT 0x2eUL + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_LAST ASYNC_EVENT_CMPL_ERROR_RECOVERY_TYPE_HWRM_ASYNC_EVENT + __le16 event_id; + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_ID_ERROR_RECOVERY 0x9UL + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_ID_LAST ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_ID_ERROR_RECOVERY + __le32 event_data2; + u8 opaque_v; + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_V 0x1UL + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_OPAQUE_MASK 0xfeUL + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_OPAQUE_SFT 1 + u8 timestamp_lo; + __le16 timestamp_hi; + __le32 event_data1; + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_MASK 0xffUL + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_SFT 0 + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_MASTER_FUNC 0x1UL + #define ASYNC_EVENT_CMPL_ERROR_RECOVERY_EVENT_DATA1_FLAGS_RECOVERY_ENABLED 0x2UL +}; + /* hwrm_async_event_cmpl_vf_cfg_change (size:128b/16B) */ struct hwrm_async_event_cmpl_vf_cfg_change { __le16 type; @@ -1014,6 +1046,7 @@ struct hwrm_func_qcaps_output { #define FUNC_QCAPS_RESP_FLAGS_WCB_PUSH_MODE 0x100000UL #define FUNC_QCAPS_RESP_FLAGS_DYNAMIC_TX_RING_ALLOC 0x200000UL #define FUNC_QCAPS_RESP_FLAGS_HOT_RESET_CAPABLE 0x400000UL + #define FUNC_QCAPS_RESP_FLAGS_ERROR_RECOVERY_CAPABLE 0x800000UL u8 mac_address[6]; __le16 max_rsscos_ctx; __le16 max_cmpl_rings; @@ -1185,6 +1218,7 @@ struct hwrm_func_cfg_input { #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE 0x200000UL #define FUNC_CFG_REQ_FLAGS_DYNAMIC_TX_RING_ALLOC 0x400000UL #define FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST 0x800000UL + #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_DISABLE 0x1000000UL __le32 enables; #define FUNC_CFG_REQ_ENABLES_MTU 0x1UL #define FUNC_CFG_REQ_ENABLES_MRU 0x2UL @@ -1390,6 +1424,7 @@ struct hwrm_func_drv_rgtr_input { #define FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE 0x4UL #define FUNC_DRV_RGTR_REQ_FLAGS_FLOW_HANDLE_64BIT_MODE 0x8UL #define FUNC_DRV_RGTR_REQ_FLAGS_HOT_RESET_SUPPORT 0x10UL + #define FUNC_DRV_RGTR_REQ_FLAGS_ERROR_RECOVERY_SUPPORT 0x20UL __le32 enables; #define FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE 0x1UL #define FUNC_DRV_RGTR_REQ_ENABLES_VER 0x2UL @@ -2024,6 +2059,89 @@ struct hwrm_func_backing_store_cfg_output { u8 valid; }; +/* hwrm_error_recovery_qcfg_input (size:192b/24B) */ +struct hwrm_error_recovery_qcfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 unused_0[8]; +}; + +/* hwrm_error_recovery_qcfg_output (size:1664b/208B) */ +struct hwrm_error_recovery_qcfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 flags; + #define ERROR_RECOVERY_QCFG_RESP_FLAGS_HOST 0x1UL + #define ERROR_RECOVERY_QCFG_RESP_FLAGS_CO_CPU 0x2UL + __le32 driver_polling_freq; + __le32 master_func_wait_period; + __le32 normal_func_wait_period; + __le32 master_func_wait_period_after_reset; + __le32 max_bailout_time_after_reset; + __le32 fw_health_status_reg; + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_MASK 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_SFT 0 + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_PCIE_CFG 0x0UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_GRC 0x1UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_BAR0 0x2UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_BAR1 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SPACE_BAR1 + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_MASK 0xfffffffcUL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEALTH_STATUS_REG_ADDR_SFT 2 + __le32 fw_heartbeat_reg; + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_MASK 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_SFT 0 + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_PCIE_CFG 0x0UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_GRC 0x1UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_BAR0 0x2UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_BAR1 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SPACE_BAR1 + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_MASK 0xfffffffcUL + #define ERROR_RECOVERY_QCFG_RESP_FW_HEARTBEAT_REG_ADDR_SFT 2 + __le32 fw_reset_cnt_reg; + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_MASK 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_SFT 0 + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_PCIE_CFG 0x0UL + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_GRC 0x1UL + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_BAR0 0x2UL + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_BAR1 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SPACE_BAR1 + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_MASK 0xfffffffcUL + #define ERROR_RECOVERY_QCFG_RESP_FW_RESET_CNT_REG_ADDR_SFT 2 + __le32 reset_inprogress_reg; + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_MASK 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_SFT 0 + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_PCIE_CFG 0x0UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_GRC 0x1UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_BAR0 0x2UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_BAR1 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SPACE_BAR1 + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_MASK 0xfffffffcUL + #define ERROR_RECOVERY_QCFG_RESP_RESET_INPROGRESS_REG_ADDR_SFT 2 + __le32 reset_inprogress_reg_mask; + u8 unused_0[3]; + u8 reg_array_cnt; + __le32 reset_reg[16]; + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_MASK 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_SFT 0 + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_PCIE_CFG 0x0UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_GRC 0x1UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_BAR0 0x2UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_BAR1 0x3UL + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_LAST ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SPACE_BAR1 + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_MASK 0xfffffffcUL + #define ERROR_RECOVERY_QCFG_RESP_RESET_REG_ADDR_SFT 2 + __le32 reset_reg_val[16]; + u8 delay_after_reset[16]; + u8 unused_1[7]; + u8 valid; +}; + /* hwrm_func_drv_if_change_input (size:192b/24B) */ struct hwrm_func_drv_if_change_input { __le16 req_type; @@ -2955,6 +3073,7 @@ struct hwrm_port_phy_qcaps_output { #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_100GB 0x800UL #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_10MBHD 0x1000UL #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_10MB 0x2000UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_FORCE_MODE_200GB 0x4000UL __le16 supported_speeds_auto_mode; #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100MBHD 0x1UL #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100MB 0x2UL @@ -2970,6 +3089,7 @@ struct hwrm_port_phy_qcaps_output { #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_100GB 0x800UL #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_10MBHD 0x1000UL #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_10MB 0x2000UL + #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_AUTO_MODE_200GB 0x4000UL __le16 supported_speeds_eee_mode; #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_RSVD1 0x1UL #define PORT_PHY_QCAPS_RESP_SUPPORTED_SPEEDS_EEE_MODE_100MB 0x2UL @@ -4919,6 +5039,35 @@ struct hwrm_ring_free_output { u8 valid; }; +/* hwrm_ring_reset_input (size:192b/24B) */ +struct hwrm_ring_reset_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 ring_type; + #define RING_RESET_REQ_RING_TYPE_L2_CMPL 0x0UL + #define RING_RESET_REQ_RING_TYPE_TX 0x1UL + #define RING_RESET_REQ_RING_TYPE_RX 0x2UL + #define RING_RESET_REQ_RING_TYPE_ROCE_CMPL 0x3UL + #define RING_RESET_REQ_RING_TYPE_LAST RING_RESET_REQ_RING_TYPE_ROCE_CMPL + u8 unused_0; + __le16 ring_id; + u8 unused_1[4]; +}; + +/* hwrm_ring_reset_output (size:128b/16B) */ +struct hwrm_ring_reset_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 unused_0[4]; + u8 consumer_idx[3]; + u8 valid; +}; + /* hwrm_ring_aggint_qcaps_input (size:128b/16B) */ struct hwrm_ring_aggint_qcaps_input { __le16 req_type; @@ -5446,19 +5595,21 @@ struct hwrm_cfa_encap_record_alloc_input { __le64 resp_addr; __le32 flags; #define CFA_ENCAP_RECORD_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_FLAGS_EXTERNAL 0x2UL u8 encap_type; - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN 0x1UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_NVGRE 0x2UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2GRE 0x3UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPIP 0x4UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_GENEVE 0x5UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_MPLS 0x6UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VLAN 0x7UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE 0x8UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN_V4 0x9UL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE_V1 0xaUL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2_ETYPE 0xbUL - #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_LAST CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2_ETYPE + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN 0x1UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_NVGRE 0x2UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2GRE 0x3UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPIP 0x4UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_GENEVE 0x5UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_MPLS 0x6UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VLAN 0x7UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE 0x8UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN_V4 0x9UL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE_V1 0xaUL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2_ETYPE 0xbUL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN_GPE_V6 0xcUL + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_LAST CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN_GPE_V6 u8 unused_0[3]; __le32 encap_data[20]; }; @@ -5506,6 +5657,7 @@ struct hwrm_cfa_ntuple_filter_alloc_input { #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DROP 0x2UL #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_METER 0x4UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DEST_FID 0x8UL __le32 enables; #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID 0x1UL #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_ETHERTYPE 0x2UL @@ -5627,7 +5779,8 @@ struct hwrm_cfa_ntuple_filter_cfg_input { #define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_DST_ID 0x1UL #define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_MIRROR_VNIC_ID 0x2UL #define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_METER_INSTANCE_ID 0x4UL - u8 unused_0[4]; + __le32 flags; + #define CFA_NTUPLE_FILTER_CFG_REQ_FLAGS_DEST_FID 0x1UL __le64 ntuple_filter_id; __le32 new_dst_id; __le32 new_mirror_vnic_id; @@ -5892,13 +6045,15 @@ struct hwrm_cfa_flow_info_input { __le64 ext_flow_handle; }; -/* hwrm_cfa_flow_info_output (size:448b/56B) */ +/* hwrm_cfa_flow_info_output (size:5632b/704B) */ struct hwrm_cfa_flow_info_output { __le16 error_code; __le16 req_type; __le16 seq_id; __le16 resp_len; u8 flags; + #define CFA_FLOW_INFO_RESP_FLAGS_PATH_TX 0x1UL + #define CFA_FLOW_INFO_RESP_FLAGS_PATH_RX 0x2UL u8 profile; __le16 src_fid; __le16 dst_fid; @@ -5910,7 +6065,10 @@ struct hwrm_cfa_flow_info_output { __le16 flow_handle; __le32 tunnel_handle; __le16 flow_timer; - u8 unused_0[5]; + u8 unused_0[6]; + __le32 flow_key_data[130]; + __le32 flow_action_info[30]; + u8 unused_1[7]; u8 valid; }; -- cgit v1.2.3 From c6cc32a2133cb1eb5aa28ced1852aab2aeaf357a Mon Sep 17 00:00:00 2001 From: Erik Burrows Date: Tue, 19 Feb 2019 05:31:13 -0500 Subject: bnxt_en: Add support for BCM957504 Add support for BCM957504 with device ID 1751 Signed-off-by: Erik Burrows Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 92d73453a318..0f7a34a3b004 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1,7 +1,7 @@ /* Broadcom NetXtreme-C/E network driver. * * Copyright (c) 2014-2016 Broadcom Corporation - * Copyright (c) 2016-2018 Broadcom Limited + * Copyright (c) 2016-2019 Broadcom Limited * * 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 @@ -112,6 +112,7 @@ enum board_idx { BCM57454, BCM5745x_NPAR, BCM57508, + BCM57504, BCM58802, BCM58804, BCM58808, @@ -155,6 +156,7 @@ static const struct { [BCM57454] = { "Broadcom BCM57454 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" }, [BCM5745x_NPAR] = { "Broadcom BCM5745x NetXtreme-E Ethernet Partition" }, [BCM57508] = { "Broadcom BCM57508 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet" }, + [BCM57504] = { "Broadcom BCM57504 NetXtreme-E 10Gb/25Gb/50Gb/100Gb/200Gb Ethernet" }, [BCM58802] = { "Broadcom BCM58802 NetXtreme-S 10Gb/25Gb/40Gb/50Gb Ethernet" }, [BCM58804] = { "Broadcom BCM58804 NetXtreme-S 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" }, [BCM58808] = { "Broadcom BCM58808 NetXtreme-S 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" }, @@ -201,6 +203,7 @@ static const struct pci_device_id bnxt_pci_tbl[] = { { PCI_VDEVICE(BROADCOM, 0x16f0), .driver_data = BCM58808 }, { PCI_VDEVICE(BROADCOM, 0x16f1), .driver_data = BCM57452 }, { PCI_VDEVICE(BROADCOM, 0x1750), .driver_data = BCM57508 }, + { PCI_VDEVICE(BROADCOM, 0x1751), .driver_data = BCM57504 }, { PCI_VDEVICE(BROADCOM, 0xd802), .driver_data = BCM58802 }, { PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 }, #ifdef CONFIG_BNXT_SRIOV -- cgit v1.2.3 From 2a516444434ffa4419e67c5289d5f53272cb9674 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 19 Feb 2019 05:31:14 -0500 Subject: bnxt_en: Propagate trusted VF attribute to firmware. Newer firmware understands the concept of a trusted VF, so propagate the trusted VF attribute set by the PF admin. to the firmware. Also, check the firmware trusted setting when considering the VF MAC address change and reporting the trusted setting to the user. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 + drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c | 58 +++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 0f7a34a3b004..9700891a26b8 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6683,6 +6683,10 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) VER_GET_RESP_DEV_CAPS_CFG_FLOW_HANDLE_64BIT_SUPPORTED) bp->fw_cap |= BNXT_FW_CAP_OVS_64BIT_HANDLE; + if (dev_caps_cfg & + VER_GET_RESP_DEV_CAPS_CFG_TRUSTED_VF_SUPPORTED) + bp->fw_cap |= BNXT_FW_CAP_TRUSTED_VF; + hwrm_ver_get_exit: mutex_unlock(&bp->hwrm_cmd_lock); return rc; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 17554d4be651..ecbe7d28a723 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -945,6 +945,7 @@ struct bnxt_vf_info { * stored by PF. */ u16 vlan; + u16 func_qcfg_flags; u32 flags; #define BNXT_VF_QOS 0x1 #define BNXT_VF_SPOOFCHK 0x2 @@ -1478,6 +1479,7 @@ struct bnxt { #define BNXT_FW_CAP_IF_CHANGE 0x00000010 #define BNXT_FW_CAP_KONG_MB_CHNL 0x00000080 #define BNXT_FW_CAP_OVS_64BIT_HANDLE 0x00000400 + #define BNXT_FW_CAP_TRUSTED_VF 0x00000800 #define BNXT_NEW_RM(bp) ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM) u32 hwrm_spec_code; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index d80f5c981d90..2b90a2bb1a1d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -121,6 +121,54 @@ int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting) return rc; } +static int bnxt_hwrm_func_qcfg_flags(struct bnxt *bp, struct bnxt_vf_info *vf) +{ + struct hwrm_func_qcfg_output *resp = bp->hwrm_cmd_resp_addr; + struct hwrm_func_qcfg_input req = {0}; + int rc; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCFG, -1, -1); + req.fid = cpu_to_le16(vf->fw_fid); + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) { + mutex_unlock(&bp->hwrm_cmd_lock); + return -EIO; + } + vf->func_qcfg_flags = le16_to_cpu(resp->flags); + mutex_unlock(&bp->hwrm_cmd_lock); + return 0; +} + +static bool bnxt_is_trusted_vf(struct bnxt *bp, struct bnxt_vf_info *vf) +{ + if (!(bp->fw_cap & BNXT_FW_CAP_TRUSTED_VF)) + return !!(vf->flags & BNXT_VF_TRUST); + + bnxt_hwrm_func_qcfg_flags(bp, vf); + return !!(vf->func_qcfg_flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF); +} + +static int bnxt_hwrm_set_trusted_vf(struct bnxt *bp, struct bnxt_vf_info *vf) +{ + struct hwrm_func_cfg_input req = {0}; + int rc; + + if (!(bp->fw_cap & BNXT_FW_CAP_TRUSTED_VF)) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); + req.fid = cpu_to_le16(vf->fw_fid); + if (vf->flags & BNXT_VF_TRUST) + req.flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE); + else + req.flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_TRUSTED_VF_DISABLE); + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) + return -EIO; + return 0; +} + int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trusted) { struct bnxt *bp = netdev_priv(dev); @@ -135,6 +183,7 @@ int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trusted) else vf->flags &= ~BNXT_VF_TRUST; + bnxt_hwrm_set_trusted_vf(bp, vf); return 0; } @@ -164,7 +213,7 @@ int bnxt_get_vf_config(struct net_device *dev, int vf_id, else ivi->qos = 0; ivi->spoofchk = !!(vf->flags & BNXT_VF_SPOOFCHK); - ivi->trusted = !!(vf->flags & BNXT_VF_TRUST); + ivi->trusted = bnxt_is_trusted_vf(bp, vf); if (!(vf->flags & BNXT_VF_LINK_FORCED)) ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; else if (vf->flags & BNXT_VF_LINK_UP) @@ -935,9 +984,10 @@ static int bnxt_vf_configure_mac(struct bnxt *bp, struct bnxt_vf_info *vf) * if the PF assigned MAC address is zero */ if (req->enables & cpu_to_le32(FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR)) { + bool trust = bnxt_is_trusted_vf(bp, vf); + if (is_valid_ether_addr(req->dflt_mac_addr) && - ((vf->flags & BNXT_VF_TRUST) || - !is_valid_ether_addr(vf->mac_addr) || + (trust || !is_valid_ether_addr(vf->mac_addr) || ether_addr_equal(req->dflt_mac_addr, vf->mac_addr))) { ether_addr_copy(vf->vf_mac_addr, req->dflt_mac_addr); return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size); @@ -962,7 +1012,7 @@ static int bnxt_vf_validate_set_mac(struct bnxt *bp, struct bnxt_vf_info *vf) * Otherwise, it must match the VF MAC address if firmware spec >= * 1.2.2 */ - if (vf->flags & BNXT_VF_TRUST) { + if (bnxt_is_trusted_vf(bp, vf)) { mac_ok = true; } else if (is_valid_ether_addr(vf->mac_addr)) { if (ether_addr_equal((const u8 *)req->l2_addr, vf->mac_addr)) -- cgit v1.2.3 From 0ca12be99667265ef8100860601d510e78f22cea Mon Sep 17 00:00:00 2001 From: Vasundhara Volam Date: Tue, 19 Feb 2019 05:31:15 -0500 Subject: bnxt_en: Add support for mdio read/write to external PHY Add support for SIOCGMIIREG and SIOCSMIIREG ioctls to mdio read/write to external PHY. Signed-off-by: Vasundhara Volam Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 69 ++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 9700891a26b8..a9edf946d3bf 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -8621,24 +8622,88 @@ static int bnxt_close(struct net_device *dev) return 0; } +static int bnxt_hwrm_port_phy_read(struct bnxt *bp, u16 phy_addr, u16 reg, + u16 *val) +{ + struct hwrm_port_phy_mdio_read_output *resp = bp->hwrm_cmd_resp_addr; + struct hwrm_port_phy_mdio_read_input req = {0}; + int rc; + + if (bp->hwrm_spec_code < 0x10a00) + return -EOPNOTSUPP; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_MDIO_READ, -1, -1); + req.port_id = cpu_to_le16(bp->pf.port_id); + req.phy_addr = phy_addr; + req.reg_addr = cpu_to_le16(reg & 0x1f); + if (bp->link_info.support_speeds & BNXT_LINK_SPEED_MSK_10GB) { + req.cl45_mdio = 1; + req.phy_addr = mdio_phy_id_prtad(phy_addr); + req.dev_addr = mdio_phy_id_devad(phy_addr); + req.reg_addr = cpu_to_le16(reg); + } + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) + *val = le16_to_cpu(resp->reg_data); + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_port_phy_write(struct bnxt *bp, u16 phy_addr, u16 reg, + u16 val) +{ + struct hwrm_port_phy_mdio_write_input req = {0}; + + if (bp->hwrm_spec_code < 0x10a00) + return -EOPNOTSUPP; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_MDIO_WRITE, -1, -1); + req.port_id = cpu_to_le16(bp->pf.port_id); + req.phy_addr = phy_addr; + req.reg_addr = cpu_to_le16(reg & 0x1f); + if (bp->link_info.support_speeds & BNXT_LINK_SPEED_MSK_10GB) { + req.cl45_mdio = 1; + req.phy_addr = mdio_phy_id_prtad(phy_addr); + req.dev_addr = mdio_phy_id_devad(phy_addr); + req.reg_addr = cpu_to_le16(reg); + } + req.reg_data = cpu_to_le16(val); + + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + /* rtnl_lock held */ static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { + struct mii_ioctl_data *mdio = if_mii(ifr); + struct bnxt *bp = netdev_priv(dev); + int rc; + switch (cmd) { case SIOCGMIIPHY: + mdio->phy_id = bp->link_info.phy_addr; + /* fallthru */ case SIOCGMIIREG: { + u16 mii_regval = 0; + if (!netif_running(dev)) return -EAGAIN; - return 0; + rc = bnxt_hwrm_port_phy_read(bp, mdio->phy_id, mdio->reg_num, + &mii_regval); + mdio->val_out = mii_regval; + return rc; } case SIOCSMIIREG: if (!netif_running(dev)) return -EAGAIN; - return 0; + return bnxt_hwrm_port_phy_write(bp, mdio->phy_id, mdio->reg_num, + mdio->val_in); default: /* do nothing */ -- cgit v1.2.3 From b2d69122fd627aa3c6c39c99b2b8706703a92634 Mon Sep 17 00:00:00 2001 From: Sriharsha Basavapatna Date: Tue, 19 Feb 2019 05:31:16 -0500 Subject: bnxt_en: Return relevant error code when offload fails The driver returns -ENOSPC when tc_can_offload() check fails. Since that routine checks for flow parameters that are not supported by the driver, we should return the more appropriate -EOPNOTSUPP. Signed-off-by: Sriharsha Basavapatna Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c index 61a3457ed71b..44d6c5743fb9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c @@ -1290,7 +1290,7 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid, bnxt_tc_set_flow_dir(bp, flow, src_fid); if (!bnxt_tc_can_offload(bp, flow)) { - rc = -ENOSPC; + rc = -EOPNOTSUPP; goto free_node; } -- cgit v1.2.3 From a968b5e9d5879f9535d6099505f9e14abcafb623 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Tue, 19 Feb 2019 12:29:43 +0530 Subject: net: dsa: qca8k: Enable delay for RGMII_ID mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RGMII_ID specifies that we should have internal delay, so resurrect the delay addition routine but under the RGMII_ID mode. Fixes: 40269aa9f40a ("net: dsa: qca8k: disable delay for RGMII mode") Tested-by: Michal Vokáč Signed-off-by: Vinod Koul Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/qca8k.c | 12 ++++++++++++ drivers/net/dsa/qca8k.h | 1 + 2 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index a4b6cda38016..195a8a87b984 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -443,6 +443,18 @@ qca8k_set_pad_ctrl(struct qca8k_priv *priv, int port, int mode) val = QCA8K_PORT_PAD_RGMII_EN; qca8k_write(priv, reg, val); break; + case PHY_INTERFACE_MODE_RGMII_ID: + /* RGMII_ID needs internal delay. This is enabled through + * PORT5_PAD_CTRL for all ports, rather than individual port + * registers + */ + qca8k_write(priv, reg, + QCA8K_PORT_PAD_RGMII_EN | + QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) | + QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY)); + qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL, + QCA8K_PORT_PAD_RGMII_RX_DELAY_EN); + break; case PHY_INTERFACE_MODE_SGMII: qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN); break; diff --git a/drivers/net/dsa/qca8k.h b/drivers/net/dsa/qca8k.h index 613fe5c50236..d146e54c8a6c 100644 --- a/drivers/net/dsa/qca8k.h +++ b/drivers/net/dsa/qca8k.h @@ -40,6 +40,7 @@ ((0x8 + (x & 0x3)) << 22) #define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) \ ((0x10 + (x & 0x3)) << 20) +#define QCA8K_MAX_DELAY 3 #define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24) #define QCA8K_PORT_PAD_SGMII_EN BIT(7) #define QCA8K_REG_MODULE_EN 0x030 -- cgit v1.2.3 From c2a5994fbb5bf6ae3fcdcc9bbe323d62f8e28618 Mon Sep 17 00:00:00 2001 From: Mao Wenan Date: Tue, 19 Feb 2019 21:45:10 +0800 Subject: net: ns83820: code cleanup for ns83820_probe_phy() This patch is to do code cleanup for ns83820_probe_phy(). It deletes unused variable 'first', commented out code, and the pointless 'for' loop. Signed-off-by: Mao Wenan Acked-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/natsemi/ns83820.c | 70 ++++++++++------------------------ 1 file changed, 21 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 000009e18ff8..9098ee7fe0d1 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -1869,56 +1869,28 @@ static unsigned ns83820_mii_write_reg(struct ns83820 *dev, unsigned phy, unsigne static void ns83820_probe_phy(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - static int first; - int i; -#define MII_PHYIDR1 0x02 -#define MII_PHYIDR2 0x03 - -#if 0 - if (!first) { - unsigned tmp; - ns83820_mii_read_reg(dev, 1, 0x09); - ns83820_mii_write_reg(dev, 1, 0x10, 0x0d3e); - - tmp = ns83820_mii_read_reg(dev, 1, 0x00); - ns83820_mii_write_reg(dev, 1, 0x00, tmp | 0x8000); - udelay(1300); - ns83820_mii_read_reg(dev, 1, 0x09); - } -#endif - first = 1; - - for (i=1; i<2; i++) { - int j; - unsigned a, b; - a = ns83820_mii_read_reg(dev, i, MII_PHYIDR1); - b = ns83820_mii_read_reg(dev, i, MII_PHYIDR2); - - //printk("%s: phy %d: 0x%04x 0x%04x\n", - // ndev->name, i, a, b); - - for (j=0; j<0x16; j+=4) { - dprintk("%s: [0x%02x] %04x %04x %04x %04x\n", - ndev->name, j, - ns83820_mii_read_reg(dev, i, 0 + j), - ns83820_mii_read_reg(dev, i, 1 + j), - ns83820_mii_read_reg(dev, i, 2 + j), - ns83820_mii_read_reg(dev, i, 3 + j) - ); - } - } - { - unsigned a, b; - /* read firmware version: memory addr is 0x8402 and 0x8403 */ - ns83820_mii_write_reg(dev, 1, 0x16, 0x000d); - ns83820_mii_write_reg(dev, 1, 0x1e, 0x810e); - a = ns83820_mii_read_reg(dev, 1, 0x1d); - - ns83820_mii_write_reg(dev, 1, 0x16, 0x000d); - ns83820_mii_write_reg(dev, 1, 0x1e, 0x810e); - b = ns83820_mii_read_reg(dev, 1, 0x1d); - dprintk("version: 0x%04x 0x%04x\n", a, b); + int j; + unsigned a, b; + + for (j = 0; j < 0x16; j += 4) { + dprintk("%s: [0x%02x] %04x %04x %04x %04x\n", + ndev->name, j, + ns83820_mii_read_reg(dev, 1, 0 + j), + ns83820_mii_read_reg(dev, 1, 1 + j), + ns83820_mii_read_reg(dev, 1, 2 + j), + ns83820_mii_read_reg(dev, 1, 3 + j) + ); } + + /* read firmware version: memory addr is 0x8402 and 0x8403 */ + ns83820_mii_write_reg(dev, 1, 0x16, 0x000d); + ns83820_mii_write_reg(dev, 1, 0x1e, 0x810e); + a = ns83820_mii_read_reg(dev, 1, 0x1d); + + ns83820_mii_write_reg(dev, 1, 0x16, 0x000d); + ns83820_mii_write_reg(dev, 1, 0x1e, 0x810e); + b = ns83820_mii_read_reg(dev, 1, 0x1d); + dprintk("version: 0x%04x 0x%04x\n", a, b); } #endif -- cgit v1.2.3 From 6a897372417e8c9e0e03c4c438fc1f48dd096ea9 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Tue, 22 Jan 2019 10:29:57 +0200 Subject: net/mlx5: ethtool, Add ethtool support for 50Gbps per lane link modes In previous patch, driver added new speed modes: 50Gbps per lane support for 50G/100G/200G. This patch modifies mlx5e_get_link_ksettings and mlx5e_set_link_ksettings to set and get these link modes via ethtool. In order to do so, added mapping of new HW bits to ethtool bitmap and enforce mutual exclusion between extended link modes and previously defined link modes. Signed-off-by: Aya Levin Reviewed-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 243 +++++++++++++++------ 1 file changed, 181 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 3cd73254d020..ee5dc8e354d6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -63,76 +63,147 @@ struct ptys2ethtool_config { __ETHTOOL_DECLARE_LINK_MODE_MASK(advertised); }; -static struct ptys2ethtool_config ptys2ethtool_table[MLX5E_LINK_MODES_NUMBER]; +static +struct ptys2ethtool_config ptys2legacy_ethtool_table[MLX5E_LINK_MODES_NUMBER]; +static +struct ptys2ethtool_config ptys2ext_ethtool_table[MLX5E_EXT_LINK_MODES_NUMBER]; -#define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, ...) \ +#define MLX5_BUILD_PTYS2ETHTOOL_CONFIG(reg_, table, ...) \ ({ \ struct ptys2ethtool_config *cfg; \ const unsigned int modes[] = { __VA_ARGS__ }; \ - unsigned int i; \ - cfg = &ptys2ethtool_table[reg_]; \ + unsigned int i, bit, idx; \ + cfg = &ptys2##table##_ethtool_table[reg_]; \ bitmap_zero(cfg->supported, \ __ETHTOOL_LINK_MODE_MASK_NBITS); \ bitmap_zero(cfg->advertised, \ __ETHTOOL_LINK_MODE_MASK_NBITS); \ for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \ - __set_bit(modes[i], cfg->supported); \ - __set_bit(modes[i], cfg->advertised); \ + bit = modes[i] % 64; \ + idx = modes[i] / 64; \ + __set_bit(bit, &cfg->supported[idx]); \ + __set_bit(bit, &cfg->advertised[idx]); \ } \ }) void mlx5e_build_ptys2ethtool_map(void) { - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII, + memset(ptys2legacy_ethtool_table, 0, sizeof(ptys2legacy_ethtool_table)); + memset(ptys2ext_ethtool_table, 0, sizeof(ptys2ext_ethtool_table)); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_CX_SGMII, legacy, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_KX, legacy, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CX4, legacy, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KX4, legacy, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_KR, legacy, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_20GBASE_KR2, legacy, ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_CR4, legacy, ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_KR4, legacy, ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_56GBASE_R4, legacy, ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_CR, legacy, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_SR, legacy, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_ER, legacy, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_SR4, legacy, ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_LR4, legacy, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_SR2, legacy, ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_CR4, legacy, ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_SR4, legacy, ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_KR4, legacy, ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, legacy, ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, legacy, ETHTOOL_LINK_MODE_10000baseT_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, legacy, ETHTOOL_LINK_MODE_25000baseCR_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_KR, legacy, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_SR, legacy, ETHTOOL_LINK_MODE_25000baseSR_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_CR2, legacy, ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT); - MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2, + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GBASE_KR2, legacy, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_SGMII_100M, ext, + ETHTOOL_LINK_MODE_100baseT_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_X_SGMII, ext, + ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, + ETHTOOL_LINK_MODE_1000baseX_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_5GBASE_R, ext, + ETHTOOL_LINK_MODE_5000baseT_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_XFI_XAUI_1, ext, + ETHTOOL_LINK_MODE_10000baseT_Full_BIT, + ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseER_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_40GBASE_XLAUI_4_XLPPI_4, ext, + ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GAUI_1_25GBASE_CR_KR, ext, + ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_25000baseSR_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2, + ext, + ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, + ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, + ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR, ext, + ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseDR_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_CAUI_4_100GBASE_CR4_KR4, ext, + ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GAUI_2_100GBASE_CR2_KR2, ext, + ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT); + MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_200GAUI_4_200GBASE_CR4_KR4, ext, + ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT); +} + +static void mlx5e_ethtool_get_speed_arr(struct mlx5_core_dev *mdev, + struct ptys2ethtool_config **arr, + u32 *size) +{ + bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet); + + *arr = ext ? ptys2ext_ethtool_table : ptys2legacy_ethtool_table; + *size = ext ? ARRAY_SIZE(ptys2ext_ethtool_table) : + ARRAY_SIZE(ptys2legacy_ethtool_table); } typedef int (*mlx5e_pflag_handler)(struct net_device *netdev, bool enable); @@ -526,27 +597,35 @@ static int mlx5e_set_coalesce(struct net_device *netdev, return mlx5e_ethtool_set_coalesce(priv, coal); } -static void ptys2ethtool_supported_link(unsigned long *supported_modes, +static void ptys2ethtool_supported_link(struct mlx5_core_dev *mdev, + unsigned long *supported_modes, u32 eth_proto_cap) { unsigned long proto_cap = eth_proto_cap; + struct ptys2ethtool_config *table; + u32 max_size; int proto; - for_each_set_bit(proto, &proto_cap, MLX5E_LINK_MODES_NUMBER) + mlx5e_ethtool_get_speed_arr(mdev, &table, &max_size); + for_each_set_bit(proto, &proto_cap, max_size) bitmap_or(supported_modes, supported_modes, - ptys2ethtool_table[proto].supported, + table[proto].supported, __ETHTOOL_LINK_MODE_MASK_NBITS); } -static void ptys2ethtool_adver_link(unsigned long *advertising_modes, +static void ptys2ethtool_adver_link(struct mlx5_core_dev *mdev, + unsigned long *advertising_modes, u32 eth_proto_cap) { unsigned long proto_cap = eth_proto_cap; + struct ptys2ethtool_config *table; + u32 max_size; int proto; - for_each_set_bit(proto, &proto_cap, MLX5E_LINK_MODES_NUMBER) + mlx5e_ethtool_get_speed_arr(mdev, &table, &max_size); + for_each_set_bit(proto, &proto_cap, max_size) bitmap_or(advertising_modes, advertising_modes, - ptys2ethtool_table[proto].advertised, + table[proto].advertised, __ETHTOOL_LINK_MODE_MASK_NBITS); } @@ -716,22 +795,22 @@ out: link_ksettings->base.duplex = duplex; } -static void get_supported(u32 eth_proto_cap, +static void get_supported(struct mlx5_core_dev *mdev, u32 eth_proto_cap, struct ethtool_link_ksettings *link_ksettings) { unsigned long *supported = link_ksettings->link_modes.supported; + ptys2ethtool_supported_link(mdev, supported, eth_proto_cap); - ptys2ethtool_supported_link(supported, eth_proto_cap); ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause); } -static void get_advertising(u32 eth_proto_cap, u8 tx_pause, - u8 rx_pause, +static void get_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_cap, + u8 tx_pause, u8 rx_pause, struct ethtool_link_ksettings *link_ksettings) { unsigned long *advertising = link_ksettings->link_modes.advertising; + ptys2ethtool_adver_link(mdev, advertising, eth_proto_cap); - ptys2ethtool_adver_link(advertising, eth_proto_cap); if (rx_pause) ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause); if (tx_pause ^ rx_pause) @@ -781,12 +860,12 @@ static u8 get_connector_port(u32 eth_proto, u8 connector_type) return PORT_OTHER; } -static void get_lp_advertising(u32 eth_proto_lp, +static void get_lp_advertising(struct mlx5_core_dev *mdev, u32 eth_proto_lp, struct ethtool_link_ksettings *link_ksettings) { unsigned long *lp_advertising = link_ksettings->link_modes.lp_advertising; - ptys2ethtool_adver_link(lp_advertising, eth_proto_lp); + ptys2ethtool_adver_link(mdev, lp_advertising, eth_proto_lp); } int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv, @@ -803,6 +882,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv, u8 an_disable_admin; u8 an_status; u8 connector_type; + bool ext; int err; err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1); @@ -811,22 +891,25 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv, __func__, err); goto err_query_regs; } - - eth_proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability); - eth_proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin); - eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); - eth_proto_lp = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise); - an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin); - an_status = MLX5_GET(ptys_reg, out, an_status); - connector_type = MLX5_GET(ptys_reg, out, connector_type); + ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet); + eth_proto_cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, + eth_proto_capability); + eth_proto_admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, + eth_proto_admin); + eth_proto_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, + eth_proto_oper); + eth_proto_lp = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise); + an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin); + an_status = MLX5_GET(ptys_reg, out, an_status); + connector_type = MLX5_GET(ptys_reg, out, connector_type); mlx5_query_port_pause(mdev, &rx_pause, &tx_pause); ethtool_link_ksettings_zero_link_mode(link_ksettings, supported); ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); - get_supported(eth_proto_cap, link_ksettings); - get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings); + get_supported(mdev, eth_proto_cap, link_ksettings); + get_advertising(mdev, eth_proto_admin, tx_pause, rx_pause, link_ksettings); get_speed_duplex(priv->netdev, eth_proto_oper, link_ksettings); eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap; @@ -835,7 +918,7 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv, connector_type); ptys2ethtool_supported_advertised_port(link_ksettings, eth_proto_admin, connector_type); - get_lp_advertising(eth_proto_lp, link_ksettings); + get_lp_advertising(mdev, eth_proto_lp, link_ksettings); if (an_status == MLX5_AN_COMPLETE) ethtool_link_ksettings_add_link_mode(link_ksettings, @@ -874,7 +957,9 @@ static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes) u32 i, ptys_modes = 0; for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { - if (bitmap_intersects(ptys2ethtool_table[i].advertised, + if (*ptys2legacy_ethtool_table[i].advertised == 0) + continue; + if (bitmap_intersects(ptys2legacy_ethtool_table[i].advertised, link_modes, __ETHTOOL_LINK_MODE_MASK_NBITS)) ptys_modes |= MLX5E_PROT_MASK(i); @@ -883,6 +968,25 @@ static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes) return ptys_modes; } +static u32 mlx5e_ethtool2ptys_ext_adver_link(const unsigned long *link_modes) +{ + u32 i, ptys_modes = 0; + unsigned long modes[2]; + + for (i = 0; i < MLX5E_EXT_LINK_MODES_NUMBER; ++i) { + if (*ptys2ext_ethtool_table[i].advertised == 0) + continue; + memset(modes, 0, sizeof(modes)); + bitmap_and(modes, ptys2ext_ethtool_table[i].advertised, + link_modes, __ETHTOOL_LINK_MODE_MASK_NBITS); + + if (modes[0] == ptys2ext_ethtool_table[i].advertised[0] && + modes[1] == ptys2ext_ethtool_table[i].advertised[1]) + ptys_modes |= MLX5E_PROT_MASK(i); + } + return ptys_modes; +} + int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, const struct ethtool_link_ksettings *link_ksettings) { @@ -890,6 +994,8 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, struct mlx5e_port_eth_proto eproto; bool an_changes = false; u8 an_disable_admin; + bool ext_supported; + bool ext_requested; u8 an_disable_cap; bool an_disable; u32 link_modes; @@ -897,18 +1003,31 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, u32 speed; int err; - speed = link_ksettings->base.speed; + u32 (*ethtool2ptys_adver_func)(const unsigned long *adver); - link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ? - mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) : - mlx5e_port_speed2linkmodes(mdev, speed); +#define MLX5E_PTYS_EXT ((1ULL << ETHTOOL_LINK_MODE_50000baseKR_Full_BIT) - 1) + + ext_requested = (link_ksettings->link_modes.advertising[0] > + MLX5E_PTYS_EXT); + ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet); + + /*when ptys_extended_ethernet is set legacy link modes are deprecated */ + if (ext_requested != ext_supported) + return -EPROTONOSUPPORT; - err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto); + speed = link_ksettings->base.speed; + ethtool2ptys_adver_func = ext_requested ? + mlx5e_ethtool2ptys_ext_adver_link : + mlx5e_ethtool2ptys_adver_link; + err = mlx5_port_query_eth_proto(mdev, 1, ext_supported, &eproto); if (err) { netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n", __func__, err); goto out; } + link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ? + ethtool2ptys_adver_func(link_ksettings->link_modes.advertising) : + mlx5e_port_speed2linkmodes(mdev, speed); link_modes = link_modes & eproto.cap; if (!link_modes) { @@ -928,7 +1047,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, if (!an_changes && link_modes == eproto.admin) goto out; - mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, false); + mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext_supported); mlx5_toggle_port_link(mdev); out: -- cgit v1.2.3 From 877662e27276f345ea07e49f153aa88e9a1e313c Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Mon, 26 Nov 2018 17:22:16 +0200 Subject: net/mlx5e: Wrap the open and apply of channels in one fail-safe function Take into a function the common code structure of opening a side set of channels followed by a call to apply them. Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 6 +-- drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 4 +- .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 54 +++++----------------- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 33 ++++++++----- .../net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 4 +- 5 files changed, 39 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index e9acfa9aa069..71c65cc17904 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -858,9 +858,9 @@ void mlx5e_close_channels(struct mlx5e_channels *chs); * switching channels */ typedef int (*mlx5e_fp_hw_modify)(struct mlx5e_priv *priv); -void mlx5e_switch_priv_channels(struct mlx5e_priv *priv, - struct mlx5e_channels *new_chs, - mlx5e_fp_hw_modify hw_modify); +int mlx5e_safe_switch_channels(struct mlx5e_priv *priv, + struct mlx5e_channels *new_chs, + mlx5e_fp_hw_modify hw_modify); void mlx5e_activate_priv_channels(struct mlx5e_priv *priv); void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index 722998d68564..554672edf8c3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -1126,9 +1126,7 @@ static void mlx5e_trust_update_sq_inline_mode(struct mlx5e_priv *priv) priv->channels.params.tx_min_inline_mode) goto out; - if (mlx5e_open_channels(priv, &new_channels)) - goto out; - mlx5e_switch_priv_channels(priv, &new_channels, NULL); + mlx5e_safe_switch_channels(priv, &new_channels, NULL); out: mutex_unlock(&priv->state_lock); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index ee5dc8e354d6..0804b478ad19 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -369,11 +369,7 @@ int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv, goto unlock; } - err = mlx5e_open_channels(priv, &new_channels); - if (err) - goto unlock; - - mlx5e_switch_priv_channels(priv, &new_channels, NULL); + err = mlx5e_safe_switch_channels(priv, &new_channels, NULL); unlock: mutex_unlock(&priv->state_lock); @@ -431,11 +427,6 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, goto out; } - /* Create fresh channels with new parameters */ - err = mlx5e_open_channels(priv, &new_channels); - if (err) - goto out; - arfs_enabled = priv->netdev->features & NETIF_F_NTUPLE; if (arfs_enabled) mlx5e_arfs_disable(priv); @@ -445,13 +436,14 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, MLX5E_INDIR_RQT_SIZE, count); /* Switch to new channels, set new parameters and close old ones */ - mlx5e_switch_priv_channels(priv, &new_channels, NULL); + err = mlx5e_safe_switch_channels(priv, &new_channels, NULL); if (arfs_enabled) { - err = mlx5e_arfs_enable(priv); - if (err) + int err2 = mlx5e_arfs_enable(priv); + + if (err2) netdev_err(priv->netdev, "%s: mlx5e_arfs_enable failed: %d\n", - __func__, err); + __func__, err2); } out: @@ -577,12 +569,7 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, goto out; } - /* open fresh channels with new coal parameters */ - err = mlx5e_open_channels(priv, &new_channels); - if (err) - goto out; - - mlx5e_switch_priv_channels(priv, &new_channels, NULL); + err = mlx5e_safe_switch_channels(priv, &new_channels, NULL); out: mutex_unlock(&priv->state_lock); @@ -1635,7 +1622,6 @@ static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable, struct mlx5e_channels new_channels = {}; bool mode_changed; u8 cq_period_mode, current_cq_period_mode; - int err = 0; cq_period_mode = enable ? MLX5_CQ_PERIOD_MODE_START_FROM_CQE : @@ -1663,12 +1649,7 @@ static int set_pflag_cqe_based_moder(struct net_device *netdev, bool enable, return 0; } - err = mlx5e_open_channels(priv, &new_channels); - if (err) - return err; - - mlx5e_switch_priv_channels(priv, &new_channels, NULL); - return 0; + return mlx5e_safe_switch_channels(priv, &new_channels, NULL); } static int set_pflag_tx_cqe_based_moder(struct net_device *netdev, bool enable) @@ -1701,11 +1682,10 @@ int mlx5e_modify_rx_cqe_compression_locked(struct mlx5e_priv *priv, bool new_val return 0; } - err = mlx5e_open_channels(priv, &new_channels); + err = mlx5e_safe_switch_channels(priv, &new_channels, NULL); if (err) return err; - mlx5e_switch_priv_channels(priv, &new_channels, NULL); mlx5e_dbg(DRV, priv, "MLX5E: RxCqeCmprss was turned %s\n", MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_RX_CQE_COMPRESS) ? "ON" : "OFF"); @@ -1738,7 +1718,6 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable) struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5_core_dev *mdev = priv->mdev; struct mlx5e_channels new_channels = {}; - int err; if (enable) { if (!mlx5e_check_fragmented_striding_rq_cap(mdev)) @@ -1760,12 +1739,7 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable) return 0; } - err = mlx5e_open_channels(priv, &new_channels); - if (err) - return err; - - mlx5e_switch_priv_channels(priv, &new_channels, NULL); - return 0; + return mlx5e_safe_switch_channels(priv, &new_channels, NULL); } static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable) @@ -1808,12 +1782,8 @@ static int set_pflag_xdp_tx_mpwqe(struct net_device *netdev, bool enable) return 0; } - err = mlx5e_open_channels(priv, &new_channels); - if (err) - return err; - - mlx5e_switch_priv_channels(priv, &new_channels, NULL); - return 0; + err = mlx5e_safe_switch_channels(priv, &new_channels, NULL); + return err; } static const struct pflag_desc mlx5e_priv_flags[MLX5E_NUM_PFLAGS] = { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 83510ca0bcd8..878b3467e459 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2885,13 +2885,14 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv) mlx5e_deactivate_channels(&priv->channels); } -void mlx5e_switch_priv_channels(struct mlx5e_priv *priv, - struct mlx5e_channels *new_chs, - mlx5e_fp_hw_modify hw_modify) +static void mlx5e_switch_priv_channels(struct mlx5e_priv *priv, + struct mlx5e_channels *new_chs, + mlx5e_fp_hw_modify hw_modify) { struct net_device *netdev = priv->netdev; int new_num_txqs; int carrier_ok; + new_num_txqs = new_chs->num * new_chs->params.num_tc; carrier_ok = netif_carrier_ok(netdev); @@ -2917,6 +2918,20 @@ void mlx5e_switch_priv_channels(struct mlx5e_priv *priv, netif_carrier_on(netdev); } +int mlx5e_safe_switch_channels(struct mlx5e_priv *priv, + struct mlx5e_channels *new_chs, + mlx5e_fp_hw_modify hw_modify) +{ + int err; + + err = mlx5e_open_channels(priv, new_chs); + if (err) + return err; + + mlx5e_switch_priv_channels(priv, new_chs, hw_modify); + return 0; +} + void mlx5e_timestamp_init(struct mlx5e_priv *priv) { priv->tstamp.tx_type = HWTSTAMP_TX_OFF; @@ -3333,13 +3348,12 @@ static int mlx5e_setup_tc_mqprio(struct net_device *netdev, goto out; } - err = mlx5e_open_channels(priv, &new_channels); + err = mlx5e_safe_switch_channels(priv, &new_channels, NULL); if (err) goto out; priv->max_opened_tc = max_t(u8, priv->max_opened_tc, new_channels.params.num_tc); - mlx5e_switch_priv_channels(priv, &new_channels, NULL); out: mutex_unlock(&priv->state_lock); return err; @@ -3549,11 +3563,7 @@ static int set_feature_lro(struct net_device *netdev, bool enable) goto out; } - err = mlx5e_open_channels(priv, &new_channels); - if (err) - goto out; - - mlx5e_switch_priv_channels(priv, &new_channels, mlx5e_modify_tirs_lro); + err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_modify_tirs_lro); out: mutex_unlock(&priv->state_lock); return err; @@ -3771,11 +3781,10 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu, goto out; } - err = mlx5e_open_channels(priv, &new_channels); + err = mlx5e_safe_switch_channels(priv, &new_channels, set_mtu_cb); if (err) goto out; - mlx5e_switch_priv_channels(priv, &new_channels, set_mtu_cb); netdev->mtu = new_channels.params.sw_mtu; out: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index bfc0f6581729..4eac42555c7d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -446,11 +446,11 @@ static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu) new_channels.params = *params; new_channels.params.sw_mtu = new_mtu; - err = mlx5e_open_channels(priv, &new_channels); + + err = mlx5e_safe_switch_channels(priv, &new_channels, NULL); if (err) goto out; - mlx5e_switch_priv_channels(priv, &new_channels, NULL); netdev->mtu = new_channels.params.sw_mtu; out: -- cgit v1.2.3 From 73c718fbb32adc2df8a7ee00c1a880b97d547d24 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Tue, 12 Feb 2019 19:45:16 +0200 Subject: net/mlx5e: Remove wrong and superfluous tc pedit header type check With recent introduction of flow_rule infrastructure drivers no longer directly include action headers, so it is no longer possible to use constants defined in them. Instead, one of flow_rule patches substituted pedit action header constant with hardcoded value '2' in mlx5 set_pedit_val() function conditional which verifies that header type is in range of values allowed by pedit action. That conditional is now both wrong (hardcoded value is '2' but __PEDIT_HDR_TYPE_MAX is 6 in current version) and superfluous (pedit action already verifies that header type is in allowed range during init). Remove the described check from mlx5 code. Fixes: 738678817573 ("drivers: net: use flow action infrastructure") Signed-off-by: Vlad Buslov Reviewed-by: Roi Dayan Reviewed-by: Dmytro Linkin Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 05892fc4e03f..43b7191e94b2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1827,9 +1827,6 @@ static int set_pedit_val(u8 hdr_type, u32 mask, u32 val, u32 offset, { u32 *curr_pmask, *curr_pval; - if (hdr_type >= 2) - goto out_err; - curr_pmask = (u32 *)(pedit_header(&hdrs->masks, hdr_type) + offset); curr_pval = (u32 *)(pedit_header(&hdrs->vals, hdr_type) + offset); -- cgit v1.2.3 From 988ab9c7363a5b24e9221ea52227b65b3ce3e5db Mon Sep 17 00:00:00 2001 From: Tonghao Zhang Date: Mon, 11 Feb 2019 19:39:42 -0800 Subject: net/mlx5e: Introduce mlx5e_flow_esw_attr_init() helper Introduce the mlx5e_flow_esw_attr_init() helper for simplifying codes. Signed-off-by: Tonghao Zhang Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 41 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 43b7191e94b2..1df7e7d6431b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2733,6 +2733,30 @@ err_free: return err; } +static void +mlx5e_flow_esw_attr_init(struct mlx5_esw_flow_attr *esw_attr, + struct mlx5e_priv *priv, + struct mlx5e_tc_flow_parse_attr *parse_attr, + struct tc_cls_flower_offload *f, + struct mlx5_eswitch_rep *in_rep, + struct mlx5_core_dev *in_mdev) +{ + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + + esw_attr->parse_attr = parse_attr; + esw_attr->chain = f->common.chain_index; + esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16; + + esw_attr->in_rep = in_rep; + esw_attr->in_mdev = in_mdev; + + if (MLX5_CAP_ESW(esw->dev, counter_eswitch_affinity) == + MLX5_COUNTER_SOURCE_ESWITCH) + esw_attr->counter_dev = in_mdev; + else + esw_attr->counter_dev = priv->mdev; +} + static struct mlx5e_tc_flow * __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct tc_cls_flower_offload *f, @@ -2754,28 +2778,21 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, &parse_attr, &flow); if (err) goto out; + parse_attr->filter_dev = filter_dev; - flow->esw_attr->parse_attr = parse_attr; + mlx5e_flow_esw_attr_init(flow->esw_attr, + priv, parse_attr, + f, in_rep, in_mdev); + err = parse_cls_flower(flow->priv, flow, &parse_attr->spec, f, filter_dev); if (err) goto err_free; - flow->esw_attr->chain = f->common.chain_index; - flow->esw_attr->prio = TC_H_MAJ(f->common.prio) >> 16; err = parse_tc_fdb_actions(priv, &rule->action, parse_attr, flow, extack); if (err) goto err_free; - flow->esw_attr->in_rep = in_rep; - flow->esw_attr->in_mdev = in_mdev; - - if (MLX5_CAP_ESW(esw->dev, counter_eswitch_affinity) == - MLX5_COUNTER_SOURCE_ESWITCH) - flow->esw_attr->counter_dev = in_mdev; - else - flow->esw_attr->counter_dev = priv->mdev; - err = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow, extack); if (err) goto err_free; -- cgit v1.2.3 From 7040632df58481424dd958a26ac0fa2d97721f22 Mon Sep 17 00:00:00 2001 From: Tonghao Zhang Date: Mon, 11 Feb 2019 19:39:43 -0800 Subject: net/mlx5e: Remove 'parse_attr' argument in mlx5e_tc_add_fdb_flow() This patch is a little improvement. Simplify the mlx5e_tc_add_fdb_flow(). Signed-off-by: Tonghao Zhang Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 1df7e7d6431b..0b3cd3f7f18a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -929,13 +929,13 @@ mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, static int mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, - struct mlx5e_tc_flow_parse_attr *parse_attr, struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; u32 max_chain = mlx5_eswitch_get_chain_range(esw); struct mlx5_esw_flow_attr *attr = flow->esw_attr; + struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr; u16 max_prio = mlx5_eswitch_get_prio_range(esw); struct net_device *out_dev, *encap_dev = NULL; struct mlx5_fc *counter = NULL; @@ -967,7 +967,7 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, if (!(attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) continue; - mirred_ifindex = attr->parse_attr->mirred_ifindex[out_index]; + mirred_ifindex = parse_attr->mirred_ifindex[out_index]; out_dev = __dev_get_by_index(dev_net(priv->netdev), mirred_ifindex); err = mlx5e_attach_encap(priv, @@ -2793,7 +2793,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, if (err) goto err_free; - err = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow, extack); + err = mlx5e_tc_add_fdb_flow(priv, flow, extack); if (err) goto err_free; -- cgit v1.2.3 From 36a73471e55967248a4911517ab8deb410882060 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Sun, 17 Feb 2019 15:21:27 +0200 Subject: net/mlx5e: Add missing static function annotation Compilation with W=1 produces following warning: drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c:69:6: warning: no previous prototype for _mlx5e_monitor_counter_start_ [-Wmissing-prototypes] void mlx5e_monitor_counter_start(struct mlx5e_priv *priv) ^~~~~~~~~~~~~~~~~~~~~~~~~~~ Avoid it by declaring mlx5e_monitor_counter_start() as a static function. Fixes: 5c7e8bbb0257 ("net/mlx5e: Use monitor counters for update stats") Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c index 2ce420851e77..7cd5b02e0f10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/monitor_stats.c @@ -66,7 +66,7 @@ static int mlx5e_monitor_event_handler(struct notifier_block *nb, return NOTIFY_OK; } -void mlx5e_monitor_counter_start(struct mlx5e_priv *priv) +static void mlx5e_monitor_counter_start(struct mlx5e_priv *priv) { MLX5_NB_INIT(&priv->monitor_counters_nb, mlx5e_monitor_event_handler, MONITOR_COUNTER); -- cgit v1.2.3 From 566428375a53619196e31803130dd1a7010c4d7f Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Sun, 17 Feb 2019 15:21:28 +0200 Subject: net/mlx5: Delete unused FPGA QPN variable fpga_qpn was assigned but never used and compilation with W=1 produced the following warning: drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c: In function _mlx5_fpga_event_: drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c:320:6: warning: variable _fpga_qpn_ set but not used [-Wunused-but-set-variable] u32 fpga_qpn; ^~~~~~~~ Fixes: 98db16bab59f ("net/mlx5: FPGA, Handle QP error event") Signed-off-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c index 27c5f6c7d36a..d046d1ec2a86 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c @@ -317,7 +317,6 @@ static int mlx5_fpga_event(struct mlx5_fpga_device *fdev, const char *event_name; bool teardown = false; unsigned long flags; - u32 fpga_qpn; u8 syndrome; switch (event) { @@ -328,7 +327,6 @@ static int mlx5_fpga_event(struct mlx5_fpga_device *fdev, case MLX5_EVENT_TYPE_FPGA_QP_ERROR: syndrome = MLX5_GET(fpga_qp_error_event, data, syndrome); event_name = mlx5_fpga_qp_syndrome_to_string(syndrome); - fpga_qpn = MLX5_GET(fpga_qp_error_event, data, fpga_qpn); break; default: return NOTIFY_DONE; -- cgit v1.2.3 From e87636117e9a093ae221c1b935bf1a698be50df0 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Tue, 19 Feb 2019 12:32:53 -0800 Subject: net/mlx5e: Remove unused variable ‘esw’ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following compiler warning: drivers/net/ethernet/mellanox/mlx5/core/en_tc.c:2770: warning: unused variable ‘esw’ [-Wunused-variable] Fixes: 1cd3ab86b713 ("net/mlx5e: Introduce mlx5e_flow_esw_attr_init() helper") Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 0b3cd3f7f18a..b38986e18dd7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2767,7 +2767,6 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, { struct flow_rule *rule = tc_cls_flower_offload_flow_rule(f); struct netlink_ext_ack *extack = f->common.extack; - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5e_tc_flow_parse_attr *parse_attr; struct mlx5e_tc_flow *flow; int attr_size, err; -- cgit v1.2.3 From acad70731e63aa3a901bc04a81a4a152cadbe9bf Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Sun, 17 Feb 2019 22:23:16 -0600 Subject: net/mlx5: E-Switch, Fix the warning on vport index out of range When eswitch gets vport data structure, the index should not be out of the range of the vport array. Driver mistakenly used vport number to check the range. Fixes: 22b8ddc86bf4 ("net/mlx5: E-Switch, Assign a different position for uplink rep and vport") Signed-off-by: Bodong Wang Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index e18af31336e6..d4f6859bf58c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -87,7 +87,7 @@ static struct mlx5_vport *mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, { u16 idx = mlx5_eswitch_vport_num_to_index(esw, vport_num); - WARN_ON(vport_num > esw->total_vports - 1); + WARN_ON(idx > esw->total_vports - 1); return &esw->vports[idx]; } -- cgit v1.2.3 From 1c50d369f560809d45e75fa9d7d6b3901192c18b Mon Sep 17 00:00:00 2001 From: Bodong Wang Date: Sun, 17 Feb 2019 21:04:42 -0600 Subject: net/mlx5: E-Switch, Disable esw manager vport correctly When disabling vport, relevant vport configurations will be cleaned up. These cleanups should be done to the vports which had these configs applied at vport enablement. As esw manager vport didn't have such vport config applied, cleanup should not touch it. Fixes: de9e6a8136c5 ("net/mlx5: E-Switch, Properly refer to host PF vport as other vport") Signed-off-by: Bodong Wang Reported-by: Eli Britstein Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index d4f6859bf58c..6cb9710f76d5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1606,7 +1606,8 @@ static void esw_disable_vport(struct mlx5_eswitch *esw, esw_vport_change_handle_locked(vport); vport->enabled_events = 0; esw_vport_disable_qos(esw, vport_num); - if (esw->mode == SRIOV_LEGACY) { + if (esw->manager_vport != vport_num && + esw->mode == SRIOV_LEGACY) { mlx5_modify_vport_admin_state(esw->dev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT, vport_num, 1, -- cgit v1.2.3 From 58066ac9d7f5dcde4ef08c03b7e127f0522d9ea0 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 19 Feb 2019 14:21:20 +0000 Subject: ptp_qoriq: don't pass a large struct by value but instead pass it by reference Passing the struct ptp_clock_info caps by parameter is passing over 130 bytes of data by value on the stack. Optimize this by passing it by reference instead. Also shinks the object code size: Before: text data bss dec hex filename 12596 2160 64 14820 39e4 drivers/ptp/ptp_qoriq.o After: text data bss dec hex filename 12567 2160 64 14791 39c7 drivers/ptp/ptp_qoriq.o Signed-off-by: Colin Ian King Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/enetc_ptp.c | 2 +- drivers/ptp/ptp_qoriq.c | 6 +++--- include/linux/fsl/ptp_qoriq.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c index dc2f58a7c9e5..8c1497e7d9c5 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_ptp.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_ptp.c @@ -92,7 +92,7 @@ static int enetc_ptp_probe(struct pci_dev *pdev, ptp_qoriq->dev = &pdev->dev; - err = ptp_qoriq_init(ptp_qoriq, base, enetc_ptp_caps); + err = ptp_qoriq_init(ptp_qoriq, base, &enetc_ptp_caps); if (err) goto err_no_clock; diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c index 42d3654f77f0..53775362aac6 100644 --- a/drivers/ptp/ptp_qoriq.c +++ b/drivers/ptp/ptp_qoriq.c @@ -459,7 +459,7 @@ static int ptp_qoriq_auto_config(struct ptp_qoriq *ptp_qoriq, } int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, - const struct ptp_clock_info caps) + const struct ptp_clock_info *caps) { struct device_node *node = ptp_qoriq->dev->of_node; struct ptp_qoriq_registers *regs; @@ -468,7 +468,7 @@ int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, u32 tmr_ctrl; ptp_qoriq->base = base; - ptp_qoriq->caps = caps; + ptp_qoriq->caps = *caps; if (of_property_read_u32(node, "fsl,cksel", &ptp_qoriq->cksel)) ptp_qoriq->cksel = DEFAULT_CKSEL; @@ -605,7 +605,7 @@ static int ptp_qoriq_probe(struct platform_device *dev) goto no_ioremap; } - err = ptp_qoriq_init(ptp_qoriq, base, ptp_qoriq_caps); + err = ptp_qoriq_init(ptp_qoriq, base, &ptp_qoriq_caps); if (err) goto no_clock; diff --git a/include/linux/fsl/ptp_qoriq.h b/include/linux/fsl/ptp_qoriq.h index f127adb71041..992bf9fa1729 100644 --- a/include/linux/fsl/ptp_qoriq.h +++ b/include/linux/fsl/ptp_qoriq.h @@ -183,7 +183,7 @@ static inline void qoriq_write_le(unsigned __iomem *addr, u32 val) irqreturn_t ptp_qoriq_isr(int irq, void *priv); int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, - const struct ptp_clock_info caps); + const struct ptp_clock_info *caps); void ptp_qoriq_free(struct ptp_qoriq *ptp_qoriq); int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm); int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta); -- cgit v1.2.3 From 28bbe23740418384e5731e984b79babd763f7181 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 19 Feb 2019 14:11:43 +0200 Subject: ath10k: change 'unsigned long int' to 'unsigned long' Fixes checkpatch warnings: Prefer 'unsigned long' over 'unsigned long int' as the int is unnecessary Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 16 ++++++++-------- drivers/net/wireless/ath/ath10k/debug.h | 20 ++++++++++---------- drivers/net/wireless/ath/ath10k/debugfs_sta.c | 10 +++++----- drivers/net/wireless/ath/ath10k/htt_rx.c | 16 ++++++++-------- drivers/net/wireless/ath/ath10k/snoc.h | 2 +- 5 files changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 2f43600717ec..482e60221ccb 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -448,14 +448,14 @@ enum ath10k_amsdu_subfrm_num { }; struct ath10k_sta_tid_stats { - unsigned long int rx_pkt_from_fw; - unsigned long int rx_pkt_unchained; - unsigned long int rx_pkt_drop_chained; - unsigned long int rx_pkt_drop_filter; - unsigned long int rx_pkt_err[ATH10K_PKT_RX_ERR_MAX]; - unsigned long int rx_pkt_queued_for_mac; - unsigned long int rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MAX]; - unsigned long int rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MAX]; + unsigned long rx_pkt_from_fw; + unsigned long rx_pkt_unchained; + unsigned long rx_pkt_drop_chained; + unsigned long rx_pkt_drop_filter; + unsigned long rx_pkt_err[ATH10K_PKT_RX_ERR_MAX]; + unsigned long rx_pkt_queued_for_mac; + unsigned long rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MAX]; + unsigned long rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MAX]; }; enum ath10k_counter_type { diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 5cf16d690724..eecafdbc873f 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -213,12 +213,12 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void ath10k_sta_update_rx_duration(struct ath10k *ar, struct ath10k_fw_stats *stats); void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr, - unsigned long int num_msdus, + unsigned long num_msdus, enum ath10k_pkt_rx_err err, - unsigned long int unchain_cnt, - unsigned long int drop_cnt, - unsigned long int drop_cnt_filter, - unsigned long int queued_msdus); + unsigned long unchain_cnt, + unsigned long drop_cnt, + unsigned long drop_cnt_filter, + unsigned long queued_msdus); void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid, struct htt_rx_indication_mpdu_range *ranges, @@ -232,12 +232,12 @@ void ath10k_sta_update_rx_duration(struct ath10k *ar, static inline void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr, - unsigned long int num_msdus, + unsigned long num_msdus, enum ath10k_pkt_rx_err err, - unsigned long int unchain_cnt, - unsigned long int drop_cnt, - unsigned long int drop_cnt_filter, - unsigned long int queued_msdus) + unsigned long unchain_cnt, + unsigned long drop_cnt, + unsigned long drop_cnt_filter, + unsigned long queued_msdus) { } diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 4778a455d81a..ab49793353f4 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -87,12 +87,12 @@ out: } void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr, - unsigned long int num_msdus, + unsigned long num_msdus, enum ath10k_pkt_rx_err err, - unsigned long int unchain_cnt, - unsigned long int drop_cnt, - unsigned long int drop_cnt_filter, - unsigned long int queued_msdus) + unsigned long unchain_cnt, + unsigned long drop_cnt, + unsigned long drop_cnt_filter, + unsigned long queued_msdus) { struct ieee80211_sta *sta; struct ath10k_sta *arsta; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index d5c666c2504c..1afaa107024a 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1905,7 +1905,7 @@ static void ath10k_htt_rx_h_enqueue(struct ath10k *ar, } static int ath10k_unchain_msdu(struct sk_buff_head *amsdu, - unsigned long int *unchain_cnt) + unsigned long *unchain_cnt) { struct sk_buff *skb, *first; int space; @@ -1954,8 +1954,8 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu, static void ath10k_htt_rx_h_unchain(struct ath10k *ar, struct sk_buff_head *amsdu, - unsigned long int *drop_cnt, - unsigned long int *unchain_cnt) + unsigned long *drop_cnt, + unsigned long *unchain_cnt) { struct sk_buff *first; struct htt_rx_desc *rxd; @@ -2005,7 +2005,7 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, static void ath10k_htt_rx_h_filter(struct ath10k *ar, struct sk_buff_head *amsdu, struct ieee80211_rx_status *rx_status, - unsigned long int *drop_cnt) + unsigned long *drop_cnt) { if (skb_queue_empty(amsdu)) return; @@ -2025,10 +2025,10 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) struct ieee80211_rx_status *rx_status = &htt->rx_status; struct sk_buff_head amsdu; int ret; - unsigned long int drop_cnt = 0; - unsigned long int unchain_cnt = 0; - unsigned long int drop_cnt_filter = 0; - unsigned long int msdus_to_queue, num_msdus; + unsigned long drop_cnt = 0; + unsigned long unchain_cnt = 0; + unsigned long drop_cnt_filter = 0; + unsigned long msdus_to_queue, num_msdus; enum ath10k_pkt_rx_err err = ATH10K_PKT_RX_ERR_MAX; u8 first_hdr[RX_HTT_HDR_STATUS_LEN]; diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index 2b2f23cf7c5d..4e256ae4b3ff 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -90,7 +90,7 @@ struct ath10k_snoc { struct ath10k_vreg_info *vreg; struct ath10k_clk_info *clk; struct ath10k_qmi *qmi; - unsigned long int flags; + unsigned long flags; }; static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar) -- cgit v1.2.3 From f0553ca9ceb5ff403623e31b7501d33ec84ce1fa Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 19 Feb 2019 19:45:26 +0200 Subject: ath10k: switch to use SPDX license identifiers Use SPDX identifiers everywhere in ath10k. Makefile was incorrectly marked in commit b24413180f56 ("License cleanup: add SPDX GPL-2.0 license identifier to files with no license"), fix that as well. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/Makefile | 2 +- drivers/net/wireless/ath/ath10k/ahb.c | 13 +------------ drivers/net/wireless/ath/ath10k/ahb.h | 13 +------------ drivers/net/wireless/ath/ath10k/bmi.c | 13 +------------ drivers/net/wireless/ath/ath10k/bmi.h | 13 +------------ drivers/net/wireless/ath/ath10k/ce.c | 13 +------------ drivers/net/wireless/ath/ath10k/ce.h | 13 +------------ drivers/net/wireless/ath/ath10k/core.c | 13 +------------ drivers/net/wireless/ath/ath10k/core.h | 13 +------------ drivers/net/wireless/ath/ath10k/coredump.c | 13 +------------ drivers/net/wireless/ath/ath10k/coredump.h | 13 +------------ drivers/net/wireless/ath/ath10k/debug.c | 13 +------------ drivers/net/wireless/ath/ath10k/debug.h | 13 +------------ drivers/net/wireless/ath/ath10k/debugfs_sta.c | 13 +------------ drivers/net/wireless/ath/ath10k/hif.h | 13 +------------ drivers/net/wireless/ath/ath10k/htc.c | 13 +------------ drivers/net/wireless/ath/ath10k/htc.h | 13 +------------ drivers/net/wireless/ath/ath10k/htt.c | 13 +------------ drivers/net/wireless/ath/ath10k/htt.h | 13 +------------ drivers/net/wireless/ath/ath10k/htt_rx.c | 13 +------------ drivers/net/wireless/ath/ath10k/htt_tx.c | 13 +------------ drivers/net/wireless/ath/ath10k/hw.c | 13 +------------ drivers/net/wireless/ath/ath10k/hw.h | 13 +------------ drivers/net/wireless/ath/ath10k/mac.c | 13 +------------ drivers/net/wireless/ath/ath10k/mac.h | 13 +------------ drivers/net/wireless/ath/ath10k/p2p.c | 13 +------------ drivers/net/wireless/ath/ath10k/p2p.h | 13 +------------ drivers/net/wireless/ath/ath10k/pci.c | 13 +------------ drivers/net/wireless/ath/ath10k/pci.h | 13 +------------ drivers/net/wireless/ath/ath10k/qmi.c | 13 +------------ drivers/net/wireless/ath/ath10k/qmi.h | 13 +------------ drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c | 13 +------------ drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h | 13 +------------ drivers/net/wireless/ath/ath10k/rx_desc.h | 13 +------------ drivers/net/wireless/ath/ath10k/sdio.c | 13 +------------ drivers/net/wireless/ath/ath10k/sdio.h | 13 +------------ drivers/net/wireless/ath/ath10k/snoc.c | 13 +------------ drivers/net/wireless/ath/ath10k/snoc.h | 13 +------------ drivers/net/wireless/ath/ath10k/spectral.c | 13 +------------ drivers/net/wireless/ath/ath10k/spectral.h | 13 +------------ drivers/net/wireless/ath/ath10k/swap.c | 13 +------------ drivers/net/wireless/ath/ath10k/swap.h | 13 +------------ drivers/net/wireless/ath/ath10k/targaddrs.h | 13 +------------ drivers/net/wireless/ath/ath10k/testmode.c | 13 +------------ drivers/net/wireless/ath/ath10k/testmode.h | 13 +------------ drivers/net/wireless/ath/ath10k/testmode_i.h | 13 +------------ drivers/net/wireless/ath/ath10k/thermal.c | 13 +------------ drivers/net/wireless/ath/ath10k/thermal.h | 13 +------------ drivers/net/wireless/ath/ath10k/trace.c | 13 +------------ drivers/net/wireless/ath/ath10k/trace.h | 13 +------------ drivers/net/wireless/ath/ath10k/txrx.c | 13 +------------ drivers/net/wireless/ath/ath10k/txrx.h | 13 +------------ drivers/net/wireless/ath/ath10k/usb.c | 13 +------------ drivers/net/wireless/ath/ath10k/usb.h | 13 +------------ drivers/net/wireless/ath/ath10k/wmi-ops.h | 13 +------------ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 13 +------------ drivers/net/wireless/ath/ath10k/wmi-tlv.h | 13 +------------ drivers/net/wireless/ath/ath10k/wmi.c | 13 +------------ drivers/net/wireless/ath/ath10k/wmi.h | 13 +------------ drivers/net/wireless/ath/ath10k/wow.c | 13 +------------ drivers/net/wireless/ath/ath10k/wow.h | 13 +------------ 61 files changed, 61 insertions(+), 721 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index 66326b949ab1..142c777b287f 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: GPL-2.0 +# SPDX-License-Identifier: ISC obj-$(CONFIG_ATH10K) += ath10k_core.o ath10k_core-y += mac.o \ debug.o \ diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 66b7ca9ced17..0bf726c55736 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2016-2017 Qualcomm Atheros, Inc. All rights reserved. * Copyright (c) 2015 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index d43e375215c8..cee11a3ae2a5 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved. * Copyright (c) 2015 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _AHB_H_ diff --git a/drivers/net/wireless/ath/ath10k/bmi.c b/drivers/net/wireless/ath/ath10k/bmi.c index 1750b182209b..95dc4be82e5c 100644 --- a/drivers/net/wireless/ath/ath10k/bmi.c +++ b/drivers/net/wireless/ath/ath10k/bmi.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2014,2016-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "bmi.h" diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h index 725c9afc63f2..ef3bdba43bed 100644 --- a/drivers/net/wireless/ath/ath10k/bmi.h +++ b/drivers/net/wireless/ath/ath10k/bmi.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _BMI_H_ diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 9dbe7574443c..cc154a81737d 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "hif.h" diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index f3b4f7ec863d..692b3a8957a9 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _CE_H_ diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index a1b2aea4a77f..ac2cf3f1c7b4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 482e60221ccb..27ec5557de88 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _CORE_H_ diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c index bf84e999466f..33838d9c1cb6 100644 --- a/drivers/net/wireless/ath/ath10k/coredump.c +++ b/drivers/net/wireless/ath/ath10k/coredump.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "coredump.h" diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h index 5dac653e1649..09de41922f97 100644 --- a/drivers/net/wireless/ath/ath10k/coredump.h +++ b/drivers/net/wireless/ath/ath10k/coredump.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _COREDUMP_H_ diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 9f2534d6b56f..1b8903280d42 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index eecafdbc873f..db78e855a80f 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _DEBUG_H_ diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index ab49793353f4..8331d8b09987 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "core.h" diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 04320d792c88..fe5417962f40 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HIF_H_ diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 5aa57a01c033..805a7f8a04f2 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "core.h" diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index cb30add7dd33..f55d3caec61f 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2016 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HTC_H_ diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 55c716499830..d235ff3098e8 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index d194bbe18fc3..fef716aa8f3a 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HTT_H_ diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 1afaa107024a..4fc885617de1 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "core.h" diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 33639a6bf7d6..d8e9cc0bb772 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 48886b6b9056..eeaee8e41b28 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index f9ffed53f2c4..de7dc01bf51d 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _HW_H_ diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 795446d31f78..b73c23d4ce86 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "mac.h" diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 570493d2d648..1fe84948b868 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _MAC_H_ diff --git a/drivers/net/wireless/ath/ath10k/p2p.c b/drivers/net/wireless/ath/ath10k/p2p.c index 7e621ee194e3..29c737b2f432 100644 --- a/drivers/net/wireless/ath/ath10k/p2p.c +++ b/drivers/net/wireless/ath/ath10k/p2p.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2015 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "core.h" diff --git a/drivers/net/wireless/ath/ath10k/p2p.h b/drivers/net/wireless/ath/ath10k/p2p.h index 7be616e2e121..7d7f44809fbb 100644 --- a/drivers/net/wireless/ath/ath10k/p2p.h +++ b/drivers/net/wireless/ath/ath10k/p2p.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2015 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _P2P_H diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 71d854e2f9fc..271f92c24d44 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index a9270fa6463c..3773c79f322f 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _PCI_H_ diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c index 37b3bd629f48..a7bc2c70d076 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/qmi.h b/drivers/net/wireless/ath/ath10k/qmi.h index 1efe1d22fc2f..e4aa20445666 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.h +++ b/drivers/net/wireless/ath/ath10k/qmi.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _ATH10K_QMI_H_ #define _ATH10K_QMI_H_ diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c index 4102f7b0b5c3..1fe05c6218c3 100644 --- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c +++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h index ff668f5d8afd..bca1186e1560 100644 --- a/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h +++ b/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef WCN3990_QMI_SVC_V01_H diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h index dfbfe674e11e..dec1582005b9 100644 --- a/drivers/net/wireless/ath/ath10k/rx_desc.h +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _RX_DESC_H_ diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 7654536b830b..d62502f386f2 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2004-2011 Atheros Communications Inc. * Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc. * Copyright (c) 2016-2017 Erik Stromdahl - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/sdio.h b/drivers/net/wireless/ath/ath10k/sdio.h index 453eb6263143..b8c7ac0330bd 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.h +++ b/drivers/net/wireless/ath/ath10k/sdio.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2004-2011 Atheros Communications Inc. * Copyright (c) 2011-2012 Qualcomm Atheros, Inc. * Copyright (c) 2016-2017 Erik Stromdahl - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SDIO_H_ diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index b81b02ae384f..873cb4ce419b 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index 4e256ae4b3ff..d62f53501fbb 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2018 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SNOC_H_ diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c index 4a7fa3e4e99f..5db6bff5193b 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.c +++ b/drivers/net/wireless/ath/ath10k/spectral.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2013-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h index 13276f4dc12c..5f481f11c6e5 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.h +++ b/drivers/net/wireless/ath/ath10k/spectral.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2013-2015 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef SPECTRAL_H diff --git a/drivers/net/wireless/ath/ath10k/swap.c b/drivers/net/wireless/ath/ath10k/swap.c index e7f57efadae1..4dddeee684b4 100644 --- a/drivers/net/wireless/ath/ath10k/swap.c +++ b/drivers/net/wireless/ath/ath10k/swap.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2015-2016 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* This file has implementation for code swap logic. With code swap feature, diff --git a/drivers/net/wireless/ath/ath10k/swap.h b/drivers/net/wireless/ath/ath10k/swap.h index fa602f15fa93..25e0ad36ddb1 100644 --- a/drivers/net/wireless/ath/ath10k/swap.h +++ b/drivers/net/wireless/ath/ath10k/swap.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2015-2016 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SWAP_H_ diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index b11a1c3d87b4..dff6c8ac9dba 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2016 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __TARGADDRS_H__ diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index 67faafecaf06..6433ff10d80e 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "testmode.h" diff --git a/drivers/net/wireless/ath/ath10k/testmode.h b/drivers/net/wireless/ath/ath10k/testmode.h index 9cdd150815db..6488fd514ae3 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.h +++ b/drivers/net/wireless/ath/ath10k/testmode.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2014 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "core.h" diff --git a/drivers/net/wireless/ath/ath10k/testmode_i.h b/drivers/net/wireless/ath/ath10k/testmode_i.h index 6514d1a14242..ee1cb27c1d60 100644 --- a/drivers/net/wireless/ath/ath10k/testmode_i.h +++ b/drivers/net/wireless/ath/ath10k/testmode_i.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* "API" level of the ath10k testmode interface. Bump it after every diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c index fe35edcd3ec8..36c9a1364253 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.c +++ b/drivers/net/wireless/ath/ath10k/thermal.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/thermal.h b/drivers/net/wireless/ath/ath10k/thermal.h index 65e2419543f9..5fdb020f4da3 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.h +++ b/drivers/net/wireless/ath/ath10k/thermal.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _THERMAL_ #define _THERMAL_ diff --git a/drivers/net/wireless/ath/ath10k/trace.c b/drivers/net/wireless/ath/ath10k/trace.c index 4a31e2c6fbd4..3ecdff17f64e 100644 --- a/drivers/net/wireless/ath/ath10k/trace.c +++ b/drivers/net/wireless/ath/ath10k/trace.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index 7d2fac342150..ba977bbe6291 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2016 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index a555fa38d834..c5818d28f55a 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2016 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "core.h" diff --git a/drivers/net/wireless/ath/ath10k/txrx.h b/drivers/net/wireless/ath/ath10k/txrx.h index 2bf401e436d3..ecac441d83a7 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.h +++ b/drivers/net/wireless/ath/ath10k/txrx.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2014,2016 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _TXRX_H_ #define _TXRX_H_ diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c index d3677765f96c..970cf69ac35f 100644 --- a/drivers/net/wireless/ath/ath10k/usb.c +++ b/drivers/net/wireless/ath/ath10k/usb.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2007-2011 Atheros Communications Inc. * Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc. * Copyright (c) 2016-2017 Erik Stromdahl - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/usb.h b/drivers/net/wireless/ath/ath10k/usb.h index f60a3cc7d712..34d683e8fc18 100644 --- a/drivers/net/wireless/ath/ath10k/usb.h +++ b/drivers/net/wireless/ath/ath10k/usb.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2004-2011 Atheros Communications Inc. * Copyright (c) 2011-2012 Qualcomm Atheros, Inc. * Copyright (c) 2016-2017 Erik Stromdahl - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _USB_H_ diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 015084220857..1491c25518bb 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _WMI_OPS_H_ diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 5d05bff2c5da..fc62174a115c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "core.h" #include "debug.h" diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 4fba5815cd61..af4cb0e14952 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _WMI_TLV_H #define _WMI_TLV_H diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 704c71bc3ef6..97e5b2eb8a91 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 0e2787821121..d9b646f3dcc2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1,19 +1,8 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _WMI_H_ diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c index b36fa0f8892e..8c26adddd034 100644 --- a/drivers/net/wireless/ath/ath10k/wow.c +++ b/drivers/net/wireless/ath/ath10k/wow.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2015-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "mac.h" diff --git a/drivers/net/wireless/ath/ath10k/wow.h b/drivers/net/wireless/ath/ath10k/wow.h index 6e810105b775..14ea4e1e925e 100644 --- a/drivers/net/wireless/ath/ath10k/wow.h +++ b/drivers/net/wireless/ath/ath10k/wow.h @@ -1,17 +1,6 @@ +/* SPDX-License-Identifier: ISC */ /* * Copyright (c) 2015,2017 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _WOW_H_ #define _WOW_H_ -- cgit v1.2.3 From dcb1471bc6d0541d636c7ecd9239573304842884 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 19 Feb 2019 23:42:19 +0100 Subject: brcmfmac: use bphy_err() in all wiphy-related code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This recently added macro provides more meaningful error messages thanks to identifying a specific wiphy. It's especially important on systems with few cards supported by the same (brcmfmac) driver. Signed-off-by: Rafał Miłecki Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 22 +++--- .../wireless/broadcom/brcm80211/brcmfmac/common.c | 39 +++++----- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 74 +++++++++--------- .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 8 +- .../wireless/broadcom/brcm80211/brcmfmac/fweh.c | 25 +++--- .../wireless/broadcom/brcm80211/brcmfmac/fwil.c | 10 +-- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 38 ++++++---- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 65 +++++++++------- .../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 88 +++++++++++++--------- .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 22 ++++-- .../wireless/broadcom/brcm80211/brcmfmac/proto.c | 6 +- 11 files changed, 224 insertions(+), 173 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 1068a2a4494c..73d3c1a0a7c9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -178,8 +178,8 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, *fwerr = 0; ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false); if (ret < 0) { - brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n", - ret); + bphy_err(drvr, "brcmf_proto_bcdc_msg failed w/status %d\n", + ret); goto done; } @@ -195,9 +195,9 @@ retry: if ((id < bcdc->reqid) && (++retries < RETRIES)) goto retry; if (id != bcdc->reqid) { - brcmf_err("%s: unexpected request id %d (expected %d)\n", - brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id, - bcdc->reqid); + bphy_err(drvr, "%s: unexpected request id %d (expected %d)\n", + brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id, + bcdc->reqid); ret = -EINVAL; goto done; } @@ -245,9 +245,9 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT; if (id != bcdc->reqid) { - brcmf_err("%s: unexpected request id %d (expected %d)\n", - brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id, - bcdc->reqid); + bphy_err(drvr, "%s: unexpected request id %d (expected %d)\n", + brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id, + bcdc->reqid); ret = -EINVAL; goto done; } @@ -312,8 +312,8 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, } if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != BCDC_PROTO_VER) { - brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", - brcmf_ifname(tmp_if), h->flags); + bphy_err(drvr, "%s: non-BCDC packet received, flags 0x%x\n", + brcmf_ifname(tmp_if), h->flags); return -EBADE; } @@ -460,7 +460,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) /* ensure that the msg buf directly follows the cdc msg struct */ if ((unsigned long)(&bcdc->msg + 1) != (unsigned long)bcdc->buf) { - brcmf_err("struct brcmf_proto_bcdc is not correctly defined\n"); + bphy_err(drvr, "struct brcmf_proto_bcdc is not correctly defined\n"); goto fail; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index c62009a06617..96b8d5b3aeed 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -90,6 +90,7 @@ struct brcmf_mp_global_t brcmf_mp_global; void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) { + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_join_pref_params join_pref_params[2]; int err; @@ -106,7 +107,7 @@ void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, sizeof(join_pref_params)); if (err) - brcmf_err("Set join_pref error (%d)\n", err); + bphy_err(drvr, "Set join_pref error (%d)\n", err); } static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, @@ -129,7 +130,8 @@ static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) { - struct brcmf_bus *bus = ifp->drvr->bus_if; + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_bus *bus = drvr->bus_if; struct brcmf_dload_data_le *chunk_buf; const struct firmware *clm = NULL; u8 clm_name[BRCMF_FW_NAME_LEN]; @@ -145,7 +147,7 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) memset(clm_name, 0, sizeof(clm_name)); err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name); if (err) { - brcmf_err("get CLM blob file name failed (%d)\n", err); + bphy_err(drvr, "get CLM blob file name failed (%d)\n", err); return err; } @@ -182,12 +184,12 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) } while ((datalen > 0) && (err == 0)); if (err) { - brcmf_err("clmload (%zu byte file) failed (%d); ", - clm->size, err); + bphy_err(drvr, "clmload (%zu byte file) failed (%d)\n", + clm->size, err); /* Retrieve clmload_status and print */ err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status); if (err) - brcmf_err("get clmload_status failed (%d)\n", err); + bphy_err(drvr, "get clmload_status failed (%d)\n", err); else brcmf_dbg(INFO, "clmload_status=%d\n", status); err = -EIO; @@ -201,6 +203,7 @@ done: int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) { + struct brcmf_pub *drvr = ifp->drvr; s8 eventmask[BRCMF_EVENTING_MASK_LEN]; u8 buf[BRCMF_DCMD_SMLEN]; struct brcmf_bus *bus; @@ -214,7 +217,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, sizeof(ifp->mac_addr)); if (err < 0) { - brcmf_err("Retrieving cur_etheraddr failed, %d\n", err); + bphy_err(drvr, "Retrieving cur_etheraddr failed, %d\n", err); goto done; } memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN); @@ -226,7 +229,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO, &revinfo, sizeof(revinfo)); if (err < 0) { - brcmf_err("retrieving revision info failed, %d\n", err); + bphy_err(drvr, "retrieving revision info failed, %d\n", err); strlcpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname)); } else { ri->vendorid = le32_to_cpu(revinfo.vendorid); @@ -260,7 +263,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) /* Do any CLM downloading */ err = brcmf_c_process_clm_blob(ifp); if (err < 0) { - brcmf_err("download CLM blob file failed, %d\n", err); + bphy_err(drvr, "download CLM blob file failed, %d\n", err); goto done; } @@ -269,8 +272,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) strcpy(buf, "ver"); err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); if (err < 0) { - brcmf_err("Retrieving version information failed, %d\n", - err); + bphy_err(drvr, "Retrieving version information failed, %d\n", + err); goto done; } ptr = (char *)buf; @@ -304,7 +307,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) /* set mpc */ err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); if (err) { - brcmf_err("failed setting mpc\n"); + bphy_err(drvr, "failed setting mpc\n"); goto done; } @@ -314,14 +317,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN); if (err) { - brcmf_err("Get event_msgs error (%d)\n", err); + bphy_err(drvr, "Get event_msgs error (%d)\n", err); goto done; } setbit(eventmask, BRCMF_E_IF); err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN); if (err) { - brcmf_err("Set event_msgs error (%d)\n", err); + bphy_err(drvr, "Set event_msgs error (%d)\n", err); goto done; } @@ -329,8 +332,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, BRCMF_DEFAULT_SCAN_CHANNEL_TIME); if (err) { - brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", - err); + bphy_err(drvr, "BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", + err); goto done; } @@ -338,8 +341,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, BRCMF_DEFAULT_SCAN_UNASSOC_TIME); if (err) { - brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", - err); + bphy_err(drvr, "BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", + err); goto done; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 9d911ddefe82..4fbe8791f674 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -90,7 +90,7 @@ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) s32 bsscfgidx; if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { - brcmf_err("ifidx %d out of range\n", ifidx); + bphy_err(drvr, "ifidx %d out of range\n", ifidx); return NULL; } @@ -141,7 +141,9 @@ void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable) static void _brcmf_set_multicast_list(struct work_struct *work) { - struct brcmf_if *ifp; + struct brcmf_if *ifp = container_of(work, struct brcmf_if, + multicast_work); + struct brcmf_pub *drvr = ifp->drvr; struct net_device *ndev; struct netdev_hw_addr *ha; u32 cmd_value, cnt; @@ -150,8 +152,6 @@ static void _brcmf_set_multicast_list(struct work_struct *work) u32 buflen; s32 err; - ifp = container_of(work, struct brcmf_if, multicast_work); - brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); ndev = ifp->ndev; @@ -181,7 +181,7 @@ static void _brcmf_set_multicast_list(struct work_struct *work) err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen); if (err < 0) { - brcmf_err("Setting mcast_list failed, %d\n", err); + bphy_err(drvr, "Setting mcast_list failed, %d\n", err); cmd_value = cnt ? true : cmd_value; } @@ -194,25 +194,25 @@ static void _brcmf_set_multicast_list(struct work_struct *work) */ err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value); if (err < 0) - brcmf_err("Setting allmulti failed, %d\n", err); + bphy_err(drvr, "Setting allmulti failed, %d\n", err); /*Finally, pick up the PROMISC flag */ cmd_value = (ndev->flags & IFF_PROMISC) ? true : false; err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value); if (err < 0) - brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n", - err); + bphy_err(drvr, "Setting BRCMF_C_SET_PROMISC failed, %d\n", + err); brcmf_configure_arp_nd_offload(ifp, !cmd_value); } #if IS_ENABLED(CONFIG_IPV6) static void _brcmf_update_ndtable(struct work_struct *work) { - struct brcmf_if *ifp; + struct brcmf_if *ifp = container_of(work, struct brcmf_if, + ndoffload_work); + struct brcmf_pub *drvr = ifp->drvr; int i, ret; - ifp = container_of(work, struct brcmf_if, ndoffload_work); - /* clear the table in firmware */ ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip_clear", NULL, 0); if (ret) { @@ -225,7 +225,7 @@ static void _brcmf_update_ndtable(struct work_struct *work) &ifp->ipv6_addr_tbl[i], sizeof(struct in6_addr)); if (ret) - brcmf_err("add nd ip err %d\n", ret); + bphy_err(drvr, "add nd ip err %d\n", ret); } } #else @@ -238,6 +238,7 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) { struct brcmf_if *ifp = netdev_priv(ndev); struct sockaddr *sa = (struct sockaddr *)addr; + struct brcmf_pub *drvr = ifp->drvr; int err; brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); @@ -245,7 +246,7 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr) err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", sa->sa_data, ETH_ALEN); if (err < 0) { - brcmf_err("Setting cur_etheraddr failed, %d\n", err); + bphy_err(drvr, "Setting cur_etheraddr failed, %d\n", err); } else { brcmf_dbg(TRACE, "updated to %pM\n", sa->sa_data); memcpy(ifp->mac_addr, sa->sa_data, ETH_ALEN); @@ -305,7 +306,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, /* Can the device send data? */ if (drvr->bus_if->state != BRCMF_BUS_UP) { - brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state); + bphy_err(drvr, "xmit rejected state=%d\n", drvr->bus_if->state); netif_stop_queue(ndev); dev_kfree_skb(skb); ret = -ENODEV; @@ -339,8 +340,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, ret = pskb_expand_head(skb, ALIGN(head_delta, NET_SKB_PAD), 0, GFP_ATOMIC); if (ret < 0) { - brcmf_err("%s: failed to expand headroom\n", - brcmf_ifname(ifp)); + bphy_err(drvr, "%s: failed to expand headroom\n", + brcmf_ifname(ifp)); atomic_inc(&drvr->bus_if->stats.pktcow_failed); goto done; } @@ -607,7 +608,7 @@ static int brcmf_netdev_open(struct net_device *ndev) /* If bus is not ready, can't continue */ if (bus_if->state != BRCMF_BUS_UP) { - brcmf_err("failed bus is not ready\n"); + bphy_err(drvr, "failed bus is not ready\n"); return -EAGAIN; } @@ -621,7 +622,7 @@ static int brcmf_netdev_open(struct net_device *ndev) ndev->features &= ~NETIF_F_IP_CSUM; if (brcmf_cfg80211_up(ndev)) { - brcmf_err("failed to bring up cfg80211\n"); + bphy_err(drvr, "failed to bring up cfg80211\n"); return -EIO; } @@ -666,7 +667,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) else err = register_netdev(ndev); if (err != 0) { - brcmf_err("couldn't register the net device\n"); + bphy_err(drvr, "couldn't register the net device\n"); goto fail; } @@ -743,6 +744,7 @@ static const struct net_device_ops brcmf_netdev_ops_p2p = { static int brcmf_net_p2p_attach(struct brcmf_if *ifp) { + struct brcmf_pub *drvr = ifp->drvr; struct net_device *ndev; brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx, @@ -755,7 +757,7 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp) memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN); if (register_netdev(ndev) != 0) { - brcmf_err("couldn't register the p2p net device\n"); + bphy_err(drvr, "couldn't register the p2p net device\n"); goto fail; } @@ -784,8 +786,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx, */ if (ifp) { if (ifidx) { - brcmf_err("ERROR: netdev:%s already exists\n", - ifp->ndev->name); + bphy_err(drvr, "ERROR: netdev:%s already exists\n", + ifp->ndev->name); netif_stop_queue(ifp->ndev); brcmf_net_detach(ifp->ndev, false); drvr->iflist[bsscfgidx] = NULL; @@ -843,7 +845,7 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx, ifp = drvr->iflist[bsscfgidx]; drvr->iflist[bsscfgidx] = NULL; if (!ifp) { - brcmf_err("Null interface, bsscfgidx=%d\n", bsscfgidx); + bphy_err(drvr, "Null interface, bsscfgidx=%d\n", bsscfgidx); return; } brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx, @@ -893,16 +895,17 @@ static int brcmf_psm_watchdog_notify(struct brcmf_if *ifp, const struct brcmf_event_msg *evtmsg, void *data) { + struct brcmf_pub *drvr = ifp->drvr; int err; brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx); - brcmf_err("PSM's watchdog has fired!\n"); + bphy_err(drvr, "PSM's watchdog has fired!\n"); err = brcmf_debug_create_memdump(ifp->drvr->bus_if, data, evtmsg->datalen); if (err) - brcmf_err("Failed to get memory dump, %d\n", err); + bphy_err(drvr, "Failed to get memory dump, %d\n", err); return err; } @@ -946,7 +949,7 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb, ret = brcmf_fil_iovar_data_get(ifp, "arp_hostip", addr_table, sizeof(addr_table)); if (ret) { - brcmf_err("fail to get arp ip table err:%d\n", ret); + bphy_err(drvr, "fail to get arp ip table err:%d\n", ret); return NOTIFY_OK; } @@ -963,7 +966,7 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb, ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip", &ifa->ifa_address, sizeof(ifa->ifa_address)); if (ret) - brcmf_err("add arp ip err %d\n", ret); + bphy_err(drvr, "add arp ip err %d\n", ret); } break; case NETDEV_DOWN: @@ -975,8 +978,8 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb, ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0); if (ret) { - brcmf_err("fail to clear arp ip table err:%d\n", - ret); + bphy_err(drvr, "fail to clear arp ip table err:%d\n", + ret); return NOTIFY_OK; } for (i = 0; i < ARPOL_MAX_ENTRIES; i++) { @@ -986,8 +989,8 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb, &addr_table[i], sizeof(addr_table[i])); if (ret) - brcmf_err("add arp ip err %d\n", - ret); + bphy_err(drvr, "add arp ip err %d\n", + ret); } } break; @@ -1161,7 +1164,7 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops) return 0; fail: - brcmf_err("failed: %d\n", ret); + bphy_err(drvr, "failed: %d\n", ret); if (drvr->config) { brcmf_cfg80211_detach(drvr->config); drvr->config = NULL; @@ -1213,7 +1216,7 @@ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings) /* Attach and link in the protocol */ ret = brcmf_proto_attach(drvr); if (ret != 0) { - brcmf_err("brcmf_prot_attach failed\n"); + bphy_err(drvr, "brcmf_prot_attach failed\n"); goto fail; } @@ -1226,7 +1229,7 @@ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings) ret = brcmf_bus_started(drvr, ops); if (ret != 0) { - brcmf_err("dongle is not responding: err=%d\n", ret); + bphy_err(drvr, "dongle is not responding: err=%d\n", ret); goto fail; } @@ -1326,6 +1329,7 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp) int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp) { + struct brcmf_pub *drvr = ifp->drvr; int err; err = wait_event_timeout(ifp->pend_8021x_wait, @@ -1333,7 +1337,7 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp) MAX_WAIT_FOR_8021X_TX); if (!err) - brcmf_err("Timed out waiting for no pending 802.1x packets\n"); + bphy_err(drvr, "Timed out waiting for no pending 802.1x packets\n"); return !err; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index 072c51c953a5..acca719b3907 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -185,13 +185,14 @@ static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp, #define MAX_CAPS_BUFFER_SIZE 768 static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp) { + struct brcmf_pub *drvr = ifp->drvr; char caps[MAX_CAPS_BUFFER_SIZE]; enum brcmf_feat_id id; int i, err; err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps)); if (err) { - brcmf_err("could not get firmware cap (%d)\n", err); + bphy_err(drvr, "could not get firmware cap (%d)\n", err); return; } @@ -216,14 +217,15 @@ static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp) static int brcmf_feat_fwcap_debugfs_read(struct seq_file *seq, void *data) { struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); - struct brcmf_if *ifp = brcmf_get_ifp(bus_if->drvr, 0); + struct brcmf_pub *drvr = bus_if->drvr; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); char caps[MAX_CAPS_BUFFER_SIZE + 1] = { }; char *tmp; int err; err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps)); if (err) { - brcmf_err("could not get firmware cap (%d)\n", err); + bphy_err(drvr, "could not get firmware cap (%d)\n", err); return err; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index e7eaa57d11d9..63e98fd583ab 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -102,7 +102,8 @@ static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh, schedule_work(&fweh->event_work); } -static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp, +static int brcmf_fweh_call_event_handler(struct brcmf_pub *drvr, + struct brcmf_if *ifp, enum brcmf_fweh_event_code code, struct brcmf_event_msg *emsg, void *data) @@ -117,9 +118,9 @@ static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp, if (fweh->evt_handler[code]) err = fweh->evt_handler[code](ifp, emsg, data); else - brcmf_err("unhandled event %d ignored\n", code); + bphy_err(drvr, "unhandled event %d ignored\n", code); } else { - brcmf_err("no interface object\n"); + bphy_err(drvr, "no interface object\n"); } return err; } @@ -158,7 +159,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, return; } if (ifevent->ifidx >= BRCMF_MAX_IFS) { - brcmf_err("invalid interface index: %u\n", ifevent->ifidx); + bphy_err(drvr, "invalid interface index: %u\n", ifevent->ifidx); return; } @@ -181,7 +182,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, if (ifp && ifevent->action == BRCMF_E_IF_CHANGE) brcmf_proto_reset_if(drvr, ifp); - err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); + err = brcmf_fweh_call_event_handler(drvr, ifp, emsg->event_code, emsg, + data); if (ifp && ifevent->action == BRCMF_E_IF_DEL) { bool armed = brcmf_cfg80211_vif_event_armed(drvr->config); @@ -268,11 +270,11 @@ static void brcmf_fweh_event_worker(struct work_struct *work) ifp = drvr->iflist[0]; else ifp = drvr->iflist[emsg.bsscfgidx]; - err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg, - event->data); + err = brcmf_fweh_call_event_handler(drvr, ifp, event->code, + &emsg, event->data); if (err) { - brcmf_err("event handler failed (%d)\n", - event->code); + bphy_err(drvr, "event handler failed (%d)\n", + event->code); err = 0; } event_free: @@ -339,7 +341,7 @@ int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code, brcmf_fweh_handler_t handler) { if (drvr->fweh.evt_handler[code]) { - brcmf_err("event code %d already registered\n", code); + bphy_err(drvr, "event code %d already registered\n", code); return -ENOSPC; } drvr->fweh.evt_handler[code] = handler; @@ -369,6 +371,7 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr, */ int brcmf_fweh_activate_events(struct brcmf_if *ifp) { + struct brcmf_pub *drvr = ifp->drvr; int i, err; s8 eventmask[BRCMF_EVENTING_MASK_LEN]; @@ -388,7 +391,7 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp) err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN); if (err) - brcmf_err("Set event_msgs error (%d)\n", err); + bphy_err(drvr, "Set event_msgs error (%d)\n", err); return err; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c index 802d7cb73b80..8ea27489734e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c @@ -110,7 +110,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) s32 err, fwerr; if (drvr->bus_if->state != BRCMF_BUS_UP) { - brcmf_err("bus is down. we have nothing to do.\n"); + bphy_err(drvr, "bus is down. we have nothing to do.\n"); return -EIO; } @@ -242,7 +242,7 @@ brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data, buflen, true); } else { err = -EPERM; - brcmf_err("Creating iovar failed\n"); + bphy_err(drvr, "Creating iovar failed\n"); } mutex_unlock(&drvr->proto_block); @@ -268,7 +268,7 @@ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, memcpy(data, drvr->proto_buf, len); } else { err = -EPERM; - brcmf_err("Creating iovar failed\n"); + bphy_err(drvr, "Creating iovar failed\n"); } brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len); @@ -366,7 +366,7 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, buflen, true); } else { err = -EPERM; - brcmf_err("Creating bsscfg failed\n"); + bphy_err(drvr, "Creating bsscfg failed\n"); } mutex_unlock(&drvr->proto_block); @@ -392,7 +392,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, memcpy(data, drvr->proto_buf, len); } else { err = -EPERM; - brcmf_err("Creating bsscfg failed\n"); + bphy_err(drvr, "Creating bsscfg failed\n"); } brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx, ifp->bsscfgidx, name, len); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 02759ebd207c..abeb305492e0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -1255,6 +1255,7 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, enum brcmf_fws_skb_state state, int fifo, struct sk_buff *p) { + struct brcmf_pub *drvr = fws->drvr; int prec = 2 * fifo; u32 *qfull_stat = &fws->stats.delayq_full_error; struct brcmf_fws_mac_descriptor *entry; @@ -1267,7 +1268,7 @@ static int brcmf_fws_enq(struct brcmf_fws_info *fws, entry = brcmf_skbcb(p)->mac; if (entry == NULL) { - brcmf_err("no mac descriptor found for skb %p\n", p); + bphy_err(drvr, "no mac descriptor found for skb %p\n", p); return -ENOENT; } @@ -1457,6 +1458,7 @@ static int brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, u32 genbit, u16 seq, u8 compcnt) { + struct brcmf_pub *drvr = fws->drvr; u32 fifo; u8 cnt = 0; int ret; @@ -1481,14 +1483,14 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED) fws->stats.txs_host_tossed += compcnt; else - brcmf_err("unexpected txstatus\n"); + bphy_err(drvr, "unexpected txstatus\n"); while (cnt < compcnt) { ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, remove_from_hanger); if (ret != 0) { - brcmf_err("no packet in hanger slot: hslot=%d\n", - hslot); + bphy_err(drvr, "no packet in hanger slot: hslot=%d\n", + hslot); goto cont; } @@ -1612,12 +1614,13 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, const struct brcmf_event_msg *e, void *data) { - struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr); + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_fws_info *fws = drvr_to_fws(drvr); int i; u8 *credits = data; if (e->datalen < BRCMF_FWS_FIFO_COUNT) { - brcmf_err("event payload too small (%d)\n", e->datalen); + bphy_err(drvr, "event payload too small (%d)\n", e->datalen); return -EINVAL; } @@ -1681,6 +1684,7 @@ static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi, void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) { + struct brcmf_pub *drvr = ifp->drvr; u8 *reorder_data; u8 flow_id, max_idx, cur_idx, exp_idx, end_idx; struct brcmf_ampdu_rx_reorder *rfi; @@ -1695,7 +1699,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) /* validate flags and flow id */ if (flags == 0xFF) { - brcmf_err("invalid flags...so ignore this packet\n"); + bphy_err(drvr, "invalid flags...so ignore this packet\n"); brcmf_netif_rx(ifp, pkt); return; } @@ -1732,7 +1736,7 @@ void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt) flow_id, max_idx); rfi = kzalloc(buf_size, GFP_ATOMIC); if (rfi == NULL) { - brcmf_err("failed to alloc buffer\n"); + bphy_err(drvr, "failed to alloc buffer\n"); brcmf_netif_rx(ifp, pkt); return; } @@ -1996,6 +2000,7 @@ static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, struct sk_buff *skb, int fifo) { + struct brcmf_pub *drvr = fws->drvr; struct brcmf_fws_mac_descriptor *entry; struct sk_buff *pktout; int qidx, hslot; @@ -2009,11 +2014,11 @@ static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb); if (pktout == NULL) { - brcmf_err("%s queue %d full\n", entry->name, qidx); + bphy_err(drvr, "%s queue %d full\n", entry->name, qidx); rc = -ENOSPC; } } else { - brcmf_err("%s entry removed\n", entry->name); + bphy_err(drvr, "%s entry removed\n", entry->name); rc = -ENOENT; } @@ -2118,7 +2123,8 @@ static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p, int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) { - struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr); + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_fws_info *fws = drvr_to_fws(drvr); struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); struct ethhdr *eh = (struct ethhdr *)(skb->data); int fifo = BRCMF_FWS_FIFO_BCMC; @@ -2146,7 +2152,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); brcmf_fws_schedule_deq(fws); } else { - brcmf_err("drop skb: no hanger slot\n"); + bphy_err(drvr, "drop skb: no hanger slot\n"); brcmf_txfinalize(ifp, skb, false); rc = -ENOMEM; } @@ -2365,7 +2371,7 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr) fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq"); if (fws->fws_wq == NULL) { - brcmf_err("workqueue creation failed\n"); + bphy_err(drvr, "workqueue creation failed\n"); rc = -EBADF; goto fail; } @@ -2381,13 +2387,13 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr) rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP, brcmf_fws_notify_credit_map); if (rc < 0) { - brcmf_err("register credit map handler failed\n"); + bphy_err(drvr, "register credit map handler failed\n"); goto fail; } rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT, brcmf_fws_notify_bcmc_credit_support); if (rc < 0) { - brcmf_err("register bcmc credit handler failed\n"); + bphy_err(drvr, "register bcmc credit handler failed\n"); brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP); goto fail; } @@ -2399,7 +2405,7 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr) fws->fw_signals = true; ifp = brcmf_get_ifp(drvr, 0); if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) { - brcmf_err("failed to set bdcv2 tlv signaling\n"); + bphy_err(drvr, "failed to set bdcv2 tlv signaling\n"); fws->fcmode = BRCMF_FWS_FCMODE_NONE; fws->fw_signals = false; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 0da0a68f47cb..aef2d4092872 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -439,7 +439,7 @@ static int brcmf_msgbuf_tx_ioctl(struct brcmf_pub *drvr, int ifidx, brcmf_commonring_lock(commonring); ret_ptr = brcmf_commonring_reserve_for_write(commonring); if (!ret_ptr) { - brcmf_err("Failed to reserve space in commonring\n"); + bphy_err(drvr, "Failed to reserve space in commonring\n"); brcmf_commonring_unlock(commonring); return -ENOMEM; } @@ -503,7 +503,7 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx, timeout = brcmf_msgbuf_ioctl_resp_wait(msgbuf); if (!timeout) { - brcmf_err("Timeout on response for query command\n"); + bphy_err(drvr, "Timeout on response for query command\n"); return -EIO; } @@ -580,6 +580,7 @@ static u32 brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf, struct brcmf_msgbuf_work_item *work) { + struct brcmf_pub *drvr = msgbuf->drvr; struct msgbuf_tx_flowring_create_req *create; struct brcmf_commonring *commonring; void *ret_ptr; @@ -595,7 +596,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf, &msgbuf->flowring_dma_handle[flowid], GFP_KERNEL); if (!dma_buf) { - brcmf_err("dma_alloc_coherent failed\n"); + bphy_err(drvr, "dma_alloc_coherent failed\n"); brcmf_flowring_delete(msgbuf->flow, flowid); return BRCMF_FLOWRING_INVALID_ID; } @@ -608,7 +609,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf, brcmf_commonring_lock(commonring); ret_ptr = brcmf_commonring_reserve_for_write(commonring); if (!ret_ptr) { - brcmf_err("Failed to reserve space in commonring\n"); + bphy_err(drvr, "Failed to reserve space in commonring\n"); brcmf_commonring_unlock(commonring); brcmf_msgbuf_remove_flowring(msgbuf, flowid); return BRCMF_FLOWRING_INVALID_ID; @@ -635,7 +636,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf, err = brcmf_commonring_write_complete(commonring); brcmf_commonring_unlock(commonring); if (err) { - brcmf_err("Failed to write commonring\n"); + bphy_err(drvr, "Failed to write commonring\n"); brcmf_msgbuf_remove_flowring(msgbuf, flowid); return BRCMF_FLOWRING_INVALID_ID; } @@ -694,6 +695,7 @@ static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx, static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid) { struct brcmf_flowring *flow = msgbuf->flow; + struct brcmf_pub *drvr = msgbuf->drvr; struct brcmf_commonring *commonring; void *ret_ptr; u32 count; @@ -713,8 +715,8 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid) while (brcmf_flowring_qlen(flow, flowid)) { skb = brcmf_flowring_dequeue(flow, flowid); if (skb == NULL) { - brcmf_err("No SKB, but qlen %d\n", - brcmf_flowring_qlen(flow, flowid)); + bphy_err(drvr, "No SKB, but qlen %d\n", + brcmf_flowring_qlen(flow, flowid)); break; } skb_orphan(skb); @@ -722,7 +724,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid) msgbuf->tx_pktids, skb, ETH_HLEN, &physaddr, &pktid)) { brcmf_flowring_reinsert(flow, flowid, skb); - brcmf_err("No PKTID available !!\n"); + bphy_err(drvr, "No PKTID available !!\n"); break; } ret_ptr = brcmf_commonring_reserve_for_write(commonring); @@ -893,6 +895,7 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count) { + struct brcmf_pub *drvr = msgbuf->drvr; struct brcmf_commonring *commonring; void *ret_ptr; struct sk_buff *skb; @@ -920,7 +923,7 @@ static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count) skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE); if (skb == NULL) { - brcmf_err("Failed to alloc SKB\n"); + bphy_err(drvr, "Failed to alloc SKB\n"); brcmf_commonring_write_cancel(commonring, alloced - i); break; } @@ -930,7 +933,7 @@ static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count) msgbuf->rx_pktids, skb, 0, &physaddr, &pktid)) { dev_kfree_skb_any(skb); - brcmf_err("No PKTID available !!\n"); + bphy_err(drvr, "No PKTID available !!\n"); brcmf_commonring_write_cancel(commonring, alloced - i); break; } @@ -1000,6 +1003,7 @@ static u32 brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf, u32 count) { + struct brcmf_pub *drvr = msgbuf->drvr; struct brcmf_commonring *commonring; void *ret_ptr; struct sk_buff *skb; @@ -1017,7 +1021,7 @@ brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf, count, &alloced); if (!ret_ptr) { - brcmf_err("Failed to reserve space in commonring\n"); + bphy_err(drvr, "Failed to reserve space in commonring\n"); brcmf_commonring_unlock(commonring); return 0; } @@ -1029,7 +1033,7 @@ brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf, skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE); if (skb == NULL) { - brcmf_err("Failed to alloc SKB\n"); + bphy_err(drvr, "Failed to alloc SKB\n"); brcmf_commonring_write_cancel(commonring, alloced - i); break; } @@ -1039,7 +1043,7 @@ brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf, msgbuf->rx_pktids, skb, 0, &physaddr, &pktid)) { dev_kfree_skb_any(skb); - brcmf_err("No PKTID available !!\n"); + bphy_err(drvr, "No PKTID available !!\n"); brcmf_commonring_write_cancel(commonring, alloced - i); break; } @@ -1091,6 +1095,7 @@ static void brcmf_msgbuf_rxbuf_event_post(struct brcmf_msgbuf *msgbuf) static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) { + struct brcmf_pub *drvr = msgbuf->drvr; struct msgbuf_rx_event *event; u32 idx; u16 buflen; @@ -1117,8 +1122,8 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) ifp = brcmf_get_ifp(msgbuf->drvr, event->msg.ifidx); if (!ifp || !ifp->ndev) { - brcmf_err("Received pkt for invalid ifidx %d\n", - event->msg.ifidx); + bphy_err(drvr, "Received pkt for invalid ifidx %d\n", + event->msg.ifidx); goto exit; } @@ -1134,6 +1139,7 @@ exit: static void brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) { + struct brcmf_pub *drvr = msgbuf->drvr; struct msgbuf_rx_complete *rx_complete; struct sk_buff *skb; u16 data_offset; @@ -1167,7 +1173,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) ifp = msgbuf->drvr->mon_if; if (!ifp) { - brcmf_err("Received unexpected monitor pkt\n"); + bphy_err(drvr, "Received unexpected monitor pkt\n"); brcmu_pkt_buf_free_skb(skb); return; } @@ -1178,8 +1184,8 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx); if (!ifp || !ifp->ndev) { - brcmf_err("Received pkt for invalid ifidx %d\n", - rx_complete->msg.ifidx); + bphy_err(drvr, "Received pkt for invalid ifidx %d\n", + rx_complete->msg.ifidx); brcmu_pkt_buf_free_skb(skb); return; } @@ -1192,13 +1198,15 @@ static void brcmf_msgbuf_process_ring_status(struct brcmf_msgbuf *msgbuf, void *buf) { struct msgbuf_ring_status *ring_status = buf; + struct brcmf_pub *drvr = msgbuf->drvr; int err; err = le16_to_cpu(ring_status->compl_hdr.status); if (err) { int ring = le16_to_cpu(ring_status->compl_hdr.flow_ring_id); - brcmf_err("Firmware reported ring %d error: %d\n", ring, err); + bphy_err(drvr, "Firmware reported ring %d error: %d\n", ring, + err); } } @@ -1206,6 +1214,7 @@ static void brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf, void *buf) { + struct brcmf_pub *drvr = msgbuf->drvr; struct msgbuf_flowring_create_resp *flowring_create_resp; u16 status; u16 flowid; @@ -1217,7 +1226,7 @@ brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf, status = le16_to_cpu(flowring_create_resp->compl_hdr.status); if (status) { - brcmf_err("Flowring creation failed, code %d\n", status); + bphy_err(drvr, "Flowring creation failed, code %d\n", status); brcmf_msgbuf_remove_flowring(msgbuf, flowid); return; } @@ -1234,6 +1243,7 @@ static void brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf, void *buf) { + struct brcmf_pub *drvr = msgbuf->drvr; struct msgbuf_flowring_delete_resp *flowring_delete_resp; u16 status; u16 flowid; @@ -1245,7 +1255,7 @@ brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf, status = le16_to_cpu(flowring_delete_resp->compl_hdr.status); if (status) { - brcmf_err("Flowring deletion failed, code %d\n", status); + bphy_err(drvr, "Flowring deletion failed, code %d\n", status); brcmf_flowring_delete(msgbuf->flow, flowid); return; } @@ -1258,6 +1268,7 @@ brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf, static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf) { + struct brcmf_pub *drvr = msgbuf->drvr; struct msgbuf_common_hdr *msg; msg = (struct msgbuf_common_hdr *)buf; @@ -1294,7 +1305,7 @@ static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf) brcmf_msgbuf_process_rx_complete(msgbuf, buf); break; default: - brcmf_err("Unsupported msgtype %d\n", msg->msgtype); + bphy_err(drvr, "Unsupported msgtype %d\n", msg->msgtype); break; } } @@ -1377,7 +1388,7 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid) brcmf_commonring_lock(commonring); ret_ptr = brcmf_commonring_reserve_for_write(commonring); if (!ret_ptr) { - brcmf_err("FW unaware, flowring will be removed !!\n"); + bphy_err(drvr, "FW unaware, flowring will be removed !!\n"); brcmf_commonring_unlock(commonring); brcmf_msgbuf_remove_flowring(msgbuf, flowid); return; @@ -1401,7 +1412,7 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid) err = brcmf_commonring_write_complete(commonring); brcmf_commonring_unlock(commonring); if (err) { - brcmf_err("Failed to submit RING_DELETE, flowring will be removed\n"); + bphy_err(drvr, "Failed to submit RING_DELETE, flowring will be removed\n"); brcmf_msgbuf_remove_flowring(msgbuf, flowid); } } @@ -1476,8 +1487,8 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) if_msgbuf = drvr->bus_if->msgbuf; if (if_msgbuf->max_flowrings >= BRCMF_FLOWRING_HASHSIZE) { - brcmf_err("driver not configured for this many flowrings %d\n", - if_msgbuf->max_flowrings); + bphy_err(drvr, "driver not configured for this many flowrings %d\n", + if_msgbuf->max_flowrings); if_msgbuf->max_flowrings = BRCMF_FLOWRING_HASHSIZE - 1; } @@ -1487,7 +1498,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) msgbuf->txflow_wq = create_singlethread_workqueue("msgbuf_txflow"); if (msgbuf->txflow_wq == NULL) { - brcmf_err("workqueue creation failed\n"); + bphy_err(drvr, "workqueue creation failed\n"); goto fail; } INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 456a1bf008b3..73a0e550f2b2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -434,6 +434,7 @@ static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len) */ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) { + struct brcmf_pub *drvr = ifp->drvr; s32 ret = 0; brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); @@ -450,7 +451,7 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) ret = brcmf_fil_iovar_data_set(ifp, "p2p_da_override", p2p_mac, ETH_ALEN); if (ret) - brcmf_err("failed to update device address ret %d\n", ret); + bphy_err(drvr, "failed to update device address ret %d\n", ret); return ret; } @@ -570,13 +571,14 @@ static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p) */ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p) { + struct brcmf_pub *drvr = p2p->cfg->pub; struct brcmf_cfg80211_vif *vif; s32 ret = 0; brcmf_dbg(TRACE, "enter\n"); vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; if (!vif) { - brcmf_err("P2P config device not available\n"); + bphy_err(drvr, "P2P config device not available\n"); ret = -EPERM; goto exit; } @@ -590,13 +592,13 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p) vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; ret = brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 1); if (ret < 0) { - brcmf_err("set p2p_disc error\n"); + bphy_err(drvr, "set p2p_disc error\n"); goto exit; } vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; ret = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0); if (ret < 0) { - brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n"); + bphy_err(drvr, "unable to set WL_P2P_DISC_ST_SCAN\n"); goto exit; } @@ -608,7 +610,7 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p) */ ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED); if (ret < 0) { - brcmf_err("wsec error %d\n", ret); + bphy_err(drvr, "wsec error %d\n", ret); goto exit; } @@ -630,6 +632,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans, u16 chanspecs[], s32 search_state, enum p2p_bss_type bss_type) { + struct brcmf_pub *drvr = p2p->cfg->pub; s32 ret = 0; s32 memsize = offsetof(struct brcmf_p2p_scan_le, eparams.params_le.channel_list); @@ -648,7 +651,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans, vif = p2p->bss_idx[bss_type].vif; if (vif == NULL) { - brcmf_err("no vif for bss type %d\n", bss_type); + bphy_err(drvr, "no vif for bss type %d\n", bss_type); ret = -EINVAL; goto exit; } @@ -676,7 +679,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans, BRCMF_P2P_WILDCARD_SSID_LEN); break; default: - brcmf_err(" invalid search state %d\n", search_state); + bphy_err(drvr, " invalid search state %d\n", search_state); ret = -EINVAL; goto exit; } @@ -760,6 +763,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, struct cfg80211_scan_request *request) { struct brcmf_p2p_info *p2p = &cfg->p2p; + struct brcmf_pub *drvr = cfg->pub; s32 err = 0; s32 search_state = WL_P2P_DISC_ST_SCAN; struct brcmf_cfg80211_vif *vif; @@ -822,7 +826,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, } exit: if (err) - brcmf_err("error (%d)\n", err); + bphy_err(drvr, "error (%d)\n", err); return err; } @@ -917,19 +921,20 @@ int brcmf_p2p_scan_prep(struct wiphy *wiphy, static s32 brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration) { + struct brcmf_pub *drvr = p2p->cfg->pub; struct brcmf_cfg80211_vif *vif; struct brcmu_chan ch; s32 err = 0; vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; if (!vif) { - brcmf_err("Discovery is not set, so we have nothing to do\n"); + bphy_err(drvr, "Discovery is not set, so we have nothing to do\n"); err = -EPERM; goto exit; } if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status)) { - brcmf_err("Previous LISTEN is not completed yet\n"); + bphy_err(drvr, "Previous LISTEN is not completed yet\n"); /* WAR: prevent cookie mismatch in wpa_supplicant return OK */ goto exit; } @@ -1046,6 +1051,7 @@ void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp) */ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel) { + struct brcmf_pub *drvr = p2p->cfg->pub; s32 err; u32 channel_cnt; u16 *default_chan_list; @@ -1061,7 +1067,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel) default_chan_list = kcalloc(channel_cnt, sizeof(*default_chan_list), GFP_KERNEL); if (default_chan_list == NULL) { - brcmf_err("channel list allocation failed\n"); + bphy_err(drvr, "channel list allocation failed\n"); err = -ENOMEM; goto exit; } @@ -1103,6 +1109,7 @@ static void brcmf_p2p_afx_handler(struct work_struct *work) struct brcmf_p2p_info *p2p = container_of(afx_hdl, struct brcmf_p2p_info, afx_hdl); + struct brcmf_pub *drvr = p2p->cfg->pub; s32 err; if (!afx_hdl->is_active) @@ -1116,7 +1123,7 @@ static void brcmf_p2p_afx_handler(struct work_struct *work) err = brcmf_p2p_act_frm_search(p2p, afx_hdl->peer_listen_chan); if (err) { - brcmf_err("ERROR occurred! value is (%d)\n", err); + bphy_err(drvr, "ERROR occurred! value is (%d)\n", err); if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status)) complete(&afx_hdl->act_frm_scan); @@ -1338,7 +1345,8 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, const struct brcmf_event_msg *e, void *data) { - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_cfg80211_info *cfg = drvr->config; struct brcmf_p2p_info *p2p = &cfg->p2p; struct afx_hdl *afx_hdl = &p2p->afx_hdl; struct wireless_dev *wdev; @@ -1409,7 +1417,7 @@ int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, mgmt_frame = kzalloc(offsetof(struct ieee80211_mgmt, u) + mgmt_frame_len, GFP_KERNEL); if (!mgmt_frame) { - brcmf_err("No memory available for action frame\n"); + bphy_err(drvr, "No memory available for action frame\n"); return -ENOMEM; } memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN); @@ -1492,6 +1500,7 @@ int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp, static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p, struct brcmf_fil_af_params_le *af_params) { + struct brcmf_pub *drvr = p2p->cfg->pub; struct brcmf_cfg80211_vif *vif; s32 err = 0; s32 timeout = 0; @@ -1506,7 +1515,7 @@ static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p, err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe", af_params, sizeof(*af_params)); if (err) { - brcmf_err(" sending action frame has failed\n"); + bphy_err(drvr, " sending action frame has failed\n"); goto exit; } @@ -1556,6 +1565,7 @@ static s32 brcmf_p2p_pub_af_tx(struct brcmf_cfg80211_info *cfg, struct brcmf_config_af_params *config_af_params) { struct brcmf_p2p_info *p2p = &cfg->p2p; + struct brcmf_pub *drvr = cfg->pub; struct brcmf_fil_action_frame_le *action_frame; struct brcmf_p2p_pub_act_frame *act_frm; s32 err = 0; @@ -1634,8 +1644,8 @@ static s32 brcmf_p2p_pub_af_tx(struct brcmf_cfg80211_info *cfg, config_af_params->extra_listen = false; break; default: - brcmf_err("Unknown p2p pub act frame subtype: %d\n", - act_frm->subtype); + bphy_err(drvr, "Unknown p2p pub act frame subtype: %d\n", + act_frm->subtype); err = -EINVAL; } return err; @@ -1657,6 +1667,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, struct brcmf_fil_action_frame_le *action_frame; struct brcmf_config_af_params config_af_params; struct afx_hdl *afx_hdl = &p2p->afx_hdl; + struct brcmf_pub *drvr = cfg->pub; u16 action_frame_len; bool ack = false; u8 category; @@ -1692,7 +1703,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, if (brcmf_p2p_pub_af_tx(cfg, af_params, &config_af_params)) { /* Just send unknown subtype frame with */ /* default parameters. */ - brcmf_err("P2P Public action frame, unknown subtype.\n"); + bphy_err(drvr, "P2P Public action frame, unknown subtype.\n"); } } else if (brcmf_p2p_is_gas_action(action_frame->data, action_frame_len)) { @@ -1714,7 +1725,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, af_params->dwell_time = cpu_to_le32(P2P_AF_MIN_DWELL_TIME); } else { - brcmf_err("Unknown action type: %d\n", action); + bphy_err(drvr, "Unknown action type: %d\n", action); goto exit; } } else if (brcmf_p2p_is_p2p_action(action_frame->data, @@ -1722,8 +1733,8 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, /* do not configure anything. it will be */ /* sent with a default configuration */ } else { - brcmf_err("Unknown Frame: category 0x%x, action 0x%x\n", - category, action); + bphy_err(drvr, "Unknown Frame: category 0x%x, action 0x%x\n", + category, action); return false; } @@ -1761,7 +1772,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, if (brcmf_p2p_af_searching_channel(p2p) == P2P_INVALID_CHANNEL) { - brcmf_err("Couldn't find peer's channel.\n"); + bphy_err(drvr, "Couldn't find peer's channel.\n"); goto exit; } @@ -1783,7 +1794,8 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, tx_retry++; } if (ack == false) { - brcmf_err("Failed to send Action Frame(retry %d)\n", tx_retry); + bphy_err(drvr, "Failed to send Action Frame(retry %d)\n", + tx_retry); clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); } @@ -1965,6 +1977,7 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, enum brcmf_fil_p2p_if_types if_type) { struct brcmf_p2p_info *p2p = &cfg->p2p; + struct brcmf_pub *drvr = cfg->pub; struct brcmf_cfg80211_vif *vif; struct brcmf_fil_p2p_if_le if_request; s32 err; @@ -1974,13 +1987,13 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; if (!vif) { - brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); + bphy_err(drvr, "vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); return -EPERM; } brcmf_notify_escan_complete(cfg, vif->ifp, true, true); vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; if (!vif) { - brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); + bphy_err(drvr, "vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); return -EPERM; } brcmf_set_mpc(vif->ifp, 0); @@ -1998,7 +2011,7 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, err = brcmf_fil_iovar_data_set(vif->ifp, "p2p_ifupd", &if_request, sizeof(if_request)); if (err) { - brcmf_err("p2p_ifupd FAILED, err=%d\n", err); + bphy_err(drvr, "p2p_ifupd FAILED, err=%d\n", err); brcmf_cfg80211_arm_vif_event(cfg, NULL); return err; } @@ -2006,7 +2019,7 @@ int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, BRCMF_VIF_EVENT_TIMEOUT); brcmf_cfg80211_arm_vif_event(cfg, NULL); if (!err) { - brcmf_err("No BRCMF_E_IF_CHANGE event received\n"); + bphy_err(drvr, "No BRCMF_E_IF_CHANGE event received\n"); return -EIO; } @@ -2069,6 +2082,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, struct wiphy *wiphy, u8 *addr) { + struct brcmf_pub *drvr = p2p->cfg->pub; struct brcmf_cfg80211_vif *p2p_vif; struct brcmf_if *p2p_ifp; struct brcmf_if *pri_ifp; @@ -2080,7 +2094,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE); if (IS_ERR(p2p_vif)) { - brcmf_err("could not create discovery vif\n"); + bphy_err(drvr, "could not create discovery vif\n"); return (struct wireless_dev *)p2p_vif; } @@ -2088,7 +2102,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, /* firmware requires unique mac address for p2pdev interface */ if (addr && ether_addr_equal(addr, pri_ifp->mac_addr)) { - brcmf_err("discovery vif must be different from primary interface\n"); + bphy_err(drvr, "discovery vif must be different from primary interface\n"); return ERR_PTR(-EINVAL); } @@ -2101,7 +2115,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, /* Initialize P2P Discovery in the firmware */ err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); if (err < 0) { - brcmf_err("set p2p_disc error\n"); + bphy_err(drvr, "set p2p_disc error\n"); brcmf_fweh_p2pdev_setup(pri_ifp, false); brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); goto fail; @@ -2113,7 +2127,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); brcmf_fweh_p2pdev_setup(pri_ifp, false); if (!err) { - brcmf_err("timeout occurred\n"); + bphy_err(drvr, "timeout occurred\n"); err = -EIO; goto fail; } @@ -2127,7 +2141,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, /* verify bsscfg index for P2P discovery */ err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bsscfgidx); if (err < 0) { - brcmf_err("retrieving discover bsscfg index failed\n"); + bphy_err(drvr, "retrieving discover bsscfg index failed\n"); goto fail; } @@ -2161,6 +2175,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); + struct brcmf_pub *drvr = cfg->pub; struct brcmf_cfg80211_vif *vif; enum brcmf_fil_p2p_if_types iftype; int err; @@ -2201,7 +2216,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, BRCMF_VIF_EVENT_TIMEOUT); brcmf_cfg80211_arm_vif_event(cfg, NULL); if (!err) { - brcmf_err("timeout occurred\n"); + bphy_err(drvr, "timeout occurred\n"); err = -EIO; goto fail; } @@ -2209,7 +2224,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, /* interface created in firmware */ ifp = vif->ifp; if (!ifp) { - brcmf_err("no if pointer provided\n"); + bphy_err(drvr, "no if pointer provided\n"); err = -ENOENT; goto fail; } @@ -2218,7 +2233,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, ifp->ndev->name_assign_type = name_assign_type; err = brcmf_net_attach(ifp, true); if (err) { - brcmf_err("Registering netdevice failed\n"); + bphy_err(drvr, "Registering netdevice failed\n"); free_netdev(ifp->ndev); goto fail; } @@ -2373,6 +2388,7 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) */ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced) { + struct brcmf_pub *drvr = cfg->pub; struct brcmf_p2p_info *p2p; struct brcmf_if *pri_ifp; s32 err = 0; @@ -2387,7 +2403,7 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced) if (p2pdev_forced) { err_ptr = brcmf_p2p_create_p2pdev(p2p, NULL, NULL); if (IS_ERR(err_ptr)) { - brcmf_err("P2P device creation failed.\n"); + bphy_err(drvr, "P2P device creation failed.\n"); err = PTR_ERR(err_ptr); } } else { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c index 37b403877228..0fb97f7dd5a2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c @@ -109,6 +109,7 @@ static int brcmf_pno_channel_config(struct brcmf_if *ifp, static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, u32 mscan, u32 bestn) { + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_pno_param_le pfn_param; u16 flags; u32 pfnmem; @@ -132,13 +133,13 @@ static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, /* set bestn in firmware */ err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem); if (err < 0) { - brcmf_err("failed to set pfnmem\n"); + bphy_err(drvr, "failed to set pfnmem\n"); goto exit; } /* get max mscan which the firmware supports */ err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem); if (err < 0) { - brcmf_err("failed to get pfnmem\n"); + bphy_err(drvr, "failed to get pfnmem\n"); goto exit; } mscan = min_t(u32, mscan, pfnmem); @@ -152,7 +153,7 @@ static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, sizeof(pfn_param)); if (err) - brcmf_err("pfn_set failed, err=%d\n", err); + bphy_err(drvr, "pfn_set failed, err=%d\n", err); exit: return err; @@ -160,6 +161,7 @@ exit: static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi) { + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_pno_macaddr_le pfn_mac; u8 *mac_addr = NULL; u8 *mac_mask = NULL; @@ -194,7 +196,7 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi) err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac, sizeof(pfn_mac)); if (err) - brcmf_err("pfn_macaddr failed, err=%d\n", err); + bphy_err(drvr, "pfn_macaddr failed, err=%d\n", err); return err; } @@ -202,6 +204,7 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi) static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, bool active) { + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_pno_net_param_le pfn; int err; @@ -218,12 +221,13 @@ static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, brcmf_dbg(SCAN, "adding ssid=%.32s (active=%d)\n", ssid->ssid, active); err = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn)); if (err < 0) - brcmf_err("adding failed: err=%d\n", err); + bphy_err(drvr, "adding failed: err=%d\n", err); return err; } static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid) { + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_pno_bssid_le bssid_cfg; int err; @@ -234,7 +238,7 @@ static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid) err = brcmf_fil_iovar_data_set(ifp, "pfn_add_bssid", &bssid_cfg, sizeof(bssid_cfg)); if (err < 0) - brcmf_err("adding failed: err=%d\n", err); + bphy_err(drvr, "adding failed: err=%d\n", err); return err; } @@ -258,6 +262,7 @@ static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid, static int brcmf_pno_clean(struct brcmf_if *ifp) { + struct brcmf_pub *drvr = ifp->drvr; int ret; /* Disable pfn */ @@ -267,7 +272,7 @@ static int brcmf_pno_clean(struct brcmf_if *ifp) ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); } if (ret < 0) - brcmf_err("failed code %d\n", ret); + bphy_err(drvr, "failed code %d\n", ret); return ret; } @@ -392,6 +397,7 @@ static int brcmf_pno_config_networks(struct brcmf_if *ifp, static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp) { + struct brcmf_pub *drvr = ifp->drvr; struct brcmf_pno_info *pi; struct brcmf_gscan_config *gscan_cfg; struct brcmf_gscan_bucket_config *buckets; @@ -416,7 +422,7 @@ static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp) /* clean up everything */ err = brcmf_pno_clean(ifp); if (err < 0) { - brcmf_err("failed error=%d\n", err); + bphy_err(drvr, "failed error=%d\n", err); goto free_gscan; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c index c5ff551ec659..024c643052bc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c @@ -47,8 +47,8 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) if (brcmf_proto_msgbuf_attach(drvr)) goto fail; } else { - brcmf_err("Unsupported proto type %d\n", - drvr->bus_if->proto_type); + bphy_err(drvr, "Unsupported proto type %d\n", + drvr->bus_if->proto_type); goto fail; } if (!proto->tx_queue_data || (proto->hdrpull == NULL) || @@ -56,7 +56,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) (proto->configure_addr_mode == NULL) || (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL) || (proto->debugfs_create == NULL)) { - brcmf_err("Not all proto handlers have been installed\n"); + bphy_err(drvr, "Not all proto handlers have been installed\n"); goto fail; } return 0; -- cgit v1.2.3 From 0421dd4167ec7d74daf891aae9e64801a3adcd4f Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 20 Feb 2019 09:27:27 +0000 Subject: rtlwifi: rtl8192ce: fix typo, "PairwiseENcAlgorithm" -> "PairwiseEncAlgorithm" There is an uppercase 'N' that should be a lowercase 'n', fix this. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index 5cf5a85d1376..d8f496e2d68b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c @@ -876,7 +876,7 @@ void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw) u8 sec_reg_value; RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PairwiseENcAlgorithm = %d GroupEncAlgorithm = %d\n", + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", rtlpriv->sec.pairwise_enc_algorithm, rtlpriv->sec.group_enc_algorithm); -- cgit v1.2.3 From e0a8ef4d7b4315bc4c1641fb3f3a7dfdfa6627b8 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 20 Feb 2019 11:30:47 +0100 Subject: brcmfmac: add basic validation of shared RAM address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While experimenting with firmware loading I ended up in a state of firmware reporting shared RAM address 0x04000001. It was causing: [ 94.448015] Unable to handle kernel paging request at virtual address cd680001 due to reading out of the mapped memory. This patch adds some basic validation to avoid kernel crashes due to the unexpected firmware behavior. Signed-off-by: Rafał Miłecki Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 257f919c52cc..58a6bc379358 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1560,6 +1560,12 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, brcmf_err(bus, "FW failed to initialize\n"); return -ENODEV; } + if (sharedram_addr < devinfo->ci->rambase || + sharedram_addr >= devinfo->ci->rambase + devinfo->ci->ramsize) { + brcmf_err(bus, "Invalid shared RAM address 0x%08x\n", + sharedram_addr); + return -ENODEV; + } brcmf_dbg(PCIE, "Shared RAM addr: 0x%08x\n", sharedram_addr); return (brcmf_pcie_init_share_ram_info(devinfo, sharedram_addr)); -- cgit v1.2.3 From be9d0d3fe1392cefd710a96101250d76d42f632c Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 20 Feb 2019 11:58:38 +0100 Subject: libertas_tf: move hardware callbacks to a separate structure We'll need to talk to the firmware to get a hardware address before device is registered with ieee80211 subsystem at the end of lbtf_add_card(). Hooking the callbacks after that is too late. Signed-off-by: Lubomir Rintel Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/cmd.c | 2 +- drivers/net/wireless/marvell/libertas_tf/if_usb.c | 12 +++++++----- drivers/net/wireless/marvell/libertas_tf/libertas_tf.h | 17 +++++++++++------ drivers/net/wireless/marvell/libertas_tf/main.c | 10 ++++++---- 4 files changed, 25 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/cmd.c b/drivers/net/wireless/marvell/libertas_tf/cmd.c index 64b147dd2432..130f578daafd 100644 --- a/drivers/net/wireless/marvell/libertas_tf/cmd.c +++ b/drivers/net/wireless/marvell/libertas_tf/cmd.c @@ -256,7 +256,7 @@ static void lbtf_submit_command(struct lbtf_private *priv, command, le16_to_cpu(cmd->seqnum), cmdsize); lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); - ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); + ret = priv->ops->hw_host_to_card(priv, MVMS_CMD, (u8 *)cmd, cmdsize); spin_unlock_irqrestore(&priv->driver_lock, flags); if (ret) { diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c index 6ede6168bd85..7a5a1a85dcf7 100644 --- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c +++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c @@ -131,6 +131,12 @@ static void if_usb_fw_timeo(struct timer_list *t) lbtf_deb_leave(LBTF_DEB_USB); } +static const struct lbtf_ops if_usb_ops = { + .hw_host_to_card = if_usb_host_to_card, + .hw_prog_firmware = if_usb_prog_firmware, + .hw_reset_device = if_usb_reset_device, +}; + /** * if_usb_probe - sets the configuration values * @@ -216,15 +222,11 @@ static int if_usb_probe(struct usb_interface *intf, goto dealloc; } - priv = lbtf_add_card(cardp, &udev->dev); + priv = lbtf_add_card(cardp, &udev->dev, &if_usb_ops); if (!priv) goto dealloc; cardp->priv = priv; - - priv->hw_host_to_card = if_usb_host_to_card; - priv->hw_prog_firmware = if_usb_prog_firmware; - priv->hw_reset_device = if_usb_reset_device; cardp->boot2_version = udev->descriptor.bcdDevice; usb_get_dev(udev); diff --git a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h index ad77b92d0b41..11d5ff68bc5e 100644 --- a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h +++ b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h @@ -173,10 +173,19 @@ struct channel_range { struct if_usb_card; +struct lbtf_ops { + /** Hardware access */ + int (*hw_host_to_card)(struct lbtf_private *priv, u8 type, + u8 *payload, u16 nb); + int (*hw_prog_firmware)(struct if_usb_card *cardp); + int (*hw_reset_device)(struct if_usb_card *cardp); +}; + /** Private structure for the MV device */ struct lbtf_private { void *card; struct ieee80211_hw *hw; + const struct lbtf_ops *ops; /* Command response buffer */ u8 cmd_resp_buff[LBS_UPLD_SIZE]; @@ -188,11 +197,6 @@ struct lbtf_private { struct work_struct cmd_work; struct work_struct tx_work; - /** Hardware access */ - int (*hw_host_to_card) (struct lbtf_private *priv, u8 type, u8 *payload, u16 nb); - int (*hw_prog_firmware) (struct if_usb_card *cardp); - int (*hw_reset_device) (struct if_usb_card *cardp); - /** Wlan adapter data structure*/ /** STATUS variables */ @@ -486,7 +490,8 @@ void lbtf_cmd_response_rx(struct lbtf_private *priv); /* main.c */ struct chan_freq_power *lbtf_get_region_cfp_table(u8 region, int *cfp_no); -struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev); +struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev, + const struct lbtf_ops *ops); int lbtf_remove_card(struct lbtf_private *priv); int lbtf_start_card(struct lbtf_private *priv); int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb); diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index f048b57043c6..a9c04ca75ccc 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c @@ -281,7 +281,7 @@ static void lbtf_tx_work(struct work_struct *work) BUG_ON(priv->tx_skb); spin_lock_irq(&priv->driver_lock); priv->tx_skb = skb; - err = priv->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len); + err = priv->ops->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len); spin_unlock_irq(&priv->driver_lock); if (err) { dev_kfree_skb_any(skb); @@ -301,7 +301,7 @@ static int lbtf_op_start(struct ieee80211_hw *hw) if (!priv->fw_ready) /* Upload firmware */ - if (priv->hw_prog_firmware(card)) + if (priv->ops->hw_prog_firmware(card)) goto err_prog_firmware; /* poke the firmware */ @@ -322,7 +322,7 @@ static int lbtf_op_start(struct ieee80211_hw *hw) return 0; err_prog_firmware: - priv->hw_reset_device(card); + priv->ops->hw_reset_device(card); lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret); return ret; } @@ -603,7 +603,8 @@ EXPORT_SYMBOL_GPL(lbtf_rx); * * Returns: pointer to struct lbtf_priv. */ -struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) +struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev, + const struct lbtf_ops *ops) { struct ieee80211_hw *hw; struct lbtf_private *priv = NULL; @@ -620,6 +621,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) priv->hw = hw; priv->card = card; + priv->ops = ops; priv->tx_skb = NULL; hw->queues = 1; -- cgit v1.2.3 From baa0280f08c71a3ce699a5213f16f45f6e0e592b Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 20 Feb 2019 11:58:39 +0100 Subject: libertas_tf: don't defer firmware loading until start() In order to be able to get a MAC address before we register the device with ieee80211 we'll need to load the firmware way earlier. There seems to be one problem with this: the device seems to start with radio enabled and starts sending in frames right after the firmware load finishes. Disable the radio as soon as possible. Signed-off-by: Lubomir Rintel Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/if_usb.c | 24 ++++++------- .../net/wireless/marvell/libertas_tf/libertas_tf.h | 5 ++- drivers/net/wireless/marvell/libertas_tf/main.c | 41 +++++++++++++--------- 3 files changed, 38 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c index 7a5a1a85dcf7..a4b9ede70705 100644 --- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c +++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c @@ -42,14 +42,14 @@ MODULE_DEVICE_TABLE(usb, if_usb_table); static void if_usb_receive(struct urb *urb); static void if_usb_receive_fwload(struct urb *urb); -static int if_usb_prog_firmware(struct if_usb_card *cardp); +static int if_usb_prog_firmware(struct lbtf_private *priv); static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type, uint8_t *payload, uint16_t nb); static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb, u8 data); static void if_usb_free(struct if_usb_card *cardp); static int if_usb_submit_rx_urb(struct if_usb_card *cardp); -static int if_usb_reset_device(struct if_usb_card *cardp); +static int if_usb_reset_device(struct lbtf_private *priv); /** * if_usb_wrike_bulk_callback - call back to handle URB status @@ -222,13 +222,11 @@ static int if_usb_probe(struct usb_interface *intf, goto dealloc; } + cardp->boot2_version = udev->descriptor.bcdDevice; priv = lbtf_add_card(cardp, &udev->dev, &if_usb_ops); if (!priv) goto dealloc; - cardp->priv = priv; - cardp->boot2_version = udev->descriptor.bcdDevice; - usb_get_dev(udev); usb_set_intfdata(intf, cardp); @@ -253,7 +251,7 @@ static void if_usb_disconnect(struct usb_interface *intf) lbtf_deb_enter(LBTF_DEB_MAIN); - if_usb_reset_device(cardp); + if_usb_reset_device(priv); if (priv) lbtf_remove_card(priv); @@ -336,8 +334,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) return 0; } -static int if_usb_reset_device(struct if_usb_card *cardp) +static int if_usb_reset_device(struct lbtf_private *priv) { + struct if_usb_card *cardp = priv->card; struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4; int ret; @@ -808,14 +807,17 @@ static int check_fwfile_format(const u8 *data, u32 totlen) } -static int if_usb_prog_firmware(struct if_usb_card *cardp) +static int if_usb_prog_firmware(struct lbtf_private *priv) { + struct if_usb_card *cardp = priv->card; int i = 0; static int reset_count = 10; int ret = 0; lbtf_deb_enter(LBTF_DEB_USB); + cardp->priv = priv; + kernel_param_lock(THIS_MODULE); ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); if (ret < 0) { @@ -851,7 +853,7 @@ restart: if (cardp->bootcmdresp <= 0) { if (--reset_count >= 0) { - if_usb_reset_device(cardp); + if_usb_reset_device(priv); goto restart; } return -1; @@ -880,7 +882,7 @@ restart: if (!cardp->fwdnldover) { pr_info("failed to load fw, resetting device!\n"); if (--reset_count >= 0) { - if_usb_reset_device(cardp); + if_usb_reset_device(priv); goto restart; } @@ -889,8 +891,6 @@ restart: goto release_fw; } - cardp->priv->fw_ready = 1; - release_fw: release_firmware(cardp->fw); cardp->fw = NULL; diff --git a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h index 11d5ff68bc5e..3ed1fbe28798 100644 --- a/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h +++ b/drivers/net/wireless/marvell/libertas_tf/libertas_tf.h @@ -177,8 +177,8 @@ struct lbtf_ops { /** Hardware access */ int (*hw_host_to_card)(struct lbtf_private *priv, u8 type, u8 *payload, u16 nb); - int (*hw_prog_firmware)(struct if_usb_card *cardp); - int (*hw_reset_device)(struct if_usb_card *cardp); + int (*hw_prog_firmware)(struct lbtf_private *priv); + int (*hw_reset_device)(struct lbtf_private *priv); }; /** Private structure for the MV device */ @@ -254,7 +254,6 @@ struct lbtf_private { struct ieee80211_supported_band band; struct lbtf_offset_value offsetvalue; - u8 fw_ready; u8 surpriseremoved; struct sk_buff_head bc_ps_buf; diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index a9c04ca75ccc..d8bf0a4071da 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c @@ -118,11 +118,6 @@ static void lbtf_cmd_work(struct work_struct *work) priv->cmd_timed_out = 0; spin_unlock_irq(&priv->driver_lock); - if (!priv->fw_ready) { - lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready"); - return; - } - /* Execute the next command */ if (!priv->cur_cmd) lbtf_execute_next_command(priv); @@ -294,36 +289,29 @@ static void lbtf_tx_work(struct work_struct *work) static int lbtf_op_start(struct ieee80211_hw *hw) { struct lbtf_private *priv = hw->priv; - void *card = priv->card; int ret = -1; lbtf_deb_enter(LBTF_DEB_MACOPS); - if (!priv->fw_ready) - /* Upload firmware */ - if (priv->ops->hw_prog_firmware(card)) - goto err_prog_firmware; - /* poke the firmware */ priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; priv->radioon = RADIO_ON; priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; ret = lbtf_setup_firmware(priv); if (ret) - goto err_prog_firmware; + goto err_setup_firmware; if ((priv->fwrelease < LBTF_FW_VER_MIN) || (priv->fwrelease > LBTF_FW_VER_MAX)) { ret = -1; - goto err_prog_firmware; + goto err_setup_firmware; } lbtf_deb_leave(LBTF_DEB_MACOPS); return 0; -err_prog_firmware: - priv->ops->hw_reset_device(card); - lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programming fw; ret=%d", ret); +err_setup_firmware: + lbtf_deb_leave_args(LBTF_DEB_MACOPS, "fw setup error; ret=%d", ret); return ret; } @@ -554,6 +542,11 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) lbtf_deb_enter(LBTF_DEB_RX); + if (priv->radioon != RADIO_ON) { + lbtf_deb_rx("rx before we turned on the radio"); + goto done; + } + prxpd = (struct rxpd *) skb->data; memset(&stats, 0, sizeof(stats)); @@ -591,13 +584,14 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) ieee80211_rx_irqsafe(priv->hw, skb); +done: lbtf_deb_leave(LBTF_DEB_RX); return 0; } EXPORT_SYMBOL_GPL(lbtf_rx); /** - * lbtf_add_card: Add and initialize the card, no fw upload yet. + * lbtf_add_card: Add and initialize the card. * * @card A pointer to card * @@ -623,6 +617,7 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev, priv->card = card; priv->ops = ops; priv->tx_skb = NULL; + priv->radioon = RADIO_OFF; hw->queues = 1; ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); @@ -646,6 +641,18 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev, INIT_WORK(&priv->cmd_work, lbtf_cmd_work); INIT_WORK(&priv->tx_work, lbtf_tx_work); + + if (priv->ops->hw_prog_firmware(priv)) { + lbtf_deb_usbd(dmdev, "Error programming the firmware\n"); + priv->ops->hw_reset_device(priv); + goto err_init_adapter; + } + + /* The firmware seems to start with the radio enabled. Turn it + * off before an actual mac80211 start callback is invoked. + */ + lbtf_set_radio_control(priv); + if (ieee80211_register_hw(hw)) goto err_init_adapter; -- cgit v1.2.3 From 5d04b22b881d2b21569304fd6930509bb232fa0d Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Wed, 20 Feb 2019 11:58:40 +0100 Subject: libertas_tf: get the MAC address before registering the device The start() callback is too late for this: NetworkManager would already have seen the hardware, thinking 00:00:00:00:00:00 is its permanent address. Signed-off-by: Lubomir Rintel Reviewed-by: Steve deRosier Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas_tf/main.c | 57 +++++-------------------- 1 file changed, 11 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c index d8bf0a4071da..5799e9886d83 100644 --- a/drivers/net/wireless/marvell/libertas_tf/main.c +++ b/drivers/net/wireless/marvell/libertas_tf/main.c @@ -125,37 +125,6 @@ static void lbtf_cmd_work(struct work_struct *work) lbtf_deb_leave(LBTF_DEB_CMD); } -/** - * lbtf_setup_firmware: initialize firmware. - * - * @priv A pointer to struct lbtf_private structure - * - * Returns: 0 on success. - */ -static int lbtf_setup_firmware(struct lbtf_private *priv) -{ - int ret = -1; - - lbtf_deb_enter(LBTF_DEB_FW); - /* - * Read priv address from HW - */ - eth_broadcast_addr(priv->current_addr); - ret = lbtf_update_hw_spec(priv); - if (ret) { - ret = -1; - goto done; - } - - lbtf_set_mac_control(priv); - lbtf_set_radio_control(priv); - - ret = 0; -done: - lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret); - return ret; -} - /** * This function handles the timeout of command sending. * It will re-send the same command again. @@ -289,30 +258,17 @@ static void lbtf_tx_work(struct work_struct *work) static int lbtf_op_start(struct ieee80211_hw *hw) { struct lbtf_private *priv = hw->priv; - int ret = -1; lbtf_deb_enter(LBTF_DEB_MACOPS); - /* poke the firmware */ priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; priv->radioon = RADIO_ON; priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; - ret = lbtf_setup_firmware(priv); - if (ret) - goto err_setup_firmware; - - if ((priv->fwrelease < LBTF_FW_VER_MIN) || - (priv->fwrelease > LBTF_FW_VER_MAX)) { - ret = -1; - goto err_setup_firmware; - } + lbtf_set_mac_control(priv); + lbtf_set_radio_control(priv); lbtf_deb_leave(LBTF_DEB_MACOPS); return 0; - -err_setup_firmware: - lbtf_deb_leave_args(LBTF_DEB_MACOPS, "fw setup error; ret=%d", ret); - return ret; } static void lbtf_op_stop(struct ieee80211_hw *hw) @@ -648,6 +604,15 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev, goto err_init_adapter; } + eth_broadcast_addr(priv->current_addr); + if (lbtf_update_hw_spec(priv)) + goto err_init_adapter; + + if (priv->fwrelease < LBTF_FW_VER_MIN || + priv->fwrelease > LBTF_FW_VER_MAX) { + goto err_init_adapter; + } + /* The firmware seems to start with the radio enabled. Turn it * off before an actual mac80211 start callback is invoked. */ -- cgit v1.2.3 From 6cc6ba3a0d9af64bfba573dec385af4302a29700 Mon Sep 17 00:00:00 2001 From: Triebitz Date: Thu, 17 Jan 2019 14:27:20 +0200 Subject: iwlwifi: pcie: allocate rb_stts's for all queues in one place AX210 devices assume that the (DRAM) addresses of the rb_stts's for the different queues are continuous. So allocate the rb_stts's for all the Rx queues in one place. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 9 ++- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 66 ++++++++++++++++------ 2 files changed, 57 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 0ecd90d050e6..bf8b61a476c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -8,7 +8,7 @@ * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -526,6 +526,8 @@ struct cont_rec { * @fh_mask: current unmasked fh causes * @hw_mask: current unmasked hw causes * @in_rescan: true if we have triggered a device rescan + * @base_rb_stts: base virtual address of receive buffer status for all queues + * @base_rb_stts_dma: base physical address of receive buffer status */ struct iwl_trans_pcie { struct iwl_rxq *rxq; @@ -617,6 +619,9 @@ struct iwl_trans_pcie { cpumask_t affinity_mask[IWL_MAX_RX_HW_QUEUES]; u16 tx_cmd_queue_size; bool in_rescan; + + void *base_rb_stts; + dma_addr_t base_rb_stts_dma; }; static inline struct iwl_trans_pcie * diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 38844215a58e..8d4f0628622b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -702,11 +702,6 @@ static void iwl_pcie_free_rxq_dma(struct iwl_trans *trans, rxq->bd_dma = 0; rxq->bd = NULL; - if (rxq->rb_stts) - dma_free_coherent(trans->dev, - use_rx_td ? sizeof(__le16) : - sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); rxq->rb_stts_dma = 0; rxq->rb_stts = NULL; @@ -743,6 +738,8 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, int free_size; bool use_rx_td = (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560); + size_t rb_stts_size = use_rx_td ? sizeof(__le16) : + sizeof(struct iwl_rb_status); spin_lock_init(&rxq->lock); if (trans->cfg->mq_rx_supported) @@ -770,12 +767,9 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans, goto err; } - /* Allocate the driver's pointer to receive buffer status */ - rxq->rb_stts = dma_alloc_coherent(dev, - use_rx_td ? sizeof(__le16) : sizeof(struct iwl_rb_status), - &rxq->rb_stts_dma, GFP_KERNEL); - if (!rxq->rb_stts) - goto err; + rxq->rb_stts = trans_pcie->base_rb_stts + rxq->id * rb_stts_size; + rxq->rb_stts_dma = + trans_pcie->base_rb_stts_dma + rxq->id * rb_stts_size; if (!use_rx_td) return 0; @@ -805,7 +799,6 @@ err: iwl_pcie_free_rxq_dma(trans, rxq); } - kfree(trans_pcie->rxq); return -ENOMEM; } @@ -815,6 +808,9 @@ int iwl_pcie_rx_alloc(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rb_allocator *rba = &trans_pcie->rba; int i, ret; + size_t rb_stts_size = trans->cfg->device_family >= + IWL_DEVICE_FAMILY_22560 ? + sizeof(__le16) : sizeof(struct iwl_rb_status); if (WARN_ON(trans_pcie->rxq)) return -EINVAL; @@ -822,18 +818,46 @@ int iwl_pcie_rx_alloc(struct iwl_trans *trans) trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq), GFP_KERNEL); if (!trans_pcie->rxq) - return -EINVAL; + return -ENOMEM; spin_lock_init(&rba->lock); + /* + * Allocate the driver's pointer to receive buffer status. + * Allocate for all queues continuously (HW requirement). + */ + trans_pcie->base_rb_stts = + dma_alloc_coherent(trans->dev, + rb_stts_size * trans->num_rx_queues, + &trans_pcie->base_rb_stts_dma, + GFP_KERNEL); + if (!trans_pcie->base_rb_stts) { + ret = -ENOMEM; + goto err; + } + for (i = 0; i < trans->num_rx_queues; i++) { struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + rxq->id = i; ret = iwl_pcie_alloc_rxq_dma(trans, rxq); if (ret) - return ret; + goto err; } return 0; + +err: + if (trans_pcie->base_rb_stts) { + dma_free_coherent(trans->dev, + rb_stts_size * trans->num_rx_queues, + trans_pcie->base_rb_stts, + trans_pcie->base_rb_stts_dma); + trans_pcie->base_rb_stts = NULL; + trans_pcie->base_rb_stts_dma = 0; + } + kfree(trans_pcie->rxq); + + return ret; } static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) @@ -1042,8 +1066,6 @@ int _iwl_pcie_rx_init(struct iwl_trans *trans) for (i = 0; i < trans->num_rx_queues; i++) { struct iwl_rxq *rxq = &trans_pcie->rxq[i]; - rxq->id = i; - spin_lock(&rxq->lock); /* * Set read write pointer to reflect that we have processed @@ -1130,6 +1152,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rb_allocator *rba = &trans_pcie->rba; int i; + size_t rb_stts_size = trans->cfg->device_family >= + IWL_DEVICE_FAMILY_22560 ? + sizeof(__le16) : sizeof(struct iwl_rb_status); /* * if rxq is NULL, it means that nothing has been allocated, @@ -1144,6 +1169,15 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) iwl_pcie_free_rbs_pool(trans); + if (trans_pcie->base_rb_stts) { + dma_free_coherent(trans->dev, + rb_stts_size * trans->num_rx_queues, + trans_pcie->base_rb_stts, + trans_pcie->base_rb_stts_dma); + trans_pcie->base_rb_stts = NULL; + trans_pcie->base_rb_stts_dma = 0; + } + for (i = 0; i < trans->num_rx_queues; i++) { struct iwl_rxq *rxq = &trans_pcie->rxq[i]; -- cgit v1.2.3 From 1e78e759bed84cc55e08cc10988287464a49747f Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Sun, 20 Jan 2019 17:45:16 +0200 Subject: iwlwifi: mvm: Don't request HW restart if already requested In case mac80211 was requested to perform an HW restart, but the HW restart has not started yet, there is no need to request another one. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 33053d136a8c..0996c97c4b94 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1320,6 +1320,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) reprobe->dev = mvm->trans->dev; INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); schedule_work(&reprobe->work); + } else if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status)) { + IWL_ERR(mvm, "HW restart already requested, but not started\n"); } else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR && mvm->hw_registered && !test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { -- cgit v1.2.3 From e8698301f2c13ea4b0e78f2ed8a15b244ee3649b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 10 Dec 2018 21:39:06 +0100 Subject: iwlwifi: fix false-positive maybe-uninitialized warning With CONFIG_NO_AUTO_INLINE, we run into a silly warning when gcc fails to remember that n_profiles is constant across the function call to iwl_mvm_sar_set_profile: drivers/net/wireless/intel/iwlwifi/mvm/fw.c: In function 'iwl_mvm_sar_get_ewrd_table': drivers/net/wireless/intel/iwlwifi/mvm/fw.c:746:9: error: 'ret' may be used uninitialized in this function [-Werror=maybe-uninitialized] Marking that function 'inline' avoids the warning. Signed-off-by: Arnd Bergmann Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 1bc51e3260eb..00a47f6f1d81 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -646,10 +646,10 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) } #ifdef CONFIG_ACPI -static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm, - union acpi_object *table, - struct iwl_mvm_sar_profile *profile, - bool enabled) +static inline int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm, + union acpi_object *table, + struct iwl_mvm_sar_profile *profile, + bool enabled) { int i; -- cgit v1.2.3 From 9178aa7c465440bae84a0de002d919ad7034a08a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 8 Jan 2019 11:17:38 -0600 Subject: iwlwifi: eeprom-parse: use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c index 75940ac406b9..04338c3a6205 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-parse.c @@ -850,8 +850,7 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, if (WARN_ON(!cfg || !cfg->eeprom_params)) return NULL; - data = kzalloc(sizeof(*data) + - sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, + data = kzalloc(struct_size(data, channels, IWL_NUM_CHANNELS), GFP_KERNEL); if (!data) return NULL; -- cgit v1.2.3 From 6b367c9f88b0813f6a557e688b665324499a159e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 8 Jan 2019 11:55:19 -0600 Subject: iwlwifi: nvm-parse: use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 503860a2b36d..ca6a243d704b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -946,15 +946,13 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, const __le16 *ch_section; if (cfg->nvm_type != IWL_NVM_EXT) - data = kzalloc(sizeof(*data) + - sizeof(struct ieee80211_channel) * - IWL_NVM_NUM_CHANNELS, - GFP_KERNEL); + data = kzalloc(struct_size(data, channels, + IWL_NVM_NUM_CHANNELS), + GFP_KERNEL); else - data = kzalloc(sizeof(*data) + - sizeof(struct ieee80211_channel) * - IWL_NVM_NUM_CHANNELS_EXT, - GFP_KERNEL); + data = kzalloc(struct_size(data, channels, + IWL_NVM_NUM_CHANNELS_EXT), + GFP_KERNEL); if (!data) return NULL; @@ -1441,9 +1439,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans, if (empty_otp) IWL_INFO(trans, "OTP is empty\n"); - nvm = kzalloc(sizeof(*nvm) + - sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, - GFP_KERNEL); + nvm = kzalloc(struct_size(nvm, channels, IWL_NUM_CHANNELS), GFP_KERNEL); if (!nvm) { ret = -ENOMEM; goto out; -- cgit v1.2.3 From de645e8992ef79a952cd5c7ca728f44c1c6b7ee6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Jan 2019 13:26:28 +0100 Subject: iwlwifi: mvm: fix error path in iwl_mvm_mac_setup_register() The IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE bit shouldn't be set, and realistically we should complete all setup before we call the ieee80211_register_hw() function. Fix this. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index a3bbf2ce571f..a585ee509987 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -796,16 +796,19 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->netdev_features |= IWL_TX_CSUM_NETIF_FLAGS; } - ret = ieee80211_register_hw(mvm->hw); - if (ret) - iwl_mvm_leds_exit(mvm); - mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE; - if (mvm->cfg->vht_mu_mimo_supported) wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER); - return ret; + ret = ieee80211_register_hw(mvm->hw); + if (ret) { + iwl_mvm_leds_exit(mvm); + return ret; + } + + mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE; + + return 0; } static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm, -- cgit v1.2.3 From 7691fa6947374f2a0c3a17ae664fe258db508ae2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Jan 2019 11:14:13 +0100 Subject: iwlwifi: nvm-parse: advertise IEEE80211_VHT_EXT_NSS_BW_CAPABLE in VHT We support this, so we should advertise it. In fact, if we don't, mac80211 will do it for us (as we advertise SUPPORTS_VHT_EXT_NSS_BW to it), but that requires a memory reallocation which is wasteful: ieee80211 phy0: copying sband (band 1) due to VHT EXT NSS BW flag Set the flag here to avoid that. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index ca6a243d704b..65228a092bd6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -8,7 +8,7 @@ * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -463,6 +463,9 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, } vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map; + + vht_cap->vht_mcs.tx_highest |= + cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE); } static struct ieee80211_sband_iftype_data iwl_he_capa[] = { -- cgit v1.2.3 From 84caa1dd0092e7e57bd39df0e1b8791c7a756103 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:19 +0100 Subject: iwlwifi: dvm: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Johannes Berg Cc: Emmanuel Grumbach Cc: Luca Coelho Cc: Intel Linux Wireless Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/dvm/agn.h | 9 ++--- drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c | 44 +++--------------------- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 5 +-- 3 files changed, 8 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h index 431e13c6ee35..254a5ce52456 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h @@ -439,13 +439,10 @@ static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state) } #ifdef CONFIG_IWLWIFI_DEBUGFS -int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir); +void iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir); #else -static inline int iwl_dbgfs_register(struct iwl_priv *priv, - struct dentry *dbgfs_dir) -{ - return 0; -} +static inline void iwl_dbgfs_register(struct iwl_priv *priv, + struct dentry *dbgfs_dir) { } #endif /* CONFIG_IWLWIFI_DEBUGFS */ #ifdef CONFIG_IWLWIFI_DEBUG diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c index e64cdafc5623..d4b19673b06a 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c @@ -37,31 +37,8 @@ /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ - if (!debugfs_create_file(#name, mode, parent, priv, \ - &iwl_dbgfs_##name##_ops)) \ - goto err; \ -} while (0) - -#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ - struct dentry *__tmp; \ - __tmp = debugfs_create_bool(#name, 0600, parent, ptr); \ - if (IS_ERR(__tmp) || !__tmp) \ - goto err; \ -} while (0) - -#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ - struct dentry *__tmp; \ - __tmp = debugfs_create_x32(#name, 0600, parent, ptr); \ - if (IS_ERR(__tmp) || !__tmp) \ - goto err; \ -} while (0) - -#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ - struct dentry *__tmp; \ - __tmp = debugfs_create_u32(#name, mode, \ - parent, ptr); \ - if (IS_ERR(__tmp) || !__tmp) \ - goto err; \ + debugfs_create_file(#name, mode, parent, priv, \ + &iwl_dbgfs_##name##_ops); \ } while (0) /* file operation */ @@ -2348,21 +2325,15 @@ DEBUGFS_READ_WRITE_FILE_OPS(calib_disabled); * Create the debugfs files and directories * */ -int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir) +void iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir) { struct dentry *dir_data, *dir_rf, *dir_debug; priv->debugfs_dir = dbgfs_dir; dir_data = debugfs_create_dir("data", dbgfs_dir); - if (!dir_data) - goto err; dir_rf = debugfs_create_dir("rf", dbgfs_dir); - if (!dir_rf) - goto err; dir_debug = debugfs_create_dir("debug", dbgfs_dir); - if (!dir_debug) - goto err; DEBUGFS_ADD_FILE(nvm, dir_data, 0400); DEBUGFS_ADD_FILE(sram, dir_data, 0600); @@ -2422,13 +2393,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir) snprintf(buf, 100, "../../%pd2", dev_dir); - if (!debugfs_create_symlink("iwlwifi", mac80211_dir, buf)) - goto err; + debugfs_create_symlink("iwlwifi", mac80211_dir, buf); } - - return 0; - -err: - IWL_ERR(priv, "failed to create the dvm debugfs entries\n"); - return -ENOMEM; } diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 114f0ab022a7..7c68a86ed9e1 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -1509,13 +1509,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, if (iwlagn_mac_setup_register(priv, &fw->ucode_capa)) goto out_destroy_workqueue; - if (iwl_dbgfs_register(priv, dbgfs_dir)) - goto out_mac80211_unregister; + iwl_dbgfs_register(priv, dbgfs_dir); return op_mode; -out_mac80211_unregister: - iwlagn_mac_unregister(priv); out_destroy_workqueue: iwl_tt_exit(priv); iwl_cancel_deferred_work(priv); -- cgit v1.2.3 From 5987dfde6f555248f4b6c83147ec9bc877cd6f4c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:21 +0100 Subject: iwlwifi: fw: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Johannes Berg Cc: Emmanuel Grumbach Cc: Luca Coelho Cc: Intel Linux Wireless Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/debugfs.c | 11 +++-------- drivers/net/wireless/intel/iwlwifi/fw/debugfs.h | 9 +++------ 2 files changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index 3e120dd47305..c1aa4360736b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -173,9 +173,8 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \ _FWRT_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_fw_runtime) #define FWRT_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do { \ - if (!debugfs_create_file(alias, mode, parent, fwrt, \ - &iwl_dbgfs_##name##_ops)) \ - goto err; \ + debugfs_create_file(alias, mode, parent, fwrt, \ + &iwl_dbgfs_##name##_ops); \ } while (0) #define FWRT_DEBUGFS_ADD_FILE(name, parent, mode) \ FWRT_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode) @@ -321,14 +320,10 @@ out: FWRT_DEBUGFS_WRITE_FILE_OPS(send_hcmd, 512); -int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, +void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, struct dentry *dbgfs_dir) { INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk); FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200); FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200); - return 0; -err: - IWL_ERR(fwrt, "Can't create the fwrt debugfs directory\n"); - return -ENOMEM; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h index 88255035e8ef..fde40ff88451 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h @@ -63,14 +63,11 @@ #include "runtime.h" #ifdef CONFIG_IWLWIFI_DEBUGFS -int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, +void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, struct dentry *dbgfs_dir); #else -static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, - struct dentry *dbgfs_dir) -{ - return 0; -} +static inline void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, + struct dentry *dbgfs_dir) { } #endif /* CONFIG_IWLWIFI_DEBUGFS */ -- cgit v1.2.3 From dc475ae9c00a83c4b29d165689ea5f7813f6ea99 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Jan 2019 16:21:22 +0100 Subject: iwlwifi: iwl-drv: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Johannes Berg Cc: Emmanuel Grumbach Cc: Luca Coelho Cc: Intel Linux Wireless Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 4b75a93c7364..689a65b11cc3 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -1253,11 +1253,6 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) #ifdef CONFIG_IWLWIFI_DEBUGFS drv->dbgfs_op_mode = debugfs_create_dir(op->name, drv->dbgfs_drv); - if (!drv->dbgfs_op_mode) { - IWL_ERR(drv, - "failed to create opmode debugfs directory\n"); - return op_mode; - } dbgfs_dir = drv->dbgfs_op_mode; #endif @@ -1620,20 +1615,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans) drv->dbgfs_drv = debugfs_create_dir(dev_name(trans->dev), iwl_dbgfs_root); - if (!drv->dbgfs_drv) { - IWL_ERR(drv, "failed to create debugfs directory\n"); - ret = -ENOMEM; - goto err_free_tlv; - } - /* Create transport layer debugfs dir */ drv->trans->dbgfs_dir = debugfs_create_dir("trans", drv->dbgfs_drv); - - if (!drv->trans->dbgfs_dir) { - IWL_ERR(drv, "failed to create transport debugfs directory\n"); - ret = -ENOMEM; - goto err_free_dbgfs; - } #endif ret = iwl_request_firmware(drv, true); @@ -1646,9 +1629,7 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans) err_fw: #ifdef CONFIG_IWLWIFI_DEBUGFS -err_free_dbgfs: debugfs_remove_recursive(drv->dbgfs_drv); -err_free_tlv: iwl_fw_dbg_free(drv->trans); #endif kfree(drv); @@ -1759,9 +1740,6 @@ static int __init iwl_drv_init(void) #ifdef CONFIG_IWLWIFI_DEBUGFS /* Create the root of iwlwifi debugfs subsystem. */ iwl_dbgfs_root = debugfs_create_dir(DRV_NAME, NULL); - - if (!iwl_dbgfs_root) - return -EFAULT; #endif return iwl_pci_register_driver(); -- cgit v1.2.3 From 90a128291ded5f86a730729f74d6b2f0e8f668df Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Sun, 27 Jan 2019 11:24:30 +0200 Subject: iwlwifi: mvm: reject new beacons when in inject mode Verify we do not accept new beacon templates while beacon injection is active. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 7 +++++-- drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 5 +++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 80b0b2ed69bb..05a6db2db478 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1238,6 +1238,8 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len) goto out_err; } + mvm->beacon_inject_active = true; + mvmvif = iwl_mvm_vif_from_mac80211(vif); info = IEEE80211_SKB_CB(beacon); rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif); @@ -1287,6 +1289,7 @@ static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm, int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0); mvm->hw->extra_beacon_tailroom = 0; + mvm->beacon_inject_active = false; return ret ?: count; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 9bd4376cad9b..003a20630252 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1041,6 +1041,11 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, if (!beacon) return -ENOMEM; +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (mvm->beacon_inject_active) + return -EBUSY; +#endif + ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon); dev_kfree_skb(beacon); return ret; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 9993337a2bbd..acb4cca5bdcf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -978,6 +978,7 @@ struct iwl_mvm { u32 dbgfs_prph_reg_addr; bool disable_power_off; bool disable_power_off_d3; + bool beacon_inject_active; bool scan_iter_notif_enabled; -- cgit v1.2.3 From 8bf52e0ab3d6c4c64295250382fcff2d9d3fed6a Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 15 Jan 2019 13:38:30 +0200 Subject: iwlwifi: mvm: add read debugfs for he_sniffer_params Return the AID currently set when reading this debugfs entry. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 25 ++++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 05a6db2db478..776b24f54200 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1789,6 +1789,7 @@ iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf, struct iwl_mvm_sniffer_apply { struct iwl_mvm *mvm; + u8 *bssid; u16 aid; }; @@ -1798,6 +1799,8 @@ static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data, struct iwl_mvm_sniffer_apply *apply = data; apply->mvm->cur_aid = cpu_to_le16(apply->aid); + memcpy(apply->mvm->cur_bssid, apply->bssid, + sizeof(apply->mvm->cur_bssid)); return true; } @@ -1830,6 +1833,7 @@ iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf, he_mon_cmd.aid = cpu_to_le16(aid); apply.aid = aid; + apply.bssid = (void *)he_mon_cmd.bssid; mutex_lock(&mvm->mutex); @@ -1858,6 +1862,23 @@ iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf, return ret ?: count; } +static ssize_t +iwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_mvm *mvm = file->private_data; + u8 buf[32]; + int len; + + len = scnprintf(buf, sizeof(buf), + "%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", + le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0], + mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3], + mvm->cur_bssid[4], mvm->cur_bssid[5]); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + static ssize_t iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1928,7 +1949,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile); #endif -MVM_DEBUGFS_WRITE_FILE_OPS(he_sniffer_params, 32); +MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32); static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -2119,7 +2140,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) #ifdef CONFIG_ACPI MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400); #endif - MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0200); + MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600); if (!debugfs_create_bool("enable_scan_iteration_notif", 0600, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index acb4cca5bdcf..148aee1ad79d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1176,6 +1176,7 @@ struct iwl_mvm { /* sniffer data to include in radiotap */ __le16 cur_aid; + u8 cur_bssid[ETH_ALEN]; #ifdef CONFIG_ACPI struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM]; -- cgit v1.2.3 From 503863055d9eff82a985739a73f13337fe9580ba Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 29 Jan 2019 11:53:03 +0200 Subject: iwlwifi: mvm: support non-transmitting AP Add an option to not send beacons and probe responses. This is used for testing multiple-bssid. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/constants.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 10 ++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 6a3edea3d580..dff14f1ec55f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -117,6 +117,7 @@ #define IWL_MVM_TCM_LOWLAT_ENABLE_THRESH 100 /* packets/10 seconds */ #define IWL_MVM_UAPSD_NONAGG_PERIOD 5000 /* msecs */ #define IWL_MVM_UAPSD_NOAGG_LIST_LEN IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM +#define IWL_MVM_NON_TRANSMITTING_AP 0 #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 003a20630252..6a70dece447d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -1016,6 +1016,9 @@ int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm, if (WARN_ON(!beacon)) return -EINVAL; + if (IWL_MVM_NON_TRANSMITTING_AP) + return 0; + if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CSA_AND_TBTT_OFFLOAD)) return iwl_mvm_mac_ctxt_send_beacon_v6(mvm, vif, beacon); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index ac62eb8c4b36..898bfda93029 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -719,6 +719,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) IEEE80211_TX_CTL_TX_OFFCHAN; int queue = -1; + if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc)) + return -1; + memcpy(&info, skb->cb, sizeof(info)); if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU)) @@ -1078,6 +1081,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, fc = hdr->frame_control; hdrlen = ieee80211_hdrlen(fc); + if (IWL_MVM_NON_TRANSMITTING_AP && ieee80211_is_probe_resp(fc)) + return -1; + if (WARN_ON_ONCE(!mvmsta)) return -1; -- cgit v1.2.3 From a371bb646ff72f7ea13bdb920b2353b34f9d45b5 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Tue, 29 Jan 2019 20:38:48 +0200 Subject: iwlwifi: mvm: Set TX_CMD_FLG_PROT_REQUIRE correctly Previously the protection flag wasn't set on multicast frames even if the RA is unicast. Fix this by checking addr1 instead. Signed-off-by: Andrei Otcheretianski Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 898bfda93029..b82b2f062c95 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -278,7 +278,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, } if (ieee80211_is_data(fc) && len > mvm->rts_threshold && - !is_multicast_ether_addr(ieee80211_get_DA(hdr))) + !is_multicast_ether_addr(hdr->addr1)) tx_flags |= TX_CMD_FLG_PROT_REQUIRE; if (fw_has_capa(&mvm->fw->ucode_capa, -- cgit v1.2.3 From cad7eb754dbd8e921e481b0a41ee0596016afa2f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 29 Jan 2019 13:23:05 +0100 Subject: iwlwifi: mvm: remove IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE There's no point in this, we already do everything in a nested fashion, and if we didn't we'd already crash in iwl_mvm_leds_exit() etc. Just remove the bit. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 5 +---- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 - drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 5 +---- 3 files changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index a585ee509987..24556a7cd29c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -803,12 +803,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ret = ieee80211_register_hw(mvm->hw); if (ret) { iwl_mvm_leds_exit(mvm); - return ret; } - mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE; - - return 0; + return ret; } static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 148aee1ad79d..bca6f6b536d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1221,7 +1221,6 @@ enum iwl_mvm_status { enum iwl_mvm_init_status { IWL_MVM_INIT_STATUS_THERMAL_INIT_COMPLETE = BIT(0), IWL_MVM_INIT_STATUS_LEDS_INIT_COMPLETE = BIT(1), - IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE = BIT(2), }; static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 0996c97c4b94..ba27dce4c2bb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -919,10 +919,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) iwl_mvm_thermal_exit(mvm); - if (mvm->init_status & IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE) { - ieee80211_unregister_hw(mvm->hw); - mvm->init_status &= ~IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE; - } + ieee80211_unregister_hw(mvm->hw); kfree(mvm->scan_cmd); kfree(mvm->mcast_filter_cmd); -- cgit v1.2.3 From 8c739d8d7935e87bf68a0f8cefa6a947f787d642 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 28 Jan 2019 13:32:52 +0200 Subject: iwlwifi: mvm: Allow retries for probe responses When hostapd sends a probe response, it does not request an acknowledgment on the probe response. This setting is propagated to the driver and FW from mac80211, and as a result probe responses are transmitted only once without retries. In congested environments, this reduces the likelihood for finding the AP. To overcome this, enable acknowledgment and retries for probe responses, even in case no acknowledgment is requested. In such a case the retry limit is set to 3. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index b82b2f062c95..d01998853d1f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -209,7 +209,9 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, u16 offload_assist = 0; u8 ac; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) || + (ieee80211_is_probe_resp(fc) && + !is_multicast_ether_addr(hdr->addr1))) tx_flags |= TX_CMD_FLG_ACK; else tx_flags &= ~TX_CMD_FLG_ACK; -- cgit v1.2.3 From a53b2a0b1245d70430a8b541d76666b585346882 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Jan 2019 12:22:41 +0100 Subject: iwlwifi: mvm: implement VHT extended NSS support in rs.c For non-offloaded rate control, implement VHT extended NSS support by just ignoring 160 MHz on transmit if the peer doesn't support the full NSS (2). This is pretty unlikely and gets us 160 MHz RX as well as TX in most cases, since the typical case for this workaround is 4x4 AP only doing 2x2 on 160 MHz. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 2d7a089d93a3..e231a44d2423 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -3,7 +3,7 @@ * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -1643,8 +1643,26 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta) { + struct ieee80211_sta_vht_cap *sta_vht_cap = &sta->vht_cap; + struct ieee80211_vht_cap vht_cap = { + .vht_cap_info = cpu_to_le32(sta_vht_cap->cap), + .supp_mcs = sta_vht_cap->vht_mcs, + }; + switch (sta->bandwidth) { case IEEE80211_STA_RX_BW_160: + /* + * Don't use 160 MHz if VHT extended NSS support + * says we cannot use 2 streams, we don't want to + * deal with this. + * We only check MCS 0 - they will support that if + * we got here at all and we don't care which MCS, + * we want to determine a more global state. + */ + if (ieee80211_get_vht_max_nss(&vht_cap, + IEEE80211_VHT_CHANWIDTH_160MHZ, + 0, true) < sta->rx_nss) + return RATE_MCS_CHAN_WIDTH_80; return RATE_MCS_CHAN_WIDTH_160; case IEEE80211_STA_RX_BW_80: return RATE_MCS_CHAN_WIDTH_80; @@ -1796,7 +1814,7 @@ static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm, struct iwl_scale_tbl_info *tbl, enum rs_action scale_action) { - if (sta->bandwidth != IEEE80211_STA_RX_BW_80) + if (rs_bw_from_sta_bw(sta) != RATE_MCS_CHAN_WIDTH_80) return false; if (!is_vht_siso(&tbl->rate)) @@ -4127,6 +4145,7 @@ static const struct rate_control_ops rs_mvm_ops_drv = { .add_sta_debugfs = rs_drv_add_sta_debugfs, .remove_sta_debugfs = rs_remove_sta_debugfs, #endif + .capa = RATE_CTRL_CAPA_VHT_EXT_NSS_BW, }; void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, -- cgit v1.2.3 From 714afd35065b6b5ad5a384d7401a82a3db50a477 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 23 Jan 2019 11:31:58 +0200 Subject: iwlwifi: remove redundant condition from prior alive dump flow After the FW image was loaded for the first time, fwrt->smem_cfg.num_lmacs value will no longer be zero since we don't clean it when we stop the device. So if we load the image once and then we fail on a consecutive attempt, the driver will abort any dumping. Solve this by removing the condition. It is safe to remove since when we do the actual dumping in iwl_fw_dbg_collect_sync we check that STATUS_DEVICE_ENABLED bit is still active. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 202f96e9ca0c..b189a605ec13 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1592,22 +1592,6 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, bool monitor_only, unsigned int delay) { - /* - * If the loading of the FW completed successfully, the next step is to - * get the SMEM config data. Thus, if fwrt->smem_cfg.num_lmacs is non - * zero, the FW was already loaded successully. If the state is "NO_FW" - * in such a case - exit, since FW may be dead. Otherwise, we - * can try to collect the data, since FW might just not be fully - * loaded (no "ALIVE" yet), and the debug data is accessible. - * - * Corner case: got the FW alive but crashed before getting the SMEM - * config. In such a case, due to HW access problems, we might - * collect garbage. - */ - if (fwrt->trans->state == IWL_TRANS_NO_FW && - fwrt->smem_cfg.num_lmacs) - return -EIO; - if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) return -EBUSY; -- cgit v1.2.3 From f50d693b9fbe1d533e29cf470ebe51140c5c0b13 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 28 Jan 2019 15:12:08 +0200 Subject: iwlwifi: mvm: add some debug data to TX path This helps debugging when things go wrong. Signed-off-by: Sara Sharon Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 8 +++++++- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 11 +++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 24556a7cd29c..f8928ba1f338 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -941,8 +941,14 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq) IWL_PLAT_PM_MODE_DISABLED))) { skb = ieee80211_tx_dequeue(hw, txq); - if (!skb) + if (!skb) { + if (txq->sta) + IWL_DEBUG_TX(mvm, + "TXQ of sta %pM tid %d is now empty\n", + txq->sta->addr, + txq->tid); break; + } if (!txq->sta) iwl_mvm_tx_skb_non_sta(mvm, skb); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index d01998853d1f..0c2aabc842f9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1115,12 +1115,14 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, */ if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { tid = ieee80211_get_tid(hdr); - if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) + if (WARN_ONCE(tid >= IWL_MAX_TID_COUNT, "Invalid TID %d", tid)) goto drop_unlock_sta; is_ampdu = info->flags & IEEE80211_TX_CTL_AMPDU; - if (WARN_ON_ONCE(is_ampdu && - mvmsta->tid_data[tid].state != IWL_AGG_ON)) + if (WARN_ONCE(is_ampdu && + mvmsta->tid_data[tid].state != IWL_AGG_ON, + "Invalid internal agg state %d for TID %d", + mvmsta->tid_data[tid].state, tid)) goto drop_unlock_sta; seq_number = mvmsta->tid_data[tid].seq_number; @@ -1142,7 +1144,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM); - if (WARN_ON_ONCE(txq_id == IWL_MVM_INVALID_QUEUE)) { + if (WARN_ONCE(txq_id == IWL_MVM_INVALID_QUEUE, "Invalid TXQ id")) { iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); spin_unlock(&mvmsta->lock); return 0; @@ -1192,6 +1194,7 @@ drop_unlock_sta: iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); spin_unlock(&mvmsta->lock); drop: + IWL_DEBUG_TX(mvm, "TX to [%d|%d] dropped\n", mvmsta->sta_id, tid); return -1; } -- cgit v1.2.3 From 00276722194658d8e33e370845a198db42f8033f Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 29 Jan 2019 09:51:44 +0200 Subject: iwlwifi: dbg_ini: fix infinite time ignore consecutive dumps The driver sets ignore_consec to -1 which is 0xffffffff in u32 so when iwl_fw_ini_trigger_on is called, it will always return false and each trigger could be used only once. Solve this by removing the assignment to -1. Signed-off-by: Shahar S Matityahu Fixes: fe1b7d6c2888 ("iwlwifi: add support for triggering ini triggers") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index b189a605ec13..5e5c4e8c4a69 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2093,8 +2093,6 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, /* Since zero means infinity - just set to -1 */ if (!le32_to_cpu(active->trig->occurrences)) active->trig->occurrences = cpu_to_le32(-1); - if (!le32_to_cpu(active->trig->ignore_consec)) - active->trig->ignore_consec = cpu_to_le32(-1); active->active = true; next: -- cgit v1.2.3 From 05841faa8567fccf3bf9c223267ec76a3a040cef Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 27 Jan 2019 11:34:05 +0200 Subject: iwlwifi: dbg_ini: add print to iwl_dump_ini_mem in case of invalid range Add informative print in case the range is not available. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 5e5c4e8c4a69..e4e50d598377 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1300,14 +1300,18 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, memcpy(header->name, reg->name, le32_to_cpu(header->name_len)); range = ops->fill_mem_hdr(fwrt, header); - if (!range) + if (!range) { + IWL_ERR(fwrt, "Failed to fill region header: id=%d, type=%d\n", + le32_to_cpu(reg->region_id), type); return; + } for (i = 0; i < num_of_ranges; i++) { int range_data_size = ops->fill_range(fwrt, range, reg, i); if (range_data_size < 0) { - IWL_ERR(fwrt, "Failed to dump region type %d\n", type); + IWL_ERR(fwrt, "Failed to dump region: id=%d, type=%d\n", + le32_to_cpu(reg->region_id), type); return; } range = ((void *)range) + sizeof(*range) + range_data_size; -- cgit v1.2.3 From 01e591c9f42aa3ee0440e7547ecdad8009cfaf61 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 28 Jan 2019 11:02:30 +0200 Subject: iwlwifi: dbg_ini: make memory dump get_size handler include headers Make the get size handler of iwl_dump_ini_mem_ops include the total size of the region. It is needed for fifos dumping. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 98 ++++++++++++++--------------- 1 file changed, 49 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index e4e50d598377..5a98eb0d5c00 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1187,21 +1187,50 @@ static struct iwl_fw_ini_error_dump_range return mon_dump->ranges; } +static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return le32_to_cpu(reg->internal.num_of_ranges); +} + +static u32 iwl_dump_ini_paging_gen2_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return fwrt->trans->init_dram.paging_cnt; +} + +static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return fwrt->num_of_paging_blk; +} + +static u32 iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return 1; +} + static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { - return le32_to_cpu(reg->internal.num_of_ranges) * - le32_to_cpu(reg->internal.range_data_size); + return sizeof(struct iwl_fw_ini_error_dump) + + iwl_dump_ini_mem_ranges(fwrt, reg) * + (sizeof(struct iwl_fw_ini_error_dump_range) + + le32_to_cpu(reg->internal.range_data_size)); } static u32 iwl_dump_ini_paging_gen2_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { int i; - u32 size = 0; + u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range); + u32 size = sizeof(struct iwl_fw_ini_error_dump); + + for (i = 0; i < iwl_dump_ini_paging_gen2_ranges(fwrt, reg); i++) + size += range_header_len + + fwrt->trans->init_dram.paging[i].size; - for (i = 0; i < fwrt->trans->init_dram.paging_cnt; i++) - size += fwrt->trans->init_dram.paging[i].size; return size; } @@ -1209,47 +1238,30 @@ static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { int i; - u32 size = 0; + u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range); + u32 size = sizeof(struct iwl_fw_ini_error_dump); + + for (i = 1; i <= iwl_dump_ini_paging_ranges(fwrt, reg); i++) + size += range_header_len + fwrt->fw_paging_db[i].fw_paging_size; - for (i = 1; i <= fwrt->num_of_paging_blk; i++) - size += fwrt->fw_paging_db[i].fw_paging_size; return size; } static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { - return fwrt->trans->num_blocks ? fwrt->trans->fw_mon[0].size : 0; -} - -static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_region_cfg *reg) -{ - return le32_to_cpu(reg->internal.num_of_ranges); -} - -static u32 iwl_dump_ini_paging_gen2_ranges(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_region_cfg *reg) -{ - return fwrt->trans->init_dram.paging_cnt; -} + u32 size = sizeof(struct iwl_fw_ini_monitor_dram_dump); -static u32 iwl_dump_ini_paging_ranges(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_region_cfg *reg) -{ - return fwrt->num_of_paging_blk; -} + if (fwrt->trans->num_blocks) + size += fwrt->trans->fw_mon[0].size; -static u32 iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_region_cfg *reg) -{ - return 1; + return size; } /** * struct iwl_dump_ini_mem_ops - ini memory dump operations * @get_num_of_ranges: returns the number of memory ranges in the region. - * @get_size: returns the size of the region data without headers. + * @get_size: returns the total size of the region. * @fill_mem_hdr: fills region type specific headers and returns the first * range or NULL if failed to fill headers. * @fill_range: copies a given memory range into the dump. @@ -1291,8 +1303,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, num_of_ranges = ops->get_num_of_ranges(fwrt, reg); (*data)->type = cpu_to_le32(type | INI_DUMP_BIT); - (*data)->len = cpu_to_le32(sizeof(*header) + num_of_ranges * - sizeof(*range) + ops->get_size(fwrt, reg)); + (*data)->len = cpu_to_le32(ops->get_size(fwrt, reg)); header->num_of_ranges = cpu_to_le32(num_of_ranges); header->name_len = cpu_to_le32(min_t(int, IWL_FW_INI_MAX_NAME, @@ -1323,8 +1334,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_trigger *trigger) { int i, size = 0, hdr_len = sizeof(struct iwl_fw_error_dump_data); - u32 dump_header_len = sizeof(struct iwl_fw_ini_error_dump); - u32 range_header_len = sizeof(struct iwl_fw_ini_error_dump_range); if (!trigger || !trigger->num_regions) return 0; @@ -1349,9 +1358,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_PERIPHERY_AUX: case IWL_FW_INI_REGION_INTERNAL_BUFFER: case IWL_FW_INI_REGION_CSR: - size += hdr_len + dump_header_len + range_header_len * - iwl_dump_ini_mem_ranges(fwrt, reg) + - iwl_dump_ini_mem_get_size(fwrt, reg); + size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_TXF: size += iwl_fw_txf_len(fwrt, &fwrt->smem_cfg); @@ -1360,16 +1367,11 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, size += iwl_fw_rxf_len(fwrt, &fwrt->smem_cfg); break; case IWL_FW_INI_REGION_PAGING: { - size += hdr_len + dump_header_len; + size += hdr_len; if (iwl_fw_dbg_is_paging_enabled(fwrt)) { - size += range_header_len * - iwl_dump_ini_paging_ranges(fwrt, reg) + - iwl_dump_ini_paging_get_size(fwrt, reg); + size += iwl_dump_ini_paging_get_size(fwrt, reg); } else { - size += range_header_len * - iwl_dump_ini_paging_gen2_ranges(fwrt, - reg) + - iwl_dump_ini_paging_gen2_get_size(fwrt, + size += iwl_dump_ini_paging_gen2_get_size(fwrt, reg); } break; @@ -1378,8 +1380,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, if (!fwrt->trans->num_blocks) break; size += hdr_len + - sizeof(struct iwl_fw_ini_monitor_dram_dump) * - iwl_dump_ini_mon_dram_ranges(fwrt, reg) + iwl_dump_ini_mon_dram_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_DRAM_IMR: -- cgit v1.2.3 From 1a6c8bb7f84c8f75e0fb16726186a8ec314a0010 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 28 Jan 2019 11:03:45 +0200 Subject: iwlwifi: dbg_ini: make fill_range handler accept generic range pointer Make fill_range handler of iwl_dump_ini_mem_ops accept a generic range pointer. It is needed for future support in fifos dumping. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 53 ++++++++++++++++------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 5a98eb0d5c00..b86691fdacb3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1044,10 +1044,10 @@ out: } static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_error_dump_range *range, struct iwl_fw_ini_region_cfg *reg, - int idx) + void *range_ptr, int idx) { + struct iwl_fw_ini_error_dump_range *range = range_ptr; __le32 *val = range->data; u32 addr, prph_val, offset = le32_to_cpu(reg->offset); int i; @@ -1061,14 +1061,15 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, return -1; *val++ = cpu_to_le32(prph_val); } - return le32_to_cpu(range->range_data_size); + + return sizeof(*range) + le32_to_cpu(range->range_data_size); } static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_error_dump_range *range, struct iwl_fw_ini_region_cfg *reg, - int idx) + void *range_ptr, int idx) { + struct iwl_fw_ini_error_dump_range *range = range_ptr; __le32 *val = range->data; u32 addr, offset = le32_to_cpu(reg->offset); int i; @@ -1080,14 +1081,15 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt, *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, addr + offset)); } - return le32_to_cpu(range->range_data_size); + + return sizeof(*range) + le32_to_cpu(range->range_data_size); } static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_error_dump_range *range, struct iwl_fw_ini_region_cfg *reg, - int idx) + void *range_ptr, int idx) { + struct iwl_fw_ini_error_dump_range *range = range_ptr; u32 addr = le32_to_cpu(range->start_addr); u32 offset = le32_to_cpu(reg->offset); @@ -1095,33 +1097,35 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, range->range_data_size = reg->internal.range_data_size; iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data, le32_to_cpu(reg->internal.range_data_size)); - return le32_to_cpu(range->range_data_size); + + return sizeof(*range) + le32_to_cpu(range->range_data_size); } static int iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_error_dump_range *range, struct iwl_fw_ini_region_cfg *reg, - int idx) + void *range_ptr, int idx) { + struct iwl_fw_ini_error_dump_range *range = range_ptr; u32 page_size = fwrt->trans->init_dram.paging[idx].size; range->start_addr = cpu_to_le32(idx); range->range_data_size = cpu_to_le32(page_size); memcpy(range->data, fwrt->trans->init_dram.paging[idx].block, page_size); - return le32_to_cpu(range->range_data_size); + + return sizeof(*range) + le32_to_cpu(range->range_data_size); } static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_error_dump_range *range, struct iwl_fw_ini_region_cfg *reg, - int idx) + void *range_ptr, int idx) { /* increase idx by 1 since the pages are from 1 to * fwrt->num_of_paging_blk + 1 */ struct page *page = fwrt->fw_paging_db[++idx].fw_paging_block; + struct iwl_fw_ini_error_dump_range *range = range_ptr; dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys; u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size; @@ -1132,15 +1136,16 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt, memcpy(range->data, page_address(page), page_size); dma_sync_single_for_device(fwrt->trans->dev, addr, page_size, DMA_BIDIRECTIONAL); - return le32_to_cpu(range->range_data_size); + + return sizeof(*range) + le32_to_cpu(range->range_data_size); } static int iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_error_dump_range *range, - struct iwl_fw_ini_region_cfg *reg, + struct iwl_fw_ini_region_cfg *reg, void *range_ptr, int idx) { + struct iwl_fw_ini_error_dump_range *range = range_ptr; u32 start_addr = iwl_read_umac_prph(fwrt->trans, MON_BUFF_BASE_ADDR_VER2); @@ -1153,7 +1158,7 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, memcpy(range->data, fwrt->trans->fw_mon[idx].block, fwrt->trans->fw_mon[idx].size); - return le32_to_cpu(range->range_data_size); + return sizeof(*range) + le32_to_cpu(range->range_data_size); } static struct iwl_fw_ini_error_dump_range @@ -1275,8 +1280,8 @@ struct iwl_dump_ini_mem_ops { struct iwl_fw_ini_error_dump_range * (*fill_mem_hdr)(struct iwl_fw_runtime *fwrt, void *data); int (*fill_range)(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_error_dump_range *range, - struct iwl_fw_ini_region_cfg *reg, int idx); + struct iwl_fw_ini_region_cfg *reg, void *range, + int idx); }; /** @@ -1293,7 +1298,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct iwl_dump_ini_mem_ops *ops) { struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data; - struct iwl_fw_ini_error_dump_range *range; + void *range; u32 num_of_ranges, i; if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size || @@ -1318,14 +1323,14 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, } for (i = 0; i < num_of_ranges; i++) { - int range_data_size = ops->fill_range(fwrt, range, reg, i); + int range_size = ops->fill_range(fwrt, reg, range, i); - if (range_data_size < 0) { + if (range_size < 0) { IWL_ERR(fwrt, "Failed to dump region: id=%d, type=%d\n", le32_to_cpu(reg->region_id), type); return; } - range = ((void *)range) + sizeof(*range) + range_data_size; + range = range + range_size; } *data = iwl_fw_error_next_data(*data); } -- cgit v1.2.3 From 2dbf3aea791ebf10bbb67102d1c7a40868e2499e Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 19 Dec 2018 14:47:36 +0200 Subject: iwlwifi: dbg_ini: add region to fill_header handler Add iwl_fw_ini_region_cfg region struct to fill_header handler of iwl_dump_ini_mem_ops. it is needed for future support in fifos dumping. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index b86691fdacb3..c9a63b2c6c9b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1161,16 +1161,19 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, return sizeof(*range) + le32_to_cpu(range->range_data_size); } -static struct iwl_fw_ini_error_dump_range -*iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, void *data) +static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *data) { struct iwl_fw_ini_error_dump *dump = data; return dump->ranges; } -static struct iwl_fw_ini_error_dump_range -*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, void *data) +static void +*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *data) { struct iwl_fw_ini_monitor_dram_dump *mon_dump = (void *)data; u32 write_ptr, cycle_cnt; @@ -1267,8 +1270,8 @@ static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, * struct iwl_dump_ini_mem_ops - ini memory dump operations * @get_num_of_ranges: returns the number of memory ranges in the region. * @get_size: returns the total size of the region. - * @fill_mem_hdr: fills region type specific headers and returns the first - * range or NULL if failed to fill headers. + * @fill_mem_hdr: fills region type specific headers and returns pointer to + * the first range or NULL if failed to fill headers. * @fill_range: copies a given memory range into the dump. * Returns the size of the range or -1 otherwise. */ @@ -1277,8 +1280,8 @@ struct iwl_dump_ini_mem_ops { struct iwl_fw_ini_region_cfg *reg); u32 (*get_size)(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg); - struct iwl_fw_ini_error_dump_range * - (*fill_mem_hdr)(struct iwl_fw_runtime *fwrt, void *data); + void *(*fill_mem_hdr)(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, void *data); int (*fill_range)(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg, void *range, int idx); @@ -1315,7 +1318,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, le32_to_cpu(reg->name_len))); memcpy(header->name, reg->name, le32_to_cpu(header->name_len)); - range = ops->fill_mem_hdr(fwrt, header); + range = ops->fill_mem_hdr(fwrt, reg, header); if (!range) { IWL_ERR(fwrt, "Failed to fill region header: id=%d, type=%d\n", le32_to_cpu(reg->region_id), type); -- cgit v1.2.3 From 1b64d58bd4cb60cd7b0251d8654e18e5b1539ef4 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 20 Dec 2018 14:54:58 +0200 Subject: iwlwifi: dbg_ini: implement Tx fifos dump Implement Tx fifos dump in the new dump mechanism. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- .../net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 13 +- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 189 ++++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 29 +++- drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 1 + 4 files changed, 218 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index 70cc0820e068..33858787817b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -25,7 +25,7 @@ * * BSD LICENSE * - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -146,16 +146,17 @@ struct iwl_fw_ini_region_cfg_internal { /** * struct iwl_fw_ini_region_cfg_fifos - meta data of fifos region - * @lmac1_id: bit map of lmac1 fifos to include in the region. - * @lmac2_id: bit map of lmac2 fifos to include in the region. + * @fid1: fifo id 1 - bitmap of lmac tx/rx fifos to include in the region + * @fid2: fifo id 2 - bitmap of umac rx fifos to include in the region. + * It is unused for tx. * @num_of_registers: number of prph registers in the region, each register is * 4 bytes size. * @header_only: none zero value indicates that this region does not include * fifo data and includes only the given registers. */ struct iwl_fw_ini_region_cfg_fifos { - __le32 lmac1_id; - __le32 lmac2_id; + __le32 fid1; + __le32 fid2; __le32 num_of_registers; __le32 header_only; } __packed; /* FW_DEBUG_TLV_REGION_FIFOS_S */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index c9a63b2c6c9b..744d831b4dbb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1058,7 +1058,7 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, addr = le32_to_cpu(range->start_addr) + i; prph_val = iwl_read_prph(fwrt->trans, addr + offset); if (prph_val == 0x5a5a5a5a) - return -1; + return -EBUSY; *val++ = cpu_to_le32(prph_val); } @@ -1150,7 +1150,7 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, MON_BUFF_BASE_ADDR_VER2); if (start_addr == 0x5a5a5a5a) - return -1; + return -EBUSY; range->start_addr = cpu_to_le32(start_addr); range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size); @@ -1161,6 +1161,124 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, return sizeof(*range) + le32_to_cpu(range->range_data_size); } +struct iwl_ini_txf_iter_data { + int fifo; + int lmac; + u32 fifo_size; + bool internal_txf; + bool init; +}; + +static bool iwl_ini_txf_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + struct iwl_ini_txf_iter_data *iter = fwrt->dump.fifo_iter; + struct iwl_fwrt_shared_mem_cfg *cfg = &fwrt->smem_cfg; + int txf_num = cfg->num_txfifo_entries; + int int_txf_num = ARRAY_SIZE(cfg->internal_txfifo_size); + u32 lmac_bitmap = le32_to_cpu(reg->fifos.fid1); + + if (!iter) + return false; + + if (iter->init) { + if (le32_to_cpu(reg->offset) && + WARN_ONCE(cfg->num_lmacs == 1, + "Invalid lmac offset: 0x%x\n", + le32_to_cpu(reg->offset))) + return false; + + iter->init = false; + iter->internal_txf = false; + iter->fifo_size = 0; + iter->fifo = -1; + if (le32_to_cpu(reg->offset)) + iter->lmac = 1; + else + iter->lmac = 0; + } + + if (!iter->internal_txf) + for (iter->fifo++; iter->fifo < txf_num; iter->fifo++) { + iter->fifo_size = + cfg->lmac[iter->lmac].txfifo_size[iter->fifo]; + if (iter->fifo_size && (lmac_bitmap & BIT(iter->fifo))) + return true; + } + + iter->internal_txf = true; + + if (!fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) + return false; + + for (iter->fifo++; iter->fifo < int_txf_num + txf_num; iter->fifo++) { + iter->fifo_size = + cfg->internal_txfifo_size[iter->fifo - txf_num]; + if (iter->fifo_size && (lmac_bitmap & BIT(iter->fifo))) + return true; + } + + return false; +} + +static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *range_ptr, int idx) +{ + struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr; + struct iwl_ini_txf_iter_data *iter; + u32 offs = le32_to_cpu(reg->offset), addr; + u32 registers_size = + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); + __le32 *val = range->data; + unsigned long flags; + int i; + + if (!iwl_ini_txf_iter(fwrt, reg)) + return -EIO; + + if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) + return -EBUSY; + + iter = fwrt->dump.fifo_iter; + + range->fifo_num = cpu_to_le32(iter->fifo); + range->num_of_registers = reg->fifos.num_of_registers; + range->range_data_size = cpu_to_le32(iter->fifo_size + registers_size); + + iwl_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo); + + /* read txf registers */ + for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) { + addr = le32_to_cpu(reg->start_addr[i]) + offs; + + *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + } + + if (reg->fifos.header_only) { + range->range_data_size = cpu_to_le32(registers_size); + goto out; + } + + /* Set the TXF_READ_MODIFY_ADDR to TXF_WR_PTR */ + iwl_write_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_ADDR + offs, + TXF_WR_PTR + offs); + + /* Dummy-read to advance the read pointer to the head */ + iwl_read_prph_no_grab(fwrt->trans, TXF_READ_MODIFY_DATA + offs); + + /* Read FIFO */ + addr = TXF_READ_MODIFY_DATA + offs; + for (i = 0; i < iter->fifo_size; i += sizeof(__le32)) + *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + +out: + iwl_trans_release_nic_access(fwrt->trans, &flags); + + return sizeof(*range) + le32_to_cpu(range->range_data_size); +} + static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg, void *data) @@ -1195,6 +1313,15 @@ static void return mon_dump->ranges; } +static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *data) +{ + struct iwl_fw_ini_fifo_error_dump *dump = data; + + return dump->ranges; +} + static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { @@ -1219,6 +1346,22 @@ static u32 iwl_dump_ini_mon_dram_ranges(struct iwl_fw_runtime *fwrt, return 1; } +static u32 iwl_dump_ini_txf_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + struct iwl_ini_txf_iter_data iter = { .init = true }; + void *fifo_iter = fwrt->dump.fifo_iter; + u32 num_of_fifos = 0; + + fwrt->dump.fifo_iter = &iter; + while (iwl_ini_txf_iter(fwrt, reg)) + num_of_fifos++; + + fwrt->dump.fifo_iter = fifo_iter; + + return num_of_fifos; +} + static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { @@ -1266,6 +1409,30 @@ static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, return size; } +static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + struct iwl_ini_txf_iter_data iter = { .init = true }; + void *fifo_iter = fwrt->dump.fifo_iter; + u32 size = 0; + u32 fifo_hdr = sizeof(struct iwl_fw_ini_fifo_error_dump_range) + + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); + + fwrt->dump.fifo_iter = &iter; + while (iwl_ini_txf_iter(fwrt, reg)) { + size += fifo_hdr; + if (!reg->fifos.header_only) + size += iter.fifo_size; + } + + if (size) + size += sizeof(struct iwl_fw_ini_fifo_error_dump); + + fwrt->dump.fifo_iter = fifo_iter; + + return size; +} + /** * struct iwl_dump_ini_mem_ops - ini memory dump operations * @get_num_of_ranges: returns the number of memory ranges in the region. @@ -1273,7 +1440,7 @@ static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, * @fill_mem_hdr: fills region type specific headers and returns pointer to * the first range or NULL if failed to fill headers. * @fill_range: copies a given memory range into the dump. - * Returns the size of the range or -1 otherwise. + * Returns the size of the range or negative error value otherwise. */ struct iwl_dump_ini_mem_ops { u32 (*get_num_of_ranges)(struct iwl_fw_runtime *fwrt, @@ -1369,7 +1536,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_TXF: - size += iwl_fw_txf_len(fwrt, &fwrt->smem_cfg); + size += hdr_len + iwl_dump_ini_txf_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_RXF: size += iwl_fw_rxf_len(fwrt, &fwrt->smem_cfg); @@ -1463,9 +1630,19 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; } - case IWL_FW_INI_REGION_TXF: - iwl_fw_dump_txf(fwrt, data); + case IWL_FW_INI_REGION_TXF: { + struct iwl_ini_txf_iter_data iter = { .init = true }; + void *fifo_iter = fwrt->dump.fifo_iter; + + fwrt->dump.fifo_iter = &iter; + ops.get_num_of_ranges = iwl_dump_ini_txf_ranges; + ops.get_size = iwl_dump_ini_txf_get_size; + ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header; + ops.fill_range = iwl_dump_ini_txf_iter; + iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + fwrt->dump.fifo_iter = fifo_iter; break; + } case IWL_FW_INI_REGION_RXF: iwl_fw_dump_rxf(fwrt, data); break; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 063f2b925808..2cc4f13d0abb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -8,7 +8,7 @@ * Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -308,6 +308,31 @@ struct iwl_fw_ini_error_dump { struct iwl_fw_ini_error_dump_range ranges[]; } __packed; +/** + * struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump + * @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to + * distinguish between lmac and umac + * @num_of_registers: num of registers to dump, dword size each + * @range_data_size: the size of the registers and fifo data + * @data: fifo data + */ +struct iwl_fw_ini_fifo_error_dump_range { + __le32 fifo_num; + __le32 num_of_registers; + __le32 range_data_size; + __le32 data[]; +} __packed; + +/** + * struct iwl_fw_ini_fifo_error_dump - ini fifo region dump + * @header: the header of this region + * @ranges: the memory ranges of this region + */ +struct iwl_fw_ini_fifo_error_dump { + struct iwl_fw_ini_error_dump_header header; + struct iwl_fw_ini_fifo_error_dump_range ranges[]; +} __packed; + /** * struct iwl_fw_error_dump_rb - content of an Receive Buffer * @index: the index of the Receive Buffer in the Rx queue diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 6e843998d1c8..a5fe1a8ca426 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -144,6 +144,7 @@ struct iwl_fw_runtime { struct iwl_fw_ini_active_triggers active_trigs[IWL_FW_TRIGGER_ID_NUM]; u32 lmac_err_id[MAX_NUM_LMAC]; u32 umac_err_id; + void *fifo_iter; } dump; #ifdef CONFIG_IWLWIFI_DEBUGFS struct { -- cgit v1.2.3 From 8d7dea25ada762f68d9522fb070a7cf6935cf822 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 27 Jan 2019 11:22:21 +0200 Subject: iwlwifi: dbg_ini: implement Rx fifos dump Implement Rx fifos dump in the new dump mechanism. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 133 ++++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 3 + 2 files changed, 134 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 744d831b4dbb..f119c49cd39c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1279,6 +1279,105 @@ out: return sizeof(*range) + le32_to_cpu(range->range_data_size); } +struct iwl_ini_rxf_data { + u32 fifo_num; + u32 size; + u32 offset; +}; + +static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + struct iwl_ini_rxf_data *data) +{ + u32 fid1 = le32_to_cpu(reg->fifos.fid1); + u32 fid2 = le32_to_cpu(reg->fifos.fid2); + u32 fifo_idx; + + if (!data) + return; + + memset(data, 0, sizeof(*data)); + + if (WARN_ON_ONCE((fid1 && fid2) || (!fid1 && !fid2))) + return; + + fifo_idx = ffs(fid1) - 1; + if (fid1 && !WARN_ON_ONCE((~BIT(fifo_idx) & fid1) || + fifo_idx >= MAX_NUM_LMAC)) { + data->size = fwrt->smem_cfg.lmac[fifo_idx].rxfifo1_size; + data->fifo_num = fifo_idx; + return; + } + + fifo_idx = ffs(fid2) - 1; + if (fid2 && !WARN_ON_ONCE(fifo_idx != 0)) { + data->size = fwrt->smem_cfg.rxfifo2_size; + data->offset = RXF_DIFF_FROM_PREV; + /* use bit 31 to distinguish between umac and lmac rxf while + * parsing the dump + */ + data->fifo_num = fifo_idx | IWL_RXF_UMAC_BIT; + return; + } +} + +static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *range_ptr, int idx) +{ + struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr; + struct iwl_ini_rxf_data rxf_data; + u32 offs = le32_to_cpu(reg->offset), addr; + u32 registers_size = + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); + __le32 *val = range->data; + unsigned long flags; + int i; + + iwl_ini_get_rxf_data(fwrt, reg, &rxf_data); + if (!rxf_data.size) + return -EIO; + + if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) + return -EBUSY; + + offs += rxf_data.offset; + + range->fifo_num = cpu_to_le32(rxf_data.fifo_num); + range->num_of_registers = reg->fifos.num_of_registers; + range->range_data_size = cpu_to_le32(rxf_data.size + registers_size); + + /* read rxf registers */ + for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) { + addr = le32_to_cpu(reg->start_addr[i]) + offs; + + *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + } + + if (reg->fifos.header_only) { + range->range_data_size = cpu_to_le32(registers_size); + goto out; + } + + /* Lock fence */ + iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1); + /* Set fence pointer to the same place like WR pointer */ + iwl_write_prph_no_grab(fwrt->trans, RXF_LD_WR2FENCE + offs, 0x1); + /* Set fence offset */ + iwl_write_prph_no_grab(fwrt->trans, RXF_LD_FENCE_OFFSET_ADDR + offs, + 0x0); + + /* Read FIFO */ + addr = RXF_FIFO_RD_FENCE_INC + offs; + for (i = 0; i < rxf_data.size; i += sizeof(__le32)) + *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + +out: + iwl_trans_release_nic_access(fwrt->trans, &flags); + + return sizeof(*range) + le32_to_cpu(range->range_data_size); +} + static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg, void *data) @@ -1362,6 +1461,15 @@ static u32 iwl_dump_ini_txf_ranges(struct iwl_fw_runtime *fwrt, return num_of_fifos; } +static u32 iwl_dump_ini_rxf_ranges(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + /* Each Rx fifo needs a different offset and therefore, it's + * region can contain only one fifo, i.e. 1 memory range. + */ + return 1; +} + static u32 iwl_dump_ini_mem_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { @@ -1433,6 +1541,23 @@ static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt, return size; } +static u32 iwl_dump_ini_rxf_get_size(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + struct iwl_ini_rxf_data rx_data; + u32 size = sizeof(struct iwl_fw_ini_fifo_error_dump) + + sizeof(struct iwl_fw_ini_fifo_error_dump_range) + + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); + + if (reg->fifos.header_only) + return size; + + iwl_ini_get_rxf_data(fwrt, reg, &rx_data); + size += rx_data.size; + + return size; +} + /** * struct iwl_dump_ini_mem_ops - ini memory dump operations * @get_num_of_ranges: returns the number of memory ranges in the region. @@ -1539,7 +1664,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, size += hdr_len + iwl_dump_ini_txf_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_RXF: - size += iwl_fw_rxf_len(fwrt, &fwrt->smem_cfg); + size += hdr_len + iwl_dump_ini_rxf_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_PAGING: { size += hdr_len; @@ -1644,7 +1769,11 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, break; } case IWL_FW_INI_REGION_RXF: - iwl_fw_dump_rxf(fwrt, data); + ops.get_num_of_ranges = iwl_dump_ini_rxf_ranges; + ops.get_size = iwl_dump_ini_rxf_get_size; + ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header; + ops.fill_range = iwl_dump_ini_rxf_iter; + iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; case IWL_FW_INI_REGION_CSR: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 2cc4f13d0abb..9b5077bd46c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -308,6 +308,9 @@ struct iwl_fw_ini_error_dump { struct iwl_fw_ini_error_dump_range ranges[]; } __packed; +/* This bit is used to differentiate between lmac and umac rxf */ +#define IWL_RXF_UMAC_BIT BIT(31) + /** * struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump * @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to -- cgit v1.2.3 From 3941310cf665b8a7965424d2a185c80782faa030 Mon Sep 17 00:00:00 2001 From: Ihab Zhaika Date: Mon, 4 Feb 2019 10:16:03 +0200 Subject: iwlwifi: add new card for 9260 series Add one PCI ID for 9260 series. CC: # 4.14+ Signed-off-by: Ihab Zhaika Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index b839a921cec8..fb7a0def9355 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -597,6 +597,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x4018, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x401C, iwl9260_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_160_cfg_soc)}, -- cgit v1.2.3 From 085486de833e383705bce61dbde8d31077f5b8ca Mon Sep 17 00:00:00 2001 From: Ihab Zhaika Date: Sun, 3 Feb 2019 18:54:01 +0200 Subject: iwlwifi: add new cards for 22000 and killer series and change the market name Add a few PCI ID'S for 22000 and killer series in addition to chainging the marketing name. Signed-off-by: Ihab Zhaika Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 8 +- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 98 ++++++++++++++----------- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 4 +- 4 files changed, 64 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 2d472a04807f..fdc56f821b5a 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -223,8 +223,8 @@ const struct iwl_cfg iwl22000_2ac_cfg_jf = { IWL_DEVICE_22500, }; -const struct iwl_cfg iwl22560_2ax_cfg_hr = { - .name = "Intel(R) Wireless-AX 22560", +const struct iwl_cfg iwl_ax101_cfg_qu_hr = { + .name = "Intel(R) Wi-Fi 6 AX101", .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* @@ -249,7 +249,7 @@ const struct iwl_cfg iwl22260_2ax_cfg = { }; const struct iwl_cfg killer1650x_2ax_cfg = { - .name = "Killer(R) Wireless-AX 1650x Wireless Network Adapter (22260NGW)", + .name = "Killer(R) Wireless-AX 1650x Wireless Network Adapter (200NGW)", .fw_name_pre = IWL_CC_A_FW_PRE, IWL_DEVICE_22500, /* @@ -262,7 +262,7 @@ const struct iwl_cfg killer1650x_2ax_cfg = { }; const struct iwl_cfg killer1650w_2ax_cfg = { - .name = "Killer(R) Wireless-AX 1650w Wireless Network Adapter (22260D2W)", + .name = "Killer(R) Wireless-AX 1650w Wireless Network Adapter (200D2W)", .fw_name_pre = IWL_CC_A_FW_PRE, IWL_DEVICE_22500, /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 7f2fa5cc8c2c..f5f87773667b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -548,7 +548,7 @@ extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl22000_2ac_cfg_hr; extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; extern const struct iwl_cfg iwl22000_2ac_cfg_jf; -extern const struct iwl_cfg iwl22560_2ax_cfg_hr; +extern const struct iwl_cfg iwl_ax101_cfg_qu_hr; extern const struct iwl_cfg iwl22000_2ax_cfg_hr; extern const struct iwl_cfg iwl22260_2ax_cfg; extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index fb7a0def9355..2b94e4cef56c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -517,6 +517,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x02F0, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x0040, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x0044, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x02F0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -525,6 +527,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x02F0, 0x0234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x0238, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x023C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x02F0, 0x0244, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x02F0, 0x0260, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x02F0, 0x02A0, iwl9462_2ac_cfg_soc)}, @@ -542,6 +545,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x06F0, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x0040, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0044, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x06F0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -550,6 +555,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x06F0, 0x0234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0238, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x023C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x06F0, 0x0244, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x06F0, 0x0260, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x06F0, 0x02A0, iwl9462_2ac_cfg_soc)}, @@ -615,6 +621,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2720, 0x0034, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2720, 0x0038, iwl9560_2ac_160_cfg)}, {IWL_PCI_DEVICE(0x2720, 0x003C, iwl9560_2ac_160_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x0044, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -623,6 +630,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2720, 0x0234, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2720, 0x0238, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2720, 0x023C, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x0244, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0260, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_soc)}, @@ -700,6 +708,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x003C, iwl9560_2ac_160_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x0044, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x34F0, 0x0060, iwl9461_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0064, iwl9461_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x00A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, @@ -708,6 +717,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x34F0, 0x0234, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0238, iwl9560_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x023C, iwl9560_2ac_cfg_qu_b0_jf_b0)}, + {IWL_PCI_DEVICE(0x34F0, 0x0244, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x34F0, 0x0260, iwl9461_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x0264, iwl9461_2ac_cfg_qu_b0_jf_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x02A0, iwl9462_2ac_cfg_qu_b0_jf_b0)}, @@ -754,6 +764,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x43F0, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0044, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x43F0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -762,6 +773,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x43F0, 0x0234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x0238, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x023C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0244, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x43F0, 0x0260, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x43F0, 0x02A0, iwl9462_2ac_cfg_soc)}, @@ -821,6 +833,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_160_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_160_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0044, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x0060, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x00A0, iwl9462_2ac_cfg_soc)}, @@ -829,6 +842,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA0F0, 0x0234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x0238, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x023C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0244, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x0260, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA0F0, 0x02A0, iwl9462_2ac_cfg_soc)}, @@ -876,73 +890,75 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2720, 0x0030, iwl9560_2ac_cfg_qnj_jf_b0)}, /* 22000 Series */ - {IWL_PCI_DEVICE(0x02F0, 0x0070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x02F0, 0x0074, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x02F0, 0x0078, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x02F0, 0x007C, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x02F0, 0x0310, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x0070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x0074, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x0078, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x007C, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x0310, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x02F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x02F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, - {IWL_PCI_DEVICE(0x02F0, 0x4070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x06F0, 0x0070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x06F0, 0x0074, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x06F0, 0x0078, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x06F0, 0x007C, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x06F0, 0x0310, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x02F0, 0x4070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0074, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0078, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x007C, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x0310, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x06F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x06F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, - {IWL_PCI_DEVICE(0x06F0, 0x4070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0000, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0040, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x06F0, 0x4070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0000, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0040, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0070, iwl22000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x2720, 0x0074, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x0078, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x2720, 0x007C, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0074, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x0078, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x007C, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0310, iwl22000_2ac_cfg_hr_cdb)}, {IWL_PCI_DEVICE(0x2720, 0x0A10, iwl22000_2ac_cfg_hr_cdb)}, - {IWL_PCI_DEVICE(0x2720, 0x1080, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x1080, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2720, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x2720, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, - {IWL_PCI_DEVICE(0x2720, 0x4070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0074, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x007C, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x2720, 0x4070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0040, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0074, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0078, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x007C, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x0310, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, - {IWL_PCI_DEVICE(0x34F0, 0x4070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x34F0, 0x4070, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x40C0, 0x0000, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40C0, 0x0010, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40c0, 0x0090, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40C0, 0x0310, iwl22560_2ax_cfg_su_cdb)}, {IWL_PCI_DEVICE(0x40C0, 0x0A10, iwl22560_2ax_cfg_su_cdb)}, - {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x43F0, 0x0074, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0x43F0, 0x007C, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x0040, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x0070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x0074, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x0078, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x007C, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, - {IWL_PCI_DEVICE(0x43F0, 0x4070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0074, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x007C, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl22560_2ax_cfg_hr)}, - {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0x43F0, 0x4070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0000, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0040, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0070, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0074, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0078, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x007C, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x00B0, iwl_ax101_cfg_qu_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0A10, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0xA0F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0)}, {IWL_PCI_DEVICE(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)}, - {IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl22560_2ax_cfg_hr)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl_ax101_cfg_qu_hr)}, {IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)}, {IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)}, {IWL_PCI_DEVICE(0x2723, 0x0088, iwl22260_2ax_cfg)}, {IWL_PCI_DEVICE(0x2723, 0x008C, iwl22260_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x1653, killer1650w_2ax_cfg)}, + {IWL_PCI_DEVICE(0x2723, 0x1654, killer1650x_2ax_cfg)}, {IWL_PCI_DEVICE(0x2723, 0x4080, iwl22260_2ax_cfg)}, {IWL_PCI_DEVICE(0x2723, 0x4088, iwl22260_2ax_cfg)}, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index e2579a0bcc25..fe8269d023de 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3540,10 +3540,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { trans->cfg = &iwlax210_2ax_cfg_so_gf_a0; } - } else if (cfg == &iwl22560_2ax_cfg_hr) { + } else if (cfg == &iwl_ax101_cfg_qu_hr) { if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { - trans->cfg = &iwl22560_2ax_cfg_hr; + trans->cfg = &iwl_ax101_cfg_qu_hr; } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { trans->cfg = &iwl22000_2ax_cfg_jf; -- cgit v1.2.3 From 29f000f7751e3c7f4d26decfe5094090504fd8ba Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 16 Feb 2019 20:44:16 +0100 Subject: net: phy: disable aneg in genphy_c45_pma_setup_forced When genphy_c45_pma_setup_forced() is called the "aneg enabled" bit may still be set, therefore clear it. This is also in line with what genphy_setup_forced() does for Clause 22. v2: - fix typo Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 1cf5e8ae46de..16636d49bd14 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -70,7 +70,11 @@ int genphy_c45_pma_setup_forced(struct phy_device *phydev) if (ret < 0) return ret; - return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2); + ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2); + if (ret < 0) + return ret; + + return genphy_c45_an_disable_aneg(phydev); } EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced); -- cgit v1.2.3 From 30de65c3d5a3559abc80d4b508c646438c06790c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 16 Feb 2019 20:44:59 +0100 Subject: net: phy: marvell10g: improve mv3310_config_aneg Now that genphy_c45_pma_setup_forced() makes sure the "aneg enabled" bit is cleared, the call to genphy_c45_an_disable_aneg() isn't needed any longer. And the code pattern is now the same as in genphy_config_aneg(). Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index f9e0a2fc0277..9ea27acf05ad 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -268,13 +268,8 @@ static int mv3310_config_aneg(struct phy_device *phydev) /* We don't support manual MDI control */ phydev->mdix_ctrl = ETH_TP_MDI_AUTO; - if (phydev->autoneg == AUTONEG_DISABLE) { - ret = genphy_c45_pma_setup_forced(phydev); - if (ret < 0) - return ret; - - return genphy_c45_an_disable_aneg(phydev); - } + if (phydev->autoneg == AUTONEG_DISABLE) + return genphy_c45_pma_setup_forced(phydev); ret = genphy_c45_an_config_aneg(phydev); if (ret < 0) -- cgit v1.2.3 From 64ccfd2dbbdff4946e114e36cb8d58f432cccc50 Mon Sep 17 00:00:00 2001 From: Vishal Kulkarni Date: Sun, 17 Feb 2019 09:45:30 +0530 Subject: cxgb4: Mask out interrupts that are not enabled. There are rare cases where a PL_INT_CAUSE bit may end up getting set when the corresponding PL_INT_ENABLE bit isn't set. Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 27af347be4af..49e4374d584c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -4962,7 +4962,13 @@ static void pl_intr_handler(struct adapter *adap) */ int t4_slow_intr_handler(struct adapter *adapter) { - u32 cause = t4_read_reg(adapter, PL_INT_CAUSE_A); + /* There are rare cases where a PL_INT_CAUSE bit may end up getting + * set when the corresponding PL_INT_ENABLE bit isn't set. It's + * easiest just to mask that case here. + */ + u32 raw_cause = t4_read_reg(adapter, PL_INT_CAUSE_A); + u32 enable = t4_read_reg(adapter, PL_INT_ENABLE_A); + u32 cause = raw_cause & enable; if (!(cause & GLBL_INTR_MASK)) return 0; @@ -5014,7 +5020,7 @@ int t4_slow_intr_handler(struct adapter *adapter) ulptx_intr_handler(adapter); /* Clear the interrupts just processed for which we are the master. */ - t4_write_reg(adapter, PL_INT_CAUSE_A, cause & GLBL_INTR_MASK); + t4_write_reg(adapter, PL_INT_CAUSE_A, raw_cause & GLBL_INTR_MASK); (void)t4_read_reg(adapter, PL_INT_CAUSE_A); /* flush */ return 1; } -- cgit v1.2.3 From 0ebcebbef1cc50fb94ae17917208b04868de9c38 Mon Sep 17 00:00:00 2001 From: Sudarsana Reddy Kalluru Date: Thu, 21 Feb 2019 06:03:31 -0800 Subject: qed: Read device port count from the shmem Read port count from the shared memory instead of driver deriving this value. This change simplifies the driver implementation and also avoids any dependencies for finding the port-count. Signed-off-by: Sudarsana Reddy Kalluru Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 6 +- drivers/net/ethernet/qlogic/qed/qed_dev.c | 95 ++++++++++++------------------- drivers/net/ethernet/qlogic/qed/qed_l2.c | 4 +- drivers/net/ethernet/qlogic/qed/qed_mcp.h | 4 -- drivers/net/ethernet/qlogic/qed/qed_ptp.c | 2 +- 5 files changed, 44 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 2d21c94f19c2..43a57ec296fd 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -753,6 +753,7 @@ struct qed_dev { #define CHIP_BOND_ID_SHIFT 0 u8 num_engines; + u8 num_ports; u8 num_ports_in_engine; u8 num_funcs_in_port; @@ -892,7 +893,6 @@ void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, void qed_clean_wfq_db(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); int qed_device_num_engines(struct qed_dev *cdev); -int qed_device_get_port_id(struct qed_dev *cdev); void qed_set_fw_mac_addr(__le16 *fw_msb, __le16 *fw_mid, __le16 *fw_lsb, u8 *mac); @@ -939,6 +939,10 @@ bool qed_edpm_enabled(struct qed_hwfn *p_hwfn); writel((u32)val, (void __iomem *)((u8 __iomem *)\ (cdev->doorbells) + (db_addr))) +#define MFW_PORT(_p_hwfn) ((_p_hwfn)->abs_pf_id % \ + qed_device_num_ports((_p_hwfn)->cdev)) +int qed_device_num_ports(struct qed_dev *cdev); + /* Prototypes */ int qed_fill_dev_info(struct qed_dev *cdev, struct qed_dev_info *dev_info); diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index e2cbd77646a2..9df8c4b3b54e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -3269,55 +3269,43 @@ static void qed_get_num_funcs(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) p_hwfn->enabled_func_idx, p_hwfn->num_funcs_on_engine); } -static void qed_hw_info_port_num_bb(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt) -{ - u32 port_mode; - - port_mode = qed_rd(p_hwfn, p_ptt, CNIG_REG_NW_PORT_MODE_BB); - - if (port_mode < 3) { - p_hwfn->cdev->num_ports_in_engine = 1; - } else if (port_mode <= 5) { - p_hwfn->cdev->num_ports_in_engine = 2; - } else { - DP_NOTICE(p_hwfn, "PORT MODE: %d not supported\n", - p_hwfn->cdev->num_ports_in_engine); - - /* Default num_ports_in_engine to something */ - p_hwfn->cdev->num_ports_in_engine = 1; - } -} - -static void qed_hw_info_port_num_ah(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt) +static void qed_hw_info_port_num(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 port; - int i; - - p_hwfn->cdev->num_ports_in_engine = 0; + u32 addr, global_offsize, global_addr, port_mode; + struct qed_dev *cdev = p_hwfn->cdev; - for (i = 0; i < MAX_NUM_PORTS_K2; i++) { - port = qed_rd(p_hwfn, p_ptt, - CNIG_REG_NIG_PORT0_CONF_K2 + (i * 4)); - if (port & 1) - p_hwfn->cdev->num_ports_in_engine++; + /* In CMT there is always only one port */ + if (cdev->num_hwfns > 1) { + cdev->num_ports_in_engine = 1; + cdev->num_ports = 1; + return; } - if (!p_hwfn->cdev->num_ports_in_engine) { - DP_NOTICE(p_hwfn, "All NIG ports are inactive\n"); - - /* Default num_ports_in_engine to something */ - p_hwfn->cdev->num_ports_in_engine = 1; + /* Determine the number of ports per engine */ + port_mode = qed_rd(p_hwfn, p_ptt, MISC_REG_PORT_MODE); + switch (port_mode) { + case 0x0: + cdev->num_ports_in_engine = 1; + break; + case 0x1: + cdev->num_ports_in_engine = 2; + break; + case 0x2: + cdev->num_ports_in_engine = 4; + break; + default: + DP_NOTICE(p_hwfn, "Unknown port mode 0x%08x\n", port_mode); + cdev->num_ports_in_engine = 1; /* Default to something */ + break; } -} -static void qed_hw_info_port_num(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) -{ - if (QED_IS_BB(p_hwfn->cdev)) - qed_hw_info_port_num_bb(p_hwfn, p_ptt); - else - qed_hw_info_port_num_ah(p_hwfn, p_ptt); + /* Get the total number of ports of the device */ + addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, + PUBLIC_GLOBAL); + global_offsize = qed_rd(p_hwfn, p_ptt, addr); + global_addr = SECTION_ADDR(global_offsize, 0); + addr = global_addr + offsetof(struct public_global, max_ports); + cdev->num_ports = (u8)qed_rd(p_hwfn, p_ptt, addr); } static void qed_get_eee_caps(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) @@ -3355,7 +3343,8 @@ qed_get_hw_info(struct qed_hwfn *p_hwfn, return rc; } - qed_hw_info_port_num(p_hwfn, p_ptt); + if (IS_LEAD_HWFN(p_hwfn)) + qed_hw_info_port_num(p_hwfn, p_ptt); qed_mcp_get_capabilities(p_hwfn, p_ptt); @@ -4760,23 +4749,9 @@ void qed_clean_wfq_db(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) sizeof(*p_hwfn->qm_info.wfq_data) * p_hwfn->qm_info.num_vports); } -int qed_device_num_engines(struct qed_dev *cdev) -{ - return QED_IS_BB(cdev) ? 2 : 1; -} - -static int qed_device_num_ports(struct qed_dev *cdev) -{ - /* in CMT always only one port */ - if (cdev->num_hwfns > 1) - return 1; - - return cdev->num_ports_in_engine * qed_device_num_engines(cdev); -} - -int qed_device_get_port_id(struct qed_dev *cdev) +int qed_device_num_ports(struct qed_dev *cdev) { - return (QED_LEADING_HWFN(cdev)->abs_pf_id) % qed_device_num_ports(cdev); + return cdev->num_ports; } void qed_set_fw_mac_addr(__le16 *fw_msb, diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 58be1c4c6668..57641728df69 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1898,6 +1898,7 @@ static void _qed_get_vport_stats(struct qed_dev *cdev, struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn) : NULL; + bool b_get_port_stats; if (IS_PF(cdev)) { /* The main vport index is relative first */ @@ -1912,8 +1913,9 @@ static void _qed_get_vport_stats(struct qed_dev *cdev, continue; } + b_get_port_stats = IS_PF(cdev) && IS_LEAD_HWFN(p_hwfn); __qed_get_vport_stats(p_hwfn, p_ptt, stats, fw_vport, - IS_PF(cdev) ? true : false); + b_get_port_stats); out: if (IS_PF(cdev) && p_ptt) diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 2799e6741765..261c1a392e2c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -691,10 +691,6 @@ int qed_mfw_process_tlv_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); rel_pfid) #define MCP_PF_ID(p_hwfn) MCP_PF_ID_BY_REL(p_hwfn, (p_hwfn)->rel_pf_id) -#define MFW_PORT(_p_hwfn) ((_p_hwfn)->abs_pf_id % \ - ((_p_hwfn)->cdev->num_ports_in_engine * \ - qed_device_num_engines((_p_hwfn)->cdev))) - struct qed_mcp_info { /* List for mailbox commands which were sent and wait for a response */ struct list_head cmd_list; diff --git a/drivers/net/ethernet/qlogic/qed/qed_ptp.c b/drivers/net/ethernet/qlogic/qed/qed_ptp.c index 5a90d69dc2f8..1302b308bd87 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ptp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ptp.c @@ -47,7 +47,7 @@ static enum qed_resc_lock qed_ptcdev_to_resc(struct qed_hwfn *p_hwfn) { - switch (qed_device_get_port_id(p_hwfn->cdev)) { + switch (MFW_PORT(p_hwfn)) { case 0: return QED_RESC_LOCK_PTP_PORT0; case 1: -- cgit v1.2.3 From 40d5432cd50edf2b8a8a466a2ad48b487fec17f6 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 18 Feb 2019 20:28:54 +0100 Subject: net: phy: remove orphaned register read in genphy_read_status After recent changes to genphy_read_status() this orphaned register read remained as leftover. So remove it. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 7e71124bb20e..803197fdd87d 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1785,10 +1785,6 @@ int genphy_read_status(struct phy_device *phydev) mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa); - adv = phy_read(phydev, MII_ADVERTISE); - if (adv < 0) - return adv; - phydev->speed = SPEED_10; phydev->duplex = DUPLEX_HALF; phydev->pause = 0; -- cgit v1.2.3 From 51f9f234dac5284333a047b7906f3095d410e6c3 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 18 Feb 2019 20:29:36 +0100 Subject: net: phy: don't use 10BaseT/half as default in genphy_read_status If link partner and we can't agree on any mode, then it doesn't make sense to pretend we would have agreed on 10/half. Therefore set a proper default. Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 803197fdd87d..4bb3b6c2894e 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1785,8 +1785,8 @@ int genphy_read_status(struct phy_device *phydev) mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa); - phydev->speed = SPEED_10; - phydev->duplex = DUPLEX_HALF; + phydev->speed = SPEED_UNKNOWN; + phydev->duplex = DUPLEX_UNKNOWN; phydev->pause = 0; phydev->asym_pause = 0; -- cgit v1.2.3 From cd34499cacf3c34e2e094ff2a347b9378417970c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 18 Feb 2019 21:26:58 +0100 Subject: net: phy: export genphy_config_eee_advert We want to use this function in phy-c45.c too, therefore export it. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 3 ++- include/linux/phy.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 4bb3b6c2894e..49fdd1ee798e 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1575,7 +1575,7 @@ static int genphy_config_advert(struct phy_device *phydev) * efficent ethernet modes. Returns 0 if the PHY's advertisement hasn't * changed, and 1 if it has changed. */ -static int genphy_config_eee_advert(struct phy_device *phydev) +int genphy_config_eee_advert(struct phy_device *phydev) { int err; @@ -1588,6 +1588,7 @@ static int genphy_config_eee_advert(struct phy_device *phydev) /* If the call failed, we assume that EEE is not supported */ return err < 0 ? 0 : err; } +EXPORT_SYMBOL(genphy_config_eee_advert); /** * genphy_setup_forced - configures/forces speed/duplex from @phydev diff --git a/include/linux/phy.h b/include/linux/phy.h index 3db507e68191..761131de4971 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1077,6 +1077,7 @@ void phy_attached_info(struct phy_device *phydev); int genphy_config_init(struct phy_device *phydev); int genphy_setup_forced(struct phy_device *phydev); int genphy_restart_aneg(struct phy_device *phydev); +int genphy_config_eee_advert(struct phy_device *phydev); int genphy_config_aneg(struct phy_device *phydev); int genphy_aneg_done(struct phy_device *phydev); int genphy_update_link(struct phy_device *phydev); -- cgit v1.2.3 From cc429d529126e5bbe867e839d7de4f75b9daad44 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 18 Feb 2019 21:27:12 +0100 Subject: net: phy: use genphy_config_eee_advert in genphy_c45_an_config_aneg Like in genphy_config_aneg() for clause 22 PHY's, we should keep modes from being advertised that are known to be broken with EEE. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 16636d49bd14..2f5721430e05 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -89,12 +89,14 @@ EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced); */ int genphy_c45_an_config_aneg(struct phy_device *phydev) { - int changed = 0, ret; + int changed, ret; u32 adv; linkmode_and(phydev->advertising, phydev->advertising, phydev->supported); + changed = genphy_config_eee_advert(phydev); + adv = linkmode_adv_to_mii_adv_t(phydev->advertising); ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, -- cgit v1.2.3 From 1af9f16840e920c6193490ae58371fc5cc28bb01 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 18 Feb 2019 21:27:18 +0100 Subject: net: phy: add genphy_c45_check_and_restart_aneg This function will be used by config_aneg callback implementations of PHY drivers and allows to reduce boilerplate code. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 30 ++++++++++++++++++++++++++++++ include/linux/phy.h | 1 + 2 files changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 2f5721430e05..fc3173cc078b 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -156,6 +156,36 @@ int genphy_c45_restart_aneg(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg); +/** + * genphy_c45_check_and_restart_aneg - Enable and restart auto-negotiation + * @phydev: target phy_device struct + * @restart: whether aneg restart is requested + * + * This assumes that the auto-negotiation MMD is present. + * + * Check, and restart auto-negotiation if needed. + */ +int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart) +{ + int ret = 0; + + if (!restart) { + /* Configure and restart aneg if it wasn't set before */ + ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); + if (ret < 0) + return ret; + + if (!(ret & MDIO_AN_CTRL1_ENABLE)) + restart = true; + } + + if (restart) + ret = genphy_c45_restart_aneg(phydev); + + return ret; +} +EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg); + /** * genphy_c45_aneg_done - return auto-negotiation complete status * @phydev: target phy_device struct diff --git a/include/linux/phy.h b/include/linux/phy.h index 761131de4971..8e9fc576472b 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1097,6 +1097,7 @@ int genphy_write_mmd_unsupported(struct phy_device *phdev, int devnum, /* Clause 45 PHY */ int genphy_c45_restart_aneg(struct phy_device *phydev); +int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart); int genphy_c45_aneg_done(struct phy_device *phydev); int genphy_c45_read_link(struct phy_device *phydev); int genphy_c45_read_lpa(struct phy_device *phydev); -- cgit v1.2.3 From 6b4cb6cb1385337d72a2bc0bd3b264f54a7bfaae Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 18 Feb 2019 21:27:46 +0100 Subject: net: phy: marvell10g: use genphy_c45_check_and_restart_aneg in mv3310_config_aneg Use new function genphy_c45_check_and_restart_aneg() to reduce boilerplate code. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 9ea27acf05ad..586ae1bc5a50 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -288,20 +288,7 @@ static int mv3310_config_aneg(struct phy_device *phydev) if (ret > 0) changed = true; - if (!changed) { - /* Configure and restart aneg if it wasn't set before */ - ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); - if (ret < 0) - return ret; - - if (!(ret & MDIO_AN_CTRL1_ENABLE)) - changed = 1; - } - - if (changed) - ret = genphy_c45_restart_aneg(phydev); - - return ret; + return genphy_c45_check_and_restart_aneg(phydev, changed); } static int mv3310_aneg_done(struct phy_device *phydev) -- cgit v1.2.3 From 4f85901f0063e6f435125f8eb54d12e3108ab064 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 20 Feb 2019 15:35:05 -0800 Subject: net: dsa: mv88e6xxx: add support for bridge flags Add support for the bridge flags to Marvell 88e6xxx bridges, allowing the multicast and unicast flood properties to be controlled. These can be controlled on a per-port basis via commands such as: bridge link set dev lan1 flood on|off bridge link set dev lan1 mcast_flood on|off Reviewed-by: Florian Fainelli Reviewed-by: Vivien Didelot Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 32e7af5caa69..cc7ce06b6d58 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4692,6 +4692,22 @@ static int mv88e6xxx_port_mdb_del(struct dsa_switch *ds, int port, return err; } +static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port, + bool unicast, bool multicast) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err = -EOPNOTSUPP; + + mutex_lock(&chip->reg_lock); + if (chip->info->ops->port_set_egress_floods) + err = chip->info->ops->port_set_egress_floods(chip, port, + unicast, + multicast); + mutex_unlock(&chip->reg_lock); + + return err; +} + static const struct dsa_switch_ops mv88e6xxx_switch_ops = { #if IS_ENABLED(CONFIG_NET_DSA_LEGACY) .probe = mv88e6xxx_drv_probe, @@ -4719,6 +4735,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .set_ageing_time = mv88e6xxx_set_ageing_time, .port_bridge_join = mv88e6xxx_port_bridge_join, .port_bridge_leave = mv88e6xxx_port_bridge_leave, + .port_egress_floods = mv88e6xxx_port_egress_floods, .port_stp_state_set = mv88e6xxx_port_stp_state_set, .port_fast_age = mv88e6xxx_port_fast_age, .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, -- cgit v1.2.3 From c19c44f867ca3c0bb3b820c9234590dbd0f7afbe Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Feb 2019 16:58:20 -0800 Subject: mlxsw: spectrum: Handle PORT_PRE_BRIDGE_FLAGS In preparation for getting rid of switchdev_port_attr_get(), have mlxsw check for the bridge flags being set through switchdev_port_attr_set() when the SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS attribute identifier is used. Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 1f492b7dbea8..9a8798f74d2b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -595,6 +595,17 @@ err_port_bridge_vlan_learning_set: return err; } +static int mlxsw_sp_port_attr_br_pre_flags_set(struct mlxsw_sp_port + *mlxsw_sp_port, + struct switchdev_trans *trans, + unsigned long brport_flags) +{ + if (brport_flags & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) + return -EINVAL; + + return 0; +} + static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, struct switchdev_trans *trans, struct net_device *orig_dev, @@ -841,6 +852,11 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev, attr->orig_dev, attr->u.stp_state); break; + case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: + err = mlxsw_sp_port_attr_br_pre_flags_set(mlxsw_sp_port, + trans, + attr->u.brport_flags); + break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port, trans, attr->orig_dev, -- cgit v1.2.3 From e1230246d0ad7571dba93a136f16e90daad187eb Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Feb 2019 16:58:21 -0800 Subject: staging: fsl-dpaa2: ethsw: Handle PORT_PRE_BRIDGE_FLAGS In preparation for removing SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, handle the SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS attribute and check that the bridge port flags being configured are supported. Signed-off-by: Florian Fainelli Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 1b3943b71254..331625137717 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -666,6 +666,16 @@ static int port_attr_stp_state_set(struct net_device *netdev, return ethsw_port_set_stp_state(port_priv, state); } +static int port_attr_br_flags_pre_set(struct net_device *netdev, + struct switchdev_trans *trans, + unsigned long flags) +{ + if (flags & ~(BR_LEARNING | BR_FLOOD)) + return -EINVAL; + + return 0; +} + static int port_attr_br_flags_set(struct net_device *netdev, struct switchdev_trans *trans, unsigned long flags) @@ -698,6 +708,10 @@ static int swdev_port_attr_set(struct net_device *netdev, err = port_attr_stp_state_set(netdev, trans, attr->u.stp_state); break; + case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: + err = port_attr_br_flags_pre_set(netdev, trans, + attr->u.brport_flags); + break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = port_attr_br_flags_set(netdev, trans, attr->u.brport_flags); -- cgit v1.2.3 From 93700458ff63836ff73d3301e5e98d2e0bb01e98 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Feb 2019 16:58:23 -0800 Subject: rocker: Check Handle PORT_PRE_BRIDGE_FLAGS In preparation for getting rid of switchdev_port_attr_get(), have rocker check for the bridge flags being set through switchdev_port_attr_set() with the SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS attribute identifier. Signed-off-by: Florian Fainelli Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker_main.c | 55 +++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 5ce8d5aba603..25129f7b5583 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -1566,34 +1566,57 @@ static int rocker_world_port_attr_stp_state_set(struct rocker_port *rocker_port, } static int -rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port, - unsigned long brport_flags, - struct switchdev_trans *trans) +rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port * + rocker_port, + unsigned long * + p_brport_flags_support) { struct rocker_world_ops *wops = rocker_port->rocker->wops; + if (!wops->port_attr_bridge_flags_support_get) + return -EOPNOTSUPP; + return wops->port_attr_bridge_flags_support_get(rocker_port, + p_brport_flags_support); +} + +static int +rocker_world_port_attr_pre_bridge_flags_set(struct rocker_port *rocker_port, + unsigned long brport_flags, + struct switchdev_trans *trans) +{ + struct rocker_world_ops *wops = rocker_port->rocker->wops; + unsigned long brport_flags_s; + int err; + if (!wops->port_attr_bridge_flags_set) return -EOPNOTSUPP; - if (switchdev_trans_ph_prepare(trans)) - return 0; + err = rocker_world_port_attr_bridge_flags_support_get(rocker_port, + &brport_flags_s); + if (err) + return err; - return wops->port_attr_bridge_flags_set(rocker_port, brport_flags, - trans); + if (brport_flags & ~brport_flags_s) + return -EINVAL; + + return 0; } static int -rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port * - rocker_port, - unsigned long * - p_brport_flags_support) +rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port, + unsigned long brport_flags, + struct switchdev_trans *trans) { struct rocker_world_ops *wops = rocker_port->rocker->wops; - if (!wops->port_attr_bridge_flags_support_get) + if (!wops->port_attr_bridge_flags_set) return -EOPNOTSUPP; - return wops->port_attr_bridge_flags_support_get(rocker_port, - p_brport_flags_support); + + if (switchdev_trans_ph_prepare(trans)) + return 0; + + return wops->port_attr_bridge_flags_set(rocker_port, brport_flags, + trans); } static int @@ -2074,6 +2097,10 @@ static int rocker_port_attr_set(struct net_device *dev, attr->u.stp_state, trans); break; + case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: + err = rocker_world_port_attr_pre_bridge_flags_set(rocker_port, + attr->u.brport_flags, + trans); case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = rocker_world_port_attr_bridge_flags_set(rocker_port, attr->u.brport_flags, -- cgit v1.2.3 From cc0c207a5d18333fbfecc964a47ddb182fbcb720 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Feb 2019 16:58:25 -0800 Subject: net: Remove SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT Now that we have converted the bridge code and the drivers to check for bridge port(s) flags at the time we try to set them, there is no need for a get() -> set() sequence anymore and SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT therefore becomes unused. Reviewed-by: Ido Schimmel Signed-off-by: Florian Fainelli Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- Documentation/networking/switchdev.txt | 6 ++---- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 11 +---------- drivers/net/ethernet/rocker/rocker_main.c | 14 +------------- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 10 +--------- include/net/switchdev.h | 2 -- net/dsa/slave.c | 16 +--------------- 6 files changed, 6 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index f3244d87512a..79c8b0f16aee 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -232,10 +232,8 @@ Learning_sync attribute enables syncing of the learned/forgotten FDB entry to the bridge's FDB. It's possible, but not optimal, to enable learning on the device port and on the bridge port, and disable learning_sync. -To support learning and learning_sync port attributes, the driver implements -switchdev op switchdev_port_attr_get/set for -SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. The driver should initialize the attributes -to the hardware defaults. +To support learning, the driver implements switchdev op +switchdev_port_attr_get/set for SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. FDB Ageing ^^^^^^^^^^ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 9a8798f74d2b..bbb5a406232e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -434,16 +434,7 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan) static int mlxsw_sp_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD | - BR_MCAST_FLOOD; - break; - default: - return -EOPNOTSUPP; - } - - return 0; + return -EOPNOTSUPP; } static int diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 25129f7b5583..6b8273e2057d 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2069,19 +2069,7 @@ static const struct net_device_ops rocker_port_netdev_ops = { static int rocker_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { - const struct rocker_port *rocker_port = netdev_priv(dev); - int err = 0; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - err = rocker_world_port_attr_bridge_flags_support_get(rocker_port, - &attr->u.brport_flags_support); - break; - default: - return -EOPNOTSUPP; - } - - return err; + return -EOPNOTSUPP; } static int rocker_port_attr_set(struct net_device *dev, diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 331625137717..de4dcabbc29a 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -643,15 +643,7 @@ static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev) static int swdev_port_attr_get(struct net_device *netdev, struct switchdev_attr *attr) { - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD; - break; - default: - return -EOPNOTSUPP; - } - - return 0; + return -EOPNOTSUPP; } static int port_attr_stp_state_set(struct net_device *netdev, diff --git a/include/net/switchdev.h b/include/net/switchdev.h index de72b0a3867f..0f352019ef99 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -45,7 +45,6 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_UNDEFINED, SWITCHDEV_ATTR_ID_PORT_STP_STATE, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, - SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_MROUTER, SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, @@ -63,7 +62,6 @@ struct switchdev_attr { union { u8 stp_state; /* PORT_STP_STATE */ unsigned long brport_flags; /* PORT_{PRE}_BRIDGE_FLAGS */ - unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */ bool mrouter; /* PORT_MROUTER */ clock_t ageing_time; /* BRIDGE_AGEING_TIME */ bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 44cc4e50dd5a..db0a2651070f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -388,21 +388,7 @@ static int dsa_slave_get_port_parent_id(struct net_device *dev, static int dsa_slave_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { - struct dsa_port *dp = dsa_slave_to_port(dev); - struct dsa_switch *ds = dp->ds; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = 0; - if (ds->ops->port_egress_floods) - attr->u.brport_flags_support |= BR_FLOOD | - BR_MCAST_FLOOD; - break; - default: - return -EOPNOTSUPP; - } - - return 0; + return -EOPNOTSUPP; } static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev, -- cgit v1.2.3 From 010c8f01aa7fe18ea97d302e1c7e9ca83bc27433 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 20 Feb 2019 16:58:26 -0800 Subject: net: Get rid of switchdev_port_attr_get() With the bridge no longer calling switchdev_port_attr_get() to obtain the supported bridge port flags from a driver but instead trying to set the bridge port flags directly and relying on driver to reject unsupported configurations, we can effectively get rid of switchdev_port_attr_get() entirely since this was the only place where it was called. Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- Documentation/networking/switchdev.txt | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 7 ------- drivers/net/ethernet/rocker/rocker_main.c | 7 ------- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 7 ------- include/net/switchdev.h | 8 -------- net/dsa/slave.c | 7 ------- 6 files changed, 1 insertion(+), 37 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index 79c8b0f16aee..413abbae952f 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -233,7 +233,7 @@ the bridge's FDB. It's possible, but not optimal, to enable learning on the device port and on the bridge port, and disable learning_sync. To support learning, the driver implements switchdev op -switchdev_port_attr_get/set for SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. +switchdev_port_attr_set for SWITCHDEV_ATTR_PORT_ID_{PRE}_BRIDGE_FLAGS. FDB Ageing ^^^^^^^^^^ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index bbb5a406232e..766f5b5f1cf5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -431,12 +431,6 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan) mlxsw_sp_bridge_vlan_destroy(bridge_vlan); } -static int mlxsw_sp_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static int mlxsw_sp_port_bridge_vlan_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_bridge_vlan *bridge_vlan, @@ -1945,7 +1939,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, } static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { - .switchdev_port_attr_get = mlxsw_sp_port_attr_get, .switchdev_port_attr_set = mlxsw_sp_port_attr_set, }; diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 6b8273e2057d..8200fbf91306 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2066,12 +2066,6 @@ static const struct net_device_ops rocker_port_netdev_ops = { * swdev interface ********************/ -static int rocker_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static int rocker_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans) @@ -2148,7 +2142,6 @@ static int rocker_port_obj_del(struct net_device *dev, } static const struct switchdev_ops rocker_port_switchdev_ops = { - .switchdev_port_attr_get = rocker_port_attr_get, .switchdev_port_attr_set = rocker_port_attr_set, }; diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index de4dcabbc29a..018399ee8731 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -640,12 +640,6 @@ static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev) fsl_mc_free_irqs(sw_dev); } -static int swdev_port_attr_get(struct net_device *netdev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static int port_attr_stp_state_set(struct net_device *netdev, struct switchdev_trans *trans, u8 state) @@ -932,7 +926,6 @@ static int swdev_port_obj_del(struct net_device *netdev, } static const struct switchdev_ops ethsw_port_switchdev_ops = { - .switchdev_port_attr_get = swdev_port_attr_get, .switchdev_port_attr_set = swdev_port_attr_set, }; diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 0f352019ef99..45310ddf2d7e 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -179,8 +179,6 @@ switchdev_notifier_info_to_extack(const struct switchdev_notifier_info *info) #ifdef CONFIG_NET_SWITCHDEV void switchdev_deferred_process(void); -int switchdev_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr); int switchdev_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr); int switchdev_port_obj_add(struct net_device *dev, @@ -225,12 +223,6 @@ static inline void switchdev_deferred_process(void) { } -static inline int switchdev_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static inline int switchdev_port_attr_set(struct net_device *dev, const struct switchdev_attr *attr) { diff --git a/net/dsa/slave.c b/net/dsa/slave.c index db0a2651070f..a78b2bba0332 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -385,12 +385,6 @@ static int dsa_slave_get_port_parent_id(struct net_device *dev, return 0; } -static int dsa_slave_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - return -EOPNOTSUPP; -} - static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev, struct sk_buff *skb) { @@ -1057,7 +1051,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = { }; static const struct switchdev_ops dsa_slave_switchdev_ops = { - .switchdev_port_attr_get = dsa_slave_port_attr_get, .switchdev_port_attr_set = dsa_slave_port_attr_set, }; -- cgit v1.2.3 From 4ccb45857c2c0776d0f72e39768295062c1a0de1 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Tue, 19 Feb 2019 10:38:47 +0100 Subject: net: stmmac: Fix NAPI poll in TX path when in multi-queue Commit 8fce33317023 introduced the concept of NAPI per-channel and independent cleaning of TX path. This is currently breaking performance in some cases. The scenario happens when all packets are being received in Queue 0 but the TX is performed in Queue != 0. Fix this by using different NAPI instances per each TX and RX queue, as suggested by Florian. Changes from v2: - Only force restart transmission if there are pending packets Changes from v1: - Pass entire ring size to TX clean path (Florian) Signed-off-by: Jose Abreu Cc: Florian Fainelli Cc: Joao Pinto Cc: David S. Miller Cc: Giuseppe Cavallaro Cc: Alexandre Torgue Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 5 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 115 +++++++++++++--------- 2 files changed, 68 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index f9b42b0c20f4..dd95d959c1ce 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -79,11 +79,10 @@ struct stmmac_rx_queue { }; struct stmmac_channel { - struct napi_struct napi ____cacheline_aligned_in_smp; + struct napi_struct rx_napi ____cacheline_aligned_in_smp; + struct napi_struct tx_napi ____cacheline_aligned_in_smp; struct stmmac_priv *priv_data; u32 index; - int has_rx; - int has_tx; }; struct stmmac_tc_entry { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f12dd59c85cf..e2a13ec2e30b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -155,7 +155,10 @@ static void stmmac_disable_all_queues(struct stmmac_priv *priv) for (queue = 0; queue < maxq; queue++) { struct stmmac_channel *ch = &priv->channel[queue]; - napi_disable(&ch->napi); + if (queue < rx_queues_cnt) + napi_disable(&ch->rx_napi); + if (queue < tx_queues_cnt) + napi_disable(&ch->tx_napi); } } @@ -173,7 +176,10 @@ static void stmmac_enable_all_queues(struct stmmac_priv *priv) for (queue = 0; queue < maxq; queue++) { struct stmmac_channel *ch = &priv->channel[queue]; - napi_enable(&ch->napi); + if (queue < rx_queues_cnt) + napi_enable(&ch->rx_napi); + if (queue < tx_queues_cnt) + napi_enable(&ch->tx_napi); } } @@ -1955,6 +1961,10 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue) mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); } + /* We still have pending packets, let's call for a new scheduling */ + if (tx_q->dirty_tx != tx_q->cur_tx) + mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(10)); + __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue)); return count; @@ -2045,23 +2055,15 @@ static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan) int status = stmmac_dma_interrupt_status(priv, priv->ioaddr, &priv->xstats, chan); struct stmmac_channel *ch = &priv->channel[chan]; - bool needs_work = false; - - if ((status & handle_rx) && ch->has_rx) { - needs_work = true; - } else { - status &= ~handle_rx; - } - if ((status & handle_tx) && ch->has_tx) { - needs_work = true; - } else { - status &= ~handle_tx; + if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) { + stmmac_disable_dma_irq(priv, priv->ioaddr, chan); + napi_schedule_irqoff(&ch->rx_napi); } - if (needs_work && napi_schedule_prep(&ch->napi)) { + if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) { stmmac_disable_dma_irq(priv, priv->ioaddr, chan); - __napi_schedule(&ch->napi); + napi_schedule_irqoff(&ch->tx_napi); } return status; @@ -2257,8 +2259,14 @@ static void stmmac_tx_timer(struct timer_list *t) ch = &priv->channel[tx_q->queue_index]; - if (likely(napi_schedule_prep(&ch->napi))) - __napi_schedule(&ch->napi); + /* + * If NAPI is already running we can miss some events. Let's rearm + * the timer and try again. + */ + if (likely(napi_schedule_prep(&ch->tx_napi))) + __napi_schedule(&ch->tx_napi); + else + mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(10)); } /** @@ -3514,7 +3522,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) else skb->ip_summed = CHECKSUM_UNNECESSARY; - napi_gro_receive(&ch->napi, skb); + napi_gro_receive(&ch->rx_napi, skb); priv->dev->stats.rx_packets++; priv->dev->stats.rx_bytes += frame_len; @@ -3529,40 +3537,45 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) return count; } -/** - * stmmac_poll - stmmac poll method (NAPI) - * @napi : pointer to the napi structure. - * @budget : maximum number of packets that the current CPU can receive from - * all interfaces. - * Description : - * To look at the incoming frames and clear the tx resources. - */ -static int stmmac_napi_poll(struct napi_struct *napi, int budget) +static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget) { struct stmmac_channel *ch = - container_of(napi, struct stmmac_channel, napi); + container_of(napi, struct stmmac_channel, rx_napi); struct stmmac_priv *priv = ch->priv_data; - int work_done, rx_done = 0, tx_done = 0; u32 chan = ch->index; + int work_done; priv->xstats.napi_poll++; - if (ch->has_tx) - tx_done = stmmac_tx_clean(priv, budget, chan); - if (ch->has_rx) - rx_done = stmmac_rx(priv, budget, chan); + work_done = stmmac_rx(priv, budget, chan); + if (work_done < budget && napi_complete_done(napi, work_done)) + stmmac_enable_dma_irq(priv, priv->ioaddr, chan); + return work_done; +} - work_done = max(rx_done, tx_done); - work_done = min(work_done, budget); +static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget) +{ + struct stmmac_channel *ch = + container_of(napi, struct stmmac_channel, tx_napi); + struct stmmac_priv *priv = ch->priv_data; + struct stmmac_tx_queue *tx_q; + u32 chan = ch->index; + int work_done; - if (work_done < budget && napi_complete_done(napi, work_done)) { - int stat; + priv->xstats.napi_poll++; + + work_done = stmmac_tx_clean(priv, DMA_TX_SIZE, chan); + work_done = min(work_done, budget); + if (work_done < budget && napi_complete_done(napi, work_done)) stmmac_enable_dma_irq(priv, priv->ioaddr, chan); - stat = stmmac_dma_interrupt_status(priv, priv->ioaddr, - &priv->xstats, chan); - if (stat && napi_reschedule(napi)) - stmmac_disable_dma_irq(priv, priv->ioaddr, chan); + + /* Force transmission restart */ + tx_q = &priv->tx_queue[chan]; + if (tx_q->cur_tx != tx_q->dirty_tx) { + stmmac_enable_dma_transmission(priv, priv->ioaddr); + stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, + chan); } return work_done; @@ -4342,13 +4355,14 @@ int stmmac_dvr_probe(struct device *device, ch->priv_data = priv; ch->index = queue; - if (queue < priv->plat->rx_queues_to_use) - ch->has_rx = true; - if (queue < priv->plat->tx_queues_to_use) - ch->has_tx = true; - - netif_napi_add(ndev, &ch->napi, stmmac_napi_poll, - NAPI_POLL_WEIGHT); + if (queue < priv->plat->rx_queues_to_use) { + netif_napi_add(ndev, &ch->rx_napi, stmmac_napi_poll_rx, + NAPI_POLL_WEIGHT); + } + if (queue < priv->plat->tx_queues_to_use) { + netif_napi_add(ndev, &ch->tx_napi, stmmac_napi_poll_tx, + NAPI_POLL_WEIGHT); + } } mutex_init(&priv->lock); @@ -4404,7 +4418,10 @@ error_mdio_register: for (queue = 0; queue < maxq; queue++) { struct stmmac_channel *ch = &priv->channel[queue]; - netif_napi_del(&ch->napi); + if (queue < priv->plat->rx_queues_to_use) + netif_napi_del(&ch->rx_napi); + if (queue < priv->plat->tx_queues_to_use) + netif_napi_del(&ch->tx_napi); } error_hw_init: destroy_workqueue(priv->wq); -- cgit v1.2.3 From 1103d3a5531ce60fa1f8ecaaa95d6f3558b77a29 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Tue, 19 Feb 2019 10:38:48 +0100 Subject: net: stmmac: dwmac4: Also use TBU interrupt to clean TX path TBU interrupt is a normal interrupt and can be used to trigger the cleaning of TX path. Lets check if it's active in DMA interrupt handler. While at it, refactor a little bit the function: - Don't check if RI is enabled because at function exit we will only clear the interrupts that are enabled so, no event will be missed. In my tests with GMAC5 this increased performance. Signed-off-by: Jose Abreu Cc: Joao Pinto Cc: David S. Miller Cc: Giuseppe Cavallaro Cc: Alexandre Torgue Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index 49f5687879df..545cb9c47433 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -124,9 +124,9 @@ void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan) int dwmac4_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x, u32 chan) { - int ret = 0; - u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan)); + u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(chan)); + int ret = 0; /* ABNORMAL interrupts */ if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) { @@ -151,16 +151,11 @@ int dwmac4_dma_interrupt(void __iomem *ioaddr, if (likely(intr_status & DMA_CHAN_STATUS_NIS)) { x->normal_irq_n++; if (likely(intr_status & DMA_CHAN_STATUS_RI)) { - u32 value; - - value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan)); - /* to schedule NAPI on real RIE event. */ - if (likely(value & DMA_CHAN_INTR_ENA_RIE)) { - x->rx_normal_irq_n++; - ret |= handle_rx; - } + x->rx_normal_irq_n++; + ret |= handle_rx; } - if (likely(intr_status & DMA_CHAN_STATUS_TI)) { + if (likely(intr_status & (DMA_CHAN_STATUS_TI | + DMA_CHAN_STATUS_TBU))) { x->tx_normal_irq_n++; ret |= handle_tx; } @@ -168,12 +163,7 @@ int dwmac4_dma_interrupt(void __iomem *ioaddr, x->rx_early_irq++; } - /* Clear the interrupt by writing a logic 1 to the chanX interrupt - * status [21-0] expect reserved bits [5-3] - */ - writel((intr_status & 0x3fffc7), - ioaddr + DMA_CHAN_STATUS(chan)); - + writel(intr_status & intr_en, ioaddr + DMA_CHAN_STATUS(chan)); return ret; } -- cgit v1.2.3 From ae9f346dd38cc10d083fce4175ba6c8f8e06fe00 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Tue, 19 Feb 2019 10:38:49 +0100 Subject: net: stmmac: dwxgmac2: Also use TBU interrupt to clean TX path TBU interrupt is a normal interrupt and can be used to trigger the cleaning of TX path. Lets check if it's active in DMA interrupt handler. While at it, refactor a little bit the function: - Don't check if RI is enabled because at function exit we will only clear the interrupts that are enabled so, no event will be missed. In my tests withe XGMAC2 this increased performance. Signed-off-by: Jose Abreu Cc: Joao Pinto Cc: David S. Miller Cc: Giuseppe Cavallaro Cc: Alexandre Torgue Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 4 +++- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h index d6bb953685fa..37d5e6fe7473 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h @@ -193,9 +193,10 @@ #define XGMAC_AIE BIT(14) #define XGMAC_RBUE BIT(7) #define XGMAC_RIE BIT(6) +#define XGMAC_TBUE BIT(2) #define XGMAC_TIE BIT(0) #define XGMAC_DMA_INT_DEFAULT_EN (XGMAC_NIE | XGMAC_AIE | XGMAC_RBUE | \ - XGMAC_RIE | XGMAC_TIE) + XGMAC_RIE | XGMAC_TBUE | XGMAC_TIE) #define XGMAC_DMA_CH_Rx_WATCHDOG(x) (0x0000313c + (0x80 * (x))) #define XGMAC_RWT GENMASK(7, 0) #define XGMAC_DMA_CH_STATUS(x) (0x00003160 + (0x80 * (x))) @@ -204,6 +205,7 @@ #define XGMAC_FBE BIT(12) #define XGMAC_RBU BIT(7) #define XGMAC_RI BIT(6) +#define XGMAC_TBU BIT(2) #define XGMAC_TPS BIT(1) #define XGMAC_TI BIT(0) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c index c5e25580a43f..2ba712b48a89 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c @@ -283,12 +283,10 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr, x->normal_irq_n++; if (likely(intr_status & XGMAC_RI)) { - if (likely(intr_en & XGMAC_RIE)) { - x->rx_normal_irq_n++; - ret |= handle_rx; - } + x->rx_normal_irq_n++; + ret |= handle_rx; } - if (likely(intr_status & XGMAC_TI)) { + if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) { x->tx_normal_irq_n++; ret |= handle_tx; } -- cgit v1.2.3 From c39f3e0e4f15714f29cf3c089cdb6e179997a415 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:12 +0000 Subject: mlxsw: spectrum: Add struct mlxsw_sp_sb_vals Spectrum-2 will be configured with a different shared buffer configuration than Spectrum-1. Therefore introduce a structure for keeping the chip-specific default and immutable configuration. Configuration mutable in runtime will still be kept in struct mlxsw_sp_sb. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 5 +++++ drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 9 +++++++++ 3 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 7ee6d747e97b..c1ec4f89973b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4092,6 +4092,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->nve_ops_arr = mlxsw_sp1_nve_ops_arr; mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask; mlxsw_sp->rif_ops_arr = mlxsw_sp1_rif_ops_arr; + mlxsw_sp->sb_vals = &mlxsw_sp1_sb_vals; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info); } @@ -4109,6 +4110,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr; mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask; mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr; + mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index ceebc91f4f1d..976843917c95 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -133,6 +133,7 @@ struct mlxsw_sp_kvdl_ops; struct mlxsw_sp_mr_tcam_ops; struct mlxsw_sp_acl_tcam_ops; struct mlxsw_sp_nve_ops; +struct mlxsw_sp_sb_vals; struct mlxsw_sp { struct mlxsw_sp_port **ports; @@ -167,6 +168,7 @@ struct mlxsw_sp { const struct mlxsw_sp_acl_tcam_ops *acl_tcam_ops; const struct mlxsw_sp_nve_ops **nve_ops_arr; const struct mlxsw_sp_rif_ops **rif_ops_arr; + const struct mlxsw_sp_sb_vals *sb_vals; }; static inline struct mlxsw_sp_upper * @@ -372,6 +374,9 @@ int mlxsw_sp_sb_occ_tc_port_bind_get(struct mlxsw_core_port *mlxsw_core_port, u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells); u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes); +extern const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals; +extern const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals; + /* spectrum_switchdev.c */ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 80066f437a65..cd23ec9268bc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -73,6 +73,9 @@ struct mlxsw_sp_sb { u64 sb_size; }; +struct mlxsw_sp_sb_vals { +}; + u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells) { return mlxsw_sp->sb->cell_size * cells; @@ -625,6 +628,12 @@ out: *p_egress_len = MLXSW_SP_SB_POOL_DESS_LEN - i; } +const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = { +}; + +const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { +}; + int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) { u16 ing_pool_count; -- cgit v1.2.3 From 93d201f7757e0ec079bc72344fe3577b7333a585 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:14 +0000 Subject: mlxsw: spectrum_buffers: Allocate prs & pms dynamically Spectrum-2 will be configured with a different set of pools than Spectrum-1. The size of prs and pms buffers will therefore depend on the chip type of the device. Therefore, instead of reserving an array directly in a structure definition, allocate the buffer in mlxsw_sp_sb_port{,s}_init(). Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 52 +++++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index cd23ec9268bc..7fa291ebcddf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -63,11 +63,11 @@ static const struct mlxsw_sp_sb_pool_des mlxsw_sp_sb_pool_dess[] = { struct mlxsw_sp_sb_port { struct mlxsw_sp_sb_cm ing_cms[MLXSW_SP_SB_ING_TC_COUNT]; struct mlxsw_sp_sb_cm eg_cms[MLXSW_SP_SB_EG_TC_COUNT]; - struct mlxsw_sp_sb_pm pms[MLXSW_SP_SB_POOL_DESS_LEN]; + struct mlxsw_sp_sb_pm *pms; }; struct mlxsw_sp_sb { - struct mlxsw_sp_sb_pr prs[MLXSW_SP_SB_POOL_DESS_LEN]; + struct mlxsw_sp_sb_pr *prs; struct mlxsw_sp_sb_port *ports; u32 cell_size; u64 sb_size; @@ -283,20 +283,68 @@ static int mlxsw_sp_port_headroom_init(struct mlxsw_sp_port *mlxsw_sp_port) return mlxsw_sp_port_pb_prio_init(mlxsw_sp_port); } +static int mlxsw_sp_sb_port_init(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_sb_port *sb_port) +{ + struct mlxsw_sp_sb_pm *pms; + + pms = kcalloc(MLXSW_SP_SB_POOL_DESS_LEN, sizeof(*pms), GFP_KERNEL); + if (!pms) + return -ENOMEM; + sb_port->pms = pms; + return 0; +} + +static void mlxsw_sp_sb_port_fini(struct mlxsw_sp_sb_port *sb_port) +{ + kfree(sb_port->pms); +} + static int mlxsw_sp_sb_ports_init(struct mlxsw_sp *mlxsw_sp) { unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); + struct mlxsw_sp_sb_pr *prs; + int i; + int err; mlxsw_sp->sb->ports = kcalloc(max_ports, sizeof(struct mlxsw_sp_sb_port), GFP_KERNEL); if (!mlxsw_sp->sb->ports) return -ENOMEM; + + prs = kcalloc(MLXSW_SP_SB_POOL_DESS_LEN, sizeof(*prs), GFP_KERNEL); + if (!prs) { + err = -ENOMEM; + goto err_alloc_prs; + } + mlxsw_sp->sb->prs = prs; + + for (i = 0; i < max_ports; i++) { + err = mlxsw_sp_sb_port_init(mlxsw_sp, &mlxsw_sp->sb->ports[i]); + if (err) + goto err_sb_port_init; + } + return 0; + +err_sb_port_init: + for (i--; i >= 0; i--) + mlxsw_sp_sb_port_fini(&mlxsw_sp->sb->ports[i]); + kfree(mlxsw_sp->sb->prs); +err_alloc_prs: + kfree(mlxsw_sp->sb->ports); + return err; } static void mlxsw_sp_sb_ports_fini(struct mlxsw_sp *mlxsw_sp) { + int max_ports = mlxsw_core_max_ports(mlxsw_sp->core); + int i; + + for (i = max_ports - 1; i >= 0; i--) + mlxsw_sp_sb_port_fini(&mlxsw_sp->sb->ports[i]); + kfree(mlxsw_sp->sb->prs); kfree(mlxsw_sp->sb->ports); } -- cgit v1.2.3 From 5d65f5f45eaff091a2409e67225983dad4a33423 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:16 +0000 Subject: mlxsw: spectrum_buffers: Keep pool descriptors in mlxsw_sp_sb_vals Keep the table of pool descriptors and its length in struct mlxsw_sp_sb_vals so that it can be specialized per chip type. Redirect all users from the global definitions to the mlxsw_sp_sb fields. Give mlxsw_sp_pool_count() an extra mlxsw_sp parameter so that it can access the descriptor table. Drop the now unnecessary MLXSW_SP_SB_POOL_DESS_LEN. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 50 +++++++++++++--------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 7fa291ebcddf..72126d904013 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -55,8 +55,6 @@ static const struct mlxsw_sp_sb_pool_des mlxsw_sp_sb_pool_dess[] = { {MLXSW_REG_SBXX_DIR_EGRESS, 15}, }; -#define MLXSW_SP_SB_POOL_DESS_LEN ARRAY_SIZE(mlxsw_sp_sb_pool_dess) - #define MLXSW_SP_SB_ING_TC_COUNT 8 #define MLXSW_SP_SB_EG_TC_COUNT 16 @@ -74,6 +72,8 @@ struct mlxsw_sp_sb { }; struct mlxsw_sp_sb_vals { + unsigned int pool_count; + const struct mlxsw_sp_sb_pool_des *pool_dess; }; u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells) @@ -124,7 +124,7 @@ static int mlxsw_sp_sb_pr_write(struct mlxsw_sp *mlxsw_sp, u16 pool_index, u32 size, bool infi_size) { const struct mlxsw_sp_sb_pool_des *des = - &mlxsw_sp_sb_pool_dess[pool_index]; + &mlxsw_sp->sb_vals->pool_dess[pool_index]; char sbpr_pl[MLXSW_REG_SBPR_LEN]; struct mlxsw_sp_sb_pr *pr; int err; @@ -148,7 +148,7 @@ static int mlxsw_sp_sb_cm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, bool infi_max, u16 pool_index) { const struct mlxsw_sp_sb_pool_des *des = - &mlxsw_sp_sb_pool_dess[pool_index]; + &mlxsw_sp->sb_vals->pool_dess[pool_index]; char sbcm_pl[MLXSW_REG_SBCM_LEN]; struct mlxsw_sp_sb_cm *cm; int err; @@ -177,7 +177,7 @@ static int mlxsw_sp_sb_pm_write(struct mlxsw_sp *mlxsw_sp, u8 local_port, u16 pool_index, u32 min_buff, u32 max_buff) { const struct mlxsw_sp_sb_pool_des *des = - &mlxsw_sp_sb_pool_dess[pool_index]; + &mlxsw_sp->sb_vals->pool_dess[pool_index]; char sbpm_pl[MLXSW_REG_SBPM_LEN]; struct mlxsw_sp_sb_pm *pm; int err; @@ -198,7 +198,7 @@ static int mlxsw_sp_sb_pm_occ_clear(struct mlxsw_sp *mlxsw_sp, u8 local_port, u16 pool_index, struct list_head *bulk_list) { const struct mlxsw_sp_sb_pool_des *des = - &mlxsw_sp_sb_pool_dess[pool_index]; + &mlxsw_sp->sb_vals->pool_dess[pool_index]; char sbpm_pl[MLXSW_REG_SBPM_LEN]; mlxsw_reg_sbpm_pack(sbpm_pl, local_port, des->pool, des->dir, @@ -220,7 +220,7 @@ static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port, u16 pool_index, struct list_head *bulk_list) { const struct mlxsw_sp_sb_pool_des *des = - &mlxsw_sp_sb_pool_dess[pool_index]; + &mlxsw_sp->sb_vals->pool_dess[pool_index]; char sbpm_pl[MLXSW_REG_SBPM_LEN]; struct mlxsw_sp_sb_pm *pm; @@ -288,7 +288,8 @@ static int mlxsw_sp_sb_port_init(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_sb_pm *pms; - pms = kcalloc(MLXSW_SP_SB_POOL_DESS_LEN, sizeof(*pms), GFP_KERNEL); + pms = kcalloc(mlxsw_sp->sb_vals->pool_count, sizeof(*pms), + GFP_KERNEL); if (!pms) return -ENOMEM; sb_port->pms = pms; @@ -313,7 +314,8 @@ static int mlxsw_sp_sb_ports_init(struct mlxsw_sp *mlxsw_sp) if (!mlxsw_sp->sb->ports) return -ENOMEM; - prs = kcalloc(MLXSW_SP_SB_POOL_DESS_LEN, sizeof(*prs), GFP_KERNEL); + prs = kcalloc(mlxsw_sp->sb_vals->pool_count, sizeof(*prs), + GFP_KERNEL); if (!prs) { err = -ENOMEM; goto err_alloc_prs; @@ -498,6 +500,7 @@ static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, const struct mlxsw_sp_sb_cm *cms, size_t cms_len) { + const struct mlxsw_sp_sb_vals *sb_vals = mlxsw_sp->sb_vals; int i; int err; @@ -509,7 +512,7 @@ static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, if (i == 8 && dir == MLXSW_REG_SBXX_DIR_INGRESS) continue; /* PG number 8 does not exist, skip it */ cm = &cms[i]; - if (WARN_ON(mlxsw_sp_sb_pool_dess[cm->pool_index].dir != dir)) + if (WARN_ON(sb_vals->pool_dess[cm->pool_index].dir != dir)) continue; min_buff = mlxsw_sp_bytes_cells(mlxsw_sp, cm->min_buff); @@ -648,7 +651,7 @@ static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp) u32 min_buff; mc = &mlxsw_sp_sb_mms[i]; - des = &mlxsw_sp_sb_pool_dess[mc->pool_index]; + des = &mlxsw_sp->sb_vals->pool_dess[mc->pool_index]; /* All pools used by sb_mm's are initialized using dynamic * thresholds, therefore 'max_buff' isn't specified in cells. */ @@ -662,24 +665,30 @@ static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp) return 0; } -static void mlxsw_sp_pool_count(u16 *p_ingress_len, u16 *p_egress_len) +static void mlxsw_sp_pool_count(struct mlxsw_sp *mlxsw_sp, + u16 *p_ingress_len, u16 *p_egress_len) { int i; - for (i = 0; i < MLXSW_SP_SB_POOL_DESS_LEN; ++i) - if (mlxsw_sp_sb_pool_dess[i].dir == MLXSW_REG_SBXX_DIR_EGRESS) + for (i = 0; i < mlxsw_sp->sb_vals->pool_count; ++i) + if (mlxsw_sp->sb_vals->pool_dess[i].dir == + MLXSW_REG_SBXX_DIR_EGRESS) goto out; WARN(1, "No egress pools\n"); out: *p_ingress_len = i; - *p_egress_len = MLXSW_SP_SB_POOL_DESS_LEN - i; + *p_egress_len = mlxsw_sp->sb_vals->pool_count - i; } const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = { + .pool_count = ARRAY_SIZE(mlxsw_sp_sb_pool_dess), + .pool_dess = mlxsw_sp_sb_pool_dess, }; const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { + .pool_count = ARRAY_SIZE(mlxsw_sp_sb_pool_dess), + .pool_dess = mlxsw_sp_sb_pool_dess, }; int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) @@ -714,7 +723,7 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) err = mlxsw_sp_sb_mms_init(mlxsw_sp); if (err) goto err_sb_mms_init; - mlxsw_sp_pool_count(&ing_pool_count, &eg_pool_count); + mlxsw_sp_pool_count(mlxsw_sp, &ing_pool_count, &eg_pool_count); err = devlink_sb_register(priv_to_devlink(mlxsw_sp->core), 0, mlxsw_sp->sb->sb_size, ing_pool_count, @@ -762,10 +771,11 @@ int mlxsw_sp_sb_pool_get(struct mlxsw_core *mlxsw_core, unsigned int sb_index, u16 pool_index, struct devlink_sb_pool_info *pool_info) { - enum mlxsw_reg_sbxx_dir dir = mlxsw_sp_sb_pool_dess[pool_index].dir; struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); + enum mlxsw_reg_sbxx_dir dir; struct mlxsw_sp_sb_pr *pr; + dir = mlxsw_sp->sb_vals->pool_dess[pool_index].dir; pr = mlxsw_sp_sb_pr_get(mlxsw_sp, pool_index); pool_info->pool_type = (enum devlink_sb_pool_type) dir; pool_info->size = mlxsw_sp_cells_bytes(mlxsw_sp, pr->size); @@ -891,7 +901,7 @@ int mlxsw_sp_sb_tc_pool_bind_set(struct mlxsw_core_port *mlxsw_core_port, u32 max_buff; int err; - if (dir != mlxsw_sp_sb_pool_dess[pool_index].dir) + if (dir != mlxsw_sp->sb_vals->pool_dess[pool_index].dir) return -EINVAL; err = mlxsw_sp_sb_threshold_in(mlxsw_sp, pool_index, @@ -989,7 +999,7 @@ next_batch: continue; mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1); mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1); - for (i = 0; i < MLXSW_SP_SB_POOL_DESS_LEN; i++) { + for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) { err = mlxsw_sp_sb_pm_occ_query(mlxsw_sp, local_port, i, &bulk_list); if (err) @@ -1048,7 +1058,7 @@ next_batch: continue; mlxsw_reg_sbsr_ingress_port_mask_set(sbsr_pl, local_port, 1); mlxsw_reg_sbsr_egress_port_mask_set(sbsr_pl, local_port, 1); - for (i = 0; i < MLXSW_SP_SB_POOL_DESS_LEN; i++) { + for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) { err = mlxsw_sp_sb_pm_occ_clear(mlxsw_sp, local_port, i, &bulk_list); if (err) -- cgit v1.2.3 From cc1ce6ff3453d7b188bd0c4ca186cf9ebd071e82 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:18 +0000 Subject: mlxsw: spectrum_buffers: Keep mlxsw_sp_sb_pms in mlxsw_sp_sb_vals The SBPM register can be used to configure quotas for packets ingressing from a certain pool to a certain port, and egressing from a certain pool to a certain port. The default configuration depends on the chip type. Therefore keep it in struct mlxsw_sp_sb_vals. Redirect the one reference from the global array to the field. Because the pool descriptor ID is implicit in the ordering of array members, both this array and the pool descriptor array have the same length. Therefore reuse mlxsw_sp_sb.pool_dess_len for the purpose of determining the length of SBPM array. Drop the now useless MLXSW_SP_SB_PMS_LEN. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 72126d904013..672c27c79e8a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -74,6 +74,7 @@ struct mlxsw_sp_sb { struct mlxsw_sp_sb_vals { unsigned int pool_count; const struct mlxsw_sp_sb_pool_des *pool_dess; + const struct mlxsw_sp_sb_pm *pms; }; u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells) @@ -581,16 +582,14 @@ static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = { MLXSW_SP_SB_PM(10000, 90000), }; -#define MLXSW_SP_SB_PMS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms) - static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; int i; int err; - for (i = 0; i < MLXSW_SP_SB_PMS_LEN; i++) { - const struct mlxsw_sp_sb_pm *pm = &mlxsw_sp_sb_pms[i]; + for (i = 0; i < mlxsw_sp->sb_vals->pool_count; i++) { + const struct mlxsw_sp_sb_pm *pm = &mlxsw_sp->sb_vals->pms[i]; u32 max_buff; u32 min_buff; @@ -684,11 +683,13 @@ out: const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = { .pool_count = ARRAY_SIZE(mlxsw_sp_sb_pool_dess), .pool_dess = mlxsw_sp_sb_pool_dess, + .pms = mlxsw_sp_sb_pms, }; const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { .pool_count = ARRAY_SIZE(mlxsw_sp_sb_pool_dess), .pool_dess = mlxsw_sp_sb_pool_dess, + .pms = mlxsw_sp_sb_pms, }; int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) -- cgit v1.2.3 From 5d25232eb925b73c4f632923821006d0d9ffb9aa Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:20 +0000 Subject: mlxsw: spectrum_buffers: Keep mlxsw_sp_sb_prs in mlxsw_sp_sb_vals The SBPR register configures shared buffer pools. The default configuration depends on the chip type. Therefore keep it in struct mlxsw_sp_sb_vals. Redirect the one reference from the global array to the field. Because the pool descriptor ID is implicit in the ordering of array members, both this array and the pool descriptor array have the same length. Therefore reuse mlxsw_sp_sb.pool_dess_len for the purpose of determining the length of SBPR array. Drop the now useless MLXSW_SP_SB_PRS_LEN. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 672c27c79e8a..c100ce11417a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -75,6 +75,7 @@ struct mlxsw_sp_sb_vals { unsigned int pool_count; const struct mlxsw_sp_sb_pool_des *pool_dess; const struct mlxsw_sp_sb_pm *pms; + const struct mlxsw_sp_sb_pr *prs; }; u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells) @@ -377,8 +378,6 @@ static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs[] = { MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, MLXSW_SP_SB_INFI), }; -#define MLXSW_SP_SB_PRS_LEN ARRAY_SIZE(mlxsw_sp_sb_prs) - static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_sb_pr *prs, size_t prs_len) @@ -684,12 +683,14 @@ const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = { .pool_count = ARRAY_SIZE(mlxsw_sp_sb_pool_dess), .pool_dess = mlxsw_sp_sb_pool_dess, .pms = mlxsw_sp_sb_pms, + .prs = mlxsw_sp_sb_prs, }; const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { .pool_count = ARRAY_SIZE(mlxsw_sp_sb_pool_dess), .pool_dess = mlxsw_sp_sb_pool_dess, .pms = mlxsw_sp_sb_pms, + .prs = mlxsw_sp_sb_prs, }; int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) @@ -710,12 +711,11 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) mlxsw_sp->sb->cell_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, CELL_SIZE); mlxsw_sp->sb->sb_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_BUFFER_SIZE); - err = mlxsw_sp_sb_ports_init(mlxsw_sp); if (err) goto err_sb_ports_init; - err = mlxsw_sp_sb_prs_init(mlxsw_sp, mlxsw_sp_sb_prs, - MLXSW_SP_SB_PRS_LEN); + err = mlxsw_sp_sb_prs_init(mlxsw_sp, mlxsw_sp->sb_vals->prs, + mlxsw_sp->sb_vals->pool_count); if (err) goto err_sb_prs_init; err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp); -- cgit v1.2.3 From bb60a62e0247571e3f4224b792930711e18950ce Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:22 +0000 Subject: mlxsw: spectrum_buffers: Keep mlxsw_sp_sb_cm in sb_vals The SBCM register configures shared buffer quota according to port-priority resp. port-TC. The default configuration depends on the chip type. Therefore keep the tables and their lengths in struct mlxsw_sp_sb_vals. Redirect the references from the global definitions to the fields. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 40 ++++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index c100ce11417a..18b182656df2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -76,6 +76,12 @@ struct mlxsw_sp_sb_vals { const struct mlxsw_sp_sb_pool_des *pool_dess; const struct mlxsw_sp_sb_pm *pms; const struct mlxsw_sp_sb_pr *prs; + const struct mlxsw_sp_sb_cm *cms_ingress; + const struct mlxsw_sp_sb_cm *cms_egress; + const struct mlxsw_sp_sb_cm *cms_cpu; + unsigned int cms_ingress_count; + unsigned int cms_egress_count; + unsigned int cms_cpu_count; }; u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells) @@ -423,8 +429,6 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = { MLXSW_SP_SB_CM(20000, 1, 3), }; -#define MLXSW_SP_SB_CMS_INGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_ingress) - static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = { MLXSW_SP_SB_CM(1500, 9, 4), MLXSW_SP_SB_CM(1500, 9, 4), @@ -445,8 +449,6 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = { MLXSW_SP_SB_CM(1, 0xff, 4), }; -#define MLXSW_SP_SB_CMS_EGRESS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms_egress) - #define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(0, 0, 4) static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = { @@ -484,9 +486,6 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = { MLXSW_SP_CPU_PORT_SB_CM, }; -#define MLXSW_SP_CPU_PORT_SB_MCS_LEN \ - ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms) - static bool mlxsw_sp_sb_pool_is_static(struct mlxsw_sp *mlxsw_sp, u16 pool_index) { @@ -538,27 +537,28 @@ static int __mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, static int mlxsw_sp_port_sb_cms_init(struct mlxsw_sp_port *mlxsw_sp_port) { + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; int err; - err = __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp, + err = __mlxsw_sp_sb_cms_init(mlxsw_sp, mlxsw_sp_port->local_port, MLXSW_REG_SBXX_DIR_INGRESS, - mlxsw_sp_sb_cms_ingress, - MLXSW_SP_SB_CMS_INGRESS_LEN); + mlxsw_sp->sb_vals->cms_ingress, + mlxsw_sp->sb_vals->cms_ingress_count); if (err) return err; return __mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp, mlxsw_sp_port->local_port, MLXSW_REG_SBXX_DIR_EGRESS, - mlxsw_sp_sb_cms_egress, - MLXSW_SP_SB_CMS_EGRESS_LEN); + mlxsw_sp->sb_vals->cms_egress, + mlxsw_sp->sb_vals->cms_egress_count); } static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp) { return __mlxsw_sp_sb_cms_init(mlxsw_sp, 0, MLXSW_REG_SBXX_DIR_EGRESS, - mlxsw_sp_cpu_port_sb_cms, - MLXSW_SP_CPU_PORT_SB_MCS_LEN); + mlxsw_sp->sb_vals->cms_cpu, + mlxsw_sp->sb_vals->cms_cpu_count); } #define MLXSW_SP_SB_PM(_min_buff, _max_buff) \ @@ -684,6 +684,12 @@ const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = { .pool_dess = mlxsw_sp_sb_pool_dess, .pms = mlxsw_sp_sb_pms, .prs = mlxsw_sp_sb_prs, + .cms_ingress = mlxsw_sp_sb_cms_ingress, + .cms_egress = mlxsw_sp_sb_cms_egress, + .cms_cpu = mlxsw_sp_cpu_port_sb_cms, + .cms_ingress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_ingress), + .cms_egress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_egress), + .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms), }; const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { @@ -691,6 +697,12 @@ const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { .pool_dess = mlxsw_sp_sb_pool_dess, .pms = mlxsw_sp_sb_pms, .prs = mlxsw_sp_sb_prs, + .cms_ingress = mlxsw_sp_sb_cms_ingress, + .cms_egress = mlxsw_sp_sb_cms_egress, + .cms_cpu = mlxsw_sp_cpu_port_sb_cms, + .cms_ingress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_ingress), + .cms_egress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_egress), + .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms), }; int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) -- cgit v1.2.3 From 13f35cc4245c8de3bdae3e5529c0904f3f80da3f Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:23 +0000 Subject: mlxsw: spectrum_buffers: Keep mlxsw_sp_sb_mm in sb_vals The SBMM register configures the shared buffer quota for MC packets according to Switch-Priority. The default configuration depends on the chip type. Therefore keep the table and length in struct mlxsw_sp_sb_vals. Redirect the references from the global definitions to the fields. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 18b182656df2..5194fc8f80cc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -37,6 +37,12 @@ struct mlxsw_sp_sb_pm { struct mlxsw_cp_sb_occ occ; }; +struct mlxsw_sp_sb_mm { + u32 min_buff; + u32 max_buff; + u16 pool_index; +}; + struct mlxsw_sp_sb_pool_des { enum mlxsw_reg_sbxx_dir dir; u8 pool; @@ -76,9 +82,11 @@ struct mlxsw_sp_sb_vals { const struct mlxsw_sp_sb_pool_des *pool_dess; const struct mlxsw_sp_sb_pm *pms; const struct mlxsw_sp_sb_pr *prs; + const struct mlxsw_sp_sb_mm *mms; const struct mlxsw_sp_sb_cm *cms_ingress; const struct mlxsw_sp_sb_cm *cms_egress; const struct mlxsw_sp_sb_cm *cms_cpu; + unsigned int mms_count; unsigned int cms_ingress_count; unsigned int cms_egress_count; unsigned int cms_cpu_count; @@ -604,12 +612,6 @@ static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) return 0; } -struct mlxsw_sp_sb_mm { - u32 min_buff; - u32 max_buff; - u16 pool_index; -}; - #define MLXSW_SP_SB_MM(_min_buff, _max_buff, _pool) \ { \ .min_buff = _min_buff, \ @@ -635,20 +637,18 @@ static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = { MLXSW_SP_SB_MM(0, 6, 4), }; -#define MLXSW_SP_SB_MMS_LEN ARRAY_SIZE(mlxsw_sp_sb_mms) - static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp) { char sbmm_pl[MLXSW_REG_SBMM_LEN]; int i; int err; - for (i = 0; i < MLXSW_SP_SB_MMS_LEN; i++) { + for (i = 0; i < mlxsw_sp->sb_vals->mms_count; i++) { const struct mlxsw_sp_sb_pool_des *des; const struct mlxsw_sp_sb_mm *mc; u32 min_buff; - mc = &mlxsw_sp_sb_mms[i]; + mc = &mlxsw_sp->sb_vals->mms[i]; des = &mlxsw_sp->sb_vals->pool_dess[mc->pool_index]; /* All pools used by sb_mm's are initialized using dynamic * thresholds, therefore 'max_buff' isn't specified in cells. @@ -684,9 +684,11 @@ const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = { .pool_dess = mlxsw_sp_sb_pool_dess, .pms = mlxsw_sp_sb_pms, .prs = mlxsw_sp_sb_prs, + .mms = mlxsw_sp_sb_mms, .cms_ingress = mlxsw_sp_sb_cms_ingress, .cms_egress = mlxsw_sp_sb_cms_egress, .cms_cpu = mlxsw_sp_cpu_port_sb_cms, + .mms_count = ARRAY_SIZE(mlxsw_sp_sb_mms), .cms_ingress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_ingress), .cms_egress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_egress), .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms), @@ -697,9 +699,11 @@ const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { .pool_dess = mlxsw_sp_sb_pool_dess, .pms = mlxsw_sp_sb_pms, .prs = mlxsw_sp_sb_prs, + .mms = mlxsw_sp_sb_mms, .cms_ingress = mlxsw_sp_sb_cms_ingress, .cms_egress = mlxsw_sp_sb_cms_egress, .cms_cpu = mlxsw_sp_cpu_port_sb_cms, + .mms_count = ARRAY_SIZE(mlxsw_sp_sb_mms), .cms_ingress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_ingress), .cms_egress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_egress), .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms), -- cgit v1.2.3 From fe099bf682abbec77d0be73f62423ad794d88a04 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:25 +0000 Subject: mlxsw: spectrum_buffers: Add Spectrum-2 shared buffer configuration Customize the tables related to shared buffer configuration to match the current recommendation for Spectrum-2 systems. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 134 ++++++++++++++++----- 1 file changed, 106 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 5194fc8f80cc..bb327dfe1336 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -49,7 +49,7 @@ struct mlxsw_sp_sb_pool_des { }; /* Order ingress pools before egress pools. */ -static const struct mlxsw_sp_sb_pool_des mlxsw_sp_sb_pool_dess[] = { +static const struct mlxsw_sp_sb_pool_des mlxsw_sp1_sb_pool_dess[] = { {MLXSW_REG_SBXX_DIR_INGRESS, 0}, {MLXSW_REG_SBXX_DIR_INGRESS, 1}, {MLXSW_REG_SBXX_DIR_INGRESS, 2}, @@ -61,6 +61,17 @@ static const struct mlxsw_sp_sb_pool_des mlxsw_sp_sb_pool_dess[] = { {MLXSW_REG_SBXX_DIR_EGRESS, 15}, }; +static const struct mlxsw_sp_sb_pool_des mlxsw_sp2_sb_pool_dess[] = { + {MLXSW_REG_SBXX_DIR_INGRESS, 0}, + {MLXSW_REG_SBXX_DIR_INGRESS, 1}, + {MLXSW_REG_SBXX_DIR_INGRESS, 2}, + {MLXSW_REG_SBXX_DIR_INGRESS, 3}, + {MLXSW_REG_SBXX_DIR_EGRESS, 0}, + {MLXSW_REG_SBXX_DIR_EGRESS, 1}, + {MLXSW_REG_SBXX_DIR_EGRESS, 2}, + {MLXSW_REG_SBXX_DIR_EGRESS, 3}, +}; + #define MLXSW_SP_SB_ING_TC_COUNT 8 #define MLXSW_SP_SB_EG_TC_COUNT 16 @@ -366,32 +377,53 @@ static void mlxsw_sp_sb_ports_fini(struct mlxsw_sp *mlxsw_sp) kfree(mlxsw_sp->sb->ports); } -#define MLXSW_SP_SB_PR_INGRESS_SIZE 12440000 -#define MLXSW_SP_SB_PR_INGRESS_MNG_SIZE (200 * 1000) -#define MLXSW_SP_SB_PR_EGRESS_SIZE 13232000 - #define MLXSW_SP_SB_PR(_mode, _size) \ { \ .mode = _mode, \ .size = _size, \ } -static const struct mlxsw_sp_sb_pr mlxsw_sp_sb_prs[] = { +#define MLXSW_SP1_SB_PR_INGRESS_SIZE 12440000 +#define MLXSW_SP1_SB_PR_INGRESS_MNG_SIZE (200 * 1000) +#define MLXSW_SP1_SB_PR_EGRESS_SIZE 13232000 + +static const struct mlxsw_sp_sb_pr mlxsw_sp1_sb_prs[] = { /* Ingress pools. */ MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, - MLXSW_SP_SB_PR_INGRESS_SIZE), + MLXSW_SP1_SB_PR_INGRESS_SIZE), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, - MLXSW_SP_SB_PR_INGRESS_MNG_SIZE), + MLXSW_SP1_SB_PR_INGRESS_MNG_SIZE), /* Egress pools. */ - MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, MLXSW_SP_SB_PR_EGRESS_SIZE), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP1_SB_PR_EGRESS_SIZE), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, 0), MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, MLXSW_SP_SB_INFI), }; +#define MLXSW_SP2_SB_PR_INGRESS_SIZE 40960000 +#define MLXSW_SP2_SB_PR_INGRESS_MNG_SIZE (200 * 1000) +#define MLXSW_SP2_SB_PR_EGRESS_SIZE 40960000 + +static const struct mlxsw_sp_sb_pr mlxsw_sp2_sb_prs[] = { + /* Ingress pools. */ + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP2_SB_PR_INGRESS_SIZE), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP2_SB_PR_INGRESS_MNG_SIZE), + /* Egress pools. */ + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_DYNAMIC, + MLXSW_SP2_SB_PR_EGRESS_SIZE), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0), + MLXSW_SP_SB_PR(MLXSW_REG_SBPR_MODE_STATIC, 0), +}; + static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_sb_pr *prs, size_t prs_len) @@ -424,7 +456,7 @@ static int mlxsw_sp_sb_prs_init(struct mlxsw_sp *mlxsw_sp, .pool_index = _pool, \ } -static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = { +static const struct mlxsw_sp_sb_cm mlxsw_sp1_sb_cms_ingress[] = { MLXSW_SP_SB_CM(10000, 8, 0), MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), @@ -437,7 +469,20 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_ingress[] = { MLXSW_SP_SB_CM(20000, 1, 3), }; -static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = { +static const struct mlxsw_sp_sb_cm mlxsw_sp2_sb_cms_ingress[] = { + MLXSW_SP_SB_CM(0, 7, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN, 0), + MLXSW_SP_SB_CM(0, 0, 0), /* dummy, this PG does not exist */ + MLXSW_SP_SB_CM(20000, 1, 3), +}; + +static const struct mlxsw_sp_sb_cm mlxsw_sp1_sb_cms_egress[] = { MLXSW_SP_SB_CM(1500, 9, 4), MLXSW_SP_SB_CM(1500, 9, 4), MLXSW_SP_SB_CM(1500, 9, 4), @@ -457,6 +502,26 @@ static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms_egress[] = { MLXSW_SP_SB_CM(1, 0xff, 4), }; +static const struct mlxsw_sp_sb_cm mlxsw_sp2_sb_cms_egress[] = { + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(0, 7, 4), + MLXSW_SP_SB_CM(1, 0xff, 4), +}; + #define MLXSW_SP_CPU_PORT_SB_CM MLXSW_SP_SB_CM(0, 0, 4) static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = { @@ -575,7 +640,7 @@ static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp) .max_buff = _max_buff, \ } -static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = { +static const struct mlxsw_sp_sb_pm mlxsw_sp1_sb_pms[] = { /* Ingress pools. */ MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX), MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MIN), @@ -589,6 +654,19 @@ static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = { MLXSW_SP_SB_PM(10000, 90000), }; +static const struct mlxsw_sp_sb_pm mlxsw_sp2_sb_pms[] = { + /* Ingress pools. */ + MLXSW_SP_SB_PM(0, 7), + MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, MLXSW_REG_SBXX_DYN_MAX_BUFF_MAX), + /* Egress pools. */ + MLXSW_SP_SB_PM(0, 7), + MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, 0), + MLXSW_SP_SB_PM(0, 0), +}; + static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; @@ -680,32 +758,32 @@ out: } const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals = { - .pool_count = ARRAY_SIZE(mlxsw_sp_sb_pool_dess), - .pool_dess = mlxsw_sp_sb_pool_dess, - .pms = mlxsw_sp_sb_pms, - .prs = mlxsw_sp_sb_prs, + .pool_count = ARRAY_SIZE(mlxsw_sp1_sb_pool_dess), + .pool_dess = mlxsw_sp1_sb_pool_dess, + .pms = mlxsw_sp1_sb_pms, + .prs = mlxsw_sp1_sb_prs, .mms = mlxsw_sp_sb_mms, - .cms_ingress = mlxsw_sp_sb_cms_ingress, - .cms_egress = mlxsw_sp_sb_cms_egress, + .cms_ingress = mlxsw_sp1_sb_cms_ingress, + .cms_egress = mlxsw_sp1_sb_cms_egress, .cms_cpu = mlxsw_sp_cpu_port_sb_cms, .mms_count = ARRAY_SIZE(mlxsw_sp_sb_mms), - .cms_ingress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_ingress), - .cms_egress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_egress), + .cms_ingress_count = ARRAY_SIZE(mlxsw_sp1_sb_cms_ingress), + .cms_egress_count = ARRAY_SIZE(mlxsw_sp1_sb_cms_egress), .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms), }; const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { - .pool_count = ARRAY_SIZE(mlxsw_sp_sb_pool_dess), - .pool_dess = mlxsw_sp_sb_pool_dess, - .pms = mlxsw_sp_sb_pms, - .prs = mlxsw_sp_sb_prs, + .pool_count = ARRAY_SIZE(mlxsw_sp2_sb_pool_dess), + .pool_dess = mlxsw_sp2_sb_pool_dess, + .pms = mlxsw_sp2_sb_pms, + .prs = mlxsw_sp2_sb_prs, .mms = mlxsw_sp_sb_mms, - .cms_ingress = mlxsw_sp_sb_cms_ingress, - .cms_egress = mlxsw_sp_sb_cms_egress, + .cms_ingress = mlxsw_sp2_sb_cms_ingress, + .cms_egress = mlxsw_sp2_sb_cms_egress, .cms_cpu = mlxsw_sp_cpu_port_sb_cms, .mms_count = ARRAY_SIZE(mlxsw_sp_sb_mms), - .cms_ingress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_ingress), - .cms_egress_count = ARRAY_SIZE(mlxsw_sp_sb_cms_egress), + .cms_ingress_count = ARRAY_SIZE(mlxsw_sp2_sb_cms_ingress), + .cms_egress_count = ARRAY_SIZE(mlxsw_sp2_sb_cms_egress), .cms_cpu_count = ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms), }; -- cgit v1.2.3 From edf777f55aee61d1021fc496f16ef121380cfa67 Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:27 +0000 Subject: mlxsw: spectrum_buffers: Update port headroom configuration The recommendation for headroom size for 100Gbps port and 100m cable is 101.6KB, reduced accordingly for split ports. The closest higher number evenly divisible by cell size for both Spectrum-1 and Spectrum-2, and such that the number of cells can be further divided by maximum split factor of 4, is 102528 bytes, or 25632 bytes per lane. Update mlxsw_sp_port_pb_init() to compute the headroom taking into account this recommended per-lane value and number of lanes actually dedicated to a given port. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index bb327dfe1336..65ef4a9f6afb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -260,24 +260,24 @@ static int mlxsw_sp_sb_pm_occ_query(struct mlxsw_sp *mlxsw_sp, u8 local_port, (unsigned long) pm); } -static const u16 mlxsw_sp_pbs[] = { - [0] = 2 * ETH_FRAME_LEN, - [9] = 2 * MLXSW_PORT_MAX_MTU, -}; - -#define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs) +/* 1/4 of a headroom necessary for 100Gbps port and 100m cable. */ +#define MLXSW_SP_PB_HEADROOM 25632 #define MLXSW_SP_PB_UNUSED 8 static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port) { + const u32 pbs[] = { + [0] = MLXSW_SP_PB_HEADROOM * mlxsw_sp_port->mapping.width, + [9] = 2 * MLXSW_PORT_MAX_MTU, + }; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char pbmc_pl[MLXSW_REG_PBMC_LEN]; int i; mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0xffff, 0xffff / 2); - for (i = 0; i < MLXSW_SP_PBS_LEN; i++) { - u16 size = mlxsw_sp_bytes_cells(mlxsw_sp, mlxsw_sp_pbs[i]); + for (i = 0; i < ARRAY_SIZE(pbs); i++) { + u16 size = mlxsw_sp_bytes_cells(mlxsw_sp, pbs[i]); if (i == MLXSW_SP_PB_UNUSED) continue; -- cgit v1.2.3 From bb6c346cef6fb0414865aaa6e2f3a11ceeeae14a Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Wed, 20 Feb 2019 19:32:29 +0000 Subject: mlxsw: spectrum_buffers: Reject overlarge headroom size requests cap_max_headroom_size holds maximum headroom size supported. Overstepping that limit might under certain conditions lead to ASIC freeze. Query and store the value, and add mlxsw_sp_sb_max_headroom_cells() for obtaining the stored value. In __mlxsw_sp_port_headroom_set(), reject requests where the total port buffer is larger than the advertised maximum. Signed-off-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/resources.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 13 ++++++++++++- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 1 + drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 16 ++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h index b8b3a01c2a9e..773ef7fdb285 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/resources.h +++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h @@ -26,6 +26,7 @@ enum mlxsw_res_id { MLXSW_RES_ID_MAX_LAG_MEMBERS, MLXSW_RES_ID_MAX_BUFFER_SIZE, MLXSW_RES_ID_CELL_SIZE, + MLXSW_RES_ID_MAX_HEADROOM_SIZE, MLXSW_RES_ID_ACL_MAX_TCAM_REGIONS, MLXSW_RES_ID_ACL_MAX_TCAM_RULES, MLXSW_RES_ID_ACL_MAX_REGIONS, @@ -79,6 +80,7 @@ static u16 mlxsw_res_ids[] = { [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521, [MLXSW_RES_ID_MAX_BUFFER_SIZE] = 0x2802, /* Bytes */ [MLXSW_RES_ID_CELL_SIZE] = 0x2803, /* Bytes */ + [MLXSW_RES_ID_MAX_HEADROOM_SIZE] = 0x2811, /* Bytes */ [MLXSW_RES_ID_ACL_MAX_TCAM_REGIONS] = 0x2901, [MLXSW_RES_ID_ACL_MAX_TCAM_RULES] = 0x2902, [MLXSW_RES_ID_ACL_MAX_REGIONS] = 0x2903, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index c1ec4f89973b..f018b0607dac 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -852,8 +852,12 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, u8 pfc_en = !!my_pfc ? my_pfc->pfc_en : 0; u16 delay = !!my_pfc ? my_pfc->delay : 0; char pbmc_pl[MLXSW_REG_PBMC_LEN]; + u32 taken_headroom_cells = 0; + u32 max_headroom_cells; int i, j, err; + max_headroom_cells = mlxsw_sp_sb_max_headroom_cells(mlxsw_sp); + mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0, 0); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); if (err) @@ -864,6 +868,7 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, bool pfc = false; u16 thres_cells; u16 delay_cells; + u16 total_cells; bool lossy; for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) { @@ -881,7 +886,13 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu); delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay, pfc, pause_en); - mlxsw_sp_pg_buf_pack(pbmc_pl, i, thres_cells + delay_cells, + total_cells = thres_cells + delay_cells; + + taken_headroom_cells += total_cells; + if (taken_headroom_cells > max_headroom_cells) + return -ENOBUFS; + + mlxsw_sp_pg_buf_pack(pbmc_pl, i, total_cells, thres_cells, lossy); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 976843917c95..8bb83d0facc2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -373,6 +373,7 @@ int mlxsw_sp_sb_occ_tc_port_bind_get(struct mlxsw_core_port *mlxsw_core_port, u32 *p_cur, u32 *p_max); u32 mlxsw_sp_cells_bytes(const struct mlxsw_sp *mlxsw_sp, u32 cells); u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes); +u32 mlxsw_sp_sb_max_headroom_cells(const struct mlxsw_sp *mlxsw_sp); extern const struct mlxsw_sp_sb_vals mlxsw_sp1_sb_vals; extern const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c index 65ef4a9f6afb..9a79b5e11597 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -85,6 +85,7 @@ struct mlxsw_sp_sb { struct mlxsw_sp_sb_pr *prs; struct mlxsw_sp_sb_port *ports; u32 cell_size; + u32 max_headroom_cells; u64 sb_size; }; @@ -113,6 +114,11 @@ u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes) return DIV_ROUND_UP(bytes, mlxsw_sp->sb->cell_size); } +u32 mlxsw_sp_sb_max_headroom_cells(const struct mlxsw_sp *mlxsw_sp) +{ + return mlxsw_sp->sb->max_headroom_cells; +} + static struct mlxsw_sp_sb_pr *mlxsw_sp_sb_pr_get(struct mlxsw_sp *mlxsw_sp, u16 pool_index) { @@ -789,6 +795,7 @@ const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals = { int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) { + u32 max_headroom_size; u16 ing_pool_count; u16 eg_pool_count; int err; @@ -799,12 +806,21 @@ int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_BUFFER_SIZE)) return -EIO; + if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_HEADROOM_SIZE)) + return -EIO; + mlxsw_sp->sb = kzalloc(sizeof(*mlxsw_sp->sb), GFP_KERNEL); if (!mlxsw_sp->sb) return -ENOMEM; mlxsw_sp->sb->cell_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, CELL_SIZE); mlxsw_sp->sb->sb_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_BUFFER_SIZE); + max_headroom_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, + MAX_HEADROOM_SIZE); + /* Round down, because this limit must not be overstepped. */ + mlxsw_sp->sb->max_headroom_cells = max_headroom_size / + mlxsw_sp->sb->cell_size; + err = mlxsw_sp_sb_ports_init(mlxsw_sp); if (err) goto err_sb_ports_init; -- cgit v1.2.3 From bdd59d661153a59af79112676565276ae2a1f457 Mon Sep 17 00:00:00 2001 From: Yonglong Liu Date: Wed, 20 Feb 2019 10:32:40 +0800 Subject: net: hns3: add pointer checking at the beginning of the exported functions. These functions are exported, add pointer checking at the beginning can make them more safe. Signed-off-by: Yonglong Liu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c b/drivers/net/ethernet/hisilicon/hns3/hnae3.c index 50011aafbae4..9f5349b9243f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.c +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c @@ -32,6 +32,9 @@ static bool hnae3_client_match(enum hnae3_client_type client_type, void hnae3_set_client_init_flag(struct hnae3_client *client, struct hnae3_ae_dev *ae_dev, int inited) { + if (!client || !ae_dev) + return; + switch (client->type) { case HNAE3_CLIENT_KNIC: hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited); @@ -109,6 +112,9 @@ int hnae3_register_client(struct hnae3_client *client) struct hnae3_ae_dev *ae_dev; int ret = 0; + if (!client) + return -ENODEV; + mutex_lock(&hnae3_common_lock); /* one system should only have one client for every type */ list_for_each_entry(client_tmp, &hnae3_client_list, node) { @@ -141,6 +147,9 @@ void hnae3_unregister_client(struct hnae3_client *client) { struct hnae3_ae_dev *ae_dev; + if (!client) + return; + mutex_lock(&hnae3_common_lock); /* un-initialize the client on every matched port */ list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) { @@ -163,6 +172,9 @@ void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo) struct hnae3_client *client; int ret = 0; + if (!ae_algo) + return; + mutex_lock(&hnae3_common_lock); list_add_tail(&ae_algo->node, &hnae3_ae_algo_list); @@ -209,6 +221,9 @@ void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo) struct hnae3_ae_dev *ae_dev; struct hnae3_client *client; + if (!ae_algo) + return; + mutex_lock(&hnae3_common_lock); /* Check if there are matched ae_dev */ list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) { @@ -245,6 +260,9 @@ int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev) struct hnae3_client *client; int ret = 0; + if (!ae_dev) + return -ENODEV; + mutex_lock(&hnae3_common_lock); list_add_tail(&ae_dev->node, &hnae3_ae_dev_list); @@ -307,6 +325,9 @@ void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev) struct hnae3_ae_algo *ae_algo; struct hnae3_client *client; + if (!ae_dev) + return; + mutex_lock(&hnae3_common_lock); /* Check if there are matched ae_algo */ list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) { -- cgit v1.2.3 From 676131f7c53ecdd79e29fc8cfcdefe6f9f2485e8 Mon Sep 17 00:00:00 2001 From: Yonglong Liu Date: Wed, 20 Feb 2019 10:32:41 +0800 Subject: net: hns3: Check variable is valid before assigning it to another In hnae3_register_ae_dev(), ae_algo->ops is assigned to ae_dev->ops before check that ae_algo->ops is valid. And in hnae3_register_ae_algo(), missing check for ae_algo->ops. This patch fixes them. Signed-off-by: Yonglong Liu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hnae3.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c b/drivers/net/ethernet/hisilicon/hns3/hnae3.c index 9f5349b9243f..17ab4f4af6ad 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.c +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c @@ -185,8 +185,12 @@ void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo) if (!id) continue; - /* ae_dev init should set flag */ + if (!ae_algo->ops) { + dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n"); + continue; + } ae_dev->ops = ae_algo->ops; + ret = ae_algo->ops->init_ae_dev(ae_dev); if (ret) { dev_err(&ae_dev->pdev->dev, @@ -194,6 +198,7 @@ void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo) continue; } + /* ae_dev init should set flag */ hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1); /* check the client list for the match with this ae_dev type and @@ -273,15 +278,13 @@ int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev) if (!id) continue; - ae_dev->ops = ae_algo->ops; - - if (!ae_dev->ops) { - dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n"); + if (!ae_algo->ops) { + dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n"); ret = -EOPNOTSUPP; goto out_err; } + ae_dev->ops = ae_algo->ops; - /* ae_dev init should set flag */ ret = ae_dev->ops->init_ae_dev(ae_dev); if (ret) { dev_err(&ae_dev->pdev->dev, @@ -289,6 +292,7 @@ int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev) goto out_err; } + /* ae_dev init should set flag */ hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1); break; } -- cgit v1.2.3 From db68ca0ef7c98bb39cb193571c63b22ca99f633f Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Wed, 20 Feb 2019 10:32:42 +0800 Subject: net: hns3: convert mac advertize and supported from u32 to link mode The link mode with bits has been up to more than 31 for some MAC and phy. Convert to using a linkmode bitmap, which can support all link modes. Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 75ec3094bbf9..9a442f3c682a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -839,27 +839,27 @@ static void hclge_parse_fiber_link_mode(struct hclge_dev *hdev, unsigned long *supported = hdev->hw.mac.supported; if (speed_ability & HCLGE_SUPPORT_1G_BIT) - set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, - supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, + supported); if (speed_ability & HCLGE_SUPPORT_10G_BIT) - set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, - supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + supported); if (speed_ability & HCLGE_SUPPORT_25G_BIT) - set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, - supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, + supported); if (speed_ability & HCLGE_SUPPORT_50G_BIT) - set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, - supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, + supported); if (speed_ability & HCLGE_SUPPORT_100G_BIT) - set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, - supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, + supported); - set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported); - set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported); } static void hclge_parse_link_mode(struct hclge_dev *hdev, u8 speed_ability) -- cgit v1.2.3 From f18635d52c23594259da2f741399abc6c6f41f15 Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Wed, 20 Feb 2019 10:32:43 +0800 Subject: net: hns3: fix port info query issue for copper port In original codes, for copper port which doesn't connect to phy, it always returns -EOPNOTSUPP when query port information. This patch fixes it by return the port information of MAC. Fixes: 5f373b158523 ("net: hns3: Fix speed/duplex information loss problem when executing ethtool ethx cmd of VF") Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 9 +++-- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 38 +++++++++++++++++++--- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 4 +++ .../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 17 ++-------- 4 files changed, 44 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 63f5f56bda94..d94c90a38563 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -621,12 +621,11 @@ static int hns3_get_link_ksettings(struct net_device *netdev, hns3_get_ksettings(h, cmd); break; case HNAE3_MEDIA_TYPE_COPPER: - if (!netdev->phydev) - return -EOPNOTSUPP; - cmd->base.port = PORT_TP; - phy_ethtool_ksettings_get(netdev->phydev, cmd); - + if (!netdev->phydev) + hns3_get_ksettings(h, cmd); + else + phy_ethtool_ksettings_get(netdev->phydev, cmd); break; default: diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 9a442f3c682a..87edac45c040 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -862,14 +862,44 @@ static void hclge_parse_fiber_link_mode(struct hclge_dev *hdev, linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported); } +static void hclge_parse_copper_link_mode(struct hclge_dev *hdev, + u8 speed_ability) +{ + unsigned long *supported = hdev->hw.mac.supported; + + /* default to support all speed for GE port */ + if (!speed_ability) + speed_ability = HCLGE_SUPPORT_GE; + + if (speed_ability & HCLGE_SUPPORT_1G_BIT) + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + supported); + + if (speed_ability & HCLGE_SUPPORT_100M_BIT) { + linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, + supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, + supported); + } + + if (speed_ability & HCLGE_SUPPORT_10M_BIT) { + linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, supported); + } + + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported); +} + static void hclge_parse_link_mode(struct hclge_dev *hdev, u8 speed_ability) { u8 media_type = hdev->hw.mac.media_type; - if (media_type != HNAE3_MEDIA_TYPE_FIBER) - return; - - hclge_parse_fiber_link_mode(hdev, speed_ability); + if (media_type == HNAE3_MEDIA_TYPE_FIBER) + hclge_parse_fiber_link_mode(hdev, speed_ability); + else if (media_type == HNAE3_MEDIA_TYPE_COPPER) + hclge_parse_copper_link_mode(hdev, speed_ability); } static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index c939f4a7f5f0..3303919d089d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -188,6 +188,10 @@ enum HLCGE_PORT_TYPE { #define HCLGE_SUPPORT_25G_BIT BIT(2) #define HCLGE_SUPPORT_50G_BIT BIT(3) #define HCLGE_SUPPORT_100G_BIT BIT(4) +#define HCLGE_SUPPORT_100M_BIT BIT(6) +#define HCLGE_SUPPORT_10M_BIT BIT(7) +#define HCLGE_SUPPORT_GE \ + (HCLGE_SUPPORT_1G_BIT | HCLGE_SUPPORT_100M_BIT | HCLGE_SUPPORT_10M_BIT) enum HCLGE_DEV_STATE { HCLGE_STATE_REINITING, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c index 84f28785ba28..48eda2c6fdae 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c @@ -8,12 +8,6 @@ #include "hclge_main.h" #include "hclge_mdio.h" -#define HCLGE_PHY_SUPPORTED_FEATURES (SUPPORTED_Autoneg | \ - SUPPORTED_TP | \ - PHY_10BT_FEATURES | \ - PHY_100BT_FEATURES | \ - SUPPORTED_1000baseT_Full) - enum hclge_mdio_c22_op_seq { HCLGE_MDIO_C22_WRITE = 1, HCLGE_MDIO_C22_READ = 2 @@ -217,16 +211,9 @@ int hclge_mac_connect_phy(struct hnae3_handle *handle) return ret; } - linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, mask); - linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, mask); - linkmode_set_bit_array(phy_10_100_features_array, - ARRAY_SIZE(phy_10_100_features_array), - mask); - linkmode_set_bit_array(phy_gbit_features_array, - ARRAY_SIZE(phy_gbit_features_array), - mask); + linkmode_copy(mask, hdev->hw.mac.supported); linkmode_and(phydev->supported, phydev->supported, mask); - phy_support_asym_pause(phydev); + linkmode_copy(phydev->advertising, phydev->supported); return 0; } -- cgit v1.2.3 From 3d69e59f42bdd57c2a185da52f9579c33dec7121 Mon Sep 17 00:00:00 2001 From: Weihang Li Date: Wed, 20 Feb 2019 10:32:44 +0800 Subject: net: hns3: modify print message of ssu common ecc errors This patch add information of specific bit in log to be consistent with other type of errors, so that we can know which memory of ssu has occurred a ecc ras errors. Signed-off-by: Weihang Li Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 45 +++++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index d0f654123b9b..c9c2c850aee4 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -277,6 +277,45 @@ static const struct hclge_hw_error hclge_ssu_com_err_int[] = { { /* sentinel */ } }; +#define HCLGE_SSU_MEM_ECC_ERR(x) \ + { .int_msk = BIT(x), .msg = "ssu_mem" #x "_ecc_mbit_err" } + +static const struct hclge_hw_error hclge_ssu_mem_ecc_err_int[] = { + HCLGE_SSU_MEM_ECC_ERR(0), + HCLGE_SSU_MEM_ECC_ERR(1), + HCLGE_SSU_MEM_ECC_ERR(2), + HCLGE_SSU_MEM_ECC_ERR(3), + HCLGE_SSU_MEM_ECC_ERR(4), + HCLGE_SSU_MEM_ECC_ERR(5), + HCLGE_SSU_MEM_ECC_ERR(6), + HCLGE_SSU_MEM_ECC_ERR(7), + HCLGE_SSU_MEM_ECC_ERR(8), + HCLGE_SSU_MEM_ECC_ERR(9), + HCLGE_SSU_MEM_ECC_ERR(10), + HCLGE_SSU_MEM_ECC_ERR(11), + HCLGE_SSU_MEM_ECC_ERR(12), + HCLGE_SSU_MEM_ECC_ERR(13), + HCLGE_SSU_MEM_ECC_ERR(14), + HCLGE_SSU_MEM_ECC_ERR(15), + HCLGE_SSU_MEM_ECC_ERR(16), + HCLGE_SSU_MEM_ECC_ERR(17), + HCLGE_SSU_MEM_ECC_ERR(18), + HCLGE_SSU_MEM_ECC_ERR(19), + HCLGE_SSU_MEM_ECC_ERR(20), + HCLGE_SSU_MEM_ECC_ERR(21), + HCLGE_SSU_MEM_ECC_ERR(22), + HCLGE_SSU_MEM_ECC_ERR(23), + HCLGE_SSU_MEM_ECC_ERR(24), + HCLGE_SSU_MEM_ECC_ERR(25), + HCLGE_SSU_MEM_ECC_ERR(26), + HCLGE_SSU_MEM_ECC_ERR(27), + HCLGE_SSU_MEM_ECC_ERR(28), + HCLGE_SSU_MEM_ECC_ERR(29), + HCLGE_SSU_MEM_ECC_ERR(30), + HCLGE_SSU_MEM_ECC_ERR(31), + { /* sentinel */ } +}; + static const struct hclge_hw_error hclge_ssu_port_based_err_int[] = { { .int_msk = BIT(0), .msg = "roc_pkt_without_key_port" }, { .int_msk = BIT(1), .msg = "tpu_pkt_without_key_port" }, @@ -835,13 +874,15 @@ static int hclge_handle_mpf_ras_error(struct hclge_dev *hdev, desc_data = (__le32 *)&desc[2]; status = le32_to_cpu(*(desc_data + 2)); if (status) { - dev_warn(dev, "SSU_ECC_MULTI_BIT_INT_0 ssu_ecc_mbit_int[31:0]\n"); + hclge_log_error(dev, "SSU_ECC_MULTI_BIT_INT_0", + &hclge_ssu_mem_ecc_err_int[0], status); HCLGE_SET_DEFAULT_RESET_REQUEST(HNAE3_CORE_RESET); } status = le32_to_cpu(*(desc_data + 3)) & BIT(0); if (status) { - dev_warn(dev, "SSU_ECC_MULTI_BIT_INT_1 ssu_ecc_mbit_int[32]\n"); + dev_warn(dev, "SSU_ECC_MULTI_BIT_INT_1 ssu_mem32_ecc_mbit_err found [error status=0x%x]\n", + status); HCLGE_SET_DEFAULT_RESET_REQUEST(HNAE3_CORE_RESET); } -- cgit v1.2.3 From 747fc3f351baa061b41a1e2a81821bc963e4f794 Mon Sep 17 00:00:00 2001 From: Weihang Li Date: Wed, 20 Feb 2019 10:32:45 +0800 Subject: net: hns3: some bugfix of ppu(rcb) ras errors The 3rd and 4th of PPU(RCB) PF Abnormal is RAS errors instead of MSI-X like other bits. This patch adds process of handling and logging this two bits. Otherwise, this patch modifies print message of 28th and 29th bit of PPU MPF Abnormal errors, which keep same with other errors now. Fixes: f69b10b317f9 ("net: hns3: handle hw errors of PPU(RCB)") Signed-off-by: Weihang Li Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 16 +++++++++++----- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index c9c2c850aee4..4951684cf4d0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -1038,6 +1038,13 @@ static int hclge_handle_pf_ras_error(struct hclge_dev *hdev, hclge_log_error(dev, "IGU_EGU_TNL_INT_STS", &hclge_igu_egu_tnl_int[0], status); + /* log PPU(RCB) errors */ + desc_data = (__le32 *)&desc[3]; + status = le32_to_cpu(*desc_data) & HCLGE_PPU_PF_INT_RAS_MASK; + if (status) + hclge_log_error(dev, "PPU_PF_ABNORMAL_INT_ST0", + &hclge_ppu_pf_abnormal_int[0], status); + /* clear all PF RAS errors */ hclge_cmd_reuse_desc(&desc[0], false); desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); @@ -1373,14 +1380,13 @@ int hclge_handle_hw_msix_error(struct hclge_dev *hdev, set_bit(HNAE3_GLOBAL_RESET, reset_requests); } - /* log PPU(RCB) errors */ + /* log PPU(RCB) MPF errors */ desc_data = (__le32 *)&desc[5]; status = le32_to_cpu(*(desc_data + 2)) & HCLGE_PPU_MPF_INT_ST2_MSIX_MASK; if (status) { - dev_warn(dev, - "PPU_MPF_ABNORMAL_INT_ST2[28:29], err_status(0x%x)\n", - status); + hclge_log_error(dev, "PPU_MPF_ABNORMAL_INT_ST2", + &hclge_ppu_mpf_abnormal_int_st2[0], status); set_bit(HNAE3_CORE_RESET, reset_requests); } @@ -1427,7 +1433,7 @@ int hclge_handle_hw_msix_error(struct hclge_dev *hdev, hclge_log_error(dev, "PPP_PF_ABNORMAL_INT_ST0", &hclge_ppp_pf_abnormal_int[0], status); - /* PPU(RCB) PF errors */ + /* log PPU(RCB) PF errors */ desc_data = (__le32 *)&desc[3]; status = le32_to_cpu(*desc_data) & HCLGE_PPU_PF_INT_MSIX_MASK; if (status) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h index 51a7d4eb066a..86d6143068c1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -79,6 +79,7 @@ #define HCLGE_PPP_MPF_INT_ST3_MASK GENMASK(5, 0) #define HCLGE_PPU_MPF_INT_ST3_MASK GENMASK(7, 0) #define HCLGE_PPU_MPF_INT_ST2_MSIX_MASK GENMASK(29, 28) +#define HCLGE_PPU_PF_INT_RAS_MASK 0x18 #define HCLGE_PPU_PF_INT_MSIX_MASK 0x27 #define HCLGE_QCN_FIFO_INT_MASK GENMASK(17, 0) #define HCLGE_QCN_ECC_INT_MASK GENMASK(21, 0) -- cgit v1.2.3 From d1f55d6bfcf007691a6392ca421cf5fa1b007d1c Mon Sep 17 00:00:00 2001 From: Weihang Li Date: Wed, 20 Feb 2019 10:32:46 +0800 Subject: net: hns3: enable 8~11th bit of mac common msi-x error These bits are enabled now and have been test. Signed-off-by: Weihang Li Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 6 ++++++ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index 4951684cf4d0..f0f1221fae8b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -219,6 +219,12 @@ static const struct hclge_hw_error hclge_mac_afifo_tnl_int[] = { { .int_msk = BIT(5), .msg = "cge_igu_afifo_ecc_mbit_err" }, { .int_msk = BIT(6), .msg = "lge_igu_afifo_ecc_1bit_err" }, { .int_msk = BIT(7), .msg = "lge_igu_afifo_ecc_mbit_err" }, + { .int_msk = BIT(8), .msg = "cge_igu_afifo_overflow_err" }, + { .int_msk = BIT(9), .msg = "lge_igu_afifo_overflow_err" }, + { .int_msk = BIT(10), .msg = "egu_cge_afifo_underrun_err" }, + { .int_msk = BIT(11), .msg = "egu_lge_afifo_underrun_err" }, + { .int_msk = BIT(12), .msg = "egu_ge_afifo_underrun_err" }, + { .int_msk = BIT(13), .msg = "ge_igu_afifo_overflow_err" }, { /* sentinel */ } }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h index 86d6143068c1..fc068280d391 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h @@ -45,8 +45,8 @@ #define HCLGE_TM_QCN_MEM_ERR_INT_EN 0xFFFFFF #define HCLGE_NCSI_ERR_INT_EN 0x3 #define HCLGE_NCSI_ERR_INT_TYPE 0x9 -#define HCLGE_MAC_COMMON_ERR_INT_EN GENMASK(7, 0) -#define HCLGE_MAC_COMMON_ERR_INT_EN_MASK GENMASK(7, 0) +#define HCLGE_MAC_COMMON_ERR_INT_EN 0x107FF +#define HCLGE_MAC_COMMON_ERR_INT_EN_MASK 0x107FF #define HCLGE_PPU_MPF_ABNORMAL_INT0_EN GENMASK(31, 0) #define HCLGE_PPU_MPF_ABNORMAL_INT0_EN_MASK GENMASK(31, 0) #define HCLGE_PPU_MPF_ABNORMAL_INT1_EN GENMASK(31, 0) -- cgit v1.2.3 From 3aff0ac97391fe4181fd68f06b8fec345f7d1bc5 Mon Sep 17 00:00:00 2001 From: Weihang Li Date: Wed, 20 Feb 2019 10:32:47 +0800 Subject: net: hns3: fix 6th bit of ppp mpf abnormal errors This patch modify print message of 6th bit of ppp mpf abnormal errors, there is a extra letter e in it. Signed-off-by: Weihang Li Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index f0f1221fae8b..b9d363fa595a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -80,7 +80,7 @@ static const struct hclge_hw_error hclge_ppp_mpf_abnormal_int_st1[] = { { .int_msk = BIT(3), .msg = "umv_key_mem1_ecc_mbit_err" }, { .int_msk = BIT(4), .msg = "umv_key_mem2_ecc_mbit_err" }, { .int_msk = BIT(5), .msg = "umv_key_mem3_ecc_mbit_err" }, - { .int_msk = BIT(6), .msg = "umv_ad_mem_ecc_mbit_erre" }, + { .int_msk = BIT(6), .msg = "umv_ad_mem_ecc_mbit_err" }, { .int_msk = BIT(7), .msg = "rss_tc_mode_mem_ecc_mbit_err" }, { .int_msk = BIT(8), .msg = "rss_idt_mem0_ecc_mbit_err" }, { .int_msk = BIT(9), .msg = "rss_idt_mem1_ecc_mbit_err" }, -- cgit v1.2.3 From 6dd86902f21d096ed7ef2dcc921ee80c73807313 Mon Sep 17 00:00:00 2001 From: liuzhongzhu Date: Wed, 20 Feb 2019 10:32:48 +0800 Subject: net: hns3: Record VF unicast and multicast tables Record the unicast and multicast tables that the VF sends to the chip. After the VF exception, the PF actively clears the VF to chip config. Signed-off-by: liuzhongzhu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h | 2 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 102 +++++++++++++++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 25 +++++ .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 28 +++++- 4 files changed, 156 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 53089cd980d9..9b6b7b45dde3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -42,6 +42,8 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_GET_QID_IN_PF, /* (VF -> PF) get queue id in pf */ HCLGE_MBX_LINK_STAT_MODE, /* (PF -> VF) link mode has changed */ HCLGE_MBX_GET_LINK_MODE, /* (VF -> PF) get the link mode of pf */ + + HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */ }; /* below are per-VF mac-vlan subcodes */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 87edac45c040..b1f5c6fa6954 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1329,6 +1329,8 @@ static int hclge_alloc_vport(struct hclge_dev *hdev) vport->back = hdev; vport->vport_id = i; vport->mps = HCLGE_MAC_DEFAULT_FRAME; + INIT_LIST_HEAD(&vport->uc_mac_list); + INIT_LIST_HEAD(&vport->mc_mac_list); if (i == 0) ret = hclge_vport_setup(vport, tqp_main_vport); @@ -6074,6 +6076,103 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport, return status; } +void hclge_add_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr, + enum HCLGE_MAC_ADDR_TYPE mac_type) +{ + struct hclge_vport_mac_addr_cfg *mac_cfg; + struct list_head *list; + + if (!vport->vport_id) + return; + + mac_cfg = kzalloc(sizeof(*mac_cfg), GFP_KERNEL); + if (!mac_cfg) + return; + + mac_cfg->hd_tbl_status = true; + memcpy(mac_cfg->mac_addr, mac_addr, ETH_ALEN); + + list = (mac_type == HCLGE_MAC_ADDR_UC) ? + &vport->uc_mac_list : &vport->mc_mac_list; + + list_add_tail(&mac_cfg->node, list); +} + +void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr, + bool is_write_tbl, + enum HCLGE_MAC_ADDR_TYPE mac_type) +{ + struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp; + struct list_head *list; + bool uc_flag, mc_flag; + + list = (mac_type == HCLGE_MAC_ADDR_UC) ? + &vport->uc_mac_list : &vport->mc_mac_list; + + uc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_UC; + mc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_MC; + + list_for_each_entry_safe(mac_cfg, tmp, list, node) { + if (strncmp(mac_cfg->mac_addr, mac_addr, ETH_ALEN) == 0) { + if (uc_flag && mac_cfg->hd_tbl_status) + hclge_rm_uc_addr_common(vport, mac_addr); + + if (mc_flag && mac_cfg->hd_tbl_status) + hclge_rm_mc_addr_common(vport, mac_addr); + + list_del(&mac_cfg->node); + kfree(mac_cfg); + break; + } + } +} + +void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, + enum HCLGE_MAC_ADDR_TYPE mac_type) +{ + struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp; + struct list_head *list; + + list = (mac_type == HCLGE_MAC_ADDR_UC) ? + &vport->uc_mac_list : &vport->mc_mac_list; + + list_for_each_entry_safe(mac_cfg, tmp, list, node) { + if (mac_type == HCLGE_MAC_ADDR_UC && mac_cfg->hd_tbl_status) + hclge_rm_uc_addr_common(vport, mac_cfg->mac_addr); + + if (mac_type == HCLGE_MAC_ADDR_MC && mac_cfg->hd_tbl_status) + hclge_rm_mc_addr_common(vport, mac_cfg->mac_addr); + + mac_cfg->hd_tbl_status = false; + if (is_del_list) { + list_del(&mac_cfg->node); + kfree(mac_cfg); + } + } +} + +void hclge_uninit_vport_mac_table(struct hclge_dev *hdev) +{ + struct hclge_vport_mac_addr_cfg *mac, *tmp; + struct hclge_vport *vport; + int i; + + mutex_lock(&hdev->vport_cfg_mutex); + for (i = 0; i < hdev->num_alloc_vport; i++) { + vport = &hdev->vport[i]; + list_for_each_entry_safe(mac, tmp, &vport->uc_mac_list, node) { + list_del(&mac->node); + kfree(mac); + } + + list_for_each_entry_safe(mac, tmp, &vport->mc_mac_list, node) { + list_del(&mac->node); + kfree(mac); + } + } + mutex_unlock(&hdev->vport_cfg_mutex); +} + static int hclge_get_mac_ethertype_cmd_status(struct hclge_dev *hdev, u16 cmdq_resp, u8 resp_code) { @@ -7329,6 +7428,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) hdev->mps = ETH_FRAME_LEN + ETH_FCS_LEN + 2 * VLAN_HLEN; mutex_init(&hdev->vport_lock); + mutex_init(&hdev->vport_cfg_mutex); ret = hclge_pci_init(hdev); if (ret) { @@ -7621,6 +7721,8 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_misc_irq_uninit(hdev); hclge_pci_uninit(hdev); mutex_destroy(&hdev->vport_lock); + hclge_uninit_vport_mac_table(hdev); + mutex_destroy(&hdev->vport_cfg_mutex); ae_dev->priv = NULL; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 3303919d089d..781bd1145e2c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -632,6 +632,17 @@ struct hclge_fd_ad_data { u16 rule_id; }; +struct hclge_vport_mac_addr_cfg { + struct list_head node; + int hd_tbl_status; + u8 mac_addr[ETH_ALEN]; +}; + +enum HCLGE_MAC_ADDR_TYPE { + HCLGE_MAC_ADDR_UC, + HCLGE_MAC_ADDR_MC +}; + /* For each bit of TCAM entry, it uses a pair of 'x' and * 'y' to indicate which value to match, like below: * ---------------------------------- @@ -771,6 +782,8 @@ struct hclge_dev { /* unicast mac vlan space shared by PF and its VFs */ u16 share_umv_size; struct mutex umv_mutex; /* protect share_umv_size */ + + struct mutex vport_cfg_mutex; /* Protect stored vf table */ }; /* VPort level vlan tag configuration for TX direction */ @@ -838,6 +851,9 @@ struct hclge_vport { unsigned long state; unsigned long last_active_jiffies; u32 mps; /* Max packet size */ + + struct list_head uc_mac_list; /* Store VF unicast table */ + struct list_head mc_mac_list; /* Store VF multicast table */ }; void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc, @@ -892,4 +908,13 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf); u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id); int hclge_notify_client(struct hclge_dev *hdev, enum hnae3_reset_notify_type type); +void hclge_add_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr, + enum HCLGE_MAC_ADDR_TYPE mac_type); +void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr, + bool is_write_tbl, + enum HCLGE_MAC_ADDR_TYPE mac_type); +void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, + enum HCLGE_MAC_ADDR_TYPE mac_type); +void hclge_uninit_vport_mac_table(struct hclge_dev *hdev); + #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 7e4a104582d6..476ca8399446 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -224,12 +224,24 @@ static int hclge_set_vf_uc_mac_addr(struct hclge_vport *vport, hclge_rm_uc_addr_common(vport, old_addr); status = hclge_add_uc_addr_common(vport, mac_addr); - if (status) + if (status) { hclge_add_uc_addr_common(vport, old_addr); + } else { + hclge_rm_vport_mac_table(vport, mac_addr, + false, HCLGE_MAC_ADDR_UC); + hclge_add_vport_mac_table(vport, mac_addr, + HCLGE_MAC_ADDR_UC); + } } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_ADD) { status = hclge_add_uc_addr_common(vport, mac_addr); + if (!status) + hclge_add_vport_mac_table(vport, mac_addr, + HCLGE_MAC_ADDR_UC); } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_REMOVE) { status = hclge_rm_uc_addr_common(vport, mac_addr); + if (!status) + hclge_rm_vport_mac_table(vport, mac_addr, + false, HCLGE_MAC_ADDR_UC); } else { dev_err(&hdev->pdev->dev, "failed to set unicast mac addr, unknown subcode %d\n", @@ -255,8 +267,14 @@ static int hclge_set_vf_mc_mac_addr(struct hclge_vport *vport, if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_ADD) { status = hclge_add_mc_addr_common(vport, mac_addr); + if (!status) + hclge_add_vport_mac_table(vport, mac_addr, + HCLGE_MAC_ADDR_MC); } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_REMOVE) { status = hclge_rm_mc_addr_common(vport, mac_addr); + if (!status) + hclge_rm_vport_mac_table(vport, mac_addr, + false, HCLGE_MAC_ADDR_MC); } else { dev_err(&hdev->pdev->dev, "failed to set mcast mac addr, unknown subcode %d\n", @@ -585,6 +603,14 @@ void hclge_mbx_handler(struct hclge_dev *hdev) case HCLGE_MBX_GET_LINK_MODE: hclge_get_link_mode(vport, req); break; + case HCLGE_MBX_GET_VF_FLR_STATUS: + mutex_lock(&hdev->vport_cfg_mutex); + hclge_rm_vport_all_mac_table(vport, true, + HCLGE_MAC_ADDR_UC); + hclge_rm_vport_all_mac_table(vport, true, + HCLGE_MAC_ADDR_MC); + mutex_unlock(&hdev->vport_cfg_mutex); + break; default: dev_err(&hdev->pdev->dev, "un-supported mailbox message, code = %d\n", -- cgit v1.2.3 From c6075b193462d9a3930fb41f587f94720658752a Mon Sep 17 00:00:00 2001 From: liuzhongzhu Date: Wed, 20 Feb 2019 10:32:49 +0800 Subject: net: hns3: Record VF vlan tables Record the vlan tables that the VF sends to the chip. After the VF exception, the PF actively clears the VF to chip config. Signed-off-by: liuzhongzhu Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 80 ++++++++++++++++++++++ .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 13 +++- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++ 3 files changed, 96 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index b1f5c6fa6954..4a596460271c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1329,6 +1329,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev) vport->back = hdev; vport->vport_id = i; vport->mps = HCLGE_MAC_DEFAULT_FRAME; + INIT_LIST_HEAD(&vport->vlan_list); INIT_LIST_HEAD(&vport->uc_mac_list); INIT_LIST_HEAD(&vport->mc_mac_list); @@ -6746,6 +6747,84 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev) return hclge_set_vlan_filter(handle, htons(ETH_P_8021Q), 0, false); } +void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id) +{ + struct hclge_vport_vlan_cfg *vlan; + + /* vlan 0 is reserved */ + if (!vlan_id) + return; + + vlan = kzalloc(sizeof(*vlan), GFP_KERNEL); + if (!vlan) + return; + + vlan->hd_tbl_status = true; + vlan->vlan_id = vlan_id; + + list_add_tail(&vlan->node, &vport->vlan_list); +} + +void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id, + bool is_write_tbl) +{ + struct hclge_vport_vlan_cfg *vlan, *tmp; + struct hclge_dev *hdev = vport->back; + + list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) { + if (vlan->vlan_id == vlan_id) { + if (is_write_tbl && vlan->hd_tbl_status) + hclge_set_vlan_filter_hw(hdev, + htons(ETH_P_8021Q), + vport->vport_id, + vlan_id, 0, + true); + + list_del(&vlan->node); + kfree(vlan); + break; + } + } +} + +void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list) +{ + struct hclge_vport_vlan_cfg *vlan, *tmp; + struct hclge_dev *hdev = vport->back; + + list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) { + if (vlan->hd_tbl_status) + hclge_set_vlan_filter_hw(hdev, + htons(ETH_P_8021Q), + vport->vport_id, + vlan->vlan_id, 0, + true); + + vlan->hd_tbl_status = false; + if (is_del_list) { + list_del(&vlan->node); + kfree(vlan); + } + } +} + +void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev) +{ + struct hclge_vport_vlan_cfg *vlan, *tmp; + struct hclge_vport *vport; + int i; + + mutex_lock(&hdev->vport_cfg_mutex); + for (i = 0; i < hdev->num_alloc_vport; i++) { + vport = &hdev->vport[i]; + list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) { + list_del(&vlan->node); + kfree(vlan); + } + } + mutex_unlock(&hdev->vport_cfg_mutex); +} + int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable) { struct hclge_vport *vport = hclge_get_vport(handle); @@ -7722,6 +7801,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) hclge_pci_uninit(hdev); mutex_destroy(&hdev->vport_lock); hclge_uninit_vport_mac_table(hdev); + hclge_uninit_vport_vlan_table(hdev); mutex_destroy(&hdev->vport_cfg_mutex); ae_dev->priv = NULL; } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 781bd1145e2c..abbc58ea4864 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -643,6 +643,12 @@ enum HCLGE_MAC_ADDR_TYPE { HCLGE_MAC_ADDR_MC }; +struct hclge_vport_vlan_cfg { + struct list_head node; + int hd_tbl_status; + u16 vlan_id; +}; + /* For each bit of TCAM entry, it uses a pair of 'x' and * 'y' to indicate which value to match, like below: * ---------------------------------- @@ -854,6 +860,7 @@ struct hclge_vport { struct list_head uc_mac_list; /* Store VF unicast table */ struct list_head mc_mac_list; /* Store VF multicast table */ + struct list_head vlan_list; /* Store VF vlan table */ }; void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc, @@ -916,5 +923,9 @@ void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr, void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list, enum HCLGE_MAC_ADDR_TYPE mac_type); void hclge_uninit_vport_mac_table(struct hclge_dev *hdev); - +void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id); +void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id, + bool is_write_tbl); +void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list); +void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 476ca8399446..9e0952c329bb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -305,6 +305,9 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport, memcpy(&proto, &mbx_req->msg[5], sizeof(proto)); status = hclge_set_vlan_filter(handle, cpu_to_be16(proto), vlan, is_kill); + if (!status) + is_kill ? hclge_rm_vport_vlan_table(vport, vlan, false) + : hclge_add_vport_vlan_table(vport, vlan); } else if (mbx_req->msg[1] == HCLGE_MBX_VLAN_RX_OFF_CFG) { struct hnae3_handle *handle = &vport->nic; bool en = mbx_req->msg[2] ? true : false; @@ -609,6 +612,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev) HCLGE_MAC_ADDR_UC); hclge_rm_vport_all_mac_table(vport, true, HCLGE_MAC_ADDR_MC); + hclge_rm_vport_all_vlan_table(vport, true); mutex_unlock(&hdev->vport_cfg_mutex); break; default: -- cgit v1.2.3 From 232d0d55fca6ab589d5267c74a376210f341d71e Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Wed, 20 Feb 2019 10:32:50 +0800 Subject: net: hns3: uninitialize command queue while unloading PF driver According to the hardware's description, the driver should clear the command queue's registers when uloading driver. Otherwise, these existing value may lead the IMP get into a wrong state. Also this patch adds hclge_cmd_uninit() to do the command queue uninitialization which includes clearing registers and freeing memory. Fixes: 68c0a5c70614 ("net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd Interface Support") Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 26 ++++++++++++++++++++++ .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 ++-- 3 files changed, 29 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c index 1dddfcba41a9..3a093a92eac5 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c @@ -390,6 +390,20 @@ int hclge_cmd_init(struct hclge_dev *hdev) return 0; } +static void hclge_cmd_uninit_regs(struct hclge_hw *hw) +{ + hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_L_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CSQ_HEAD_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_L_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_H_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CRQ_DEPTH_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CRQ_HEAD_REG, 0); + hclge_write_dev(hw, HCLGE_NIC_CRQ_TAIL_REG, 0); +} + static void hclge_destroy_queue(struct hclge_cmq_ring *ring) { spin_lock(&ring->lock); @@ -402,3 +416,15 @@ void hclge_destroy_cmd_queue(struct hclge_hw *hw) hclge_destroy_queue(&hw->cmq.csq); hclge_destroy_queue(&hw->cmq.crq); } + +void hclge_cmd_uninit(struct hclge_dev *hdev) +{ + spin_lock_bh(&hdev->hw.cmq.csq.lock); + spin_lock(&hdev->hw.cmq.crq.lock); + set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state); + hclge_cmd_uninit_regs(&hdev->hw); + spin_unlock(&hdev->hw.cmq.crq.lock); + spin_unlock_bh(&hdev->hw.cmq.csq.lock); + + hclge_destroy_cmd_queue(&hdev->hw); +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index ac2cd219a9fb..bad21c89f6b7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -975,6 +975,6 @@ enum hclge_cmd_status hclge_cmd_mdio_write(struct hclge_hw *hw, enum hclge_cmd_status hclge_cmd_mdio_read(struct hclge_hw *hw, struct hclge_desc *desc); -void hclge_destroy_cmd_queue(struct hclge_hw *hw); +void hclge_cmd_uninit(struct hclge_dev *hdev); int hclge_cmd_queue_init(struct hclge_dev *hdev); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 4a596460271c..5c8f2e4d71c9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -7669,7 +7669,7 @@ err_msi_irq_uninit: err_msi_uninit: pci_free_irq_vectors(pdev); err_cmd_uninit: - hclge_destroy_cmd_queue(&hdev->hw); + hclge_cmd_uninit(hdev); err_pci_uninit: pcim_iounmap(pdev, hdev->hw.io_base); pci_clear_master(pdev); @@ -7796,7 +7796,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) synchronize_irq(hdev->misc_vector.vector_irq); hclge_hw_error_set_state(hdev, false); - hclge_destroy_cmd_queue(&hdev->hw); + hclge_cmd_uninit(hdev); hclge_misc_irq_uninit(hdev); hclge_pci_uninit(hdev); mutex_destroy(&hdev->vport_lock); -- cgit v1.2.3 From 34f81f049e354082f638820afe5e59bbd243fb18 Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Wed, 20 Feb 2019 10:32:51 +0800 Subject: net: hns3: clear command queue's registers when unloading VF driver According to the hardware's description, the driver should clear the command queue's registers when uloading VF driver. Otherwise, these existing value may lead the IMP get into a wrong state. Fixes: fedd0c15d288 ("net: hns3: Add HNS3 VF IMP(Integrated Management Proc) cmd interface") Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c index 4e78e8812a04..9441b453d38d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c @@ -362,8 +362,28 @@ int hclgevf_cmd_init(struct hclgevf_dev *hdev) return 0; } +static void hclgevf_cmd_uninit_regs(struct hclgevf_hw *hw) +{ + hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_L_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_H_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_DEPTH_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_HEAD_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_TAIL_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_L_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_H_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_DEPTH_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_HEAD_REG, 0); + hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_TAIL_REG, 0); +} + void hclgevf_cmd_uninit(struct hclgevf_dev *hdev) { + spin_lock_bh(&hdev->hw.cmq.csq.lock); + spin_lock(&hdev->hw.cmq.crq.lock); + clear_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state); + hclgevf_cmd_uninit_regs(&hdev->hw); + spin_unlock(&hdev->hw.cmq.crq.lock); + spin_unlock_bh(&hdev->hw.cmq.csq.lock); hclgevf_free_cmd_desc(&hdev->hw.cmq.csq); hclgevf_free_cmd_desc(&hdev->hw.cmq.crq); } -- cgit v1.2.3 From 7a25c6c0aac85bbc50d3ce49cd08888adb14508b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 21 Feb 2019 18:26:46 -0800 Subject: rocker: Add missing break for PRE_BRIDGE_FLAGS A missing break keyword should have been added after adding support for PRE_BRIDGE_FLAGS. Reported-by: Stephen Rothwell Fixes: 93700458ff63 ("rocker: Check Handle PORT_PRE_BRIDGE_FLAGS") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 8200fbf91306..309a6bf9130c 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2083,6 +2083,7 @@ static int rocker_port_attr_set(struct net_device *dev, err = rocker_world_port_attr_pre_bridge_flags_set(rocker_port, attr->u.brport_flags, trans); + break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = rocker_world_port_attr_bridge_flags_set(rocker_port, attr->u.brport_flags, -- cgit v1.2.3 From 77ff2c6b49843b01adef1f80abb091753e4c9c65 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Wed, 6 Feb 2019 13:17:20 +0200 Subject: mac80211: update HE IEs to D3.3 Update element names and new fields according to D3.3 of the HE spec. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/fw/api/mac.h | 26 +++++++++- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 58 ++++++++-------------- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 40 +++++++++++++++ include/linux/ieee80211.h | 22 +++++--- net/mac80211/debugfs_sta.c | 35 +++++++++---- 5 files changed, 125 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h index 7a3f7b7e6358..941c50477003 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h @@ -7,7 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -29,7 +29,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -433,6 +433,28 @@ struct iwl_he_backoff_conf { __le16 mu_time; } __packed; /* AC_QOS_DOT11AX_API_S */ +/** + * enum iwl_he_pkt_ext_constellations - PPE constellation indices + * @IWL_HE_PKT_EXT_BPSK: BPSK + * @IWL_HE_PKT_EXT_QPSK: QPSK + * @IWL_HE_PKT_EXT_16QAM: 16-QAM + * @IWL_HE_PKT_EXT_64QAM: 64-QAM + * @IWL_HE_PKT_EXT_256QAM: 256-QAM + * @IWL_HE_PKT_EXT_1024QAM: 1024-QAM + * @IWL_HE_PKT_EXT_RESERVED: reserved value + * @IWL_HE_PKT_EXT_NONE: not defined + */ +enum iwl_he_pkt_ext_constellations { + IWL_HE_PKT_EXT_BPSK = 0, + IWL_HE_PKT_EXT_QPSK, + IWL_HE_PKT_EXT_16QAM, + IWL_HE_PKT_EXT_64QAM, + IWL_HE_PKT_EXT_256QAM, + IWL_HE_PKT_EXT_1024QAM, + IWL_HE_PKT_EXT_RESERVED, + IWL_HE_PKT_EXT_NONE, +}; + #define MAX_HE_SUPP_NSS 2 #define MAX_HE_CHANNEL_BW_INDX 4 diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index d9afedc3d1d9..e1178b09c4d5 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -479,7 +479,6 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, .mac_cap_info[2] = IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP | - IEEE80211_HE_MAC_CAP2_MU_CASCADING | IEEE80211_HE_MAC_CAP2_ACK_EN, .mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_OMI_CONTROL | @@ -490,7 +489,9 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { .mac_cap_info[5] = IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B40 | IEEE80211_HE_MAC_CAP5_MULTI_TID_AGG_TX_QOS_B41 | - IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU, + IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU | + IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS | + IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX, .phy_cap_info[0] = IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | @@ -498,18 +499,13 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { .phy_cap_info[1] = IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | - IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD, .phy_cap_info[2] = - IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | - IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | - IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ | - IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | - IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO, + IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US, .phy_cap_info[3] = - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM | IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 | - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM | IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1, .phy_cap_info[4] = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | @@ -517,16 +513,8 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8, .phy_cap_info[5] = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 | - IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2 | - IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | - IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK, + IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2, .phy_cap_info[6] = - IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | - IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | - IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | - IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | - IEEE80211_HE_PHY_CAP6_TRIG_CQI_FB | - IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT, .phy_cap_info[7] = IEEE80211_HE_PHY_CAP7_POWER_BOOST_FACTOR_AR | @@ -537,11 +525,12 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU | - IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_160_OR_80P80_MHZ, + IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996, .phy_cap_info[9] = IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK | IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | - IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB, + IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB | + IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED, }, /* * Set default Tx/Rx HE MCS NSS Support field. @@ -576,28 +565,26 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8, .mac_cap_info[2] = IEEE80211_HE_MAC_CAP2_BSR | - IEEE80211_HE_MAC_CAP2_MU_CASCADING | IEEE80211_HE_MAC_CAP2_ACK_EN, .mac_cap_info[3] = IEEE80211_HE_MAC_CAP3_OMI_CONTROL | IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2, .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU, + .mac_cap_info[5] = + IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU, .phy_cap_info[0] = IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G, .phy_cap_info[1] = - IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD | - IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS, + IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD, .phy_cap_info[2] = - IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US | - IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ | - IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ, + IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US, .phy_cap_info[3] = - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_BPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_TX_NO_DCM | IEEE80211_HE_PHY_CAP3_DCM_MAX_TX_NSS_1 | - IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_BPSK | + IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_NO_DCM | IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1, .phy_cap_info[4] = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE | @@ -605,12 +592,8 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_8, .phy_cap_info[5] = IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_2 | - IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2 | - IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | - IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK, + IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_ABOVE_80MHZ_2, .phy_cap_info[6] = - IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | - IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT, .phy_cap_info[7] = IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI | @@ -620,10 +603,11 @@ static struct ieee80211_sband_iftype_data iwl_he_capa[] = { IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G | IEEE80211_HE_PHY_CAP8_20MHZ_IN_160MHZ_HE_PPDU | IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU | - IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_160_OR_80P80_MHZ, + IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996, .phy_cap_info[9] = IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB | - IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB, + IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB | + IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED, }, /* * Set default Tx/Rx HE MCS NSS Support field. diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 97dc464379d2..47d65adfa3e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -2076,6 +2076,46 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, } flags |= STA_CTXT_HE_PACKET_EXT; + } else if ((sta->he_cap.he_cap_elem.phy_cap_info[9] & + IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) != + IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED) { + int low_th = -1; + int high_th = -1; + + /* Take the PPE thresholds from the nominal padding info */ + switch (sta->he_cap.he_cap_elem.phy_cap_info[9] & + IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) { + case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US: + low_th = IWL_HE_PKT_EXT_NONE; + high_th = IWL_HE_PKT_EXT_NONE; + break; + case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US: + low_th = IWL_HE_PKT_EXT_BPSK; + high_th = IWL_HE_PKT_EXT_NONE; + break; + case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US: + low_th = IWL_HE_PKT_EXT_NONE; + high_th = IWL_HE_PKT_EXT_BPSK; + break; + } + + /* Set the PPE thresholds accordingly */ + if (low_th >= 0 && high_th >= 0) { + u8 ***pkt_ext_qam = + (void *)sta_ctxt_cmd.pkt_ext.pkt_ext_qam_th; + + for (i = 0; i < MAX_HE_SUPP_NSS; i++) { + u8 bw; + + for (bw = 0; bw < MAX_HE_CHANNEL_BW_INDX; + bw++) { + pkt_ext_qam[i][bw][0] = low_th; + pkt_ext_qam[i][bw][1] = high_th; + } + } + + flags |= STA_CTXT_HE_PACKET_EXT; + } } rcu_read_unlock(); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index d9650ae2b4f7..353fb722ab98 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1803,6 +1803,9 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, #define IEEE80211_HE_MAC_CAP5_SUBCHAN_SELECVITE_TRANSMISSION 0x04 #define IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU 0x08 #define IEEE80211_HE_MAC_CAP5_OM_CTRL_UL_MU_DATA_DIS_RX 0x10 +#define IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS 0x20 +#define IEEE80211_HE_MAC_CAP5_PUNCTURED_SOUNDING 0x40 +#define IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX 0x80 /* 802.11ax HE PHY capabilities */ #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 @@ -1926,11 +1929,11 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, #define IEEE80211_HE_PHY_CAP8_80MHZ_IN_160MHZ_HE_PPDU 0x08 #define IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI 0x10 #define IEEE80211_HE_PHY_CAP8_MIDAMBLE_RX_TX_2X_AND_1XLTF 0x20 -#define IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_20MHZ 0x00 -#define IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_40MHZ 0x40 -#define IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_80MHZ 0x80 -#define IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_160_OR_80P80_MHZ 0xc0 -#define IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_MASK 0xc0 +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242 0x00 +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484 0x40 +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996 0x80 +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996 0xc0 +#define IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK 0xc0 #define IEEE80211_HE_PHY_CAP9_LONGER_THAN_16_SIGB_OFDM_SYM 0x01 #define IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK 0x02 @@ -1938,6 +1941,11 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, #define IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU 0x08 #define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10 #define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20 +#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US 0x00 +#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US 0x40 +#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US 0x80 +#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_RESERVED 0xc0 +#define IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK 0xc0 /* 802.11ax HE TX/RX MCS NSS Support */ #define IEEE80211_TX_RX_MCS_NSS_SUPP_HIGHEST_MCS_POS (3) @@ -2016,7 +2024,7 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK 0x00003ff0 #define IEEE80211_HE_OPERATION_RTS_THRESHOLD_OFFSET 4 #define IEEE80211_HE_OPERATION_VHT_OPER_INFO 0x00004000 -#define IEEE80211_HE_OPERATION_CO_LOCATED_BSS 0x00008000 +#define IEEE80211_HE_OPERATION_CO_HOSTED_BSS 0x00008000 #define IEEE80211_HE_OPERATION_ER_SU_DISABLE 0x00010000 #define IEEE80211_HE_OPERATION_BSS_COLOR_MASK 0x3f000000 #define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET 24 @@ -2046,7 +2054,7 @@ ieee80211_he_oper_size(const u8 *he_oper_ie) he_oper_params = le32_to_cpu(he_oper->he_oper_params); if (he_oper_params & IEEE80211_HE_OPERATION_VHT_OPER_INFO) oper_len += 3; - if (he_oper_params & IEEE80211_HE_OPERATION_CO_LOCATED_BSS) + if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS) oper_len++; /* Add the first byte (extension ID) to the total length */ diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 3aa618dcc58e..8e921281e0d5 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -4,7 +4,7 @@ * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -685,6 +685,9 @@ static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf, "SUBCHAN-SELECVITE-TRANSMISSION"); PFLAG(MAC, 5, UL_2x996_TONE_RU, "UL-2x996-TONE-RU"); PFLAG(MAC, 5, OM_CTRL_UL_MU_DATA_DIS_RX, "OM-CTRL-UL-MU-DATA-DIS-RX"); + PFLAG(MAC, 5, HE_DYNAMIC_SM_PS, "HE-DYNAMIC-SM-PS"); + PFLAG(MAC, 5, PUNCTURED_SOUNDING, "PUNCTURED-SOUNDING"); + PFLAG(MAC, 5, HT_VHT_TRIG_FRAME_RX, "HT-VHT-TRIG-FRAME-RX"); cap = hec->he_cap_elem.phy_cap_info; p += scnprintf(p, buf_sz + buf - p, @@ -819,18 +822,18 @@ static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf, PFLAG(PHY, 8, MIDAMBLE_RX_TX_2X_AND_1XLTF, "MIDAMBLE-RX-TX-2X-AND-1XLTF"); - switch (cap[8] & IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_MASK) { - case IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_20MHZ: - PRINT("DDCM-MAX-BW-20MHZ"); + switch (cap[8] & IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_MASK) { + case IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242: + PRINT("DCM-MAX-RU-242"); break; - case IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_40MHZ: - PRINT("DCM-MAX-BW-40MHZ"); + case IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484: + PRINT("DCM-MAX-RU-484"); break; - case IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_80MHZ: - PRINT("DCM-MAX-BW-80MHZ"); + case IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996: + PRINT("DCM-MAX-RU-996"); break; - case IEEE80211_HE_PHY_CAP8_DCM_MAX_BW_160_OR_80P80_MHZ: - PRINT("DCM-MAX-BW-160-OR-80P80-MHZ"); + case IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_2x996: + PRINT("DCM-MAX-RU-2x996"); break; } @@ -847,6 +850,18 @@ static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf, PFLAG(PHY, 9, RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB, "RX-FULL-BW-SU-USING-MU-WITH-NON-COMP-SIGB"); + switch (cap[9] & IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_MASK) { + case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_0US: + PRINT("NOMINAL-PACKET-PADDING-0US"); + break; + case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_8US: + PRINT("NOMINAL-PACKET-PADDING-8US"); + break; + case IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US: + PRINT("NOMINAL-PACKET-PADDING-16US"); + break; + } + #undef PFLAG_RANGE_DEFAULT #undef PFLAG_RANGE #undef PFLAG -- cgit v1.2.3 From 023fb4b51fa975e55b429f624102706f7156395f Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Wed, 20 Feb 2019 07:46:22 +0100 Subject: net: phy: aquantia: Use get_features for the PHYs abilities Use the new PHY driver call to get the PHYs supported features. Signed-off-by: Andrew Lunn [hkallweit1@gmail.com: removed new config_init callback from patch] Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 0f772a47a18e..34be44d00c19 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -156,8 +156,8 @@ static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), .name = "Aquantia AQ1202", - .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, @@ -166,8 +166,8 @@ static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), .name = "Aquantia AQ2104", - .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, @@ -176,8 +176,8 @@ static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQR105), .name = "Aquantia AQR105", - .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, @@ -186,8 +186,8 @@ static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQR106), .name = "Aquantia AQR106", - .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, @@ -196,8 +196,8 @@ static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQR107), .name = "Aquantia AQR107", - .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, @@ -206,8 +206,8 @@ static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), .name = "Aquantia AQCS109", - .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, @@ -216,8 +216,8 @@ static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQR405), .name = "Aquantia AQR405", - .features = PHY_10GBIT_FULL_FEATURES, .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, -- cgit v1.2.3 From 6d20faecc5949a305946559a38c89578e7d68264 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 20 Feb 2019 14:25:26 -0600 Subject: isdn_common: Mark expected switch fall-throughs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warnings: drivers/isdn/i4l/isdn_common.c: In function ‘isdn_wildmat’: drivers/isdn/i4l/isdn_common.c:173:5: warning: this statement may fall through [-Wimplicit-fallthrough=] p++; ~^~ drivers/isdn/i4l/isdn_common.c:174:3: note: here default: ^~~~~~~ CC [M] drivers/leds/leds-lp8788.o CC [M] drivers/gpu/drm/amd/amdgpu/../powerplay/smumgr/smu10_smumgr.o drivers/isdn/i4l/isdn_common.c: In function ‘isdn_status_callback’: drivers/isdn/i4l/isdn_common.c:729:6: warning: this statement may fall through [-Wimplicit-fallthrough=] if (divert_if) ^ drivers/isdn/i4l/isdn_common.c:732:2: note: here default: ^~~~~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_common.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 6a5b3f00f9ad..74ee00f5b310 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -166,11 +166,9 @@ isdn_wildmat(char *s, char *p) for (; *p; s++, p++) switch (*p) { case '\\': - /* - * Literal match with following character, - * fall through. - */ + /* Literal match with following character. */ p++; + /* fall through */ default: if (*s != *p) return (*s == '\0') ? 2 : 1; @@ -729,6 +727,7 @@ isdn_status_callback(isdn_ctrl *c) if (divert_if) return (divert_if->stat_callback(c)); #endif /* CONFIG_ISDN_DIVERSION */ + /* fall through */ default: return -1; } -- cgit v1.2.3 From d2aa125d629080c4f3e31f23b7f612ef6b8492ac Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Thu, 21 Feb 2019 12:39:57 +0000 Subject: net: Don't set transport offset to invalid value If the socket was created with socket(AF_PACKET, SOCK_RAW, 0), skb->protocol will be unset, __skb_flow_dissect() will fail, and skb_probe_transport_header() will fall back to the offset_hint, making the resulting skb_transport_offset incorrect. If, however, there is no transport header in the packet, transport_header shouldn't be set to an arbitrary value. Fix it by leaving the transport offset unset if it couldn't be found, to be explicit rather than to fill it with some wrong value. It changes the behavior, but if some code relied on the old behavior, it would be broken anyway, as the old one is incorrect. Signed-off-by: Maxim Mikityanskiy Signed-off-by: David S. Miller --- drivers/net/tap.c | 4 ++-- drivers/net/tun.c | 4 ++-- drivers/net/xen-netback/netback.c | 15 ++++++++++++--- include/linux/skbuff.h | 5 +---- include/linux/virtio_net.h | 2 +- net/packet/af_packet.c | 6 +++--- 6 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tap.c b/drivers/net/tap.c index c0b52e48f0e6..2ea9b4976f4a 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -712,7 +712,7 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control, goto err_kfree; } - skb_probe_transport_header(skb, ETH_HLEN); + skb_probe_transport_header(skb); /* Move network header to the right position for VLAN tagged packets */ if ((skb->protocol == htons(ETH_P_8021Q) || @@ -1187,7 +1187,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) tap = rcu_dereference(q->tap); if (tap) { skb->dev = tap->dev; - skb_probe_transport_header(skb, ETH_HLEN); + skb_probe_transport_header(skb); dev_queue_xmit(skb); } else { kfree_skb(skb); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index fed298c0cb39..80bff1b4ec17 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1929,7 +1929,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, } skb_reset_network_header(skb); - skb_probe_transport_header(skb, 0); + skb_probe_transport_header(skb); if (skb_xdp) { struct bpf_prog *xdp_prog; @@ -2482,7 +2482,7 @@ build: skb->protocol = eth_type_trans(skb, tun->dev); skb_reset_network_header(skb); - skb_probe_transport_header(skb, 0); + skb_probe_transport_header(skb); if (skb_xdp) { err = do_xdp_generic(xdp_prog, skb); diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 80aae3a32c2a..c801a832851c 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1169,15 +1169,24 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) continue; } - skb_probe_transport_header(skb, 0); + skb_probe_transport_header(skb); /* If the packet is GSO then we will have just set up the * transport header offset in checksum_setup so it's now * straightforward to calculate gso_segs. */ if (skb_is_gso(skb)) { - int mss = skb_shinfo(skb)->gso_size; - int hdrlen = skb_transport_header(skb) - + int mss, hdrlen; + + /* GSO implies having the L4 header. */ + WARN_ON_ONCE(!skb_transport_header_was_set(skb)); + if (unlikely(!skb_transport_header_was_set(skb))) { + kfree_skb(skb); + continue; + } + + mss = skb_shinfo(skb)->gso_size; + hdrlen = skb_transport_header(skb) - skb_mac_header(skb) + tcp_hdrlen(skb); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2069fb90a559..27beb549ffbe 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2429,8 +2429,7 @@ static inline void skb_pop_mac_header(struct sk_buff *skb) skb->mac_header = skb->network_header; } -static inline void skb_probe_transport_header(struct sk_buff *skb, - const int offset_hint) +static inline void skb_probe_transport_header(struct sk_buff *skb) { struct flow_keys_basic keys; @@ -2439,8 +2438,6 @@ static inline void skb_probe_transport_header(struct sk_buff *skb, if (skb_flow_dissect_flow_keys_basic(skb, &keys, NULL, 0, 0, 0, 0)) skb_set_transport_header(skb, keys.control.thoff); - else if (offset_hint >= 0) - skb_set_transport_header(skb, offset_hint); } static inline void skb_mac_header_rebuild(struct sk_buff *skb) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 71f2394abbf7..6728bf581e98 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -62,7 +62,7 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, * probe and drop if does not match one of the above types. */ if (gso_type) { - skb_probe_transport_header(skb, -1); + skb_probe_transport_header(skb); if (!skb_transport_header_was_set(skb)) return -EINVAL; } diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 1cd1d83a4be0..6afd6369d19e 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1970,7 +1970,7 @@ retry: if (unlikely(extra_len == 4)) skb->no_fcs = 1; - skb_probe_transport_header(skb, 0); + skb_probe_transport_header(skb); dev_queue_xmit(skb); rcu_read_unlock(); @@ -2519,7 +2519,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, len = ((to_write > len_max) ? len_max : to_write); } - skb_probe_transport_header(skb, 0); + skb_probe_transport_header(skb); return tp_len; } @@ -2925,7 +2925,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) virtio_net_hdr_set_proto(skb, &vnet_hdr); } - skb_probe_transport_header(skb, reserve); + skb_probe_transport_header(skb); if (unlikely(extra_len == 4)) skb->no_fcs = 1; -- cgit v1.2.3 From 3517dfe6f23608951044cbfc833fa108603441fa Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Thu, 21 Feb 2019 12:40:04 +0000 Subject: net/mlx5e: Remove the wrong assumption about transport offset skb_transport_offset() == 0 is not a special value. The only special value is when skb->transport_header is ~0U, and it's checked by skb_transport_header_was_set(). Signed-off-by: Maxim Mikityanskiy Reviewed-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index c1334a8ac8f3..6ca834702306 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -172,15 +172,8 @@ static inline u16 mlx5e_calc_min_inline(enum mlx5_inline_modes mode, hlen += VLAN_HLEN; break; case MLX5_INLINE_MODE_IP: - /* When transport header is set to zero, it means no transport - * header. When transport header is set to 0xff's, it means - * transport header wasn't set. - */ - if (skb_transport_offset(skb)) { - hlen = mlx5e_skb_l3_header_offset(skb); - break; - } - /* fall through */ + hlen = mlx5e_skb_l3_header_offset(skb); + break; case MLX5_INLINE_MODE_L2: default: hlen = mlx5e_skb_l2_header_offset(skb); -- cgit v1.2.3 From 41f5f63cd17530d9eddaf99a71f5d069afd787d8 Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Thu, 21 Feb 2019 12:40:05 +0000 Subject: net/mlx5e: Trust kernel regarding transport offset After AF_PACKET is fixed to calculate the transport header offset correctly, trust the value set by the kernel. If the offset wasn't set, it means there is no transport header in the packet. Signed-off-by: Maxim Mikityanskiy Reviewed-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 6ca834702306..e7aae45a01f8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -148,12 +148,8 @@ static inline int mlx5e_skb_l2_header_offset(struct sk_buff *skb) static inline int mlx5e_skb_l3_header_offset(struct sk_buff *skb) { - struct flow_keys keys; - if (skb_transport_header_was_set(skb)) return skb_transport_offset(skb); - else if (skb_flow_dissect_flow_keys(skb, &keys, 0)) - return keys.control.thoff; else return mlx5e_skb_l2_header_offset(skb); } -- cgit v1.2.3 From bfedc645deb7f96303afbdb38a42e2a8f356a5cc Mon Sep 17 00:00:00 2001 From: Eli Britstein Date: Mon, 21 Jan 2019 09:00:42 +0200 Subject: net/mlx5: Use read-modify-write when changing PCMR register values Currently changing a PCMR field is done by setting the field in a zeroed buffer, zeroing other unrelated fields. Fix this behaviour by modifying only the required field after first reading the current register values, as a pre-step towards using more fields in PCMR register. Signed-off-by: Eli Britstein Reviewed-by: Oz Shlomo Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/port.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index b81542820528..55b30d21a73a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -785,7 +785,11 @@ static int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen) int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable) { u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0}; + int err; + err = mlx5_query_ports_check(mdev, in, sizeof(in)); + if (err) + return err; MLX5_SET(pcmr_reg, in, local_port, 1); MLX5_SET(pcmr_reg, in, fcs_chk, enable); return mlx5_set_ports_check(mdev, in, sizeof(in)); -- cgit v1.2.3 From 97417f6182f80a80c9b4443f282ef707be74dade Mon Sep 17 00:00:00 2001 From: Eli Britstein Date: Mon, 14 Jan 2019 10:07:44 +0200 Subject: net/mlx5e: Fix GRE key by controlling port tunnel entropy calculation Flow entropy is calculated on the inner packet headers and used for flow distribution in processing, routing etc. For GRE-type encapsulations the entropy value is placed in the eight LSB of the key field in the GRE header as defined in NVGRE RFC 7637. For UDP based encapsulations the entropy value is placed in the source port of the UDP header. The hardware may support entropy calculation specifically for GRE and for all tunneling protocols. With commit df2ef3bff193 ("net/mlx5e: Add GRE protocol offloading") GRE is offloaded, but the hardware is configured by default to calculate flow entropy so packets transmitted on the wire have a wrong key. To support UDP based tunnels (i.e VXLAN), GRE (i.e. no flow entropy) and NVGRE (i.e. with flow entropy) the hardware behaviour must be controlled by the driver. Ensure port entropy calculation is enabled for offloaded VXLAN tunnels and disable port entropy calculation in the presence of offloaded GRE tunnels by monitoring the presence of entropy enabling tunnels (i.e VXLAN) and entropy disabing tunnels (i.e GRE). Fixes: df2ef3bff193 ("net/mlx5e: Add GRE protocol offloading") Signed-off-by: Eli Britstein Reviewed-by: Oz Shlomo Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 18 +- drivers/net/ethernet/mellanox/mlx5/core/en_rep.h | 3 + .../net/ethernet/mellanox/mlx5/core/lib/port_tun.c | 205 +++++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/lib/port_tun.h | 24 +++ drivers/net/ethernet/mellanox/mlx5/core/port.c | 5 +- include/linux/mlx5/port.h | 2 + 7 files changed, 254 insertions(+), 5 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 82d636baaa4e..17f1a8b28c0a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -30,7 +30,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ mlx5_core-$(CONFIG_MLX5_EN_ARFS) += en_arfs.o mlx5_core-$(CONFIG_MLX5_EN_RXNFC) += en_fs_ethtool.o mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o -mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o +mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o lib/port_tun.o # # Core extra diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 287d48e5b073..4d033e01f6ab 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -44,6 +44,7 @@ #include "en_tc.h" #include "en/tc_tun.h" #include "fs_core.h" +#include "lib/port_tun.h" #define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \ max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE) @@ -1044,14 +1045,23 @@ static void mlx5e_rep_neigh_entry_destroy(struct mlx5e_priv *priv, int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) { + struct mlx5e_rep_priv *rpriv = priv->ppriv; + struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv; + struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy; struct mlx5e_neigh_hash_entry *nhe; int err; + err = mlx5_tun_entropy_refcount_inc(tun_entropy, e->reformat_type); + if (err) + return err; nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh); if (!nhe) { err = mlx5e_rep_neigh_entry_create(priv, e, &nhe); - if (err) + if (err) { + mlx5_tun_entropy_refcount_dec(tun_entropy, + e->reformat_type); return err; + } } list_add(&e->encap_list, &nhe->encap_list); return 0; @@ -1060,6 +1070,9 @@ int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv, void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) { + struct mlx5e_rep_priv *rpriv = priv->ppriv; + struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv; + struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy; struct mlx5e_neigh_hash_entry *nhe; list_del(&e->encap_list); @@ -1067,6 +1080,7 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv, if (list_empty(&nhe->encap_list)) mlx5e_rep_neigh_entry_destroy(priv, nhe); + mlx5_tun_entropy_refcount_dec(tun_entropy, e->reformat_type); } static int mlx5e_vf_rep_open(struct net_device *dev) @@ -1564,6 +1578,8 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) if (err) goto destroy_tises; + mlx5_init_port_tun_entropy(&uplink_priv->tun_entropy, priv->mdev); + /* init indirect block notifications */ INIT_LIST_HEAD(&uplink_priv->tc_indr_block_priv_list); uplink_priv->netdevice_nb.notifier_call = mlx5e_nic_rep_netdevice_event; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 36eafc877e6b..1aa3e110bb97 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -37,6 +37,7 @@ #include #include "eswitch.h" #include "en.h" +#include "lib/port_tun.h" #ifdef CONFIG_MLX5_ESWITCH struct mlx5e_neigh_update_table { @@ -71,6 +72,8 @@ struct mlx5_rep_uplink_priv { */ struct list_head tc_indr_block_priv_list; struct notifier_block netdevice_nb; + + struct mlx5_tun_entropy tun_entropy; }; struct mlx5e_rep_priv { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c new file mode 100644 index 000000000000..40f4a19b1ce1 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#include +#include +#include +#include +#include "mlx5_core.h" +#include "lib/port_tun.h" + +struct mlx5_port_tun_entropy_flags { + bool force_supported, force_enabled; + bool calc_supported, calc_enabled; + bool gre_calc_supported, gre_calc_enabled; +}; + +static void mlx5_query_port_tun_entropy(struct mlx5_core_dev *mdev, + struct mlx5_port_tun_entropy_flags *entropy_flags) +{ + u32 out[MLX5_ST_SZ_DW(pcmr_reg)]; + /* Default values for FW which do not support MLX5_REG_PCMR */ + entropy_flags->force_supported = false; + entropy_flags->calc_supported = false; + entropy_flags->gre_calc_supported = false; + entropy_flags->force_enabled = false; + entropy_flags->calc_enabled = true; + entropy_flags->gre_calc_enabled = true; + + if (!MLX5_CAP_GEN(mdev, ports_check)) + return; + + if (mlx5_query_ports_check(mdev, out, sizeof(out))) + return; + + entropy_flags->force_supported = !!(MLX5_GET(pcmr_reg, out, entropy_force_cap)); + entropy_flags->calc_supported = !!(MLX5_GET(pcmr_reg, out, entropy_calc_cap)); + entropy_flags->gre_calc_supported = !!(MLX5_GET(pcmr_reg, out, entropy_gre_calc_cap)); + entropy_flags->force_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_force)); + entropy_flags->calc_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_calc)); + entropy_flags->gre_calc_enabled = !!(MLX5_GET(pcmr_reg, out, entropy_gre_calc)); +} + +static int mlx5_set_port_tun_entropy_calc(struct mlx5_core_dev *mdev, u8 enable, + u8 force) +{ + u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0}; + int err; + + err = mlx5_query_ports_check(mdev, in, sizeof(in)); + if (err) + return err; + MLX5_SET(pcmr_reg, in, local_port, 1); + MLX5_SET(pcmr_reg, in, entropy_force, force); + MLX5_SET(pcmr_reg, in, entropy_calc, enable); + return mlx5_set_ports_check(mdev, in, sizeof(in)); +} + +static int mlx5_set_port_gre_tun_entropy_calc(struct mlx5_core_dev *mdev, + u8 enable, u8 force) +{ + u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0}; + int err; + + err = mlx5_query_ports_check(mdev, in, sizeof(in)); + if (err) + return err; + MLX5_SET(pcmr_reg, in, local_port, 1); + MLX5_SET(pcmr_reg, in, entropy_force, force); + MLX5_SET(pcmr_reg, in, entropy_gre_calc, enable); + return mlx5_set_ports_check(mdev, in, sizeof(in)); +} + +void mlx5_init_port_tun_entropy(struct mlx5_tun_entropy *tun_entropy, + struct mlx5_core_dev *mdev) +{ + struct mlx5_port_tun_entropy_flags entropy_flags; + + tun_entropy->mdev = mdev; + mutex_init(&tun_entropy->lock); + mlx5_query_port_tun_entropy(mdev, &entropy_flags); + tun_entropy->num_enabling_entries = 0; + tun_entropy->num_disabling_entries = 0; + tun_entropy->enabled = entropy_flags.calc_enabled; + tun_entropy->enabled = + (entropy_flags.calc_supported) ? + entropy_flags.calc_enabled : true; +} + +static int mlx5_set_entropy(struct mlx5_tun_entropy *tun_entropy, + int reformat_type, bool enable) +{ + struct mlx5_port_tun_entropy_flags entropy_flags; + int err; + + mlx5_query_port_tun_entropy(tun_entropy->mdev, &entropy_flags); + /* Tunnel entropy calculation may be controlled either on port basis + * for all tunneling protocols or specifically for GRE protocol. + * Prioritize GRE protocol control (if capable) over global port + * configuration. + */ + if (entropy_flags.gre_calc_supported && + reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE) { + /* Other applications may change the global FW entropy + * calculations settings. Check that the current entropy value + * is the negative of the updated value. + */ + if (entropy_flags.force_enabled && + enable == entropy_flags.gre_calc_enabled) { + mlx5_core_warn(tun_entropy->mdev, + "Unexpected GRE entropy calc setting - expected %d", + !entropy_flags.gre_calc_enabled); + return -EOPNOTSUPP; + } + err = mlx5_set_port_gre_tun_entropy_calc(tun_entropy->mdev, enable, + entropy_flags.force_supported); + if (err) + return err; + /* if we turn on the entropy we don't need to force it anymore */ + if (entropy_flags.force_supported && enable) { + err = mlx5_set_port_gre_tun_entropy_calc(tun_entropy->mdev, 1, 0); + if (err) + return err; + } + } else if (entropy_flags.calc_supported) { + /* Other applications may change the global FW entropy + * calculations settings. Check that the current entropy value + * is the negative of the updated value. + */ + if (entropy_flags.force_enabled && + enable == entropy_flags.calc_enabled) { + mlx5_core_warn(tun_entropy->mdev, + "Unexpected entropy calc setting - expected %d", + !entropy_flags.calc_enabled); + return -EOPNOTSUPP; + } + /* GRE requires disabling entropy calculation. if there are + * enabling entries (i.e VXLAN) we cannot turn it off for them, + * thus fail. + */ + if (tun_entropy->num_enabling_entries) + return -EOPNOTSUPP; + err = mlx5_set_port_tun_entropy_calc(tun_entropy->mdev, enable, + entropy_flags.force_supported); + if (err) + return err; + tun_entropy->enabled = enable; + /* if we turn on the entropy we don't need to force it anymore */ + if (entropy_flags.force_supported && enable) { + err = mlx5_set_port_tun_entropy_calc(tun_entropy->mdev, 1, 0); + if (err) + return err; + } + } + + return 0; +} + +/* the function manages the refcount for enabling/disabling tunnel types. + * the return value indicates if the inc is successful or not, depending on + * entropy capabilities and configuration. + */ +int mlx5_tun_entropy_refcount_inc(struct mlx5_tun_entropy *tun_entropy, + int reformat_type) +{ + /* the default is error for unknown (non VXLAN/GRE tunnel types) */ + int err = -EOPNOTSUPP; + + mutex_lock(&tun_entropy->lock); + if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_VXLAN && + tun_entropy->enabled) { + /* in case entropy calculation is enabled for all tunneling + * types, it is ok for VXLAN, so approve. + * otherwise keep the error default. + */ + tun_entropy->num_enabling_entries++; + err = 0; + } else if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE) { + /* turn off the entropy only for the first GRE rule. + * for the next rules the entropy was already disabled + * successfully. + */ + if (tun_entropy->num_disabling_entries == 0) + err = mlx5_set_entropy(tun_entropy, reformat_type, 0); + else + err = 0; + if (!err) + tun_entropy->num_disabling_entries++; + } + mutex_unlock(&tun_entropy->lock); + + return err; +} + +void mlx5_tun_entropy_refcount_dec(struct mlx5_tun_entropy *tun_entropy, + int reformat_type) +{ + mutex_lock(&tun_entropy->lock); + if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_VXLAN) + tun_entropy->num_enabling_entries--; + else if (reformat_type == MLX5_REFORMAT_TYPE_L2_TO_NVGRE && + --tun_entropy->num_disabling_entries == 0) + mlx5_set_entropy(tun_entropy, reformat_type, 1); + mutex_unlock(&tun_entropy->lock); +} + diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.h new file mode 100644 index 000000000000..54c42a88705e --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef __MLX5_PORT_TUN_H__ +#define __MLX5_PORT_TUN_H__ + +#include + +struct mlx5_tun_entropy { + struct mlx5_core_dev *mdev; + u32 num_enabling_entries; + u32 num_disabling_entries; + u8 enabled; + struct mutex lock; /* lock the entropy fields */ +}; + +void mlx5_init_port_tun_entropy(struct mlx5_tun_entropy *tun_entropy, + struct mlx5_core_dev *mdev); +int mlx5_tun_entropy_refcount_inc(struct mlx5_tun_entropy *tun_entropy, + int reformat_type); +void mlx5_tun_entropy_refcount_dec(struct mlx5_tun_entropy *tun_entropy, + int reformat_type); + +#endif /* __MLX5_PORT_TUN_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 55b30d21a73a..21b7f05b16a5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -764,8 +764,7 @@ int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode) } EXPORT_SYMBOL_GPL(mlx5_query_port_wol); -static int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, - int outlen) +int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, int outlen) { u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {0}; @@ -774,7 +773,7 @@ static int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, outlen, MLX5_REG_PCMR, 0, 0); } -static int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen) +int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen) { u32 out[MLX5_ST_SZ_DW(pcmr_reg)]; diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h index 814fa194663b..64e78394fc9c 100644 --- a/include/linux/mlx5/port.h +++ b/include/linux/mlx5/port.h @@ -182,6 +182,8 @@ int mlx5_query_port_ets_rate_limit(struct mlx5_core_dev *mdev, int mlx5_set_port_wol(struct mlx5_core_dev *mdev, u8 wol_mode); int mlx5_query_port_wol(struct mlx5_core_dev *mdev, u8 *wol_mode); +int mlx5_query_ports_check(struct mlx5_core_dev *mdev, u32 *out, int outlen); +int mlx5_set_ports_check(struct mlx5_core_dev *mdev, u32 *in, int inlen); int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable); void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported, bool *enabled); -- cgit v1.2.3 From 772ac5e284c7cee1f377f01fcc3e88cc5dc9fb12 Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Tue, 19 Feb 2019 15:05:12 +0200 Subject: net/mlx5e: Fix warn print in case of TX reporter creation failure Print warning message in case of TX reporter creation failure, only if the return value is ERR_PTR type. NULL pointer return indicates that NET_DEVLINK is not set, and the warning print can be skipped. Fixes: de8650a82071 ("net/mlx5e: Add tx reporter support") Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 0aebfb377cf0..e05b8fce8dbb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -281,7 +281,7 @@ int mlx5e_tx_reporter_create(struct mlx5e_priv *priv) devlink_health_reporter_create(devlink, &mlx5_tx_reporter_ops, MLX5_REPORTER_TX_GRACEFUL_PERIOD, true, priv); - if (IS_ERR_OR_NULL(priv->tx_reporter)) + if (IS_ERR(priv->tx_reporter)) netdev_warn(priv->netdev, "Failed to create tx reporter, err = %ld\n", PTR_ERR(priv->tx_reporter)); -- cgit v1.2.3 From 2c493ae03a24db7117c812c5fd0adc90c19cc833 Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Tue, 19 Feb 2019 15:26:04 +0200 Subject: net/mlx5e: Re-add support for TX timeout when TX reporter is not valid When TX reporter was introduced, it took ownership over TX timeout error handling. this introduced a regression in case TX reporter is not valid (NET_DEVLINK is not set, or devlink_health_reporter_create failure). Fix mlx5e_tx_reporter_timeout function so it can be called at all times. In addition, remove a warning print that indicates that a TX timeout won't be handled in case of no valid TX reporter. Fixes: 7d91126b1aea ("net/mlx5e: Add tx timeout support for mlx5e tx reporter") Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 16 ++++++++++++++-- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 6 ------ drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 5 ++--- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index e05b8fce8dbb..201ea73e3021 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -113,6 +113,18 @@ static int mlx5e_tx_reporter_err_cqe_recover(struct mlx5e_txqsq *sq) return 0; } +static int mlx5_tx_health_report(struct devlink_health_reporter *tx_reporter, + char *err_str, + struct mlx5e_tx_err_ctx *err_ctx) +{ + if (IS_ERR_OR_NULL(tx_reporter)) { + netdev_err(err_ctx->sq->channel->netdev, err_str); + return err_ctx->recover(err_ctx->sq); + } + + return devlink_health_report(tx_reporter, err_str, err_ctx); +} + void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq) { char err_str[MLX5E_TX_REPORTER_PER_SQ_MAX_LEN]; @@ -122,7 +134,7 @@ void mlx5e_tx_reporter_err_cqe(struct mlx5e_txqsq *sq) err_ctx.recover = mlx5e_tx_reporter_err_cqe_recover; sprintf(err_str, "ERR CQE on SQ: 0x%x", sq->sqn); - devlink_health_report(sq->channel->priv->tx_reporter, err_str, + mlx5_tx_health_report(sq->channel->priv->tx_reporter, err_str, &err_ctx); } @@ -160,7 +172,7 @@ int mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq) sq->channel->ix, sq->sqn, sq->cq.mcq.cqn, sq->cc, sq->pc, jiffies_to_usecs(jiffies - sq->txq->trans_start)); - return devlink_health_report(sq->channel->priv->tx_reporter, err_str, + return mlx5_tx_health_report(sq->channel->priv->tx_reporter, err_str, &err_ctx); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 878b3467e459..4f971f3d8ce7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -4173,12 +4173,6 @@ static void mlx5e_tx_timeout(struct net_device *dev) struct mlx5e_priv *priv = netdev_priv(dev); netdev_err(dev, "TX timeout detected\n"); - - if (IS_ERR_OR_NULL(priv->tx_reporter)) { - netdev_err_once(priv->netdev, "tx timeout will not be handled, no valid tx reporter\n"); - return; - } - queue_work(priv->wq, &priv->tx_timeout_work); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index c1334a8ac8f3..d5fadbd6577e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -519,9 +519,8 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) &sq->state)) { mlx5e_dump_error_cqe(sq, (struct mlx5_err_cqe *)cqe); - if (!IS_ERR_OR_NULL(cq->channel->priv->tx_reporter)) - queue_work(cq->channel->priv->wq, - &sq->recover_work); + queue_work(cq->channel->priv->wq, + &sq->recover_work); } stats->cqe_err++; } -- cgit v1.2.3 From c7981bea48fbbbf17215038c3d7c48706dafd6ff Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Wed, 20 Feb 2019 12:10:48 +0200 Subject: net/mlx5e: Fix return status of TX reporter timeout recover In case of lost interrupt recover, we shall return success. Fix that. Fixes: 7d91126b1aea ("net/mlx5e: Add tx timeout support for mlx5e tx reporter") Signed-off-by: Eran Ben Elisha Reported-by: Maria Pasechnik Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 201ea73e3021..627392bead3b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -148,7 +148,7 @@ static int mlx5e_tx_reporter_timeout_recover(struct mlx5e_txqsq *sq) eq->core.eqn, eq->core.cons_index, eq->core.irqn); eqe_count = mlx5_eq_poll_irq_disabled(eq); - ret = eqe_count ? true : false; + ret = eqe_count ? false : true; if (!eqe_count) { clear_bit(MLX5E_SQ_STATE_ENABLED, &sq->state); return ret; -- cgit v1.2.3 From 2e5b0534622fa87fd570d54af2d01ce304b88077 Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Wed, 20 Feb 2019 12:33:01 +0200 Subject: net/mlx5e: Fix mlx5e_tx_reporter_create return value If reporter is ERR_PTR or NULL, error code shall be returned. At all other cases it shall return success. Fix that. Fixes: de8650a82071 ("net/mlx5e: Add tx reporter support") Signed-off-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 627392bead3b..75dad8797720 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -297,7 +297,7 @@ int mlx5e_tx_reporter_create(struct mlx5e_priv *priv) netdev_warn(priv->netdev, "Failed to create tx reporter, err = %ld\n", PTR_ERR(priv->tx_reporter)); - return PTR_ERR_OR_ZERO(priv->tx_reporter); + return IS_ERR_OR_NULL(priv->tx_reporter); } void mlx5e_tx_reporter_destroy(struct mlx5e_priv *priv) -- cgit v1.2.3 From 8da202b2491301648c5d0830a8d280a7a35bd4eb Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Mon, 21 Jan 2019 16:22:05 -0600 Subject: net/mlx5: E-Switch, Add support for VEPA in legacy mode. In Virtual Ethernet Port Aggregator (VEPA) mode, the packet skips the system internal virtual switch and forwards to external network switch. In Mellanox HCA case, the virtual switch is the HCA's Eswitch. To support this, an new FDB flow table are created with level 0 and linked to the existing FDB flow table in legacy mode. By default, VEPA is turned off and this FDB flow table is empty. When VEPA is turned on, two rules are created. One rule to forward on uplink vport traffic to the legacy FDB. The other rule forward all other traffic to uplink vport. Other design alternatives were not chosen as explained below: 1. Create a forward rule in ACL flow table (most efficient design). This approach is the not chosen because firmware does not support forward rule to uplink vport (0xffff) for ACL flow table. 2. Add additional source port criteria in all the FDB rules to make the FDB rules to be received rules only. This approach is not chosen because it is not efficient as there can many rules in the FDB and VEPA mode cannot be controlled per vport. 3. Add a highest prioirty flow group in the existing legacy FDB Flow Table instead of a new flow table. This approoach does not work because the new flow group has the same match criteria as the promiscuous flow group and mlx5_add_flow_rules does not allow specifying flow group. Signed-off-by: Huy Nguyen Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 223 ++++++++++++++++++++-- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 5 + 2 files changed, 207 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 6cb9710f76d5..84200d93cf9d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -64,6 +64,9 @@ enum { PROMISC_CHANGE = BIT(3), }; +static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw); +static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw); + /* Vport context events */ #define SRIOV_VPORT_EVENTS (UC_ADDR_CHANGE | \ MC_ADDR_CHANGE | \ @@ -268,6 +271,37 @@ esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport) return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v); } +enum { + LEGACY_VEPA_PRIO = 0, + LEGACY_FDB_PRIO, +}; + +static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw) +{ + struct mlx5_core_dev *dev = esw->dev; + struct mlx5_flow_namespace *root_ns; + struct mlx5_flow_table *fdb; + int err; + + root_ns = mlx5_get_fdb_sub_ns(dev, 0); + if (!root_ns) { + esw_warn(dev, "Failed to get FDB flow namespace\n"); + return -EOPNOTSUPP; + } + + /* num FTE 2, num FG 2 */ + fdb = mlx5_create_auto_grouped_flow_table(root_ns, LEGACY_VEPA_PRIO, + 2, 2, 0, 0); + if (IS_ERR(fdb)) { + err = PTR_ERR(fdb); + esw_warn(dev, "Failed to create VEPA FDB err %d\n", err); + return err; + } + esw->fdb_table.legacy.vepa_fdb = fdb; + + return 0; +} + static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); @@ -296,8 +330,8 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw) return -ENOMEM; table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size)); - ft_attr.max_fte = table_size; + ft_attr.prio = LEGACY_FDB_PRIO; fdb = mlx5_create_flow_table(root_ns, &ft_attr); if (IS_ERR(fdb)) { err = PTR_ERR(fdb); @@ -356,41 +390,65 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw) esw->fdb_table.legacy.promisc_grp = g; out: - if (err) { - if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.allmulti_grp)) { - mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp); - esw->fdb_table.legacy.allmulti_grp = NULL; - } - if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.addr_grp)) { - mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp); - esw->fdb_table.legacy.addr_grp = NULL; - } - if (!IS_ERR_OR_NULL(esw->fdb_table.legacy.fdb)) { - mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb); - esw->fdb_table.legacy.fdb = NULL; - } - } + if (err) + esw_destroy_legacy_fdb_table(esw); kvfree(flow_group_in); return err; } +static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw) +{ + esw_debug(esw->dev, "Destroy VEPA Table\n"); + if (!esw->fdb_table.legacy.vepa_fdb) + return; + + mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb); + esw->fdb_table.legacy.vepa_fdb = NULL; +} + static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw) { + esw_debug(esw->dev, "Destroy FDB Table\n"); if (!esw->fdb_table.legacy.fdb) return; - esw_debug(esw->dev, "Destroy FDB Table\n"); - mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp); - mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp); - mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp); + if (esw->fdb_table.legacy.promisc_grp) + mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp); + if (esw->fdb_table.legacy.allmulti_grp) + mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp); + if (esw->fdb_table.legacy.addr_grp) + mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp); mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb); + esw->fdb_table.legacy.fdb = NULL; esw->fdb_table.legacy.addr_grp = NULL; esw->fdb_table.legacy.allmulti_grp = NULL; esw->fdb_table.legacy.promisc_grp = NULL; } +static int esw_create_legacy_table(struct mlx5_eswitch *esw) +{ + int err; + + err = esw_create_legacy_vepa_table(esw); + if (err) + return err; + + err = esw_create_legacy_fdb_table(esw); + if (err) + esw_destroy_legacy_vepa_table(esw); + + return err; +} + +static void esw_destroy_legacy_table(struct mlx5_eswitch *esw) +{ + esw_cleanup_vepa_rules(esw); + esw_destroy_legacy_fdb_table(esw); + esw_destroy_legacy_vepa_table(esw); +} + /* E-Switch vport UC/MC lists management */ typedef int (*vport_addr_action)(struct mlx5_eswitch *esw, struct vport_addr *vaddr); @@ -1677,7 +1735,9 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) mlx5_lag_update(esw->dev); if (mode == SRIOV_LEGACY) { - err = esw_create_legacy_fdb_table(esw); + err = esw_create_legacy_table(esw); + if (err) + goto abort; } else { mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH); mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB); @@ -1758,7 +1818,7 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) esw_destroy_tsar(esw); if (esw->mode == SRIOV_LEGACY) - esw_destroy_legacy_fdb_table(esw); + esw_destroy_legacy_table(esw); else if (esw->mode == SRIOV_OFFLOADS) esw_offloads_cleanup(esw); @@ -2041,6 +2101,127 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw, return err; } +static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw) +{ + if (esw->fdb_table.legacy.vepa_uplink_rule) + mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule); + + if (esw->fdb_table.legacy.vepa_star_rule) + mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule); + + esw->fdb_table.legacy.vepa_uplink_rule = NULL; + esw->fdb_table.legacy.vepa_star_rule = NULL; +} + +static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw, + u8 setting) +{ + struct mlx5_flow_destination dest = {}; + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_handle *flow_rule; + struct mlx5_flow_spec *spec; + int err = 0; + void *misc; + + if (!setting) { + esw_cleanup_vepa_rules(esw); + return 0; + } + + if (esw->fdb_table.legacy.vepa_uplink_rule) + return 0; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + + /* Uplink rule forward uplink traffic to FDB */ + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); + MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK); + + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); + MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); + + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + dest.ft = esw->fdb_table.legacy.fdb; + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec, + &flow_act, &dest, 1); + if (IS_ERR(flow_rule)) { + err = PTR_ERR(flow_rule); + goto out; + } else { + esw->fdb_table.legacy.vepa_uplink_rule = flow_rule; + } + + /* Star rule to forward all traffic to uplink vport */ + memset(spec, 0, sizeof(*spec)); + dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; + dest.vport.num = MLX5_VPORT_UPLINK; + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec, + &flow_act, &dest, 1); + if (IS_ERR(flow_rule)) { + err = PTR_ERR(flow_rule); + goto out; + } else { + esw->fdb_table.legacy.vepa_star_rule = flow_rule; + } + +out: + kvfree(spec); + if (err) + esw_cleanup_vepa_rules(esw); + return err; +} + +int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting) +{ + int err = 0; + + if (!esw) + return -EOPNOTSUPP; + + if (!ESW_ALLOWED(esw)) + return -EPERM; + + mutex_lock(&esw->state_lock); + if (esw->mode != SRIOV_LEGACY) { + err = -EOPNOTSUPP; + goto out; + } + + err = _mlx5_eswitch_set_vepa_locked(esw, setting); + +out: + mutex_unlock(&esw->state_lock); + return err; +} + +int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting) +{ + int err = 0; + + if (!esw) + return -EOPNOTSUPP; + + if (!ESW_ALLOWED(esw)) + return -EPERM; + + mutex_lock(&esw->state_lock); + if (esw->mode != SRIOV_LEGACY) { + err = -EOPNOTSUPP; + goto out; + } + + *setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0; + +out: + mutex_unlock(&esw->state_lock); + return err; +} + int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, int vport, bool setting) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index af5581a57e56..5f82e637410b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -137,6 +137,9 @@ struct mlx5_eswitch_fdb { struct mlx5_flow_group *addr_grp; struct mlx5_flow_group *allmulti_grp; struct mlx5_flow_group *promisc_grp; + struct mlx5_flow_table *vepa_fdb; + struct mlx5_flow_handle *vepa_uplink_rule; + struct mlx5_flow_handle *vepa_star_rule; } legacy; struct offloads_fdb { @@ -242,6 +245,8 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw, int vport_num, bool setting); int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport, u32 max_rate, u32 min_rate); +int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting); +int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting); int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw, int vport, struct ifla_vf_info *ivi); int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw, -- cgit v1.2.3 From 4b89251de024fb85329e4cbd8fbea551ae6c665c Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Tue, 19 Feb 2019 21:40:34 -0600 Subject: net/mlx5: Support ndo bridge_setlink and getlink Allow enabling VEPA mode on the HCA's port in legacy devlink mode. Example: bridge link set dev ens1f0 hwmode vepa will turn on VEPA mode on the netdev ens1f0. Signed-off-by: Huy Nguyen Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 59 +++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 4f971f3d8ce7..e5f74eb986b3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "eswitch.h" #include "en.h" @@ -4305,6 +4306,61 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp) } } +#ifdef CONFIG_MLX5_ESWITCH +static int mlx5e_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, + struct net_device *dev, u32 filter_mask, + int nlflags) +{ + struct mlx5e_priv *priv = netdev_priv(dev); + struct mlx5_core_dev *mdev = priv->mdev; + u8 mode, setting; + int err; + + err = mlx5_eswitch_get_vepa(mdev->priv.eswitch, &setting); + if (err) + return err; + mode = setting ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB; + return ndo_dflt_bridge_getlink(skb, pid, seq, dev, + mode, + 0, 0, nlflags, filter_mask, NULL); +} + +static int mlx5e_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, + u16 flags, struct netlink_ext_ack *extack) +{ + struct mlx5e_priv *priv = netdev_priv(dev); + struct mlx5_core_dev *mdev = priv->mdev; + struct nlattr *attr, *br_spec; + u16 mode = BRIDGE_MODE_UNDEF; + u8 setting; + int rem; + + br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); + if (!br_spec) + return -EINVAL; + + nla_for_each_nested(attr, br_spec, rem) { + if (nla_type(attr) != IFLA_BRIDGE_MODE) + continue; + + if (nla_len(attr) < sizeof(mode)) + return -EINVAL; + + mode = nla_get_u16(attr); + if (mode > BRIDGE_MODE_VEPA) + return -EINVAL; + + break; + } + + if (mode == BRIDGE_MODE_UNDEF) + return -EINVAL; + + setting = (mode == BRIDGE_MODE_VEPA) ? 1 : 0; + return mlx5_eswitch_set_vepa(mdev->priv.eswitch, setting); +} +#endif + const struct net_device_ops mlx5e_netdev_ops = { .ndo_open = mlx5e_open, .ndo_stop = mlx5e_close, @@ -4331,6 +4387,9 @@ const struct net_device_ops mlx5e_netdev_ops = { .ndo_rx_flow_steer = mlx5e_rx_flow_steer, #endif #ifdef CONFIG_MLX5_ESWITCH + .ndo_bridge_setlink = mlx5e_bridge_setlink, + .ndo_bridge_getlink = mlx5e_bridge_getlink, + /* SRIOV E-Switch NDOs */ .ndo_set_vf_mac = mlx5e_set_vf_mac, .ndo_set_vf_vlan = mlx5e_set_vf_vlan, -- cgit v1.2.3 From 43f2ebd5571653f5a02c178d6d73ab642e8a0cad Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 21 Feb 2019 15:53:14 +0530 Subject: net: phy: at803x: don't inline helpers Some helpers were declared with the "inline" function specifier. It is preferable to let the compiler pick the right optimizations, so drop the specifier for at803x_disable_rx_delay() and at803x_disable_tx_delay() Reviewed-by: Niklas Cassel Tested-by: Peter Ujfalusi Reviewed-by: Marc Gonzalez Signed-off-by: Vinod Koul Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 90dc62c15fc5..3bcdb28b6366 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -103,13 +103,13 @@ static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, return phy_write(phydev, AT803X_DEBUG_DATA, val); } -static inline int at803x_disable_rx_delay(struct phy_device *phydev) +static int at803x_disable_rx_delay(struct phy_device *phydev) { return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, AT803X_DEBUG_RX_CLK_DLY_EN, 0); } -static inline int at803x_disable_tx_delay(struct phy_device *phydev) +static int at803x_disable_tx_delay(struct phy_device *phydev) { return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, AT803X_DEBUG_TX_CLK_DLY_EN, 0); -- cgit v1.2.3 From 6d4cd041f0af5b4c8fc742b4a68eac22e420e28c Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 21 Feb 2019 15:53:15 +0530 Subject: net: phy: at803x: disable delay only for RGMII mode Per "Documentation/devicetree/bindings/net/ethernet.txt" RGMII mode should not have delay in PHY whereas RGMII_ID and RGMII_RXID/RGMII_TXID can have delay in PHY. So disable the delay only for RGMII mode and enable for other modes. Also treat the default case as disabled delays. Fixes: cd28d1d6e52e: ("net: phy: at803x: Disable phy delay for RGMII mode") Reported-by: Peter Ujfalusi Reviewed-by: Niklas Cassel Tested-by: Peter Ujfalusi Signed-off-by: Vinod Koul Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 53 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index 3bcdb28b6366..f3e96191eb6f 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -103,6 +103,18 @@ static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg, return phy_write(phydev, AT803X_DEBUG_DATA, val); } +static int at803x_enable_rx_delay(struct phy_device *phydev) +{ + return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0, + AT803X_DEBUG_RX_CLK_DLY_EN); +} + +static int at803x_enable_tx_delay(struct phy_device *phydev) +{ + return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0, + AT803X_DEBUG_TX_CLK_DLY_EN); +} + static int at803x_disable_rx_delay(struct phy_device *phydev) { return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, @@ -241,23 +253,42 @@ static int at803x_config_init(struct phy_device *phydev) if (ret < 0) return ret; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || - phydev->interface == PHY_INTERFACE_MODE_RGMII) { - ret = at803x_disable_rx_delay(phydev); + /* The RX and TX delay default is: + * after HW reset: RX delay enabled and TX delay disabled + * after SW reset: RX delay enabled, while TX delay retains the + * value before reset. + * + * So let's first disable the RX and TX delays in PHY and enable + * them based on the mode selected (this also takes care of RGMII + * mode where we expect delays to be disabled) + */ + + ret = at803x_disable_rx_delay(phydev); + if (ret < 0) + return ret; + ret = at803x_disable_tx_delay(phydev); + if (ret < 0) + return ret; + + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { + /* If RGMII_ID or RGMII_RXID are specified enable RX delay, + * otherwise keep it disabled + */ + ret = at803x_enable_rx_delay(phydev); if (ret < 0) return ret; } - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || - phydev->interface == PHY_INTERFACE_MODE_RGMII) { - ret = at803x_disable_tx_delay(phydev); - if (ret < 0) - return ret; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { + /* If RGMII_ID or RGMII_TXID are specified enable TX delay, + * otherwise keep it disabled + */ + ret = at803x_enable_tx_delay(phydev); } - return 0; + return ret; } static int at803x_ack_interrupt(struct phy_device *phydev) -- cgit v1.2.3 From ab2c4e2581ad32c28627235ff0ae8c5a5ea6899f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 21 Feb 2019 20:09:26 -0800 Subject: mlxsw: spectrum: Avoid -Wformat-truncation warnings Give precision identifiers to the two snprintf() formatting the priority and TC strings to avoid producing these two warnings: drivers/net/ethernet/mellanox/mlxsw/spectrum.c: In function 'mlxsw_sp_port_get_prio_strings': drivers/net/ethernet/mellanox/mlxsw/spectrum.c:2132:37: warning: '%d' directive output may be truncated writing between 1 and 3 bytes into a region of size between 0 and 31 [-Wformat-truncation=] snprintf(*p, ETH_GSTRING_LEN, "%s_%d", ^~ drivers/net/ethernet/mellanox/mlxsw/spectrum.c:2132:3: note: 'snprintf' output between 3 and 36 bytes into a destination of size 32 snprintf(*p, ETH_GSTRING_LEN, "%s_%d", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mlxsw_sp_port_hw_prio_stats[i].str, prio); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/net/ethernet/mellanox/mlxsw/spectrum.c: In function 'mlxsw_sp_port_get_tc_strings': drivers/net/ethernet/mellanox/mlxsw/spectrum.c:2143:37: warning: '%d' directive output may be truncated writing between 1 and 11 bytes into a region of size between 0 and 31 [-Wformat-truncation=] snprintf(*p, ETH_GSTRING_LEN, "%s_%d", ^~ drivers/net/ethernet/mellanox/mlxsw/spectrum.c:2143:3: note: 'snprintf' output between 3 and 44 bytes into a destination of size 32 snprintf(*p, ETH_GSTRING_LEN, "%s_%d", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mlxsw_sp_port_hw_tc_stats[i].str, tc); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index f018b0607dac..5f6962da8877 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2129,7 +2129,7 @@ static void mlxsw_sp_port_get_prio_strings(u8 **p, int prio) int i; for (i = 0; i < MLXSW_SP_PORT_HW_PRIO_STATS_LEN; i++) { - snprintf(*p, ETH_GSTRING_LEN, "%s_%d", + snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d", mlxsw_sp_port_hw_prio_stats[i].str, prio); *p += ETH_GSTRING_LEN; } @@ -2140,7 +2140,7 @@ static void mlxsw_sp_port_get_tc_strings(u8 **p, int tc) int i; for (i = 0; i < MLXSW_SP_PORT_HW_TC_STATS_LEN; i++) { - snprintf(*p, ETH_GSTRING_LEN, "%s_%d", + snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d", mlxsw_sp_port_hw_tc_stats[i].str, tc); *p += ETH_GSTRING_LEN; } -- cgit v1.2.3 From 3f8b86964ee5ba52f3ab28ec45d2f02d6ecce464 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 21 Feb 2019 20:09:27 -0800 Subject: net: dsa: mv88e6xxx: Fix -Wformat-security warnings We are not specifying an explicit format argument but instead passing a string litteral which causes these two warnings to show up: drivers/net/dsa/mv88e6xxx/chip.c: In function 'mv88e6xxx_irq_poll_setup': drivers/net/dsa/mv88e6xxx/chip.c:483:2: warning: format not a string literal and no format arguments [-Wformat-security] chip->kworker = kthread_create_worker(0, dev_name(chip->dev)); ^~~~ drivers/net/dsa/mv88e6xxx/ptp.c: In function 'mv88e6xxx_ptp_setup': drivers/net/dsa/mv88e6xxx/ptp.c:403:4: warning: format not a string literal and no format arguments [-Wformat-security] dev_name(chip->dev)); ^~~~~~~~ LD [M] drivers/net/dsa/mv88e6xxx/mv88e6xxx.o Signed-off-by: Florian Fainelli Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 2 +- drivers/net/dsa/mv88e6xxx/ptp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index cc7ce06b6d58..3f9a3fc52a0e 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -480,7 +480,7 @@ static int mv88e6xxx_irq_poll_setup(struct mv88e6xxx_chip *chip) kthread_init_delayed_work(&chip->irq_poll_work, mv88e6xxx_irq_poll); - chip->kworker = kthread_create_worker(0, dev_name(chip->dev)); + chip->kworker = kthread_create_worker(0, "%s", dev_name(chip->dev)); if (IS_ERR(chip->kworker)) return PTR_ERR(chip->kworker); diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c index 4b336d8d4c67..42872d21857b 100644 --- a/drivers/net/dsa/mv88e6xxx/ptp.c +++ b/drivers/net/dsa/mv88e6xxx/ptp.c @@ -400,7 +400,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) chip->ptp_clock_info.owner = THIS_MODULE; snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name), - dev_name(chip->dev)); + "%s", dev_name(chip->dev)); chip->ptp_clock_info.max_adj = 1000000; chip->ptp_clock_info.n_ext_ts = ptp_ops->n_ext_ts; -- cgit v1.2.3 From 135e7245479addc6b1f5d031e3d7e2ddb3d2b109 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 21 Feb 2019 20:09:28 -0800 Subject: e1000e: Fix -Wformat-truncation warnings Provide precision hints to snprintf() since we know the destination buffer size of the RX/TX ring names are IFNAMSIZ + 5 - 1. This fixes the following warnings: drivers/net/ethernet/intel/e1000e/netdev.c: In function 'e1000_request_msix': drivers/net/ethernet/intel/e1000e/netdev.c:2109:13: warning: 'snprintf' output may be truncated before the last format character [-Wformat-truncation=] "%s-rx-0", netdev->name); ^ drivers/net/ethernet/intel/e1000e/netdev.c:2107:3: note: 'snprintf' output between 6 and 21 bytes into a destination of size 20 snprintf(adapter->rx_ring->name, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sizeof(adapter->rx_ring->name) - 1, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "%s-rx-0", netdev->name); ~~~~~~~~~~~~~~~~~~~~~~~~ drivers/net/ethernet/intel/e1000e/netdev.c:2125:13: warning: 'snprintf' output may be truncated before the last format character [-Wformat-truncation=] "%s-tx-0", netdev->name); ^ drivers/net/ethernet/intel/e1000e/netdev.c:2123:3: note: 'snprintf' output between 6 and 21 bytes into a destination of size 20 snprintf(adapter->tx_ring->name, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sizeof(adapter->tx_ring->name) - 1, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "%s-tx-0", netdev->name); ~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/e1000e/netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 736fa51878f8..7acc61e4f645 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2106,7 +2106,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter) if (strlen(netdev->name) < (IFNAMSIZ - 5)) snprintf(adapter->rx_ring->name, sizeof(adapter->rx_ring->name) - 1, - "%s-rx-0", netdev->name); + "%.14s-rx-0", netdev->name); else memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ); err = request_irq(adapter->msix_entries[vector].vector, @@ -2122,7 +2122,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter) if (strlen(netdev->name) < (IFNAMSIZ - 5)) snprintf(adapter->tx_ring->name, sizeof(adapter->tx_ring->name) - 1, - "%s-tx-0", netdev->name); + "%.14s-tx-0", netdev->name); else memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ); err = request_irq(adapter->msix_entries[vector].vector, -- cgit v1.2.3 From abdf47aab4123ece48877cab4153db44fe4dc340 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 21 Feb 2019 20:09:29 -0800 Subject: veth: Fix -Wformat-truncation Provide a precision hint to snprintf() in order to eliminate a -Wformat-truncation warning provided below. A maximum of 11 characters is allowed to reach a maximum of 32 - 1 characters given a possible maximum value of queues using up to UINT_MAX which occupies 10 characters. Incidentally 11 is the number of characters for "xdp_packets" which is the largest string we append. drivers/net/veth.c: In function 'veth_get_strings': drivers/net/veth.c:118:47: warning: '%s' directive output may be truncated writing up to 31 bytes into a region of size between 12 and 21 [-Wformat-truncation=] snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_%s", ^~ drivers/net/veth.c:118:5: note: 'snprintf' output between 12 and 52 bytes into a destination of size 32 snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_%s", ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ i, veth_rq_stats_desc[j].desc); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/veth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/veth.c b/drivers/net/veth.c index fbf890ebbeae..569e87a51a33 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -115,7 +115,8 @@ static void veth_get_strings(struct net_device *dev, u32 stringset, u8 *buf) p += sizeof(ethtool_stats_keys); for (i = 0; i < dev->real_num_rx_queues; i++) { for (j = 0; j < VETH_RQ_STATS_LEN; j++) { - snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_%s", + snprintf(p, ETH_GSTRING_LEN, + "rx_queue_%u_%.11s", i, veth_rq_stats_desc[j].desc); p += ETH_GSTRING_LEN; } -- cgit v1.2.3 From 1531be31973a23f97bd8844393cfd387e4647c8c Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:36 +0000 Subject: mlxsw: spectrum: Remove duplicate port link mode entry Remove duplicate port link mode entry from mlxsw_sp_port_link_mode. Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 5f6962da8877..257683e5332d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2413,11 +2413,6 @@ static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = { .mask_ethtool = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, .speed = SPEED_25000, }, - { - .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR, - .mask_ethtool = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, - .speed = SPEED_25000, - }, { .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2, .mask_ethtool = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, -- cgit v1.2.3 From 475b33cb66c957af82f71e9f26bb98fc8f788872 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:37 +0000 Subject: mlxsw: spectrum: Remove unsupported eth_proto_lp_advertise field in PTYS Remove eth_proto_lp_advertise field in PTYS register since it is not supported by the firmware. Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 7 ------- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 15 +-------------- 2 files changed, 1 insertion(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index cbd0193ec3f6..19d361219693 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -4061,13 +4061,6 @@ MLXSW_ITEM32(reg, ptys, ib_link_width_oper, 0x28, 16, 16); */ MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16); -/* reg_ptys_eth_proto_lp_advertise - * The protocols that were advertised by the link partner during - * autonegotiation. - * Access: RO - */ -MLXSW_ITEM32(reg, ptys, eth_proto_lp_advertise, 0x30, 0, 32); - static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port, u32 proto_admin, bool autoneg) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 257683e5332d..bc47bbbdaccd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2606,21 +2606,10 @@ static void mlxsw_sp_port_get_link_advertise(u32 eth_proto_admin, bool autoneg, mlxsw_sp_from_ptys_link(eth_proto_admin, cmd->link_modes.advertising); } -static void -mlxsw_sp_port_get_link_lp_advertise(u32 eth_proto_lp, u8 autoneg_status, - struct ethtool_link_ksettings *cmd) -{ - if (autoneg_status != MLXSW_REG_PTYS_AN_STATUS_OK || !eth_proto_lp) - return; - - ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, Autoneg); - mlxsw_sp_from_ptys_link(eth_proto_lp, cmd->link_modes.lp_advertising); -} - static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *cmd) { - u32 eth_proto_cap, eth_proto_admin, eth_proto_oper, eth_proto_lp; + u32 eth_proto_cap, eth_proto_admin, eth_proto_oper; struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char ptys_pl[MLXSW_REG_PTYS_LEN]; @@ -2640,9 +2629,7 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, mlxsw_sp_port_get_link_advertise(eth_proto_admin, autoneg, cmd); - eth_proto_lp = mlxsw_reg_ptys_eth_proto_lp_advertise_get(ptys_pl); autoneg_status = mlxsw_reg_ptys_an_status_get(ptys_pl); - mlxsw_sp_port_get_link_lp_advertise(eth_proto_lp, autoneg_status, cmd); cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; cmd->base.port = mlxsw_sp_port_connector_port(eth_proto_oper); -- cgit v1.2.3 From 1e2f66ecebd30b6c0a455a5a46dedb957a6ccc50 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:38 +0000 Subject: mlxsw: spectrum: Query port connector type from firmware Instead of deriving the port connector type from port admin state, query it from firmware. Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 18 +++++++++ drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 54 +++++++++++++++----------- 2 files changed, 49 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 19d361219693..a781f09b79b9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -4061,6 +4061,24 @@ MLXSW_ITEM32(reg, ptys, ib_link_width_oper, 0x28, 16, 16); */ MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16); +enum mlxsw_reg_ptys_connector_type { + MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR, + MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE, + MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP, + MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI, + MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC, + MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII, + MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE, + MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA, + MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER, +}; + +/* reg_ptys_connector_type + * Connector type indication. + * Access: RO + */ +MLXSW_ITEM32(reg, ptys, connector_type, 0x2C, 0, 4); + static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port, u32 proto_admin, bool autoneg) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index bc47bbbdaccd..626e4cd42c2f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2525,28 +2525,6 @@ out: cmd->base.duplex = duplex; } -static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto) -{ - if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 | - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | - MLXSW_REG_PTYS_ETH_SPEED_SGMII)) - return PORT_FIBRE; - - if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 | - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4)) - return PORT_DA; - - if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | - MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 | - MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 | - MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4)) - return PORT_NONE; - - return PORT_OTHER; -} - static u32 mlxsw_sp_to_ptys_advert_link(const struct ethtool_link_ksettings *cmd) { @@ -2606,6 +2584,34 @@ static void mlxsw_sp_port_get_link_advertise(u32 eth_proto_admin, bool autoneg, mlxsw_sp_from_ptys_link(eth_proto_admin, cmd->link_modes.advertising); } +static u8 +mlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type) +{ + switch (connector_type) { + case MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR: + return PORT_OTHER; + case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE: + return PORT_NONE; + case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP: + return PORT_TP; + case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI: + return PORT_AUI; + case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC: + return PORT_BNC; + case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII: + return PORT_MII; + case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE: + return PORT_FIBRE; + case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA: + return PORT_DA; + case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER: + return PORT_OTHER; + default: + WARN_ON_ONCE(1); + return PORT_OTHER; + } +} + static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *cmd) { @@ -2613,6 +2619,7 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char ptys_pl[MLXSW_REG_PTYS_LEN]; + u8 connector_type; u8 autoneg_status; bool autoneg; int err; @@ -2632,7 +2639,8 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, autoneg_status = mlxsw_reg_ptys_an_status_get(ptys_pl); cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; - cmd->base.port = mlxsw_sp_port_connector_port(eth_proto_oper); + connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl); + cmd->base.port = mlxsw_sp_port_connector_port(connector_type); mlxsw_sp_from_ptys_speed_duplex(netif_carrier_ok(dev), eth_proto_oper, cmd); -- cgit v1.2.3 From 88a4281200ff8022ebf8f69ce2bb7b528ec24d3a Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:39 +0000 Subject: mlxsw: spectrum: Rename port type-speed functions to ASIC specific Rename port speed-type functions to be Spectrum-1 ASIC specific. Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 69 +++++++++++++------------- 1 file changed, 35 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 626e4cd42c2f..951e96b3a96b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2336,13 +2336,13 @@ static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset) } } -struct mlxsw_sp_port_link_mode { +struct mlxsw_sp1_port_link_mode { enum ethtool_link_mode_bit_indices mask_ethtool; u32 mask; u32 speed; }; -static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = { +static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = { { .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T, .mask_ethtool = ETHTOOL_LINK_MODE_100baseT_Full_BIT, @@ -2470,11 +2470,11 @@ static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = { }, }; -#define MLXSW_SP_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp_port_link_mode) +#define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode) static void -mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto, - struct ethtool_link_ksettings *cmd) +mlxsw_sp1_from_ptys_supported_port(u32 ptys_eth_proto, + struct ethtool_link_ksettings *cmd) { if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | @@ -2492,19 +2492,20 @@ mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto, ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane); } -static void mlxsw_sp_from_ptys_link(u32 ptys_eth_proto, unsigned long *mode) +static void mlxsw_sp1_from_ptys_link(u32 ptys_eth_proto, unsigned long *mode) { int i; - for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { - if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask) - __set_bit(mlxsw_sp_port_link_mode[i].mask_ethtool, + for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { + if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) + __set_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool, mode); } } -static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, - struct ethtool_link_ksettings *cmd) +static void +mlxsw_sp1_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, + struct ethtool_link_ksettings *cmd) { u32 speed = SPEED_UNKNOWN; u8 duplex = DUPLEX_UNKNOWN; @@ -2513,9 +2514,9 @@ static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, if (!carrier_ok) goto out; - for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { - if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask) { - speed = mlxsw_sp_port_link_mode[i].speed; + for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { + if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) { + speed = mlxsw_sp1_port_link_mode[i].speed; duplex = DUPLEX_FULL; break; } @@ -2526,39 +2527,39 @@ out: } static u32 -mlxsw_sp_to_ptys_advert_link(const struct ethtool_link_ksettings *cmd) +mlxsw_sp1_to_ptys_advert_link(const struct ethtool_link_ksettings *cmd) { u32 ptys_proto = 0; int i; - for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { - if (test_bit(mlxsw_sp_port_link_mode[i].mask_ethtool, + for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { + if (test_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool, cmd->link_modes.advertising)) - ptys_proto |= mlxsw_sp_port_link_mode[i].mask; + ptys_proto |= mlxsw_sp1_port_link_mode[i].mask; } return ptys_proto; } -static u32 mlxsw_sp_to_ptys_speed(u32 speed) +static u32 mlxsw_sp1_to_ptys_speed(u32 speed) { u32 ptys_proto = 0; int i; - for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { - if (speed == mlxsw_sp_port_link_mode[i].speed) - ptys_proto |= mlxsw_sp_port_link_mode[i].mask; + for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { + if (speed == mlxsw_sp1_port_link_mode[i].speed) + ptys_proto |= mlxsw_sp1_port_link_mode[i].mask; } return ptys_proto; } -static u32 mlxsw_sp_to_ptys_upper_speed(u32 upper_speed) +static u32 mlxsw_sp1_to_ptys_upper_speed(u32 upper_speed) { u32 ptys_proto = 0; int i; - for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { - if (mlxsw_sp_port_link_mode[i].speed <= upper_speed) - ptys_proto |= mlxsw_sp_port_link_mode[i].mask; + for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { + if (mlxsw_sp1_port_link_mode[i].speed <= upper_speed) + ptys_proto |= mlxsw_sp1_port_link_mode[i].mask; } return ptys_proto; } @@ -2570,8 +2571,8 @@ static void mlxsw_sp_port_get_link_supported(u32 eth_proto_cap, ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); - mlxsw_sp_from_ptys_supported_port(eth_proto_cap, cmd); - mlxsw_sp_from_ptys_link(eth_proto_cap, cmd->link_modes.supported); + mlxsw_sp1_from_ptys_supported_port(eth_proto_cap, cmd); + mlxsw_sp1_from_ptys_link(eth_proto_cap, cmd->link_modes.supported); } static void mlxsw_sp_port_get_link_advertise(u32 eth_proto_admin, bool autoneg, @@ -2581,7 +2582,7 @@ static void mlxsw_sp_port_get_link_advertise(u32 eth_proto_admin, bool autoneg, return; ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); - mlxsw_sp_from_ptys_link(eth_proto_admin, cmd->link_modes.advertising); + mlxsw_sp1_from_ptys_link(eth_proto_admin, cmd->link_modes.advertising); } static u8 @@ -2641,8 +2642,8 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl); cmd->base.port = mlxsw_sp_port_connector_port(connector_type); - mlxsw_sp_from_ptys_speed_duplex(netif_carrier_ok(dev), eth_proto_oper, - cmd); + mlxsw_sp1_from_ptys_speed_duplex(netif_carrier_ok(dev), eth_proto_oper, + cmd); return 0; } @@ -2666,8 +2667,8 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev, autoneg = cmd->base.autoneg == AUTONEG_ENABLE; eth_proto_new = autoneg ? - mlxsw_sp_to_ptys_advert_link(cmd) : - mlxsw_sp_to_ptys_speed(cmd->base.speed); + mlxsw_sp1_to_ptys_advert_link(cmd) : + mlxsw_sp1_to_ptys_speed(cmd->base.speed); eth_proto_new = eth_proto_new & eth_proto_cap; if (!eth_proto_new) { @@ -2867,7 +2868,7 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width) char ptys_pl[MLXSW_REG_PTYS_LEN]; u32 eth_proto_admin; - eth_proto_admin = mlxsw_sp_to_ptys_upper_speed(upper_speed); + eth_proto_admin = mlxsw_sp1_to_ptys_upper_speed(upper_speed); mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, eth_proto_admin, mlxsw_sp_port->link.autoneg); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); -- cgit v1.2.3 From c5b870df694051776c9d43179d1f4240e039c095 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:40 +0000 Subject: mlxsw: spectrum: Add port type-speed operations Add port type-speed operations in order to have different operations for different ASICs. For now, both ASICs use the same pointer. Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 137 +++++++++++++++++++------ drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 27 ++++- 2 files changed, 133 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 951e96b3a96b..895cc425157c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2473,7 +2473,8 @@ static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = { #define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode) static void -mlxsw_sp1_from_ptys_supported_port(u32 ptys_eth_proto, +mlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp, + u32 ptys_eth_proto, struct ethtool_link_ksettings *cmd) { if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | @@ -2492,7 +2493,9 @@ mlxsw_sp1_from_ptys_supported_port(u32 ptys_eth_proto, ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane); } -static void mlxsw_sp1_from_ptys_link(u32 ptys_eth_proto, unsigned long *mode) +static void +mlxsw_sp1_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto, + unsigned long *mode) { int i; @@ -2504,7 +2507,8 @@ static void mlxsw_sp1_from_ptys_link(u32 ptys_eth_proto, unsigned long *mode) } static void -mlxsw_sp1_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, +mlxsw_sp1_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok, + u32 ptys_eth_proto, struct ethtool_link_ksettings *cmd) { u32 speed = SPEED_UNKNOWN; @@ -2527,7 +2531,8 @@ out: } static u32 -mlxsw_sp1_to_ptys_advert_link(const struct ethtool_link_ksettings *cmd) +mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, + const struct ethtool_link_ksettings *cmd) { u32 ptys_proto = 0; int i; @@ -2540,7 +2545,7 @@ mlxsw_sp1_to_ptys_advert_link(const struct ethtool_link_ksettings *cmd) return ptys_proto; } -static u32 mlxsw_sp1_to_ptys_speed(u32 speed) +static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 speed) { u32 ptys_proto = 0; int i; @@ -2552,7 +2557,8 @@ static u32 mlxsw_sp1_to_ptys_speed(u32 speed) return ptys_proto; } -static u32 mlxsw_sp1_to_ptys_upper_speed(u32 upper_speed) +static u32 +mlxsw_sp1_to_ptys_upper_speed(struct mlxsw_sp *mlxsw_sp, u32 upper_speed) { u32 ptys_proto = 0; int i; @@ -2564,25 +2570,74 @@ static u32 mlxsw_sp1_to_ptys_upper_speed(u32 upper_speed) return ptys_proto; } -static void mlxsw_sp_port_get_link_supported(u32 eth_proto_cap, - struct ethtool_link_ksettings *cmd) +static int +mlxsw_sp1_port_speed_base(struct mlxsw_sp *mlxsw_sp, u8 local_port, + u32 *base_speed) +{ + *base_speed = MLXSW_SP_PORT_BASE_SPEED_25G; + return 0; +} + +static void +mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload, + u8 local_port, u32 proto_admin, bool autoneg) +{ + mlxsw_reg_ptys_eth_pack(payload, local_port, proto_admin, autoneg); +} + +static void +mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload, + u32 *p_eth_proto_cap, u32 *p_eth_proto_admin, + u32 *p_eth_proto_oper) +{ + mlxsw_reg_ptys_eth_unpack(payload, p_eth_proto_cap, p_eth_proto_admin, + p_eth_proto_oper); +} + +static const struct mlxsw_sp_port_type_speed_ops +mlxsw_sp1_port_type_speed_ops = { + .from_ptys_supported_port = mlxsw_sp1_from_ptys_supported_port, + .from_ptys_link = mlxsw_sp1_from_ptys_link, + .from_ptys_speed_duplex = mlxsw_sp1_from_ptys_speed_duplex, + .to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link, + .to_ptys_speed = mlxsw_sp1_to_ptys_speed, + .to_ptys_upper_speed = mlxsw_sp1_to_ptys_upper_speed, + .port_speed_base = mlxsw_sp1_port_speed_base, + .reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack, + .reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack, +}; + +static void +mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap, + struct ethtool_link_ksettings *cmd) { + const struct mlxsw_sp_port_type_speed_ops *ops; + + ops = mlxsw_sp->port_type_speed_ops; + ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause); ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); - mlxsw_sp1_from_ptys_supported_port(eth_proto_cap, cmd); - mlxsw_sp1_from_ptys_link(eth_proto_cap, cmd->link_modes.supported); + ops->from_ptys_supported_port(mlxsw_sp, eth_proto_cap, cmd); + ops->from_ptys_link(mlxsw_sp, eth_proto_cap, cmd->link_modes.supported); } -static void mlxsw_sp_port_get_link_advertise(u32 eth_proto_admin, bool autoneg, - struct ethtool_link_ksettings *cmd) +static void +mlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp, + u32 eth_proto_admin, bool autoneg, + struct ethtool_link_ksettings *cmd) { + const struct mlxsw_sp_port_type_speed_ops *ops; + + ops = mlxsw_sp->port_type_speed_ops; + if (!autoneg) return; ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); - mlxsw_sp1_from_ptys_link(eth_proto_admin, cmd->link_modes.advertising); + ops->from_ptys_link(mlxsw_sp, eth_proto_admin, + cmd->link_modes.advertising); } static u8 @@ -2619,31 +2674,36 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, u32 eth_proto_cap, eth_proto_admin, eth_proto_oper; struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + const struct mlxsw_sp_port_type_speed_ops *ops; char ptys_pl[MLXSW_REG_PTYS_LEN]; u8 connector_type; u8 autoneg_status; bool autoneg; int err; + ops = mlxsw_sp->port_type_speed_ops; + autoneg = mlxsw_sp_port->link.autoneg; - mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0, false); + ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, + 0, false); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); if (err) return err; - mlxsw_reg_ptys_eth_unpack(ptys_pl, ð_proto_cap, ð_proto_admin, - ð_proto_oper); + ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, ð_proto_cap, + ð_proto_admin, ð_proto_oper); - mlxsw_sp_port_get_link_supported(eth_proto_cap, cmd); + mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap, cmd); - mlxsw_sp_port_get_link_advertise(eth_proto_admin, autoneg, cmd); + mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg, + cmd); autoneg_status = mlxsw_reg_ptys_an_status_get(ptys_pl); cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl); cmd->base.port = mlxsw_sp_port_connector_port(connector_type); - mlxsw_sp1_from_ptys_speed_duplex(netif_carrier_ok(dev), eth_proto_oper, - cmd); + ops->from_ptys_speed_duplex(mlxsw_sp, netif_carrier_ok(dev), + eth_proto_oper, cmd); return 0; } @@ -2654,21 +2714,25 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev, { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + const struct mlxsw_sp_port_type_speed_ops *ops; char ptys_pl[MLXSW_REG_PTYS_LEN]; u32 eth_proto_cap, eth_proto_new; bool autoneg; int err; - mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0, false); + ops = mlxsw_sp->port_type_speed_ops; + + ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, + 0, false); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); if (err) return err; - mlxsw_reg_ptys_eth_unpack(ptys_pl, ð_proto_cap, NULL, NULL); + ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, ð_proto_cap, NULL, NULL); autoneg = cmd->base.autoneg == AUTONEG_ENABLE; eth_proto_new = autoneg ? - mlxsw_sp1_to_ptys_advert_link(cmd) : - mlxsw_sp1_to_ptys_speed(cmd->base.speed); + ops->to_ptys_advert_link(mlxsw_sp, cmd) : + ops->to_ptys_speed(mlxsw_sp, cmd->base.speed); eth_proto_new = eth_proto_new & eth_proto_cap; if (!eth_proto_new) { @@ -2676,8 +2740,8 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev, return -EINVAL; } - mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, - eth_proto_new, autoneg); + ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, + eth_proto_new, autoneg); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); if (err) return err; @@ -2864,13 +2928,24 @@ static int mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - u32 upper_speed = MLXSW_SP_PORT_BASE_SPEED * width; + const struct mlxsw_sp_port_type_speed_ops *ops; char ptys_pl[MLXSW_REG_PTYS_LEN]; u32 eth_proto_admin; + u32 upper_speed; + u32 base_speed; + int err; + + ops = mlxsw_sp->port_type_speed_ops; + + err = ops->port_speed_base(mlxsw_sp, mlxsw_sp_port->local_port, + &base_speed); + if (err) + return err; + upper_speed = base_speed * width; - eth_proto_admin = mlxsw_sp1_to_ptys_upper_speed(upper_speed); - mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, - eth_proto_admin, mlxsw_sp_port->link.autoneg); + eth_proto_admin = ops->to_ptys_upper_speed(mlxsw_sp, upper_speed); + ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, + eth_proto_admin, mlxsw_sp_port->link.autoneg); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); } @@ -4095,6 +4170,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask; mlxsw_sp->rif_ops_arr = mlxsw_sp1_rif_ops_arr; mlxsw_sp->sb_vals = &mlxsw_sp1_sb_vals; + mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info); } @@ -4113,6 +4189,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask; mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr; mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals; + mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 8bb83d0facc2..d4f53632b24c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -33,7 +33,7 @@ #define MLXSW_SP_PORTS_PER_CLUSTER_MAX 4 -#define MLXSW_SP_PORT_BASE_SPEED 25000 /* Mb/s */ +#define MLXSW_SP_PORT_BASE_SPEED_25G 25000 /* Mb/s */ #define MLXSW_SP_KVD_LINEAR_SIZE 98304 /* entries */ #define MLXSW_SP_KVD_GRANULARITY 128 @@ -134,6 +134,7 @@ struct mlxsw_sp_mr_tcam_ops; struct mlxsw_sp_acl_tcam_ops; struct mlxsw_sp_nve_ops; struct mlxsw_sp_sb_vals; +struct mlxsw_sp_port_type_speed_ops; struct mlxsw_sp { struct mlxsw_sp_port **ports; @@ -169,6 +170,7 @@ struct mlxsw_sp { const struct mlxsw_sp_nve_ops **nve_ops_arr; const struct mlxsw_sp_rif_ops **rif_ops_arr; const struct mlxsw_sp_sb_vals *sb_vals; + const struct mlxsw_sp_port_type_speed_ops *port_type_speed_ops; }; static inline struct mlxsw_sp_upper * @@ -258,6 +260,29 @@ struct mlxsw_sp_port { struct mlxsw_sp_acl_block *eg_acl_block; }; +struct mlxsw_sp_port_type_speed_ops { + void (*from_ptys_supported_port)(struct mlxsw_sp *mlxsw_sp, + u32 ptys_eth_proto, + struct ethtool_link_ksettings *cmd); + void (*from_ptys_link)(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto, + unsigned long *mode); + void (*from_ptys_speed_duplex)(struct mlxsw_sp *mlxsw_sp, + bool carrier_ok, u32 ptys_eth_proto, + struct ethtool_link_ksettings *cmd); + u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp, + const struct ethtool_link_ksettings *cmd); + u32 (*to_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u32 speed); + u32 (*to_ptys_upper_speed)(struct mlxsw_sp *mlxsw_sp, u32 upper_speed); + int (*port_speed_base)(struct mlxsw_sp *mlxsw_sp, u8 local_port, + u32 *base_speed); + void (*reg_ptys_eth_pack)(struct mlxsw_sp *mlxsw_sp, char *payload, + u8 local_port, u32 proto_admin, bool autoneg); + void (*reg_ptys_eth_unpack)(struct mlxsw_sp *mlxsw_sp, char *payload, + u32 *p_eth_proto_cap, + u32 *p_eth_proto_admin, + u32 *p_eth_proto_oper); +}; + static inline struct net_device * mlxsw_sp_bridge_vxlan_dev_find(struct net_device *br_dev) { -- cgit v1.2.3 From e6f66f50bfe6103c017c9996670389a318f45e9d Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:41 +0000 Subject: mlxsw: reg: Rename p_eth_proto_adm to full name p_eth_proto_admin Rename p_eth_proto_adm to p_eth_proto_admin in mlxsw_reg_ptys_eth_unpack function. Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index a781f09b79b9..34c5e603907b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -4091,13 +4091,13 @@ static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port, static inline void mlxsw_reg_ptys_eth_unpack(char *payload, u32 *p_eth_proto_cap, - u32 *p_eth_proto_adm, + u32 *p_eth_proto_admin, u32 *p_eth_proto_oper) { if (p_eth_proto_cap) *p_eth_proto_cap = mlxsw_reg_ptys_eth_proto_cap_get(payload); - if (p_eth_proto_adm) - *p_eth_proto_adm = mlxsw_reg_ptys_eth_proto_admin_get(payload); + if (p_eth_proto_admin) + *p_eth_proto_admin = mlxsw_reg_ptys_eth_proto_admin_get(payload); if (p_eth_proto_oper) *p_eth_proto_oper = mlxsw_reg_ptys_eth_proto_oper_get(payload); } -- cgit v1.2.3 From 1dc3c0a24867903b098b61eb7eb1d05b2e5093e9 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:42 +0000 Subject: mlxsw: reg: 80 columns wrapping change 80 columns wrapping change in mlxsw_reg_ptys_eth_unpack function. Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 34c5e603907b..a174ff2f8a8d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -4095,11 +4095,14 @@ static inline void mlxsw_reg_ptys_eth_unpack(char *payload, u32 *p_eth_proto_oper) { if (p_eth_proto_cap) - *p_eth_proto_cap = mlxsw_reg_ptys_eth_proto_cap_get(payload); + *p_eth_proto_cap = + mlxsw_reg_ptys_eth_proto_cap_get(payload); if (p_eth_proto_admin) - *p_eth_proto_admin = mlxsw_reg_ptys_eth_proto_admin_get(payload); + *p_eth_proto_admin = + mlxsw_reg_ptys_eth_proto_admin_get(payload); if (p_eth_proto_oper) - *p_eth_proto_oper = mlxsw_reg_ptys_eth_proto_oper_get(payload); + *p_eth_proto_oper = + mlxsw_reg_ptys_eth_proto_oper_get(payload); } static inline void mlxsw_reg_ptys_ib_pack(char *payload, u8 local_port, -- cgit v1.2.3 From 9ce8439718b6dfef2509dc72ec841740b14cc6d5 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:44 +0000 Subject: mlxsw: reg: Add new port type-speed fields for PTYS register PTYS register introduces a new layout for port type-speed fields. These fields extend the existing ones in order to handle more types and speeds. For example, the new 200Gbps speed. Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index a174ff2f8a8d..eb4c5e8964cd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3971,6 +3971,25 @@ enum { */ MLXSW_ITEM32(reg, ptys, an_status, 0x04, 28, 4); +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M BIT(0) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII BIT(1) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_2_5GBASE_X_2_5GMII BIT(2) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R BIT(3) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G BIT(4) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G BIT(5) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR BIT(6) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2 BIT(7) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR BIT(8) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4 BIT(9) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2 BIT(10) +#define MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4 BIT(12) + +/* reg_ptys_ext_eth_proto_cap + * Extended Ethernet port supported speeds and protocols. + * Access: RO + */ +MLXSW_ITEM32(reg, ptys, ext_eth_proto_cap, 0x08, 0, 32); + #define MLXSW_REG_PTYS_ETH_SPEED_SGMII BIT(0) #define MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX BIT(1) #define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 BIT(2) @@ -4025,6 +4044,12 @@ MLXSW_ITEM32(reg, ptys, ib_link_width_cap, 0x10, 16, 16); */ MLXSW_ITEM32(reg, ptys, ib_proto_cap, 0x10, 0, 16); +/* reg_ptys_ext_eth_proto_admin + * Extended speed and protocol to set port to. + * Access: RW + */ +MLXSW_ITEM32(reg, ptys, ext_eth_proto_admin, 0x14, 0, 32); + /* reg_ptys_eth_proto_admin * Speed and protocol to set port to. * Access: RW @@ -4043,6 +4068,12 @@ MLXSW_ITEM32(reg, ptys, ib_link_width_admin, 0x1C, 16, 16); */ MLXSW_ITEM32(reg, ptys, ib_proto_admin, 0x1C, 0, 16); +/* reg_ptys_ext_eth_proto_oper + * The extended current speed and protocol configured for the port. + * Access: RO + */ +MLXSW_ITEM32(reg, ptys, ext_eth_proto_oper, 0x20, 0, 32); + /* reg_ptys_eth_proto_oper * The current speed and protocol configured for the port. * Access: RO @@ -4089,6 +4120,16 @@ static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port, mlxsw_reg_ptys_an_disable_admin_set(payload, !autoneg); } +static inline void mlxsw_reg_ptys_ext_eth_pack(char *payload, u8 local_port, + u32 proto_admin, bool autoneg) +{ + MLXSW_REG_ZERO(ptys, payload); + mlxsw_reg_ptys_local_port_set(payload, local_port); + mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_ETH); + mlxsw_reg_ptys_ext_eth_proto_admin_set(payload, proto_admin); + mlxsw_reg_ptys_an_disable_admin_set(payload, !autoneg); +} + static inline void mlxsw_reg_ptys_eth_unpack(char *payload, u32 *p_eth_proto_cap, u32 *p_eth_proto_admin, @@ -4105,6 +4146,22 @@ static inline void mlxsw_reg_ptys_eth_unpack(char *payload, mlxsw_reg_ptys_eth_proto_oper_get(payload); } +static inline void mlxsw_reg_ptys_ext_eth_unpack(char *payload, + u32 *p_eth_proto_cap, + u32 *p_eth_proto_admin, + u32 *p_eth_proto_oper) +{ + if (p_eth_proto_cap) + *p_eth_proto_cap = + mlxsw_reg_ptys_ext_eth_proto_cap_get(payload); + if (p_eth_proto_admin) + *p_eth_proto_admin = + mlxsw_reg_ptys_ext_eth_proto_admin_get(payload); + if (p_eth_proto_oper) + *p_eth_proto_oper = + mlxsw_reg_ptys_ext_eth_proto_oper_get(payload); +} + static inline void mlxsw_reg_ptys_ib_pack(char *payload, u8 local_port, u16 proto_admin, u16 link_width) { -- cgit v1.2.3 From d3eaf1085a247344848e8bf454c6130b045fe495 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:45 +0000 Subject: mlxsw: spectrum: Add Spectrum-2 ASIC port type-speed operations Add Spectrum-2 ASIC port type-speed operations. Since multiple ethtool link modes are represented using a single bit in the ASIC, the driver forces the user to configure all types per a specific speed. For example, if the user wants to advertise 100Gbps 4-lanes speed, he should advertise all the types of 100Gbps 4-lanes speed that are supported by the ASIC as shown below: Supported ethtool bits for 100Gbps 4-lanes: 0x1000000000 100000baseKR4 Full 0x2000000000 100000baseSR4 Full 0x4000000000 100000baseCR4 Full 0x8000000000 100000baseLR4_ER4 Full Command for advertising 100Gbps 4-lanes: ethtool -s enp3s0np1 advertise 0xF000000000 Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 330 ++++++++++++++++++++++++- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 1 + 2 files changed, 330 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 895cc425157c..b4e38cde13d7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2607,6 +2607,334 @@ mlxsw_sp1_port_type_speed_ops = { .reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack, }; +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_sgmii_100m[] = { + ETHTOOL_LINK_MODE_100baseT_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_sgmii_100m) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_1000base_x_sgmii[] = { + ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_1000base_x_sgmii) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii[] = { + ETHTOOL_LINK_MODE_2500baseX_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_5gbase_r[] = { + ETHTOOL_LINK_MODE_5000baseT_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_5gbase_r) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g[] = { + ETHTOOL_LINK_MODE_10000baseT_Full_BIT, + ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseER_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g[] = { + ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr[] = { + ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2[] = { + ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, + ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, + ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = { + ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4) + +struct mlxsw_sp2_port_link_mode { + const enum ethtool_link_mode_bit_indices *mask_ethtool; + int m_ethtool_len; + u32 mask; + u32 speed; +}; + +static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = { + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M, + .mask_ethtool = mlxsw_sp2_mask_ethtool_sgmii_100m, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN, + .speed = SPEED_100, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII, + .mask_ethtool = mlxsw_sp2_mask_ethtool_1000base_x_sgmii, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN, + .speed = SPEED_1000, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_2_5GBASE_X_2_5GMII, + .mask_ethtool = mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN, + .speed = SPEED_2500, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R, + .mask_ethtool = mlxsw_sp2_mask_ethtool_5gbase_r, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN, + .speed = SPEED_5000, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G, + .mask_ethtool = mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN, + .speed = SPEED_10000, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G, + .mask_ethtool = mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN, + .speed = SPEED_40000, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR, + .mask_ethtool = mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN, + .speed = SPEED_25000, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2, + .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN, + .speed = SPEED_50000, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4, + .mask_ethtool = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN, + .speed = SPEED_100000, + }, +}; + +#define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode) + +static void +mlxsw_sp2_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp, + u32 ptys_eth_proto, + struct ethtool_link_ksettings *cmd) +{ + ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); + ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane); +} + +static void +mlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode, + unsigned long *mode) +{ + int i; + + for (i = 0; i < link_mode->m_ethtool_len; i++) + __set_bit(link_mode->mask_ethtool[i], mode); +} + +static void +mlxsw_sp2_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto, + unsigned long *mode) +{ + int i; + + for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { + if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) + mlxsw_sp2_set_bit_ethtool(&mlxsw_sp2_port_link_mode[i], + mode); + } +} + +static void +mlxsw_sp2_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok, + u32 ptys_eth_proto, + struct ethtool_link_ksettings *cmd) +{ + u32 speed = SPEED_UNKNOWN; + u8 duplex = DUPLEX_UNKNOWN; + int i; + + if (!carrier_ok) + goto out; + + for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { + if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) { + speed = mlxsw_sp2_port_link_mode[i].speed; + duplex = DUPLEX_FULL; + break; + } + } +out: + cmd->base.speed = speed; + cmd->base.duplex = duplex; +} + +static bool +mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode, + const unsigned long *mode) +{ + int cnt = 0; + int i; + + for (i = 0; i < link_mode->m_ethtool_len; i++) { + if (test_bit(link_mode->mask_ethtool[i], mode)) + cnt++; + } + + return cnt == link_mode->m_ethtool_len; +} + +static u32 +mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, + const struct ethtool_link_ksettings *cmd) +{ + u32 ptys_proto = 0; + int i; + + for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { + if (mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i], + cmd->link_modes.advertising)) + ptys_proto |= mlxsw_sp2_port_link_mode[i].mask; + } + return ptys_proto; +} + +static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 speed) +{ + u32 ptys_proto = 0; + int i; + + for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { + if (speed == mlxsw_sp2_port_link_mode[i].speed) + ptys_proto |= mlxsw_sp2_port_link_mode[i].mask; + } + return ptys_proto; +} + +static u32 +mlxsw_sp2_to_ptys_upper_speed(struct mlxsw_sp *mlxsw_sp, u32 upper_speed) +{ + u32 ptys_proto = 0; + int i; + + for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { + if (mlxsw_sp2_port_link_mode[i].speed <= upper_speed) + ptys_proto |= mlxsw_sp2_port_link_mode[i].mask; + } + return ptys_proto; +} + +static int +mlxsw_sp2_port_speed_base(struct mlxsw_sp *mlxsw_sp, u8 local_port, + u32 *base_speed) +{ + char ptys_pl[MLXSW_REG_PTYS_LEN]; + u32 eth_proto_cap; + int err; + + /* In Spectrum-2, the speed of 1x can change from port to port, so query + * it from firmware. + */ + mlxsw_reg_ptys_ext_eth_pack(ptys_pl, local_port, 0, false); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); + if (err) + return err; + mlxsw_reg_ptys_ext_eth_unpack(ptys_pl, ð_proto_cap, NULL, NULL); + + if (eth_proto_cap & + MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR) { + *base_speed = MLXSW_SP_PORT_BASE_SPEED_50G; + return 0; + } + + if (eth_proto_cap & + MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR) { + *base_speed = MLXSW_SP_PORT_BASE_SPEED_25G; + return 0; + } + + return -EIO; +} + +static void +mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload, + u8 local_port, u32 proto_admin, + bool autoneg) +{ + mlxsw_reg_ptys_ext_eth_pack(payload, local_port, proto_admin, autoneg); +} + +static void +mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload, + u32 *p_eth_proto_cap, u32 *p_eth_proto_admin, + u32 *p_eth_proto_oper) +{ + mlxsw_reg_ptys_ext_eth_unpack(payload, p_eth_proto_cap, + p_eth_proto_admin, p_eth_proto_oper); +} + +static const struct mlxsw_sp_port_type_speed_ops +mlxsw_sp2_port_type_speed_ops = { + .from_ptys_supported_port = mlxsw_sp2_from_ptys_supported_port, + .from_ptys_link = mlxsw_sp2_from_ptys_link, + .from_ptys_speed_duplex = mlxsw_sp2_from_ptys_speed_duplex, + .to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link, + .to_ptys_speed = mlxsw_sp2_to_ptys_speed, + .to_ptys_upper_speed = mlxsw_sp2_to_ptys_upper_speed, + .port_speed_base = mlxsw_sp2_port_speed_base, + .reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack, + .reg_ptys_eth_unpack = mlxsw_sp2_reg_ptys_eth_unpack, +}; + static void mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap, struct ethtool_link_ksettings *cmd) @@ -4189,7 +4517,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask; mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr; mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals; - mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops; + mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops; return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index d4f53632b24c..a61c1130d9e3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -34,6 +34,7 @@ #define MLXSW_SP_PORTS_PER_CLUSTER_MAX 4 #define MLXSW_SP_PORT_BASE_SPEED_25G 25000 /* Mb/s */ +#define MLXSW_SP_PORT_BASE_SPEED_50G 50000 /* Mb/s */ #define MLXSW_SP_KVD_LINEAR_SIZE 98304 /* entries */ #define MLXSW_SP_KVD_GRANULARITY 128 -- cgit v1.2.3 From 6c485084af8d981f1e9002a39498cef735af4180 Mon Sep 17 00:00:00 2001 From: Shalom Toledo Date: Fri, 22 Feb 2019 13:56:46 +0000 Subject: mlxsw: spectrum: Add Spectrum-2 ASIC support for new port types and speeds Add Spectrum-2 ASIC support for the following new port types and speeds: * 50Gbps 1-lane * 100Gbps 2-lanes * 200Gbps 4-lanes Signed-off-by: Shalom Toledo Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 54 ++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index b4e38cde13d7..40177b9834c4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2685,6 +2685,18 @@ mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2[] = { #define MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN \ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2) +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr[] = { + ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr) + static const enum ethtool_link_mode_bit_indices mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, @@ -2696,6 +2708,30 @@ mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = { #define MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN \ ARRAY_SIZE(mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4) +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2[] = { + ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2) + +static const enum ethtool_link_mode_bit_indices +mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = { + ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, +}; + +#define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \ + ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4) + struct mlxsw_sp2_port_link_mode { const enum ethtool_link_mode_bit_indices *mask_ethtool; int m_ethtool_len; @@ -2752,12 +2788,30 @@ static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = { .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN, .speed = SPEED_50000, }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR, + .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN, + .speed = SPEED_50000, + }, { .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4, .mask_ethtool = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4, .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN, .speed = SPEED_100000, }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2, + .mask_ethtool = mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN, + .speed = SPEED_100000, + }, + { + .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4, + .mask_ethtool = mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4, + .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN, + .speed = SPEED_200000, + }, }; #define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode) -- cgit v1.2.3 From 0974f1f03b07543f3225414118e6e7ff205da96e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 22 Feb 2019 23:48:14 +0100 Subject: net: phy: aquantia: remove false 5G and 10G speed ability for AQCS109 AQCS109 belongs to a family of PHY's where certain members don't support 5G or 10G. However for all members of the family the chip reports 10G and 5G capability. Therefore remove the not supported modes for AQCS109. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 34be44d00c19..9661ef4b40b0 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -152,6 +152,15 @@ static int aqr_read_status(struct phy_device *phydev) return 0; } +static int aqcs109_config_init(struct phy_device *phydev) +{ + /* AQCS109 belongs to a chip family partially supporting 10G and 5G. + * PMA speed ability bits are the same for all members of the family, + * AQCS109 however supports speeds up to 2.5G only. + */ + return phy_set_max_speed(phydev, SPEED_2500); +} + static struct phy_driver aqr_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), @@ -208,6 +217,7 @@ static struct phy_driver aqr_driver[] = { .name = "Aquantia AQCS109", .aneg_done = genphy_c45_aneg_done, .get_features = genphy_c45_pma_read_abilities, + .config_init = aqcs109_config_init, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, -- cgit v1.2.3 From 09c4c57f7bc4150cfe516126d921ae15c32750e7 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Fri, 22 Feb 2019 23:49:54 +0100 Subject: net: phy: aquantia: add support for auto-negotiation configuration Make use of the generic c45 code, plus code specific to the Aquantia phy for 1000BaseT negotiation. Signed-off-by: Andrew Lunn Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 9661ef4b40b0..a1846daa3388 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -20,6 +20,10 @@ #define PHY_ID_AQCS109 0x03a1b5c2 #define PHY_ID_AQR405 0x03a1b4b0 +#define MDIO_AN_VEND_PROV 0xc400 +#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) +#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) + #define MDIO_AN_TX_VEND_STATUS1 0xc800 #define MDIO_AN_TX_VEND_STATUS1_10BASET (0x0 << 1) #define MDIO_AN_TX_VEND_STATUS1_100BASETX (0x1 << 1) @@ -64,10 +68,40 @@ static int aqr_config_aneg(struct phy_device *phydev) { - linkmode_copy(phydev->supported, phy_10gbit_features); - linkmode_copy(phydev->advertising, phydev->supported); + bool changed = false; + u16 reg; + int ret; - return 0; + if (phydev->autoneg == AUTONEG_DISABLE) + return genphy_c45_pma_setup_forced(phydev); + + ret = genphy_c45_an_config_aneg(phydev); + if (ret < 0) + return ret; + if (ret > 0) + changed = true; + + /* Clause 45 has no standardized support for 1000BaseT, therefore + * use vendor registers for this mode. + */ + reg = 0; + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->advertising)) + reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + phydev->advertising)) + reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; + + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, + MDIO_AN_VEND_PROV_1000BASET_HALF | + MDIO_AN_VEND_PROV_1000BASET_FULL, reg); + if (ret < 0) + return ret; + if (ret > 0) + changed = true; + + return genphy_c45_check_and_restart_aneg(phydev, changed); } static int aqr_config_intr(struct phy_device *phydev) -- cgit v1.2.3 From 3b845d87d858dd699c5fbc2081ea0fd8ba1f1e9c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 22 Feb 2019 23:50:49 +0100 Subject: net: phy: don't change modes we don't care about in genphy_c45_read_lpa Because 1000BaseT isn't covered by Clause 45, the 1000BaseT flags in phydev->lp_advertising may have been set based on vendor registers already. genphy_c45_read_lpa() would clear these flags as of today. Therefore switch to mii_lpa_mod_linkmode_lpa_t. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index fc3173cc078b..2d1ba43e14ec 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -275,7 +275,7 @@ int genphy_c45_read_lpa(struct phy_device *phydev) if (val < 0) return val; - mii_lpa_to_linkmode_lpa_t(phydev->lp_advertising, val); + mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, val); phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0; phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0; -- cgit v1.2.3 From 70fa3a9699cbc7aa1e93a5fddb9b9105d2b3acda Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 22 Feb 2019 23:51:44 +0100 Subject: net: phy: add genphy_c45_read_status Similar to genphy_read_status() for Clause 22 add a generic read_status function for Clause 45. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 33 +++++++++++++++++++++++++++++++++ include/linux/phy.h | 1 + 2 files changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 2d1ba43e14ec..c86bef005ef2 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -454,6 +454,39 @@ int genphy_c45_pma_read_abilities(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities); +/** + * genphy_c45_read_status - read PHY status + * @phydev: target phy_device struct + * + * Reads status from PHY and sets phy_device members accordingly. + */ +int genphy_c45_read_status(struct phy_device *phydev) +{ + int ret; + + ret = genphy_c45_read_link(phydev); + if (ret) + return ret; + + phydev->speed = SPEED_UNKNOWN; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; + + if (phydev->autoneg == AUTONEG_ENABLE) { + ret = genphy_c45_read_lpa(phydev); + if (ret) + return ret; + + phy_resolve_aneg_linkmode(phydev); + } else { + ret = genphy_c45_read_pma(phydev); + } + + return ret; +} +EXPORT_SYMBOL_GPL(genphy_c45_read_status); + /* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev) diff --git a/include/linux/phy.h b/include/linux/phy.h index 8e9fc576472b..a05ba366dae4 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1107,6 +1107,7 @@ int genphy_c45_an_config_aneg(struct phy_device *phydev); int genphy_c45_an_disable_aneg(struct phy_device *phydev); int genphy_c45_read_mdix(struct phy_device *phydev); int genphy_c45_pma_read_abilities(struct phy_device *phydev); +int genphy_c45_read_status(struct phy_device *phydev); /* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev); -- cgit v1.2.3 From dc59d9bb9c0d7ad5b5722a83b2030dbb1a71ea2c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 22 Feb 2019 23:52:32 +0100 Subject: net: phy: aquantia: use genphy_c45_read_status Use new function genphy_c45_read_status(). 1000BaseT link partner advertisement needs to be read from vendor registers. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 46 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index a1846daa3388..0f0eb568267d 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -39,6 +39,10 @@ #define MDIO_AN_TX_VEND_INT_MASK2 0xd401 #define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) +#define MDIO_AN_RX_LP_STAT1 0xe820 +#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) +#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) + /* Vendor specific 1, MDIO_MMD_VEND1 */ #define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 #define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 @@ -154,36 +158,22 @@ static int aqr_ack_interrupt(struct phy_device *phydev) static int aqr_read_status(struct phy_device *phydev) { - int reg; - - reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); - reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); - if (reg & MDIO_STAT1_LSTATUS) - phydev->link = 1; - else - phydev->link = 0; - - reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); - mdelay(10); - reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_STATUS1); - - switch (reg & MDIO_AN_TX_VEND_STATUS1_RATE_MASK) { - case MDIO_AN_TX_VEND_STATUS1_2500BASET: - phydev->speed = SPEED_2500; - break; - case MDIO_AN_TX_VEND_STATUS1_1000BASET: - phydev->speed = SPEED_1000; - break; - case MDIO_AN_TX_VEND_STATUS1_100BASETX: - phydev->speed = SPEED_100; - break; - default: - phydev->speed = SPEED_10000; - break; + int val; + + if (phydev->autoneg == AUTONEG_ENABLE) { + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->lp_advertising, + val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + phydev->lp_advertising, + val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); } - phydev->duplex = DUPLEX_FULL; - return 0; + return genphy_c45_read_status(phydev); } static int aqcs109_config_init(struct phy_device *phydev) -- cgit v1.2.3 From b6a4119d9d01633d78409fed457fbe840c757f79 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 22 Feb 2019 08:23:04 +0100 Subject: net: phy: let genphy_c45_read_abilities also check aneg capability When using genphy_c45_read_abilities() as get_features callback we also have to set the autoneg capability in phydev->supported. Signed-off-by: Heiner Kallweit Reviewed-by: Maxime Chevallier Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index c86bef005ef2..d79c27431aa5 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -380,6 +380,17 @@ int genphy_c45_pma_read_abilities(struct phy_device *phydev) { int val; + linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) { + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); + if (val < 0) + return val; + + if (val & MDIO_AN_STAT1_ABLE) + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + phydev->supported); + } + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2); if (val < 0) return val; -- cgit v1.2.3 From 2e8b4ba64676f0871ee5952c23cdef6d4ac35195 Mon Sep 17 00:00:00 2001 From: Andy Roulin Date: Fri, 22 Feb 2019 18:06:37 +0000 Subject: macvlan: add ndo_change_proto_down support Add ndo_change_proto_down support through dev_change_proto_down_generic for use by control protocols like VRRPD. Signed-off-by: Andy Roulin Acked-by: Roopa Prabhu Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 26e53832b095..0c0f105657d3 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -1122,6 +1122,7 @@ static const struct net_device_ops macvlan_netdev_ops = { #endif .ndo_get_iflink = macvlan_dev_get_iflink, .ndo_features_check = passthru_features_check, + .ndo_change_proto_down = dev_change_proto_down_generic, }; void macvlan_common_setup(struct net_device *dev) -- cgit v1.2.3 From 8f1af75df3a7a670d125f31ede3cfea1f5c1a81b Mon Sep 17 00:00:00 2001 From: Andy Roulin Date: Fri, 22 Feb 2019 18:06:38 +0000 Subject: vxlan: add ndo_change_proto_down support Add ndo_change_proto_down support through dev_change_proto_down_generic for use by control protocols like VRRPD. Signed-off-by: Andy Roulin Acked-by: Roopa Prabhu Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 33edc78e818d..577201cd880c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2923,6 +2923,7 @@ static const struct net_device_ops vxlan_netdev_ether_ops = { .ndo_fdb_dump = vxlan_fdb_dump, .ndo_fdb_get = vxlan_fdb_get, .ndo_fill_metadata_dst = vxlan_fill_metadata_dst, + .ndo_change_proto_down = dev_change_proto_down_generic, }; static const struct net_device_ops vxlan_netdev_raw_ops = { -- cgit v1.2.3 From 6a5f9161bc0e282b813f8f7d98c1cea85c374a5e Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Fri, 22 Feb 2019 20:12:57 +0100 Subject: net: lantiq: Do not use eth_change_mtu() eth_change_mtu() is not needed any more, the networking subsystem will call it automatically when this callback is not implemented. Signed-off-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/ethernet/lantiq_xrx200.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c index 2d4d10a017e5..d29104de0d53 100644 --- a/drivers/net/ethernet/lantiq_xrx200.c +++ b/drivers/net/ethernet/lantiq_xrx200.c @@ -335,7 +335,6 @@ static const struct net_device_ops xrx200_netdev_ops = { .ndo_start_xmit = xrx200_start_xmit, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, }; static irqreturn_t xrx200_dma_irq(int irq, void *ptr) -- cgit v1.2.3 From d7977107b393bfa66ef83d8513070ba23e0708dd Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Feb 2019 12:31:33 -0800 Subject: nfp: Remove switchdev.h inclusion This is no longer necessary after a5084bb71fa4 ("nfp: Implement ndo_get_port_parent_id()") Signed-off-by: Florian Fainelli Acked-by: Jakub Kicinski Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_port.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c index 7e90880fa46b..93c5bfc0510b 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_port.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c @@ -3,7 +3,6 @@ #include #include -#include #include "nfpcore/nfp_cpp.h" #include "nfpcore/nfp_nsp.h" -- cgit v1.2.3 From 47f706262f1d53aff4c67a4e74fbb051d60a7526 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 22 Feb 2019 12:31:34 -0800 Subject: net: Remove switchdev.h inclusion from team/bond/vlan This is no longer necessary after eca59f691566 ("net: Remove support for bridge bypass ndos from stacked devices") Suggested-by: Ido Schimmel Signed-off-by: Florian Fainelli Reviewed-by: Andy Gospodarek Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 1 - drivers/net/team/team.c | 1 - net/8021q/vlan_dev.c | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 537c90c8eb0a..b59708c35faf 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 6ce3f666d142..6ed96fdfd96d 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index b2d9c8f27cd7..15293c2a5dd8 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -31,7 +31,6 @@ #include #include #include -#include #include "vlan.h" #include "vlanproc.h" -- cgit v1.2.3 From c1164bb1a631205a28b9dd8d4a9331a689e85561 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 22 Feb 2019 22:59:38 +0100 Subject: net: phy: check PMAPMD link status only in genphy_c45_read_link The current code reports a link as up if all devices (except a few blacklisted ones) report the link as up. This breaks Aquantia AQCS109 for lower speeds because on this PHY the PCS link status reflects a 10G link only. For Marvell there's a similar issue, therefore PHYXS device isn't checked. There may be more PHYs where depending on the mode the link status of only selected devices is relevant. For now it seems to be sufficient to check the link status of the PMAPMD device only. Leave the loop in the code to be prepared in case we have to add functionality to check more than one device, depending on the mode. Successfully tested on a board with an AQCS109. Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index d79c27431aa5..49e7cd08b05f 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -215,17 +215,10 @@ EXPORT_SYMBOL_GPL(genphy_c45_aneg_done); */ int genphy_c45_read_link(struct phy_device *phydev) { - u32 mmd_mask = phydev->c45_ids.devices_in_package; + u32 mmd_mask = MDIO_DEVS_PMAPMD; int val, devad; bool link = true; - /* The vendor devads and C22EXT do not report link status. Avoid the - * PHYXS instance as its status may depend on the MAC being - * appropriately configured for the negotiated speed. - */ - mmd_mask &= ~(MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2 | MDIO_DEVS_C22EXT | - MDIO_DEVS_PHYXS); - while (mmd_mask && link) { devad = __ffs(mmd_mask); mmd_mask &= ~BIT(devad); -- cgit v1.2.3 From 7414542406cd3806bac8ec7d50b63969cb98b37f Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Sat, 23 Feb 2019 00:37:38 +0100 Subject: net: phy: marvell10g: Use get_features to get the PHY abilities The Alaska family of 10G PHYs has more abilities than the ones listed in PHY_10GBIT_FULL_FEATURES, the exact list depending on the model. Make use of the newly introduced .get_features call to build this list, using genphy_c45_pma_read_abilities to build the list of supported linkmodes, and adding autoneg ability based on what's reported by the AN MMD. .config_init is still used to validate the interface_mode. Signed-off-by: Maxime Chevallier Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 586ae1bc5a50..89920b10d75b 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -233,8 +233,6 @@ static int mv3310_resume(struct phy_device *phydev) static int mv3310_config_init(struct phy_device *phydev) { - int ret, val; - /* Check that the PHY interface type is compatible */ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && phydev->interface != PHY_INTERFACE_MODE_XAUI && @@ -242,6 +240,13 @@ static int mv3310_config_init(struct phy_device *phydev) phydev->interface != PHY_INTERFACE_MODE_10GKR) return -ENODEV; + return 0; +} + +static int mv3310_get_features(struct phy_device *phydev) +{ + int ret, val; + if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) { val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); if (val < 0) @@ -416,7 +421,7 @@ static struct phy_driver mv3310_drivers[] = { .phy_id = 0x002b09aa, .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "mv88x3310", - .features = PHY_10GBIT_FEATURES, + .get_features = mv3310_get_features, .soft_reset = gen10g_no_soft_reset, .config_init = mv3310_config_init, .probe = mv3310_probe, -- cgit v1.2.3 From 0feaccd595fb130f23833938db77551f534b4932 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Sat, 23 Feb 2019 00:37:39 +0100 Subject: net: phy: marvell10g: Use linkmode_set_bit helper instead of __set_bit Cosmetic patch making use of helpers dedicated to linkmodes handling. Signed-off-by: Maxime Chevallier Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 89920b10d75b..821ef1b2f8cc 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -253,8 +253,8 @@ static int mv3310_get_features(struct phy_device *phydev) return val; if (val & MDIO_AN_STAT1_ABLE) - __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + phydev->supported); } ret = genphy_c45_pma_read_abilities(phydev); -- cgit v1.2.3 From e555e5b1b9aeec679eecb228fa9a36c070c57cbb Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Sat, 23 Feb 2019 00:37:40 +0100 Subject: net: phy: marvell10g: Use 2500BASEX when using 2.5GBASET The Marvell Alaska family of PHYs supports 2.5GBaseT and 5GBaseT modes, as defined in the 802.3bz specification. Upon establishing a 2.5GBASET link, the PHY will reconfigure it's MII interface to 2500BASEX. At 5G, the PHY will reconfigure it's interface to 5GBASE-R, but this mode isn't supported by any MAC for now. This was tested with : - The 88X3310, which is on the MacchiatoBin - The 88E2010, an Alaska PHY that has no fiber interfaces, and is limited to 5G maximum speed. Signed-off-by: Maxime Chevallier Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 821ef1b2f8cc..9342d8c2ff7f 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -235,6 +235,7 @@ static int mv3310_config_init(struct phy_device *phydev) { /* Check that the PHY interface type is compatible */ if (phydev->interface != PHY_INTERFACE_MODE_SGMII && + phydev->interface != PHY_INTERFACE_MODE_2500BASEX && phydev->interface != PHY_INTERFACE_MODE_XAUI && phydev->interface != PHY_INTERFACE_MODE_RXAUI && phydev->interface != PHY_INTERFACE_MODE_10GKR) @@ -313,18 +314,29 @@ static int mv3310_aneg_done(struct phy_device *phydev) static void mv3310_update_interface(struct phy_device *phydev) { if ((phydev->interface == PHY_INTERFACE_MODE_SGMII || + phydev->interface == PHY_INTERFACE_MODE_2500BASEX || phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) { /* The PHY automatically switches its serdes interface (and - * active PHYXS instance) between Cisco SGMII and 10GBase-KR - * modes according to the speed. Florian suggests setting - * phydev->interface to communicate this to the MAC. Only do - * this if we are already in either SGMII or 10GBase-KR mode. + * active PHYXS instance) between Cisco SGMII, 10GBase-KR and + * 2500BaseX modes according to the speed. Florian suggests + * setting phydev->interface to communicate this to the MAC. + * Only do this if we are already in one of the above modes. */ - if (phydev->speed == SPEED_10000) + switch (phydev->speed) { + case SPEED_10000: phydev->interface = PHY_INTERFACE_MODE_10GKR; - else if (phydev->speed >= SPEED_10 && - phydev->speed < SPEED_10000) + break; + case SPEED_2500: + phydev->interface = PHY_INTERFACE_MODE_2500BASEX; + break; + case SPEED_1000: + case SPEED_100: + case SPEED_10: phydev->interface = PHY_INTERFACE_MODE_SGMII; + break; + default: + break; + } } } -- cgit v1.2.3 From 631ba9063b446800e96debb41ad45eba85f880a8 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Sat, 23 Feb 2019 00:37:41 +0100 Subject: net: phy: marvell10g: Use a #define for 88X3310 family id The PHY ID corresponding to the 88X3310 is also used for other PHYs in the same family, such as the 88E2010. Use a #define for the PHY id, that ignores the last nibble. Signed-off-by: Maxime Chevallier Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 4 ++-- include/linux/marvell_phy.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 9342d8c2ff7f..9c0b8f16cec5 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -430,7 +430,7 @@ static int mv3310_read_status(struct phy_device *phydev) static struct phy_driver mv3310_drivers[] = { { - .phy_id = 0x002b09aa, + .phy_id = MARVELL_PHY_ID_88X3310, .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "mv88x3310", .get_features = mv3310_get_features, @@ -448,7 +448,7 @@ static struct phy_driver mv3310_drivers[] = { module_phy_driver(mv3310_drivers); static struct mdio_device_id __maybe_unused mv3310_tbl[] = { - { 0x002b09aa, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK }, { }, }; MODULE_DEVICE_TABLE(mdio, mv3310_tbl); diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index 1eb6f244588d..70c17345e118 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -20,6 +20,7 @@ #define MARVELL_PHY_ID_88E1540 0x01410eb0 #define MARVELL_PHY_ID_88E1545 0x01410ea0 #define MARVELL_PHY_ID_88E3016 0x01410e60 +#define MARVELL_PHY_ID_88X3310 0x002b09a0 /* The MV88e6390 Ethernet switch contains embedded PHYs. These PHYs do * not have a model ID. So the switch driver traps reads to the ID2 -- cgit v1.2.3 From c47455f9a7fc9129cb2e8d839e8bb70b96d7ded2 Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Sat, 23 Feb 2019 00:37:42 +0100 Subject: net: phy: marvell10g: Force reading of 2.5/5G As per 802.3bz, if bit 14 of (1.11) "PMA Extended Abilities" indicates whether or not we should read register (1.21) "2.52/5G PMA Extended Abilities", which contains information on the support of 2.5GBASET and 5GBASET. After testing on several variants of PHYS of this family, it appears that bit 14 in (1.11) isn't always set when it should be. PHYs 88X3310 (on MacchiatoBin) and 88E2010 do support 2.5G and 5GBASET, but don't have 1.11.14 set. Their register 1.21 is filled with the correct values, indicating 2.5G and 5G support. PHYs 88E2110 do have their 1.11.14 bit set, as it should. Signed-off-by: Maxime Chevallier Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 9c0b8f16cec5..8f354c3f3876 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -27,6 +27,9 @@ #include #include +#define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe +#define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa) + enum { MV_PCS_BASE_T = 0x0000, MV_PCS_BASE_R = 0x1000, @@ -231,6 +234,23 @@ static int mv3310_resume(struct phy_device *phydev) return mv3310_hwmon_config(phydev, true); } +/* Some PHYs in the Alaska family such as the 88X3310 and the 88E2010 + * don't set bit 14 in PMA Extended Abilities (1.11), although they do + * support 2.5GBASET and 5GBASET. For these models, we can still read their + * 2.5G/5G extended abilities register (1.21). We detect these models based on + * the PMA device identifier, with a mask matching models known to have this + * issue + */ +static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev) +{ + if (!(phydev->c45_ids.devices_in_package & MDIO_DEVS_PMAPMD)) + return false; + + /* Only some revisions of the 88X3310 family PMA seem to be impacted */ + return (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] & + MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV; +} + static int mv3310_config_init(struct phy_device *phydev) { /* Check that the PHY interface type is compatible */ @@ -262,6 +282,21 @@ static int mv3310_get_features(struct phy_device *phydev) if (ret) return ret; + if (mv3310_has_pma_ngbaset_quirk(phydev)) { + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, + MDIO_PMA_NG_EXTABLE); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->supported, + val & MDIO_PMA_NG_EXTABLE_2_5GBT); + + linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + phydev->supported, + val & MDIO_PMA_NG_EXTABLE_5GBT); + } + return 0; } -- cgit v1.2.3 From b38d198cfbc556b52a4ba28b27e8728b4d73aa8c Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Sat, 23 Feb 2019 00:37:43 +0100 Subject: net: mvpp2: Add 2.5GBaseT support The PPv2 controller is able to support 2.5G speeds, allowing to use 2.5GBASET in conjunction with PHYs that use 2500BASEX as their MII interface when using this mode. Signed-off-by: Maxime Chevallier Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 191d9ce85b7e..6638a3339efc 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4403,6 +4403,7 @@ static void mvpp2_phylink_validate(struct net_device *dev, case PHY_INTERFACE_MODE_2500BASEX: phylink_set(mask, 1000baseT_Full); phylink_set(mask, 1000baseX_Full); + phylink_set(mask, 2500baseT_Full); phylink_set(mask, 2500baseX_Full); break; default: -- cgit v1.2.3 From 62d01535474b612b3c5d864999b17cbf2cd8f2cc Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Sat, 23 Feb 2019 00:37:44 +0100 Subject: net: phy: marvell10g: add support for the 88x2110 PHY This patch adds support for the 88x2110 PHY, which is similar to the already supported 88x3310 PHY without the SFP interface. It supports 10/100/1000BASET along with 2.5GBASET, 5GBASET and 10GBASET, with the same interface modes that are used by the 3310. This PHY don't have the same issue as the 88x3310 regarding 2.5/5G abilities, and correctly follows the 802.3bz standard to list the supported abilities. Signed-off-by: Maxime Chevallier Suggested-by: Antoine Tenart Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 13 +++++++++++++ include/linux/marvell_phy.h | 1 + 2 files changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 8f354c3f3876..580e91deadbc 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -478,12 +478,25 @@ static struct phy_driver mv3310_drivers[] = { .aneg_done = mv3310_aneg_done, .read_status = mv3310_read_status, }, + { + .phy_id = MARVELL_PHY_ID_88E2110, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "mv88x2110", + .features = PHY_10GBIT_FEATURES, + .probe = mv3310_probe, + .soft_reset = gen10g_no_soft_reset, + .config_init = mv3310_config_init, + .config_aneg = mv3310_config_aneg, + .aneg_done = mv3310_aneg_done, + .read_status = mv3310_read_status, + }, }; module_phy_driver(mv3310_drivers); static struct mdio_device_id __maybe_unused mv3310_tbl[] = { { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK }, { }, }; MODULE_DEVICE_TABLE(mdio, mv3310_tbl); diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index 70c17345e118..73d04743a2bb 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -21,6 +21,7 @@ #define MARVELL_PHY_ID_88E1545 0x01410ea0 #define MARVELL_PHY_ID_88E3016 0x01410e60 #define MARVELL_PHY_ID_88X3310 0x002b09a0 +#define MARVELL_PHY_ID_88E2110 0x002b09b0 /* The MV88e6390 Ethernet switch contains embedded PHYs. These PHYs do * not have a model ID. So the switch driver traps reads to the ID2 -- cgit v1.2.3 From 42fc6a4c613019666f2fd11bc0b542cf2f4dae24 Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Fri, 22 Feb 2019 16:36:47 -0800 Subject: net: dsa: microchip: prepare PHY for proper advertisement Prepare PHY for proper advertisement as sometimes the PHY in the switch has its own problems even though it may share the PHY id from regular PHY but the fixes in the PHY driver do not apply. Signed-off-by: Tristram Ha Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz9477.c | 13 ++++++++++++- drivers/net/dsa/microchip/ksz_common.c | 3 ++- drivers/net/dsa/microchip/ksz_priv.h | 4 +++- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 674d77e1b029..4573b6ed2c4f 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -2,7 +2,7 @@ /* * Microchip KSZ9477 switch driver main logic * - * Copyright (C) 2017-2018 Microchip Technology Inc. + * Copyright (C) 2017-2019 Microchip Technology Inc. */ #include @@ -966,6 +966,16 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port, PORT_MIRROR_SNIFFER, false); } +static void ksz9477_phy_setup(struct ksz_device *dev, int port, + struct phy_device *phy) +{ + if (port < dev->phy_port_cnt) { + /* The MAC actually cannot run in 1000 half-duplex mode. */ + phy_remove_link_mode(phy, + ETHTOOL_LINK_MODE_1000baseT_Half_BIT); + } +} + static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) { u8 data8; @@ -1299,6 +1309,7 @@ static const struct ksz_dev_ops ksz9477_dev_ops = { .get_port_addr = ksz9477_get_port_addr, .cfg_port_member = ksz9477_cfg_port_member, .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, + .phy_setup = ksz9477_phy_setup, .port_setup = ksz9477_port_setup, .shutdown = ksz9477_reset_switch, .detect = ksz9477_switch_detect, diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 8a5111f9414c..6f728429eec6 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -2,7 +2,7 @@ /* * Microchip switch driver main logic * - * Copyright (C) 2017-2018 Microchip Technology Inc. + * Copyright (C) 2017-2019 Microchip Technology Inc. */ #include @@ -238,6 +238,7 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) /* setup slave port */ dev->dev_ops->port_setup(dev, port, false); + dev->dev_ops->phy_setup(dev, port, phy); /* port_stp_state_set() will be called after to enable the port so * there is no need to do anything. diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h index 60b49010904b..0fdc58bdd503 100644 --- a/drivers/net/dsa/microchip/ksz_priv.h +++ b/drivers/net/dsa/microchip/ksz_priv.h @@ -2,7 +2,7 @@ * * Microchip KSZ series switch common definitions * - * Copyright (C) 2017-2018 Microchip Technology Inc. + * Copyright (C) 2017-2019 Microchip Technology Inc. */ #ifndef __KSZ_PRIV_H @@ -137,6 +137,8 @@ struct ksz_dev_ops { u32 (*get_port_addr)(int port, int offset); void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member); void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); + void (*phy_setup)(struct ksz_device *dev, int port, + struct phy_device *phy); void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val); -- cgit v1.2.3 From 7c6ff470aa867f53b8522a3a5c84c36ac7a20090 Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Fri, 22 Feb 2019 16:36:48 -0800 Subject: net: dsa: microchip: add MIB counter reading support Add background MIB counter reading support. Port MIB counters should only be read when there is link. Otherwise it is a waste of time as hardware never increases those counters. There are exceptions as some switches keep track of dropped counts no matter what. Signed-off-by: Tristram Ha Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz9477.c | 123 ++++++++++++++++++++++----------- drivers/net/dsa/microchip/ksz_common.c | 103 +++++++++++++++++++++++++++ drivers/net/dsa/microchip/ksz_common.h | 18 ++++- drivers/net/dsa/microchip/ksz_priv.h | 9 ++- 4 files changed, 205 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 4573b6ed2c4f..94cd38515ab8 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -18,8 +19,8 @@ #include #include "ksz_priv.h" -#include "ksz_common.h" #include "ksz9477_reg.h" +#include "ksz_common.h" static const struct { int index; @@ -259,6 +260,75 @@ static int ksz9477_reset_switch(struct ksz_device *dev) return 0; } +static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, + u64 *cnt) +{ + struct ksz_poll_ctx ctx = { + .dev = dev, + .port = port, + .offset = REG_PORT_MIB_CTRL_STAT__4, + }; + struct ksz_port *p = &dev->ports[port]; + u32 data; + int ret; + + /* retain the flush/freeze bit */ + data = p->freeze ? MIB_COUNTER_FLUSH_FREEZE : 0; + data |= MIB_COUNTER_READ; + data |= (addr << MIB_COUNTER_INDEX_S); + ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data); + + ret = readx_poll_timeout(ksz_pread32_poll, &ctx, data, + !(data & MIB_COUNTER_READ), 10, 1000); + + /* failed to read MIB. get out of loop */ + if (ret < 0) { + dev_dbg(dev->dev, "Failed to get MIB\n"); + return; + } + + /* count resets upon read */ + ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data); + *cnt += data; +} + +static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt) +{ + addr = ksz9477_mib_names[addr].index; + ksz9477_r_mib_cnt(dev, port, addr, cnt); +} + +static void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze) +{ + u32 val = freeze ? MIB_COUNTER_FLUSH_FREEZE : 0; + struct ksz_port *p = &dev->ports[port]; + + /* enable/disable the port for flush/freeze function */ + mutex_lock(&p->mib.cnt_mutex); + ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, val); + + /* used by MIB counter reading code to know freeze is enabled */ + p->freeze = freeze; + mutex_unlock(&p->mib.cnt_mutex); +} + +static void ksz9477_port_init_cnt(struct ksz_device *dev, int port) +{ + struct ksz_port_mib *mib = &dev->ports[port].mib; + + /* flush all enabled port MIB counters */ + mutex_lock(&mib->cnt_mutex); + ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, + MIB_COUNTER_FLUSH_FREEZE); + ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH); + ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0); + mutex_unlock(&mib->cnt_mutex); + + mib->cnt_ptr = 0; + memset(mib->counters, 0, dev->mib_cnt * sizeof(u64)); +} + static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds, int port) { @@ -342,47 +412,6 @@ static void ksz9477_get_strings(struct dsa_switch *ds, int port, } } -static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, - uint64_t *buf) -{ - struct ksz_device *dev = ds->priv; - int i; - u32 data; - int timeout; - - mutex_lock(&dev->stats_mutex); - - for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) { - data = MIB_COUNTER_READ; - data |= ((ksz9477_mib_names[i].index & 0xFF) << - MIB_COUNTER_INDEX_S); - ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data); - - timeout = 1000; - do { - ksz_pread32(dev, port, REG_PORT_MIB_CTRL_STAT__4, - &data); - usleep_range(1, 10); - if (!(data & MIB_COUNTER_READ)) - break; - } while (timeout-- > 0); - - /* failed to read MIB. get out of loop */ - if (!timeout) { - dev_dbg(dev->dev, "Failed to get MIB\n"); - break; - } - - /* count resets upon read */ - ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data); - - dev->mib_value[i] += (uint64_t)data; - buf[i] = dev->mib_value[i]; - } - - mutex_unlock(&dev->stats_mutex); -} - static void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member) { @@ -1151,9 +1180,14 @@ static int ksz9477_setup(struct dsa_switch *ds) /* queue based egress rate limit */ ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true); + /* enable global MIB counter freeze function */ + ksz_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true); + /* start switch */ ksz_cfg(dev, REG_SW_OPERATION, SW_START, true); + ksz_init_mib_timer(dev); + return 0; } @@ -1287,6 +1321,7 @@ static int ksz9477_switch_init(struct ksz_device *dev) if (!dev->ports) return -ENOMEM; for (i = 0; i < dev->mib_port_cnt; i++) { + mutex_init(&dev->ports[i].mib.cnt_mutex); dev->ports[i].mib.counters = devm_kzalloc(dev->dev, sizeof(u64) * @@ -1311,6 +1346,10 @@ static const struct ksz_dev_ops ksz9477_dev_ops = { .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, .phy_setup = ksz9477_phy_setup, .port_setup = ksz9477_port_setup, + .r_mib_cnt = ksz9477_r_mib_cnt, + .r_mib_pkt = ksz9477_r_mib_pkt, + .freeze_mib = ksz9477_freeze_mib, + .port_init_cnt = ksz9477_port_init_cnt, .shutdown = ksz9477_reset_switch, .detect = ksz9477_switch_detect, .init = ksz9477_switch_init, diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 6f728429eec6..eecfbf30cdc2 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -40,6 +40,85 @@ void ksz_update_port_member(struct ksz_device *dev, int port) } EXPORT_SYMBOL_GPL(ksz_update_port_member); +static void port_r_cnt(struct ksz_device *dev, int port) +{ + struct ksz_port_mib *mib = &dev->ports[port].mib; + u64 *dropped; + + /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ + while (mib->cnt_ptr < dev->reg_mib_cnt) { + dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, + &mib->counters[mib->cnt_ptr]); + ++mib->cnt_ptr; + } + + /* last one in storage */ + dropped = &mib->counters[dev->mib_cnt]; + + /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ + while (mib->cnt_ptr < dev->mib_cnt) { + dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, + dropped, &mib->counters[mib->cnt_ptr]); + ++mib->cnt_ptr; + } + mib->cnt_ptr = 0; +} + +static void ksz_mib_read_work(struct work_struct *work) +{ + struct ksz_device *dev = container_of(work, struct ksz_device, + mib_read); + struct ksz_port_mib *mib; + struct ksz_port *p; + int i; + + for (i = 0; i < dev->mib_port_cnt; i++) { + p = &dev->ports[i]; + mib = &p->mib; + mutex_lock(&mib->cnt_mutex); + + /* Only read MIB counters when the port is told to do. + * If not, read only dropped counters when link is not up. + */ + if (!p->read) { + const struct dsa_port *dp = dsa_to_port(dev->ds, i); + + if (!netif_carrier_ok(dp->slave)) + mib->cnt_ptr = dev->reg_mib_cnt; + } + port_r_cnt(dev, i); + p->read = false; + mutex_unlock(&mib->cnt_mutex); + } +} + +static void mib_monitor(struct timer_list *t) +{ + struct ksz_device *dev = from_timer(dev, t, mib_read_timer); + + mod_timer(&dev->mib_read_timer, jiffies + dev->mib_read_interval); + schedule_work(&dev->mib_read); +} + +void ksz_init_mib_timer(struct ksz_device *dev) +{ + int i; + + /* Read MIB counters every 30 seconds to avoid overflow. */ + dev->mib_read_interval = msecs_to_jiffies(30000); + + INIT_WORK(&dev->mib_read, ksz_mib_read_work); + timer_setup(&dev->mib_read_timer, mib_monitor, 0); + + for (i = 0; i < dev->mib_port_cnt; i++) + dev->dev_ops->port_init_cnt(dev, i); + + /* Start the timer 2 seconds later. */ + dev->mib_read_timer.expires = jiffies + msecs_to_jiffies(2000); + add_timer(&dev->mib_read_timer); +} +EXPORT_SYMBOL_GPL(ksz_init_mib_timer); + int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) { struct ksz_device *dev = ds->priv; @@ -72,6 +151,24 @@ int ksz_sset_count(struct dsa_switch *ds, int port, int sset) } EXPORT_SYMBOL_GPL(ksz_sset_count); +void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf) +{ + const struct dsa_port *dp = dsa_to_port(ds, port); + struct ksz_device *dev = ds->priv; + struct ksz_port_mib *mib; + + mib = &dev->ports[port].mib; + mutex_lock(&mib->cnt_mutex); + + /* Only read dropped counters if no link. */ + if (!netif_carrier_ok(dp->slave)) + mib->cnt_ptr = dev->reg_mib_cnt; + port_r_cnt(dev, port); + memcpy(buf, mib->counters, dev->mib_cnt * sizeof(u64)); + mutex_unlock(&mib->cnt_mutex); +} +EXPORT_SYMBOL_GPL(ksz_get_ethtool_stats); + int ksz_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br) { @@ -339,6 +436,12 @@ EXPORT_SYMBOL(ksz_switch_register); void ksz_switch_remove(struct ksz_device *dev) { + /* timer started */ + if (dev->mib_read_timer.expires) { + del_timer_sync(&dev->mib_read_timer); + flush_work(&dev->mib_read); + } + dev->dev_ops->exit(dev); dsa_unregister_switch(dev->ds); diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 2dd832de0d52..f45a55369e4b 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -1,19 +1,21 @@ /* SPDX-License-Identifier: GPL-2.0 * Microchip switch driver common header * - * Copyright (C) 2017-2018 Microchip Technology Inc. + * Copyright (C) 2017-2019 Microchip Technology Inc. */ #ifndef __KSZ_COMMON_H #define __KSZ_COMMON_H void ksz_update_port_member(struct ksz_device *dev, int port); +void ksz_init_mib_timer(struct ksz_device *dev); /* Common DSA access functions */ int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg); int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val); int ksz_sset_count(struct dsa_switch *ds, int port, int sset); +void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf); int ksz_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br); void ksz_port_bridge_leave(struct dsa_switch *ds, int port, @@ -211,4 +213,18 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, ksz_write8(dev, addr, data); } +struct ksz_poll_ctx { + struct ksz_device *dev; + int port; + int offset; +}; + +static inline u32 ksz_pread32_poll(struct ksz_poll_ctx *ctx) +{ + u32 data; + + ksz_pread32(ctx->dev, ctx->port, ctx->offset, &data); + return data; +} + #endif diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h index 0fdc58bdd503..1d2d98f35bb0 100644 --- a/drivers/net/dsa/microchip/ksz_priv.h +++ b/drivers/net/dsa/microchip/ksz_priv.h @@ -14,8 +14,6 @@ #include #include -#include "ksz9477_reg.h" - struct ksz_io_ops; struct vlan_table { @@ -23,6 +21,7 @@ struct vlan_table { }; struct ksz_port_mib { + struct mutex cnt_mutex; /* structure access */ u8 cnt_ptr; u64 *counters; }; @@ -38,7 +37,8 @@ struct ksz_port { u32 fiber:1; /* port is fiber */ u32 sgmii:1; /* port is SGMII */ u32 force:1; - u32 link_just_down:1; /* link just goes down */ + u32 read:1; /* read MIB counters in background */ + u32 freeze:1; /* MIB counter freeze is enabled */ struct ksz_port_mib mib; }; @@ -79,8 +79,6 @@ struct ksz_device { struct vlan_table *vlan_cache; - u64 mib_value[TOTAL_SWITCH_COUNTER_NUM]; - u8 *txbuf; struct ksz_port *ports; @@ -153,6 +151,7 @@ struct ksz_dev_ops { u64 *cnt); void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr, u64 *dropped, u64 *cnt); + void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze); void (*port_init_cnt)(struct ksz_device *dev, int port); int (*shutdown)(struct ksz_device *dev); int (*detect)(struct ksz_device *dev); -- cgit v1.2.3 From c30d894b6a6a2d1c7ea47d06e6ad4fb5cf0b4999 Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Fri, 22 Feb 2019 16:36:49 -0800 Subject: net: dsa: microchip: get port link status Get port link status to know whether to read MIB counters when the link is going down. Signed-off-by: Tristram Ha Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz9477.c | 1 + drivers/net/dsa/microchip/ksz_common.c | 14 ++++++++++++++ drivers/net/dsa/microchip/ksz_common.h | 2 ++ 3 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 94cd38515ab8..1b8267c8177f 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -1196,6 +1196,7 @@ static const struct dsa_switch_ops ksz9477_switch_ops = { .setup = ksz9477_setup, .phy_read = ksz9477_phy_read16, .phy_write = ksz9477_phy_write16, + .adjust_link = ksz_adjust_link, .port_enable = ksz_enable_port, .port_disable = ksz_disable_port, .get_strings = ksz9477_get_strings, diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index eecfbf30cdc2..0589fc7ad09e 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -140,6 +140,20 @@ int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) } EXPORT_SYMBOL_GPL(ksz_phy_write16); +void ksz_adjust_link(struct dsa_switch *ds, int port, + struct phy_device *phydev) +{ + struct ksz_device *dev = ds->priv; + struct ksz_port *p = &dev->ports[port]; + + /* Read all MIB counters when the link is going down. */ + if (!phydev->link) { + p->read = true; + schedule_work(&dev->mib_read); + } +} +EXPORT_SYMBOL_GPL(ksz_adjust_link); + int ksz_sset_count(struct dsa_switch *ds, int port, int sset) { struct ksz_device *dev = ds->priv; diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index f45a55369e4b..eb29bb076e67 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -14,6 +14,8 @@ void ksz_init_mib_timer(struct ksz_device *dev); int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg); int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val); +void ksz_adjust_link(struct dsa_switch *ds, int port, + struct phy_device *phydev); int ksz_sset_count(struct dsa_switch *ds, int port, int sset); void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf); int ksz_port_bridge_join(struct dsa_switch *ds, int port, -- cgit v1.2.3 From 6ca5081526228571a70ef0160fd44da3fe661ccb Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Fri, 22 Feb 2019 16:36:50 -0800 Subject: net: dsa: microchip: remove unnecessary include headers Remove unnecessary header include. Signed-off-by: Tristram Ha Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz9477.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 1b8267c8177f..b1b86b60f708 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -5,15 +5,11 @@ * Copyright (C) 2017-2019 Microchip Technology Inc. */ -#include -#include -#include #include #include #include #include #include -#include #include #include #include -- cgit v1.2.3 From 7049f9b5d0529a8fefaae681e57baeb31bd2d40a Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Fri, 22 Feb 2019 16:36:51 -0800 Subject: net: dsa: microchip: add port_cleanup function Add port_cleanup function to reset some device variables when the port is disabled. Add a mutex to make sure changing those variables is thread-safe. Signed-off-by: Tristram Ha Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz9477.c | 6 ++++++ drivers/net/dsa/microchip/ksz_common.c | 22 ++++++++++++++++++++++ drivers/net/dsa/microchip/ksz_common.h | 1 + drivers/net/dsa/microchip/ksz_priv.h | 2 ++ 4 files changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index b1b86b60f708..03de50e62beb 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -450,12 +450,14 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port, break; member = dev->host_mask | p->vid_member; + mutex_lock(&dev->dev_mutex); /* Port is a member of a bridge. */ if (dev->br_member & (1 << port)) { dev->member |= (1 << port); member = dev->member; } + mutex_unlock(&dev->dev_mutex); break; case BR_STATE_BLOCKING: data |= PORT_LEARN_DISABLE; @@ -470,6 +472,7 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port, ksz_pwrite8(dev, port, P_STP_CTRL, data); p->stp_state = state; + mutex_lock(&dev->dev_mutex); if (data & PORT_RX_ENABLE) dev->rx_ports |= (1 << port); else @@ -494,6 +497,7 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port, */ if (forward != dev->member) ksz_update_port_member(dev, port); + mutex_unlock(&dev->dev_mutex); } static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port) @@ -1080,6 +1084,7 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) ksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_1, data8); p->phydev.duplex = 1; } + mutex_lock(&dev->dev_mutex); if (cpu_port) { member = dev->port_mask; dev->on_ports = dev->host_mask; @@ -1092,6 +1097,7 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) if (p->phydev.link) dev->live_ports |= (1 << port); } + mutex_unlock(&dev->dev_mutex); ksz9477_cfg_port_member(dev, port, member); /* clear pending interrupts */ diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 0589fc7ad09e..d89c97724c35 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -20,6 +20,16 @@ #include "ksz_priv.h" +void ksz_port_cleanup(struct ksz_device *dev, int port) +{ + /* Common code for port cleanup. */ + mutex_lock(&dev->dev_mutex); + dev->on_ports &= ~(1 << port); + dev->live_ports &= ~(1 << port); + mutex_unlock(&dev->dev_mutex); +} +EXPORT_SYMBOL_GPL(ksz_port_cleanup); + void ksz_update_port_member(struct ksz_device *dev, int port) { struct ksz_port *p; @@ -151,6 +161,13 @@ void ksz_adjust_link(struct dsa_switch *ds, int port, p->read = true; schedule_work(&dev->mib_read); } + mutex_lock(&dev->dev_mutex); + if (!phydev->link) + dev->live_ports &= ~(1 << port); + else + /* Remember which port is connected and active. */ + dev->live_ports |= (1 << port) & dev->on_ports; + mutex_unlock(&dev->dev_mutex); } EXPORT_SYMBOL_GPL(ksz_adjust_link); @@ -188,7 +205,9 @@ int ksz_port_bridge_join(struct dsa_switch *ds, int port, { struct ksz_device *dev = ds->priv; + mutex_lock(&dev->dev_mutex); dev->br_member |= (1 << port); + mutex_unlock(&dev->dev_mutex); /* port_stp_state_set() will be called after to put the port in * appropriate state so there is no need to do anything. @@ -203,8 +222,10 @@ void ksz_port_bridge_leave(struct dsa_switch *ds, int port, { struct ksz_device *dev = ds->priv; + mutex_lock(&dev->dev_mutex); dev->br_member &= ~(1 << port); dev->member &= ~(1 << port); + mutex_unlock(&dev->dev_mutex); /* port_stp_state_set() will be called after to put the port in * forwarding state so there is no need to do anything. @@ -417,6 +438,7 @@ int ksz_switch_register(struct ksz_device *dev, gpiod_set_value(dev->reset_gpio, 0); } + mutex_init(&dev->dev_mutex); mutex_init(&dev->reg_mutex); mutex_init(&dev->stats_mutex); mutex_init(&dev->alu_mutex); diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index eb29bb076e67..0d25bc44f453 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -7,6 +7,7 @@ #ifndef __KSZ_COMMON_H #define __KSZ_COMMON_H +void ksz_port_cleanup(struct ksz_device *dev, int port); void ksz_update_port_member(struct ksz_device *dev, int port); void ksz_init_mib_timer(struct ksz_device *dev); diff --git a/drivers/net/dsa/microchip/ksz_priv.h b/drivers/net/dsa/microchip/ksz_priv.h index 1d2d98f35bb0..b52e5ca17ab4 100644 --- a/drivers/net/dsa/microchip/ksz_priv.h +++ b/drivers/net/dsa/microchip/ksz_priv.h @@ -48,6 +48,7 @@ struct ksz_device { struct ksz_platform_data *pdata; const char *name; + struct mutex dev_mutex; /* device access */ struct mutex reg_mutex; /* register access */ struct mutex stats_mutex; /* status access */ struct mutex alu_mutex; /* ALU access */ @@ -137,6 +138,7 @@ struct ksz_dev_ops { void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); void (*phy_setup)(struct ksz_device *dev, int port, struct phy_device *phy); + void (*port_cleanup)(struct ksz_device *dev, int port); void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val); -- cgit v1.2.3 From 7c3cb68f488ebee1ea5695cd26434df192ce2239 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:22 +0000 Subject: mlxsw: spectrum_acl: Remove unused ops field from group structure Never used, remove it. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 7e225a86e3a8..80bf0a510203 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -164,7 +164,6 @@ struct mlxsw_sp_acl_tcam_group { struct list_head vregion_list; unsigned int region_count; struct rhashtable vchunk_ht; - struct mlxsw_sp_acl_tcam_group_ops *ops; const struct mlxsw_sp_acl_tcam_pattern *patterns; unsigned int patterns_count; bool tmplt_elusage_set; -- cgit v1.2.3 From 2802aadfcff32a61d4afe78c07137dac63cd8d3c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:23 +0000 Subject: mlxsw: spectrum_acl: Split TCAM group structure into two Make the existing group structure to contain fields needed for HW region list manipulations. Move the rest of the fields into new vgroup struct. This makes layering cleaner as the vgroup struct is on higher level than low-level group struct. Also, this makes it possible to introduce fine-grained locking. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 260 +++++++++++++-------- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 2 + 2 files changed, 161 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 80bf0a510203..922f17adcee7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -161,8 +161,13 @@ struct mlxsw_sp_acl_tcam_pattern { struct mlxsw_sp_acl_tcam_group { struct mlxsw_sp_acl_tcam *tcam; u16 id; - struct list_head vregion_list; + struct list_head region_list; unsigned int region_count; +}; + +struct mlxsw_sp_acl_tcam_vgroup { + struct mlxsw_sp_acl_tcam_group group; + struct list_head vregion_list; struct rhashtable vchunk_ht; const struct mlxsw_sp_acl_tcam_pattern *patterns; unsigned int patterns_count; @@ -176,7 +181,6 @@ struct mlxsw_sp_acl_tcam_vregion { struct list_head list; /* Member of a TCAM group */ struct list_head tlist; /* Member of a TCAM */ struct list_head vchunk_list; /* List of vchunks under this vregion */ - struct mlxsw_sp_acl_tcam_group *group; struct mlxsw_afk_key_info *key_info; struct mlxsw_sp_acl_tcam *tcam; struct delayed_work rehash_dw; @@ -200,7 +204,7 @@ struct mlxsw_sp_acl_tcam_vchunk { struct rhash_head ht_node; /* Member of a chunk HT */ struct list_head ventry_list; unsigned int priority; /* Priority within the vregion and group */ - struct mlxsw_sp_acl_tcam_group *group; + struct mlxsw_sp_acl_tcam_vgroup *vgroup; struct mlxsw_sp_acl_tcam_vregion *vregion; unsigned int ref_count; }; @@ -229,46 +233,73 @@ static const struct rhashtable_params mlxsw_sp_acl_tcam_vchunk_ht_params = { static int mlxsw_sp_acl_tcam_group_update(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_group *group) { - struct mlxsw_sp_acl_tcam_vregion *vregion; + struct mlxsw_sp_acl_tcam_region *region; char pagt_pl[MLXSW_REG_PAGT_LEN]; int acl_index = 0; mlxsw_reg_pagt_pack(pagt_pl, group->id); - list_for_each_entry(vregion, &group->vregion_list, list) { - if (vregion->region2) - mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++, - vregion->region2->id, true); + list_for_each_entry(region, &group->region_list, list) { + bool multi = false; + + /* Check if the next entry in the list has the same vregion. */ + if (region->list.next != &group->region_list && + list_next_entry(region, list)->vregion == region->vregion) + multi = true; mlxsw_reg_pagt_acl_id_pack(pagt_pl, acl_index++, - vregion->region->id, false); + region->id, multi); } mlxsw_reg_pagt_size_set(pagt_pl, acl_index); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pagt), pagt_pl); } static int -mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam *tcam, - struct mlxsw_sp_acl_tcam_group *group, - const struct mlxsw_sp_acl_tcam_pattern *patterns, - unsigned int patterns_count, - struct mlxsw_afk_element_usage *tmplt_elusage) +mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp_acl_tcam *tcam, + struct mlxsw_sp_acl_tcam_group *group) { int err; group->tcam = tcam; - group->patterns = patterns; - group->patterns_count = patterns_count; + INIT_LIST_HEAD(&group->region_list); + + err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id); + if (err) + return err; + + return 0; +} + +static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp_acl_tcam_group *group) +{ + struct mlxsw_sp_acl_tcam *tcam = group->tcam; + + mlxsw_sp_acl_tcam_group_id_put(tcam, group->id); + WARN_ON(!list_empty(&group->region_list)); +} + +static int +mlxsw_sp_acl_tcam_vgroup_add(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam *tcam, + struct mlxsw_sp_acl_tcam_vgroup *vgroup, + const struct mlxsw_sp_acl_tcam_pattern *patterns, + unsigned int patterns_count, + struct mlxsw_afk_element_usage *tmplt_elusage) +{ + int err; + + vgroup->patterns = patterns; + vgroup->patterns_count = patterns_count; if (tmplt_elusage) { - group->tmplt_elusage_set = true; - memcpy(&group->tmplt_elusage, tmplt_elusage, - sizeof(group->tmplt_elusage)); + vgroup->tmplt_elusage_set = true; + memcpy(&vgroup->tmplt_elusage, tmplt_elusage, + sizeof(vgroup->tmplt_elusage)); } - INIT_LIST_HEAD(&group->vregion_list); - err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id); + INIT_LIST_HEAD(&vgroup->vregion_list); + + err = mlxsw_sp_acl_tcam_group_add(tcam, &vgroup->group); if (err) return err; - err = rhashtable_init(&group->vchunk_ht, + err = rhashtable_init(&vgroup->vchunk_ht, &mlxsw_sp_acl_tcam_vchunk_ht_params); if (err) goto err_rhashtable_init; @@ -276,18 +307,16 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp *mlxsw_sp, return 0; err_rhashtable_init: - mlxsw_sp_acl_tcam_group_id_put(tcam, group->id); + mlxsw_sp_acl_tcam_group_del(&vgroup->group); return err; } -static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group) +static void +mlxsw_sp_acl_tcam_vgroup_del(struct mlxsw_sp_acl_tcam_vgroup *vgroup) { - struct mlxsw_sp_acl_tcam *tcam = group->tcam; - - rhashtable_destroy(&group->vchunk_ht); - mlxsw_sp_acl_tcam_group_id_put(tcam, group->id); - WARN_ON(!list_empty(&group->vregion_list)); + rhashtable_destroy(&vgroup->vchunk_ht); + mlxsw_sp_acl_tcam_group_del(&vgroup->group); + WARN_ON(!list_empty(&vgroup->vregion_list)); } static int @@ -353,52 +382,78 @@ mlxsw_sp_acl_tcam_vregion_max_prio(struct mlxsw_sp_acl_tcam_vregion *vregion) static int mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_region *region) + struct mlxsw_sp_acl_tcam_group *group, + struct mlxsw_sp_acl_tcam_region *region, + struct mlxsw_sp_acl_tcam_region *next_region) { - struct mlxsw_sp_acl_tcam_group *group = region->vregion->group; + struct mlxsw_sp_acl_tcam_region *region2; + struct list_head *pos; int err; if (group->region_count == group->tcam->max_group_size) return -ENOBUFS; + if (next_region) { + /* If the next region is defined, place the new one + * before it. The next one is a sibling. + */ + pos = &next_region->list; + } else { + /* Position the region inside the list according to priority */ + list_for_each(pos, &group->region_list) { + region2 = list_entry(pos, typeof(*region2), list); + if (mlxsw_sp_acl_tcam_vregion_prio(region2->vregion) > + mlxsw_sp_acl_tcam_vregion_prio(region->vregion)) + break; + } + } + list_add_tail(®ion->list, pos); + region->group = group; + err = mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group); if (err) - return err; + goto err_group_update; group->region_count++; return 0; + +err_group_update: + list_del(®ion->list); + return err; } static void mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_region *region) { - struct mlxsw_sp_acl_tcam_group *group = region->vregion->group; + struct mlxsw_sp_acl_tcam_group *group = region->group; + list_del(®ion->list); group->region_count--; mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group); } static int -mlxsw_sp_acl_tcam_group_vregion_attach(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, - struct mlxsw_sp_acl_tcam_vregion *vregion) +mlxsw_sp_acl_tcam_vgroup_vregion_attach(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vgroup *vgroup, + struct mlxsw_sp_acl_tcam_vregion *vregion) { struct mlxsw_sp_acl_tcam_vregion *vregion2; struct list_head *pos; int err; /* Position the vregion inside the list according to priority */ - list_for_each(pos, &group->vregion_list) { + list_for_each(pos, &vgroup->vregion_list) { vregion2 = list_entry(pos, typeof(*vregion2), list); if (mlxsw_sp_acl_tcam_vregion_prio(vregion2) > - mlxsw_sp_acl_tcam_vregion_prio(vregion)) + mlxsw_sp_acl_tcam_vregion_prio(vregion)) { break; + } } list_add_tail(&vregion->list, pos); - vregion->group = group; - err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, vregion->region); + err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, &vgroup->group, + vregion->region, NULL); if (err) goto err_region_attach; @@ -410,8 +465,8 @@ err_region_attach: } static void -mlxsw_sp_acl_tcam_group_vregion_detach(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vregion *vregion) +mlxsw_sp_acl_tcam_vgroup_vregion_detach(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion) { list_del(&vregion->list); if (vregion->region2) @@ -421,22 +476,22 @@ mlxsw_sp_acl_tcam_group_vregion_detach(struct mlxsw_sp *mlxsw_sp, } static struct mlxsw_sp_acl_tcam_vregion * -mlxsw_sp_acl_tcam_group_vregion_find(struct mlxsw_sp_acl_tcam_group *group, - unsigned int priority, - struct mlxsw_afk_element_usage *elusage, - bool *p_need_split) +mlxsw_sp_acl_tcam_vgroup_vregion_find(struct mlxsw_sp_acl_tcam_vgroup *vgroup, + unsigned int priority, + struct mlxsw_afk_element_usage *elusage, + bool *p_need_split) { struct mlxsw_sp_acl_tcam_vregion *vregion, *vregion2; struct list_head *pos; bool issubset; - list_for_each(pos, &group->vregion_list) { + list_for_each(pos, &vgroup->vregion_list) { vregion = list_entry(pos, typeof(*vregion), list); /* First, check if the requested priority does not rather belong * under some of the next vregions. */ - if (pos->next != &group->vregion_list) { /* not last */ + if (pos->next != &vgroup->vregion_list) { /* not last */ vregion2 = list_entry(pos->next, typeof(*vregion2), list); if (priority >= @@ -477,9 +532,9 @@ mlxsw_sp_acl_tcam_group_vregion_find(struct mlxsw_sp_acl_tcam_group *group, } static void -mlxsw_sp_acl_tcam_group_use_patterns(struct mlxsw_sp_acl_tcam_group *group, - struct mlxsw_afk_element_usage *elusage, - struct mlxsw_afk_element_usage *out) +mlxsw_sp_acl_tcam_vgroup_use_patterns(struct mlxsw_sp_acl_tcam_vgroup *vgroup, + struct mlxsw_afk_element_usage *elusage, + struct mlxsw_afk_element_usage *out) { const struct mlxsw_sp_acl_tcam_pattern *pattern; int i; @@ -487,14 +542,14 @@ mlxsw_sp_acl_tcam_group_use_patterns(struct mlxsw_sp_acl_tcam_group *group, /* In case the template is set, we don't have to look up the pattern * and just use the template. */ - if (group->tmplt_elusage_set) { - memcpy(out, &group->tmplt_elusage, sizeof(*out)); + if (vgroup->tmplt_elusage_set) { + memcpy(out, &vgroup->tmplt_elusage, sizeof(*out)); WARN_ON(!mlxsw_afk_element_usage_subset(elusage, out)); return; } - for (i = 0; i < group->patterns_count; i++) { - pattern = &group->patterns[i]; + for (i = 0; i < vgroup->patterns_count; i++) { + pattern = &vgroup->patterns[i]; mlxsw_afk_element_usage_fill(out, pattern->elements, pattern->elements_count); if (mlxsw_afk_element_usage_subset(elusage, out)) @@ -627,7 +682,7 @@ mlxsw_sp_acl_tcam_region_destroy(struct mlxsw_sp *mlxsw_sp, ops->region_fini(mlxsw_sp, region->priv); mlxsw_sp_acl_tcam_region_disable(mlxsw_sp, region); mlxsw_sp_acl_tcam_region_free(mlxsw_sp, region); - mlxsw_sp_acl_tcam_region_id_put(region->vregion->group->tcam, + mlxsw_sp_acl_tcam_region_id_put(region->group->tcam, region->id); kfree(region); } @@ -763,7 +818,7 @@ int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, + struct mlxsw_sp_acl_tcam_vgroup *vgroup, unsigned int priority, struct mlxsw_afk_element_usage *elusage, struct mlxsw_sp_acl_tcam_vchunk *vchunk) @@ -773,8 +828,8 @@ mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp, bool need_split; int err; - vregion = mlxsw_sp_acl_tcam_group_vregion_find(group, priority, elusage, - &need_split); + vregion = mlxsw_sp_acl_tcam_vgroup_vregion_find(vgroup, priority, + elusage, &need_split); if (vregion && need_split) { /* According to priority, the vchunk should belong to an * existing vregion. However, this vchunk needs elements @@ -787,10 +842,10 @@ mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp, if (!vregion) { struct mlxsw_afk_element_usage vregion_elusage; - mlxsw_sp_acl_tcam_group_use_patterns(group, elusage, - &vregion_elusage); + mlxsw_sp_acl_tcam_vgroup_use_patterns(vgroup, elusage, + &vregion_elusage); vregion = mlxsw_sp_acl_tcam_vregion_create(mlxsw_sp, - group->tcam, + vgroup->group.tcam, &vregion_elusage); if (IS_ERR(vregion)) return PTR_ERR(vregion); @@ -803,13 +858,14 @@ mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp, if (!vregion_created) return 0; - err = mlxsw_sp_acl_tcam_group_vregion_attach(mlxsw_sp, group, vregion); + err = mlxsw_sp_acl_tcam_vgroup_vregion_attach(mlxsw_sp, vgroup, + vregion); if (err) - goto err_group_vregion_attach; + goto err_vgroup_vregion_attach; return 0; -err_group_vregion_attach: +err_vgroup_vregion_attach: mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); return err; } @@ -822,7 +878,7 @@ mlxsw_sp_acl_tcam_vchunk_deassoc(struct mlxsw_sp *mlxsw_sp, list_del(&vchunk->list); if (list_empty(&vregion->vchunk_list)) { - mlxsw_sp_acl_tcam_group_vregion_detach(mlxsw_sp, vregion); + mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion); mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); } } @@ -857,7 +913,7 @@ mlxsw_sp_acl_tcam_chunk_destroy(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_acl_tcam_vchunk * mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, + struct mlxsw_sp_acl_tcam_vgroup *vgroup, unsigned int priority, struct mlxsw_afk_element_usage *elusage) { @@ -872,15 +928,15 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&vchunk->ventry_list); vchunk->priority = priority; - vchunk->group = group; + vchunk->vgroup = vgroup; vchunk->ref_count = 1; - err = mlxsw_sp_acl_tcam_vchunk_assoc(mlxsw_sp, group, priority, + err = mlxsw_sp_acl_tcam_vchunk_assoc(mlxsw_sp, vgroup, priority, elusage, vchunk); if (err) goto err_vchunk_assoc; - err = rhashtable_insert_fast(&group->vchunk_ht, &vchunk->ht_node, + err = rhashtable_insert_fast(&vgroup->vchunk_ht, &vchunk->ht_node, mlxsw_sp_acl_tcam_vchunk_ht_params); if (err) goto err_rhashtable_insert; @@ -895,7 +951,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, return vchunk; err_chunk_create: - rhashtable_remove_fast(&group->vchunk_ht, &vchunk->ht_node, + rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node, mlxsw_sp_acl_tcam_vchunk_ht_params); err_rhashtable_insert: mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk); @@ -908,12 +964,12 @@ static void mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vchunk *vchunk) { - struct mlxsw_sp_acl_tcam_group *group = vchunk->group; + struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup; if (vchunk->chunk2) mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk); - rhashtable_remove_fast(&group->vchunk_ht, &vchunk->ht_node, + rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node, mlxsw_sp_acl_tcam_vchunk_ht_params); mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk); kfree(vchunk); @@ -921,13 +977,13 @@ mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp, static struct mlxsw_sp_acl_tcam_vchunk * mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, + struct mlxsw_sp_acl_tcam_vgroup *vgroup, unsigned int priority, struct mlxsw_afk_element_usage *elusage) { struct mlxsw_sp_acl_tcam_vchunk *vchunk; - vchunk = rhashtable_lookup_fast(&group->vchunk_ht, &priority, + vchunk = rhashtable_lookup_fast(&vgroup->vchunk_ht, &priority, mlxsw_sp_acl_tcam_vchunk_ht_params); if (vchunk) { if (WARN_ON(!mlxsw_afk_key_info_subset(vchunk->vregion->key_info, @@ -936,7 +992,7 @@ mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp, vchunk->ref_count++; return vchunk; } - return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, group, + return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, vgroup, priority, elusage); } @@ -1010,14 +1066,14 @@ mlxsw_sp_acl_tcam_entry_activity_get(struct mlxsw_sp *mlxsw_sp, } static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_group *group, + struct mlxsw_sp_acl_tcam_vgroup *vgroup, struct mlxsw_sp_acl_tcam_ventry *ventry, struct mlxsw_sp_acl_rule_info *rulei) { struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; - vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, group, rulei->priority, + vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, vgroup, rulei->priority, &rulei->values.elusage); if (IS_ERR(vchunk)) return PTR_ERR(vchunk); @@ -1183,7 +1239,9 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, return PTR_ERR(region2); vregion->region2 = region2; - err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, region2); + err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, + vregion->region->group, + region2, vregion->region); if (err) goto err_group_region_attach; @@ -1297,7 +1355,7 @@ static const struct mlxsw_sp_acl_tcam_pattern mlxsw_sp_acl_tcam_patterns[] = { ARRAY_SIZE(mlxsw_sp_acl_tcam_patterns) struct mlxsw_sp_acl_tcam_flower_ruleset { - struct mlxsw_sp_acl_tcam_group group; + struct mlxsw_sp_acl_tcam_vgroup vgroup; }; struct mlxsw_sp_acl_tcam_flower_rule { @@ -1312,10 +1370,10 @@ mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv; - return mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group, - mlxsw_sp_acl_tcam_patterns, - MLXSW_SP_ACL_TCAM_PATTERNS_COUNT, - tmplt_elusage); + return mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup, + mlxsw_sp_acl_tcam_patterns, + MLXSW_SP_ACL_TCAM_PATTERNS_COUNT, + tmplt_elusage); } static void @@ -1324,7 +1382,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_del(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv; - mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group); + mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup); } static int @@ -1335,7 +1393,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_bind(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv; - return mlxsw_sp_acl_tcam_group_bind(mlxsw_sp, &ruleset->group, + return mlxsw_sp_acl_tcam_group_bind(mlxsw_sp, &ruleset->vgroup.group, mlxsw_sp_port, ingress); } @@ -1347,7 +1405,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv; - mlxsw_sp_acl_tcam_group_unbind(mlxsw_sp, &ruleset->group, + mlxsw_sp_acl_tcam_group_unbind(mlxsw_sp, &ruleset->vgroup.group, mlxsw_sp_port, ingress); } @@ -1356,7 +1414,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_group_id(void *ruleset_priv) { struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv; - return mlxsw_sp_acl_tcam_group_id(&ruleset->group); + return mlxsw_sp_acl_tcam_group_id(&ruleset->vgroup.group); } static int @@ -1367,7 +1425,7 @@ mlxsw_sp_acl_tcam_flower_rule_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_flower_ruleset *ruleset = ruleset_priv; struct mlxsw_sp_acl_tcam_flower_rule *rule = rule_priv; - return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->group, + return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->vgroup, &rule->ventry, rulei); } @@ -1413,7 +1471,7 @@ static const struct mlxsw_sp_acl_profile_ops mlxsw_sp_acl_tcam_flower_ops = { struct mlxsw_sp_acl_tcam_mr_ruleset { struct mlxsw_sp_acl_tcam_vchunk *vchunk; - struct mlxsw_sp_acl_tcam_group group; + struct mlxsw_sp_acl_tcam_vgroup vgroup; }; struct mlxsw_sp_acl_tcam_mr_rule { @@ -1429,10 +1487,10 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv; int err; - err = mlxsw_sp_acl_tcam_group_add(mlxsw_sp, tcam, &ruleset->group, - mlxsw_sp_acl_tcam_patterns, - MLXSW_SP_ACL_TCAM_PATTERNS_COUNT, - tmplt_elusage); + err = mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup, + mlxsw_sp_acl_tcam_patterns, + MLXSW_SP_ACL_TCAM_PATTERNS_COUNT, + tmplt_elusage); if (err) return err; @@ -1443,7 +1501,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp, * is initialized. */ ruleset->vchunk = mlxsw_sp_acl_tcam_vchunk_get(mlxsw_sp, - &ruleset->group, 1, + &ruleset->vgroup, 1, tmplt_elusage); if (IS_ERR(ruleset->vchunk)) { err = PTR_ERR(ruleset->vchunk); @@ -1453,7 +1511,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp, return 0; err_chunk_get: - mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group); + mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup); return err; } @@ -1463,7 +1521,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_del(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv) struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv; mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, ruleset->vchunk); - mlxsw_sp_acl_tcam_group_del(mlxsw_sp, &ruleset->group); + mlxsw_sp_acl_tcam_vgroup_del(&ruleset->vgroup); } static int @@ -1488,7 +1546,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_group_id(void *ruleset_priv) { struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv; - return mlxsw_sp_acl_tcam_group_id(&ruleset->group); + return mlxsw_sp_acl_tcam_group_id(&ruleset->vgroup.group); } static int @@ -1499,7 +1557,7 @@ mlxsw_sp_acl_tcam_mr_rule_add(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv, struct mlxsw_sp_acl_tcam_mr_ruleset *ruleset = ruleset_priv; struct mlxsw_sp_acl_tcam_mr_rule *rule = rule_priv; - return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->group, + return mlxsw_sp_acl_tcam_ventry_add(mlxsw_sp, &ruleset->vgroup, &rule->ventry, rulei); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 96bd42a9fbc3..77de76647ede 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -78,6 +78,8 @@ struct mlxsw_sp_acl_tcam_vregion; struct mlxsw_sp_acl_tcam_region { struct mlxsw_sp_acl_tcam_vregion *vregion; + struct mlxsw_sp_acl_tcam_group *group; + struct list_head list; /* Member of a TCAM group */ enum mlxsw_reg_ptar_key_type key_type; u16 id; /* ACL ID and region ID - they are same */ char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN]; -- cgit v1.2.3 From 5ec2ee28d27b9232d1cae08ec597b9f3464fd8be Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:24 +0000 Subject: mlxsw: spectrum_acl: Introduce a mutex to guard region list updates In order to remove RTNL lock dependency, it is needed to protect the regions list in a group. Introduce a mutex to do the job. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 922f17adcee7..21ebda19a2ad 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "reg.h" @@ -161,6 +162,7 @@ struct mlxsw_sp_acl_tcam_pattern { struct mlxsw_sp_acl_tcam_group { struct mlxsw_sp_acl_tcam *tcam; u16 id; + struct mutex lock; /* guards region list updates */ struct list_head region_list; unsigned int region_count; }; @@ -259,6 +261,7 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp_acl_tcam *tcam, int err; group->tcam = tcam; + mutex_init(&group->lock); INIT_LIST_HEAD(&group->region_list); err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id); @@ -272,6 +275,7 @@ static void mlxsw_sp_acl_tcam_group_del(struct mlxsw_sp_acl_tcam_group *group) { struct mlxsw_sp_acl_tcam *tcam = group->tcam; + mutex_destroy(&group->lock); mlxsw_sp_acl_tcam_group_id_put(tcam, group->id); WARN_ON(!list_empty(&group->region_list)); } @@ -390,8 +394,11 @@ mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp, struct list_head *pos; int err; - if (group->region_count == group->tcam->max_group_size) - return -ENOBUFS; + mutex_lock(&group->lock); + if (group->region_count == group->tcam->max_group_size) { + err = -ENOBUFS; + goto err_region_count_check; + } if (next_region) { /* If the next region is defined, place the new one @@ -415,10 +422,13 @@ mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp, goto err_group_update; group->region_count++; + mutex_unlock(&group->lock); return 0; err_group_update: list_del(®ion->list); +err_region_count_check: + mutex_unlock(&group->lock); return err; } @@ -428,9 +438,11 @@ mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_group *group = region->group; + mutex_lock(&group->lock); list_del(®ion->list); group->region_count--; mlxsw_sp_acl_tcam_group_update(mlxsw_sp, group); + mutex_unlock(&group->lock); } static int -- cgit v1.2.3 From 79604b6e17426d64435bc947532a89fa8b0cf6b4 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:25 +0000 Subject: mlxsw: spectrum_acl: Refactor vregion association code Refactor existing _vchunk_assoc/_vchunk_deassoc() functions into _vregion_get()/_vregion_put() to make the code simpler and prepared for vregion locking. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 133 ++++++++++----------- 1 file changed, 66 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 21ebda19a2ad..e100b14b4815 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -188,6 +188,7 @@ struct mlxsw_sp_acl_tcam_vregion { struct delayed_work rehash_dw; struct mlxsw_sp *mlxsw_sp; bool failed_rollback; /* Indicates failed rollback during migration */ + unsigned int ref_count; }; struct mlxsw_sp_acl_tcam_vchunk; @@ -388,6 +389,7 @@ static int mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_group *group, struct mlxsw_sp_acl_tcam_region *region, + unsigned int priority, struct mlxsw_sp_acl_tcam_region *next_region) { struct mlxsw_sp_acl_tcam_region *region2; @@ -410,7 +412,7 @@ mlxsw_sp_acl_tcam_group_region_attach(struct mlxsw_sp *mlxsw_sp, list_for_each(pos, &group->region_list) { region2 = list_entry(pos, typeof(*region2), list); if (mlxsw_sp_acl_tcam_vregion_prio(region2->vregion) > - mlxsw_sp_acl_tcam_vregion_prio(region->vregion)) + priority) break; } } @@ -448,7 +450,8 @@ mlxsw_sp_acl_tcam_group_region_detach(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_vgroup_vregion_attach(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vgroup *vgroup, - struct mlxsw_sp_acl_tcam_vregion *vregion) + struct mlxsw_sp_acl_tcam_vregion *vregion, + unsigned int priority) { struct mlxsw_sp_acl_tcam_vregion *vregion2; struct list_head *pos; @@ -457,15 +460,14 @@ mlxsw_sp_acl_tcam_vgroup_vregion_attach(struct mlxsw_sp *mlxsw_sp, /* Position the vregion inside the list according to priority */ list_for_each(pos, &vgroup->vregion_list) { vregion2 = list_entry(pos, typeof(*vregion2), list); - if (mlxsw_sp_acl_tcam_vregion_prio(vregion2) > - mlxsw_sp_acl_tcam_vregion_prio(vregion)) { + if (mlxsw_sp_acl_tcam_vregion_prio(vregion2) > priority) break; - } } list_add_tail(&vregion->list, pos); err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, &vgroup->group, - vregion->region, NULL); + vregion->region, + priority, NULL); if (err) goto err_region_attach; @@ -731,11 +733,13 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) static struct mlxsw_sp_acl_tcam_vregion * mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam *tcam, + struct mlxsw_sp_acl_tcam_vgroup *vgroup, + unsigned int priority, struct mlxsw_afk_element_usage *elusage) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); + struct mlxsw_sp_acl_tcam *tcam = vgroup->group.tcam; struct mlxsw_sp_acl_tcam_vregion *vregion; int err; @@ -745,6 +749,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, INIT_LIST_HEAD(&vregion->vchunk_list); vregion->tcam = tcam; vregion->mlxsw_sp = mlxsw_sp; + vregion->ref_count = 1; vregion->key_info = mlxsw_afk_key_info_get(afk, elusage); if (IS_ERR(vregion->key_info)) { @@ -759,6 +764,11 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, goto err_region_create; } + err = mlxsw_sp_acl_tcam_vgroup_vregion_attach(mlxsw_sp, vgroup, vregion, + priority); + if (err) + goto err_vgroup_vregion_attach; + list_add_tail(&vregion->tlist, &tcam->vregion_list); if (ops->region_rehash_hints_get) { @@ -770,6 +780,8 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, return vregion; +err_vgroup_vregion_attach: + mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region); err_region_create: mlxsw_afk_key_info_put(vregion->key_info); err_key_info_get: @@ -786,6 +798,7 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, if (ops->region_rehash_hints_get) cancel_delayed_work_sync(&vregion->rehash_dw); list_del(&vregion->tlist); + mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion); if (vregion->region2) mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2); mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region); @@ -828,71 +841,47 @@ int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, return 0; } -static int -mlxsw_sp_acl_tcam_vchunk_assoc(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vgroup *vgroup, - unsigned int priority, - struct mlxsw_afk_element_usage *elusage, - struct mlxsw_sp_acl_tcam_vchunk *vchunk) +static struct mlxsw_sp_acl_tcam_vregion * +mlxsw_sp_acl_tcam_vregion_get(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vgroup *vgroup, + unsigned int priority, + struct mlxsw_afk_element_usage *elusage) { + struct mlxsw_afk_element_usage vregion_elusage; struct mlxsw_sp_acl_tcam_vregion *vregion; - bool vregion_created = false; bool need_split; - int err; vregion = mlxsw_sp_acl_tcam_vgroup_vregion_find(vgroup, priority, elusage, &need_split); - if (vregion && need_split) { - /* According to priority, the vchunk should belong to an - * existing vregion. However, this vchunk needs elements - * that vregion does not contain. We need to split the existing - * vregion into two and create a new vregion for this vchunk - * in between. This is not supported now. - */ - return -EOPNOTSUPP; - } - if (!vregion) { - struct mlxsw_afk_element_usage vregion_elusage; - - mlxsw_sp_acl_tcam_vgroup_use_patterns(vgroup, elusage, - &vregion_elusage); - vregion = mlxsw_sp_acl_tcam_vregion_create(mlxsw_sp, - vgroup->group.tcam, - &vregion_elusage); - if (IS_ERR(vregion)) - return PTR_ERR(vregion); - vregion_created = true; + if (vregion) { + if (need_split) { + /* According to priority, new vchunk should belong to + * an existing vregion. However, this vchunk needs + * elements that vregion does not contain. We need + * to split the existing vregion into two and create + * a new vregion for the new vchunk in between. + * This is not supported now. + */ + return ERR_PTR(-EOPNOTSUPP); + } + vregion->ref_count++; + return vregion; } - vchunk->vregion = vregion; - list_add_tail(&vchunk->list, &vregion->vchunk_list); - - if (!vregion_created) - return 0; + mlxsw_sp_acl_tcam_vgroup_use_patterns(vgroup, elusage, + &vregion_elusage); - err = mlxsw_sp_acl_tcam_vgroup_vregion_attach(mlxsw_sp, vgroup, - vregion); - if (err) - goto err_vgroup_vregion_attach; - - return 0; - -err_vgroup_vregion_attach: - mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); - return err; + return mlxsw_sp_acl_tcam_vregion_create(mlxsw_sp, vgroup, priority, + &vregion_elusage); } static void -mlxsw_sp_acl_tcam_vchunk_deassoc(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vchunk *vchunk) +mlxsw_sp_acl_tcam_vregion_put(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion) { - struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion; - - list_del(&vchunk->list); - if (list_empty(&vregion->vchunk_list)) { - mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion); - mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); - } + if (--vregion->ref_count) + return; + mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion); } static struct mlxsw_sp_acl_tcam_chunk * @@ -929,6 +918,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, unsigned int priority, struct mlxsw_afk_element_usage *elusage) { + struct mlxsw_sp_acl_tcam_vregion *vregion; struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; @@ -943,10 +933,14 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, vchunk->vgroup = vgroup; vchunk->ref_count = 1; - err = mlxsw_sp_acl_tcam_vchunk_assoc(mlxsw_sp, vgroup, priority, - elusage, vchunk); - if (err) - goto err_vchunk_assoc; + vregion = mlxsw_sp_acl_tcam_vregion_get(mlxsw_sp, vgroup, + priority, elusage); + if (IS_ERR(vregion)) { + err = PTR_ERR(vregion); + goto err_vregion_get; + } + + vchunk->vregion = vregion; err = rhashtable_insert_fast(&vgroup->vchunk_ht, &vchunk->ht_node, mlxsw_sp_acl_tcam_vchunk_ht_params); @@ -960,14 +954,16 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, goto err_chunk_create; } + list_add_tail(&vchunk->list, &vregion->vchunk_list); + return vchunk; err_chunk_create: rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node, mlxsw_sp_acl_tcam_vchunk_ht_params); err_rhashtable_insert: - mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk); -err_vchunk_assoc: + mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vregion); +err_vregion_get: kfree(vchunk); return ERR_PTR(err); } @@ -978,12 +974,13 @@ mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup; + list_del(&vchunk->list); if (vchunk->chunk2) mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk); rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node, mlxsw_sp_acl_tcam_vchunk_ht_params); - mlxsw_sp_acl_tcam_vchunk_deassoc(mlxsw_sp, vchunk); + mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vchunk->vregion); kfree(vchunk); } @@ -1240,6 +1237,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, void *hints_priv) { + unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion); struct mlxsw_sp_acl_tcam_region *region2, *unused_region; int err; @@ -1253,7 +1251,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, vregion->region2 = region2; err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, vregion->region->group, - region2, vregion->region); + region2, priority, + vregion->region); if (err) goto err_group_region_attach; -- cgit v1.2.3 From 1263a9ab82249a5af42302a522ea8453affc5fda Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:26 +0000 Subject: mlxsw: spectrum_acl: Introduce vregion mutex In order to remove dependency on RTNL, introduce a mutex to guard vregion structure, list of chunks and list of entries in chunks. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index e100b14b4815..54c0519195b7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -178,6 +178,9 @@ struct mlxsw_sp_acl_tcam_vgroup { }; struct mlxsw_sp_acl_tcam_vregion { + struct mutex lock; /* Protects consistency of region, region2 pointers + * and vchunk_list. + */ struct mlxsw_sp_acl_tcam_region *region; struct mlxsw_sp_acl_tcam_region *region2; /* Used during migration */ struct list_head list; /* Member of a TCAM group */ @@ -747,6 +750,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, if (!vregion) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&vregion->vchunk_list); + mutex_init(&vregion->lock); vregion->tcam = tcam; vregion->mlxsw_sp = mlxsw_sp; vregion->ref_count = 1; @@ -803,6 +807,7 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2); mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region); mlxsw_afk_key_info_put(vregion->key_info); + mutex_destroy(&vregion->lock); kfree(vregion); } @@ -947,14 +952,17 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, if (err) goto err_rhashtable_insert; + mutex_lock(&vregion->lock); vchunk->chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, vchunk->vregion->region); if (IS_ERR(vchunk->chunk)) { + mutex_unlock(&vregion->lock); err = PTR_ERR(vchunk->chunk); goto err_chunk_create; } list_add_tail(&vchunk->list, &vregion->vchunk_list); + mutex_unlock(&vregion->lock); return vchunk; @@ -972,12 +980,15 @@ static void mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vchunk *vchunk) { + struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion; struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup; + mutex_lock(&vregion->lock); list_del(&vchunk->list); if (vchunk->chunk2) mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk); + mutex_unlock(&vregion->lock); rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node, mlxsw_sp_acl_tcam_vchunk_ht_params); mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vchunk->vregion); @@ -1079,6 +1090,7 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_ventry *ventry, struct mlxsw_sp_acl_rule_info *rulei) { + struct mlxsw_sp_acl_tcam_vregion *vregion; struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; @@ -1089,14 +1101,19 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp, ventry->vchunk = vchunk; ventry->rulei = rulei; + vregion = vchunk->vregion; + + mutex_lock(&vregion->lock); ventry->entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, vchunk->chunk); if (IS_ERR(ventry->entry)) { + mutex_unlock(&vregion->lock); err = PTR_ERR(ventry->entry); goto err_entry_create; } list_add_tail(&ventry->list, &vchunk->ventry_list); + mutex_unlock(&vregion->lock); return 0; @@ -1109,9 +1126,12 @@ static void mlxsw_sp_acl_tcam_ventry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_ventry *ventry) { struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk; + struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion; + mutex_lock(&vregion->lock); list_del(&ventry->list); mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry); + mutex_unlock(&vregion->lock); mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk); } @@ -1256,6 +1276,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, if (err) goto err_group_region_attach; + mutex_lock(&vregion->lock); + err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion); if (!vregion->failed_rollback) { if (!err) { @@ -1270,10 +1292,14 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, */ unused_region = vregion->region2; } + mutex_unlock(&vregion->lock); vregion->region2 = NULL; mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, unused_region); mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, unused_region); + } else { + mutex_unlock(&vregion->lock); } + return err; err_group_region_attach: -- cgit v1.2.3 From 65e190356098f2bd6adbdee06047a941ca1d20e1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:27 +0000 Subject: mlxsw: spectrum_acl: Introduce mutex to guard Bloom Filter updates Bloom filter is shared within multiple regions. For updates, it needs to be guarded by a separate mutex. Do that in order to not rely on RTNL mutex. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../mellanox/mlxsw/spectrum_acl_bloom_filter.c | 34 +++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c index 9545b572747e..3a2de13fcb68 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_bloom_filter.c @@ -5,11 +5,13 @@ #include #include #include +#include #include "spectrum.h" #include "spectrum_acl_tcam.h" struct mlxsw_sp_acl_bf { + struct mutex lock; /* Protects Bloom Filter updates. */ unsigned int bank_size; refcount_t refcnt[0]; }; @@ -172,26 +174,36 @@ mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp, u16 bf_index; int err; + mutex_lock(&bf->lock); + bf_index = mlxsw_sp_acl_bf_index_get(bf, aregion, aentry); rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank, bf_index); - if (refcount_inc_not_zero(&bf->refcnt[rule_index])) - return 0; + if (refcount_inc_not_zero(&bf->refcnt[rule_index])) { + err = 0; + goto unlock; + } peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL); - if (!peabfe_pl) - return -ENOMEM; + if (!peabfe_pl) { + err = -ENOMEM; + goto unlock; + } mlxsw_reg_peabfe_pack(peabfe_pl); mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 1, erp_bank, bf_index); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl); kfree(peabfe_pl); if (err) - return err; + goto unlock; refcount_set(&bf->refcnt[rule_index], 1); - return 0; + err = 0; + +unlock: + mutex_unlock(&bf->lock); + return err; } void @@ -205,6 +217,8 @@ mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp, char *peabfe_pl; u16 bf_index; + mutex_lock(&bf->lock); + bf_index = mlxsw_sp_acl_bf_index_get(bf, aregion, aentry); rule_index = mlxsw_sp_acl_bf_rule_count_index_get(bf, erp_bank, bf_index); @@ -212,13 +226,16 @@ mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp, if (refcount_dec_and_test(&bf->refcnt[rule_index])) { peabfe_pl = kmalloc(MLXSW_REG_PEABFE_LEN, GFP_KERNEL); if (!peabfe_pl) - return; + goto unlock; mlxsw_reg_peabfe_pack(peabfe_pl); mlxsw_reg_peabfe_rec_pack(peabfe_pl, 0, 0, erp_bank, bf_index); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(peabfe), peabfe_pl); kfree(peabfe_pl); } + +unlock: + mutex_unlock(&bf->lock); } struct mlxsw_sp_acl_bf * @@ -240,10 +257,13 @@ mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks) return ERR_PTR(-ENOMEM); bf->bank_size = bf_bank_size; + mutex_init(&bf->lock); + return bf; } void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf) { + mutex_destroy(&bf->lock); kfree(bf); } -- cgit v1.2.3 From 6b861682474ca0dd78bcaebbd3f471c8244689de Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:28 +0000 Subject: mlxsw: spectrum_acl: Enable vregion rehash per-profile For MR ACL profile is does not make sense to do periodical rehashes, as there is only one mask in use during the whole vregion lifetime. Therefore periodical work is scheduled but the rehash never happens. So allow to enable/disable rehash for the whole group, which is added per-profile. Disable rehashing for MR profile. Addition to the vregion list is done only in case the rehash is enable on the particular vregion. Also, the addition is moved after delayed work init to avoid schedule of uninitialized work from vregion_rehash_intrvl_set(). Symmetrically, deletion from the list is done before canceling the delayed work so it is not scheduled by vregion_rehash_intrvl_set() again. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 54c0519195b7..cdbcf612b6fd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -175,6 +175,7 @@ struct mlxsw_sp_acl_tcam_vgroup { unsigned int patterns_count; bool tmplt_elusage_set; struct mlxsw_afk_element_usage tmplt_elusage; + bool vregion_rehash_enabled; }; struct mlxsw_sp_acl_tcam_vregion { @@ -188,6 +189,7 @@ struct mlxsw_sp_acl_tcam_vregion { struct list_head vchunk_list; /* List of vchunks under this vregion */ struct mlxsw_afk_key_info *key_info; struct mlxsw_sp_acl_tcam *tcam; + struct mlxsw_sp_acl_tcam_vgroup *vgroup; struct delayed_work rehash_dw; struct mlxsw_sp *mlxsw_sp; bool failed_rollback; /* Indicates failed rollback during migration */ @@ -290,12 +292,15 @@ mlxsw_sp_acl_tcam_vgroup_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vgroup *vgroup, const struct mlxsw_sp_acl_tcam_pattern *patterns, unsigned int patterns_count, - struct mlxsw_afk_element_usage *tmplt_elusage) + struct mlxsw_afk_element_usage *tmplt_elusage, + bool vregion_rehash_enabled) { int err; vgroup->patterns = patterns; vgroup->patterns_count = patterns_count; + vgroup->vregion_rehash_enabled = vregion_rehash_enabled; + if (tmplt_elusage) { vgroup->tmplt_elusage_set = true; memcpy(&vgroup->tmplt_elusage, tmplt_elusage, @@ -753,6 +758,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, mutex_init(&vregion->lock); vregion->tcam = tcam; vregion->mlxsw_sp = mlxsw_sp; + vregion->vgroup = vgroup; vregion->ref_count = 1; vregion->key_info = mlxsw_afk_key_info_get(afk, elusage); @@ -773,13 +779,12 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, if (err) goto err_vgroup_vregion_attach; - list_add_tail(&vregion->tlist, &tcam->vregion_list); - - if (ops->region_rehash_hints_get) { + if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) { /* Create the delayed work for vregion periodic rehash */ INIT_DELAYED_WORK(&vregion->rehash_dw, mlxsw_sp_acl_tcam_vregion_rehash_work); mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); + list_add_tail(&vregion->tlist, &tcam->vregion_list); } return vregion; @@ -798,10 +803,12 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + struct mlxsw_sp_acl_tcam_vgroup *vgroup = vregion->vgroup; - if (ops->region_rehash_hints_get) + if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) { + list_del(&vregion->tlist); cancel_delayed_work_sync(&vregion->rehash_dw); - list_del(&vregion->tlist); + } mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion); if (vregion->region2) mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2); @@ -1410,7 +1417,7 @@ mlxsw_sp_acl_tcam_flower_ruleset_add(struct mlxsw_sp *mlxsw_sp, return mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup, mlxsw_sp_acl_tcam_patterns, MLXSW_SP_ACL_TCAM_PATTERNS_COUNT, - tmplt_elusage); + tmplt_elusage, true); } static void @@ -1527,7 +1534,7 @@ mlxsw_sp_acl_tcam_mr_ruleset_add(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_acl_tcam_vgroup_add(mlxsw_sp, tcam, &ruleset->vgroup, mlxsw_sp_acl_tcam_patterns, MLXSW_SP_ACL_TCAM_PATTERNS_COUNT, - tmplt_elusage); + tmplt_elusage, false); if (err) return err; -- cgit v1.2.3 From ddaa2875da02070029cee2ae19371a4b21ddd137 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:28 +0000 Subject: mlxsw: spectrum_acl: Introduce a mutex to guard objagg instance manipulation Protect objagg structures by adding a mutex to ERP code and take it during the structure manipulation. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index e935c36638d9..d6961dd0c556 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,7 @@ struct mlxsw_sp_acl_erp_table { unsigned int num_ctcam_erps; unsigned int num_deltas; struct objagg *objagg; + struct mutex objagg_lock; /* guards objagg manipulation */ }; struct mlxsw_sp_acl_erp_table_ops { @@ -1001,6 +1003,7 @@ struct mlxsw_sp_acl_erp_mask * mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion, const char *mask, bool ctcam) { + struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table; struct mlxsw_sp_acl_erp_key key; struct objagg_obj *objagg_obj; @@ -1011,7 +1014,9 @@ mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion, memcpy(key.mask, mask, MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN); key.ctcam = ctcam; - objagg_obj = objagg_obj_get(aregion->erp_table->objagg, &key); + mutex_lock(&erp_table->objagg_lock); + objagg_obj = objagg_obj_get(erp_table->objagg, &key); + mutex_unlock(&erp_table->objagg_lock); if (IS_ERR(objagg_obj)) return ERR_CAST(objagg_obj); return (struct mlxsw_sp_acl_erp_mask *) objagg_obj; @@ -1021,8 +1026,11 @@ void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_erp_mask *erp_mask) { struct objagg_obj *objagg_obj = (struct objagg_obj *) erp_mask; + struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table; - objagg_obj_put(aregion->erp_table->objagg, objagg_obj); + mutex_lock(&erp_table->objagg_lock); + objagg_obj_put(erp_table->objagg, objagg_obj); + mutex_unlock(&erp_table->objagg_lock); } int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp, @@ -1334,6 +1342,7 @@ mlxsw_sp_acl_erp_table_create(struct mlxsw_sp_acl_atcam_region *aregion, erp_table->ops = &erp_no_mask_ops; INIT_LIST_HEAD(&erp_table->atcam_erps_list); erp_table->aregion = aregion; + mutex_init(&erp_table->objagg_lock); return erp_table; @@ -1346,6 +1355,7 @@ static void mlxsw_sp_acl_erp_table_destroy(struct mlxsw_sp_acl_erp_table *erp_table) { WARN_ON(!list_empty(&erp_table->atcam_erps_list)); + mutex_destroy(&erp_table->objagg_lock); objagg_destroy(erp_table->objagg); kfree(erp_table); } @@ -1376,14 +1386,16 @@ mlxsw_sp_acl_erp_hints_check(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_atcam_region *aregion, struct objagg_hints *hints, bool *p_rehash_needed) { - struct objagg *objagg = aregion->erp_table->objagg; + struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table; const struct objagg_stats *ostats; const struct objagg_stats *hstats; int err; *p_rehash_needed = false; - ostats = objagg_stats_get(objagg); + mutex_lock(&erp_table->objagg_lock); + ostats = objagg_stats_get(erp_table->objagg); + mutex_unlock(&erp_table->objagg_lock); if (IS_ERR(ostats)) { dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get ERP stats\n"); return PTR_ERR(ostats); @@ -1411,13 +1423,16 @@ err_hints_stats_get: void * mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion) { + struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table; struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp; struct objagg_hints *hints; bool rehash_needed; int err; - hints = objagg_hints_get(aregion->erp_table->objagg, + mutex_lock(&erp_table->objagg_lock); + hints = objagg_hints_get(erp_table->objagg, OBJAGG_OPT_ALGO_SIMPLE_GREEDY); + mutex_unlock(&erp_table->objagg_lock); if (IS_ERR(hints)) { dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to create ERP hints\n"); return ERR_CAST(hints); -- cgit v1.2.3 From 7b0f62eefc7f04a6fd3bddc88cf39c7a60f28672 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:29 +0000 Subject: mlxsw: spectrum_acl: Don't take rtnl lock during vregion_rehash_intrvl_set() Relax dependency on rtnl mutex during vregion_rehash_intrvl_set(). The vregion list is protected with newly introduced mutex. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 11 +++++++++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index cdbcf612b6fd..5c8976e471ad 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -38,6 +38,7 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, size_t alloc_size; int err; + mutex_init(&tcam->lock); tcam->vregion_rehash_intrvl = MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT; INIT_LIST_HEAD(&tcam->vregion_list); @@ -85,6 +86,7 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + mutex_destroy(&tcam->lock); ops->fini(mlxsw_sp, tcam->priv); kfree(tcam->used_groups); kfree(tcam->used_regions); @@ -784,7 +786,9 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, INIT_DELAYED_WORK(&vregion->rehash_dw, mlxsw_sp_acl_tcam_vregion_rehash_work); mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); + mutex_lock(&tcam->lock); list_add_tail(&vregion->tlist, &tcam->vregion_list); + mutex_unlock(&tcam->lock); } return vregion; @@ -804,9 +808,12 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; struct mlxsw_sp_acl_tcam_vgroup *vgroup = vregion->vgroup; + struct mlxsw_sp_acl_tcam *tcam = vregion->tcam; if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) { + mutex_lock(&tcam->lock); list_del(&vregion->tlist); + mutex_unlock(&tcam->lock); cancel_delayed_work_sync(&vregion->rehash_dw); } mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion); @@ -842,14 +849,14 @@ int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, if (WARN_ON(!ops->region_rehash_hints_get)) return -EOPNOTSUPP; tcam->vregion_rehash_intrvl = val; - rtnl_lock(); + mutex_lock(&tcam->lock); list_for_each_entry(vregion, &tcam->vregion_list, tlist) { if (val) mlxsw_core_schedule_dw(&vregion->rehash_dw, 0); else cancel_delayed_work_sync(&vregion->rehash_dw); } - rtnl_unlock(); + mutex_unlock(&tcam->lock); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 77de76647ede..5965913565a5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -17,6 +17,7 @@ struct mlxsw_sp_acl_tcam { unsigned long *used_groups; /* bit array */ unsigned int max_groups; unsigned int max_group_size; + struct mutex lock; /* guards vregion list */ struct list_head vregion_list; u32 vregion_rehash_intrvl; /* ms */ unsigned long priv[0]; -- cgit v1.2.3 From c70b13275b8a826e561f4ac6a6940a044e65a809 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:30 +0000 Subject: mlxsw: spectrum_acl: Remove RTNL lock assertions from ERP code No longer require RTNL lock in this code. Newly introduced mutexes take care of guarding objagg and bloom filter. There is no need to guard gen_pool_alloc()/gen_pool_free() as they are fine to be called lockless. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c index d6961dd0c556..c1a9cc9a3292 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c @@ -1007,11 +1007,6 @@ mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_erp_key key; struct objagg_obj *objagg_obj; - /* eRPs are allocated from a shared resource, but currently all - * allocations are done under RTNL. - */ - ASSERT_RTNL(); - memcpy(key.mask, mask, MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN); key.ctcam = ctcam; mutex_lock(&erp_table->objagg_lock); @@ -1042,7 +1037,6 @@ int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_acl_erp *erp = objagg_obj_root_priv(objagg_obj); unsigned int erp_bank; - ASSERT_RTNL(); if (!mlxsw_sp_acl_erp_table_is_used(erp->erp_table)) return 0; -- cgit v1.2.3 From 2bffc5322fd8679e879cd6370881ee50cf141ada Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:31 +0000 Subject: mlxsw: spectrum_acl: Don't take mutex in mlxsw_sp_acl_tcam_vregion_rehash_work() Other mutexes are taking care of proper locking for this, no longer needed to take RTNL mutex here. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 5c8976e471ad..822766f81236 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -732,12 +732,7 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) container_of(work, struct mlxsw_sp_acl_tcam_vregion, rehash_dw.work); - /* TODO: Take rtnl lock here as the rest of the code counts on it - * now. Later, this should be replaced by per-vregion lock. - */ - rtnl_lock(); mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion); - rtnl_unlock(); mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); } -- cgit v1.2.3 From 6375da3dc07f7c9a3f006646e4a03c6ded7b163e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 24 Feb 2019 06:46:33 +0000 Subject: mlxsw: spectrum_acl: Add vregion migration end tracepoint Hit the new tracepoint once the vregion migration ends. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 11 ++++++++--- include/trace/events/mlxsw.h | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 822766f81236..c9d9cded1724 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1274,8 +1274,10 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam, vregion, hints_priv); - if (IS_ERR(region2)) - return PTR_ERR(region2); + if (IS_ERR(region2)) { + err = PTR_ERR(region2); + goto out; + } vregion->region2 = region2; err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, @@ -1309,11 +1311,14 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, mutex_unlock(&vregion->lock); } - return err; + goto out; err_group_region_attach: vregion->region2 = NULL; mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2); +out: + trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion); + return err; } diff --git a/include/trace/events/mlxsw.h b/include/trace/events/mlxsw.h index a5ce6df9dc49..6a4cfaef33a2 100644 --- a/include/trace/events/mlxsw.h +++ b/include/trace/events/mlxsw.h @@ -73,6 +73,26 @@ TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_migrate, __entry->mlxsw_sp, __entry->vregion) ); +TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_migrate_end, + TP_PROTO(const struct mlxsw_sp *mlxsw_sp, + const struct mlxsw_sp_acl_tcam_vregion *vregion), + + TP_ARGS(mlxsw_sp, vregion), + + TP_STRUCT__entry( + __field(const void *, mlxsw_sp) + __field(const void *, vregion) + ), + + TP_fast_assign( + __entry->mlxsw_sp = mlxsw_sp; + __entry->vregion = vregion; + ), + + TP_printk("mlxsw_sp %p, vregion %p", + __entry->mlxsw_sp, __entry->vregion) +); + TRACE_EVENT(mlxsw_sp_acl_tcam_vregion_rehash_dis, TP_PROTO(const struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_acl_tcam_vregion *vregion), -- cgit v1.2.3 From 2a73ac3e6c9d7cd80af731bcb699c180d95c8166 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sat, 23 Feb 2019 17:22:08 +0800 Subject: net: hns3: add xps setting support for hns3 driver This patch adds xps setting support for hns3 driver based on the interrupt affinity info. Signed-off-by: Yunsheng Lin Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 40b17223ee41..d75977c5d4a3 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -378,6 +378,29 @@ out_start_err: return ret; } +static void hns3_config_xps(struct hns3_nic_priv *priv) +{ + int i; + + for (i = 0; i < priv->vector_num; i++) { + struct hns3_enet_tqp_vector *tqp_vector = &priv->tqp_vector[i]; + struct hns3_enet_ring *ring = tqp_vector->tx_group.ring; + + while (ring) { + int ret; + + ret = netif_set_xps_queue(priv->netdev, + &tqp_vector->affinity_mask, + ring->tqp->tqp_index); + if (ret) + netdev_warn(priv->netdev, + "set xps queue failed: %d", ret); + + ring = ring->next; + } + } +} + static int hns3_nic_net_open(struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); @@ -410,6 +433,7 @@ static int hns3_nic_net_open(struct net_device *netdev) if (h->ae_algo->ops->set_timer_task) h->ae_algo->ops->set_timer_task(priv->ae_handle, true); + hns3_config_xps(priv); return 0; } -- cgit v1.2.3 From 3fe13ed95dd3c4aede3313a2dd2d589c207b51d0 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sat, 23 Feb 2019 17:22:09 +0800 Subject: net: hns3: avoid mult + div op in critical data path This patch uses shift offset to avoid doing mult and div operation. Signed-off-by: Yunsheng Lin Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 15 ++++++++------- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 3 +++ 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index d75977c5d4a3..14c3aa74c92b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -658,7 +658,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen, /* normal or tunnel packet*/ l4_offset = l4.hdr - skb->data; - hdr_len = (l4.tcp->doff * 4) + l4_offset; + hdr_len = (l4.tcp->doff << 2) + l4_offset; /* remove payload length from inner pseudo checksum when tso*/ l4_paylen = skb->len - l4_offset; @@ -1100,8 +1100,8 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, desc_cb->length = size; - frag_buf_num = (size + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; - sizeoflast = size % HNS3_MAX_BD_SIZE; + frag_buf_num = (size + HNS3_MAX_BD_SIZE - 1) >> HNS3_MAX_BD_SIZE_OFFSET; + sizeoflast = size & HNS3_TX_LAST_SIZE_M; sizeoflast = sizeoflast ? sizeoflast : HNS3_MAX_BD_SIZE; /* When frag size is bigger than hardware limit, split this frag */ @@ -1145,14 +1145,14 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, int i; size = skb_headlen(skb); - buf_num = (size + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; + buf_num = (size + HNS3_MAX_BD_SIZE - 1) >> HNS3_MAX_BD_SIZE_OFFSET; frag_num = skb_shinfo(skb)->nr_frags; for (i = 0; i < frag_num; i++) { frag = &skb_shinfo(skb)->frags[i]; size = skb_frag_size(frag); - bdnum_for_frag = - (size + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; + bdnum_for_frag = (size + HNS3_MAX_BD_SIZE - 1) >> + HNS3_MAX_BD_SIZE_OFFSET; if (bdnum_for_frag > HNS3_MAX_BD_PER_FRAG) return -ENOMEM; @@ -1160,7 +1160,8 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, } if (unlikely(buf_num > HNS3_MAX_BD_PER_FRAG)) { - buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) / HNS3_MAX_BD_SIZE; + buf_num = (skb->len + HNS3_MAX_BD_SIZE - 1) >> + HNS3_MAX_BD_SIZE_OFFSET; if (ring_space(ring) < buf_num) return -EBUSY; /* manual split the send packet */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 71ff8f4d6c18..5c414653d0b6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -184,6 +184,8 @@ enum hns3_nic_state { #define HNS3_TXD_MSS_S 0 #define HNS3_TXD_MSS_M (0x3fff << HNS3_TXD_MSS_S) +#define HNS3_TX_LAST_SIZE_M 0xffff + #define HNS3_VECTOR_TX_IRQ BIT_ULL(0) #define HNS3_VECTOR_RX_IRQ BIT_ULL(1) @@ -191,6 +193,7 @@ enum hns3_nic_state { #define HNS3_VECTOR_INITED 1 #define HNS3_MAX_BD_SIZE 65535 +#define HNS3_MAX_BD_SIZE_OFFSET 16 #define HNS3_MAX_BD_PER_FRAG 8 #define HNS3_MAX_BD_PER_PKT MAX_SKB_FRAGS -- cgit v1.2.3 From 47e7b13b0aff869465585d36a8d5075fe17cb90a Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sat, 23 Feb 2019 17:22:10 +0800 Subject: net: hns3: limit some variable scope in critical data path This patch limits some variables' scope as much as possible in hns3_fill_desc. Also, only set l3_type and l4_type when necessary. Signed-off-by: Yunsheng Lin Signed-off-by: Huazhong tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 35 +++++++++++-------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 14c3aa74c92b..a84060fd0464 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1029,26 +1029,21 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; struct hns3_desc *desc = &ring->desc[ring->next_to_use]; struct device *dev = ring_to_dev(ring); - u32 ol_type_vlan_len_msec = 0; u16 bdtp_fe_sc_vld_ra_ri = 0; struct skb_frag_struct *frag; unsigned int frag_buf_num; - u32 type_cs_vlan_tso = 0; - struct sk_buff *skb; - u16 inner_vtag = 0; - u16 out_vtag = 0; - unsigned int k; - int sizeoflast; - u32 paylen = 0; + int k, sizeoflast; dma_addr_t dma; - u16 mss = 0; - u8 ol4_proto; - u8 il4_proto; - int ret; if (type == DESC_TYPE_SKB) { - skb = (struct sk_buff *)priv; - paylen = skb->len; + struct sk_buff *skb = (struct sk_buff *)priv; + u32 ol_type_vlan_len_msec = 0; + u32 type_cs_vlan_tso = 0; + u32 paylen = skb->len; + u16 inner_vtag = 0; + u16 out_vtag = 0; + u16 mss = 0; + int ret; ret = hns3_fill_desc_vtags(skb, ring, &type_cs_vlan_tso, &ol_type_vlan_len_msec, @@ -1057,6 +1052,8 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, return ret; if (skb->ip_summed == CHECKSUM_PARTIAL) { + u8 ol4_proto, il4_proto; + skb_reset_mac_len(skb); ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto); @@ -2353,11 +2350,6 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, return; } - l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M, - HNS3_RXD_L3ID_S); - l4_type = hnae3_get_field(l234info, HNS3_RXD_L4ID_M, - HNS3_RXD_L4ID_S); - ol4_type = hnae3_get_field(l234info, HNS3_RXD_OL4ID_M, HNS3_RXD_OL4ID_S); switch (ol4_type) { @@ -2366,6 +2358,11 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, skb->csum_level = 1; /* fall through */ case HNS3_OL4_TYPE_NO_TUN: + l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M, + HNS3_RXD_L3ID_S); + l4_type = hnae3_get_field(l234info, HNS3_RXD_L4ID_M, + HNS3_RXD_L4ID_S); + /* Can checksum ipv4 or ipv6 + UDP/TCP/SCTP packets */ if ((l3_type == HNS3_L3_TYPE_IPV4 || l3_type == HNS3_L3_TYPE_IPV6) && -- cgit v1.2.3 From d40fa7eeab55dc1f0ab5f81d1c53af31dbcdd9ac Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sat, 23 Feb 2019 17:22:11 +0800 Subject: net: hns3: remove some ops in struct hns3_nic_ops The fill_desc ops has only one implementation, and get_rxd_bnum has not been used, so this patch removes them. Signed-off-by: Yunsheng Lin Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 11 +++++------ drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 3 --- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a84060fd0464..33ac732a9e28 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1279,8 +1279,8 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) next_to_use_head = ring->next_to_use; - ret = priv->ops.fill_desc(ring, skb, size, seg_num == 1 ? 1 : 0, - DESC_TYPE_SKB); + ret = hns3_fill_desc(ring, skb, size, seg_num == 1 ? 1 : 0, + DESC_TYPE_SKB); if (ret) goto head_fill_err; @@ -1290,9 +1290,9 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) frag = &skb_shinfo(skb)->frags[i - 1]; size = skb_frag_size(frag); - ret = priv->ops.fill_desc(ring, frag, size, - seg_num - 1 == i ? 1 : 0, - DESC_TYPE_PAGE); + ret = hns3_fill_desc(ring, frag, size, + seg_num - 1 == i ? 1 : 0, + DESC_TYPE_PAGE); if (ret) goto frag_fill_err; @@ -3579,7 +3579,6 @@ static void hns3_nic_set_priv_ops(struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); - priv->ops.fill_desc = hns3_fill_desc; if ((netdev->features & NETIF_F_TSO) || (netdev->features & NETIF_F_TSO6)) priv->ops.maybe_stop_tx = hns3_nic_maybe_stop_tso; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 5c414653d0b6..3a1e4879b2f8 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -444,11 +444,8 @@ struct hns3_nic_ring_data { }; struct hns3_nic_ops { - int (*fill_desc)(struct hns3_enet_ring *ring, void *priv, - int size, int frag_end, enum hns_desc_type type); int (*maybe_stop_tx)(struct sk_buff **out_skb, int *bnum, struct hns3_enet_ring *ring); - void (*get_rxd_bnum)(u32 bnum_flag, int *out_bnum); }; enum hns3_flow_level_range { -- cgit v1.2.3 From 0cccebac710a2ac1ee9a18744e9ee24746f7d947 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sat, 23 Feb 2019 17:22:12 +0800 Subject: net: hns3: add unlikely for error handling in data path This patch adds unlikely hint for error handling in critical data path. Signed-off-by: Yunsheng Lin Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 33ac732a9e28..50bfdba1f5d9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -619,7 +619,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen, return 0; ret = skb_cow_head(skb, 0); - if (ret) + if (unlikely(ret)) return ret; l3.hdr = skb_network_header(skb); @@ -1012,7 +1012,7 @@ static int hns3_fill_desc_vtags(struct sk_buff *skb, int rc; rc = skb_cow_head(skb, 0); - if (rc < 0) + if (unlikely(rc < 0)) return rc; vhdr = (struct vlan_ethhdr *)skb->data; vhdr->h_vlan_TCI |= cpu_to_be16((skb->priority & 0x7) @@ -1057,7 +1057,7 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, skb_reset_mac_len(skb); ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto); - if (ret) + if (unlikely(ret)) return ret; hns3_set_l2l3l4_len(skb, ol4_proto, il4_proto, &type_cs_vlan_tso, @@ -1065,12 +1065,12 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, ret = hns3_set_l3l4_type_csum(skb, ol4_proto, il4_proto, &type_cs_vlan_tso, &ol_type_vlan_len_msec); - if (ret) + if (unlikely(ret)) return ret; ret = hns3_set_tso(skb, &paylen, &mss, &type_cs_vlan_tso); - if (ret) + if (unlikely(ret)) return ret; } @@ -1090,7 +1090,7 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE); } - if (dma_mapping_error(ring->dev, dma)) { + if (unlikely(dma_mapping_error(ring->dev, dma))) { ring->stats.sw_err_cnt++; return -ENOMEM; } @@ -1150,7 +1150,7 @@ static int hns3_nic_maybe_stop_tso(struct sk_buff **out_skb, int *bnum, size = skb_frag_size(frag); bdnum_for_frag = (size + HNS3_MAX_BD_SIZE - 1) >> HNS3_MAX_BD_SIZE_OFFSET; - if (bdnum_for_frag > HNS3_MAX_BD_PER_FRAG) + if (unlikely(bdnum_for_frag > HNS3_MAX_BD_PER_FRAG)) return -ENOMEM; buf_num += bdnum_for_frag; @@ -1281,7 +1281,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) ret = hns3_fill_desc(ring, skb, size, seg_num == 1 ? 1 : 0, DESC_TYPE_SKB); - if (ret) + if (unlikely(ret)) goto head_fill_err; next_to_use_frag = ring->next_to_use; @@ -1294,7 +1294,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev) seg_num - 1 == i ? 1 : 0, DESC_TYPE_PAGE); - if (ret) + if (unlikely(ret)) goto frag_fill_err; } -- cgit v1.2.3 From cde4ffada8290c803e5b68423466118e5421c774 Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sat, 23 Feb 2019 17:22:13 +0800 Subject: net: hns3: replace hnae3_set_bit and hnae3_set_field in data path hnae3_set_bit and hnae3_set_field masks the data before setting the field or bit, which is unnecessary because the data is already zero initialized. Suggested-by: John Garry Signed-off-by: Yunsheng Lin Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 120 ++++++++++-------------- 1 file changed, 51 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 50bfdba1f5d9..ce9878bfaa1a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -21,6 +21,8 @@ #include "hnae3.h" #include "hns3_enet.h" +#define hns3_set_field(origin, shift, val) ((origin) |= ((val) << (shift))) + static void hns3_clear_all_ring(struct hnae3_handle *h); static void hns3_force_clear_all_rx_ring(struct hnae3_handle *h); static void hns3_remove_hw_addr(struct net_device *netdev); @@ -667,8 +669,7 @@ static int hns3_set_tso(struct sk_buff *skb, u32 *paylen, /* find the txbd field values */ *paylen = skb->len - hdr_len; - hnae3_set_bit(*type_cs_vlan_tso, - HNS3_TXD_TSO_B, 1); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_TSO_B, 1); /* get MSS for TSO */ *mss = skb_shinfo(skb)->gso_size; @@ -747,21 +748,19 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto, /* compute L2 header size for normal packet, defined in 2 Bytes */ l2_len = l3.hdr - skb->data; - hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_M, - HNS3_TXD_L2LEN_S, l2_len >> 1); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_S, l2_len >> 1); /* tunnel packet*/ if (skb->encapsulation) { /* compute OL2 header size, defined in 2 Bytes */ ol2_len = l2_len; - hnae3_set_field(*ol_type_vlan_len_msec, - HNS3_TXD_L2LEN_M, - HNS3_TXD_L2LEN_S, ol2_len >> 1); + hns3_set_field(*ol_type_vlan_len_msec, + HNS3_TXD_L2LEN_S, ol2_len >> 1); /* compute OL3 header size, defined in 4 Bytes */ ol3_len = l4.hdr - l3.hdr; - hnae3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L3LEN_M, - HNS3_TXD_L3LEN_S, ol3_len >> 2); + hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_L3LEN_S, + ol3_len >> 2); /* MAC in UDP, MAC in GRE (0x6558)*/ if ((ol4_proto == IPPROTO_UDP) || (ol4_proto == IPPROTO_GRE)) { @@ -770,17 +769,16 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto, /* compute OL4 header size, defined in 4 Bytes. */ ol4_len = l2_hdr - l4.hdr; - hnae3_set_field(*ol_type_vlan_len_msec, - HNS3_TXD_L4LEN_M, HNS3_TXD_L4LEN_S, - ol4_len >> 2); + hns3_set_field(*ol_type_vlan_len_msec, + HNS3_TXD_L4LEN_S, ol4_len >> 2); /* switch IP header ptr from outer to inner header */ l3.hdr = skb_inner_network_header(skb); /* compute inner l2 header size, defined in 2 Bytes. */ l2_len = l3.hdr - l2_hdr; - hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_M, - HNS3_TXD_L2LEN_S, l2_len >> 1); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L2LEN_S, + l2_len >> 1); } else { /* skb packet types not supported by hardware, * txbd len fild doesn't be filled. @@ -796,24 +794,21 @@ static void hns3_set_l2l3l4_len(struct sk_buff *skb, u8 ol4_proto, /* compute inner(/normal) L3 header size, defined in 4 Bytes */ l3_len = l4.hdr - l3.hdr; - hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3LEN_M, - HNS3_TXD_L3LEN_S, l3_len >> 2); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3LEN_S, l3_len >> 2); /* compute inner(/normal) L4 header size, defined in 4 Bytes */ switch (l4_proto) { case IPPROTO_TCP: - hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_M, - HNS3_TXD_L4LEN_S, l4.tcp->doff); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S, + l4.tcp->doff); break; case IPPROTO_SCTP: - hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_M, - HNS3_TXD_L4LEN_S, - (sizeof(struct sctphdr) >> 2)); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S, + (sizeof(struct sctphdr) >> 2)); break; case IPPROTO_UDP: - hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_M, - HNS3_TXD_L4LEN_S, - (sizeof(struct udphdr) >> 2)); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4LEN_S, + (sizeof(struct udphdr) >> 2)); break; default: /* skb packet types not supported by hardware, @@ -858,34 +853,30 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto, /* define outer network header type.*/ if (skb->protocol == htons(ETH_P_IP)) { if (skb_is_gso(skb)) - hnae3_set_field(*ol_type_vlan_len_msec, - HNS3_TXD_OL3T_M, - HNS3_TXD_OL3T_S, - HNS3_OL3T_IPV4_CSUM); + hns3_set_field(*ol_type_vlan_len_msec, + HNS3_TXD_OL3T_S, + HNS3_OL3T_IPV4_CSUM); else - hnae3_set_field(*ol_type_vlan_len_msec, - HNS3_TXD_OL3T_M, - HNS3_TXD_OL3T_S, - HNS3_OL3T_IPV4_NO_CSUM); + hns3_set_field(*ol_type_vlan_len_msec, + HNS3_TXD_OL3T_S, + HNS3_OL3T_IPV4_NO_CSUM); } else if (skb->protocol == htons(ETH_P_IPV6)) { - hnae3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_OL3T_M, - HNS3_TXD_OL3T_S, HNS3_OL3T_IPV6); + hns3_set_field(*ol_type_vlan_len_msec, HNS3_TXD_OL3T_S, + HNS3_OL3T_IPV6); } /* define tunnel type(OL4).*/ switch (l4_proto) { case IPPROTO_UDP: - hnae3_set_field(*ol_type_vlan_len_msec, - HNS3_TXD_TUNTYPE_M, - HNS3_TXD_TUNTYPE_S, - HNS3_TUN_MAC_IN_UDP); + hns3_set_field(*ol_type_vlan_len_msec, + HNS3_TXD_TUNTYPE_S, + HNS3_TUN_MAC_IN_UDP); break; case IPPROTO_GRE: - hnae3_set_field(*ol_type_vlan_len_msec, - HNS3_TXD_TUNTYPE_M, - HNS3_TXD_TUNTYPE_S, - HNS3_TUN_NVGRE); + hns3_set_field(*ol_type_vlan_len_msec, + HNS3_TXD_TUNTYPE_S, + HNS3_TUN_NVGRE); break; default: /* drop the skb tunnel packet if hardware don't support, @@ -906,43 +897,37 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto, } if (l3.v4->version == 4) { - hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_M, - HNS3_TXD_L3T_S, HNS3_L3T_IPV4); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S, + HNS3_L3T_IPV4); /* the stack computes the IP header already, the only time we * need the hardware to recompute it is in the case of TSO. */ if (skb_is_gso(skb)) - hnae3_set_bit(*type_cs_vlan_tso, HNS3_TXD_L3CS_B, 1); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3CS_B, 1); } else if (l3.v6->version == 6) { - hnae3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_M, - HNS3_TXD_L3T_S, HNS3_L3T_IPV6); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L3T_S, + HNS3_L3T_IPV6); } switch (l4_proto) { case IPPROTO_TCP: - hnae3_set_bit(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1); - hnae3_set_field(*type_cs_vlan_tso, - HNS3_TXD_L4T_M, - HNS3_TXD_L4T_S, - HNS3_L4T_TCP); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S, + HNS3_L4T_TCP); break; case IPPROTO_UDP: if (hns3_tunnel_csum_bug(skb)) break; - hnae3_set_bit(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1); - hnae3_set_field(*type_cs_vlan_tso, - HNS3_TXD_L4T_M, - HNS3_TXD_L4T_S, - HNS3_L4T_UDP); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S, + HNS3_L4T_UDP); break; case IPPROTO_SCTP: - hnae3_set_bit(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1); - hnae3_set_field(*type_cs_vlan_tso, - HNS3_TXD_L4T_M, - HNS3_TXD_L4T_S, - HNS3_L4T_SCTP); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1); + hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S, + HNS3_L4T_SCTP); break; default: /* drop the skb tunnel packet if hardware don't support, @@ -964,11 +949,8 @@ static int hns3_set_l3l4_type_csum(struct sk_buff *skb, u8 ol4_proto, static void hns3_set_txbd_baseinfo(u16 *bdtp_fe_sc_vld_ra_ri, int frag_end) { /* Config bd buffer end */ - hnae3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_BDTYPE_M, - HNS3_TXD_BDTYPE_S, 0); - hnae3_set_bit(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_FE_B, !!frag_end); - hnae3_set_bit(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B, 1); - hnae3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_SC_M, HNS3_TXD_SC_S, 0); + hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_FE_B, !!frag_end); + hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B, 1); } static int hns3_fill_desc_vtags(struct sk_buff *skb, @@ -1001,10 +983,10 @@ static int hns3_fill_desc_vtags(struct sk_buff *skb, * and use inner_vtag in one tag case. */ if (skb->protocol == htons(ETH_P_8021Q)) { - hnae3_set_bit(*out_vlan_flag, HNS3_TXD_OVLAN_B, 1); + hns3_set_field(*out_vlan_flag, HNS3_TXD_OVLAN_B, 1); *out_vtag = vlan_tag; } else { - hnae3_set_bit(*inner_vlan_flag, HNS3_TXD_VLAN_B, 1); + hns3_set_field(*inner_vlan_flag, HNS3_TXD_VLAN_B, 1); *inner_vtag = vlan_tag; } } else if (skb->protocol == htons(ETH_P_8021Q)) { -- cgit v1.2.3 From e8149933b1fab774e892f8ab605d241df673291c Mon Sep 17 00:00:00 2001 From: Yunsheng Lin Date: Sat, 23 Feb 2019 17:22:14 +0800 Subject: net: hns3: remove hnae3_get_bit in data path The hnae3_get_bit uses hnae3_get_field, and hnae3_get_field masks the data, which is unnecessary in data path. Signed-off-by: Yunsheng Lin Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 33 +++++++++++-------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index ce9878bfaa1a..236b340f8102 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2318,13 +2318,12 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, } /* check if hardware has done checksum */ - if (!hnae3_get_bit(bd_base_info, HNS3_RXD_L3L4P_B)) + if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) return; - if (unlikely(hnae3_get_bit(l234info, HNS3_RXD_L3E_B) || - hnae3_get_bit(l234info, HNS3_RXD_L4E_B) || - hnae3_get_bit(l234info, HNS3_RXD_OL3E_B) || - hnae3_get_bit(l234info, HNS3_RXD_OL4E_B))) { + if (unlikely(l234info & (BIT(HNS3_RXD_L3E_B) | BIT(HNS3_RXD_L4E_B) || + BIT(HNS3_RXD_OL3E_B) || + BIT(HNS3_RXD_OL4E_B)))) { u64_stats_update_begin(&ring->syncp); ring->stats.l3l4_csum_err++; u64_stats_update_end(&ring->syncp); @@ -2469,11 +2468,11 @@ static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc, bd_base_info = le32_to_cpu(desc->rx.bd_base_info); } - while (!hnae3_get_bit(bd_base_info, HNS3_RXD_FE_B)) { + while (!(bd_base_info & BIT(HNS3_RXD_FE_B))) { desc = &ring->desc[ring->next_to_clean]; desc_cb = &ring->desc_cb[ring->next_to_clean]; bd_base_info = le32_to_cpu(desc->rx.bd_base_info); - if (!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B)) + if (!(bd_base_info & BIT(HNS3_RXD_VLD_B))) return -ENXIO; if (unlikely(ring->frag_num >= MAX_SKB_FRAGS)) { @@ -2587,7 +2586,7 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, bd_base_info = le32_to_cpu(desc->rx.bd_base_info); /* Check valid BD */ - if (unlikely(!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B))) + if (unlikely(!(bd_base_info & BIT(HNS3_RXD_VLD_B)))) return -ENXIO; if (!skb) @@ -2650,7 +2649,7 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, vlan_tag); } - if (unlikely(!hnae3_get_bit(bd_base_info, HNS3_RXD_VLD_B))) { + if (unlikely(!(bd_base_info & BIT(HNS3_RXD_VLD_B)))) { u64_stats_update_begin(&ring->syncp); ring->stats.non_vld_descs++; u64_stats_update_end(&ring->syncp); @@ -2660,23 +2659,19 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring, } if (unlikely((!desc->rx.pkt_len) || - hnae3_get_bit(l234info, HNS3_RXD_TRUNCAT_B))) { + (l234info & (BIT(HNS3_RXD_TRUNCAT_B) | + BIT(HNS3_RXD_L2E_B))))) { u64_stats_update_begin(&ring->syncp); - ring->stats.err_pkt_len++; + if (l234info & BIT(HNS3_RXD_L2E_B)) + ring->stats.l2_err++; + else + ring->stats.err_pkt_len++; u64_stats_update_end(&ring->syncp); dev_kfree_skb_any(skb); return -EFAULT; } - if (unlikely(hnae3_get_bit(l234info, HNS3_RXD_L2E_B))) { - u64_stats_update_begin(&ring->syncp); - ring->stats.l2_err++; - u64_stats_update_end(&ring->syncp); - - dev_kfree_skb_any(skb); - return -EFAULT; - } l2_frame_type = hnae3_get_field(l234info, HNS3_RXD_DMAC_M, HNS3_RXD_DMAC_S); -- cgit v1.2.3 From c04259442395a6d9648e8dd105e9058726b2451a Mon Sep 17 00:00:00 2001 From: Peng Li Date: Sat, 23 Feb 2019 17:22:15 +0800 Subject: net: hns3: add support to config depth for tx|rx ring separately This patch adds support to config depth for tx|rx ring separately by ethtool command "-G". Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h | 1 + drivers/net/ethernet/hisilicon/hns3/hnae3.h | 10 ++-- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 54 ++++++++++++---------- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 22 ++++++--- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 3 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 28 +++++++++-- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 39 ++++++++++++++-- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 3 +- 10 files changed, 119 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index 9b6b7b45dde3..299b277bc7ae 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -21,6 +21,7 @@ enum HCLGE_MBX_OPCODE { HCLGE_MBX_SET_MACVLAN, /* (VF -> PF) set unicast filter */ HCLGE_MBX_API_NEGOTIATE, /* (VF -> PF) negotiate API version */ HCLGE_MBX_GET_QINFO, /* (VF -> PF) get queue config */ + HCLGE_MBX_GET_QDEPTH, /* (VF -> PF) get queue depth */ HCLGE_MBX_GET_TCINFO, /* (VF -> PF) get TC config */ HCLGE_MBX_GET_RETA, /* (VF -> PF) get RETA */ HCLGE_MBX_GET_RSS_KEY, /* (VF -> PF) get RSS key */ diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index 10f1cc2ba157..66d7a8b80e76 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -87,7 +87,8 @@ struct hnae3_queue { struct hnae3_handle *handle; int tqp_index; /* index in a handle */ u32 buf_size; /* size for hnae_desc->addr, preset by AE */ - u16 desc_num; /* total number of desc */ + u16 tx_desc_num;/* total number of tx desc */ + u16 rx_desc_num;/* total number of rx desc */ }; /*hnae3 loop mode*/ @@ -505,7 +506,8 @@ struct hnae3_knic_private_info { u16 rss_size; /* Allocated RSS queues */ u16 req_rss_size; u16 rx_buf_len; - u16 num_desc; + u16 num_tx_desc; + u16 num_rx_desc; u8 num_tc; /* Total number of enabled TCs */ u8 prio_tc[HNAE3_MAX_USER_PRIO]; /* TC indexed by prio */ @@ -537,7 +539,9 @@ struct hnae3_roce_private_info { struct hnae3_unic_private_info { struct net_device *netdev; u16 rx_buf_len; - u16 num_desc; + u16 num_tx_desc; + u16 num_rx_desc; + u16 num_tqps; /* total number of tqps in this handle */ struct hnae3_queue **tqp; /* array base of all TQPs of this instance */ }; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 236b340f8102..9f9a52d74f7a 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3231,19 +3231,21 @@ static int hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, { struct hns3_nic_ring_data *ring_data = priv->ring_data; int queue_num = priv->ae_handle->kinfo.num_tqps; - int desc_num = priv->ae_handle->kinfo.num_desc; struct pci_dev *pdev = priv->ae_handle->pdev; struct hns3_enet_ring *ring; + int desc_num; ring = devm_kzalloc(&pdev->dev, sizeof(*ring), GFP_KERNEL); if (!ring) return -ENOMEM; if (ring_type == HNAE3_RING_TYPE_TX) { + desc_num = priv->ae_handle->kinfo.num_tx_desc; ring_data[q->tqp_index].ring = ring; ring_data[q->tqp_index].queue_index = q->tqp_index; ring->io_base = (u8 __iomem *)q->io_base + HNS3_TX_REG_OFFSET; } else { + desc_num = priv->ae_handle->kinfo.num_rx_desc; ring_data[q->tqp_index + queue_num].ring = ring; ring_data[q->tqp_index + queue_num].queue_index = q->tqp_index; ring->io_base = q->io_base; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 3a1e4879b2f8..1db0bd41d209 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -74,7 +74,7 @@ enum hns3_nic_state { #define HNS3_RING_NAME_LEN 16 #define HNS3_BUFFER_SIZE_2048 2048 #define HNS3_RING_MAX_PENDING 32768 -#define HNS3_RING_MIN_PENDING 8 +#define HNS3_RING_MIN_PENDING 24 #define HNS3_RING_BD_MULTIPLE 8 /* max frame size of mac */ #define HNS3_MAC_MAX_FRAME 9728 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index d94c90a38563..359d4731fb2d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -748,15 +748,19 @@ static int hns3_get_rxnfc(struct net_device *netdev, } static int hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv, - u32 new_desc_num) + u32 tx_desc_num, u32 rx_desc_num) { struct hnae3_handle *h = priv->ae_handle; int i; - h->kinfo.num_desc = new_desc_num; + h->kinfo.num_tx_desc = tx_desc_num; + h->kinfo.num_rx_desc = rx_desc_num; - for (i = 0; i < h->kinfo.num_tqps * 2; i++) - priv->ring_data[i].ring->desc_num = new_desc_num; + for (i = 0; i < h->kinfo.num_tqps; i++) { + priv->ring_data[i].ring->desc_num = tx_desc_num; + priv->ring_data[i + h->kinfo.num_tqps].ring->desc_num = + rx_desc_num; + } return hns3_init_all_ring(priv); } @@ -767,7 +771,9 @@ static int hns3_set_ringparam(struct net_device *ndev, struct hns3_nic_priv *priv = netdev_priv(ndev); struct hnae3_handle *h = priv->ae_handle; bool if_running = netif_running(ndev); - u32 old_desc_num, new_desc_num; + u32 old_tx_desc_num, new_tx_desc_num; + u32 old_rx_desc_num, new_rx_desc_num; + int queue_num = h->kinfo.num_tqps; int ret; if (hns3_nic_resetting(ndev)) @@ -776,32 +782,28 @@ static int hns3_set_ringparam(struct net_device *ndev, if (param->rx_mini_pending || param->rx_jumbo_pending) return -EINVAL; - if (param->tx_pending != param->rx_pending) { - netdev_err(ndev, - "Descriptors of tx and rx must be equal"); - return -EINVAL; - } - if (param->tx_pending > HNS3_RING_MAX_PENDING || - param->tx_pending < HNS3_RING_MIN_PENDING) { - netdev_err(ndev, - "Descriptors requested (Tx/Rx: %d) out of range [%d-%d]\n", - param->tx_pending, HNS3_RING_MIN_PENDING, - HNS3_RING_MAX_PENDING); + param->tx_pending < HNS3_RING_MIN_PENDING || + param->rx_pending > HNS3_RING_MAX_PENDING || + param->rx_pending < HNS3_RING_MIN_PENDING) { + netdev_err(ndev, "Queue depth out of range [%d-%d]\n", + HNS3_RING_MIN_PENDING, HNS3_RING_MAX_PENDING); return -EINVAL; } - new_desc_num = param->tx_pending; - /* Hardware requires that its descriptors must be multiple of eight */ - new_desc_num = ALIGN(new_desc_num, HNS3_RING_BD_MULTIPLE); - old_desc_num = h->kinfo.num_desc; - if (old_desc_num == new_desc_num) + new_tx_desc_num = ALIGN(param->tx_pending, HNS3_RING_BD_MULTIPLE); + new_rx_desc_num = ALIGN(param->rx_pending, HNS3_RING_BD_MULTIPLE); + old_tx_desc_num = priv->ring_data[0].ring->desc_num; + old_rx_desc_num = priv->ring_data[queue_num].ring->desc_num; + if (old_tx_desc_num == new_tx_desc_num && + old_rx_desc_num == new_rx_desc_num) return 0; netdev_info(ndev, - "Changing descriptor count from %d to %d.\n", - old_desc_num, new_desc_num); + "Changing Tx/Rx ring depth from %d/%d to %d/%d\n", + old_tx_desc_num, old_rx_desc_num, + new_tx_desc_num, new_rx_desc_num); if (if_running) ndev->netdev_ops->ndo_stop(ndev); @@ -810,9 +812,11 @@ static int hns3_set_ringparam(struct net_device *ndev, if (ret) return ret; - ret = hns3_change_all_ring_bd_num(priv, new_desc_num); + ret = hns3_change_all_ring_bd_num(priv, new_tx_desc_num, + new_rx_desc_num); if (ret) { - ret = hns3_change_all_ring_bd_num(priv, old_desc_num); + ret = hns3_change_all_ring_bd_num(priv, old_tx_desc_num, + old_rx_desc_num); if (ret) { netdev_err(ndev, "Revert to old bd num fail, ret=%d.\n", ret); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 5c8f2e4d71c9..f1134393b7b6 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -1033,7 +1033,8 @@ static int hclge_configure(struct hclge_dev *hdev) ether_addr_copy(hdev->hw.mac.mac_addr, cfg.mac_addr); hdev->hw.mac.media_type = cfg.media_type; hdev->hw.mac.phy_addr = cfg.phy_addr; - hdev->num_desc = cfg.tqp_desc_num; + hdev->num_tx_desc = cfg.tqp_desc_num; + hdev->num_rx_desc = cfg.tqp_desc_num; hdev->tm_info.num_pg = 1; hdev->tc_max = cfg.tc_num; hdev->tm_info.hw_pfc_map = 0; @@ -1140,7 +1141,8 @@ static int hclge_alloc_tqps(struct hclge_dev *hdev) tqp->q.ae_algo = &ae_algo; tqp->q.buf_size = hdev->rx_buf_len; - tqp->q.desc_num = hdev->num_desc; + tqp->q.tx_desc_num = hdev->num_tx_desc; + tqp->q.rx_desc_num = hdev->num_rx_desc; tqp->q.io_base = hdev->hw.io_base + HCLGE_TQP_REG_OFFSET + i * HCLGE_TQP_REG_SIZE; @@ -1184,7 +1186,8 @@ static int hclge_assign_tqp(struct hclge_vport *vport, u16 num_tqps) if (!hdev->htqp[i].alloced) { hdev->htqp[i].q.handle = &vport->nic; hdev->htqp[i].q.tqp_index = alloced; - hdev->htqp[i].q.desc_num = kinfo->num_desc; + hdev->htqp[i].q.tx_desc_num = kinfo->num_tx_desc; + hdev->htqp[i].q.rx_desc_num = kinfo->num_rx_desc; kinfo->tqp[alloced] = &hdev->htqp[i].q; hdev->htqp[i].alloced = true; alloced++; @@ -1197,15 +1200,18 @@ static int hclge_assign_tqp(struct hclge_vport *vport, u16 num_tqps) return 0; } -static int hclge_knic_setup(struct hclge_vport *vport, - u16 num_tqps, u16 num_desc) +static int hclge_knic_setup(struct hclge_vport *vport, u16 num_tqps, + u16 num_tx_desc, u16 num_rx_desc) + { struct hnae3_handle *nic = &vport->nic; struct hnae3_knic_private_info *kinfo = &nic->kinfo; struct hclge_dev *hdev = vport->back; int ret; - kinfo->num_desc = num_desc; + kinfo->num_tx_desc = num_tx_desc; + kinfo->num_rx_desc = num_rx_desc; + kinfo->rx_buf_len = hdev->rx_buf_len; kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, num_tqps, @@ -1279,7 +1285,9 @@ static int hclge_vport_setup(struct hclge_vport *vport, u16 num_tqps) nic->numa_node_mask = hdev->numa_node_mask; if (hdev->ae_dev->dev_type == HNAE3_DEV_KNIC) { - ret = hclge_knic_setup(vport, num_tqps, hdev->num_desc); + ret = hclge_knic_setup(vport, num_tqps, + hdev->num_tx_desc, hdev->num_rx_desc); + if (ret) { dev_err(&hdev->pdev->dev, "knic setup failed %d\n", ret); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index abbc58ea4864..b57ac4beb313 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -706,7 +706,8 @@ struct hclge_dev { u16 num_alloc_vport; /* Num vports this driver supports */ u32 numa_node_mask; u16 rx_buf_len; - u16 num_desc; + u16 num_tx_desc; /* desc num of per tx queue */ + u16 num_rx_desc; /* desc num of per rx queue */ u8 hw_tc_map; u8 tc_num_last_time; enum hclge_fc_mode fc_mode_last_time; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 9e0952c329bb..ca056b3a6589 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -357,20 +357,34 @@ static int hclge_get_vf_queue_info(struct hclge_vport *vport, struct hclge_mbx_vf_to_pf_cmd *mbx_req, bool gen_resp) { -#define HCLGE_TQPS_RSS_INFO_LEN 8 +#define HCLGE_TQPS_RSS_INFO_LEN 6 u8 resp_data[HCLGE_TQPS_RSS_INFO_LEN]; struct hclge_dev *hdev = vport->back; /* get the queue related info */ memcpy(&resp_data[0], &vport->alloc_tqps, sizeof(u16)); memcpy(&resp_data[2], &vport->nic.kinfo.rss_size, sizeof(u16)); - memcpy(&resp_data[4], &hdev->num_desc, sizeof(u16)); - memcpy(&resp_data[6], &hdev->rx_buf_len, sizeof(u16)); + memcpy(&resp_data[4], &hdev->rx_buf_len, sizeof(u16)); return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, HCLGE_TQPS_RSS_INFO_LEN); } +static int hclge_get_vf_queue_depth(struct hclge_vport *vport, + struct hclge_mbx_vf_to_pf_cmd *mbx_req, + bool gen_resp) +{ +#define HCLGE_TQPS_DEPTH_INFO_LEN 4 + u8 resp_data[HCLGE_TQPS_DEPTH_INFO_LEN]; + struct hclge_dev *hdev = vport->back; + + /* get the queue depth info */ + memcpy(&resp_data[0], &hdev->num_tx_desc, sizeof(u16)); + memcpy(&resp_data[2], &hdev->num_rx_desc, sizeof(u16)); + return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, + HCLGE_TQPS_DEPTH_INFO_LEN); +} + static int hclge_get_link_info(struct hclge_vport *vport, struct hclge_mbx_vf_to_pf_cmd *mbx_req) { @@ -567,6 +581,14 @@ void hclge_mbx_handler(struct hclge_dev *hdev) "PF failed(%d) to get Q info for VF\n", ret); break; + case HCLGE_MBX_GET_QDEPTH: + ret = hclge_get_vf_queue_depth(vport, req, true); + if (ret) + dev_err(&hdev->pdev->dev, + "PF failed(%d) to get Q depth for VF\n", + ret); + break; + case HCLGE_MBX_GET_TCINFO: ret = hclge_get_vf_tcinfo(vport, req, true); if (ret) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 4a897cfb573b..12f16b96e746 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -247,7 +247,7 @@ static int hclgevf_get_tc_info(struct hclgevf_dev *hdev) static int hclgevf_get_queue_info(struct hclgevf_dev *hdev) { -#define HCLGEVF_TQPS_RSS_INFO_LEN 8 +#define HCLGEVF_TQPS_RSS_INFO_LEN 6 u8 resp_msg[HCLGEVF_TQPS_RSS_INFO_LEN]; int status; @@ -263,8 +263,29 @@ static int hclgevf_get_queue_info(struct hclgevf_dev *hdev) memcpy(&hdev->num_tqps, &resp_msg[0], sizeof(u16)); memcpy(&hdev->rss_size_max, &resp_msg[2], sizeof(u16)); - memcpy(&hdev->num_desc, &resp_msg[4], sizeof(u16)); - memcpy(&hdev->rx_buf_len, &resp_msg[6], sizeof(u16)); + memcpy(&hdev->rx_buf_len, &resp_msg[4], sizeof(u16)); + + return 0; +} + +static int hclgevf_get_queue_depth(struct hclgevf_dev *hdev) +{ +#define HCLGEVF_TQPS_DEPTH_INFO_LEN 4 + u8 resp_msg[HCLGEVF_TQPS_DEPTH_INFO_LEN]; + int ret; + + ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_QDEPTH, 0, NULL, 0, + true, resp_msg, + HCLGEVF_TQPS_DEPTH_INFO_LEN); + if (ret) { + dev_err(&hdev->pdev->dev, + "VF request to get tqp depth info from PF failed %d", + ret); + return ret; + } + + memcpy(&hdev->num_tx_desc, &resp_msg[0], sizeof(u16)); + memcpy(&hdev->num_rx_desc, &resp_msg[2], sizeof(u16)); return 0; } @@ -304,7 +325,8 @@ static int hclgevf_alloc_tqps(struct hclgevf_dev *hdev) tqp->q.ae_algo = &ae_algovf; tqp->q.buf_size = hdev->rx_buf_len; - tqp->q.desc_num = hdev->num_desc; + tqp->q.tx_desc_num = hdev->num_tx_desc; + tqp->q.rx_desc_num = hdev->num_rx_desc; tqp->q.io_base = hdev->hw.io_base + HCLGEVF_TQP_REG_OFFSET + i * HCLGEVF_TQP_REG_SIZE; @@ -323,7 +345,8 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev) kinfo = &nic->kinfo; kinfo->num_tc = 0; - kinfo->num_desc = hdev->num_desc; + kinfo->num_tx_desc = hdev->num_tx_desc; + kinfo->num_rx_desc = hdev->num_rx_desc; kinfo->rx_buf_len = hdev->rx_buf_len; for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++) if (hdev->hw_tc_map & BIT(i)) @@ -1747,6 +1770,12 @@ static int hclgevf_configure(struct hclgevf_dev *hdev) ret = hclgevf_get_queue_info(hdev); if (ret) return ret; + + /* get queue depth info from PF */ + ret = hclgevf_get_queue_depth(hdev); + if (ret) + return ret; + /* get tc configuration from PF */ return hclgevf_get_tc_info(hdev); } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h index eba1118a766d..c128863ee7d0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h @@ -239,7 +239,8 @@ struct hclgevf_dev { u16 num_alloc_vport; /* num vports this driver supports */ u32 numa_node_mask; u16 rx_buf_len; - u16 num_desc; + u16 num_tx_desc; /* desc num of per tx queue */ + u16 num_rx_desc; /* desc num of per rx queue */ u8 hw_tc_map; u16 num_msi; -- cgit v1.2.3 From 30ebc576d7773c7d8b53fa7941c2c56e488589fd Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sat, 23 Feb 2019 17:22:16 +0800 Subject: net: hns3: enable VF VLAN filter for each VF when initializing For revision 0x21, the switch of VF VLAN filter is per function. It's necessary to enable VF VLAN filter for each VF when initializing. Otherwise, VF will be able to receive broadcast packets with unknown VLAN when PF enters promisc mode. Fixes: 64d114f0a750 ("net: hns3: Add egress/ingress vlan filter for revision 0x21") Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 4 ++- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 30 ++++++++++++++-------- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index bad21c89f6b7..3714733c96d9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -693,7 +693,9 @@ struct hclge_mac_vlan_remove_cmd { struct hclge_vlan_filter_ctrl_cmd { u8 vlan_type; u8 vlan_fe; - u8 rsv[22]; + u8 rsv1[2]; + u8 vf_id; + u8 rsv2[19]; }; struct hclge_vlan_filter_pf_cfg_cmd { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index f1134393b7b6..deda606c51e7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -6337,7 +6337,7 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr, } static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type, - u8 fe_type, bool filter_en) + u8 fe_type, bool filter_en, u8 vf_id) { struct hclge_vlan_filter_ctrl_cmd *req; struct hclge_desc desc; @@ -6348,6 +6348,7 @@ static int hclge_set_vlan_filter_ctrl(struct hclge_dev *hdev, u8 vlan_type, req = (struct hclge_vlan_filter_ctrl_cmd *)desc.data; req->vlan_type = vlan_type; req->vlan_fe = filter_en ? fe_type : 0; + req->vf_id = vf_id; ret = hclge_cmd_send(&hdev->hw, &desc, 1); if (ret) @@ -6376,12 +6377,13 @@ static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable) if (hdev->pdev->revision >= 0x21) { hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, - HCLGE_FILTER_FE_EGRESS, enable); + HCLGE_FILTER_FE_EGRESS, enable, 0); hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT, - HCLGE_FILTER_FE_INGRESS, enable); + HCLGE_FILTER_FE_INGRESS, enable, 0); } else { hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, - HCLGE_FILTER_FE_EGRESS_V1_B, enable); + HCLGE_FILTER_FE_EGRESS_V1_B, enable, + 0); } if (enable) handle->netdev_flags |= HNAE3_VLAN_FLTR; @@ -6689,19 +6691,27 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev) int i; if (hdev->pdev->revision >= 0x21) { - ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, - HCLGE_FILTER_FE_EGRESS, true); - if (ret) - return ret; + /* for revision 0x21, vf vlan filter is per function */ + for (i = 0; i < hdev->num_alloc_vport; i++) { + vport = &hdev->vport[i]; + ret = hclge_set_vlan_filter_ctrl(hdev, + HCLGE_FILTER_TYPE_VF, + HCLGE_FILTER_FE_EGRESS, + true, + vport->vport_id); + if (ret) + return ret; + } ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT, - HCLGE_FILTER_FE_INGRESS, true); + HCLGE_FILTER_FE_INGRESS, true, + 0); if (ret) return ret; } else { ret = hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF, HCLGE_FILTER_FE_EGRESS_V1_B, - true); + true, 0); if (ret) return ret; } -- cgit v1.2.3 From a638b1d8cc875ae819591be787503fc1db053d5f Mon Sep 17 00:00:00 2001 From: Jian Shen Date: Sat, 23 Feb 2019 17:22:17 +0800 Subject: net: hns3: fix get VF RSS issue For revision 0x20, VF shares the same RSS config with PF. In original codes, it always return 0 when query RSS hash key for VF. This patch fixes it by return the hash key got from PF. Fixes: 374ad291762a ("net: hns3: net: hns3: Add RSS general configuration support for VF") Signed-off-by: Jian Shen Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 25 +++++++++++ .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 50 +++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index ca056b3a6589..306a23e486de 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -490,6 +490,24 @@ static int hclge_get_queue_id_in_pf(struct hclge_vport *vport, return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, 2); } +static int hclge_get_rss_key(struct hclge_vport *vport, + struct hclge_mbx_vf_to_pf_cmd *mbx_req) +{ +#define HCLGE_RSS_MBX_RESP_LEN 8 + u8 resp_data[HCLGE_RSS_MBX_RESP_LEN]; + struct hclge_dev *hdev = vport->back; + u8 index; + + index = mbx_req->msg[2]; + + memcpy(&resp_data[0], + &hdev->vport[0].rss_hash_key[index * HCLGE_RSS_MBX_RESP_LEN], + HCLGE_RSS_MBX_RESP_LEN); + + return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, + HCLGE_RSS_MBX_RESP_LEN); +} + static bool hclge_cmd_crq_empty(struct hclge_hw *hw) { u32 tail = hclge_read_dev(hw, HCLGE_NIC_CRQ_TAIL_REG); @@ -625,6 +643,13 @@ void hclge_mbx_handler(struct hclge_dev *hdev) "PF failed(%d) to get qid for VF\n", ret); break; + case HCLGE_MBX_GET_RSS_KEY: + ret = hclge_get_rss_key(vport, req); + if (ret) + dev_err(&hdev->pdev->dev, + "PF fail(%d) to get rss key for VF\n", + ret); + break; case HCLGE_MBX_GET_LINK_MODE: hclge_get_link_mode(vport, req); break; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 12f16b96e746..8bc28e6f465f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -620,12 +620,50 @@ static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev, u16 rss_size) return status; } +/* for revision 0x20, vf shared the same rss config with pf */ +static int hclgevf_get_rss_hash_key(struct hclgevf_dev *hdev) +{ +#define HCLGEVF_RSS_MBX_RESP_LEN 8 + + struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; + u8 resp_msg[HCLGEVF_RSS_MBX_RESP_LEN]; + u16 msg_num, hash_key_index; + u8 index; + int ret; + + msg_num = (HCLGEVF_RSS_KEY_SIZE + HCLGEVF_RSS_MBX_RESP_LEN - 1) / + HCLGEVF_RSS_MBX_RESP_LEN; + for (index = 0; index < msg_num; index++) { + ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_RSS_KEY, 0, + &index, sizeof(index), + true, resp_msg, + HCLGEVF_RSS_MBX_RESP_LEN); + if (ret) { + dev_err(&hdev->pdev->dev, + "VF get rss hash key from PF failed, ret=%d", + ret); + return ret; + } + + hash_key_index = HCLGEVF_RSS_MBX_RESP_LEN * index; + if (index == msg_num - 1) + memcpy(&rss_cfg->rss_hash_key[hash_key_index], + &resp_msg[0], + HCLGEVF_RSS_KEY_SIZE - hash_key_index); + else + memcpy(&rss_cfg->rss_hash_key[hash_key_index], + &resp_msg[0], HCLGEVF_RSS_MBX_RESP_LEN); + } + + return 0; +} + static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key, u8 *hfunc) { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg; - int i; + int i, ret; if (handle->pdev->revision >= 0x21) { /* Get hash algorithm */ @@ -647,6 +685,16 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key, if (key) memcpy(key, rss_cfg->rss_hash_key, HCLGEVF_RSS_KEY_SIZE); + } else { + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + if (key) { + ret = hclgevf_get_rss_hash_key(hdev); + if (ret) + return ret; + memcpy(key, rss_cfg->rss_hash_key, + HCLGEVF_RSS_KEY_SIZE); + } } if (indir) -- cgit v1.2.3 From eb4c2ccbad6c688be791e0c08640a40124558c03 Mon Sep 17 00:00:00 2001 From: Shiju Jose Date: Sat, 23 Feb 2019 17:22:18 +0800 Subject: net: hns3: fix setting of the hns reset_type for rdma hw errors Presently the hns reset_type for the roce errors is set in the hclge_log_and_clear_rocee_ras_error function. This function is also called to detect and clear roce errors while enabling the rdma error interrupts. However there is no hns reset requested for this case. This can cause issue of wrong reset_type used with subsequent hns reset as the reset_type set in the above case was not cleared. This patch moves setting of hns reset_type for the roce errors from hclge_log_and_clear_rocee_ras_error function to hclge_handle_rocee_ras_error. Fixes: 630ba007f475 ("net: hns3: add handling of RDMA RAS errors") Reported-by: Huazhong Tan Reported-by: Xiaofei Tan Signed-off-by: Shiju Jose Signed-off-by: Peng Li Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 36 ++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c index b9d363fa595a..1feceff1477c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c @@ -1148,10 +1148,10 @@ static int hclge_log_rocee_ovf_error(struct hclge_dev *hdev) return 0; } -static int hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev) +static enum hnae3_reset_type +hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev) { - enum hnae3_reset_type reset_type = HNAE3_FUNC_RESET; - struct hnae3_ae_dev *ae_dev = hdev->ae_dev; + enum hnae3_reset_type reset_type = HNAE3_NONE_RESET; struct device *dev = &hdev->pdev->dev; struct hclge_desc desc[2]; unsigned int status; @@ -1164,17 +1164,20 @@ static int hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev) if (ret) { dev_err(dev, "failed(%d) to query ROCEE RAS INT SRC\n", ret); /* reset everything for now */ - HCLGE_SET_DEFAULT_RESET_REQUEST(HNAE3_GLOBAL_RESET); - return ret; + return HNAE3_GLOBAL_RESET; } status = le32_to_cpu(desc[0].data[0]); - if (status & HCLGE_ROCEE_RERR_INT_MASK) + if (status & HCLGE_ROCEE_RERR_INT_MASK) { dev_warn(dev, "ROCEE RAS AXI rresp error\n"); + reset_type = HNAE3_FUNC_RESET; + } - if (status & HCLGE_ROCEE_BERR_INT_MASK) + if (status & HCLGE_ROCEE_BERR_INT_MASK) { dev_warn(dev, "ROCEE RAS AXI bresp error\n"); + reset_type = HNAE3_FUNC_RESET; + } if (status & HCLGE_ROCEE_ECC_INT_MASK) { dev_warn(dev, "ROCEE RAS 2bit ECC error\n"); @@ -1186,9 +1189,9 @@ static int hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev) if (ret) { dev_err(dev, "failed(%d) to process ovf error\n", ret); /* reset everything for now */ - HCLGE_SET_DEFAULT_RESET_REQUEST(HNAE3_GLOBAL_RESET); - return ret; + return HNAE3_GLOBAL_RESET; } + reset_type = HNAE3_FUNC_RESET; } /* clear error status */ @@ -1197,12 +1200,10 @@ static int hclge_log_and_clear_rocee_ras_error(struct hclge_dev *hdev) if (ret) { dev_err(dev, "failed(%d) to clear ROCEE RAS error\n", ret); /* reset everything for now */ - reset_type = HNAE3_GLOBAL_RESET; + return HNAE3_GLOBAL_RESET; } - HCLGE_SET_DEFAULT_RESET_REQUEST(reset_type); - - return ret; + return reset_type; } static int hclge_config_rocee_ras_interrupt(struct hclge_dev *hdev, bool en) @@ -1232,15 +1233,18 @@ static int hclge_config_rocee_ras_interrupt(struct hclge_dev *hdev, bool en) return ret; } -static int hclge_handle_rocee_ras_error(struct hnae3_ae_dev *ae_dev) +static void hclge_handle_rocee_ras_error(struct hnae3_ae_dev *ae_dev) { + enum hnae3_reset_type reset_type = HNAE3_NONE_RESET; struct hclge_dev *hdev = ae_dev->priv; if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) || hdev->pdev->revision < 0x21) - return HNAE3_NONE_RESET; + return; - return hclge_log_and_clear_rocee_ras_error(hdev); + reset_type = hclge_log_and_clear_rocee_ras_error(hdev); + if (reset_type != HNAE3_NONE_RESET) + HCLGE_SET_DEFAULT_RESET_REQUEST(reset_type); } static const struct hclge_hw_blk hw_blk[] = { -- cgit v1.2.3 From 186551284e6ec3d7c87b0e48da570816a39e9afc Mon Sep 17 00:00:00 2001 From: Huazhong Tan Date: Sat, 23 Feb 2019 17:22:19 +0800 Subject: net: hns3: fix improper error handling for hns3_client_start If hns3_client_start() failed in the hns3_client_init(), register_dev() should be undo in its error handling. Fixes: a6d818e31d08 ("net: hns3: Add vport alive state checking support") Signed-off-by: Huazhong Tan Signed-off-by: Peng Li Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 9f9a52d74f7a..3cb43b1f1c2e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3656,7 +3656,7 @@ static int hns3_client_init(struct hnae3_handle *handle) ret = hns3_client_start(handle); if (ret) { dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret); - goto out_reg_netdev_fail; + goto out_client_start; } hns3_dcbnl_setup(handle); @@ -3670,6 +3670,8 @@ static int hns3_client_init(struct hnae3_handle *handle) return ret; +out_client_start: + unregister_netdev(netdev); out_reg_netdev_fail: hns3_uninit_phy(netdev); out_init_phy: -- cgit v1.2.3 From f6d9758b12660484b6639364cc406da92a918c96 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 23 Feb 2019 17:43:56 +0100 Subject: net: dsa: mv88e6xxx: Add lockdep classes to fix false positive splat The following false positive lockdep splat has been observed. ====================================================== WARNING: possible circular locking dependency detected 4.20.0+ #302 Not tainted ------------------------------------------------------ systemd-udevd/160 is trying to acquire lock: edea6080 (&chip->reg_lock){+.+.}, at: __setup_irq+0x640/0x704 but task is already holding lock: edff0340 (&desc->request_mutex){+.+.}, at: __setup_irq+0xa0/0x704 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&desc->request_mutex){+.+.}: mutex_lock_nested+0x1c/0x24 __setup_irq+0xa0/0x704 request_threaded_irq+0xd0/0x150 mv88e6xxx_probe+0x41c/0x694 [mv88e6xxx] mdio_probe+0x2c/0x54 really_probe+0x200/0x2c4 driver_probe_device+0x5c/0x174 __driver_attach+0xd8/0xdc bus_for_each_dev+0x58/0x7c bus_add_driver+0xe4/0x1f0 driver_register+0x7c/0x110 mdio_driver_register+0x24/0x58 do_one_initcall+0x74/0x2e8 do_init_module+0x60/0x1d0 load_module+0x1968/0x1ff4 sys_finit_module+0x8c/0x98 ret_fast_syscall+0x0/0x28 0xbedf2ae8 -> #0 (&chip->reg_lock){+.+.}: __mutex_lock+0x50/0x8b8 mutex_lock_nested+0x1c/0x24 __setup_irq+0x640/0x704 request_threaded_irq+0xd0/0x150 mv88e6xxx_g2_irq_setup+0xcc/0x1b4 [mv88e6xxx] mv88e6xxx_probe+0x44c/0x694 [mv88e6xxx] mdio_probe+0x2c/0x54 really_probe+0x200/0x2c4 driver_probe_device+0x5c/0x174 __driver_attach+0xd8/0xdc bus_for_each_dev+0x58/0x7c bus_add_driver+0xe4/0x1f0 driver_register+0x7c/0x110 mdio_driver_register+0x24/0x58 do_one_initcall+0x74/0x2e8 do_init_module+0x60/0x1d0 load_module+0x1968/0x1ff4 sys_finit_module+0x8c/0x98 ret_fast_syscall+0x0/0x28 0xbedf2ae8 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&desc->request_mutex); lock(&chip->reg_lock); lock(&desc->request_mutex); lock(&chip->reg_lock); &desc->request_mutex refer to two different mutex. #1 is the GPIO for the chip interrupt. #2 is the chained interrupt between global 1 and global 2. Add lockdep classes to the GPIO interrupt to avoid this. Reported-by: Russell King Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 3f9a3fc52a0e..3546c5e2b924 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -442,12 +442,20 @@ out_mapping: static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip) { + static struct lock_class_key lock_key; + static struct lock_class_key request_key; int err; err = mv88e6xxx_g1_irq_setup_common(chip); if (err) return err; + /* These lock classes tells lockdep that global 1 irqs are in + * a different category than their parent GPIO, so it won't + * report false recursion. + */ + irq_set_lockdep_class(chip->irq, &lock_key, &request_key); + err = request_threaded_irq(chip->irq, NULL, mv88e6xxx_g1_irq_thread_fn, IRQF_ONESHOT | IRQF_SHARED, -- cgit v1.2.3 From 342a0ee70acbee97fdeb91349420f8744eb291fb Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 23 Feb 2019 17:43:57 +0100 Subject: net: dsa: mv88e6xxx: Release lock while requesting IRQ There is no need to hold the register lock while requesting the GPIO interrupt. By not holding it we can also avoid a false positive lockdep splat. Reported-by: Russell King Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 3546c5e2b924..d30336f259ce 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -456,10 +456,12 @@ static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip) */ irq_set_lockdep_class(chip->irq, &lock_key, &request_key); + mutex_unlock(&chip->reg_lock); err = request_threaded_irq(chip->irq, NULL, mv88e6xxx_g1_irq_thread_fn, IRQF_ONESHOT | IRQF_SHARED, dev_name(chip->dev), chip); + mutex_lock(&chip->reg_lock); if (err) mv88e6xxx_g1_irq_free_common(chip); -- cgit v1.2.3 From 726097d6d6d8e928c62f459305d74856f7cab155 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 24 Feb 2019 17:41:47 +0100 Subject: net: phy: improve auto-neg emulation in swphy Auto-neg emulation currently doesn't set bit BMCR_ANENABLE in BMCR, add this. Users will ignore speed and duplex settings in BMCR because we're emulating auto-neg, therefore we can remove related code. See also following discussion [0]. [0] https://marc.info/?t=155041784900002&r=1&w=2 Signed-off-by: Heiner Kallweit Tested-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/swphy.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/swphy.c b/drivers/net/phy/swphy.c index b9743569e431..dad22481d9c1 100644 --- a/drivers/net/phy/swphy.c +++ b/drivers/net/phy/swphy.c @@ -19,7 +19,6 @@ #define MII_REGS_NUM 29 struct swmii_regs { - u16 bmcr; u16 bmsr; u16 lpa; u16 lpagb; @@ -40,16 +39,13 @@ enum { */ static const struct swmii_regs speed[] = { [SWMII_SPEED_10] = { - .bmcr = BMCR_FULLDPLX, .lpa = LPA_10FULL | LPA_10HALF, }, [SWMII_SPEED_100] = { - .bmcr = BMCR_FULLDPLX | BMCR_SPEED100, .bmsr = BMSR_100FULL | BMSR_100HALF, .lpa = LPA_100FULL | LPA_100HALF, }, [SWMII_SPEED_1000] = { - .bmcr = BMCR_FULLDPLX | BMCR_SPEED1000, .bmsr = BMSR_ESTATEN, .lpagb = LPA_1000FULL | LPA_1000HALF, }, @@ -57,13 +53,11 @@ static const struct swmii_regs speed[] = { static const struct swmii_regs duplex[] = { [SWMII_DUPLEX_HALF] = { - .bmcr = ~BMCR_FULLDPLX, .bmsr = BMSR_ESTATEN | BMSR_100HALF, .lpa = LPA_10HALF | LPA_100HALF, .lpagb = LPA_1000HALF, }, [SWMII_DUPLEX_FULL] = { - .bmcr = ~0, .bmsr = BMSR_ESTATEN | BMSR_100FULL, .lpa = LPA_10FULL | LPA_100FULL, .lpagb = LPA_1000FULL, @@ -118,7 +112,6 @@ int swphy_read_reg(int reg, const struct fixed_phy_status *state) { int speed_index, duplex_index; u16 bmsr = BMSR_ANEGCAPABLE; - u16 bmcr = 0; u16 lpagb = 0; u16 lpa = 0; @@ -136,7 +129,6 @@ int swphy_read_reg(int reg, const struct fixed_phy_status *state) if (state->link) { bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; - bmcr |= speed[speed_index].bmcr & duplex[duplex_index].bmcr; lpa |= speed[speed_index].lpa & duplex[duplex_index].lpa; lpagb |= speed[speed_index].lpagb & duplex[duplex_index].lpagb; @@ -149,7 +141,7 @@ int swphy_read_reg(int reg, const struct fixed_phy_status *state) switch (reg) { case MII_BMCR: - return bmcr; + return BMCR_ANENABLE; case MII_BMSR: return bmsr; case MII_PHYSID1: -- cgit v1.2.3 From 0f3b1cf23f0ee72017ee6daebcf6cbe601be8bee Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sun, 24 Feb 2019 18:01:18 +0100 Subject: net: phy: fix reading fixed phy status With the switch to phy_resolve_aneg_linkmode() we don't read from the chip any longer what is advertised but use phydev->advertising directly. For a fixed phy however this bitmap is empty so far, what results in no common mode being found. This breaks DSA. Fix this by advertising everything that is supported. For a normal phy this done by phy_probe(). Fixes: 5502b218e001 ("net: phy: use phy_resolve_aneg_linkmode in genphy_read_status") Signed-off-by: Heiner Kallweit Tested-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/fixed_phy.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index b0d1368c3400..1acd8bfdb3bc 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "swphy.h" @@ -300,6 +301,8 @@ static struct phy_device *__fixed_phy_register(unsigned int irq, phy->supported); } + linkmode_copy(phy->advertising, phy->supported); + ret = phy_device_register(phy); if (ret) { phy_device_free(phy); -- cgit v1.2.3 From 75104db0cb353ec0b74644d960640ac0f84ab839 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 24 Feb 2019 20:44:43 +0100 Subject: dsa: Remove phydev parameter from disable_port call No current DSA driver makes use of the phydev parameter passed to the disable_port call. Remove it. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/b53/b53_common.c | 4 ++-- drivers/net/dsa/b53/b53_priv.h | 2 +- drivers/net/dsa/bcm_sf2.c | 9 ++++----- drivers/net/dsa/lan9303-core.c | 3 +-- drivers/net/dsa/lantiq_gswip.c | 5 ++--- drivers/net/dsa/microchip/ksz_common.c | 2 +- drivers/net/dsa/microchip/ksz_common.h | 2 +- drivers/net/dsa/mt7530.c | 5 ++--- drivers/net/dsa/mv88e6xxx/chip.c | 3 +-- drivers/net/dsa/qca8k.c | 3 +-- drivers/net/dsa/rtl8366rb.c | 3 +-- drivers/net/dsa/vitesse-vsc73xx.c | 3 +-- include/net/dsa.h | 3 +-- net/dsa/dsa_priv.h | 2 +- net/dsa/port.c | 4 ++-- net/dsa/slave.c | 2 +- 16 files changed, 23 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index c76892ac4e69..0852e5e08177 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -543,7 +543,7 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) } EXPORT_SYMBOL(b53_enable_port); -void b53_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy) +void b53_disable_port(struct dsa_switch *ds, int port) { struct b53_device *dev = ds->priv; u8 reg; @@ -963,7 +963,7 @@ static int b53_setup(struct dsa_switch *ds) if (dsa_is_cpu_port(ds, port)) b53_enable_cpu_port(dev, port); else if (dsa_is_unused_port(ds, port)) - b53_disable_port(ds, port, NULL); + b53_disable_port(ds, port); } return ret; diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h index 4dc7ee38b258..e3441dcf2d21 100644 --- a/drivers/net/dsa/b53/b53_priv.h +++ b/drivers/net/dsa/b53/b53_priv.h @@ -356,7 +356,7 @@ enum dsa_tag_protocol b53_get_tag_protocol(struct dsa_switch *ds, int port); void b53_mirror_del(struct dsa_switch *ds, int port, struct dsa_mall_mirror_tc_entry *mirror); int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy); -void b53_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy); +void b53_disable_port(struct dsa_switch *ds, int port); void b53_brcm_hdr_setup(struct dsa_switch *ds, int port); void b53_eee_enable_set(struct dsa_switch *ds, int port, bool enable); int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy); diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index f91b8e77d543..c8e3f05e1d72 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -221,8 +221,7 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, return b53_enable_port(ds, port, phy); } -static void bcm_sf2_port_disable(struct dsa_switch *ds, int port, - struct phy_device *phy) +static void bcm_sf2_port_disable(struct dsa_switch *ds, int port) { struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); u32 reg; @@ -241,7 +240,7 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port, if (priv->int_phy_mask & 1 << port && priv->hw_params.num_gphy == 1) bcm_sf2_gphy_enable_set(ds, false); - b53_disable_port(ds, port, phy); + b53_disable_port(ds, port); /* Power down the port memory */ reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL); @@ -692,7 +691,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds) */ for (port = 0; port < ds->num_ports; port++) { if (dsa_is_user_port(ds, port) || dsa_is_cpu_port(ds, port)) - bcm_sf2_port_disable(ds, port, NULL); + bcm_sf2_port_disable(ds, port); } return 0; @@ -788,7 +787,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) else if (dsa_is_cpu_port(ds, port)) bcm_sf2_imp_setup(ds, port); else - bcm_sf2_port_disable(ds, port, NULL); + bcm_sf2_port_disable(ds, port); } b53_configure_vlan(ds); diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index b4f6e1a67dd9..2ffab7ee3d80 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -1091,8 +1091,7 @@ static int lan9303_port_enable(struct dsa_switch *ds, int port, return lan9303_enable_processing_port(chip, port); } -static void lan9303_port_disable(struct dsa_switch *ds, int port, - struct phy_device *phy) +static void lan9303_port_disable(struct dsa_switch *ds, int port) { struct lan9303 *chip = ds->priv; diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 27d092cab40e..ee1455758764 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -480,8 +480,7 @@ static int gswip_port_enable(struct dsa_switch *ds, int port, return 0; } -static void gswip_port_disable(struct dsa_switch *ds, int port, - struct phy_device *phy) +static void gswip_port_disable(struct dsa_switch *ds, int port) { struct gswip_priv *priv = ds->priv; @@ -549,7 +548,7 @@ static int gswip_setup(struct dsa_switch *ds) /* disable port fetch/store dma on all ports */ for (i = 0; i < priv->hw_info->max_ports; i++) - gswip_port_disable(ds, i, NULL); + gswip_port_disable(ds, i); /* enable Switch */ gswip_mdio_mask(priv, 0, GSWIP_MDIO_GLOB_ENABLE, GSWIP_MDIO_GLOB); diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index d89c97724c35..9328b88849d2 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -380,7 +380,7 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) } EXPORT_SYMBOL_GPL(ksz_enable_port); -void ksz_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy) +void ksz_disable_port(struct dsa_switch *ds, int port) { struct ksz_device *dev = ds->priv; diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 0d25bc44f453..21cd794e18f1 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -35,7 +35,7 @@ void ksz_port_mdb_add(struct dsa_switch *ds, int port, int ksz_port_mdb_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_mdb *mdb); int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy); -void ksz_disable_port(struct dsa_switch *ds, int port, struct phy_device *phy); +void ksz_disable_port(struct dsa_switch *ds, int port); /* Common register access functions */ diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index c2b61500f958..0390c5e8271a 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -729,8 +729,7 @@ mt7530_port_enable(struct dsa_switch *ds, int port, } static void -mt7530_port_disable(struct dsa_switch *ds, int port, - struct phy_device *phy) +mt7530_port_disable(struct dsa_switch *ds, int port) { struct mt7530_priv *priv = ds->priv; @@ -1301,7 +1300,7 @@ mt7530_setup(struct dsa_switch *ds) if (dsa_is_cpu_port(ds, i)) mt7530_cpu_port_enable(priv, i); else - mt7530_port_disable(ds, i, NULL); + mt7530_port_disable(ds, i); } /* Flush the FDB table */ diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index d30336f259ce..0c944ed2173e 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2388,8 +2388,7 @@ static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port, return err; } -static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port, - struct phy_device *phydev) +static void mv88e6xxx_port_disable(struct dsa_switch *ds, int port) { struct mv88e6xxx_chip *chip = ds->priv; diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c index 195a8a87b984..576b37d12a63 100644 --- a/drivers/net/dsa/qca8k.c +++ b/drivers/net/dsa/qca8k.c @@ -801,8 +801,7 @@ qca8k_port_enable(struct dsa_switch *ds, int port, } static void -qca8k_port_disable(struct dsa_switch *ds, int port, - struct phy_device *phy) +qca8k_port_disable(struct dsa_switch *ds, int port) { struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; diff --git a/drivers/net/dsa/rtl8366rb.c b/drivers/net/dsa/rtl8366rb.c index a4d5049df692..40b3974970c6 100644 --- a/drivers/net/dsa/rtl8366rb.c +++ b/drivers/net/dsa/rtl8366rb.c @@ -1073,8 +1073,7 @@ rtl8366rb_port_enable(struct dsa_switch *ds, int port, } static void -rtl8366rb_port_disable(struct dsa_switch *ds, int port, - struct phy_device *phy) +rtl8366rb_port_disable(struct dsa_switch *ds, int port) { struct realtek_smi *smi = ds->priv; int ret; diff --git a/drivers/net/dsa/vitesse-vsc73xx.c b/drivers/net/dsa/vitesse-vsc73xx.c index 9f1b5f2e8a64..d4780610ea8a 100644 --- a/drivers/net/dsa/vitesse-vsc73xx.c +++ b/drivers/net/dsa/vitesse-vsc73xx.c @@ -1013,8 +1013,7 @@ static int vsc73xx_port_enable(struct dsa_switch *ds, int port, return 0; } -static void vsc73xx_port_disable(struct dsa_switch *ds, int port, - struct phy_device *phy) +static void vsc73xx_port_disable(struct dsa_switch *ds, int port) { struct vsc73xx *vsc = ds->priv; diff --git a/include/net/dsa.h b/include/net/dsa.h index 2c2c10812814..e8ac5b35ac4a 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -364,8 +364,7 @@ struct dsa_switch_ops { */ int (*port_enable)(struct dsa_switch *ds, int port, struct phy_device *phy); - void (*port_disable)(struct dsa_switch *ds, int port, - struct phy_device *phy); + void (*port_disable)(struct dsa_switch *ds, int port); /* * Port's MAC EEE settings diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 47a1d1379d15..c6caa58c5c71 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -143,7 +143,7 @@ static inline struct net_device *dsa_master_find_slave(struct net_device *dev, int dsa_port_set_state(struct dsa_port *dp, u8 state, struct switchdev_trans *trans); int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy); -void dsa_port_disable(struct dsa_port *dp, struct phy_device *phy); +void dsa_port_disable(struct dsa_port *dp); int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br); void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br); int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, diff --git a/net/dsa/port.c b/net/dsa/port.c index 6b114b045162..a2dad10646cb 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -85,7 +85,7 @@ int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy) return 0; } -void dsa_port_disable(struct dsa_port *dp, struct phy_device *phy) +void dsa_port_disable(struct dsa_port *dp) { struct dsa_switch *ds = dp->ds; int port = dp->index; @@ -94,7 +94,7 @@ void dsa_port_disable(struct dsa_port *dp, struct phy_device *phy) dsa_port_set_state_now(dp, BR_STATE_DISABLED); if (ds->ops->port_disable) - ds->ops->port_disable(ds, port, phy); + ds->ops->port_disable(ds, port); } int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 90629b12beaf..7274499293c9 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -122,7 +122,7 @@ static int dsa_slave_close(struct net_device *dev) phylink_stop(dp->pl); - dsa_port_disable(dp, dev->phydev); + dsa_port_disable(dp); dev_mc_unsync(master, dev); dev_uc_unsync(master, dev); -- cgit v1.2.3 From 99be37edeb2fc3c9295abefc498cc3cc37eb8357 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Feb 2019 12:50:28 -0800 Subject: ice: Mark extack argument as __always_unused Commit 87b0984ebfab ("net: Add extack argument to ndo_fdb_add()") in net-next added an extended parameter to the .ndo_fdb_add op and changed ice_fdb_add() accordingly. Update the function header and add the __always_unused attribute to the new parameter to avoid -Wunused-parameter warnings. Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 48f033928aa2..9d266d754445 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2435,11 +2435,12 @@ static void ice_set_rx_mode(struct net_device *netdev) * @addr: the MAC address entry being added * @vid: VLAN id * @flags: instructions from stack about fdb operation + * @extack: netlink extended ack */ -static int ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[], - struct net_device *dev, const unsigned char *addr, - u16 vid, u16 flags, - struct netlink_ext_ack *extack) +static int +ice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[], + struct net_device *dev, const unsigned char *addr, u16 vid, + u16 flags, struct netlink_ext_ack __always_unused *extack) { int err; -- cgit v1.2.3 From 5ed5d316d90b1487c51b8973c2b845495f3558c0 Mon Sep 17 00:00:00 2001 From: Maciej Fijalkowski Date: Fri, 8 Feb 2019 12:50:29 -0800 Subject: ice: Fix the calculation of ICE_MAX_MTU Currently ICE_MAX_MTU subtracts only ETH_HLEN from max frame size and adds ETH_FCS_LEN and VLAN_HLEN, which is not what was intended. The ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN expression should be surrounded with parentheses. Wrap mentioned expression and take into account VLAN double tagging. Signed-off-by: Maciej Fijalkowski Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 55944e089558..89440775aea1 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -83,7 +83,7 @@ extern const char ice_drv_ver[]; #define ICE_DFLT_NETIF_M (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) #define ICE_MAX_MTU (ICE_AQ_SET_MAC_FRAME_SIZE_MAX - \ - ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN) + (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2))) #define ICE_UP_TABLE_TRANSLATE(val, i) \ (((val) << ICE_AQ_VSI_UP_TABLE_UP##i##_S) & \ -- cgit v1.2.3 From 0e8fd74df2f37e2dcc305ed22f4feb8587b91929 Mon Sep 17 00:00:00 2001 From: Victor Raj Date: Fri, 8 Feb 2019 12:50:30 -0800 Subject: ice: Fix added in VSI supported nodes calc VSI supported nodes are calculated in order to add the VSI parent or intermediate nodes to the scheduler tree. If one of the node in below layers (from VSI layer) has space to add the new VSI or intermediate node above that layer then it's not required to continue the calculation further for below layers. Signed-off-by: Victor Raj Reviewed-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_sched.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index fb38e8be1e2e..81fb7d19c0fd 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -1344,9 +1344,14 @@ ice_sched_calc_vsi_support_nodes(struct ice_hw *hw, node = node->sibling; } + /* tree has one intermediate node to add this new VSI. + * So no need to calculate supported nodes for below + * layers. + */ + if (node) + break; /* all the nodes are full, allocate a new one */ - if (!node) - num_nodes[i]++; + num_nodes[i]++; } } -- cgit v1.2.3 From c6dfd690f1c333475db1833ef3b5a4f4d6ba7365 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Feb 2019 12:50:31 -0800 Subject: ice: sizeof() should be avoided With sizeof(), it is preferable to use the variable of type instead of sizeof(). There are multiple places where a temporary variable is used to hold a 'size' value which is then used for a subsequent alloc/memset. Get rid of the temporary variable by calculating size as part of the alloc/memset statement. Also remove unnecessary type-cast. Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 15 +++++++-------- drivers/net/ethernet/intel/ice/ice_lib.c | 10 +++++----- drivers/net/ethernet/intel/ice/ice_main.c | 23 +++++++++++------------ drivers/net/ethernet/intel/ice/ice_sched.c | 9 ++++----- drivers/net/ethernet/intel/ice/ice_switch.c | 2 +- drivers/net/ethernet/intel/ice/ice_txrx.c | 24 ++++++++++-------------- 6 files changed, 38 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index a82f0202652d..a93daf660171 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -1084,7 +1084,7 @@ ice_get_settings_link_up(struct ethtool_link_ksettings *ks, * current PHY type, get what is supported by the NVM and intersect * them to get what is truly supported */ - memset(&cap_ksettings, 0, sizeof(struct ethtool_link_ksettings)); + memset(&cap_ksettings, 0, sizeof(cap_ksettings)); ice_phy_type_to_ethtool(netdev, &cap_ksettings); ethtool_intersect_link_masks(ks, &cap_ksettings); @@ -1416,7 +1416,7 @@ ice_set_link_ksettings(struct net_device *netdev, return -EOPNOTSUPP; /* copy the ksettings to copy_ks to avoid modifying the original */ - memcpy(©_ks, ks, sizeof(struct ethtool_link_ksettings)); + memcpy(©_ks, ks, sizeof(copy_ks)); /* save autoneg out of ksettings */ autoneg = copy_ks.base.autoneg; @@ -1435,7 +1435,7 @@ ice_set_link_ksettings(struct net_device *netdev, return -EINVAL; /* get our own copy of the bits to check against */ - memset(&safe_ks, 0, sizeof(struct ethtool_link_ksettings)); + memset(&safe_ks, 0, sizeof(safe_ks)); safe_ks.base.cmd = copy_ks.base.cmd; safe_ks.base.link_mode_masks_nwords = copy_ks.base.link_mode_masks_nwords; @@ -1449,8 +1449,7 @@ ice_set_link_ksettings(struct net_device *netdev, /* If copy_ks.base and safe_ks.base are not the same now, then they are * trying to set something that we do not support. */ - if (memcmp(©_ks.base, &safe_ks.base, - sizeof(struct ethtool_link_settings))) + if (memcmp(©_ks.base, &safe_ks.base, sizeof(copy_ks.base))) return -EOPNOTSUPP; while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { @@ -1474,7 +1473,7 @@ ice_set_link_ksettings(struct net_device *netdev, } /* Copy abilities to config in case autoneg is not set below */ - memset(&config, 0, sizeof(struct ice_aqc_set_phy_cfg_data)); + memset(&config, 0, sizeof(config)); config.caps = abilities->caps & ~ICE_AQC_PHY_AN_MODE; if (abilities->caps & ICE_AQC_PHY_AN_MODE) config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; @@ -1668,7 +1667,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) vsi->tx_rings[0]->count, new_tx_cnt); tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, - sizeof(struct ice_ring), GFP_KERNEL); + sizeof(*tx_rings), GFP_KERNEL); if (!tx_rings) { err = -ENOMEM; goto done; @@ -1700,7 +1699,7 @@ process_rx: vsi->rx_rings[0]->count, new_rx_cnt); rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, - sizeof(struct ice_ring), GFP_KERNEL); + sizeof(*rx_rings), GFP_KERNEL); if (!rx_rings) { err = -ENOMEM; goto done; diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 27c3760ae5cb..82aae530d6c5 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -249,12 +249,12 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi, bool alloc_qvectors) /* allocate memory for both Tx and Rx ring pointers */ vsi->tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, - sizeof(struct ice_ring *), GFP_KERNEL); + sizeof(*vsi->tx_rings), GFP_KERNEL); if (!vsi->tx_rings) goto err_txrings; vsi->rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, - sizeof(struct ice_ring *), GFP_KERNEL); + sizeof(*vsi->rx_rings), GFP_KERNEL); if (!vsi->rx_rings) goto err_rxrings; @@ -262,7 +262,7 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi, bool alloc_qvectors) /* allocate memory for q_vector pointers */ vsi->q_vectors = devm_kcalloc(&pf->pdev->dev, vsi->num_q_vectors, - sizeof(struct ice_q_vector *), + sizeof(*vsi->q_vectors), GFP_KERNEL); if (!vsi->q_vectors) goto err_vectors; @@ -355,7 +355,7 @@ void ice_vsi_delete(struct ice_vsi *vsi) ctxt.vf_num = vsi->vf_id; ctxt.vsi_num = vsi->vsi_num; - memcpy(&ctxt.info, &vsi->info, sizeof(struct ice_aqc_vsi_props)); + memcpy(&ctxt.info, &vsi->info, sizeof(ctxt.info)); status = ice_free_vsi(&pf->hw, vsi->idx, &ctxt, false, NULL); if (status) @@ -1620,7 +1620,7 @@ ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings, int offset) u16 buf_len, i, pf_q; int err = 0, tc; - buf_len = sizeof(struct ice_aqc_add_tx_qgrp); + buf_len = sizeof(*qg_buf); qg_buf = devm_kzalloc(&pf->pdev->dev, buf_len, GFP_KERNEL); if (!qg_buf) return -ENOMEM; diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 9d266d754445..0731b8994958 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1513,8 +1513,8 @@ static int ice_cfg_netdev(struct ice_vsi *vsi) u8 mac_addr[ETH_ALEN]; int err; - netdev = alloc_etherdev_mqs(sizeof(struct ice_netdev_priv), - vsi->alloc_txq, vsi->alloc_rxq); + netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq, + vsi->alloc_rxq); if (!netdev) return -ENOMEM; @@ -1867,7 +1867,7 @@ static int ice_ena_msix_range(struct ice_pf *pf) v_left -= pf->num_lan_msix; pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget, - sizeof(struct msix_entry), GFP_KERNEL); + sizeof(*pf->msix_entries), GFP_KERNEL); if (!pf->msix_entries) { err = -ENOMEM; @@ -1955,7 +1955,6 @@ static void ice_clear_interrupt_scheme(struct ice_pf *pf) static int ice_init_interrupt_scheme(struct ice_pf *pf) { int vectors = 0, hw_vectors = 0; - ssize_t size; if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) vectors = ice_ena_msix_range(pf); @@ -1966,9 +1965,9 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf) return vectors; /* set up vector assignment tracking */ - size = sizeof(struct ice_res_tracker) + (sizeof(u16) * vectors); - - pf->sw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL); + pf->sw_irq_tracker = + devm_kzalloc(&pf->pdev->dev, sizeof(*pf->sw_irq_tracker) + + (sizeof(u16) * vectors), GFP_KERNEL); if (!pf->sw_irq_tracker) { ice_dis_msix(pf); return -ENOMEM; @@ -1980,9 +1979,9 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf) /* set up HW vector assignment tracking */ hw_vectors = pf->hw.func_caps.common_cap.num_msix_vectors; - size = sizeof(struct ice_res_tracker) + (sizeof(u16) * hw_vectors); - - pf->hw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL); + pf->hw_irq_tracker = + devm_kzalloc(&pf->pdev->dev, sizeof(*pf->hw_irq_tracker) + + (sizeof(u16) * hw_vectors), GFP_KERNEL); if (!pf->hw_irq_tracker) { ice_clear_interrupt_scheme(pf); return -ENOMEM; @@ -2116,7 +2115,7 @@ static int ice_probe(struct pci_dev *pdev, } pf->vsi = devm_kcalloc(&pdev->dev, pf->num_alloc_vsi, - sizeof(struct ice_vsi *), GFP_KERNEL); + sizeof(*pf->vsi), GFP_KERNEL); if (!pf->vsi) { err = -ENOMEM; goto err_init_pf_unroll; @@ -2148,7 +2147,7 @@ static int ice_probe(struct pci_dev *pdev, } /* create switch struct for the switch element created by FW on boot */ - pf->first_sw = devm_kzalloc(&pdev->dev, sizeof(struct ice_sw), + pf->first_sw = devm_kzalloc(&pdev->dev, sizeof(*pf->first_sw), GFP_KERNEL); if (!pf->first_sw) { err = -ENOMEM; diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index 81fb7d19c0fd..f355f59d8b64 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -1066,11 +1066,10 @@ enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw) hw->max_children[i] = le16_to_cpu(max_sibl); } - hw->layer_info = (struct ice_aqc_layer_props *) - devm_kmemdup(ice_hw_to_dev(hw), buf->layer_props, - (hw->num_tx_sched_layers * - sizeof(*hw->layer_info)), - GFP_KERNEL); + hw->layer_info = devm_kmemdup(ice_hw_to_dev(hw), buf->layer_props, + (hw->num_tx_sched_layers * + sizeof(*hw->layer_info)), + GFP_KERNEL); if (!hw->layer_info) { status = ICE_ERR_NO_MEMORY; goto sched_query_out; diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 2e5693107fa4..d560a8aa5015 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -98,7 +98,7 @@ enum ice_status ice_init_def_sw_recp(struct ice_hw *hw) u8 i; recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES, - sizeof(struct ice_sw_recipe), GFP_KERNEL); + sizeof(*recps), GFP_KERNEL); if (!recps) return ICE_ERR_NO_MEMORY; diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 2357fcac996b..67d129bfe489 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -48,7 +48,6 @@ static struct netdev_queue *txring_txq(const struct ice_ring *ring) */ void ice_clean_tx_ring(struct ice_ring *tx_ring) { - unsigned long size; u16 i; /* ring already cleared, nothing to do */ @@ -59,8 +58,7 @@ void ice_clean_tx_ring(struct ice_ring *tx_ring) for (i = 0; i < tx_ring->count; i++) ice_unmap_and_free_tx_buf(tx_ring, &tx_ring->tx_buf[i]); - size = sizeof(struct ice_tx_buf) * tx_ring->count; - memset(tx_ring->tx_buf, 0, size); + memset(tx_ring->tx_buf, 0, sizeof(*tx_ring->tx_buf) * tx_ring->count); /* Zero out the descriptor ring */ memset(tx_ring->desc, 0, tx_ring->size); @@ -226,21 +224,21 @@ static bool ice_clean_tx_irq(struct ice_vsi *vsi, struct ice_ring *tx_ring, int ice_setup_tx_ring(struct ice_ring *tx_ring) { struct device *dev = tx_ring->dev; - int bi_size; if (!dev) return -ENOMEM; /* warn if we are about to overwrite the pointer */ WARN_ON(tx_ring->tx_buf); - bi_size = sizeof(struct ice_tx_buf) * tx_ring->count; - tx_ring->tx_buf = devm_kzalloc(dev, bi_size, GFP_KERNEL); + tx_ring->tx_buf = + devm_kzalloc(dev, sizeof(*tx_ring->tx_buf) * tx_ring->count, + GFP_KERNEL); if (!tx_ring->tx_buf) return -ENOMEM; /* round up to nearest 4K */ - tx_ring->size = tx_ring->count * sizeof(struct ice_tx_desc); - tx_ring->size = ALIGN(tx_ring->size, 4096); + tx_ring->size = ALIGN(tx_ring->count * sizeof(struct ice_tx_desc), + 4096); tx_ring->desc = dmam_alloc_coherent(dev, tx_ring->size, &tx_ring->dma, GFP_KERNEL); if (!tx_ring->desc) { @@ -267,7 +265,6 @@ err: void ice_clean_rx_ring(struct ice_ring *rx_ring) { struct device *dev = rx_ring->dev; - unsigned long size; u16 i; /* ring already cleared, nothing to do */ @@ -292,8 +289,7 @@ void ice_clean_rx_ring(struct ice_ring *rx_ring) rx_buf->page_offset = 0; } - size = sizeof(struct ice_rx_buf) * rx_ring->count; - memset(rx_ring->rx_buf, 0, size); + memset(rx_ring->rx_buf, 0, sizeof(*rx_ring->rx_buf) * rx_ring->count); /* Zero out the descriptor ring */ memset(rx_ring->desc, 0, rx_ring->size); @@ -331,15 +327,15 @@ void ice_free_rx_ring(struct ice_ring *rx_ring) int ice_setup_rx_ring(struct ice_ring *rx_ring) { struct device *dev = rx_ring->dev; - int bi_size; if (!dev) return -ENOMEM; /* warn if we are about to overwrite the pointer */ WARN_ON(rx_ring->rx_buf); - bi_size = sizeof(struct ice_rx_buf) * rx_ring->count; - rx_ring->rx_buf = devm_kzalloc(dev, bi_size, GFP_KERNEL); + rx_ring->rx_buf = + devm_kzalloc(dev, sizeof(*rx_ring->rx_buf) * rx_ring->count, + GFP_KERNEL); if (!rx_ring->rx_buf) return -ENOMEM; -- cgit v1.2.3 From 198a666a4543be1a6e48f4b701dd3bd9387d37c3 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Feb 2019 12:50:32 -0800 Subject: ice: fix stack hogs from struct ice_vsi_ctx structures struct ice_vsi_ctx has gotten large enough that function local declarations of it on the stack are causing stack hogs. Fix that by allocating the structs on heap. Cleanup some formatting issues in the code around these changes and fix incorrect data type uses of returned functions in a couple places. Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 98 +++++++++++++++--------- drivers/net/ethernet/intel/ice/ice_main.c | 27 ++++--- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 59 ++++++++------ 3 files changed, 117 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 82aae530d6c5..d93a0d5a783c 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -348,19 +348,25 @@ static int ice_get_free_slot(void *array, int size, int curr) void ice_vsi_delete(struct ice_vsi *vsi) { struct ice_pf *pf = vsi->back; - struct ice_vsi_ctx ctxt; + struct ice_vsi_ctx *ctxt; enum ice_status status; + ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); + if (!ctxt) + return; + if (vsi->type == ICE_VSI_VF) - ctxt.vf_num = vsi->vf_id; - ctxt.vsi_num = vsi->vsi_num; + ctxt->vf_num = vsi->vf_id; + ctxt->vsi_num = vsi->vsi_num; - memcpy(&ctxt.info, &vsi->info, sizeof(ctxt.info)); + memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info)); - status = ice_free_vsi(&pf->hw, vsi->idx, &ctxt, false, NULL); + status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL); if (status) dev_err(&pf->pdev->dev, "Failed to delete VSI %i in FW\n", vsi->vsi_num); + + devm_kfree(&pf->pdev->dev, ctxt); } /** @@ -908,37 +914,41 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) */ static int ice_vsi_init(struct ice_vsi *vsi) { - struct ice_vsi_ctx ctxt = { 0 }; struct ice_pf *pf = vsi->back; struct ice_hw *hw = &pf->hw; + struct ice_vsi_ctx *ctxt; int ret = 0; + ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); + if (!ctxt) + return -ENOMEM; + switch (vsi->type) { case ICE_VSI_PF: - ctxt.flags = ICE_AQ_VSI_TYPE_PF; + ctxt->flags = ICE_AQ_VSI_TYPE_PF; break; case ICE_VSI_VF: - ctxt.flags = ICE_AQ_VSI_TYPE_VF; + ctxt->flags = ICE_AQ_VSI_TYPE_VF; /* VF number here is the absolute VF number (0-255) */ - ctxt.vf_num = vsi->vf_id + hw->func_caps.vf_base_id; + ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id; break; default: return -ENODEV; } - ice_set_dflt_vsi_ctx(&ctxt); + ice_set_dflt_vsi_ctx(ctxt); /* if the switch is in VEB mode, allow VSI loopback */ if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB) - ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; + ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; /* Set LUT type and HASH type if RSS is enabled */ if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) - ice_set_rss_vsi_ctx(&ctxt, vsi); + ice_set_rss_vsi_ctx(ctxt, vsi); - ctxt.info.sw_id = vsi->port_info->sw_id; - ice_vsi_setup_q_map(vsi, &ctxt); + ctxt->info.sw_id = vsi->port_info->sw_id; + ice_vsi_setup_q_map(vsi, ctxt); - ret = ice_add_vsi(hw, vsi->idx, &ctxt, NULL); + ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL); if (ret) { dev_err(&pf->pdev->dev, "Add VSI failed, err %d\n", ret); @@ -946,11 +956,12 @@ static int ice_vsi_init(struct ice_vsi *vsi) } /* keep context for update VSI operations */ - vsi->info = ctxt.info; + vsi->info = ctxt->info; /* record VSI number returned */ - vsi->vsi_num = ctxt.vsi_num; + vsi->vsi_num = ctxt->vsi_num; + devm_kfree(&pf->pdev->dev, ctxt); return ret; } @@ -1823,26 +1834,34 @@ int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) { struct device *dev = &vsi->back->pdev->dev; struct ice_hw *hw = &vsi->back->hw; - struct ice_vsi_ctx ctxt = { 0 }; + struct ice_vsi_ctx *ctxt; enum ice_status status; + int ret = 0; + + ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); + if (!ctxt) + return -ENOMEM; /* Here we are configuring the VSI to let the driver add VLAN tags by * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag * insertion happens in the Tx hot path, in ice_tx_map. */ - ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; + ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; - ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); + ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); - status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL); + status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); if (status) { dev_err(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n", status, hw->adminq.sq_last_status); - return -EIO; + ret = -EIO; + goto out; } - vsi->info.vlan_flags = ctxt.info.vlan_flags; - return 0; + vsi->info.vlan_flags = ctxt->info.vlan_flags; +out: + devm_kfree(dev, ctxt); + return ret; } /** @@ -1854,35 +1873,42 @@ int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) { struct device *dev = &vsi->back->pdev->dev; struct ice_hw *hw = &vsi->back->hw; - struct ice_vsi_ctx ctxt = { 0 }; + struct ice_vsi_ctx *ctxt; enum ice_status status; + int ret = 0; + + ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); + if (!ctxt) + return -ENOMEM; /* Here we are configuring what the VSI should do with the VLAN tag in * the Rx packet. We can either leave the tag in the packet or put it in * the Rx descriptor. */ - if (ena) { + if (ena) /* Strip VLAN tag from Rx packet and put it in the desc */ - ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; - } else { + ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; + else /* Disable stripping. Leave tag in packet */ - ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; - } + ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; /* Allow all packets untagged/tagged */ - ctxt.info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; + ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; - ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); + ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); - status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL); + status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); if (status) { dev_err(dev, "update VSI for VLAN strip failed, ena = %d err %d aq_err %d\n", ena, status, hw->adminq.sq_last_status); - return -EIO; + ret = -EIO; + goto out; } - vsi->info.vlan_flags = ctxt.info.vlan_flags; - return 0; + vsi->info.vlan_flags = ctxt->info.vlan_flags; +out: + devm_kfree(dev, ctxt); + return ret; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 0731b8994958..aff348e42562 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3707,30 +3707,39 @@ static int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode) struct device *dev = &vsi->back->pdev->dev; struct ice_aqc_vsi_props *vsi_props; struct ice_hw *hw = &vsi->back->hw; - struct ice_vsi_ctx ctxt = { 0 }; + struct ice_vsi_ctx *ctxt; enum ice_status status; + int ret = 0; vsi_props = &vsi->info; - ctxt.info = vsi->info; + + ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); + if (!ctxt) + return -ENOMEM; + + ctxt->info = vsi->info; if (bmode == BRIDGE_MODE_VEB) /* change from VEPA to VEB mode */ - ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; + ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; else /* change from VEB to VEPA mode */ - ctxt.info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB; - ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); + ctxt->info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB; + ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); - status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL); + status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); if (status) { dev_err(dev, "update VSI for bridge mode failed, bmode = %d err %d aq_err %d\n", bmode, status, hw->adminq.sq_last_status); - return -EIO; + ret = -EIO; + goto out; } /* Update sw flags for book keeping */ - vsi_props->sw_flags = ctxt.info.sw_flags; + vsi_props->sw_flags = ctxt->info.sw_flags; - return 0; +out: + devm_kfree(dev, ctxt); + return ret; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 80b50e67cbef..79d793a76042 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -345,25 +345,33 @@ static int ice_vsi_set_pvid(struct ice_vsi *vsi, u16 vid) { struct device *dev = &vsi->back->pdev->dev; struct ice_hw *hw = &vsi->back->hw; - struct ice_vsi_ctx ctxt = { 0 }; + struct ice_vsi_ctx *ctxt; enum ice_status status; + int ret = 0; + + ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); + if (!ctxt) + return -ENOMEM; - ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_UNTAGGED | - ICE_AQ_VSI_PVLAN_INSERT_PVID | - ICE_AQ_VSI_VLAN_EMOD_STR; - ctxt.info.pvid = cpu_to_le16(vid); - ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); + ctxt->info.vlan_flags = (ICE_AQ_VSI_VLAN_MODE_UNTAGGED | + ICE_AQ_VSI_PVLAN_INSERT_PVID | + ICE_AQ_VSI_VLAN_EMOD_STR); + ctxt->info.pvid = cpu_to_le16(vid); + ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); - status = ice_update_vsi(hw, vsi->idx, &ctxt, NULL); + status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); if (status) { dev_info(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n", status, hw->adminq.sq_last_status); - return -EIO; + ret = -EIO; + goto out; } - vsi->info.pvid = ctxt.info.pvid; - vsi->info.vlan_flags = ctxt.info.vlan_flags; - return 0; + vsi->info.pvid = ctxt->info.pvid; + vsi->info.vlan_flags = ctxt->info.vlan_flags; +out: + devm_kfree(dev, ctxt); + return ret; } /** @@ -2479,11 +2487,12 @@ int ice_get_vf_cfg(struct net_device *netdev, int vf_id, int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena) { struct ice_netdev_priv *np = netdev_priv(netdev); - struct ice_vsi_ctx ctx = { 0 }; struct ice_vsi *vsi = np->vsi; struct ice_pf *pf = vsi->back; + struct ice_vsi_ctx *ctx; + enum ice_status status; struct ice_vf *vf; - int status; + int ret = 0; /* validate the request */ if (vf_id >= pf->num_alloc_vfs) { @@ -2503,25 +2512,31 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena) return 0; } - ctx.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); + ctx = devm_kzalloc(&pf->pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); if (ena) { - ctx.info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF; - ctx.info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_M; + ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF; + ctx->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_PRUNE_EN_M; } - status = ice_update_vsi(&pf->hw, vsi->idx, &ctx, NULL); + status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL); if (status) { dev_dbg(&pf->pdev->dev, "Error %d, failed to update VSI* parameters\n", status); - return -EIO; + ret = -EIO; + goto out; } vf->spoofchk = ena; - vsi->info.sec_flags = ctx.info.sec_flags; - vsi->info.sw_flags2 = ctx.info.sw_flags2; - - return status; + vsi->info.sec_flags = ctx->info.sec_flags; + vsi->info.sw_flags2 = ctx->info.sw_flags2; +out: + devm_kfree(&pf->pdev->dev, ctx); + return ret; } /** -- cgit v1.2.3 From f9264dd687f8d3f9104c9900f8f3e5e419f27c55 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 8 Feb 2019 12:50:33 -0800 Subject: ice: fix ice_remove_rule_internal vsi_list handling When adding multiple VLANs to the same VSI, the ice_add_vlan code will share the VSI list, so as not to create multiple unnecessary VSI lists. Consider the following flow ice_add_vlan(hw, ) Where we add three VLAN filters for VIDs 7, 8, and 9, all for VSI 0. The ice_add_vlan will create a single vsi_list and share it among all the filters. Later, if we try to remove a VLAN, ice_remove_vlan(hw, ) Then the removal code will update the vsi_list and remove VSI 0 from it. But, since the vsi_list is shared, this breaks the list for the other users who reference it. We actually even free the VSI list memory, and may result in segmentation faults. This is due to the way that VLAN rule share VSI lists with reference counts, and is caused because we call ice_rem_update_vsi_list even when the ref_cnt is greater than one. To fix this, handle the case where ref_cnt is greater than one separately. In this case, we need to remove the associated rule without modifying the vsi_list, since it is currently being referenced by another rule. Instead, we just need to decrement the VSI list ref_cnt. The case for handling sharing of VSI lists with multiple VSIs is not currently supported by this code. No such rules will be created today, and this code will require changes if/when such code is added. Signed-off-by: Jacob Keller Reviewed-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_switch.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index d560a8aa5015..09d1c314b68f 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -1538,9 +1538,20 @@ ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id, } else if (!list_elem->vsi_list_info) { status = ICE_ERR_DOES_NOT_EXIST; goto exit; + } else if (list_elem->vsi_list_info->ref_cnt > 1) { + /* a ref_cnt > 1 indicates that the vsi_list is being + * shared by multiple rules. Decrement the ref_cnt and + * remove this rule, but do not modify the list, as it + * is in-use by other rules. + */ + list_elem->vsi_list_info->ref_cnt--; + remove_rule = true; } else { - if (list_elem->vsi_list_info->ref_cnt > 1) - list_elem->vsi_list_info->ref_cnt--; + /* a ref_cnt of 1 indicates the vsi_list is only used + * by one rule. However, the original removal request is only + * for a single VSI. Update the vsi_list first, and only + * remove the rule if there are no further VSIs in this list. + */ vsi_handle = f_entry->fltr_info.vsi_handle; status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); if (status) -- cgit v1.2.3 From 0e04e8e14b558c84a7c7a64d3e94655f5071eef5 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Fri, 8 Feb 2019 12:50:34 -0800 Subject: ice: fix issue where host reboots on unload when iommu=on Currently if the kernel has the intel_iommu=on parameter set, on some platforms removing the driver causes a system reboot. In initialization we associate the control queue interrupts with the pf->hw_oicr_idx and enable the interrupts by setting the CAUSE_ENA bit. The problem comes on teardown because we are not clearing the CAUSE_ENA bit for the control queues, but the vector at pf->hw_oicr_idx (miscellaneous interrupt vector) gets disabled. Fix this by clearing the CAUSE_ENA bit in the appropriate control queue registers on when freeing the miscellaneous interrupt vector. Also, move the call to ice_free_irq_msix_misc() to after ice_deinit_sw() in ice_remove() because ice_deinit_sw() makes an AQ call, but ice_free_irq_msix_misc() disables the miscellaneous vector and it's associated interrupts. Also, create two small helper functions to enable and disable the control queue interrupts respectively. Signed-off-by: Brett Creeley Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_main.c | 71 +++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index aff348e42562..fb04a5ebdc0b 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1355,15 +1355,40 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) return ret; } +/** + * ice_dis_ctrlq_interrupts - disable control queue interrupts + * @hw: pointer to HW structure + */ +static void ice_dis_ctrlq_interrupts(struct ice_hw *hw) +{ + /* disable Admin queue Interrupt causes */ + wr32(hw, PFINT_FW_CTL, + rd32(hw, PFINT_FW_CTL) & ~PFINT_FW_CTL_CAUSE_ENA_M); + + /* disable Mailbox queue Interrupt causes */ + wr32(hw, PFINT_MBX_CTL, + rd32(hw, PFINT_MBX_CTL) & ~PFINT_MBX_CTL_CAUSE_ENA_M); + + /* disable Control queue Interrupt causes */ + wr32(hw, PFINT_OICR_CTL, + rd32(hw, PFINT_OICR_CTL) & ~PFINT_OICR_CTL_CAUSE_ENA_M); + + ice_flush(hw); +} + /** * ice_free_irq_msix_misc - Unroll misc vector setup * @pf: board private structure */ static void ice_free_irq_msix_misc(struct ice_pf *pf) { + struct ice_hw *hw = &pf->hw; + + ice_dis_ctrlq_interrupts(hw); + /* disable OICR interrupt */ - wr32(&pf->hw, PFINT_OICR_ENA, 0); - ice_flush(&pf->hw); + wr32(hw, PFINT_OICR_ENA, 0); + ice_flush(hw); if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) { synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector); @@ -1377,6 +1402,32 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf) ice_free_res(pf->hw_irq_tracker, pf->hw_oicr_idx, ICE_RES_MISC_VEC_ID); } +/** + * ice_ena_ctrlq_interrupts - enable control queue interrupts + * @hw: pointer to HW structure + * @v_idx: HW vector index to associate the control queue interrupts with + */ +static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 v_idx) +{ + u32 val; + + val = ((v_idx & PFINT_OICR_CTL_MSIX_INDX_M) | + PFINT_OICR_CTL_CAUSE_ENA_M); + wr32(hw, PFINT_OICR_CTL, val); + + /* enable Admin queue Interrupt causes */ + val = ((v_idx & PFINT_FW_CTL_MSIX_INDX_M) | + PFINT_FW_CTL_CAUSE_ENA_M); + wr32(hw, PFINT_FW_CTL, val); + + /* enable Mailbox queue Interrupt causes */ + val = ((v_idx & PFINT_MBX_CTL_MSIX_INDX_M) | + PFINT_MBX_CTL_CAUSE_ENA_M); + wr32(hw, PFINT_MBX_CTL, val); + + ice_flush(hw); +} + /** * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events * @pf: board private structure @@ -1389,7 +1440,6 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) { struct ice_hw *hw = &pf->hw; int oicr_idx, err = 0; - u32 val; if (!pf->int_name[0]) snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", @@ -1438,20 +1488,7 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) skip_req_irq: ice_ena_misc_vector(pf); - val = ((pf->hw_oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) | - PFINT_OICR_CTL_CAUSE_ENA_M); - wr32(hw, PFINT_OICR_CTL, val); - - /* This enables Admin queue Interrupt causes */ - val = ((pf->hw_oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) | - PFINT_FW_CTL_CAUSE_ENA_M); - wr32(hw, PFINT_FW_CTL, val); - - /* This enables Mailbox queue Interrupt causes */ - val = ((pf->hw_oicr_idx & PFINT_MBX_CTL_MSIX_INDX_M) | - PFINT_MBX_CTL_CAUSE_ENA_M); - wr32(hw, PFINT_MBX_CTL, val); - + ice_ena_ctrlq_interrupts(hw, pf->hw_oicr_idx); wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx), ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); -- cgit v1.2.3 From 32a64994dbc3e79250f99802faddc074fa8ce667 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Feb 2019 12:50:35 -0800 Subject: ice: fix numeric overflow warning When compiling and analyzing the driver on newer kernels, a static analyzer warns about the following "numeric overflow" issues: "The result of expression: 'budget-1' generates 4-byte type while casting to a bigger size of 8-byte". "The result of expression: '*words-words_read' generates 4-byte type while casting to a bigger size of 8-byte". Fix them both. Signed-off-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_nvm.c | 7 ++++--- drivers/net/ethernet/intel/ice/ice_txrx.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c index ce64cecdae9c..413fdbbcc4d0 100644 --- a/drivers/net/ethernet/intel/ice/ice_nvm.c +++ b/drivers/net/ethernet/intel/ice/ice_nvm.c @@ -152,9 +152,10 @@ ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) */ off_w = offset % ICE_SR_SECTOR_SIZE_IN_WORDS; read_size = off_w ? - min(*words, - (u16)(ICE_SR_SECTOR_SIZE_IN_WORDS - off_w)) : - min((*words - words_read), ICE_SR_SECTOR_SIZE_IN_WORDS); + min_t(u16, *words, + (ICE_SR_SECTOR_SIZE_IN_WORDS - off_w)) : + min_t(u16, (*words - words_read), + ICE_SR_SECTOR_SIZE_IN_WORDS); /* Check if this is last command, if so set proper flag */ if ((words_read + read_size) >= *words) diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 67d129bfe489..c289d97f477d 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1169,7 +1169,7 @@ int ice_napi_poll(struct napi_struct *napi, int budget) if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) ice_update_ena_itr(vsi, q_vector); - return min(work_done, budget - 1); + return min_t(int, work_done, budget - 1); } /* helper function for building cmd/type/offset */ -- cgit v1.2.3 From b751930c6c21c3a6abc447f4f76fa2c28a11cb91 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Fri, 8 Feb 2019 12:50:36 -0800 Subject: ice: only use the VF for ICE_VSI_VF in ice_vsi_release In ice_vsi_release we are always assigning a value to the local VF variable. Change this to only be assigned if the VSI is a VF VSI. Signed-off-by: Brett Creeley Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_lib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index d93a0d5a783c..fa61203bee26 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2518,13 +2518,15 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi) */ int ice_vsi_release(struct ice_vsi *vsi) { + struct ice_vf *vf = NULL; struct ice_pf *pf; - struct ice_vf *vf; if (!vsi->back) return -ENODEV; pf = vsi->back; - vf = &pf->vf[vsi->vf_id]; + + if (vsi->type == ICE_VSI_VF) + vf = &pf->vf[vsi->vf_id]; /* do not unregister and free netdevs while driver is in the reset * recovery pending state. Since reset/rebuild happens through PF * service task workqueue, its not a good idea to unregister netdev -- cgit v1.2.3 From 4cf7bc0d276ba1fcd1330b83cece162cdf3a482b Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 8 Feb 2019 12:50:37 -0800 Subject: ice: don't spam VFs with link messages Don't send a link message to the VFs unless link actually changes state. This avoids a small timing hole in some VF drivers that can cause an apparent TX hang if they receive a link status message at the wrong time. Although we have fixed the timing hole in the current VF driver, there are still lots of drivers in the field that have this timing hole. Let's not fall into it if we can avoid it. Signed-off-by: Mitch Williams Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index fb04a5ebdc0b..47cc3f905b7f 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -609,7 +609,8 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi) } } - ice_vc_notify_link_state(pf); + if (!new_link_same_as_old && pf->num_alloc_vfs) + ice_vc_notify_link_state(pf); return 0; } -- cgit v1.2.3 From 82ba01282cf857f98d3c622a2780051a2147ae61 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 8 Feb 2019 12:50:38 -0800 Subject: ice: clear VF ARQLEN register on reset On older devices like X710 and X722, the VF's ARQLEN register is cleared on reset, so the VF driver uses that register to detect an unannounced reset. Unfortunately, on devices controlled by ice, this register is NOT cleared on reset. This causes the VF to miss resets, and even on properly-announced resets, the VF driver complains that it didn't see the reset. To fix this, we'll do it in software. When we handle a VF reset (whether triggered by software or VFLR), clear this register after the HW reset is complete. Signed-off-by: Mitch Williams Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_hw_autogen.h | 1 + drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index f9a38f2cd470..6bf5cc064270 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -30,6 +30,7 @@ #define PF_FW_ATQLEN_ATQVFE_M BIT(28) #define PF_FW_ATQLEN_ATQOVFL_M BIT(29) #define PF_FW_ATQLEN_ATQCRIT_M BIT(30) +#define VF_MBX_ARQLEN(_VF) (0x0022BC00 + ((_VF) * 4)) #define PF_FW_ATQLEN_ATQENABLE_M BIT(31) #define PF_FW_ATQT 0x00080400 #define PF_MBX_ARQBAH 0x0022E400 diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 79d793a76042..458e179ea863 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -310,6 +310,11 @@ static void ice_trigger_vf_reset(struct ice_vf *vf, bool is_vflr) */ clear_bit(ICE_VF_STATE_INIT, vf->vf_states); + /* Clear the VF's ARQLEN register. This is how the VF detects reset, + * since the VFGEN_RSTAT register doesn't stick at 0 after reset. + */ + wr32(hw, VF_MBX_ARQLEN(vf_abs_id), 0); + /* In the case of a VFLR, the HW has already reset the VF and we * just need to clean up, so don't hit the VFRTRIG register. */ -- cgit v1.2.3 From 6e9650d533dda4acf8baff7ac4bb5d8193148c37 Mon Sep 17 00:00:00 2001 From: Victor Raj Date: Fri, 8 Feb 2019 12:50:39 -0800 Subject: ice: flush Tx pipe on disable queue timeout Set the flush Tx pipe flag instead of getting an EAGAIN error when FW times out in processing the disable Tx queue command. Signed-off-by: Victor Raj Reviewed-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_common.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index b17ade424423..63f003441300 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -2450,6 +2450,7 @@ ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps, { struct ice_aqc_dis_txqs *cmd; struct ice_aq_desc desc; + enum ice_status status; u16 i, sz = 0; cmd = &desc.params.dis_txqs; @@ -2485,6 +2486,8 @@ ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps, break; } + /* flush pipe on time out */ + cmd->cmd_type |= ICE_AQC_Q_DIS_CMD_FLUSH_PIPE; /* If no queue group info, we are in a reset flow. Issue the AQ */ if (!qg_list) goto do_aq; @@ -2510,7 +2513,17 @@ ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps, return ICE_ERR_PARAM; do_aq: - return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd); + status = ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd); + if (status) { + if (!qg_list) + ice_debug(hw, ICE_DBG_SCHED, "VM%d disable failed %d\n", + vmvf_num, hw->adminq.sq_last_status); + else + ice_debug(hw, ICE_DBG_SCHED, "disable Q %d failed %d\n", + le16_to_cpu(qg_list[0].q_id[0]), + hw->adminq.sq_last_status); + } + return status; } /* End of FW Admin Queue command wrappers */ @@ -2796,8 +2809,12 @@ ice_ena_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_qgrps, /* add the lan q */ status = ice_aq_add_lan_txq(hw, num_qgrps, buf, buf_size, cd); - if (status) + if (status) { + ice_debug(hw, ICE_DBG_SCHED, "enable Q %d failed %d\n", + le16_to_cpu(buf->txqs[0].txq_id), + hw->adminq.sq_last_status); goto ena_txq_exit; + } node.node_teid = buf->txqs[0].q_teid; node.data.elem_type = ICE_AQC_ELEM_TYPE_LEAF; -- cgit v1.2.3 From f70b9d5f4426ceee885cd6799fad4f59d33c1ce7 Mon Sep 17 00:00:00 2001 From: Victor Raj Date: Fri, 8 Feb 2019 12:50:40 -0800 Subject: ice: check for a leaf node presence Check for a leaf node presence for a given VSI. This check is required before removing a VSI since VSIs can't be removed with enabled queues (with leaf nodes) from the FW scheduler tree unless its a reset. Signed-off-by: Victor Raj Reviewed-by: Bruce Allan Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_sched.c | 23 +++++++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_status.h | 1 + 2 files changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c index f355f59d8b64..56049739a250 100644 --- a/drivers/net/ethernet/intel/ice/ice_sched.c +++ b/drivers/net/ethernet/intel/ice/ice_sched.c @@ -1615,6 +1615,23 @@ ice_sched_rm_agg_vsi_info(struct ice_port_info *pi, u16 vsi_handle) } } +/** + * ice_sched_is_leaf_node_present - check for a leaf node in the sub-tree + * @node: pointer to the sub-tree node + * + * This function checks for a leaf node presence in a given sub-tree node. + */ +static bool ice_sched_is_leaf_node_present(struct ice_sched_node *node) +{ + u8 i; + + for (i = 0; i < node->num_children; i++) + if (ice_sched_is_leaf_node_present(node->children[i])) + return true; + /* check for a leaf node */ + return (node->info.data.elem_type == ICE_AQC_ELEM_TYPE_LEAF); +} + /** * ice_sched_rm_vsi_cfg - remove the VSI and its children nodes * @pi: port information structure @@ -1649,6 +1666,12 @@ ice_sched_rm_vsi_cfg(struct ice_port_info *pi, u16 vsi_handle, u8 owner) if (!vsi_node) continue; + if (ice_sched_is_leaf_node_present(vsi_node)) { + ice_debug(pi->hw, ICE_DBG_SCHED, + "VSI has leaf nodes in TC %d\n", i); + status = ICE_ERR_IN_USE; + goto exit_sched_rm_vsi_cfg; + } while (j < vsi_node->num_children) { if (vsi_node->children[j]->owner == owner) { ice_free_sched_node(pi, vsi_node->children[j]); diff --git a/drivers/net/ethernet/intel/ice/ice_status.h b/drivers/net/ethernet/intel/ice/ice_status.h index f49f299ddf2c..683f48824a29 100644 --- a/drivers/net/ethernet/intel/ice/ice_status.h +++ b/drivers/net/ethernet/intel/ice/ice_status.h @@ -22,6 +22,7 @@ enum ice_status { ICE_ERR_OUT_OF_RANGE = -13, ICE_ERR_ALREADY_EXISTS = -14, ICE_ERR_DOES_NOT_EXIST = -15, + ICE_ERR_IN_USE = -16, ICE_ERR_MAX_LIMIT = -17, ICE_ERR_RESET_ONGOING = -18, ICE_ERR_BUF_TOO_SHORT = -52, -- cgit v1.2.3 From f966127a68aa805660c05f2a729997adf93d1937 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 8 Feb 2019 12:50:41 -0800 Subject: ice: use absolute vector ID for VFs When the PF driver sets up the VF MSI-X vector allocation, it needs to use the hardware absolute vector ID, not the per-PF vector ID. Without this change we see (apparent) TX hangs when using VFs on multiple PFs. Signed-off-by: Mitch Williams Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 458e179ea863..57155b4a59dc 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -173,7 +173,8 @@ static void ice_dis_vf_mappings(struct ice_vf *vf) wr32(hw, VPINT_ALLOC(vf->vf_id), 0); wr32(hw, VPINT_ALLOC_PCI(vf->vf_id), 0); - first = vf->first_vector_idx; + first = vf->first_vector_idx + + hw->func_caps.common_cap.msix_vector_first_id; last = first + pf->num_vf_msix - 1; for (v = first; v <= last; v++) { u32 reg; @@ -523,7 +524,8 @@ static void ice_ena_vf_mappings(struct ice_vf *vf) hw = &pf->hw; vsi = pf->vsi[vf->lan_vsi_idx]; - first = vf->first_vector_idx; + first = vf->first_vector_idx + + hw->func_caps.common_cap.msix_vector_first_id; last = (first + pf->num_vf_msix) - 1; abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id; -- cgit v1.2.3 From 40c3c546380c62e325da016c7278e26ad05fa870 Mon Sep 17 00:00:00 2001 From: Lukasz Czapnik Date: Fri, 8 Feb 2019 12:50:42 -0800 Subject: ice: Fix for FC get rx/tx pause params Ethtool reported pause params based on the currently negotiated link settings instead of current PHY config. User was not able to turn off pause params because ethtool was incorrectly reporting parameters as off when link was down even though PHY was configured to support pause frames. Now pause params are taken from PHY config instead of link status. Signed-off-by: Lukasz Czapnik Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 37 +++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index a93daf660171..295571b1c4e8 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -1818,21 +1818,36 @@ static void ice_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { struct ice_netdev_priv *np = netdev_priv(netdev); - struct ice_port_info *pi; + struct ice_port_info *pi = np->vsi->port_info; + struct ice_aqc_get_phy_caps_data *pcaps; + struct ice_vsi *vsi = np->vsi; + enum ice_status status; - pi = np->vsi->port_info; - pause->autoneg = - ((pi->phy.link_info.an_info & ICE_AQ_AN_COMPLETED) ? - AUTONEG_ENABLE : AUTONEG_DISABLE); + /* Initialize pause params */ + pause->rx_pause = 0; + pause->tx_pause = 0; - if (pi->fc.current_mode == ICE_FC_RX_PAUSE) { - pause->rx_pause = 1; - } else if (pi->fc.current_mode == ICE_FC_TX_PAUSE) { + pcaps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*pcaps), + GFP_KERNEL); + if (!pcaps) + return; + + /* Get current phy config */ + status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, + NULL); + if (status) + goto out; + + pause->autoneg = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ? + AUTONEG_ENABLE : AUTONEG_DISABLE); + + if (pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) pause->tx_pause = 1; - } else if (pi->fc.current_mode == ICE_FC_FULL) { + if (pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) pause->rx_pause = 1; - pause->tx_pause = 1; - } + +out: + devm_kfree(&vsi->back->pdev->dev, pcaps); } /** -- cgit v1.2.3 From 1fa6e138ada15ca2db3bb85d569812096ff66094 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 8 Feb 2019 12:50:43 -0800 Subject: ice: fix overlong string, update stats output A test started warning on a string truncation. This led to an unfortunate realization that we are likely not accounting for the stats length correctly before this patch, so fix the issue by putting "port." in front of all the PF stats, instead of magically prepending it at runtime. Signed-off-by: Jesse Brandeburg Signed-off-by: Anirudh Venkataramanan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ice/ice_ethtool.c | 80 ++++++++++++++-------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 295571b1c4e8..eb8d149e317c 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -63,45 +63,45 @@ static const struct ice_stats ice_gstrings_vsi_stats[] = { * is queried on the base PF netdev. */ static const struct ice_stats ice_gstrings_pf_stats[] = { - ICE_PF_STAT("tx_bytes", stats.eth.tx_bytes), - ICE_PF_STAT("rx_bytes", stats.eth.rx_bytes), - ICE_PF_STAT("tx_unicast", stats.eth.tx_unicast), - ICE_PF_STAT("rx_unicast", stats.eth.rx_unicast), - ICE_PF_STAT("tx_multicast", stats.eth.tx_multicast), - ICE_PF_STAT("rx_multicast", stats.eth.rx_multicast), - ICE_PF_STAT("tx_broadcast", stats.eth.tx_broadcast), - ICE_PF_STAT("rx_broadcast", stats.eth.rx_broadcast), - ICE_PF_STAT("tx_errors", stats.eth.tx_errors), - ICE_PF_STAT("tx_size_64", stats.tx_size_64), - ICE_PF_STAT("rx_size_64", stats.rx_size_64), - ICE_PF_STAT("tx_size_127", stats.tx_size_127), - ICE_PF_STAT("rx_size_127", stats.rx_size_127), - ICE_PF_STAT("tx_size_255", stats.tx_size_255), - ICE_PF_STAT("rx_size_255", stats.rx_size_255), - ICE_PF_STAT("tx_size_511", stats.tx_size_511), - ICE_PF_STAT("rx_size_511", stats.rx_size_511), - ICE_PF_STAT("tx_size_1023", stats.tx_size_1023), - ICE_PF_STAT("rx_size_1023", stats.rx_size_1023), - ICE_PF_STAT("tx_size_1522", stats.tx_size_1522), - ICE_PF_STAT("rx_size_1522", stats.rx_size_1522), - ICE_PF_STAT("tx_size_big", stats.tx_size_big), - ICE_PF_STAT("rx_size_big", stats.rx_size_big), - ICE_PF_STAT("link_xon_tx", stats.link_xon_tx), - ICE_PF_STAT("link_xon_rx", stats.link_xon_rx), - ICE_PF_STAT("link_xoff_tx", stats.link_xoff_tx), - ICE_PF_STAT("link_xoff_rx", stats.link_xoff_rx), - ICE_PF_STAT("tx_dropped_link_down", stats.tx_dropped_link_down), - ICE_PF_STAT("rx_undersize", stats.rx_undersize), - ICE_PF_STAT("rx_fragments", stats.rx_fragments), - ICE_PF_STAT("rx_oversize", stats.rx_oversize), - ICE_PF_STAT("rx_jabber", stats.rx_jabber), - ICE_PF_STAT("rx_csum_bad", hw_csum_rx_error), - ICE_PF_STAT("rx_length_errors", stats.rx_len_errors), - ICE_PF_STAT("rx_dropped", stats.eth.rx_discards), - ICE_PF_STAT("rx_crc_errors", stats.crc_errors), - ICE_PF_STAT("illegal_bytes", stats.illegal_bytes), - ICE_PF_STAT("mac_local_faults", stats.mac_local_faults), - ICE_PF_STAT("mac_remote_faults", stats.mac_remote_faults), + ICE_PF_STAT("port.tx_bytes", stats.eth.tx_bytes), + ICE_PF_STAT("port.rx_bytes", stats.eth.rx_bytes), + ICE_PF_STAT("port.tx_unicast", stats.eth.tx_unicast), + ICE_PF_STAT("port.rx_unicast", stats.eth.rx_unicast), + ICE_PF_STAT("port.tx_multicast", stats.eth.tx_multicast), + ICE_PF_STAT("port.rx_multicast", stats.eth.rx_multicast), + ICE_PF_STAT("port.tx_broadcast", stats.eth.tx_broadcast), + ICE_PF_STAT("port.rx_broadcast", stats.eth.rx_broadcast), + ICE_PF_STAT("port.tx_errors", stats.eth.tx_errors), + ICE_PF_STAT("port.tx_size_64", stats.tx_size_64), + ICE_PF_STAT("port.rx_size_64", stats.rx_size_64), + ICE_PF_STAT("port.tx_size_127", stats.tx_size_127), + ICE_PF_STAT("port.rx_size_127", stats.rx_size_127), + ICE_PF_STAT("port.tx_size_255", stats.tx_size_255), + ICE_PF_STAT("port.rx_size_255", stats.rx_size_255), + ICE_PF_STAT("port.tx_size_511", stats.tx_size_511), + ICE_PF_STAT("port.rx_size_511", stats.rx_size_511), + ICE_PF_STAT("port.tx_size_1023", stats.tx_size_1023), + ICE_PF_STAT("port.rx_size_1023", stats.rx_size_1023), + ICE_PF_STAT("port.tx_size_1522", stats.tx_size_1522), + ICE_PF_STAT("port.rx_size_1522", stats.rx_size_1522), + ICE_PF_STAT("port.tx_size_big", stats.tx_size_big), + ICE_PF_STAT("port.rx_size_big", stats.rx_size_big), + ICE_PF_STAT("port.link_xon_tx", stats.link_xon_tx), + ICE_PF_STAT("port.link_xon_rx", stats.link_xon_rx), + ICE_PF_STAT("port.link_xoff_tx", stats.link_xoff_tx), + ICE_PF_STAT("port.link_xoff_rx", stats.link_xoff_rx), + ICE_PF_STAT("port.tx_dropped_link_down", stats.tx_dropped_link_down), + ICE_PF_STAT("port.rx_undersize", stats.rx_undersize), + ICE_PF_STAT("port.rx_fragments", stats.rx_fragments), + ICE_PF_STAT("port.rx_oversize", stats.rx_oversize), + ICE_PF_STAT("port.rx_jabber", stats.rx_jabber), + ICE_PF_STAT("port.rx_csum_bad", hw_csum_rx_error), + ICE_PF_STAT("port.rx_length_errors", stats.rx_len_errors), + ICE_PF_STAT("port.rx_dropped", stats.eth.rx_discards), + ICE_PF_STAT("port.rx_crc_errors", stats.crc_errors), + ICE_PF_STAT("port.illegal_bytes", stats.illegal_bytes), + ICE_PF_STAT("port.mac_local_faults", stats.mac_local_faults), + ICE_PF_STAT("port.mac_remote_faults", stats.mac_remote_faults), }; static const u32 ice_regs_dump_list[] = { @@ -304,7 +304,7 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) return; for (i = 0; i < ICE_PF_STATS_LEN; i++) { - snprintf(p, ETH_GSTRING_LEN, "port.%s", + snprintf(p, ETH_GSTRING_LEN, "%s", ice_gstrings_pf_stats[i].stat_string); p += ETH_GSTRING_LEN; } -- cgit v1.2.3 From 65b034cf5c1766492aa107958149b440889480be Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Mon, 25 Feb 2019 12:39:54 +0100 Subject: net: dsa: mv88e6xxx: Default CMODE to 1000BaseX only on 6390X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 787799a9d555 sets the SERDES interfaces of 6390 and 6390X to 1000BaseX, but this is only needed on 6390X, since there are SERDES interfaces which can be used on lower ports on 6390. This commit fixes this by returning to previous behaviour on 6390. (Previous behaviour means that CMODE is not set at all if requested mode is NA). This is needed on Turris MOX, where the 88e6190 is connected to CPU in 2500BaseX mode. Fixes: 787799a9d555 ("net: dsa: mv88e6xxx: Default ports 9/10 6390X CMODE to 1000BaseX") Signed-off-by: Marek Behún Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/port.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index ebd26b6a93e6..ee7029f4ee22 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -444,6 +444,8 @@ int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port, phy_interface_t mode) { switch (mode) { + case PHY_INTERFACE_MODE_NA: + return 0; case PHY_INTERFACE_MODE_XGMII: case PHY_INTERFACE_MODE_XAUI: case PHY_INTERFACE_MODE_RXAUI: -- cgit v1.2.3 From e3af71a36f9a68bd5d5a63d9960c9b624324784f Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Mon, 25 Feb 2019 12:39:55 +0100 Subject: net: dsa: mv88e6xxx: Fix phylink_validate for Topaz family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Topaz family should have different phylink_validate method from the Peridot, since on Topaz the port supporting 2500BaseX mode is port 5, not 9 and 10. Signed-off-by: Marek Behún Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 0c944ed2173e..a3a2eb985ace 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -658,6 +658,20 @@ static void mv88e6185_phylink_validate(struct mv88e6xxx_chip *chip, int port, mv88e6065_phylink_validate(chip, port, mask, state); } +static void mv88e6341_phylink_validate(struct mv88e6xxx_chip *chip, int port, + unsigned long *mask, + struct phylink_link_state *state) +{ + if (port >= 5) + phylink_set(mask, 2500baseX_Full); + + /* No ethtool bits for 200Mbps */ + phylink_set(mask, 1000baseT_Full); + phylink_set(mask, 1000baseX_Full); + + mv88e6065_phylink_validate(chip, port, mask, state); +} + static void mv88e6352_phylink_validate(struct mv88e6xxx_chip *chip, int port, unsigned long *mask, struct phylink_link_state *state) @@ -3079,7 +3093,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, .serdes_power = mv88e6341_serdes_power, .gpio_ops = &mv88e6352_gpio_ops, - .phylink_validate = mv88e6390_phylink_validate, + .phylink_validate = mv88e6341_phylink_validate, }; static const struct mv88e6xxx_ops mv88e6161_ops = { @@ -3711,7 +3725,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { .gpio_ops = &mv88e6352_gpio_ops, .avb_ops = &mv88e6390_avb_ops, .ptp_ops = &mv88e6352_ptp_ops, - .phylink_validate = mv88e6390_phylink_validate, + .phylink_validate = mv88e6341_phylink_validate, }; static const struct mv88e6xxx_ops mv88e6350_ops = { -- cgit v1.2.3 From b4e6a1021ba27233fd432ee711e5e8f1d86a894e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 25 Feb 2019 19:53:04 +0100 Subject: net: phy: aquantia: rename aquantia.c to aquantia_main.c Rename aquantia.c to aquantia_main.c to be prepared for adding new functionality to separate source code files. Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/Makefile | 1 + drivers/net/phy/aquantia.c | 279 ---------------------------------------- drivers/net/phy/aquantia_main.c | 279 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 279 deletions(-) delete mode 100644 drivers/net/phy/aquantia.c create mode 100644 drivers/net/phy/aquantia_main.c (limited to 'drivers') diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 5805c0b7d60e..b0845adaf804 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -45,6 +45,7 @@ sfp-obj-$(CONFIG_SFP) += sfp-bus.o obj-y += $(sfp-obj-y) $(sfp-obj-m) obj-$(CONFIG_AMD_PHY) += amd.o +aquantia-objs += aquantia_main.o obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o obj-$(CONFIG_ASIX_PHY) += asix.o obj-$(CONFIG_AT803X_PHY) += at803x.o diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c deleted file mode 100644 index 0f0eb568267d..000000000000 --- a/drivers/net/phy/aquantia.c +++ /dev/null @@ -1,279 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Driver for Aquantia PHY - * - * Author: Shaohui Xie - * - * Copyright 2015 Freescale Semiconductor, Inc. - */ - -#include -#include -#include -#include - -#define PHY_ID_AQ1202 0x03a1b445 -#define PHY_ID_AQ2104 0x03a1b460 -#define PHY_ID_AQR105 0x03a1b4a2 -#define PHY_ID_AQR106 0x03a1b4d0 -#define PHY_ID_AQR107 0x03a1b4e0 -#define PHY_ID_AQCS109 0x03a1b5c2 -#define PHY_ID_AQR405 0x03a1b4b0 - -#define MDIO_AN_VEND_PROV 0xc400 -#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) -#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) - -#define MDIO_AN_TX_VEND_STATUS1 0xc800 -#define MDIO_AN_TX_VEND_STATUS1_10BASET (0x0 << 1) -#define MDIO_AN_TX_VEND_STATUS1_100BASETX (0x1 << 1) -#define MDIO_AN_TX_VEND_STATUS1_1000BASET (0x2 << 1) -#define MDIO_AN_TX_VEND_STATUS1_10GBASET (0x3 << 1) -#define MDIO_AN_TX_VEND_STATUS1_2500BASET (0x4 << 1) -#define MDIO_AN_TX_VEND_STATUS1_5000BASET (0x5 << 1) -#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK (0x7 << 1) -#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) - -#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 - -#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 -#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) - -#define MDIO_AN_RX_LP_STAT1 0xe820 -#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) -#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) - -/* Vendor specific 1, MDIO_MMD_VEND1 */ -#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 -#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 - -#define VEND1_GLOBAL_INT_STD_MASK 0xff00 -#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) -#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) -#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) -#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) -#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) -#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) -#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) -#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) -#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) -#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) -#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) - -#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 -#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) -#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) -#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) -#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) -#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) -#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) -#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) -#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) - -static int aqr_config_aneg(struct phy_device *phydev) -{ - bool changed = false; - u16 reg; - int ret; - - if (phydev->autoneg == AUTONEG_DISABLE) - return genphy_c45_pma_setup_forced(phydev); - - ret = genphy_c45_an_config_aneg(phydev); - if (ret < 0) - return ret; - if (ret > 0) - changed = true; - - /* Clause 45 has no standardized support for 1000BaseT, therefore - * use vendor registers for this mode. - */ - reg = 0; - if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - phydev->advertising)) - reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; - - if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, - phydev->advertising)) - reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; - - ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, - MDIO_AN_VEND_PROV_1000BASET_HALF | - MDIO_AN_VEND_PROV_1000BASET_FULL, reg); - if (ret < 0) - return ret; - if (ret > 0) - changed = true; - - return genphy_c45_check_and_restart_aneg(phydev, changed); -} - -static int aqr_config_intr(struct phy_device *phydev) -{ - int err; - - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { - err = phy_write_mmd(phydev, MDIO_MMD_AN, - MDIO_AN_TX_VEND_INT_MASK2, - MDIO_AN_TX_VEND_INT_MASK2_LINK); - if (err < 0) - return err; - - err = phy_write_mmd(phydev, MDIO_MMD_VEND1, - VEND1_GLOBAL_INT_STD_MASK, - VEND1_GLOBAL_INT_STD_MASK_ALL); - if (err < 0) - return err; - - err = phy_write_mmd(phydev, MDIO_MMD_VEND1, - VEND1_GLOBAL_INT_VEND_MASK, - VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | - VEND1_GLOBAL_INT_VEND_MASK_AN); - } else { - err = phy_write_mmd(phydev, MDIO_MMD_AN, - MDIO_AN_TX_VEND_INT_MASK2, 0); - if (err < 0) - return err; - - err = phy_write_mmd(phydev, MDIO_MMD_VEND1, - VEND1_GLOBAL_INT_STD_MASK, 0); - if (err < 0) - return err; - - err = phy_write_mmd(phydev, MDIO_MMD_VEND1, - VEND1_GLOBAL_INT_VEND_MASK, 0); - } - - return err; -} - -static int aqr_ack_interrupt(struct phy_device *phydev) -{ - int reg; - - reg = phy_read_mmd(phydev, MDIO_MMD_AN, - MDIO_AN_TX_VEND_INT_STATUS2); - return (reg < 0) ? reg : 0; -} - -static int aqr_read_status(struct phy_device *phydev) -{ - int val; - - if (phydev->autoneg == AUTONEG_ENABLE) { - val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); - if (val < 0) - return val; - - linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - phydev->lp_advertising, - val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); - linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, - phydev->lp_advertising, - val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); - } - - return genphy_c45_read_status(phydev); -} - -static int aqcs109_config_init(struct phy_device *phydev) -{ - /* AQCS109 belongs to a chip family partially supporting 10G and 5G. - * PMA speed ability bits are the same for all members of the family, - * AQCS109 however supports speeds up to 2.5G only. - */ - return phy_set_max_speed(phydev, SPEED_2500); -} - -static struct phy_driver aqr_driver[] = { -{ - PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), - .name = "Aquantia AQ1202", - .aneg_done = genphy_c45_aneg_done, - .get_features = genphy_c45_pma_read_abilities, - .config_aneg = aqr_config_aneg, - .config_intr = aqr_config_intr, - .ack_interrupt = aqr_ack_interrupt, - .read_status = aqr_read_status, -}, -{ - PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), - .name = "Aquantia AQ2104", - .aneg_done = genphy_c45_aneg_done, - .get_features = genphy_c45_pma_read_abilities, - .config_aneg = aqr_config_aneg, - .config_intr = aqr_config_intr, - .ack_interrupt = aqr_ack_interrupt, - .read_status = aqr_read_status, -}, -{ - PHY_ID_MATCH_MODEL(PHY_ID_AQR105), - .name = "Aquantia AQR105", - .aneg_done = genphy_c45_aneg_done, - .get_features = genphy_c45_pma_read_abilities, - .config_aneg = aqr_config_aneg, - .config_intr = aqr_config_intr, - .ack_interrupt = aqr_ack_interrupt, - .read_status = aqr_read_status, -}, -{ - PHY_ID_MATCH_MODEL(PHY_ID_AQR106), - .name = "Aquantia AQR106", - .aneg_done = genphy_c45_aneg_done, - .get_features = genphy_c45_pma_read_abilities, - .config_aneg = aqr_config_aneg, - .config_intr = aqr_config_intr, - .ack_interrupt = aqr_ack_interrupt, - .read_status = aqr_read_status, -}, -{ - PHY_ID_MATCH_MODEL(PHY_ID_AQR107), - .name = "Aquantia AQR107", - .aneg_done = genphy_c45_aneg_done, - .get_features = genphy_c45_pma_read_abilities, - .config_aneg = aqr_config_aneg, - .config_intr = aqr_config_intr, - .ack_interrupt = aqr_ack_interrupt, - .read_status = aqr_read_status, -}, -{ - PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), - .name = "Aquantia AQCS109", - .aneg_done = genphy_c45_aneg_done, - .get_features = genphy_c45_pma_read_abilities, - .config_init = aqcs109_config_init, - .config_aneg = aqr_config_aneg, - .config_intr = aqr_config_intr, - .ack_interrupt = aqr_ack_interrupt, - .read_status = aqr_read_status, -}, -{ - PHY_ID_MATCH_MODEL(PHY_ID_AQR405), - .name = "Aquantia AQR405", - .aneg_done = genphy_c45_aneg_done, - .get_features = genphy_c45_pma_read_abilities, - .config_aneg = aqr_config_aneg, - .config_intr = aqr_config_intr, - .ack_interrupt = aqr_ack_interrupt, - .read_status = aqr_read_status, -}, -}; - -module_phy_driver(aqr_driver); - -static struct mdio_device_id __maybe_unused aqr_tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, - { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, - { } -}; - -MODULE_DEVICE_TABLE(mdio, aqr_tbl); - -MODULE_DESCRIPTION("Aquantia PHY driver"); -MODULE_AUTHOR("Shaohui Xie "); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c new file mode 100644 index 000000000000..0f0eb568267d --- /dev/null +++ b/drivers/net/phy/aquantia_main.c @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Aquantia PHY + * + * Author: Shaohui Xie + * + * Copyright 2015 Freescale Semiconductor, Inc. + */ + +#include +#include +#include +#include + +#define PHY_ID_AQ1202 0x03a1b445 +#define PHY_ID_AQ2104 0x03a1b460 +#define PHY_ID_AQR105 0x03a1b4a2 +#define PHY_ID_AQR106 0x03a1b4d0 +#define PHY_ID_AQR107 0x03a1b4e0 +#define PHY_ID_AQCS109 0x03a1b5c2 +#define PHY_ID_AQR405 0x03a1b4b0 + +#define MDIO_AN_VEND_PROV 0xc400 +#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15) +#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14) + +#define MDIO_AN_TX_VEND_STATUS1 0xc800 +#define MDIO_AN_TX_VEND_STATUS1_10BASET (0x0 << 1) +#define MDIO_AN_TX_VEND_STATUS1_100BASETX (0x1 << 1) +#define MDIO_AN_TX_VEND_STATUS1_1000BASET (0x2 << 1) +#define MDIO_AN_TX_VEND_STATUS1_10GBASET (0x3 << 1) +#define MDIO_AN_TX_VEND_STATUS1_2500BASET (0x4 << 1) +#define MDIO_AN_TX_VEND_STATUS1_5000BASET (0x5 << 1) +#define MDIO_AN_TX_VEND_STATUS1_RATE_MASK (0x7 << 1) +#define MDIO_AN_TX_VEND_STATUS1_FULL_DUPLEX BIT(0) + +#define MDIO_AN_TX_VEND_INT_STATUS2 0xcc01 + +#define MDIO_AN_TX_VEND_INT_MASK2 0xd401 +#define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0) + +#define MDIO_AN_RX_LP_STAT1 0xe820 +#define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15) +#define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14) + +/* Vendor specific 1, MDIO_MMD_VEND1 */ +#define VEND1_GLOBAL_INT_STD_STATUS 0xfc00 +#define VEND1_GLOBAL_INT_VEND_STATUS 0xfc01 + +#define VEND1_GLOBAL_INT_STD_MASK 0xff00 +#define VEND1_GLOBAL_INT_STD_MASK_PMA1 BIT(15) +#define VEND1_GLOBAL_INT_STD_MASK_PMA2 BIT(14) +#define VEND1_GLOBAL_INT_STD_MASK_PCS1 BIT(13) +#define VEND1_GLOBAL_INT_STD_MASK_PCS2 BIT(12) +#define VEND1_GLOBAL_INT_STD_MASK_PCS3 BIT(11) +#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS1 BIT(10) +#define VEND1_GLOBAL_INT_STD_MASK_PHY_XS2 BIT(9) +#define VEND1_GLOBAL_INT_STD_MASK_AN1 BIT(8) +#define VEND1_GLOBAL_INT_STD_MASK_AN2 BIT(7) +#define VEND1_GLOBAL_INT_STD_MASK_GBE BIT(6) +#define VEND1_GLOBAL_INT_STD_MASK_ALL BIT(0) + +#define VEND1_GLOBAL_INT_VEND_MASK 0xff01 +#define VEND1_GLOBAL_INT_VEND_MASK_PMA BIT(15) +#define VEND1_GLOBAL_INT_VEND_MASK_PCS BIT(14) +#define VEND1_GLOBAL_INT_VEND_MASK_PHY_XS BIT(13) +#define VEND1_GLOBAL_INT_VEND_MASK_AN BIT(12) +#define VEND1_GLOBAL_INT_VEND_MASK_GBE BIT(11) +#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL1 BIT(2) +#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL2 BIT(1) +#define VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 BIT(0) + +static int aqr_config_aneg(struct phy_device *phydev) +{ + bool changed = false; + u16 reg; + int ret; + + if (phydev->autoneg == AUTONEG_DISABLE) + return genphy_c45_pma_setup_forced(phydev); + + ret = genphy_c45_an_config_aneg(phydev); + if (ret < 0) + return ret; + if (ret > 0) + changed = true; + + /* Clause 45 has no standardized support for 1000BaseT, therefore + * use vendor registers for this mode. + */ + reg = 0; + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->advertising)) + reg |= MDIO_AN_VEND_PROV_1000BASET_FULL; + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + phydev->advertising)) + reg |= MDIO_AN_VEND_PROV_1000BASET_HALF; + + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV, + MDIO_AN_VEND_PROV_1000BASET_HALF | + MDIO_AN_VEND_PROV_1000BASET_FULL, reg); + if (ret < 0) + return ret; + if (ret > 0) + changed = true; + + return genphy_c45_check_and_restart_aneg(phydev, changed); +} + +static int aqr_config_intr(struct phy_device *phydev) +{ + int err; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { + err = phy_write_mmd(phydev, MDIO_MMD_AN, + MDIO_AN_TX_VEND_INT_MASK2, + MDIO_AN_TX_VEND_INT_MASK2_LINK); + if (err < 0) + return err; + + err = phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_INT_STD_MASK, + VEND1_GLOBAL_INT_STD_MASK_ALL); + if (err < 0) + return err; + + err = phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_INT_VEND_MASK, + VEND1_GLOBAL_INT_VEND_MASK_GLOBAL3 | + VEND1_GLOBAL_INT_VEND_MASK_AN); + } else { + err = phy_write_mmd(phydev, MDIO_MMD_AN, + MDIO_AN_TX_VEND_INT_MASK2, 0); + if (err < 0) + return err; + + err = phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_INT_STD_MASK, 0); + if (err < 0) + return err; + + err = phy_write_mmd(phydev, MDIO_MMD_VEND1, + VEND1_GLOBAL_INT_VEND_MASK, 0); + } + + return err; +} + +static int aqr_ack_interrupt(struct phy_device *phydev) +{ + int reg; + + reg = phy_read_mmd(phydev, MDIO_MMD_AN, + MDIO_AN_TX_VEND_INT_STATUS2); + return (reg < 0) ? reg : 0; +} + +static int aqr_read_status(struct phy_device *phydev) +{ + int val; + + if (phydev->autoneg == AUTONEG_ENABLE) { + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_RX_LP_STAT1); + if (val < 0) + return val; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->lp_advertising, + val & MDIO_AN_RX_LP_STAT1_1000BASET_FULL); + linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + phydev->lp_advertising, + val & MDIO_AN_RX_LP_STAT1_1000BASET_HALF); + } + + return genphy_c45_read_status(phydev); +} + +static int aqcs109_config_init(struct phy_device *phydev) +{ + /* AQCS109 belongs to a chip family partially supporting 10G and 5G. + * PMA speed ability bits are the same for all members of the family, + * AQCS109 however supports speeds up to 2.5G only. + */ + return phy_set_max_speed(phydev, SPEED_2500); +} + +static struct phy_driver aqr_driver[] = { +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQ1202), + .name = "Aquantia AQ1202", + .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, +}, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQ2104), + .name = "Aquantia AQ2104", + .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, +}, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR105), + .name = "Aquantia AQR105", + .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, +}, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR106), + .name = "Aquantia AQR106", + .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, +}, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR107), + .name = "Aquantia AQR107", + .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, +}, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQCS109), + .name = "Aquantia AQCS109", + .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, + .config_init = aqcs109_config_init, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, +}, +{ + PHY_ID_MATCH_MODEL(PHY_ID_AQR405), + .name = "Aquantia AQR405", + .aneg_done = genphy_c45_aneg_done, + .get_features = genphy_c45_pma_read_abilities, + .config_aneg = aqr_config_aneg, + .config_intr = aqr_config_intr, + .ack_interrupt = aqr_ack_interrupt, + .read_status = aqr_read_status, +}, +}; + +module_phy_driver(aqr_driver); + +static struct mdio_device_id __maybe_unused aqr_tbl[] = { + { PHY_ID_MATCH_MODEL(PHY_ID_AQ1202) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQ2104) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR105) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR106) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR107) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQCS109) }, + { PHY_ID_MATCH_MODEL(PHY_ID_AQR405) }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, aqr_tbl); + +MODULE_DESCRIPTION("Aquantia PHY driver"); +MODULE_AUTHOR("Shaohui Xie "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From fb470f70fea71a0e0adf3e69d1971db6b2119e3b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 25 Feb 2019 19:56:38 +0100 Subject: net: phy: aquantia: add hwmon support This adds HWMON support for the temperature sensor and the related alarms on the 107/108/109 chips. This patch is based on work from Nikita and Andrew. I added: - support for changing alarm thresholds via sysfs - move HWMON code to a separate source file to improve maintainability - smaller changes like using IS_REACHABLE instead of ifdef (avoids problems if PHY driver is built in and HWMON is a module) v2: - remove struct aqr_priv - rename header file to aquantia.h v3: - add conditional compiling of aquantia_hwmon.c - improve converting sensor register values to/from long - add helper aqr_hwmon_test_bit Signed-off-by: Nikita Yushchenko Signed-off-by: Andrew Lunn Signed-off-by: Heiner Kallweit Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/Makefile | 3 + drivers/net/phy/aquantia.h | 16 +++ drivers/net/phy/aquantia_hwmon.c | 250 +++++++++++++++++++++++++++++++++++++++ drivers/net/phy/aquantia_main.c | 4 + 4 files changed, 273 insertions(+) create mode 100644 drivers/net/phy/aquantia.h create mode 100644 drivers/net/phy/aquantia_hwmon.c (limited to 'drivers') diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index b0845adaf804..73e9670ef7e0 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -46,6 +46,9 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) obj-$(CONFIG_AMD_PHY) += amd.o aquantia-objs += aquantia_main.o +ifdef CONFIG_HWMON +aquantia-objs += aquantia_hwmon.o +endif obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o obj-$(CONFIG_ASIX_PHY) += asix.o obj-$(CONFIG_AT803X_PHY) += at803x.o diff --git a/drivers/net/phy/aquantia.h b/drivers/net/phy/aquantia.h new file mode 100644 index 000000000000..5a16caab7b2f --- /dev/null +++ b/drivers/net/phy/aquantia.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 + * HWMON driver for Aquantia PHY + * + * Author: Nikita Yushchenko + * Author: Andrew Lunn + * Author: Heiner Kallweit + */ + +#include +#include + +#if IS_REACHABLE(CONFIG_HWMON) +int aqr_hwmon_probe(struct phy_device *phydev); +#else +static inline int aqr_hwmon_probe(struct phy_device *phydev) { return 0; } +#endif diff --git a/drivers/net/phy/aquantia_hwmon.c b/drivers/net/phy/aquantia_hwmon.c new file mode 100644 index 000000000000..19c4c280a6cd --- /dev/null +++ b/drivers/net/phy/aquantia_hwmon.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0 +/* HWMON driver for Aquantia PHY + * + * Author: Nikita Yushchenko + * Author: Andrew Lunn + * Author: Heiner Kallweit + */ + +#include +#include +#include +#include + +#include "aquantia.h" + +/* Vendor specific 1, MDIO_MMD_VEND2 */ +#define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL 0xc421 +#define VEND1_THERMAL_PROV_LOW_TEMP_FAIL 0xc422 +#define VEND1_THERMAL_PROV_HIGH_TEMP_WARN 0xc423 +#define VEND1_THERMAL_PROV_LOW_TEMP_WARN 0xc424 +#define VEND1_THERMAL_STAT1 0xc820 +#define VEND1_THERMAL_STAT2 0xc821 +#define VEND1_THERMAL_STAT2_VALID BIT(0) +#define VEND1_GENERAL_STAT1 0xc830 +#define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL BIT(14) +#define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL BIT(13) +#define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN BIT(12) +#define VEND1_GENERAL_STAT1_LOW_TEMP_WARN BIT(11) + +#if IS_REACHABLE(CONFIG_HWMON) + +static umode_t aqr_hwmon_is_visible(const void *data, + enum hwmon_sensor_types type, + u32 attr, int channel) +{ + if (type != hwmon_temp) + return 0; + + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_min_alarm: + case hwmon_temp_max_alarm: + case hwmon_temp_lcrit_alarm: + case hwmon_temp_crit_alarm: + return 0444; + case hwmon_temp_min: + case hwmon_temp_max: + case hwmon_temp_lcrit: + case hwmon_temp_crit: + return 0644; + default: + return 0; + } +} + +static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value) +{ + int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); + + if (temp < 0) + return temp; + + /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */ + *value = (s16)temp * 1000 / 256; + + return 0; +} + +static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value) +{ + int temp; + + if (value >= 128000 || value < -128000) + return -ERANGE; + + temp = value * 256 / 1000; + + /* temp is in s16 range and we're interested in lower 16 bits only */ + return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp); +} + +static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit) +{ + int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg); + + if (val < 0) + return val; + + return !!(val & bit); +} + +static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value) +{ + int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit); + + if (val < 0) + return val; + + *value = val; + + return 0; +} + +static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *value) +{ + struct phy_device *phydev = dev_get_drvdata(dev); + int reg; + + if (type != hwmon_temp) + return -EOPNOTSUPP; + + switch (attr) { + case hwmon_temp_input: + reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2, + VEND1_THERMAL_STAT2_VALID); + if (reg < 0) + return reg; + if (!reg) + return -EBUSY; + + return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value); + + case hwmon_temp_lcrit: + return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, + value); + case hwmon_temp_min: + return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, + value); + case hwmon_temp_max: + return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, + value); + case hwmon_temp_crit: + return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, + value); + case hwmon_temp_lcrit_alarm: + return aqr_hwmon_status1(phydev, + VEND1_GENERAL_STAT1_LOW_TEMP_FAIL, + value); + case hwmon_temp_min_alarm: + return aqr_hwmon_status1(phydev, + VEND1_GENERAL_STAT1_LOW_TEMP_WARN, + value); + case hwmon_temp_max_alarm: + return aqr_hwmon_status1(phydev, + VEND1_GENERAL_STAT1_HIGH_TEMP_WARN, + value); + case hwmon_temp_crit_alarm: + return aqr_hwmon_status1(phydev, + VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL, + value); + default: + return -EOPNOTSUPP; + } +} + +static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long value) +{ + struct phy_device *phydev = dev_get_drvdata(dev); + + if (type != hwmon_temp) + return -EOPNOTSUPP; + + switch (attr) { + case hwmon_temp_lcrit: + return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL, + value); + case hwmon_temp_min: + return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN, + value); + case hwmon_temp_max: + return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN, + value); + case hwmon_temp_crit: + return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL, + value); + default: + return -EOPNOTSUPP; + } +} + +static const struct hwmon_ops aqr_hwmon_ops = { + .is_visible = aqr_hwmon_is_visible, + .read = aqr_hwmon_read, + .write = aqr_hwmon_write, +}; + +static u32 aqr_hwmon_chip_config[] = { + HWMON_C_REGISTER_TZ, + 0, +}; + +static const struct hwmon_channel_info aqr_hwmon_chip = { + .type = hwmon_chip, + .config = aqr_hwmon_chip_config, +}; + +static u32 aqr_hwmon_temp_config[] = { + HWMON_T_INPUT | + HWMON_T_MAX | HWMON_T_MIN | + HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM | + HWMON_T_CRIT | HWMON_T_LCRIT | + HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM, + 0, +}; + +static const struct hwmon_channel_info aqr_hwmon_temp = { + .type = hwmon_temp, + .config = aqr_hwmon_temp_config, +}; + +static const struct hwmon_channel_info *aqr_hwmon_info[] = { + &aqr_hwmon_chip, + &aqr_hwmon_temp, + NULL, +}; + +static const struct hwmon_chip_info aqr_hwmon_chip_info = { + .ops = &aqr_hwmon_ops, + .info = aqr_hwmon_info, +}; + +int aqr_hwmon_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct device *hwmon_dev; + char *hwmon_name; + int i, j; + + hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); + if (!hwmon_name) + return -ENOMEM; + + for (i = j = 0; hwmon_name[i]; i++) { + if (isalnum(hwmon_name[i])) { + if (i != j) + hwmon_name[j] = hwmon_name[i]; + j++; + } + } + hwmon_name[j] = '\0'; + + hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, + phydev, &aqr_hwmon_chip_info, NULL); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +#endif diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c index 0f0eb568267d..37218e5d7cc9 100644 --- a/drivers/net/phy/aquantia_main.c +++ b/drivers/net/phy/aquantia_main.c @@ -12,6 +12,8 @@ #include #include +#include "aquantia.h" + #define PHY_ID_AQ1202 0x03a1b445 #define PHY_ID_AQ2104 0x03a1b460 #define PHY_ID_AQR105 0x03a1b4a2 @@ -231,6 +233,7 @@ static struct phy_driver aqr_driver[] = { .name = "Aquantia AQR107", .aneg_done = genphy_c45_aneg_done, .get_features = genphy_c45_pma_read_abilities, + .probe = aqr_hwmon_probe, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, .ack_interrupt = aqr_ack_interrupt, @@ -241,6 +244,7 @@ static struct phy_driver aqr_driver[] = { .name = "Aquantia AQCS109", .aneg_done = genphy_c45_aneg_done, .get_features = genphy_c45_pma_read_abilities, + .probe = aqr_hwmon_probe, .config_init = aqcs109_config_init, .config_aneg = aqr_config_aneg, .config_intr = aqr_config_intr, -- cgit v1.2.3 From 78844068a7b9c995c3d03fd595639ebb920ed831 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 25 Feb 2019 13:01:32 -0600 Subject: mlxsw: spectrum: acl: Use struct_size() in kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; size = sizeof(struct foo) + count * sizeof(struct boo); instance = kzalloc(size, GFP_KERNEL) Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL) Notice that, in this case, variable alloc_size is not necessary, hence it is removed. This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c index df78d23b3ec3..cb3e663b1d37 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c @@ -236,12 +236,10 @@ mlxsw_afk_key_info_create(struct mlxsw_afk *mlxsw_afk, struct mlxsw_afk_element_usage *elusage) { struct mlxsw_afk_key_info *key_info; - size_t alloc_size; int err; - alloc_size = sizeof(*key_info) + - sizeof(key_info->blocks[0]) * mlxsw_afk->max_blocks; - key_info = kzalloc(alloc_size, GFP_KERNEL); + key_info = kzalloc(struct_size(key_info, blocks, mlxsw_afk->max_blocks), + GFP_KERNEL); if (!key_info) return ERR_PTR(-ENOMEM); err = mlxsw_afk_picker(mlxsw_afk, key_info, elusage); -- cgit v1.2.3 From b84caee8449e6e8a2e7da88bdb43958db82b26d8 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Mon, 25 Feb 2019 22:57:40 +0800 Subject: net: lmc: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in lmc_interrupt() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Delete a redundant comment line in lmc_interrupt(). Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/wan/lmc/lmc_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 4907453f17f5..22b065ff6d39 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1320,8 +1320,7 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ sc->lmc_device->stats.tx_packets++; } - // dev_kfree_skb(sc->lmc_txq[i]); - dev_kfree_skb_irq(sc->lmc_txq[i]); + dev_consume_skb_irq(sc->lmc_txq[i]); sc->lmc_txq[i] = NULL; badtx++; -- cgit v1.2.3 From 73634c0851cf7cb86f7614421cf6e149520fb580 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Mon, 25 Feb 2019 23:01:50 +0800 Subject: net: wan: wanxl: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in wanxl_tx_intr() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/wan/wanxl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 459ce52a0a4d..10d5333b7a88 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -185,7 +185,7 @@ static inline void wanxl_tx_intr(struct port *port) desc->stat = PACKET_EMPTY; /* Free descriptor */ pci_unmap_single(port->card->pdev, desc->address, skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); port->tx_in = (port->tx_in + 1) % TX_BUFFERS; } } -- cgit v1.2.3 From 763284d4a5df1592d626334e2c0e206ca4aa07fa Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Mon, 25 Feb 2019 23:02:57 +0800 Subject: net: wan: ixp4xx_hss: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in hss_hdlc_txdone_irq() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/wan/ixp4xx_hss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 6a505c26a3e7..5c60dc60a8e6 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -246,7 +246,7 @@ #ifdef __ARMEB__ typedef struct sk_buff buffer_t; #define free_buffer dev_kfree_skb -#define free_buffer_irq dev_kfree_skb_irq +#define free_buffer_irq dev_consume_skb_irq #else typedef void buffer_t; #define free_buffer kfree -- cgit v1.2.3 From 153d96bec5688fd563ed0569d61fa1367532b7c3 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Mon, 25 Feb 2019 23:03:40 +0800 Subject: net: wan: sbni: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in send_complete() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/wan/sbni.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index 8e8c4c0e1b64..40c04ea1200a 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -761,7 +761,7 @@ send_complete( struct net_device *dev ) dev->stats.tx_packets++; dev->stats.tx_bytes += nl->tx_buf_p->len; #endif - dev_kfree_skb_irq( nl->tx_buf_p ); + dev_consume_skb_irq(nl->tx_buf_p); nl->tx_buf_p = NULL; -- cgit v1.2.3 From 11dc98064c91b90c65210686fc744a03ad525cea Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Mon, 25 Feb 2019 23:05:41 +0800 Subject: net: wan: cosa: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in cosa_net_tx_done() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/wan/cosa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index f6b000ddcd15..55f76e422fa0 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -769,7 +769,7 @@ static int cosa_net_tx_done(struct channel_data *chan, int size) chan->netdev->stats.tx_aborted_errors++; return 1; } - dev_kfree_skb_irq(chan->tx_skb); + dev_consume_skb_irq(chan->tx_skb); chan->tx_skb = NULL; chan->netdev->stats.tx_packets++; chan->netdev->stats.tx_bytes += size; -- cgit v1.2.3 From c14f7e1efcbf744c49fcb44a121112c54d2c5330 Mon Sep 17 00:00:00 2001 From: Yang Wei Date: Mon, 25 Feb 2019 23:06:24 +0800 Subject: net: wan: z85230: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles dev_consume_skb_irq() should be called in z8530_tx_done() when skb xmit done. It makes drop profiles(dropwatch, perf) more friendly. Signed-off-by: Yang Wei Signed-off-by: David S. Miller --- drivers/net/wan/z85230.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index deea41e96f01..0e56ab0aed9a 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -1536,7 +1536,7 @@ static void z8530_tx_done(struct z8530_channel *c) z8530_tx_begin(c); c->netdevice->stats.tx_packets++; c->netdevice->stats.tx_bytes += skb->len; - dev_kfree_skb_irq(skb); + dev_consume_skb_irq(skb); } /** -- cgit v1.2.3 From 56897b217a1d0a91c9920cb418d6b3fe922f590a Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Sat, 23 Feb 2019 12:33:27 +0800 Subject: Bluetooth: hci_ldisc: Postpone HCI_UART_PROTO_READY bit set in hci_uart_set_proto() task A: task B: hci_uart_set_proto flush_to_ldisc - p->open(hu) -> h5_open //alloc h5 - receive_buf - set_bit HCI_UART_PROTO_READY - tty_port_default_receive_buf - hci_uart_register_dev - tty_ldisc_receive_buf - hci_uart_tty_receive - test_bit HCI_UART_PROTO_READY - h5_recv - clear_bit HCI_UART_PROTO_READY while() { - p->open(hu) -> h5_close //free h5 - h5_rx_3wire_hdr - h5_reset() //use-after-free } It could use ioctl to set hci uart proto, but there is a use-after-free issue when hci_uart_register_dev() fail in hci_uart_set_proto(), see stack above, fix this by setting HCI_UART_PROTO_READY bit only when hci_uart_register_dev() return success. Reported-by: syzbot+899a33dc0fa0dbaf06a6@syzkaller.appspotmail.com Signed-off-by: Kefeng Wang Reviewed-by: Jeremy Cline Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_ldisc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 4918fefc4a6f..9562e72c1ae5 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -696,14 +696,13 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) return -EPROTONOSUPPORT; hu->proto = p; - set_bit(HCI_UART_PROTO_READY, &hu->flags); err = hci_uart_register_dev(hu); if (err) { - clear_bit(HCI_UART_PROTO_READY, &hu->flags); return err; } + set_bit(HCI_UART_PROTO_READY, &hu->flags); return 0; } -- cgit v1.2.3 From de79a9df169269d6481b39d46d14768337ee4463 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 19 Feb 2019 12:05:58 -0800 Subject: Bluetooth: btqcomsmd: use HCI_QUIRK_USE_BDADDR_PROPERTY Use the HCI_QUIRK_USE_BDADDR_PROPERTY quirk to let the HCI core handle the reading of 'local-bd-address'. With this there is no need to set HCI_QUIRK_INVALID_BDADDR, the case of a non-existing or invalid fwnode property is handled by the core code. Signed-off-by: Matthias Kaehlcke Reviewed-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btqcomsmd.c | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c index 7df3eed1ef5e..e0d4c6f1d3ab 100644 --- a/drivers/bluetooth/btqcomsmd.c +++ b/drivers/bluetooth/btqcomsmd.c @@ -28,7 +28,6 @@ struct btqcomsmd { struct hci_dev *hdev; - bdaddr_t bdaddr; struct rpmsg_endpoint *acl_channel; struct rpmsg_endpoint *cmd_channel; }; @@ -116,32 +115,17 @@ static int btqcomsmd_close(struct hci_dev *hdev) static int btqcomsmd_setup(struct hci_dev *hdev) { - struct btqcomsmd *btq = hci_get_drvdata(hdev); struct sk_buff *skb; - int err; skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); if (IS_ERR(skb)) return PTR_ERR(skb); kfree_skb(skb); - /* Devices do not have persistent storage for BD address. If no - * BD address has been retrieved during probe, mark the device - * as having an invalid BD address. - */ - if (!bacmp(&btq->bdaddr, BDADDR_ANY)) { - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); - return 0; - } - - /* When setting a configured BD address fails, mark the device - * as having an invalid BD address. + /* Devices do not have persistent storage for BD address. Retrieve + * it from the firmware node property. */ - err = qca_set_bdaddr_rome(hdev, &btq->bdaddr); - if (err) { - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); - return 0; - } + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); return 0; } @@ -169,15 +153,6 @@ static int btqcomsmd_probe(struct platform_device *pdev) if (IS_ERR(btq->cmd_channel)) return PTR_ERR(btq->cmd_channel); - /* The local-bd-address property is usually injected by the - * bootloader which has access to the allocated BD address. - */ - if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address", - (u8 *)&btq->bdaddr, sizeof(bdaddr_t))) { - dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree", - &btq->bdaddr); - } - hdev = hci_alloc_dev(); if (!hdev) return -ENOMEM; -- cgit v1.2.3 From 5971752de44c8e1e3964c12185bcc3e9017e86d3 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 19 Feb 2019 12:05:59 -0800 Subject: Bluetooth: hci_qca: Set HCI_QUIRK_USE_BDADDR_PROPERTY for wcn3990 Set quirk for wcn3990 to read BD_ADDR from a firmware node property. Signed-off-by: Matthias Kaehlcke Tested-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 5e03504c4e0c..26efc2ef98d9 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1192,6 +1192,7 @@ static int qca_setup(struct hci_uart *hu) * setup for every hci up. */ set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); hu->hdev->shutdown = qca_power_off; ret = qca_wcn3990_init(hu); if (ret) -- cgit v1.2.3 From a6982fcdc3c82f0500b6bacdb471fcf406ef623a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 23 Feb 2019 20:05:02 +0100 Subject: mt76: mt76x02: fix TSF sync mode MT_BEACON_TIME_CFG_SYNC_MODE needs to be set for AP mode, according to the documentation. For other modes it should be irrelevant in this case. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 11b5f664f5b1..7b9b1956111b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -679,9 +679,9 @@ void mt76x02_init_beacon_config(struct mt76x02_dev *dev) } mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | - MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_BEACON_TX)); + mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); for (i = 0; i < 8; i++) -- cgit v1.2.3 From b3f09304bab1a775a5fda7b4bd43798118c71567 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 24 Feb 2019 11:24:43 +0100 Subject: mt76: mt76x02: fix beacon timer drift adjustment Check the count before incrementing it to match vendor code behavior. This defers the adjustment by one more tick, which should improve accuracy Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 374bc9d91f12..f0198eea2bb8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -79,24 +79,24 @@ mt76x02_resync_beacon_timer(struct mt76x02_dev *dev) * Beacon timer drifts by 1us every tick, the timer is configured * in 1/16 TU (64us) units. */ - if (dev->tbtt_count < 62) + if (dev->tbtt_count < 63) return; - if (dev->tbtt_count >= 64) { - dev->tbtt_count = 0; - return; - } - /* * The updated beacon interval takes effect after two TBTT, because * at this point the original interval has already been loaded into * the next TBTT_TIMER value */ - if (dev->tbtt_count == 62) + if (dev->tbtt_count == 63) timer_val -= 1; mt76_rmw_field(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_INTVAL, timer_val); + + if (dev->tbtt_count >= 64) { + dev->tbtt_count = 0; + return; + } } static void mt76x02_pre_tbtt_tasklet(unsigned long arg) -- cgit v1.2.3 From ed55c9b9c13e3c30ed644a6ace02fd9fd6b70a45 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 24 Feb 2019 11:37:18 +0100 Subject: mt76: mt76x02: fix beacon timer issue When mt76x0 and mt76x2 beacon code was unified, it changed the order in which beacon enable and beacon interval are configured. Configuring beacon enable before beacon interval can in some cases cause problems with the beacon timer, leading to clients not waking up properly from powersave mode. Fix this by changing the order back to interval first, then enable. Fixes: cc726268e4dce ("mt76: move mt76x02_bss_info_changed in mt76x02-lib module") Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 7b9b1956111b..2e899d30e00d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -704,9 +704,6 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) mt76x02_mac_set_bssid(dev, mvif->idx, info->bssid); - if (changed & BSS_CHANGED_BEACON_ENABLED) - mt76x02_mac_set_beacon_enable(dev, vif, info->enable_beacon); - if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) mt76x02_mac_set_tx_protection(dev, info->use_cts_prot, info->ht_operation_mode); @@ -719,6 +716,9 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, dev->tbtt_count = 0; } + if (changed & BSS_CHANGED_BEACON_ENABLED) + mt76x02_mac_set_beacon_enable(dev, vif, info->enable_beacon); + if (changed & BSS_CHANGED_ERP_PREAMBLE) mt76x02_mac_set_short_preamble(dev, info->use_short_preamble); -- cgit v1.2.3 From 90f42f2d76d0ed29553cf0167bc8e86c22e5a214 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 24 Feb 2019 13:03:18 +0100 Subject: mt76: mt76x02: only reset beacon drift counter when enabling beacons When the timer is already running, there is no need to reset the counter, because the drift will remain the same. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 3 +++ drivers/net/wireless/mediatek/mt76/mt76x02_util.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index be2979f34f31..82b178fa83bb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -1126,6 +1126,9 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, else if (val) skb = ieee80211_beacon_get(mt76_hw(dev), vif); + if (!dev->beacon_mask) + dev->tbtt_count = 0; + __mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb); if (mt76_is_mmio(dev)) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 2e899d30e00d..a48c261b0c63 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -713,7 +713,6 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, MT_BEACON_TIME_CFG_INTVAL, info->beacon_int << 4); dev->beacon_int = info->beacon_int; - dev->tbtt_count = 0; } if (changed & BSS_CHANGED_BEACON_ENABLED) -- cgit v1.2.3 From 72e5d479b8de4a3b3cbc01f9fcc4a6936f82414f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 24 Feb 2019 23:16:45 +0100 Subject: mt76: mt76x02: issue watchdog reset on MCU request timeout MCU request timeout usually indicates that the device is no longer responsive, and it usually does not recover without a reset Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02.h | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c | 1 + drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | 28 +++++++++++++++-------- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 3464b4ca2ea8..6915cce5def9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -98,6 +98,7 @@ struct mt76x02_dev { u32 tx_hang_reset; u8 tx_hang_check; + u8 mcu_timeout; struct mt76x02_calibration cal; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 4752c104abf3..6501b853b65c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -61,6 +61,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, "MCU message %d (seq %d) timed out\n", cmd, seq); ret = -ETIMEDOUT; + dev->mcu_timeout = 1; break; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index f0198eea2bb8..1229f19f2b02 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -494,18 +494,28 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) { if (mt76x02_tx_hang(dev)) { - if (++dev->tx_hang_check < MT_TX_HANG_TH) - return; - - mt76x02_watchdog_reset(dev); - - dev->tx_hang_reset++; - dev->tx_hang_check = 0; - memset(dev->mt76.tx_dma_idx, 0xff, - sizeof(dev->mt76.tx_dma_idx)); + if (++dev->tx_hang_check >= MT_TX_HANG_TH) + goto restart; } else { dev->tx_hang_check = 0; } + + if (dev->mcu_timeout) + goto restart; + + return; + +restart: + mt76x02_watchdog_reset(dev); + + mutex_lock(&dev->mt76.mmio.mcu.mutex); + dev->mcu_timeout = 0; + mutex_unlock(&dev->mt76.mmio.mcu.mutex); + + dev->tx_hang_reset++; + dev->tx_hang_check = 0; + memset(dev->mt76.tx_dma_idx, 0xff, + sizeof(dev->mt76.tx_dma_idx)); } void mt76x02_wdt_work(struct work_struct *work) -- cgit v1.2.3 From 4606a26c0c51d23401a00d787aa61e508f3e14a7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 25 Feb 2019 17:25:38 +0100 Subject: mt76: mt76x02: fix ED/CCA enabling/disabling ED/CCA needs to be disable before stopping the MAC to avoid hangs from tx being blocked. It must only be enabled again after the MAC has been started again. In many places this wasn't done properly, so fix this by always clearing the relevant ED/CCA bits in mt76x2_mac_stop and set it up again after channel change or calibration is done Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt76x0/main.c | 2 ++ drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 6 +----- drivers/net/wireless/mediatek/mt76/mt76x2/mac.c | 3 +++ drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c | 7 ++----- drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c | 6 ++---- drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 3 +-- drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c | 1 + 8 files changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index a529ce111c20..bcb72e019fd2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c @@ -187,6 +187,8 @@ void mt76x0_mac_stop(struct mt76x02_dev *dev) { int i = 200, ok = 0; + mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); + /* Page count on TxQ */ while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) || (mt76_rr(dev, 0x0a30) & 0x000000ff) || diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index a803a9b6a4c5..fee16ab21edb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -34,6 +34,8 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) mt76_rr(dev, MT_CH_IDLE); mt76_rr(dev, MT_CH_BUSY); + mt76x02_edcca_init(dev, true); + if (mt76_is_mmio(dev)) { mt76x02_dfs_init_params(dev); tasklet_enable(&dev->pre_tbtt_tasklet); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 3467a32f5fda..1fd22eb841c3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -1007,17 +1007,13 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev, /* enable vco */ mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); - if (scan) { - mt76x02_edcca_init(dev, false); + if (scan) return 0; - } mt76x02_init_agc_gain(dev); mt76x0_phy_calibrate(dev, false); mt76x0_phy_set_txpower(dev); - mt76x02_edcca_init(dev, true); - ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, MT_CALIBRATE_INTERVAL); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c index e25905c91ee2..e99d4c9bd428 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c @@ -23,6 +23,9 @@ void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force) u32 rts_cfg; int i; + mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); + mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN); + mt76_wr(dev, MT_MAC_SYS_CTRL, 0); rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 97ec575699d0..cc1aebcb0696 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c @@ -74,6 +74,7 @@ mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) mt76x2_mac_resume(dev); mt76x2_apply_gain_adj(dev); + mt76x02_edcca_init(dev, true); dev->cal.channel_cal_done = true; } @@ -240,10 +241,8 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F); - if (scan) { - mt76x02_edcca_init(dev, false); + if (scan) return 0; - } mt76x2_phy_channel_calibrate(dev, true); mt76x02_init_agc_gain(dev); @@ -256,8 +255,6 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, 0x38); } - mt76x02_edcca_init(dev, true); - ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, MT_CALIBRATE_INTERVAL); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c index db2194a92e67..361eb4fb979d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c @@ -143,8 +143,8 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev) rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); - mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20)); - mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1)); + mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); + mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN); /* wait tx dma to stop */ for (i = 0; i < 2000; i++) { @@ -217,6 +217,4 @@ void mt76x2u_mac_resume(struct mt76x02_dev *dev) mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); - mt76_set(dev, MT_TXOP_CTRL_CFG, BIT(20)); - mt76_set(dev, MT_TXOP_HLDR_ET, BIT(1)); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 10633b8de8e8..9b438adfc56c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -57,13 +57,12 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, mt76_set_channel(&dev->mt76); - mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20)); - mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1)); mt76x2_mac_stop(dev, false); err = mt76x2u_phy_set_channel(dev, chandef); mt76x2u_mac_resume(dev); + mt76x02_edcca_init(dev, true); clear_bit(MT76_RESET, &dev->mt76.state); mt76_txq_schedule_all(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index 11d414d86c68..c8b4a17302da 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -45,6 +45,7 @@ mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) if (!mac_stopped) mt76x2u_mac_resume(dev); mt76x2_apply_gain_adj(dev); + mt76x02_edcca_init(dev, true); dev->cal.channel_cal_done = true; } -- cgit v1.2.3 From 2858f60a16799f30aad9b4894d654333a503b94a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 25 Feb 2019 17:32:44 +0100 Subject: mt76: mt76x2: unify mt76x2[u]_mac_resume They are now the same and short enough to be turned into an inline function Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x2/mac.h | 8 +++++++- drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h | 1 - drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c | 7 ------- drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c | 7 ------- drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c | 2 +- 6 files changed, 9 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h index 4c8e20bce920..42ff221d7706 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h @@ -25,6 +25,12 @@ struct mt76x02_vif; int mt76x2_mac_start(struct mt76x02_dev *dev); void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force); -void mt76x2_mac_resume(struct mt76x02_dev *dev); + +static inline void mt76x2_mac_resume(struct mt76x02_dev *dev) +{ + mt76_wr(dev, MT_MAC_SYS_CTRL, + MT_MAC_SYS_CTRL_ENABLE_TX | + MT_MAC_SYS_CTRL_ENABLE_RX); +} #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h index 787cdfdf5db5..76cb1f84eff5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h @@ -35,7 +35,6 @@ void mt76x2u_cleanup(struct mt76x02_dev *dev); void mt76x2u_stop_hw(struct mt76x02_dev *dev); int mt76x2u_mac_reset(struct mt76x02_dev *dev); -void mt76x2u_mac_resume(struct mt76x02_dev *dev); int mt76x2u_mac_start(struct mt76x02_dev *dev); int mt76x2u_mac_stop(struct mt76x02_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index d4e3d7c11d74..984d9c4c2e1a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -173,13 +173,6 @@ int mt76x2_mac_start(struct mt76x02_dev *dev) return 0; } -void mt76x2_mac_resume(struct mt76x02_dev *dev) -{ - mt76_wr(dev, MT_MAC_SYS_CTRL, - MT_MAC_SYS_CTRL_ENABLE_TX | - MT_MAC_SYS_CTRL_ENABLE_RX); -} - static void mt76x2_power_on_rf_patch(struct mt76x02_dev *dev) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c index 361eb4fb979d..5e84b4535cb1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c @@ -211,10 +211,3 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev) return 0; } - -void mt76x2u_mac_resume(struct mt76x02_dev *dev) -{ - mt76_wr(dev, MT_MAC_SYS_CTRL, - MT_MAC_SYS_CTRL_ENABLE_TX | - MT_MAC_SYS_CTRL_ENABLE_RX); -} diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 9b438adfc56c..2ac78e4dc41a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c @@ -61,7 +61,7 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, err = mt76x2u_phy_set_channel(dev, chandef); - mt76x2u_mac_resume(dev); + mt76x2_mac_resume(dev); mt76x02_edcca_init(dev, true); clear_bit(MT76_RESET, &dev->mt76.state); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index c8b4a17302da..07f67cb6854c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c @@ -43,7 +43,7 @@ mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0); if (!mac_stopped) - mt76x2u_mac_resume(dev); + mt76x2_mac_resume(dev); mt76x2_apply_gain_adj(dev); mt76x02_edcca_init(dev, true); -- cgit v1.2.3 From 5c8b0a331212155fb2766a7f5ef627bbf62c3b98 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 25 Feb 2019 18:37:42 +0100 Subject: mt76: mt76x02: set MT_TXOP_HLDR_TX40M_BLK_EN for mt76x2 It needs to be always enabled for 76x2 and conditionally enabled/disabled for 76x0. Since mt76x2_mac_stop clears this bit, ensure that it is enabled in mt76x02_edcca_init Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index 82b178fa83bb..91ff6598eccf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -905,14 +905,14 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); mt76_rmw(dev, MT_BBP(AGC, 2), GENMASK(15, 0), ed_th << 8 | ed_th); - if (!is_mt76x2(dev)) - mt76_set(dev, MT_TXOP_HLDR_ET, - MT_TXOP_HLDR_TX40M_BLK_EN); + mt76_set(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN); } else { mt76_set(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN); mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); if (is_mt76x2(dev)) { mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); + mt76_set(dev, MT_TXOP_HLDR_ET, + MT_TXOP_HLDR_TX40M_BLK_EN); } else { mt76_wr(dev, MT_BBP(AGC, 2), 0x003a6464); mt76_clear(dev, MT_TXOP_HLDR_ET, -- cgit v1.2.3 From b63aa031b00b7d9db28862d9b24b15a5d4146398 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 20 Feb 2019 17:15:18 +0100 Subject: mt76usb: allow mt76u_bulk_msg be used for reads Extend mt76u_bulk_msg() such it can be used for synchronous bulk reads. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 12 ++++++++---- drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index f55dc621e060..6092646014c4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -729,16 +729,20 @@ static inline u8 q2ep(u8 qid) } static inline int -mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout) +mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, + int timeout) { struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(intf); struct mt76_usb *usb = &dev->usb; unsigned int pipe; - int sent; - pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); - return usb_bulk_msg(udev, pipe, data, len, &sent, timeout); + if (actual_len) + pipe = usb_rcvbulkpipe(udev, usb->in_ep[MT_EP_IN_CMD_RESP]); + else + pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); + + return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout); } int mt76u_vendor_request(struct mt76_dev *dev, u8 req, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index e469e383cb88..f497c8e4332a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -126,7 +126,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, if (ret) return ret; - ret = mt76u_bulk_msg(dev, skb->data, skb->len, 500); + ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500); if (ret) return ret; @@ -271,7 +271,7 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data, data_len = MT_CMD_HDR_LEN + len + sizeof(info); - err = mt76u_bulk_msg(&dev->mt76, data, data_len, 1000); + err = mt76u_bulk_msg(&dev->mt76, data, data_len, NULL, 1000); if (err) { dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err); return err; -- cgit v1.2.3 From a18a494f908f88a8be95ce95399800204e338b55 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 20 Feb 2019 17:15:19 +0100 Subject: mt76usb: use synchronous msg for mcu command responses Use usb_bulk_msg for reading MCU command responses. This simplify code a lot. Together with 97a3005759c ("mt76usb: allow mt76u_bulk_msg be used for reads") it also fix possible problems with rx data buffers not being aligned and contained within single page. After doing page_frag_alloc(1024) consecutive page_frag_alloc(PAGE_SIZE) will alloc PAGE_SIZE buffer at PAGE_SIZE - 1024 offset. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 3 +- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 11 -------- .../net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | 32 +++++++--------------- drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 11 -------- drivers/net/wireless/mediatek/mt76/usb.c | 1 - drivers/net/wireless/mediatek/mt76/usb_mcu.c | 31 +++------------------ 6 files changed, 15 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 6092646014c4..c9b5eb9b0582 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -384,8 +384,7 @@ struct mt76_usb { struct mt76u_mcu { struct mutex mutex; - struct completion cmpl; - struct mt76u_buf res; + u8 *data; u32 msg_seq; /* multiple reads */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index da9d05f6074d..f0c33890f1a5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -311,13 +311,11 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, pm_message_t state) { struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); - struct mt76_usb *usb = &dev->mt76.usb; mt76u_stop_queues(&dev->mt76); mt76x0u_mac_stop(dev); clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); mt76x0_chip_onoff(dev, false, false); - usb_kill_urb(usb->mcu.res.urb); return 0; } @@ -328,15 +326,6 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf) struct mt76_usb *usb = &dev->mt76.usb; int ret; - reinit_completion(&usb->mcu.cmpl); - ret = mt76u_submit_buf(&dev->mt76, USB_DIR_IN, - MT_EP_IN_CMD_RESP, - &usb->mcu.res, GFP_KERNEL, - mt76u_mcu_complete_urb, - &usb->mcu.cmpl); - if (ret < 0) - goto err; - ret = mt76u_submit_rx_buffers(&dev->mt76); if (ret < 0) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index f497c8e4332a..0cb8751321a1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c @@ -61,33 +61,21 @@ mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len) static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) { struct mt76_usb *usb = &dev->usb; - struct mt76u_buf *buf = &usb->mcu.res; - struct urb *urb = buf->urb; - u8 *data = buf->buf; - int i, ret; + u8 *data = usb->mcu.data; + int i, len, ret; u32 rxfce; for (i = 0; i < 5; i++) { - if (!wait_for_completion_timeout(&usb->mcu.cmpl, - msecs_to_jiffies(300))) + ret = mt76u_bulk_msg(dev, data, MCU_RESP_URB_SIZE, &len, 300); + if (ret == -ETIMEDOUT) continue; - - if (urb->status) - return -EIO; + if (ret) + goto out; if (usb->mcu.rp) - mt76x02u_multiple_mcu_reads(dev, data + 4, - urb->actual_length - 8); + mt76x02u_multiple_mcu_reads(dev, data + 4, len - 8); rxfce = get_unaligned_le32(data); - ret = mt76u_submit_buf(dev, USB_DIR_IN, - MT_EP_IN_CMD_RESP, - buf, GFP_KERNEL, - mt76u_mcu_complete_urb, - &usb->mcu.cmpl); - if (ret) - return ret; - if (seq == FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce) && FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce) == EVT_CMD_DONE) return 0; @@ -96,9 +84,9 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce), seq, FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce)); } - - dev_err(dev->dev, "error: %s timed out\n", __func__); - return -ETIMEDOUT; +out: + dev_err(dev->dev, "error: %s failed with %d\n", __func__, ret); + return ret; } static int diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index f81a85e96922..ddb6b2c48e01 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c @@ -100,11 +100,9 @@ static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf, pm_message_t state) { struct mt76x02_dev *dev = usb_get_intfdata(intf); - struct mt76_usb *usb = &dev->mt76.usb; mt76u_stop_queues(&dev->mt76); mt76x2u_stop_hw(dev); - usb_kill_urb(usb->mcu.res.urb); return 0; } @@ -115,15 +113,6 @@ static int __maybe_unused mt76x2u_resume(struct usb_interface *intf) struct mt76_usb *usb = &dev->mt76.usb; int err; - reinit_completion(&usb->mcu.cmpl); - err = mt76u_submit_buf(&dev->mt76, USB_DIR_IN, - MT_EP_IN_CMD_RESP, - &usb->mcu.res, GFP_KERNEL, - mt76u_mcu_complete_urb, - &usb->mcu.cmpl); - if (err < 0) - goto err; - err = mt76u_submit_rx_buffers(&dev->mt76); if (err < 0) goto err; diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 78191968b4fa..5c3b7f735aae 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -933,7 +933,6 @@ int mt76u_init(struct mt76_dev *dev, INIT_DELAYED_WORK(&usb->stat_work, mt76u_tx_status_data); skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]); - init_completion(&usb->mcu.cmpl); mutex_init(&usb->mcu.mutex); mutex_init(&usb->usb_ctrl_mtx); diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c index 72c8607da4b4..747231edc57d 100644 --- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/usb_mcu.c @@ -16,42 +16,19 @@ #include "mt76.h" -void mt76u_mcu_complete_urb(struct urb *urb) -{ - struct completion *cmpl = urb->context; - - complete(cmpl); -} -EXPORT_SYMBOL_GPL(mt76u_mcu_complete_urb); - int mt76u_mcu_init_rx(struct mt76_dev *dev) { struct mt76_usb *usb = &dev->usb; - int err; - err = mt76u_buf_alloc(dev, &usb->mcu.res, MCU_RESP_URB_SIZE, - MCU_RESP_URB_SIZE, GFP_KERNEL); - if (err < 0) - return err; - - err = mt76u_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP, - &usb->mcu.res, GFP_KERNEL, - mt76u_mcu_complete_urb, - &usb->mcu.cmpl); - if (err < 0) - mt76u_buf_free(&usb->mcu.res); - - return err; + usb->mcu.data = kmalloc(MCU_RESP_URB_SIZE, GFP_KERNEL); + return usb->mcu.data ? 0 : -ENOMEM; } EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx); void mt76u_mcu_deinit(struct mt76_dev *dev) { - struct mt76u_buf *buf = &dev->usb.mcu.res; + struct mt76_usb *usb = &dev->usb; - if (buf->urb) { - usb_kill_urb(buf->urb); - mt76u_buf_free(buf); - } + kfree(usb->mcu.data); } EXPORT_SYMBOL_GPL(mt76u_mcu_deinit); -- cgit v1.2.3 From fc994dbbd94e638fbdabb9d8acd965800a6f25dd Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 20 Feb 2019 17:15:20 +0100 Subject: mt76usb: remove usb_mcu.c Don't need separate file just for kmalloc/kfree. Signed-off-by: Stanislaw Gruszka Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Makefile | 2 +- drivers/net/wireless/mediatek/mt76/mt76.h | 2 -- drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 5 ---- .../net/wireless/mediatek/mt76/mt76x2/usb_init.c | 5 ---- drivers/net/wireless/mediatek/mt76/usb.c | 5 ++++ drivers/net/wireless/mediatek/mt76/usb_mcu.c | 34 ---------------------- 6 files changed, 6 insertions(+), 47 deletions(-) delete mode 100644 drivers/net/wireless/mediatek/mt76/usb_mcu.c (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index fa7a44edd02d..0d6a76f6e2ba 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -7,7 +7,7 @@ mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ tx.o agg-rx.o mcu.o -mt76-usb-y := usb.o usb_trace.o usb_mcu.o +mt76-usb-y := usb.o usb_trace.o CFLAGS_trace.o := -I$(src) CFLAGS_usb_trace.o := -I$(src) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index c9b5eb9b0582..a689af307a71 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -771,7 +771,5 @@ struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires); void mt76u_mcu_complete_urb(struct urb *urb); -int mt76u_mcu_init_rx(struct mt76_dev *dev); -void mt76u_mcu_deinit(struct mt76_dev *dev); #endif diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index f0c33890f1a5..91718647da02 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c @@ -79,7 +79,6 @@ static void mt76x0u_cleanup(struct mt76x02_dev *dev) clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); mt76x0_chip_onoff(dev, false, false); mt76u_queues_deinit(&dev->mt76); - mt76u_mcu_deinit(&dev->mt76); } static void mt76x0u_mac_stop(struct mt76x02_dev *dev) @@ -193,10 +192,6 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) if (err < 0) goto out_err; - err = mt76u_mcu_init_rx(&dev->mt76); - if (err < 0) - goto out_err; - err = mt76x0u_init_hardware(dev); if (err < 0) goto out_err; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 090aaf71b3ef..1da90e58d942 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c @@ -214,10 +214,6 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) if (err < 0) goto fail; - err = mt76u_mcu_init_rx(&dev->mt76); - if (err < 0) - goto fail; - err = mt76x2u_init_hardware(dev); if (err < 0) goto fail; @@ -259,5 +255,4 @@ void mt76x2u_cleanup(struct mt76x02_dev *dev) mt76x02_mcu_set_radio_state(dev, false); mt76x2u_stop_hw(dev); mt76u_queues_deinit(&dev->mt76); - mt76u_mcu_deinit(&dev->mt76); } diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 5c3b7f735aae..792f5012f1b1 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -577,9 +577,14 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers); static int mt76u_alloc_rx(struct mt76_dev *dev) { + struct mt76_usb *usb = &dev->usb; struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; int i, err; + usb->mcu.data = devm_kmalloc(dev->dev, MCU_RESP_URB_SIZE, GFP_KERNEL); + if (!usb->mcu.data) + return -ENOMEM; + spin_lock_init(&q->rx_page_lock); spin_lock_init(&q->lock); q->entry = devm_kcalloc(dev->dev, diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c deleted file mode 100644 index 747231edc57d..000000000000 --- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2018 Lorenzo Bianconi - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "mt76.h" - -int mt76u_mcu_init_rx(struct mt76_dev *dev) -{ - struct mt76_usb *usb = &dev->usb; - - usb->mcu.data = kmalloc(MCU_RESP_URB_SIZE, GFP_KERNEL); - return usb->mcu.data ? 0 : -ENOMEM; -} -EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx); - -void mt76u_mcu_deinit(struct mt76_dev *dev) -{ - struct mt76_usb *usb = &dev->usb; - - kfree(usb->mcu.data); -} -EXPORT_SYMBOL_GPL(mt76u_mcu_deinit); -- cgit v1.2.3 From cb1847cce03c9787e888cb545096bd53c702cf20 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Thu, 21 Feb 2019 00:57:19 +0100 Subject: mt76: usb: fix warning in mt76u_buf_free Fix following static checker warning in mt76u_buf_free: drivers/net/wireless/mediatek/mt76/usb.c:372 mt76u_buf_free() warn: address of 'urb->sg[i]' is non-NULL There is no need to check sg page pointer since urb->num_sgs has been already validated in mt76u_fill_rx_sg Fixes: cb83585e1121 ("mt76: usb: fix possible memory leak in mt76u_buf_free") Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 792f5012f1b1..7cd95f950ca2 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -364,16 +364,11 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, void mt76u_buf_free(struct mt76u_buf *buf) { struct urb *urb = buf->urb; - struct scatterlist *sg; int i; - for (i = 0; i < urb->num_sgs; i++) { - sg = &urb->sg[i]; - if (!sg) - continue; + for (i = 0; i < urb->num_sgs; i++) + skb_free_frag(sg_virt(&urb->sg[i])); - skb_free_frag(sg_virt(sg)); - } if (buf->buf) skb_free_frag(buf->buf); -- cgit v1.2.3 From 4de92bf10c6df694732d46be19f1d6350f7dba2e Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 20 Feb 2019 23:35:16 +0100 Subject: mt76: usb: introduce mt76u_fill_bulk_urb routine Add mt76u_fill_bulk_urb to initialize tx/rx urbs and remove duplicate code Signed-off-by: Stanislaw Gruszka Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 45 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 7cd95f950ca2..fca271abcfc9 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -376,9 +376,10 @@ void mt76u_buf_free(struct mt76u_buf *buf) } EXPORT_SYMBOL_GPL(mt76u_buf_free); -int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, - struct mt76u_buf *buf, gfp_t gfp, - usb_complete_t complete_fn, void *context) +static void +mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, + struct mt76u_buf *buf, usb_complete_t complete_fn, + void *context) { struct usb_interface *intf = to_usb_interface(dev->dev); struct usb_device *udev = interface_to_usbdev(intf); @@ -392,6 +393,14 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len, complete_fn, context); +} + +int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, + struct mt76u_buf *buf, gfp_t gfp, + usb_complete_t complete_fn, void *context) +{ + mt76u_fill_bulk_urb(dev, dir, index, buf, complete_fn, + context); trace_submit_urb(dev, buf->urb); return usb_submit_urb(buf->urb, gfp); @@ -724,11 +733,16 @@ static void mt76u_complete_tx(struct urb *urb) } static int -mt76u_tx_build_sg(struct sk_buff *skb, struct urb *urb) +mt76u_tx_build_sg(struct mt76_dev *dev, struct sk_buff *skb, + struct urb *urb) { - int nsgs = 1 + skb_shinfo(skb)->nr_frags; struct sk_buff *iter; + int nsgs; + + if (!dev->usb.sg_en) + return 0; + nsgs = 1 + skb_shinfo(skb)->nr_frags; skb_walk_frags(skb, iter) nsgs += 1 + skb_shinfo(iter)->nr_frags; @@ -746,12 +760,8 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, struct sk_buff *skb, struct mt76_wcid *wcid, struct ieee80211_sta *sta) { - struct usb_interface *intf = to_usb_interface(dev->dev); - struct usb_device *udev = interface_to_usbdev(intf); - u8 *data = NULL, ep = q2ep(q->hw_idx); struct mt76u_buf *buf; u16 idx = q->tail; - unsigned int pipe; int err; if (q->queued == q->ndesc) @@ -763,19 +773,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, return err; buf = &q->entry[idx].ubuf; + buf->buf = skb->data; + buf->len = skb->len; buf->done = false; - if (dev->usb.sg_en) { - err = mt76u_tx_build_sg(skb, buf->urb); - if (err < 0) - return err; - } else { - data = skb->data; - } + err = mt76u_tx_build_sg(dev, skb, buf->urb); + if (err < 0) + return err; - pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]); - usb_fill_bulk_urb(buf->urb, udev, pipe, data, skb->len, - mt76u_complete_tx, buf); + mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx), + buf, mt76u_complete_tx, buf); q->tail = (q->tail + 1) % q->ndesc; q->entry[idx].skb = skb; -- cgit v1.2.3 From 888199b89291a495507bc044352cb6b60ffafee0 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 20 Feb 2019 23:35:17 +0100 Subject: mt76: usb: simplify rx buffer allocation Squash mt76u_buf_alloc_sg and mt76u_buf_alloc and remove duplicated code. Reuse mt76u_refill_rx in mt76u_buf_alloc Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 2 - drivers/net/wireless/mediatek/mt76/usb.c | 76 +++++++++++-------------------- 2 files changed, 27 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index a689af307a71..3b674228542d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -751,8 +751,6 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val); int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); void mt76u_deinit(struct mt76_dev *dev); -int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, - int len, int data_len, gfp_t gfp); void mt76u_buf_free(struct mt76u_buf *buf); int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, struct mt76u_buf *buf, gfp_t gfp, diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index fca271abcfc9..6801928cadd0 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -324,41 +324,41 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, } static int -mt76u_buf_alloc_sg(struct mt76_dev *dev, struct mt76u_buf *buf, - int nsgs, int len, int sglen, gfp_t gfp) +mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, + struct mt76u_buf *buf, int nsgs, gfp_t gfp) { - buf->urb = usb_alloc_urb(0, gfp); - if (!buf->urb) - return -ENOMEM; - - buf->urb->sg = devm_kcalloc(dev->dev, nsgs, sizeof(*buf->urb->sg), - gfp); - if (!buf->urb->sg) - return -ENOMEM; - - sg_init_table(buf->urb->sg, nsgs); - buf->dev = dev; - - return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen); + if (dev->usb.sg_en) { + return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size, + SKB_WITH_OVERHEAD(q->buf_size)); + } else { + buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, gfp); + return buf->buf ? 0 : -ENOMEM; + } } -int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, - int len, int data_len, gfp_t gfp) +static int +mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf) { struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; - buf->urb = usb_alloc_urb(0, gfp); + buf->len = SKB_WITH_OVERHEAD(q->buf_size); + buf->dev = dev; + + buf->urb = usb_alloc_urb(0, GFP_KERNEL); if (!buf->urb) return -ENOMEM; - buf->buf = page_frag_alloc(&q->rx_page, len, gfp); - if (!buf->buf) - return -ENOMEM; + if (dev->usb.sg_en) { + buf->urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE, + sizeof(*buf->urb->sg), + GFP_KERNEL); + if (!buf->urb->sg) + return -ENOMEM; - buf->len = data_len; - buf->dev = dev; + sg_init_table(buf->urb->sg, MT_SG_MAX_SIZE); + } - return 0; + return mt76u_refill_rx(dev, q, buf, MT_SG_MAX_SIZE, GFP_KERNEL); } void mt76u_buf_free(struct mt76u_buf *buf) @@ -514,20 +514,6 @@ out: spin_unlock_irqrestore(&q->lock, flags); } -static int -mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, - struct mt76u_buf *buf, int nsgs) -{ - if (dev->usb.sg_en) { - return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size, - SKB_WITH_OVERHEAD(q->buf_size)); - } else { - buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, - GFP_ATOMIC); - return buf->buf ? 0 : -ENOMEM; - } -} - static void mt76u_rx_tasklet(unsigned long data) { struct mt76_dev *dev = (struct mt76_dev *)data; @@ -544,7 +530,8 @@ static void mt76u_rx_tasklet(unsigned long data) count = mt76u_process_rx_entry(dev, buf); if (count > 0) { - err = mt76u_refill_rx(dev, q, buf, count); + err = mt76u_refill_rx(dev, q, buf, count, + GFP_ATOMIC); if (err < 0) break; } @@ -600,16 +587,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; q->ndesc = MT_NUM_RX_ENTRIES; for (i = 0; i < q->ndesc; i++) { - if (dev->usb.sg_en) - err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf, - MT_SG_MAX_SIZE, q->buf_size, - SKB_WITH_OVERHEAD(q->buf_size), - GFP_KERNEL); - else - err = mt76u_buf_alloc(dev, &q->entry[i].ubuf, - q->buf_size, - SKB_WITH_OVERHEAD(q->buf_size), - GFP_KERNEL); + err = mt76u_buf_alloc(dev, &q->entry[i].ubuf); if (err < 0) return err; } -- cgit v1.2.3 From 04eb16fc70164c03ad84b7eb287c55dfbfc5e4e6 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 20 Feb 2019 23:35:18 +0100 Subject: mt76: usb: simplify mt76u_tx_build_sg routine Use skb_to_sgvec instad of skb_to_sgvec_nomark in mt76u_tx_build_sg. Remove nsgs check in mt76u_tx_build_sg since it is already performed by skb_to_sgvec Suggested-by: Felix Fietkau Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 6801928cadd0..096bc99378f5 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -714,23 +714,12 @@ static int mt76u_tx_build_sg(struct mt76_dev *dev, struct sk_buff *skb, struct urb *urb) { - struct sk_buff *iter; - int nsgs; - if (!dev->usb.sg_en) return 0; - nsgs = 1 + skb_shinfo(skb)->nr_frags; - skb_walk_frags(skb, iter) - nsgs += 1 + skb_shinfo(iter)->nr_frags; - - memset(urb->sg, 0, sizeof(*urb->sg) * MT_SG_MAX_SIZE); - - nsgs = min_t(int, MT_SG_MAX_SIZE, nsgs); - sg_init_marker(urb->sg, nsgs); - urb->num_sgs = nsgs; - - return skb_to_sgvec_nomark(skb, urb->sg, 0, skb->len); + sg_init_table(urb->sg, MT_SG_MAX_SIZE); + urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len); + return urb->num_sgs; } static int -- cgit v1.2.3 From 200abe6a963a8720397f7156403ff14d09457704 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 20 Feb 2019 10:20:37 +0100 Subject: mt76: usb: check urb->num_sgs limit in mt76u_process_rx_entry check nsgs value is less than urb->num_sgs in mt76u_process_rx_entry in order to avoid an out-of-bound access of urb->sg array Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 096bc99378f5..ac3da948d43a 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -468,7 +468,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf) __skb_put(skb, data_len); len -= data_len; - while (len > 0 && urb->num_sgs) { + while (len > 0 && nsgs < urb->num_sgs) { data_len = min_t(int, len, urb->sg[nsgs].length); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, sg_page(&urb->sg[nsgs]), -- cgit v1.2.3 From 6cad8240a5da0610b95cb6777cee66edfe33462b Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 26 Feb 2019 12:19:04 +0100 Subject: mt76: remove no longer used routine declarations Remove following routine declarations that are no longer used after commit cfca5f693c5d ("mt76usb: remove usb_mcu.c"): - mt76u_mcu_complete_urb - mt76u_deinit - mt76u_buf_free - mt76u_submit_urb Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt76.h | 7 ------- drivers/net/wireless/mediatek/mt76/usb.c | 11 +++++------ 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 3b674228542d..28bfe91cb2ed 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -750,11 +750,6 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, void mt76u_single_wr(struct mt76_dev *dev, const u8 req, const u16 offset, const u32 val); int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); -void mt76u_deinit(struct mt76_dev *dev); -void mt76u_buf_free(struct mt76u_buf *buf); -int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, - struct mt76u_buf *buf, gfp_t gfp, - usb_complete_t complete_fn, void *context); int mt76u_submit_rx_buffers(struct mt76_dev *dev); int mt76u_alloc_queues(struct mt76_dev *dev); void mt76u_stop_queues(struct mt76_dev *dev); @@ -768,6 +763,4 @@ void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, unsigned long expires); -void mt76u_mcu_complete_urb(struct urb *urb); - #endif diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index ac3da948d43a..ae6ada370597 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -361,7 +361,7 @@ mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf) return mt76u_refill_rx(dev, q, buf, MT_SG_MAX_SIZE, GFP_KERNEL); } -void mt76u_buf_free(struct mt76u_buf *buf) +static void mt76u_buf_free(struct mt76u_buf *buf) { struct urb *urb = buf->urb; int i; @@ -374,7 +374,6 @@ void mt76u_buf_free(struct mt76u_buf *buf) usb_free_urb(buf->urb); } -EXPORT_SYMBOL_GPL(mt76u_buf_free); static void mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, @@ -395,9 +394,10 @@ mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, complete_fn, context); } -int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, - struct mt76u_buf *buf, gfp_t gfp, - usb_complete_t complete_fn, void *context) +static int +mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, + struct mt76u_buf *buf, gfp_t gfp, + usb_complete_t complete_fn, void *context) { mt76u_fill_bulk_urb(dev, dir, index, buf, complete_fn, context); @@ -405,7 +405,6 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, return usb_submit_urb(buf->urb, gfp); } -EXPORT_SYMBOL_GPL(mt76u_submit_buf); static inline struct mt76u_buf *mt76u_get_next_rx_entry(struct mt76_queue *q) -- cgit v1.2.3 From 9c193de548c2436c108b4a2c95fefe34d9b00b26 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 30 Jan 2019 12:17:20 +0100 Subject: mt76: add driver callback for when a sta is associated MT7603 needs this to update the HT/VHT capabilities Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mac80211.c | 5 +++++ drivers/net/wireless/mediatek/mt76/mt76.h | 3 +++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 82e9f78ef328..a033745adb2f 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -714,6 +714,11 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, new_state == IEEE80211_STA_NONE) return mt76_sta_add(dev, vif, sta); + if (old_state == IEEE80211_STA_AUTH && + new_state == IEEE80211_STA_ASSOC && + dev->drv->sta_assoc) + dev->drv->sta_assoc(dev, vif, sta); + if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST) mt76_sta_remove(dev, vif, sta); diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 28bfe91cb2ed..5dfb0601f101 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -304,6 +304,9 @@ struct mt76_driver_ops { int (*sta_add)(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); + void (*sta_assoc)(struct mt76_dev *dev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + void (*sta_remove)(struct mt76_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); }; -- cgit v1.2.3 From c8846e1015022d2531ac4c895783e400b3e5babe Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 6 Nov 2018 13:47:23 +0100 Subject: mt76: add driver for MT7603E and MT7628/7688 This driver is for a newer generation of 2x2 MediaTek 802.11n chipsets. MT7603E is a PCIe chip. MT7628 and MT7688 are MIPS SoC devices with built-in WLAN. MT7688 is limited to 1x1 This driver fully supports AP, station, mesh, ad-hoc and monitor mode. Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/Kconfig | 1 + drivers/net/wireless/mediatek/mt76/Makefile | 1 + drivers/net/wireless/mediatek/mt76/mt7603/Kconfig | 9 + drivers/net/wireless/mediatek/mt76/mt7603/Makefile | 6 + drivers/net/wireless/mediatek/mt76/mt7603/beacon.c | 186 +++ drivers/net/wireless/mediatek/mt76/mt7603/core.c | 73 + .../net/wireless/mediatek/mt76/mt7603/debugfs.c | 56 + drivers/net/wireless/mediatek/mt76/mt7603/dma.c | 215 +++ drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c | 168 ++ drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h | 86 + drivers/net/wireless/mediatek/mt76/mt7603/init.c | 578 +++++++ drivers/net/wireless/mediatek/mt76/mt7603/mac.c | 1749 ++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt7603/mac.h | 242 +++ drivers/net/wireless/mediatek/mt76/mt7603/main.c | 709 ++++++++ drivers/net/wireless/mediatek/mt76/mt7603/mcu.c | 483 ++++++ drivers/net/wireless/mediatek/mt76/mt7603/mcu.h | 110 ++ drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | 253 +++ drivers/net/wireless/mediatek/mt76/mt7603/pci.c | 80 + drivers/net/wireless/mediatek/mt76/mt7603/regs.h | 774 +++++++++ drivers/net/wireless/mediatek/mt76/mt7603/soc.c | 85 + 20 files changed, 5864 insertions(+) create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/Kconfig create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/Makefile create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/beacon.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/core.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/dma.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/init.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/mac.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/mac.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/main.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/mcu.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/mcu.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/pci.c create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/regs.h create mode 100644 drivers/net/wireless/mediatek/mt76/mt7603/soc.c (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index c30d8f5bbf2a..dbe8c70a8f73 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -21,3 +21,4 @@ config MT76x02_USB source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" +source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig" diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index 0d6a76f6e2ba..3fd1b64b4aa7 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile @@ -22,3 +22,4 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ +obj-$(CONFIG_MT7603E) += mt7603/ diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig new file mode 100644 index 000000000000..087945c3d8f3 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig @@ -0,0 +1,9 @@ +config MT7603E + tristate "MediaTek MT7603E (PCIe) and MT76x8 WLAN support" + select MT76_CORE + depends on MAC80211 + depends on PCI + help + This adds support for MT7603E wireless PCIe devices and the WLAN core on + MT7628/MT7688 SoC devices + diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Makefile b/drivers/net/wireless/mediatek/mt76/mt7603/Makefile new file mode 100644 index 000000000000..d95a30421c62 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_MT7603E) += mt7603e.o + +mt7603e-y := \ + pci.o soc.o main.o init.o mcu.o \ + core.o dma.o mac.o eeprom.o \ + beacon.o debugfs.o diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c new file mode 100644 index 000000000000..afcd86f735b4 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: ISC */ + +#include "mt7603.h" + +struct beacon_bc_data { + struct mt7603_dev *dev; + struct sk_buff_head q; + struct sk_buff *tail[MT7603_MAX_INTERFACES]; + int count[MT7603_MAX_INTERFACES]; +}; + +static void +mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct mt7603_dev *dev = (struct mt7603_dev *)priv; + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; + struct sk_buff *skb = NULL; + + if (!(dev->beacon_mask & BIT(mvif->idx))) + return; + + skb = ieee80211_beacon_get(mt76_hw(dev), vif); + if (!skb) + return; + + mt76_dma_tx_queue_skb(&dev->mt76, &dev->mt76.q_tx[MT_TXQ_BEACON], skb, + &mvif->sta.wcid, NULL); + + spin_lock_bh(&dev->ps_lock); + mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | + FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) | + FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, + dev->mt76.q_tx[MT_TXQ_CAB].hw_idx) | + FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) | + FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8)); + + if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) + dev->beacon_check = MT7603_WATCHDOG_TIMEOUT; + + spin_unlock_bh(&dev->ps_lock); +} + +static void +mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ + struct beacon_bc_data *data = priv; + struct mt7603_dev *dev = data->dev; + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; + struct ieee80211_tx_info *info; + struct sk_buff *skb; + + if (!(dev->beacon_mask & BIT(mvif->idx))) + return; + + skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif); + if (!skb) + return; + + info = IEEE80211_SKB_CB(skb); + info->control.vif = vif; + info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; + mt76_skb_set_moredata(skb, true); + __skb_queue_tail(&data->q, skb); + data->tail[mvif->idx] = skb; + data->count[mvif->idx]++; +} + +void mt7603_pre_tbtt_tasklet(unsigned long arg) +{ + struct mt7603_dev *dev = (struct mt7603_dev *)arg; + struct mt76_queue *q; + struct beacon_bc_data data = {}; + struct sk_buff *skb; + int i, nframes; + + data.dev = dev; + __skb_queue_head_init(&data.q); + + q = &dev->mt76.q_tx[MT_TXQ_BEACON]; + spin_lock_bh(&q->lock); + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7603_update_beacon_iter, dev); + mt76_queue_kick(dev, q); + spin_unlock_bh(&q->lock); + + /* Flush all previous CAB queue packets */ + mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0)); + + mt76_queue_tx_cleanup(dev, MT_TXQ_CAB, false); + + mt76_csa_check(&dev->mt76); + if (dev->mt76.csa_complete) + goto out; + + q = &dev->mt76.q_tx[MT_TXQ_CAB]; + do { + nframes = skb_queue_len(&data.q); + ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7603_add_buffered_bc, &data); + } while (nframes != skb_queue_len(&data.q) && + skb_queue_len(&data.q) < 8); + + if (skb_queue_empty(&data.q)) + goto out; + + for (i = 0; i < ARRAY_SIZE(data.tail); i++) { + if (!data.tail[i]) + continue; + + mt76_skb_set_moredata(data.tail[i], false); + } + + spin_lock_bh(&q->lock); + while ((skb = __skb_dequeue(&data.q)) != NULL) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; + + mt76_dma_tx_queue_skb(&dev->mt76, q, skb, &mvif->sta.wcid, + NULL); + } + mt76_queue_kick(dev, q); + spin_unlock_bh(&q->lock); + + for (i = 0; i < ARRAY_SIZE(data.count); i++) + mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i), + data.count[i] << MT_WF_ARB_CAB_COUNT_B0_SHIFT(i)); + + mt76_wr(dev, MT_WF_ARB_CAB_START, + MT_WF_ARB_CAB_START_BSSn(0) | + (MT_WF_ARB_CAB_START_BSS0n(1) * + ((1 << (MT7603_MAX_INTERFACES - 1)) - 1))); + +out: + mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false); + if (dev->mt76.q_tx[MT_TXQ_BEACON].queued > + __sw_hweight8(dev->beacon_mask)) + dev->beacon_check++; +} + +void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval) +{ + u32 pre_tbtt = MT7603_PRE_TBTT_TIME / 64; + + if (idx >= 0) { + if (intval) + dev->beacon_mask |= BIT(idx); + else + dev->beacon_mask &= ~BIT(idx); + } + + if (!dev->beacon_mask || (!intval && idx < 0)) { + mt7603_irq_disable(dev, MT_INT_MAC_IRQ3); + mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK); + mt76_wr(dev, MT_HW_INT_MASK(3), 0); + return; + } + + dev->beacon_int = intval; + mt76_wr(dev, MT_TBTT, + FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE); + + mt76_wr(dev, MT_TBTT_TIMER_CFG, 0x99); /* start timer */ + + mt76_rmw_field(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK, + MT_BCNQ_OPMODE_AP); + mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCN_PRIO); + mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCAST_PRIO); + + mt76_wr(dev, MT_PRE_TBTT, pre_tbtt); + + mt76_set(dev, MT_HW_INT_MASK(3), + MT_HW_INT3_PRE_TBTT0 | MT_HW_INT3_TBTT0); + + mt76_set(dev, MT_WF_ARB_BCN_START, + MT_WF_ARB_BCN_START_BSSn(0) | + ((dev->beacon_mask >> 1) * MT_WF_ARB_BCN_START_BSS0n(1))); + mt7603_irq_enable(dev, MT_INT_MAC_IRQ3); + + if (dev->beacon_mask & ~BIT(0)) + mt76_set(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN); + else + mt76_clear(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c new file mode 100644 index 000000000000..1086dcd376a0 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: ISC */ + +#include "mt7603.h" + +void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags); + dev->mt76.mmio.irqmask &= ~clear; + dev->mt76.mmio.irqmask |= set; + mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); + spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags); +} + +void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + + mt7603_irq_enable(dev, MT_INT_RX_DONE(q)); +} + +irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) +{ + struct mt7603_dev *dev = dev_instance; + u32 intr; + + intr = mt76_rr(dev, MT_INT_SOURCE_CSR); + mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) + return IRQ_NONE; + + intr &= dev->mt76.mmio.irqmask; + + if (intr & MT_INT_MAC_IRQ3) { + u32 hwintr = mt76_rr(dev, MT_HW_INT_STATUS(3)); + + mt76_wr(dev, MT_HW_INT_STATUS(3), hwintr); + if (hwintr & MT_HW_INT3_PRE_TBTT0) + tasklet_schedule(&dev->pre_tbtt_tasklet); + + if ((hwintr & MT_HW_INT3_TBTT0) && dev->mt76.csa_complete) + mt76_csa_finish(&dev->mt76); + } + + if (intr & MT_INT_TX_DONE_ALL) { + mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL); + tasklet_schedule(&dev->tx_tasklet); + } + + if (intr & MT_INT_RX_DONE(0)) { + mt7603_irq_disable(dev, MT_INT_RX_DONE(0)); + napi_schedule(&dev->mt76.napi[0]); + } + + if (intr & MT_INT_RX_DONE(1)) { + mt7603_irq_disable(dev, MT_INT_RX_DONE(1)); + napi_schedule(&dev->mt76.napi[1]); + } + + return IRQ_HANDLED; +} + +u32 mt7603_reg_map(struct mt7603_dev *dev, u32 addr) +{ + u32 base = addr & GENMASK(31, 19); + u32 offset = addr & GENMASK(18, 0); + + dev->bus_ops->wr(&dev->mt76, MT_MCU_PCIE_REMAP_2, base); + + return MT_PCIE_REMAP_BASE_2 + offset; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c new file mode 100644 index 000000000000..f8b3b6ab6297 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: ISC */ + +#include "mt7603.h" + +static int +mt7603_reset_read(struct seq_file *s, void *data) +{ + struct mt7603_dev *dev = dev_get_drvdata(s->private); + static const char * const reset_cause_str[] = { + [RESET_CAUSE_TX_HANG] = "TX hang", + [RESET_CAUSE_TX_BUSY] = "TX DMA busy stuck", + [RESET_CAUSE_RX_BUSY] = "RX DMA busy stuck", + [RESET_CAUSE_RX_PSE_BUSY] = "RX PSE busy stuck", + [RESET_CAUSE_BEACON_STUCK] = "Beacon stuck", + [RESET_CAUSE_MCU_HANG] = "MCU hang", + [RESET_CAUSE_RESET_FAILED] = "PSE reset failed", + }; + int i; + + for (i = 0; i < ARRAY_SIZE(reset_cause_str); i++) { + if (!reset_cause_str[i]) + continue; + + seq_printf(s, "%20s: %u\n", reset_cause_str[i], + dev->reset_cause[i]); + } + + return 0; +} + +static int +mt7603_radio_read(struct seq_file *s, void *data) +{ + struct mt7603_dev *dev = dev_get_drvdata(s->private); + + seq_printf(s, "Sensitivity: %d\n", dev->sensitivity); + seq_printf(s, "False CCA: ofdm=%d cck=%d\n", + dev->false_cca_ofdm, dev->false_cca_cck); + + return 0; +} + +void mt7603_init_debugfs(struct mt7603_dev *dev) +{ + struct dentry *dir; + + dir = mt76_register_debugfs(&dev->mt76); + if (!dir) + return; + + debugfs_create_u32("reset_test", 0600, dir, &dev->reset_test); + debugfs_create_devm_seqfile(dev->mt76.dev, "reset", dir, + mt7603_reset_read); + debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, + mt7603_radio_read); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c new file mode 100644 index 000000000000..d69e82c66ab2 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: ISC */ + +#include "mt7603.h" +#include "mac.h" +#include "../dma.h" + +static int +mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_queue *q, + int idx, int n_desc) +{ + int ret; + + q->hw_idx = idx; + q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE; + q->ndesc = n_desc; + + ret = mt76_queue_alloc(dev, q); + if (ret) + return ret; + + mt7603_irq_enable(dev, MT_INT_TX_DONE(idx)); + + return 0; +} + +static void +mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) +{ + __le32 *txd = (__le32 *)skb->data; + struct mt7603_sta *msta; + struct mt76_wcid *wcid; + int idx; + u32 val; + + if (skb->len < sizeof(MT_TXD_SIZE) + sizeof(struct ieee80211_hdr)) + goto free; + + val = le32_to_cpu(txd[1]); + idx = FIELD_GET(MT_TXD1_WLAN_IDX, val); + skb->priority = FIELD_GET(MT_TXD1_TID, val); + + if (idx >= MT7603_WTBL_STA - 1) + goto free; + + wcid = rcu_dereference(dev->mt76.wcid[idx]); + if (!wcid) + goto free; + + msta = container_of(wcid, struct mt7603_sta, wcid); + val = le32_to_cpu(txd[0]); + skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val)); + + spin_lock_bh(&dev->ps_lock); + __skb_queue_tail(&msta->psq, skb); + if (skb_queue_len(&msta->psq) >= 64) { + skb = __skb_dequeue(&msta->psq); + dev_kfree_skb(skb); + } + spin_unlock_bh(&dev->ps_lock); + return; + +free: + dev_kfree_skb(skb); +} + +void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + __le32 *rxd = (__le32 *)skb->data; + __le32 *end = (__le32 *)&skb->data[skb->len]; + enum rx_pkt_type type; + + type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); + + if (q == MT_RXQ_MCU) { + if (type == PKT_TYPE_RX_EVENT) + mt76_mcu_rx_event(&dev->mt76, skb); + else + mt7603_rx_loopback_skb(dev, skb); + return; + } + + switch (type) { + case PKT_TYPE_TXS: + for (rxd++; rxd + 5 <= end; rxd += 5) + mt7603_mac_add_txs(dev, rxd); + dev_kfree_skb(skb); + break; + case PKT_TYPE_RX_EVENT: + mt76_mcu_rx_event(&dev->mt76, skb); + return; + case PKT_TYPE_NORMAL: + if (mt7603_mac_fill_rx(dev, skb) == 0) { + mt76_rx(&dev->mt76, q, skb); + return; + } + /* fall through */ + default: + dev_kfree_skb(skb); + break; + } +} + +static int +mt7603_init_rx_queue(struct mt7603_dev *dev, struct mt76_queue *q, + int idx, int n_desc, int bufsize) +{ + int ret; + + q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE; + q->ndesc = n_desc; + q->buf_size = bufsize; + + ret = mt76_queue_alloc(dev, q); + if (ret) + return ret; + + mt7603_irq_enable(dev, MT_INT_RX_DONE(idx)); + + return 0; +} + +static void +mt7603_tx_tasklet(unsigned long data) +{ + struct mt7603_dev *dev = (struct mt7603_dev *)data; + int i; + + dev->tx_dma_check = 0; + for (i = MT_TXQ_MCU; i >= 0; i--) + mt76_queue_tx_cleanup(dev, i, false); + + mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); +} + +int mt7603_dma_init(struct mt7603_dev *dev) +{ + static const u8 wmm_queue_map[] = { + [IEEE80211_AC_BK] = 0, + [IEEE80211_AC_BE] = 1, + [IEEE80211_AC_VI] = 2, + [IEEE80211_AC_VO] = 3, + }; + int ret; + int i; + + mt76_dma_attach(&dev->mt76); + + init_waitqueue_head(&dev->mt76.mmio.mcu.wait); + skb_queue_head_init(&dev->mt76.mmio.mcu.res_q); + + tasklet_init(&dev->tx_tasklet, mt7603_tx_tasklet, (unsigned long)dev); + + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_RX_DMA_EN | + MT_WPDMA_GLO_CFG_DMA_BURST_SIZE | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + + mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); + mt7603_pse_client_reset(dev); + + for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { + ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[i], + wmm_queue_map[i], + MT_TX_RING_SIZE); + if (ret) + return ret; + } + + ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD], + MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE); + if (ret) + return ret; + + ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], + MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE); + if (ret) + return ret; + + ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_BEACON], + MT_TX_HW_QUEUE_BCN, MT_MCU_RING_SIZE); + if (ret) + return ret; + + ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_CAB], + MT_TX_HW_QUEUE_BMC, MT_MCU_RING_SIZE); + if (ret) + return ret; + + ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, + MT_MCU_RING_SIZE, MT_RX_BUF_SIZE); + if (ret) + return ret; + + ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, + MT7603_RX_RING_SIZE, MT_RX_BUF_SIZE); + if (ret) + return ret; + + mt76_wr(dev, MT_DELAY_INT_CFG, 0); + return mt76_init_queues(dev); +} + +void mt7603_dma_cleanup(struct mt7603_dev *dev) +{ + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_RX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + + tasklet_kill(&dev->tx_tasklet); + mt76_dma_cleanup(&dev->mt76); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c new file mode 100644 index 000000000000..8c120e4461b0 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: ISC */ + +#include "mt7603.h" +#include "eeprom.h" + +static int +mt7603_efuse_read(struct mt7603_dev *dev, u32 base, u16 addr, u8 *data) +{ + u32 val; + int i; + + val = mt76_rr(dev, base + MT_EFUSE_CTRL); + val &= ~(MT_EFUSE_CTRL_AIN | + MT_EFUSE_CTRL_MODE); + val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf); + val |= MT_EFUSE_CTRL_KICK; + mt76_wr(dev, base + MT_EFUSE_CTRL, val); + + if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) + return -ETIMEDOUT; + + udelay(2); + + val = mt76_rr(dev, base + MT_EFUSE_CTRL); + if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT || + WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) { + memset(data, 0xff, 16); + return 0; + } + + for (i = 0; i < 4; i++) { + val = mt76_rr(dev, base + MT_EFUSE_RDATA(i)); + put_unaligned_le32(val, data + 4 * i); + } + + return 0; +} + +static int +mt7603_efuse_init(struct mt7603_dev *dev) +{ + u32 base = mt7603_reg_map(dev, MT_EFUSE_BASE); + int len = MT7603_EEPROM_SIZE; + void *buf; + int ret, i; + + if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY) + return 0; + + dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL); + dev->mt76.otp.size = len; + if (!dev->mt76.otp.data) + return -ENOMEM; + + buf = dev->mt76.otp.data; + for (i = 0; i + 16 <= len; i += 16) { + ret = mt7603_efuse_read(dev, base, i, buf + i); + if (ret) + return ret; + } + + return 0; +} + +static bool +mt7603_has_cal_free_data(struct mt7603_dev *dev, u8 *efuse) +{ + if (!efuse[MT_EE_TEMP_SENSOR_CAL]) + return false; + + if (get_unaligned_le16(efuse + MT_EE_TX_POWER_0_START_2G) == 0) + return false; + + if (get_unaligned_le16(efuse + MT_EE_TX_POWER_1_START_2G) == 0) + return false; + + if (!efuse[MT_EE_CP_FT_VERSION]) + return false; + + if (!efuse[MT_EE_XTAL_FREQ_OFFSET]) + return false; + + if (!efuse[MT_EE_XTAL_WF_RFCAL]) + return false; + + return true; +} + +static void +mt7603_apply_cal_free_data(struct mt7603_dev *dev, u8 *efuse) +{ + static const u8 cal_free_bytes[] = { + MT_EE_TEMP_SENSOR_CAL, + MT_EE_CP_FT_VERSION, + MT_EE_XTAL_FREQ_OFFSET, + MT_EE_XTAL_WF_RFCAL, + /* Skip for MT7628 */ + MT_EE_TX_POWER_0_START_2G, + MT_EE_TX_POWER_0_START_2G + 1, + MT_EE_TX_POWER_1_START_2G, + MT_EE_TX_POWER_1_START_2G + 1, + }; + u8 *eeprom = dev->mt76.eeprom.data; + int n = ARRAY_SIZE(cal_free_bytes); + int i; + + if (!mt7603_has_cal_free_data(dev, efuse)) + return; + + if (is_mt7628(dev)) + n -= 4; + + for (i = 0; i < n; i++) { + int offset = cal_free_bytes[i]; + + eeprom[offset] = efuse[offset]; + } +} + +static int +mt7603_eeprom_load(struct mt7603_dev *dev) +{ + int ret; + + ret = mt76_eeprom_init(&dev->mt76, MT7603_EEPROM_SIZE); + if (ret < 0) + return ret; + + return mt7603_efuse_init(dev); +} + +static int mt7603_check_eeprom(struct mt76_dev *dev) +{ + u16 val = get_unaligned_le16(dev->eeprom.data); + + switch (val) { + case 0x7628: + case 0x7603: + return 0; + default: + return -EINVAL; + } +} + +int mt7603_eeprom_init(struct mt7603_dev *dev) +{ + int ret; + + ret = mt7603_eeprom_load(dev); + if (ret < 0) + return ret; + + if (dev->mt76.otp.data) { + if (mt7603_check_eeprom(&dev->mt76) == 0) + mt7603_apply_cal_free_data(dev, dev->mt76.otp.data); + else + memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, + MT7603_EEPROM_SIZE); + } + + dev->mt76.cap.has_2ghz = true; + memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, + ETH_ALEN); + + mt76_eeprom_override(&dev->mt76); + + return 0; +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h new file mode 100644 index 000000000000..f27b99b7e359 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: ISC */ + +#ifndef __MT7603_EEPROM_H +#define __MT7603_EEPROM_H + +#include "mt7603.h" + +enum mt7603_eeprom_field { + MT_EE_CHIP_ID = 0x000, + MT_EE_VERSION = 0x002, + MT_EE_MAC_ADDR = 0x004, + MT_EE_NIC_CONF_0 = 0x034, + MT_EE_NIC_CONF_1 = 0x036, + MT_EE_NIC_CONF_2 = 0x042, + + MT_EE_XTAL_TRIM_1 = 0x03a, + + MT_EE_RSSI_OFFSET_2G = 0x046, + MT_EE_WIFI_RF_SETTING = 0x048, + MT_EE_RSSI_OFFSET_5G = 0x04a, + + MT_EE_TX_POWER_DELTA_BW40 = 0x050, + MT_EE_TX_POWER_DELTA_BW80 = 0x052, + + MT_EE_TX_POWER_EXT_PA_5G = 0x054, + + MT_EE_TEMP_SENSOR_CAL = 0x055, + + MT_EE_TX_POWER_0_START_2G = 0x056, + MT_EE_TX_POWER_1_START_2G = 0x05c, + + /* used as byte arrays */ +#define MT_TX_POWER_GROUP_SIZE_5G 5 +#define MT_TX_POWER_GROUPS_5G 6 + MT_EE_TX_POWER_0_START_5G = 0x062, + + MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA = 0x074, + MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE = 0x076, + + MT_EE_TX_POWER_1_START_5G = 0x080, + + MT_EE_TX_POWER_CCK = 0x0a0, + MT_EE_TX_POWER_OFDM_2G_6M = 0x0a2, + MT_EE_TX_POWER_OFDM_2G_24M = 0x0a4, + MT_EE_TX_POWER_OFDM_2G_54M = 0x0a6, + MT_EE_TX_POWER_HT_BPSK_QPSK = 0x0a8, + MT_EE_TX_POWER_HT_16_64_QAM = 0x0aa, + MT_EE_TX_POWER_HT_64_QAM = 0x0ac, + + MT_EE_ELAN_RX_MODE_GAIN = 0x0c0, + MT_EE_ELAN_RX_MODE_NF = 0x0c1, + MT_EE_ELAN_RX_MODE_P1DB = 0x0c2, + + MT_EE_ELAN_BYPASS_MODE_GAIN = 0x0c3, + MT_EE_ELAN_BYPASS_MODE_NF = 0x0c4, + MT_EE_ELAN_BYPASS_MODE_P1DB = 0x0c5, + + MT_EE_STEP_NUM_NEG_6_7 = 0x0c6, + MT_EE_STEP_NUM_NEG_4_5 = 0x0c8, + MT_EE_STEP_NUM_NEG_2_3 = 0x0ca, + MT_EE_STEP_NUM_NEG_0_1 = 0x0cc, + + MT_EE_REF_STEP_24G = 0x0ce, + + MT_EE_STEP_NUM_PLUS_1_2 = 0x0d0, + MT_EE_STEP_NUM_PLUS_3_4 = 0x0d2, + MT_EE_STEP_NUM_PLUS_5_6 = 0x0d4, + MT_EE_STEP_NUM_PLUS_7 = 0x0d6, + + MT_EE_CP_FT_VERSION = 0x0f0, + + MT_EE_XTAL_FREQ_OFFSET = 0x0f4, + MT_EE_XTAL_TRIM_2_COMP = 0x0f5, + MT_EE_XTAL_TRIM_3_COMP = 0x0f6, + MT_EE_XTAL_WF_RFCAL = 0x0f7, + + __MT_EE_MAX +}; + +enum mt7603_eeprom_source { + MT_EE_SRC_PROM, + MT_EE_SRC_EFUSE, + MT_EE_SRC_FLASH, +}; + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c new file mode 100644 index 000000000000..15cc8f33b34d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c @@ -0,0 +1,578 @@ +/* SPDX-License-Identifier: ISC */ + +#include +#include "mt7603.h" +#include "mac.h" +#include "eeprom.h" + +const struct mt76_driver_ops mt7603_drv_ops = { + .txwi_size = MT_TXD_SIZE, + .tx_prepare_skb = mt7603_tx_prepare_skb, + .tx_complete_skb = mt7603_tx_complete_skb, + .rx_skb = mt7603_queue_rx_skb, + .rx_poll_complete = mt7603_rx_poll_complete, + .sta_ps = mt7603_sta_ps, + .sta_add = mt7603_sta_add, + .sta_assoc = mt7603_sta_assoc, + .sta_remove = mt7603_sta_remove, + .update_survey = mt7603_update_channel, +}; + +static void +mt7603_set_tmac_template(struct mt7603_dev *dev) +{ + u32 desc[5] = { + [1] = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 0xf), + [3] = MT_TXD5_SW_POWER_MGMT + }; + u32 addr; + int i; + + addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR); + addr += MT_CLIENT_TMAC_INFO_TEMPLATE; + for (i = 0; i < ARRAY_SIZE(desc); i++) + mt76_wr(dev, addr + 4 * i, desc[i]); +} + +static void +mt7603_dma_sched_init(struct mt7603_dev *dev) +{ + int page_size = 128; + int page_count; + int max_len = 1792; + int max_amsdu_pages = 4096 / page_size; + int max_mcu_len = 4096; + int max_beacon_len = 512 * 4 + max_len; + int max_mcast_pages = 4 * max_len / page_size; + int reserved_count = 0; + int beacon_pages; + int mcu_pages; + int i; + + page_count = mt76_get_field(dev, MT_PSE_FC_P0, + MT_PSE_FC_P0_MAX_QUOTA); + beacon_pages = 4 * (max_beacon_len / page_size); + mcu_pages = max_mcu_len / page_size; + + mt76_wr(dev, MT_PSE_FRP, + FIELD_PREP(MT_PSE_FRP_P0, 7) | + FIELD_PREP(MT_PSE_FRP_P1, 6) | + FIELD_PREP(MT_PSE_FRP_P2_RQ2, 4)); + + mt76_wr(dev, MT_HIGH_PRIORITY_1, 0x55555553); + mt76_wr(dev, MT_HIGH_PRIORITY_2, 0x78555555); + + mt76_wr(dev, MT_QUEUE_PRIORITY_1, 0x2b1a096e); + mt76_wr(dev, MT_QUEUE_PRIORITY_2, 0x785f4d3c); + + mt76_wr(dev, MT_PRIORITY_MASK, 0xffffffff); + + mt76_wr(dev, MT_SCH_1, page_count | (2 << 28)); + mt76_wr(dev, MT_SCH_2, max_amsdu_pages); + + for (i = 0; i <= 4; i++) + mt76_wr(dev, MT_PAGE_COUNT(i), max_amsdu_pages); + reserved_count += 5 * max_amsdu_pages; + + mt76_wr(dev, MT_PAGE_COUNT(5), mcu_pages); + reserved_count += mcu_pages; + + mt76_wr(dev, MT_PAGE_COUNT(7), beacon_pages); + reserved_count += beacon_pages; + + mt76_wr(dev, MT_PAGE_COUNT(8), max_mcast_pages); + reserved_count += max_mcast_pages; + + if (is_mt7603(dev)) + reserved_count = 0; + + mt76_wr(dev, MT_RSV_MAX_THRESH, page_count - reserved_count); + + if (is_mt7603(dev) && mt76xx_rev(dev) >= MT7603_REV_E2) { + mt76_wr(dev, MT_GROUP_THRESH(0), + page_count - beacon_pages - mcu_pages); + mt76_wr(dev, MT_GROUP_THRESH(1), beacon_pages); + mt76_wr(dev, MT_BMAP_0, 0x0080ff5f); + mt76_wr(dev, MT_GROUP_THRESH(2), mcu_pages); + mt76_wr(dev, MT_BMAP_1, 0x00000020); + } else { + mt76_wr(dev, MT_GROUP_THRESH(0), page_count); + mt76_wr(dev, MT_BMAP_0, 0xffff); + } + + mt76_wr(dev, MT_SCH_4, 0); + + for (i = 0; i <= 15; i++) + mt76_wr(dev, MT_TXTIME_THRESH(i), 0xfffff); + + mt76_set(dev, MT_SCH_4, BIT(6)); +} + +static void +mt7603_phy_init(struct mt7603_dev *dev) +{ + int rx_chains = dev->mt76.antenna_mask; + int tx_chains = __sw_hweight8(rx_chains) - 1; + + mt76_rmw(dev, MT_WF_RMAC_RMCR, + (MT_WF_RMAC_RMCR_SMPS_MODE | + MT_WF_RMAC_RMCR_RX_STREAMS), + (FIELD_PREP(MT_WF_RMAC_RMCR_SMPS_MODE, 3) | + FIELD_PREP(MT_WF_RMAC_RMCR_RX_STREAMS, rx_chains))); + + mt76_rmw_field(dev, MT_TMAC_TCR, MT_TMAC_TCR_TX_STREAMS, + tx_chains); + + dev->agc0 = mt76_rr(dev, MT_AGC(0)); + dev->agc3 = mt76_rr(dev, MT_AGC(3)); +} + +static void +mt7603_mac_init(struct mt7603_dev *dev) +{ + u8 bc_addr[ETH_ALEN]; + u32 addr; + int i; + + mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_0, + (MT_AGG_SIZE_LIMIT(0) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(1) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(2) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(3) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT)); + + mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_1, + (MT_AGG_SIZE_LIMIT(4) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(5) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(6) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | + (MT_AGG_SIZE_LIMIT(7) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT)); + + mt76_wr(dev, MT_AGG_LIMIT, + FIELD_PREP(MT_AGG_LIMIT_AC(0), 24) | + FIELD_PREP(MT_AGG_LIMIT_AC(1), 24) | + FIELD_PREP(MT_AGG_LIMIT_AC(2), 24) | + FIELD_PREP(MT_AGG_LIMIT_AC(3), 24)); + + mt76_wr(dev, MT_AGG_LIMIT_1, + FIELD_PREP(MT_AGG_LIMIT_AC(0), 24) | + FIELD_PREP(MT_AGG_LIMIT_AC(1), 24) | + FIELD_PREP(MT_AGG_LIMIT_AC(2), 24) | + FIELD_PREP(MT_AGG_LIMIT_AC(3), 24)); + + mt76_wr(dev, MT_AGG_CONTROL, + FIELD_PREP(MT_AGG_CONTROL_BAR_RATE, 0x4b) | + FIELD_PREP(MT_AGG_CONTROL_CFEND_RATE, 0x69) | + MT_AGG_CONTROL_NO_BA_AR_RULE); + + mt76_wr(dev, MT_AGG_RETRY_CONTROL, + FIELD_PREP(MT_AGG_RETRY_CONTROL_BAR_LIMIT, 1) | + FIELD_PREP(MT_AGG_RETRY_CONTROL_RTS_LIMIT, 15)); + + mt76_rmw(dev, MT_DMA_DCR0, ~0xfffc, 4096); + + mt76_rmw(dev, MT_DMA_VCFR0, BIT(0), BIT(13)); + mt76_rmw(dev, MT_DMA_TMCFR0, BIT(0) | BIT(1), BIT(13)); + + mt76_clear(dev, MT_WF_RMAC_TMR_PA, BIT(31)); + + mt76_set(dev, MT_WF_RMACDR, MT_WF_RMACDR_MAXLEN_20BIT); + mt76_rmw(dev, MT_WF_RMAC_MAXMINLEN, 0xffffff, 0x19000); + + mt76_wr(dev, MT_WF_RFCR1, 0); + + mt76_set(dev, MT_TMAC_TCR, MT_TMAC_TCR_RX_RIFS_MODE); + + mt7603_set_tmac_template(dev); + + /* Enable RX group to HIF */ + addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR); + mt76_set(dev, addr + MT_CLIENT_RXINF, MT_CLIENT_RXINF_RXSH_GROUPS); + + /* Enable RX group to MCU */ + mt76_set(dev, MT_DMA_DCR1, GENMASK(13, 11)); + + mt76_rmw_field(dev, MT_AGG_PCR_RTS, MT_AGG_PCR_RTS_PKT_THR, 3); + mt76_set(dev, MT_TMAC_PCR, MT_TMAC_PCR_SPE_EN); + + /* include preamble detection in CCA trigger signal */ + mt76_rmw_field(dev, MT_TXREQ, MT_TXREQ_CCA_SRC_SEL, 2); + + mt76_wr(dev, MT_RXREQ, 4); + + /* Configure all rx packets to HIF */ + mt76_wr(dev, MT_DMA_RCFR0, 0xc0000000); + + /* Configure MCU txs selection with aggregation */ + mt76_wr(dev, MT_DMA_TCFR0, + FIELD_PREP(MT_DMA_TCFR_TXS_AGGR_TIMEOUT, 1) | /* 32 us */ + MT_DMA_TCFR_TXS_AGGR_COUNT); + + /* Configure HIF txs selection with aggregation */ + mt76_wr(dev, MT_DMA_TCFR1, + FIELD_PREP(MT_DMA_TCFR_TXS_AGGR_TIMEOUT, 1) | /* 32 us */ + MT_DMA_TCFR_TXS_AGGR_COUNT | /* Maximum count */ + MT_DMA_TCFR_TXS_BIT_MAP); + + mt76_wr(dev, MT_MCU_PCIE_REMAP_1, MT_PSE_WTBL_2_PHYS_ADDR); + + for (i = 0; i < MT7603_WTBL_SIZE; i++) + mt7603_wtbl_clear(dev, i); + + eth_broadcast_addr(bc_addr); + mt7603_wtbl_init(dev, MT7603_WTBL_RESERVED, -1, bc_addr); + dev->global_sta.wcid.idx = MT7603_WTBL_RESERVED; + rcu_assign_pointer(dev->mt76.wcid[MT7603_WTBL_RESERVED], + &dev->global_sta.wcid); + + mt76_rmw_field(dev, MT_LPON_BTEIR, MT_LPON_BTEIR_MBSS_MODE, 2); + mt76_rmw_field(dev, MT_WF_RMACDR, MT_WF_RMACDR_MBSSID_MASK, 2); + + mt76_wr(dev, MT_AGG_ARUCR, FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7)); + mt76_wr(dev, MT_AGG_ARDCR, + FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 0) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), + max_t(int, 0, MT7603_RATE_RETRY - 2)) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7603_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7603_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7603_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7603_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7603_RATE_RETRY - 1) | + FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7603_RATE_RETRY - 1)); + + mt76_wr(dev, MT_AGG_ARCR, + (MT_AGG_ARCR_INIT_RATE1 | + FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | + MT_AGG_ARCR_RATE_DOWN_RATIO_EN | + FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | + FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4))); + + mt76_set(dev, MT_WTBL_RMVTCR, MT_WTBL_RMVTCR_RX_MV_MODE); + + mt76_clear(dev, MT_SEC_SCR, MT_SEC_SCR_MASK_ORDER); + mt76_clear(dev, MT_SEC_SCR, BIT(18)); + + /* Set secondary beacon time offsets */ + for (i = 0; i <= 4; i++) + mt76_rmw_field(dev, MT_LPON_SBTOR(i), MT_LPON_SBTOR_TIME_OFFSET, + (i + 1) * (20 + 4096)); +} + +static int +mt7603_init_hardware(struct mt7603_dev *dev) +{ + int i, ret; + + mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); + + ret = mt7603_eeprom_init(dev); + if (ret < 0) + return ret; + + ret = mt7603_dma_init(dev); + if (ret) + return ret; + + mt76_wr(dev, MT_WPDMA_GLO_CFG, 0x52000850); + mt7603_mac_dma_start(dev); + dev->rxfilter = mt76_rr(dev, MT_WF_RFCR); + set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); + + for (i = 0; i < MT7603_WTBL_SIZE; i++) { + mt76_wr(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY | MT_PSE_RTA_WRITE | + FIELD_PREP(MT_PSE_RTA_TAG_ID, i)); + mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000); + } + + ret = mt7603_mcu_init(dev); + if (ret) + return ret; + + mt7603_dma_sched_init(dev); + mt7603_mcu_set_eeprom(dev); + mt7603_phy_init(dev); + mt7603_mac_init(dev); + + return 0; +} + +#define CCK_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ + .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + _idx), \ +} + +#define OFDM_RATE(_idx, _rate) { \ + .bitrate = _rate, \ + .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ + .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ +} + +static struct ieee80211_rate mt7603_rates[] = { + CCK_RATE(0, 10), + CCK_RATE(1, 20), + CCK_RATE(2, 55), + CCK_RATE(3, 110), + OFDM_RATE(11, 60), + OFDM_RATE(15, 90), + OFDM_RATE(10, 120), + OFDM_RATE(14, 180), + OFDM_RATE(9, 240), + OFDM_RATE(13, 360), + OFDM_RATE(8, 480), + OFDM_RATE(12, 540), +}; + +static const struct ieee80211_iface_limit if_limits[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_ADHOC) + }, { + .max = MT7603_MAX_INTERFACES, + .types = BIT(NL80211_IFTYPE_STATION) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_AP) + }, +}; + +static const struct ieee80211_iface_combination if_comb[] = { + { + .limits = if_limits, + .n_limits = ARRAY_SIZE(if_limits), + .max_interfaces = 4, + .num_different_channels = 1, + .beacon_int_infra_match = true, + } +}; + +static void mt7603_led_set_config(struct mt76_dev *mt76, u8 delay_on, + u8 delay_off) +{ + struct mt7603_dev *dev = container_of(mt76, struct mt7603_dev, + mt76); + u32 val, addr; + + val = MT_LED_STATUS_DURATION(0xffff) | + MT_LED_STATUS_OFF(delay_off) | + MT_LED_STATUS_ON(delay_on); + + addr = mt7603_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin)); + mt76_wr(dev, addr, val); + addr = mt7603_reg_map(dev, MT_LED_STATUS_1(mt76->led_pin)); + mt76_wr(dev, addr, val); + + val = MT_LED_CTRL_REPLAY(mt76->led_pin) | + MT_LED_CTRL_KICK(mt76->led_pin); + if (mt76->led_al) + val |= MT_LED_CTRL_POLARITY(mt76->led_pin); + addr = mt7603_reg_map(dev, MT_LED_CTRL); + mt76_wr(dev, addr, val); +} + +static int mt7603_led_set_blink(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, + led_cdev); + u8 delta_on, delta_off; + + delta_off = max_t(u8, *delay_off / 10, 1); + delta_on = max_t(u8, *delay_on / 10, 1); + + mt7603_led_set_config(mt76, delta_on, delta_off); + return 0; +} + +static void mt7603_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, + led_cdev); + + if (!brightness) + mt7603_led_set_config(mt76, 0, 0xff); + else + mt7603_led_set_config(mt76, 0xff, 0); +} + +static u32 __mt7603_reg_addr(struct mt7603_dev *dev, u32 addr) +{ + if (addr < 0x100000) + return addr; + + return mt7603_reg_map(dev, addr); +} + +static u32 mt7603_rr(struct mt76_dev *mdev, u32 offset) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + u32 addr = __mt7603_reg_addr(dev, offset); + + return dev->bus_ops->rr(mdev, addr); +} + +static void mt7603_wr(struct mt76_dev *mdev, u32 offset, u32 val) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + u32 addr = __mt7603_reg_addr(dev, offset); + + dev->bus_ops->wr(mdev, addr, val); +} + +static u32 mt7603_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + u32 addr = __mt7603_reg_addr(dev, offset); + + return dev->bus_ops->rmw(mdev, addr, mask, val); +} + +static void +mt7603_regd_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct mt7603_dev *dev = hw->priv; + + dev->ed_monitor = request->dfs_region == NL80211_DFS_ETSI; +} + +static int +mt7603_txpower_signed(int val) +{ + bool sign = val & BIT(6); + + if (!(val & BIT(7))) + return 0; + + val &= GENMASK(5, 0); + if (!sign) + val = -val; + + return val; +} + +static void +mt7603_init_txpower(struct mt7603_dev *dev, + struct ieee80211_supported_band *sband) +{ + struct ieee80211_channel *chan; + u8 *eeprom = (u8 *)dev->mt76.eeprom.data; + int target_power = eeprom[MT_EE_TX_POWER_0_START_2G + 2] & ~BIT(7); + u8 *rate_power = &eeprom[MT_EE_TX_POWER_CCK]; + int max_offset, cur_offset; + int i; + + if (target_power & BIT(6)) + target_power = -(target_power & GENMASK(5, 0)); + + max_offset = 0; + for (i = 0; i < 14; i++) { + cur_offset = mt7603_txpower_signed(rate_power[i]); + max_offset = max(max_offset, cur_offset); + } + + target_power += max_offset; + + dev->tx_power_limit = target_power; + dev->mt76.txpower_cur = target_power; + + target_power = DIV_ROUND_UP(target_power, 2); + + /* add 3 dBm for 2SS devices (combined output) */ + if (dev->mt76.antenna_mask & BIT(1)) + target_power += 3; + + for (i = 0; i < sband->n_channels; i++) { + chan = &sband->channels[i]; + chan->max_power = target_power; + } +} + + +int mt7603_register_device(struct mt7603_dev *dev) +{ + struct mt76_bus_ops *bus_ops; + struct ieee80211_hw *hw = mt76_hw(dev); + struct wiphy *wiphy = hw->wiphy; + int ret; + + dev->bus_ops = dev->mt76.bus; + bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), + GFP_KERNEL); + if (!bus_ops) + return -ENOMEM; + + bus_ops->rr = mt7603_rr; + bus_ops->wr = mt7603_wr; + bus_ops->rmw = mt7603_rmw; + dev->mt76.bus = bus_ops; + + INIT_DELAYED_WORK(&dev->mac_work, mt7603_mac_work); + tasklet_init(&dev->pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet, + (unsigned long)dev); + + /* Check for 7688, which only has 1SS */ + dev->mt76.antenna_mask = 3; + if (mt76_rr(dev, MT_EFUSE_BASE + 0x64) & BIT(4)) + dev->mt76.antenna_mask = 1; + + dev->slottime = 9; + + ret = mt7603_init_hardware(dev); + if (ret) + return ret; + + hw->queues = 4; + hw->max_rates = 3; + hw->max_report_rates = 7; + hw->max_rate_tries = 11; + + hw->sta_data_size = sizeof(struct mt7603_sta); + hw->vif_data_size = sizeof(struct mt7603_vif); + + wiphy->iface_combinations = if_comb; + wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); + + ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); + ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); + + /* init led callbacks */ + if (IS_ENABLED(CONFIG_MT76_LEDS)) { + dev->mt76.led_cdev.brightness_set = mt7603_led_set_brightness; + dev->mt76.led_cdev.blink_set = mt7603_led_set_blink; + } + + wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif + BIT(NL80211_IFTYPE_ADHOC); + + wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + + wiphy->reg_notifier = mt7603_regd_notifier; + + ret = mt76_register_device(&dev->mt76, true, mt7603_rates, + ARRAY_SIZE(mt7603_rates)); + if (ret) + return ret; + + mt7603_init_debugfs(dev); + mt7603_init_txpower(dev, &dev->mt76.sband_2g.sband); + + return 0; +} + +void mt7603_unregister_device(struct mt7603_dev *dev) +{ + tasklet_disable(&dev->pre_tbtt_tasklet); + mt76_unregister_device(&dev->mt76); + mt7603_mcu_exit(dev); + mt7603_dma_cleanup(dev); + ieee80211_free_hw(mt76_hw(dev)); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c new file mode 100644 index 000000000000..0a0115861b51 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -0,0 +1,1749 @@ +/* SPDX-License-Identifier: ISC */ + +#include +#include +#include "mt7603.h" +#include "mac.h" + +#define MT_PSE_PAGE_SIZE 128 + +static u32 +mt7603_ac_queue_mask0(u32 mask) +{ + u32 ret = 0; + + ret |= GENMASK(3, 0) * !!(mask & BIT(0)); + ret |= GENMASK(8, 5) * !!(mask & BIT(1)); + ret |= GENMASK(13, 10) * !!(mask & BIT(2)); + ret |= GENMASK(19, 16) * !!(mask & BIT(3)); + return ret; +} + +static void +mt76_stop_tx_ac(struct mt7603_dev *dev, u32 mask) +{ + mt76_set(dev, MT_WF_ARB_TX_STOP_0, mt7603_ac_queue_mask0(mask)); +} + +static void +mt76_start_tx_ac(struct mt7603_dev *dev, u32 mask) +{ + mt76_set(dev, MT_WF_ARB_TX_START_0, mt7603_ac_queue_mask0(mask)); +} + +void mt7603_mac_set_timing(struct mt7603_dev *dev) +{ + u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); + u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24); + int offset = 3 * dev->coverage_class; + u32 reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | + FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); + int sifs; + u32 val; + + if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) + sifs = 16; + else + sifs = 10; + + mt76_set(dev, MT_ARB_SCR, + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); + udelay(1); + + mt76_wr(dev, MT_TIMEOUT_CCK, cck + reg_offset); + mt76_wr(dev, MT_TIMEOUT_OFDM, ofdm + reg_offset); + mt76_wr(dev, MT_IFS, + FIELD_PREP(MT_IFS_EIFS, 360) | + FIELD_PREP(MT_IFS_RIFS, 2) | + FIELD_PREP(MT_IFS_SIFS, sifs) | + FIELD_PREP(MT_IFS_SLOT, dev->slottime)); + + if (dev->slottime < 20) + val = MT7603_CFEND_RATE_DEFAULT; + else + val = MT7603_CFEND_RATE_11B; + + mt76_rmw_field(dev, MT_AGG_CONTROL, MT_AGG_CONTROL_CFEND_RATE, val); + + mt76_clear(dev, MT_ARB_SCR, + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); +} + +static void +mt7603_wtbl_update(struct mt7603_dev *dev, int idx, u32 mask) +{ + mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, + FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); + + mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); +} + +static u32 +mt7603_wtbl1_addr(int idx) +{ + return MT_WTBL1_BASE + idx * MT_WTBL1_SIZE; +} + +static u32 +mt7603_wtbl2_addr(int idx) +{ + /* Mapped to WTBL2 */ + return MT_PCIE_REMAP_BASE_1 + idx * MT_WTBL2_SIZE; +} + +static u32 +mt7603_wtbl3_addr(int idx) +{ + u32 base = mt7603_wtbl2_addr(MT7603_WTBL_SIZE); + + return base + idx * MT_WTBL3_SIZE; +} + +static u32 +mt7603_wtbl4_addr(int idx) +{ + u32 base = mt7603_wtbl3_addr(MT7603_WTBL_SIZE); + + return base + idx * MT_WTBL4_SIZE; +} + +void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, int vif, + const u8 *mac_addr) +{ + const void *_mac = mac_addr; + u32 addr = mt7603_wtbl1_addr(idx); + u32 w0 = 0, w1 = 0; + int i; + + if (_mac) { + w0 = FIELD_PREP(MT_WTBL1_W0_ADDR_HI, + get_unaligned_le16(_mac + 4)); + w1 = FIELD_PREP(MT_WTBL1_W1_ADDR_LO, + get_unaligned_le32(_mac)); + } + + if (vif < 0) + vif = 0; + else + w0 |= MT_WTBL1_W0_RX_CHECK_A1; + w0 |= FIELD_PREP(MT_WTBL1_W0_MUAR_IDX, vif); + + mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); + + mt76_set(dev, addr + 0 * 4, w0); + mt76_set(dev, addr + 1 * 4, w1); + mt76_set(dev, addr + 2 * 4, MT_WTBL1_W2_ADMISSION_CONTROL); + + mt76_stop_tx_ac(dev, GENMASK(3, 0)); + addr = mt7603_wtbl2_addr(idx); + for (i = 0; i < MT_WTBL2_SIZE; i += 4) + mt76_wr(dev, addr + i, 0); + mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2); + mt76_start_tx_ac(dev, GENMASK(3, 0)); + + addr = mt7603_wtbl3_addr(idx); + for (i = 0; i < MT_WTBL3_SIZE; i += 4) + mt76_wr(dev, addr + i, 0); + + addr = mt7603_wtbl4_addr(idx); + for (i = 0; i < MT_WTBL4_SIZE; i += 4) + mt76_wr(dev, addr + i, 0); +} + +static void +mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled) +{ + u32 addr = mt7603_wtbl1_addr(idx); + u32 val = mt76_rr(dev, addr + 3 * 4); + + val &= ~MT_WTBL1_W3_SKIP_TX; + val |= enabled * MT_WTBL1_W3_SKIP_TX; + + mt76_wr(dev, addr + 3 * 4, val); +} + +void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) +{ + int i, port, queue; + + if (abort) { + port = 3; /* PSE */ + queue = 8; /* free queue */ + } else { + port = 0; /* HIF */ + queue = 1; /* MCU queue */ + } + + mt7603_wtbl_set_skip_tx(dev, idx, true); + + mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN | + FIELD_PREP(MT_TX_ABORT_WCID, idx)); + + for (i = 0; i < 4; i++) { + mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | + FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) | + FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, i) | + FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) | + FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue)); + + WARN_ON_ONCE(!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, + 0, 5000)); + } + + mt76_wr(dev, MT_TX_ABORT, 0); + + mt7603_wtbl_set_skip_tx(dev, idx, false); +} + +void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta, + bool enabled) +{ + u32 addr = mt7603_wtbl1_addr(sta->wcid.idx); + + if (sta->smps == enabled) + return; + + mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_SMPS, enabled); + sta->smps = enabled; +} + +void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, + bool enabled) +{ + int idx = sta->wcid.idx; + u32 addr; + + spin_lock_bh(&dev->ps_lock); + + if (sta->ps == enabled) + goto out; + + mt76_wr(dev, MT_PSE_RTA, + FIELD_PREP(MT_PSE_RTA_TAG_ID, idx) | + FIELD_PREP(MT_PSE_RTA_PORT_ID, 0) | + FIELD_PREP(MT_PSE_RTA_QUEUE_ID, 1) | + FIELD_PREP(MT_PSE_RTA_REDIRECT_EN, enabled) | + MT_PSE_RTA_WRITE | MT_PSE_RTA_BUSY); + + mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000); + + if (enabled) + mt7603_filter_tx(dev, idx, false); + + addr = mt7603_wtbl1_addr(idx); + mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); + mt76_rmw(dev, addr + 3 * 4, MT_WTBL1_W3_POWER_SAVE, + enabled * MT_WTBL1_W3_POWER_SAVE); + mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); + sta->ps = enabled; + +out: + spin_unlock_bh(&dev->ps_lock); +} + +void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx) +{ + int wtbl2_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL2_SIZE; + int wtbl2_frame = idx / wtbl2_frame_size; + int wtbl2_entry = idx % wtbl2_frame_size; + + int wtbl3_base_frame = MT_WTBL3_OFFSET / MT_PSE_PAGE_SIZE; + int wtbl3_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL3_SIZE; + int wtbl3_frame = wtbl3_base_frame + idx / wtbl3_frame_size; + int wtbl3_entry = (idx % wtbl3_frame_size) * 2; + + int wtbl4_base_frame = MT_WTBL4_OFFSET / MT_PSE_PAGE_SIZE; + int wtbl4_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL4_SIZE; + int wtbl4_frame = wtbl4_base_frame + idx / wtbl4_frame_size; + int wtbl4_entry = idx % wtbl4_frame_size; + + u32 addr = MT_WTBL1_BASE + idx * MT_WTBL1_SIZE; + int i; + + mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); + + mt76_wr(dev, addr + 0 * 4, + MT_WTBL1_W0_RX_CHECK_A1 | + MT_WTBL1_W0_RX_CHECK_A2 | + MT_WTBL1_W0_RX_VALID); + mt76_wr(dev, addr + 1 * 4, 0); + mt76_wr(dev, addr + 2 * 4, 0); + + mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); + + mt76_wr(dev, addr + 3 * 4, + FIELD_PREP(MT_WTBL1_W3_WTBL2_FRAME_ID, wtbl2_frame) | + FIELD_PREP(MT_WTBL1_W3_WTBL2_ENTRY_ID, wtbl2_entry) | + FIELD_PREP(MT_WTBL1_W3_WTBL4_FRAME_ID, wtbl4_frame) | + MT_WTBL1_W3_I_PSM | MT_WTBL1_W3_KEEP_I_PSM); + mt76_wr(dev, addr + 4 * 4, + FIELD_PREP(MT_WTBL1_W4_WTBL3_FRAME_ID, wtbl3_frame) | + FIELD_PREP(MT_WTBL1_W4_WTBL3_ENTRY_ID, wtbl3_entry) | + FIELD_PREP(MT_WTBL1_W4_WTBL4_ENTRY_ID, wtbl4_entry)); + + mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); + + addr = mt7603_wtbl2_addr(idx); + + /* Clear BA information */ + mt76_wr(dev, addr + (15 * 4), 0); + + mt76_stop_tx_ac(dev, GENMASK(3, 0)); + for (i = 2; i <= 4; i++) + mt76_wr(dev, addr + (i * 4), 0); + mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2); + mt76_start_tx_ac(dev, GENMASK(3, 0)); + + mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_RX_COUNT_CLEAR); + mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_TX_COUNT_CLEAR); + mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); +} + +void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta) +{ + struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; + int idx = msta->wcid.idx; + u32 addr; + u32 val; + + addr = mt7603_wtbl1_addr(idx); + + val = mt76_rr(dev, addr + 2 * 4); + val &= MT_WTBL1_W2_KEY_TYPE | MT_WTBL1_W2_ADMISSION_CONTROL; + val |= FIELD_PREP(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) | + FIELD_PREP(MT_WTBL1_W2_MPDU_DENSITY, sta->ht_cap.ampdu_density) | + MT_WTBL1_W2_TXS_BAF_REPORT; + + if (sta->ht_cap.cap) + val |= MT_WTBL1_W2_HT; + if (sta->vht_cap.cap) + val |= MT_WTBL1_W2_VHT; + + mt76_wr(dev, addr + 2 * 4, val); + + addr = mt7603_wtbl2_addr(idx); + val = mt76_rr(dev, addr + 9 * 4); + val &= ~(MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | + MT_WTBL2_W9_SHORT_GI_80); + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) + val |= MT_WTBL2_W9_SHORT_GI_20; + if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) + val |= MT_WTBL2_W9_SHORT_GI_40; + mt76_wr(dev, addr + 9 * 4, val); +} + +void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid) +{ + mt76_wr(dev, MT_BA_CONTROL_0, get_unaligned_le32(addr)); + mt76_wr(dev, MT_BA_CONTROL_1, + (get_unaligned_le16(addr + 4) | + FIELD_PREP(MT_BA_CONTROL_1_TID, tid) | + MT_BA_CONTROL_1_RESET)); +} + +void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, + int ba_size) +{ + u32 addr = mt7603_wtbl2_addr(wcid); + u32 tid_mask = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) | + (MT_WTBL2_W15_BA_WIN_SIZE << + (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT)); + u32 tid_val; + int i; + + if (ba_size < 0) { + /* disable */ + mt76_clear(dev, addr + (15 * 4), tid_mask); + return; + } + mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); + + mt7603_mac_stop(dev); + switch (tid) { + case 0: + mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID0_SN, ssn); + break; + case 1: + mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID1_SN, ssn); + break; + case 2: + mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID2_SN_LO, + ssn); + mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID2_SN_HI, + ssn >> 8); + break; + case 3: + mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID3_SN, ssn); + break; + case 4: + mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID4_SN, ssn); + break; + case 5: + mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID5_SN_LO, + ssn); + mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID5_SN_HI, + ssn >> 4); + break; + case 6: + mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID6_SN, ssn); + break; + case 7: + mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID7_SN, ssn); + break; + } + mt7603_wtbl_update(dev, wcid, MT_WTBL_UPDATE_WTBL2); + mt7603_mac_start(dev); + + for (i = 7; i > 0; i--) { + if (ba_size >= MT_AGG_SIZE_LIMIT(i)) + break; + } + + tid_val = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) | + i << (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT); + + mt76_rmw(dev, addr + (15 * 4), tid_mask, tid_val); +} + +static int +mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband, + int idx, bool cck) +{ + int offset = 0; + int len = sband->n_bitrates; + int i; + + if (cck) { + if (sband == &dev->mt76.sband_5g.sband) + return 0; + + idx &= ~BIT(2); /* short preamble */ + } else if (sband == &dev->mt76.sband_2g.sband) { + offset = 4; + } + + for (i = offset; i < len; i++) { + if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) + return i; + } + + return 0; +} + +static struct mt76_wcid * +mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) +{ + struct mt7603_sta *sta; + struct mt76_wcid *wcid; + + if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + return NULL; + + wcid = rcu_dereference(dev->mt76.wcid[idx]); + if (unicast || !wcid) + return wcid; + + if (!wcid->sta) + return NULL; + + sta = container_of(wcid, struct mt7603_sta, wcid); + if (!sta->vif) + return NULL; + + return &sta->vif->sta.wcid; +} + +static void +mt7603_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + int hdr_len = ieee80211_get_hdrlen_from_skb(skb); + u8 *pn = status->iv; + u8 *hdr; + + __skb_push(skb, 8); + memmove(skb->data, skb->data + 8, hdr_len); + hdr = skb->data + hdr_len; + + hdr[0] = pn[5]; + hdr[1] = pn[4]; + hdr[2] = 0; + hdr[3] = 0x20 | (key_id << 6); + hdr[4] = pn[3]; + hdr[5] = pn[2]; + hdr[6] = pn[1]; + hdr[7] = pn[0]; + + status->flag &= ~RX_FLAG_IV_STRIPPED; +} + +int +mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) +{ + struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; + struct ieee80211_supported_band *sband; + struct ieee80211_hdr *hdr; + __le32 *rxd = (__le32 *)skb->data; + u32 rxd0 = le32_to_cpu(rxd[0]); + u32 rxd1 = le32_to_cpu(rxd[1]); + u32 rxd2 = le32_to_cpu(rxd[2]); + bool unicast = rxd1 & MT_RXD1_NORMAL_U2M; + bool insert_ccmp_hdr = false; + bool remove_pad; + int idx; + int i; + + memset(status, 0, sizeof(*status)); + + i = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); + sband = (i & 1) ? &dev->mt76.sband_5g.sband : &dev->mt76.sband_2g.sband; + i >>= 1; + + idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); + status->wcid = mt7603_rx_get_wcid(dev, idx, unicast); + + status->band = sband->band; + if (i < sband->n_channels) + status->freq = sband->channels[i].center_freq; + + if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) + status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR) + status->flag |= RX_FLAG_MMIC_ERROR; + + if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && + !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) { + status->flag |= RX_FLAG_DECRYPTED; + status->flag |= RX_FLAG_IV_STRIPPED; + status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; + } + + remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; + + if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) + return -EINVAL; + + if (!sband->channels) + return -EINVAL; + + rxd += 4; + if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + if (rxd0 & MT_RXD0_NORMAL_GROUP_1) { + u8 *data = (u8 *)rxd; + + if (status->flag & RX_FLAG_DECRYPTED) { + status->iv[0] = data[5]; + status->iv[1] = data[4]; + status->iv[2] = data[3]; + status->iv[3] = data[2]; + status->iv[4] = data[1]; + status->iv[5] = data[0]; + + insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); + } + + rxd += 4; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + if (rxd0 & MT_RXD0_NORMAL_GROUP_2) { + rxd += 2; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } + if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { + u32 rxdg0 = le32_to_cpu(rxd[0]); + u32 rxdg3 = le32_to_cpu(rxd[3]); + bool cck = false; + + i = FIELD_GET(MT_RXV1_TX_RATE, rxdg0); + switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) { + case MT_PHY_TYPE_CCK: + cck = true; + /* fall through */ + case MT_PHY_TYPE_OFDM: + i = mt7603_get_rate(dev, sband, i, cck); + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + status->encoding = RX_ENC_HT; + if (i > 15) + return -EINVAL; + break; + default: + return -EINVAL; + } + + if (rxdg0 & MT_RXV1_HT_SHORT_GI) + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; + if (rxdg0 & MT_RXV1_HT_AD_CODE) + status->enc_flags |= RX_ENC_FLAG_LDPC; + + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * + FIELD_GET(MT_RXV1_HT_STBC, rxdg0); + + status->rate_idx = i; + + status->chains = dev->mt76.antenna_mask; + status->chain_signal[0] = FIELD_GET(MT_RXV4_IB_RSSI0, rxdg3) + + dev->rssi_offset[0]; + status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) + + dev->rssi_offset[1]; + + status->signal = status->chain_signal[0]; + if (status->chains & BIT(1)) + status->signal = max(status->signal, + status->chain_signal[1]); + + if (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0) == 1) + status->bw = RATE_INFO_BW_40; + + rxd += 6; + if ((u8 *)rxd - skb->data >= skb->len) + return -EINVAL; + } else { + return -EINVAL; + } + + skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); + + if (insert_ccmp_hdr) { + u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); + + mt7603_insert_ccmp_hdr(skb, key_id); + } + + hdr = (struct ieee80211_hdr *)skb->data; + if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) + return 0; + + status->aggr = unicast && + !ieee80211_is_qos_nullfunc(hdr->frame_control); + status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + status->seqno = hdr->seq_ctrl >> 4; + + return 0; +} + +static u16 +mt7603_mac_tx_rate_val(struct mt7603_dev *dev, + const struct ieee80211_tx_rate *rate, bool stbc, u8 *bw) +{ + u8 phy, nss, rate_idx; + u16 rateval; + + *bw = 0; + if (rate->flags & IEEE80211_TX_RC_MCS) { + rate_idx = rate->idx; + nss = 1 + (rate->idx >> 3); + phy = MT_PHY_TYPE_HT; + if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD) + phy = MT_PHY_TYPE_HT_GF; + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + *bw = 1; + } else { + const struct ieee80211_rate *r; + int band = dev->mt76.chandef.chan->band; + u16 val; + + nss = 1; + r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx]; + if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + val = r->hw_value_short; + else + val = r->hw_value; + + phy = val >> 8; + rate_idx = val & 0xff; + } + + rateval = (FIELD_PREP(MT_TX_RATE_IDX, rate_idx) | + FIELD_PREP(MT_TX_RATE_MODE, phy)); + + if (stbc && nss == 1) + rateval |= MT_TX_RATE_STBC; + + return rateval; +} + +void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, + struct ieee80211_tx_rate *probe_rate, + struct ieee80211_tx_rate *rates) +{ + int wcid = sta->wcid.idx; + u32 addr = mt7603_wtbl2_addr(wcid); + bool stbc = false; + int n_rates = sta->n_rates; + u8 bw, bw_prev, bw_idx = 0; + u16 val[4]; + u16 probe_val; + u32 w9 = mt76_rr(dev, addr + 9 * 4); + int i; + + if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) + return; + + for (i = n_rates; i < 4; i++) + rates[i] = rates[n_rates - 1]; + + w9 &= MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | + MT_WTBL2_W9_SHORT_GI_80; + + val[0] = mt7603_mac_tx_rate_val(dev, &rates[0], stbc, &bw); + bw_prev = bw; + + if (probe_rate) { + probe_val = mt7603_mac_tx_rate_val(dev, probe_rate, stbc, &bw); + if (bw) + bw_idx = 1; + else + bw_prev = 0; + } else { + probe_val = val[0]; + } + + w9 |= FIELD_PREP(MT_WTBL2_W9_CC_BW_SEL, bw); + w9 |= FIELD_PREP(MT_WTBL2_W9_BW_CAP, bw); + + val[1] = mt7603_mac_tx_rate_val(dev, &rates[1], stbc, &bw); + if (bw_prev) { + bw_idx = 3; + bw_prev = bw; + } + + val[2] = mt7603_mac_tx_rate_val(dev, &rates[2], stbc, &bw); + if (bw_prev) { + bw_idx = 5; + bw_prev = bw; + } + + val[3] = mt7603_mac_tx_rate_val(dev, &rates[3], stbc, &bw); + if (bw_prev) + bw_idx = 7; + + w9 |= FIELD_PREP(MT_WTBL2_W9_CHANGE_BW_RATE, + bw_idx ? bw_idx - 1 : 7); + + mt76_wr(dev, MT_WTBL_RIUCR0, w9); + + mt76_wr(dev, MT_WTBL_RIUCR1, + FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) | + FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) | + FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0])); + + mt76_wr(dev, MT_WTBL_RIUCR2, + FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) | + FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2])); + + mt76_wr(dev, MT_WTBL_RIUCR3, + FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) | + FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) | + FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3])); + + mt76_wr(dev, MT_WTBL_UPDATE, + FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) | + MT_WTBL_UPDATE_RATE_UPDATE | + MT_WTBL_UPDATE_TX_COUNT_CLEAR); + + if (!sta->wcid.tx_rate_set) + mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); + + sta->rate_count = 2 * MT7603_RATE_RETRY * n_rates; + sta->wcid.tx_rate_set = true; +} + +static enum mt7603_cipher_type +mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) +{ + memset(key_data, 0, 32); + if (!key) + return MT_CIPHER_NONE; + + if (key->keylen > 32) + return MT_CIPHER_NONE; + + memcpy(key_data, key->key, key->keylen); + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + return MT_CIPHER_WEP40; + case WLAN_CIPHER_SUITE_WEP104: + return MT_CIPHER_WEP104; + case WLAN_CIPHER_SUITE_TKIP: + /* Rx/Tx MIC keys are swapped */ + memcpy(key_data + 16, key->key + 24, 8); + memcpy(key_data + 24, key->key + 16, 8); + return MT_CIPHER_TKIP; + case WLAN_CIPHER_SUITE_CCMP: + return MT_CIPHER_AES_CCMP; + default: + return MT_CIPHER_NONE; + } +} + +int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid, + struct ieee80211_key_conf *key) +{ + enum mt7603_cipher_type cipher; + u32 addr = mt7603_wtbl3_addr(wcid); + u8 key_data[32]; + int key_len = sizeof(key_data); + + cipher = mt7603_mac_get_key_info(key, key_data); + if (cipher == MT_CIPHER_NONE && key) + return -EOPNOTSUPP; + + if (key && (cipher == MT_CIPHER_WEP40 || cipher == MT_CIPHER_WEP104)) { + addr += key->keyidx * 16; + key_len = 16; + } + + mt76_wr_copy(dev, addr, key_data, key_len); + + addr = mt7603_wtbl1_addr(wcid); + mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_KEY_TYPE, cipher); + if (key) + mt76_rmw_field(dev, addr, MT_WTBL1_W0_KEY_IDX, key->keyidx); + mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, !!key); + + return 0; +} + +static int +mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi, + struct sk_buff *skb, struct mt76_queue *q, + struct mt76_wcid *wcid, struct ieee80211_sta *sta, + int pid, struct ieee80211_key_conf *key) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rate = &info->control.rates[0]; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_vif *vif = info->control.vif; + struct mt7603_vif *mvif; + int wlan_idx; + int hdr_len = ieee80211_get_hdrlen_from_skb(skb); + int tx_count = 8; + u8 frame_type, frame_subtype; + u16 fc = le16_to_cpu(hdr->frame_control); + u8 vif_idx = 0; + u32 val; + u8 bw; + + if (vif) { + mvif = (struct mt7603_vif *)vif->drv_priv; + vif_idx = mvif->idx; + if (vif_idx && q >= &dev->mt76.q_tx[MT_TXQ_BEACON]) + vif_idx += 0x10; + } + + if (sta) { + struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; + + tx_count = msta->rate_count; + } + + if (wcid) + wlan_idx = wcid->idx; + else + wlan_idx = MT7603_WTBL_RESERVED; + + frame_type = (fc & IEEE80211_FCTL_FTYPE) >> 2; + frame_subtype = (fc & IEEE80211_FCTL_STYPE) >> 4; + + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | + FIELD_PREP(MT_TXD0_Q_IDX, q->hw_idx); + txwi[0] = cpu_to_le32(val); + + val = MT_TXD1_LONG_FORMAT | + FIELD_PREP(MT_TXD1_OWN_MAC, vif_idx) | + FIELD_PREP(MT_TXD1_TID, + skb->priority & IEEE80211_QOS_CTL_TID_MASK) | + FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | + FIELD_PREP(MT_TXD1_HDR_INFO, hdr_len / 2) | + FIELD_PREP(MT_TXD1_WLAN_IDX, wlan_idx) | + FIELD_PREP(MT_TXD1_PROTECTED, !!key); + txwi[1] = cpu_to_le32(val); + + if (info->flags & IEEE80211_TX_CTL_NO_ACK) + txwi[1] |= cpu_to_le32(MT_TXD1_NO_ACK); + + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, frame_type) | + FIELD_PREP(MT_TXD2_SUB_TYPE, frame_subtype) | + FIELD_PREP(MT_TXD2_MULTICAST, + is_multicast_ether_addr(hdr->addr1)); + txwi[2] = cpu_to_le32(val); + + if (!(info->flags & IEEE80211_TX_CTL_AMPDU)) + txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE); + + txwi[4] = 0; + + val = MT_TXD5_TX_STATUS_HOST | MT_TXD5_SW_POWER_MGMT | + FIELD_PREP(MT_TXD5_PID, pid); + txwi[5] = cpu_to_le32(val); + + txwi[6] = 0; + + if (rate->idx >= 0 && rate->count && + !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) { + bool stbc = info->flags & IEEE80211_TX_CTL_STBC; + u16 rateval = mt7603_mac_tx_rate_val(dev, rate, stbc, &bw); + + txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); + + val = MT_TXD6_FIXED_BW | + FIELD_PREP(MT_TXD6_BW, bw) | + FIELD_PREP(MT_TXD6_TX_RATE, rateval); + txwi[6] |= cpu_to_le32(val); + + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + txwi[6] |= cpu_to_le32(MT_TXD6_SGI); + + if (!(rate->flags & IEEE80211_TX_RC_MCS)) + txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE); + + tx_count = rate->count; + } + + /* use maximum tx count for beacons and buffered multicast */ + if (q >= &dev->mt76.q_tx[MT_TXQ_BEACON]) + tx_count = 0x1f; + + val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count) | + FIELD_PREP(MT_TXD3_SEQ, le16_to_cpu(hdr->seq_ctrl)); + txwi[3] = cpu_to_le32(val); + + if (key) { + u64 pn = atomic64_inc_return(&key->tx_pn); + + txwi[3] |= cpu_to_le32(MT_TXD3_PN_VALID); + txwi[4] = cpu_to_le32(pn & GENMASK(31, 0)); + txwi[5] |= cpu_to_le32(FIELD_PREP(MT_TXD5_PN_HIGH, pn >> 32)); + } + + txwi[7] = 0; + + return 0; +} + +int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + struct sk_buff *skb, struct mt76_queue *q, + struct mt76_wcid *wcid, struct ieee80211_sta *sta, + u32 *tx_info) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct mt7603_sta *msta = container_of(wcid, struct mt7603_sta, wcid); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_key_conf *key = info->control.hw_key; + int pid; + + if (!wcid) + wcid = &dev->global_sta.wcid; + + if (sta) { + msta = (struct mt7603_sta *)sta->drv_priv; + + if ((info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER | + IEEE80211_TX_CTL_CLEAR_PS_FILT)) || + (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)) + mt7603_wtbl_set_ps(dev, msta, false); + } + + pid = mt76_tx_status_skb_add(mdev, wcid, skb); + + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { + spin_lock_bh(&dev->mt76.lock); + msta->rate_probe = true; + mt7603_wtbl_set_rates(dev, msta, &info->control.rates[0], + msta->rates); + spin_unlock_bh(&dev->mt76.lock); + } + + mt7603_mac_write_txwi(dev, txwi_ptr, skb, q, wcid, sta, pid, key); + + return 0; +} + +static bool +mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, + struct ieee80211_tx_info *info, __le32 *txs_data) +{ + struct ieee80211_supported_band *sband; + int final_idx = 0; + u32 final_rate; + u32 final_rate_flags; + bool final_mpdu; + bool ack_timeout; + bool fixed_rate; + bool probe; + bool ampdu; + bool cck = false; + int count; + u32 txs; + u8 pid; + int idx; + int i; + + fixed_rate = info->status.rates[0].count; + probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); + + txs = le32_to_cpu(txs_data[4]); + final_mpdu = txs & MT_TXS4_ACKED_MPDU; + ampdu = !fixed_rate && (txs & MT_TXS4_AMPDU); + pid = FIELD_GET(MT_TXS4_PID, txs); + count = FIELD_GET(MT_TXS4_TX_COUNT, txs); + + txs = le32_to_cpu(txs_data[0]); + final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); + ack_timeout = txs & MT_TXS0_ACK_TIMEOUT; + + if (!ampdu && (txs & MT_TXS0_RTS_TIMEOUT)) + return false; + + if (txs & MT_TXS0_QUEUE_TIMEOUT) + return false; + + if (!ack_timeout) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.ampdu_len = 1; + info->status.ampdu_ack_len = !!(info->flags & + IEEE80211_TX_STAT_ACK); + + if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU)) + info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU; + + if (fixed_rate && !probe) { + info->status.rates[0].count = count; + goto out; + } + + for (i = 0, idx = 0; i < ARRAY_SIZE(info->status.rates); i++) { + int cur_count = min_t(int, count, 2 * MT7603_RATE_RETRY); + + if (!i && probe) { + cur_count = 1; + } else { + info->status.rates[i] = sta->rates[idx]; + idx++; + } + + if (i && info->status.rates[i].idx < 0) { + info->status.rates[i - 1].count += count; + break; + } + + if (!count) { + info->status.rates[i].idx = -1; + break; + } + + info->status.rates[i].count = cur_count; + final_idx = i; + count -= cur_count; + } + +out: + final_rate_flags = info->status.rates[final_idx].flags; + + switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) { + case MT_PHY_TYPE_CCK: + cck = true; + /* fall through */ + case MT_PHY_TYPE_OFDM: + if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) + sband = &dev->mt76.sband_5g.sband; + else + sband = &dev->mt76.sband_2g.sband; + final_rate &= GENMASK(5, 0); + final_rate = mt7603_get_rate(dev, sband, final_rate, cck); + final_rate_flags = 0; + break; + case MT_PHY_TYPE_HT_GF: + case MT_PHY_TYPE_HT: + final_rate_flags |= IEEE80211_TX_RC_MCS; + final_rate &= GENMASK(5, 0); + if (i > 15) + return false; + break; + default: + return false; + } + + info->status.rates[final_idx].idx = final_rate; + info->status.rates[final_idx].flags = final_rate_flags; + + return true; +} + +static bool +mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid, + __le32 *txs_data) +{ + struct mt76_dev *mdev = &dev->mt76; + struct sk_buff_head list; + struct sk_buff *skb; + + if (pid < MT_PACKET_ID_FIRST) + return false; + + mt76_tx_status_lock(mdev, &list); + skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { + spin_lock_bh(&dev->mt76.lock); + if (sta->rate_probe) { + mt7603_wtbl_set_rates(dev, sta, NULL, + sta->rates); + sta->rate_probe = false; + } + spin_unlock_bh(&dev->mt76.lock); + } + + if (!mt7603_fill_txs(dev, sta, info, txs_data)) { + ieee80211_tx_info_clear_status(info); + info->status.rates[0].idx = -1; + } + + mt76_tx_status_skb_done(mdev, skb, &list); + } + mt76_tx_status_unlock(mdev, &list); + + return !!skb; +} + +void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) +{ + struct ieee80211_tx_info info = {}; + struct ieee80211_sta *sta = NULL; + struct mt7603_sta *msta = NULL; + struct mt76_wcid *wcid; + __le32 *txs_data = data; + u32 txs; + u8 wcidx; + u8 pid; + + txs = le32_to_cpu(txs_data[4]); + pid = FIELD_GET(MT_TXS4_PID, txs); + txs = le32_to_cpu(txs_data[3]); + wcidx = FIELD_GET(MT_TXS3_WCID, txs); + + if (pid == MT_PACKET_ID_NO_ACK) + return; + + if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) + return; + + rcu_read_lock(); + + wcid = rcu_dereference(dev->mt76.wcid[wcidx]); + if (!wcid) + goto out; + + msta = container_of(wcid, struct mt7603_sta, wcid); + sta = wcid_to_sta(wcid); + + if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data)) + goto out; + + if (wcidx >= MT7603_WTBL_STA || !sta) + goto out; + + if (mt7603_fill_txs(dev, msta, &info, txs_data)) + ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info); + +out: + rcu_read_unlock(); +} + +void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, + struct mt76_queue_entry *e, bool flush) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct sk_buff *skb = e->skb; + + if (!e->txwi) { + dev_kfree_skb_any(skb); + return; + } + + if (q - dev->mt76.q_tx < 4) + dev->tx_hang_check = 0; + + mt76_tx_complete_skb(mdev, skb); +} + +static bool +wait_for_wpdma(struct mt7603_dev *dev) +{ + return mt76_poll(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_TX_DMA_BUSY | + MT_WPDMA_GLO_CFG_RX_DMA_BUSY, + 0, 1000); +} + +static void mt7603_pse_reset(struct mt7603_dev *dev) +{ + /* Clear previous reset result */ + if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED]) + mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE_S); + + /* Reset PSE */ + mt76_set(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE); + + if (!mt76_poll_msec(dev, MT_MCU_DEBUG_RESET, + MT_MCU_DEBUG_RESET_PSE_S, + MT_MCU_DEBUG_RESET_PSE_S, 500)) { + dev->reset_cause[RESET_CAUSE_RESET_FAILED]++; + mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE); + } else { + dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0; + mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_QUEUES); + } + + if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] >= 3) + dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0; +} + +void mt7603_mac_dma_start(struct mt7603_dev *dev) +{ + mt7603_mac_start(dev); + + wait_for_wpdma(dev); + usleep_range(50, 100); + + mt76_set(dev, MT_WPDMA_GLO_CFG, + (MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_RX_DMA_EN | + FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3) | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE)); + + mt7603_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL); +} + +void mt7603_mac_start(struct mt7603_dev *dev) +{ + mt76_clear(dev, MT_ARB_SCR, + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); + mt76_wr(dev, MT_WF_ARB_TX_START_0, ~0); + mt76_set(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START); +} + +void mt7603_mac_stop(struct mt7603_dev *dev) +{ + mt76_set(dev, MT_ARB_SCR, + MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); + mt76_wr(dev, MT_WF_ARB_TX_START_0, 0); + mt76_clear(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START); +} + +void mt7603_pse_client_reset(struct mt7603_dev *dev) +{ + u32 addr; + + addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + + MT_CLIENT_RESET_TX); + + /* Clear previous reset state */ + mt76_clear(dev, addr, + MT_CLIENT_RESET_TX_R_E_1 | + MT_CLIENT_RESET_TX_R_E_2 | + MT_CLIENT_RESET_TX_R_E_1_S | + MT_CLIENT_RESET_TX_R_E_2_S); + + /* Start PSE client TX abort */ + mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1); + mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S, + MT_CLIENT_RESET_TX_R_E_1_S, 500); + + mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_2); + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET); + + /* Wait for PSE client to clear TX FIFO */ + mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_2_S, + MT_CLIENT_RESET_TX_R_E_2_S, 500); + + /* Clear PSE client TX abort state */ + mt76_clear(dev, addr, + MT_CLIENT_RESET_TX_R_E_1 | + MT_CLIENT_RESET_TX_R_E_2); +} + +static void mt7603_dma_sched_reset(struct mt7603_dev *dev) +{ + if (!is_mt7628(dev)) + return; + + mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET); + mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET); +} + +static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) +{ + int beacon_int = dev->beacon_int; + u32 mask = dev->mt76.mmio.irqmask; + int i; + + ieee80211_stop_queues(dev->mt76.hw); + set_bit(MT76_RESET, &dev->mt76.state); + + /* lock/unlock all queues to ensure that no tx is pending */ + mt76_txq_schedule_all(&dev->mt76); + + tasklet_disable(&dev->tx_tasklet); + tasklet_disable(&dev->pre_tbtt_tasklet); + napi_disable(&dev->mt76.napi[0]); + napi_disable(&dev->mt76.napi[1]); + + mutex_lock(&dev->mt76.mutex); + + mt7603_beacon_set_timer(dev, -1, 0); + + if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] || + dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY || + dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK || + dev->cur_reset_cause == RESET_CAUSE_TX_HANG) + mt7603_pse_reset(dev); + + if (dev->reset_cause[RESET_CAUSE_RESET_FAILED]) + goto skip_dma_reset; + + mt7603_mac_stop(dev); + + mt76_clear(dev, MT_WPDMA_GLO_CFG, + MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | + MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); + usleep_range(1000, 2000); + + mt7603_irq_disable(dev, mask); + + mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF); + + mt7603_pse_client_reset(dev); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) + mt76_queue_tx_cleanup(dev, i, true); + + for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_queue_rx_reset(dev, i); + + mt7603_dma_sched_reset(dev); + + mt7603_mac_dma_start(dev); + + mt7603_irq_enable(dev, mask); + +skip_dma_reset: + clear_bit(MT76_RESET, &dev->mt76.state); + mutex_unlock(&dev->mt76.mutex); + + tasklet_enable(&dev->tx_tasklet); + tasklet_schedule(&dev->tx_tasklet); + + tasklet_enable(&dev->pre_tbtt_tasklet); + mt7603_beacon_set_timer(dev, -1, beacon_int); + + napi_enable(&dev->mt76.napi[0]); + napi_schedule(&dev->mt76.napi[0]); + + napi_enable(&dev->mt76.napi[1]); + napi_schedule(&dev->mt76.napi[1]); + + ieee80211_wake_queues(dev->mt76.hw); + mt76_txq_schedule_all(&dev->mt76); +} + +static u32 mt7603_dma_debug(struct mt7603_dev *dev, u8 index) +{ + u32 val; + + mt76_wr(dev, MT_WPDMA_DEBUG, + FIELD_PREP(MT_WPDMA_DEBUG_IDX, index) | + MT_WPDMA_DEBUG_SEL); + + val = mt76_rr(dev, MT_WPDMA_DEBUG); + return FIELD_GET(MT_WPDMA_DEBUG_VALUE, val); +} + +static bool mt7603_rx_fifo_busy(struct mt7603_dev *dev) +{ + if (is_mt7628(dev)) + return mt7603_dma_debug(dev, 9) & BIT(9); + + return mt7603_dma_debug(dev, 2) & BIT(8); +} + +static bool mt7603_rx_dma_busy(struct mt7603_dev *dev) +{ + if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_RX_DMA_BUSY)) + return false; + + return mt7603_rx_fifo_busy(dev); +} + +static bool mt7603_tx_dma_busy(struct mt7603_dev *dev) +{ + u32 val; + + if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_TX_DMA_BUSY)) + return false; + + val = mt7603_dma_debug(dev, 9); + return (val & BIT(8)) && (val & 0xf) != 0xf; +} + +static bool mt7603_tx_hang(struct mt7603_dev *dev) +{ + struct mt76_queue *q; + u32 dma_idx, prev_dma_idx; + int i; + + for (i = 0; i < 4; i++) { + q = &dev->mt76.q_tx[i]; + + if (!q->queued) + continue; + + prev_dma_idx = dev->tx_dma_idx[i]; + dma_idx = ioread32(&q->regs->dma_idx); + dev->tx_dma_idx[i] = dma_idx; + + if (dma_idx == prev_dma_idx && + dma_idx != ioread32(&q->regs->cpu_idx)) + break; + } + + return i < 4; +} + +static bool mt7603_rx_pse_busy(struct mt7603_dev *dev) +{ + u32 addr, val; + + if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES) + return true; + + if (mt7603_rx_fifo_busy(dev)) + return false; + + addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS); + mt76_wr(dev, addr, 3); + val = mt76_rr(dev, addr) >> 16; + + if (is_mt7628(dev) && (val & 0x4001) == 0x4001) + return true; + + return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001; +} + +static bool +mt7603_watchdog_check(struct mt7603_dev *dev, u8 *counter, + enum mt7603_reset_cause cause, + bool (*check)(struct mt7603_dev *dev)) +{ + if (dev->reset_test == cause + 1) { + dev->reset_test = 0; + goto trigger; + } + + if (check) { + if (!check(dev) && *counter < MT7603_WATCHDOG_TIMEOUT) { + *counter = 0; + return false; + } + + (*counter)++; + } + + if (*counter < MT7603_WATCHDOG_TIMEOUT) + return false; +trigger: + dev->cur_reset_cause = cause; + dev->reset_cause[cause]++; + return true; +} + +void mt7603_update_channel(struct mt76_dev *mdev) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct mt76_channel_state *state; + ktime_t cur_time; + u32 busy; + + if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) + return; + + state = mt76_channel_state(&dev->mt76, dev->mt76.chandef.chan); + busy = mt76_rr(dev, MT_MIB_STAT_PSCCA); + + spin_lock_bh(&dev->mt76.cc_lock); + cur_time = ktime_get_boottime(); + state->cc_busy += busy; + state->cc_active += ktime_to_us(ktime_sub(cur_time, dev->survey_time)); + dev->survey_time = cur_time; + spin_unlock_bh(&dev->mt76.cc_lock); +} + +void +mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val) +{ + u32 rxtd_6 = 0xd7c80000; + + if (val == dev->ed_strict_mode) + return; + + dev->ed_strict_mode = val; + + /* Ensure that ED/CCA does not trigger if disabled */ + if (!dev->ed_monitor) + rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x34); + else + rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x7d); + + if (dev->ed_monitor && !dev->ed_strict_mode) + rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x0f); + else + rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x10); + + mt76_wr(dev, MT_RXTD(6), rxtd_6); + + mt76_rmw_field(dev, MT_RXTD(13), MT_RXTD_13_ACI_TH_EN, + dev->ed_monitor && !dev->ed_strict_mode); +} + +static void +mt7603_edcca_check(struct mt7603_dev *dev) +{ + u32 val = mt76_rr(dev, MT_AGC(41)); + ktime_t cur_time; + int rssi0, rssi1; + u32 active; + u32 ed_busy; + + if (!dev->ed_monitor) + return; + + rssi0 = FIELD_GET(MT_AGC_41_RSSI_0, val); + if (rssi0 > 128) + rssi0 -= 256; + + rssi1 = FIELD_GET(MT_AGC_41_RSSI_1, val); + if (rssi1 > 128) + rssi1 -= 256; + + if (max(rssi0, rssi1) >= -40 && + dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH) + dev->ed_strong_signal++; + else if (dev->ed_strong_signal > 0) + dev->ed_strong_signal--; + + cur_time = ktime_get_boottime(); + ed_busy = mt76_rr(dev, MT_MIB_STAT_ED) & MT_MIB_STAT_ED_MASK; + + active = ktime_to_us(ktime_sub(cur_time, dev->ed_time)); + dev->ed_time = cur_time; + + if (!active) + return; + + if (100 * ed_busy / active > 90) { + if (dev->ed_trigger < 0) + dev->ed_trigger = 0; + dev->ed_trigger++; + } else { + if (dev->ed_trigger > 0) + dev->ed_trigger = 0; + dev->ed_trigger--; + } + + if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH || + dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH / 2) { + mt7603_edcca_set_strict(dev, true); + } else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) { + mt7603_edcca_set_strict(dev, false); + } + + if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH) + dev->ed_trigger = MT7603_EDCCA_BLOCK_TH; + else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) + dev->ed_trigger = -MT7603_EDCCA_BLOCK_TH; +} + +void mt7603_cca_stats_reset(struct mt7603_dev *dev) +{ + mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET); + mt76_clear(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET); + mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_EN); +} + +static void +mt7603_adjust_sensitivity(struct mt7603_dev *dev) +{ + u32 agc0 = dev->agc0, agc3 = dev->agc3; + u32 adj; + + if (!dev->sensitivity || dev->sensitivity < -100) { + dev->sensitivity = 0; + } else if (dev->sensitivity <= -84) { + adj = 7 + (dev->sensitivity + 92) / 2; + + agc0 = 0x56f0076f; + agc0 |= adj << 12; + agc0 |= adj << 16; + agc3 = 0x81d0d5e3; + } else if (dev->sensitivity <= -72) { + adj = 7 + (dev->sensitivity + 80) / 2; + + agc0 = 0x6af0006f; + agc0 |= adj << 8; + agc0 |= adj << 12; + agc0 |= adj << 16; + + agc3 = 0x8181d5e3; + } else { + if (dev->sensitivity > -54) + dev->sensitivity = -54; + + adj = 7 + (dev->sensitivity + 80) / 2; + + agc0 = 0x7ff0000f; + agc0 |= adj << 4; + agc0 |= adj << 8; + agc0 |= adj << 12; + agc0 |= adj << 16; + + agc3 = 0x818181e3; + } + + mt76_wr(dev, MT_AGC(0), agc0); + mt76_wr(dev, MT_AGC1(0), agc0); + + mt76_wr(dev, MT_AGC(3), agc3); + mt76_wr(dev, MT_AGC1(3), agc3); +} + +static void +mt7603_false_cca_check(struct mt7603_dev *dev) +{ + int pd_cck, pd_ofdm, mdrdy_cck, mdrdy_ofdm; + int false_cca; + int min_signal; + u32 val; + + val = mt76_rr(dev, MT_PHYCTRL_STAT_PD); + pd_cck = FIELD_GET(MT_PHYCTRL_STAT_PD_CCK, val); + pd_ofdm = FIELD_GET(MT_PHYCTRL_STAT_PD_OFDM, val); + + val = mt76_rr(dev, MT_PHYCTRL_STAT_MDRDY); + mdrdy_cck = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_CCK, val); + mdrdy_ofdm = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_OFDM, val); + + dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; + dev->false_cca_cck = pd_cck - mdrdy_cck; + + mt7603_cca_stats_reset(dev); + + min_signal = mt76_get_min_avg_rssi(&dev->mt76); + if (!min_signal) { + dev->sensitivity = 0; + dev->last_cca_adj = jiffies; + goto out; + } + + min_signal -= 15; + + false_cca = dev->false_cca_ofdm + dev->false_cca_cck; + if (false_cca > 600) { + if (!dev->sensitivity) + dev->sensitivity = -92; + else + dev->sensitivity += 2; + dev->last_cca_adj = jiffies; + } else if (false_cca < 100 || + time_after(jiffies, dev->last_cca_adj + 10 * HZ)) { + dev->last_cca_adj = jiffies; + if (!dev->sensitivity) + goto out; + + dev->sensitivity -= 2; + } + + if (dev->sensitivity && dev->sensitivity > min_signal) { + dev->sensitivity = min_signal; + dev->last_cca_adj = jiffies; + } + +out: + mt7603_adjust_sensitivity(dev); +} + +void mt7603_mac_work(struct work_struct *work) +{ + struct mt7603_dev *dev = container_of(work, struct mt7603_dev, + mac_work.work); + bool reset = false; + + mt76_tx_status_check(&dev->mt76, NULL, false); + + mutex_lock(&dev->mt76.mutex); + + dev->mac_work_count++; + mt7603_update_channel(&dev->mt76); + mt7603_edcca_check(dev); + + if (dev->mac_work_count == 10) + mt7603_false_cca_check(dev); + + if (mt7603_watchdog_check(dev, &dev->rx_pse_check, + RESET_CAUSE_RX_PSE_BUSY, + mt7603_rx_pse_busy) || + mt7603_watchdog_check(dev, &dev->beacon_check, + RESET_CAUSE_BEACON_STUCK, + NULL) || + mt7603_watchdog_check(dev, &dev->tx_hang_check, + RESET_CAUSE_TX_HANG, + mt7603_tx_hang) || + mt7603_watchdog_check(dev, &dev->tx_dma_check, + RESET_CAUSE_TX_BUSY, + mt7603_tx_dma_busy) || + mt7603_watchdog_check(dev, &dev->rx_dma_check, + RESET_CAUSE_RX_BUSY, + mt7603_rx_dma_busy) || + mt7603_watchdog_check(dev, &dev->mcu_hang, + RESET_CAUSE_MCU_HANG, + NULL) || + dev->reset_cause[RESET_CAUSE_RESET_FAILED]) { + dev->beacon_check = 0; + dev->tx_dma_check = 0; + dev->tx_hang_check = 0; + dev->rx_dma_check = 0; + dev->rx_pse_check = 0; + dev->mcu_hang = 0; + dev->rx_dma_idx = ~0; + memset(dev->tx_dma_idx, 0xff, sizeof(dev->tx_dma_idx)); + reset = true; + dev->mac_work_count = 0; + } + + if (dev->mac_work_count >= 10) + dev->mac_work_count = 0; + + mutex_unlock(&dev->mt76.mutex); + + if (reset) + mt7603_mac_watchdog_reset(dev); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, + msecs_to_jiffies(MT7603_WATCHDOG_TIME)); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.h b/drivers/net/wireless/mediatek/mt76/mt7603/mac.h new file mode 100644 index 000000000000..17e34ecf2bfb --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.h @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: ISC */ + +#ifndef __MT7603_MAC_H +#define __MT7603_MAC_H + +#define MT_RXD0_LENGTH GENMASK(15, 0) +#define MT_RXD0_PKT_TYPE GENMASK(31, 29) + +#define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) +#define MT_RXD0_NORMAL_IP_SUM BIT(23) +#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) +#define MT_RXD0_NORMAL_GROUP_1 BIT(25) +#define MT_RXD0_NORMAL_GROUP_2 BIT(26) +#define MT_RXD0_NORMAL_GROUP_3 BIT(27) +#define MT_RXD0_NORMAL_GROUP_4 BIT(28) + +enum rx_pkt_type { + PKT_TYPE_TXS = 0, + PKT_TYPE_TXRXV = 1, + PKT_TYPE_NORMAL = 2, + PKT_TYPE_RX_DUP_RFB = 3, + PKT_TYPE_RX_TMR = 4, + PKT_TYPE_RETRIEVE = 5, + PKT_TYPE_RX_EVENT = 7, +}; + +#define MT_RXD1_NORMAL_BSSID GENMASK(31, 26) +#define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24) +#define MT_RXD1_NORMAL_HDR_TRANS BIT(23) +#define MT_RXD1_NORMAL_HDR_OFFSET BIT(22) +#define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16) +#define MT_RXD1_NORMAL_CH_FREQ GENMASK(15, 8) +#define MT_RXD1_NORMAL_KEY_ID GENMASK(7, 6) +#define MT_RXD1_NORMAL_BEACON_UC BIT(5) +#define MT_RXD1_NORMAL_BEACON_MC BIT(4) +#define MT_RXD1_NORMAL_BCAST BIT(3) +#define MT_RXD1_NORMAL_MCAST BIT(2) +#define MT_RXD1_NORMAL_U2M BIT(1) +#define MT_RXD1_NORMAL_HTC_VLD BIT(0) + +#define MT_RXD2_NORMAL_NON_AMPDU BIT(31) +#define MT_RXD2_NORMAL_NON_AMPDU_SUB BIT(30) +#define MT_RXD2_NORMAL_NDATA BIT(29) +#define MT_RXD2_NORMAL_NULL_FRAME BIT(28) +#define MT_RXD2_NORMAL_FRAG BIT(27) +#define MT_RXD2_NORMAL_UDF_VALID BIT(26) +#define MT_RXD2_NORMAL_LLC_MIS BIT(25) +#define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) +#define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) +#define MT_RXD2_NORMAL_LEN_MISMATCH BIT(22) +#define MT_RXD2_NORMAL_TKIP_MIC_ERR BIT(21) +#define MT_RXD2_NORMAL_ICV_ERR BIT(20) +#define MT_RXD2_NORMAL_CLM BIT(19) +#define MT_RXD2_NORMAL_CM BIT(18) +#define MT_RXD2_NORMAL_FCS_ERR BIT(17) +#define MT_RXD2_NORMAL_SW_BIT BIT(16) +#define MT_RXD2_NORMAL_SEC_MODE GENMASK(15, 12) +#define MT_RXD2_NORMAL_TID GENMASK(11, 8) +#define MT_RXD2_NORMAL_WLAN_IDX GENMASK(7, 0) + +#define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) +#define MT_RXD3_NORMAL_PF_MODE BIT(29) +#define MT_RXD3_NORMAL_CLS_BITMAP GENMASK(28, 19) +#define MT_RXD3_NORMAL_WOL GENMASK(18, 14) +#define MT_RXD3_NORMAL_MAGIC_PKT BIT(13) +#define MT_RXD3_NORMAL_OFLD GENMASK(12, 11) +#define MT_RXD3_NORMAL_CLS BIT(10) +#define MT_RXD3_NORMAL_PATTERN_DROP BIT(9) +#define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8) +#define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) + +#define MT_RXV1_VHTA1_B5_B4 GENMASK(31, 30) +#define MT_RXV1_VHTA2_B8_B1 GENMASK(29, 22) +#define MT_RXV1_HT_NO_SOUND BIT(21) +#define MT_RXV1_HT_SMOOTH BIT(20) +#define MT_RXV1_HT_SHORT_GI BIT(19) +#define MT_RXV1_HT_AGGR BIT(18) +#define MT_RXV1_VHTA1_B22 BIT(17) +#define MT_RXV1_FRAME_MODE GENMASK(16, 15) +#define MT_RXV1_TX_MODE GENMASK(14, 12) +#define MT_RXV1_HT_EXT_LTF GENMASK(11, 10) +#define MT_RXV1_HT_AD_CODE BIT(9) +#define MT_RXV1_HT_STBC GENMASK(8, 7) +#define MT_RXV1_TX_RATE GENMASK(6, 0) + +#define MT_RXV2_VHTA1_B16_B6 GENMASK(31, 21) +#define MT_RXV2_LENGTH GENMASK(20, 0) + +#define MT_RXV3_F_AGC1_CAL_GAIN GENMASK(31, 29) +#define MT_RXV3_F_AGC1_EQ_CAL BIT(28) +#define MT_RXV3_RCPI1 GENMASK(27, 20) +#define MT_RXV3_F_AGC0_CAL_GAIN GENMASK(19, 17) +#define MT_RXV3_F_AGC0_EQ_CAL BIT(16) +#define MT_RXV3_RCPI0 GENMASK(15, 8) +#define MT_RXV3_SEL_ANT BIT(7) +#define MT_RXV3_ACI_DET_X BIT(6) +#define MT_RXV3_OFDM_FREQ_TRANS_DETECT BIT(5) +#define MT_RXV3_VHTA1_B21_B17 GENMASK(4, 0) + +#define MT_RXV4_F_AGC_CAL_GAIN GENMASK(31, 29) +#define MT_RXV4_F_AGC2_EQ_CAL BIT(28) +#define MT_RXV4_IB_RSSI1 GENMASK(27, 20) +#define MT_RXV4_F_AGC_LPF_GAIN_X GENMASK(19, 16) +#define MT_RXV4_WB_RSSI_X GENMASK(15, 8) +#define MT_RXV4_IB_RSSI0 GENMASK(7, 0) + +#define MT_RXV5_LTF_SNR0 GENMASK(31, 26) +#define MT_RXV5_LTF_PROC_TIME GENMASK(25, 19) +#define MT_RXV5_FOE GENMASK(18, 7) +#define MT_RXV5_C_AGC_SATE GENMASK(6, 4) +#define MT_RXV5_F_AGC_LNA_GAIN_0 GENMASK(3, 2) +#define MT_RXV5_F_AGC_LNA_GAIN_1 GENMASK(1, 0) + +#define MT_RXV6_C_AGC_STATE GENMASK(30, 28) +#define MT_RXV6_NS_TS_FIELD GENMASK(27, 25) +#define MT_RXV6_RX_VALID BIT(24) +#define MT_RXV6_NF2 GENMASK(23, 16) +#define MT_RXV6_NF1 GENMASK(15, 8) +#define MT_RXV6_NF0 GENMASK(7, 0) + +enum mt7603_tx_header_format { + MT_HDR_FORMAT_802_3, + MT_HDR_FORMAT_CMD, + MT_HDR_FORMAT_802_11, + MT_HDR_FORMAT_802_11_EXT, +}; + +#define MT_TXD_SIZE (8 * 4) + +#define MT_TXD0_P_IDX BIT(31) +#define MT_TXD0_Q_IDX GENMASK(30, 27) +#define MT_TXD0_UTXB BIT(26) +#define MT_TXD0_UNXV BIT(25) +#define MT_TXD0_UDP_TCP_SUM BIT(24) +#define MT_TXD0_IP_SUM BIT(23) +#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) +#define MT_TXD0_TX_BYTES GENMASK(15, 0) + +#define MT_TXD1_OWN_MAC GENMASK(31, 26) +#define MT_TXD1_PROTECTED BIT(23) +#define MT_TXD1_TID GENMASK(22, 20) +#define MT_TXD1_NO_ACK BIT(19) +#define MT_TXD1_HDR_PAD GENMASK(18, 16) +#define MT_TXD1_LONG_FORMAT BIT(15) +#define MT_TXD1_HDR_FORMAT GENMASK(14, 13) +#define MT_TXD1_HDR_INFO GENMASK(12, 8) +#define MT_TXD1_WLAN_IDX GENMASK(7, 0) + +#define MT_TXD2_FIX_RATE BIT(31) +#define MT_TXD2_TIMING_MEASURE BIT(30) +#define MT_TXD2_BA_DISABLE BIT(29) +#define MT_TXD2_POWER_OFFSET GENMASK(28, 24) +#define MT_TXD2_MAX_TX_TIME GENMASK(23, 16) +#define MT_TXD2_FRAG GENMASK(15, 14) +#define MT_TXD2_HTC_VLD BIT(13) +#define MT_TXD2_DURATION BIT(12) +#define MT_TXD2_BIP BIT(11) +#define MT_TXD2_MULTICAST BIT(10) +#define MT_TXD2_RTS BIT(9) +#define MT_TXD2_SOUNDING BIT(8) +#define MT_TXD2_NDPA BIT(7) +#define MT_TXD2_NDP BIT(6) +#define MT_TXD2_FRAME_TYPE GENMASK(5, 4) +#define MT_TXD2_SUB_TYPE GENMASK(3, 0) + +#define MT_TXD3_SN_VALID BIT(31) +#define MT_TXD3_PN_VALID BIT(30) +#define MT_TXD3_SEQ GENMASK(27, 16) +#define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) +#define MT_TXD3_TX_COUNT GENMASK(10, 6) + +#define MT_TXD4_PN_LOW GENMASK(31, 0) + +#define MT_TXD5_PN_HIGH GENMASK(31, 16) +#define MT_TXD5_SW_POWER_MGMT BIT(13) +#define MT_TXD5_BA_SEQ_CTRL BIT(12) +#define MT_TXD5_DA_SELECT BIT(11) +#define MT_TXD5_TX_STATUS_HOST BIT(10) +#define MT_TXD5_TX_STATUS_MCU BIT(9) +#define MT_TXD5_TX_STATUS_FMT BIT(8) +#define MT_TXD5_PID GENMASK(7, 0) + +#define MT_TXD6_SGI BIT(31) +#define MT_TXD6_LDPC BIT(30) +#define MT_TXD6_TX_RATE GENMASK(29, 18) +#define MT_TXD6_I_TXBF BIT(17) +#define MT_TXD6_E_TXBF BIT(16) +#define MT_TXD6_DYN_BW BIT(15) +#define MT_TXD6_ANT_PRI GENMASK(14, 12) +#define MT_TXD6_SPE_EN BIT(11) +#define MT_TXD6_FIXED_BW BIT(10) +#define MT_TXD6_BW GENMASK(9, 8) +#define MT_TXD6_ANT_ID GENMASK(7, 2) +#define MT_TXD6_FIXED_RATE BIT(0) + +#define MT_TX_RATE_STBC BIT(11) +#define MT_TX_RATE_NSS GENMASK(10, 9) +#define MT_TX_RATE_MODE GENMASK(8, 6) +#define MT_TX_RATE_IDX GENMASK(5, 0) + +#define MT_TXS0_ANTENNA GENMASK(31, 26) +#define MT_TXS0_TID GENMASK(25, 22) +#define MT_TXS0_BA_ERROR BIT(22) +#define MT_TXS0_PS_FLAG BIT(21) +#define MT_TXS0_TXOP_TIMEOUT BIT(20) +#define MT_TXS0_BIP_ERROR BIT(19) + +#define MT_TXS0_QUEUE_TIMEOUT BIT(18) +#define MT_TXS0_RTS_TIMEOUT BIT(17) +#define MT_TXS0_ACK_TIMEOUT BIT(16) +#define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) + +#define MT_TXS0_TX_STATUS_HOST BIT(15) +#define MT_TXS0_TX_STATUS_MCU BIT(14) +#define MT_TXS0_TXS_FORMAT BIT(13) +#define MT_TXS0_FIXED_RATE BIT(12) +#define MT_TXS0_TX_RATE GENMASK(11, 0) + +#define MT_TXS1_F0_TIMESTAMP GENMASK(31, 0) +#define MT_TXS1_F1_NOISE_2 GENMASK(23, 16) +#define MT_TXS1_F1_NOISE_1 GENMASK(15, 8) +#define MT_TXS1_F1_NOISE_0 GENMASK(7, 0) + +#define MT_TXS2_F0_FRONT_TIME GENMASK(24, 0) +#define MT_TXS2_F1_RCPI_2 GENMASK(23, 16) +#define MT_TXS2_F1_RCPI_1 GENMASK(15, 8) +#define MT_TXS2_F1_RCPI_0 GENMASK(7, 0) + +#define MT_TXS3_WCID GENMASK(31, 24) +#define MT_TXS3_RXV_SEQNO GENMASK(23, 16) +#define MT_TXS3_TX_DELAY GENMASK(15, 0) + +#define MT_TXS4_LAST_TX_RATE GENMASK(31, 29) +#define MT_TXS4_TX_COUNT GENMASK(28, 24) +#define MT_TXS4_AMPDU BIT(23) +#define MT_TXS4_ACKED_MPDU BIT(22) +#define MT_TXS4_PID GENMASK(21, 14) +#define MT_TXS4_BW GENMASK(13, 12) +#define MT_TXS4_F0_SEQNO GENMASK(11, 0) +#define MT_TXS4_F1_TSSI GENMASK(11, 0) + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c new file mode 100644 index 000000000000..b10775ed92e6 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -0,0 +1,709 @@ +/* SPDX-License-Identifier: ISC */ + +#include +#include +#include +#include +#include "mt7603.h" +#include "eeprom.h" + +static int +mt7603_start(struct ieee80211_hw *hw) +{ + struct mt7603_dev *dev = hw->priv; + + mt7603_mac_start(dev); + dev->survey_time = ktime_get_boottime(); + set_bit(MT76_STATE_RUNNING, &dev->mt76.state); + mt7603_mac_work(&dev->mac_work.work); + + return 0; +} + +static void +mt7603_stop(struct ieee80211_hw *hw) +{ + struct mt7603_dev *dev = hw->priv; + + clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); + cancel_delayed_work_sync(&dev->mac_work); + mt7603_mac_stop(dev); +} + +static int +mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; + struct mt7603_dev *dev = hw->priv; + struct mt76_txq *mtxq; + u8 bc_addr[ETH_ALEN]; + int idx; + int ret = 0; + + mutex_lock(&dev->mt76.mutex); + + mvif->idx = ffs(~dev->vif_mask) - 1; + if (mvif->idx >= MT7603_MAX_INTERFACES) { + ret = -ENOSPC; + goto out; + } + + mt76_wr(dev, MT_MAC_ADDR0(mvif->idx), + get_unaligned_le32(vif->addr)); + mt76_wr(dev, MT_MAC_ADDR1(mvif->idx), + (get_unaligned_le16(vif->addr + 4) | + MT_MAC_ADDR1_VALID)); + + if (vif->type == NL80211_IFTYPE_AP) { + mt76_wr(dev, MT_BSSID0(mvif->idx), + get_unaligned_le32(vif->addr)); + mt76_wr(dev, MT_BSSID1(mvif->idx), + (get_unaligned_le16(vif->addr + 4) | + MT_BSSID1_VALID)); + } + + idx = MT7603_WTBL_RESERVED - 1 - mvif->idx; + dev->vif_mask |= BIT(mvif->idx); + mvif->sta.wcid.idx = idx; + mvif->sta.wcid.hw_key_idx = -1; + + eth_broadcast_addr(bc_addr); + mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr); + + mtxq = (struct mt76_txq *)vif->txq->drv_priv; + mtxq->wcid = &mvif->sta.wcid; + mt76_txq_init(&dev->mt76, vif->txq); + rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); + +out: + mutex_unlock(&dev->mt76.mutex); + + return ret; +} + +static void +mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; + struct mt7603_dev *dev = hw->priv; + int idx = mvif->sta.wcid.idx; + + mt76_wr(dev, MT_MAC_ADDR0(mvif->idx), 0); + mt76_wr(dev, MT_MAC_ADDR1(mvif->idx), 0); + mt76_wr(dev, MT_BSSID0(mvif->idx), 0); + mt76_wr(dev, MT_BSSID1(mvif->idx), 0); + mt7603_beacon_set_timer(dev, mvif->idx, 0); + + rcu_assign_pointer(dev->mt76.wcid[idx], NULL); + mt76_txq_remove(&dev->mt76, vif->txq); + + mutex_lock(&dev->mt76.mutex); + dev->vif_mask &= ~BIT(mvif->idx); + mutex_unlock(&dev->mt76.mutex); +} + +static void +mt7603_init_edcca(struct mt7603_dev *dev) +{ + /* Set lower signal level to -65dBm */ + mt76_rmw_field(dev, MT_RXTD(8), MT_RXTD_8_LOWER_SIGNAL, 0x23); + + /* clear previous energy detect monitor results */ + mt76_rr(dev, MT_MIB_STAT_ED); + + if (dev->ed_monitor) + mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME); + else + mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME); + + dev->ed_strict_mode = 0xff; + dev->ed_strong_signal = 0; + dev->ed_time = ktime_get_boottime(); + + mt7603_edcca_set_strict(dev, false); +} + +static int +mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) +{ + u8 *rssi_data = (u8 *)dev->mt76.eeprom.data; + int idx, ret; + u8 bw = MT_BW_20; + bool failed = false; + + cancel_delayed_work_sync(&dev->mac_work); + + mutex_lock(&dev->mt76.mutex); + set_bit(MT76_RESET, &dev->mt76.state); + + mt76_set_channel(&dev->mt76); + mt7603_mac_stop(dev); + + if (def->width == NL80211_CHAN_WIDTH_40) + bw = MT_BW_40; + + dev->mt76.chandef = *def; + mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw); + ret = mt7603_mcu_set_channel(dev); + if (ret) { + failed = true; + goto out; + } + + if (def->chan->band == NL80211_BAND_5GHZ) { + idx = 1; + rssi_data += MT_EE_RSSI_OFFSET_5G; + } else { + idx = 0; + rssi_data += MT_EE_RSSI_OFFSET_2G; + } + + memcpy(dev->rssi_offset, rssi_data, sizeof(dev->rssi_offset)); + + idx |= (def->chan - + mt76_hw(dev)->wiphy->bands[def->chan->band]->channels) << 1; + mt76_wr(dev, MT_WF_RMAC_CH_FREQ, idx); + mt7603_mac_set_timing(dev); + mt7603_mac_start(dev); + + clear_bit(MT76_RESET, &dev->mt76.state); + + mt76_txq_schedule_all(&dev->mt76); + + ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, + MT7603_WATCHDOG_TIME); + + /* reset channel stats */ + mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_READ_CLR_DIS); + mt76_set(dev, MT_MIB_CTL, + MT_MIB_CTL_CCA_NAV_TX | MT_MIB_CTL_PSCCA_TIME); + mt76_rr(dev, MT_MIB_STAT_PSCCA); + mt7603_cca_stats_reset(dev); + + dev->survey_time = ktime_get_boottime(); + + mt7603_init_edcca(dev); + +out: + mutex_unlock(&dev->mt76.mutex); + + if (failed) + mt7603_mac_work(&dev->mac_work.work); + + return ret; +} + +static int +mt7603_config(struct ieee80211_hw *hw, u32 changed) +{ + struct mt7603_dev *dev = hw->priv; + int ret = 0; + + if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | + IEEE80211_CONF_CHANGE_POWER)) + ret = mt7603_set_channel(dev, &hw->conf.chandef); + + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + mutex_lock(&dev->mt76.mutex); + + if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) + dev->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; + else + dev->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; + + mt76_wr(dev, MT_WF_RFCR, dev->rxfilter); + + mutex_unlock(&dev->mt76.mutex); + } + + return ret; +} + +static void +mt7603_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, + unsigned int *total_flags, u64 multicast) +{ + struct mt7603_dev *dev = hw->priv; + u32 flags = 0; + +#define MT76_FILTER(_flag, _hw) do { \ + flags |= *total_flags & FIF_##_flag; \ + dev->rxfilter &= ~(_hw); \ + dev->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ + } while (0) + + dev->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | + MT_WF_RFCR_DROP_OTHER_BEACON | + MT_WF_RFCR_DROP_FRAME_REPORT | + MT_WF_RFCR_DROP_PROBEREQ | + MT_WF_RFCR_DROP_MCAST_FILTERED | + MT_WF_RFCR_DROP_MCAST | + MT_WF_RFCR_DROP_BCAST | + MT_WF_RFCR_DROP_DUPLICATE | + MT_WF_RFCR_DROP_A2_BSSID | + MT_WF_RFCR_DROP_UNWANTED_CTL | + MT_WF_RFCR_DROP_STBC_MULTI); + + MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | + MT_WF_RFCR_DROP_A3_MAC | + MT_WF_RFCR_DROP_A3_BSSID); + + MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL); + + MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | + MT_WF_RFCR_DROP_RTS | + MT_WF_RFCR_DROP_CTL_RSV | + MT_WF_RFCR_DROP_NDPA); + + *total_flags = flags; + mt76_wr(dev, MT_WF_RFCR, dev->rxfilter); +} + +static void +mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, u32 changed) +{ + struct mt7603_dev *dev = hw->priv; + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; + + mutex_lock(&dev->mt76.mutex); + + if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID)) { + if (info->assoc || info->ibss_joined) { + mt76_wr(dev, MT_BSSID0(mvif->idx), + get_unaligned_le32(info->bssid)); + mt76_wr(dev, MT_BSSID1(mvif->idx), + (get_unaligned_le16(info->bssid + 4) | + MT_BSSID1_VALID)); + } else { + mt76_wr(dev, MT_BSSID0(mvif->idx), 0); + mt76_wr(dev, MT_BSSID1(mvif->idx), 0); + } + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + int slottime = info->use_short_slot ? 9 : 20; + + if (slottime != dev->slottime) { + dev->slottime = slottime; + mt7603_mac_set_timing(dev); + } + } + + if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) { + int beacon_int = !!info->enable_beacon * info->beacon_int; + + tasklet_disable(&dev->pre_tbtt_tasklet); + mt7603_beacon_set_timer(dev, mvif->idx, beacon_int); + tasklet_enable(&dev->pre_tbtt_tasklet); + } + + mutex_unlock(&dev->mt76.mutex); +} + +int +mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; + int idx; + int ret = 0; + + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7603_WTBL_STA - 1); + if (idx < 0) + return -ENOSPC; + + __skb_queue_head_init(&msta->psq); + msta->ps = ~0; + msta->smps = ~0; + msta->wcid.sta = 1; + msta->wcid.idx = idx; + mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr); + mt7603_wtbl_set_ps(dev, msta, false); + + if (vif->type == NL80211_IFTYPE_AP) + set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags); + + return ret; +} + +void +mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + + mt7603_wtbl_update_cap(dev, sta); +} + +void +mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; + struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; + + spin_lock_bh(&dev->ps_lock); + __skb_queue_purge(&msta->psq); + mt7603_filter_tx(dev, wcid->idx, true); + spin_unlock_bh(&dev->ps_lock); + + mt7603_wtbl_clear(dev, wcid->idx); +} + +static void +mt7603_ps_tx_list(struct mt7603_dev *dev, struct sk_buff_head *list) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(list)) != NULL) + mt76_tx_queue_skb_raw(dev, skb_get_queue_mapping(skb), + skb, 0); +} + +void +mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) +{ + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; + struct sk_buff_head list; + + mt76_stop_tx_queues(&dev->mt76, sta, false); + mt7603_wtbl_set_ps(dev, msta, ps); + if (ps) + return; + + __skb_queue_head_init(&list); + + spin_lock_bh(&dev->ps_lock); + skb_queue_splice_tail_init(&msta->psq, &list); + spin_unlock_bh(&dev->ps_lock); + + mt7603_ps_tx_list(dev, &list); +} + +static void +mt7603_release_buffered_frames(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u16 tids, int nframes, + enum ieee80211_frame_release_type reason, + bool more_data) +{ + struct mt7603_dev *dev = hw->priv; + struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; + struct sk_buff_head list; + struct sk_buff *skb, *tmp; + + __skb_queue_head_init(&list); + + spin_lock_bh(&dev->ps_lock); + skb_queue_walk_safe(&msta->psq, skb, tmp) { + if (!nframes) + break; + + if (!(tids & BIT(skb->priority))) + continue; + + skb_set_queue_mapping(skb, MT_TXQ_PSD); + __skb_unlink(skb, &msta->psq); + __skb_queue_tail(&list, skb); + nframes--; + } + spin_unlock_bh(&dev->ps_lock); + + mt7603_ps_tx_list(dev, &list); + + if (nframes) + mt76_release_buffered_frames(hw, sta, tids, nframes, reason, + more_data); +} + +static int +mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct mt7603_dev *dev = hw->priv; + struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; + struct mt7603_sta *msta = sta ? (struct mt7603_sta *)sta->drv_priv : + &mvif->sta; + struct mt76_wcid *wcid = &msta->wcid; + int idx = key->keyidx; + + /* fall back to sw encryption for unsupported ciphers */ + switch (key->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + break; + default: + return -EOPNOTSUPP; + } + + /* + * The hardware does not support per-STA RX GTK, fall back + * to software mode for these. + */ + if ((vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT) && + (key->cipher == WLAN_CIPHER_SUITE_TKIP || + key->cipher == WLAN_CIPHER_SUITE_CCMP) && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + + if (cmd == SET_KEY) { + key->hw_key_idx = wcid->idx; + wcid->hw_key_idx = idx; + } else { + if (idx == wcid->hw_key_idx) + wcid->hw_key_idx = -1; + + key = NULL; + } + mt76_wcid_key_setup(&dev->mt76, wcid, key); + + return mt7603_wtbl_set_key(dev, wcid->idx, key); +} + +static int +mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct mt7603_dev *dev = hw->priv; + u16 cw_min = (1 << 5) - 1; + u16 cw_max = (1 << 10) - 1; + u32 val; + + queue = dev->mt76.q_tx[queue].hw_idx; + + if (params->cw_min) + cw_min = params->cw_min; + if (params->cw_max) + cw_max = params->cw_max; + + mutex_lock(&dev->mt76.mutex); + mt7603_mac_stop(dev); + + val = mt76_rr(dev, MT_WMM_TXOP(queue)); + val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue)); + val |= params->txop << MT_WMM_TXOP_SHIFT(queue); + mt76_wr(dev, MT_WMM_TXOP(queue), val); + + val = mt76_rr(dev, MT_WMM_AIFSN); + val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue)); + val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue); + mt76_wr(dev, MT_WMM_AIFSN, val); + + val = mt76_rr(dev, MT_WMM_CWMIN); + val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue)); + val |= cw_min << MT_WMM_CWMIN_SHIFT(queue); + mt76_wr(dev, MT_WMM_CWMIN, val); + + val = mt76_rr(dev, MT_WMM_CWMAX(queue)); + val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue)); + val |= cw_max << MT_WMM_CWMAX_SHIFT(queue); + mt76_wr(dev, MT_WMM_CWMAX(queue), val); + + mt7603_mac_start(dev); + mutex_unlock(&dev->mt76.mutex); + + return 0; +} + +static void +mt7603_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + const u8 *mac) +{ + struct mt7603_dev *dev = hw->priv; + + set_bit(MT76_SCANNING, &dev->mt76.state); + mt7603_beacon_set_timer(dev, -1, 0); +} + +static void +mt7603_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct mt7603_dev *dev = hw->priv; + + clear_bit(MT76_SCANNING, &dev->mt76.state); + mt7603_beacon_set_timer(dev, -1, dev->beacon_int); +} + +static void +mt7603_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop) +{ +} + +static int +mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_ampdu_params *params) +{ + enum ieee80211_ampdu_mlme_action action = params->action; + struct mt7603_dev *dev = hw->priv; + struct ieee80211_sta *sta = params->sta; + struct ieee80211_txq *txq = sta->txq[params->tid]; + struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 ba_size = params->buf_size; + struct mt76_txq *mtxq; + + if (!txq) + return -EINVAL; + + mtxq = (struct mt76_txq *)txq->drv_priv; + + switch (action) { + case IEEE80211_AMPDU_RX_START: + mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, *ssn, + params->buf_size); + mt7603_mac_rx_ba_reset(dev, sta->addr, tid); + break; + case IEEE80211_AMPDU_RX_STOP: + mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + mtxq->aggr = true; + mtxq->send_bar = false; + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, ba_size); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + mtxq->aggr = false; + ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn); + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); + break; + case IEEE80211_AMPDU_TX_START: + mtxq->agg_ssn = *ssn << 4; + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP_CONT: + mtxq->aggr = false; + mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + } + + return 0; +} + +static void +mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mt7603_dev *dev = hw->priv; + struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; + struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); + int i; + + spin_lock_bh(&dev->mt76.lock); + for (i = 0; i < ARRAY_SIZE(msta->rates); i++) { + msta->rates[i].idx = sta_rates->rate[i].idx; + msta->rates[i].count = sta_rates->rate[i].count; + msta->rates[i].flags = sta_rates->rate[i].flags; + + if (msta->rates[i].idx < 0 || !msta->rates[i].count) + break; + } + msta->n_rates = i; + mt7603_wtbl_set_rates(dev, msta, NULL, msta->rates); + msta->rate_probe = false; + mt7603_wtbl_set_smps(dev, msta, + sta->smps_mode == IEEE80211_SMPS_DYNAMIC); + spin_unlock_bh(&dev->mt76.lock); +} + +static void +mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) +{ + struct mt7603_dev *dev = hw->priv; + + dev->coverage_class = coverage_class; + mt7603_mac_set_timing(dev); +} + +static void mt7603_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_vif *vif = info->control.vif; + struct mt7603_dev *dev = hw->priv; + struct mt76_wcid *wcid = &dev->global_sta.wcid; + + if (control->sta) { + struct mt7603_sta *msta; + + msta = (struct mt7603_sta *)control->sta->drv_priv; + wcid = &msta->wcid; + } else if (vif) { + struct mt7603_vif *mvif; + + mvif = (struct mt7603_vif *)vif->drv_priv; + wcid = &mvif->sta.wcid; + } + + mt76_tx(&dev->mt76, control->sta, wcid, skb); +} + +static int +mt7603_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) +{ + return 0; +} + +const struct ieee80211_ops mt7603_ops = { + .tx = mt7603_tx, + .start = mt7603_start, + .stop = mt7603_stop, + .add_interface = mt7603_add_interface, + .remove_interface = mt7603_remove_interface, + .config = mt7603_config, + .configure_filter = mt7603_configure_filter, + .bss_info_changed = mt7603_bss_info_changed, + .sta_state = mt76_sta_state, + .set_key = mt7603_set_key, + .conf_tx = mt7603_conf_tx, + .sw_scan_start = mt7603_sw_scan, + .sw_scan_complete = mt7603_sw_scan_complete, + .flush = mt7603_flush, + .ampdu_action = mt7603_ampdu_action, + .get_txpower = mt76_get_txpower, + .wake_tx_queue = mt76_wake_tx_queue, + .sta_rate_tbl_update = mt7603_sta_rate_tbl_update, + .release_buffered_frames = mt7603_release_buffered_frames, + .set_coverage_class = mt7603_set_coverage_class, + .set_tim = mt7603_set_tim, + .get_survey = mt76_get_survey, +}; + +MODULE_LICENSE("Dual BSD/GPL"); + +static int __init mt7603_init(void) +{ + int ret; + + ret = platform_driver_register(&mt76_wmac_driver); + if (ret) + return ret; + +#ifdef CONFIG_PCI + ret = pci_register_driver(&mt7603_pci_driver); + if (ret) + platform_driver_unregister(&mt76_wmac_driver); +#endif + return ret; +} + +static void __exit mt7603_exit(void) +{ +#ifdef CONFIG_PCI + pci_unregister_driver(&mt7603_pci_driver); +#endif + platform_driver_unregister(&mt76_wmac_driver); +} + +module_init(mt7603_init); +module_exit(mt7603_exit); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c new file mode 100644 index 000000000000..4b0713f1fd5e --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c @@ -0,0 +1,483 @@ +/* SPDX-License-Identifier: ISC */ + +#include +#include "mt7603.h" +#include "mcu.h" +#include "eeprom.h" + +#define MCU_SKB_RESERVE 8 + +struct mt7603_fw_trailer { + char fw_ver[10]; + char build_date[15]; + __le32 dl_len; +} __packed; + +static int +__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, + int query, int *wait_seq) +{ + int hdrlen = dev->mcu_running ? sizeof(struct mt7603_mcu_txd) : 12; + struct mt76_dev *mdev = &dev->mt76; + struct mt7603_mcu_txd *txd; + u8 seq; + + if (!skb) + return -EINVAL; + + seq = ++mdev->mmio.mcu.msg_seq & 0xf; + if (!seq) + seq = ++mdev->mmio.mcu.msg_seq & 0xf; + + txd = (struct mt7603_mcu_txd *)skb_push(skb, hdrlen); + memset(txd, 0, hdrlen); + + txd->len = cpu_to_le16(skb->len); + if (cmd == -MCU_CMD_FW_SCATTER) + txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE_FW); + else + txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE); + txd->pkt_type = MCU_PKT_ID; + txd->seq = seq; + + if (cmd < 0) { + txd->cid = -cmd; + } else { + txd->cid = MCU_CMD_EXT_CID; + txd->ext_cid = cmd; + if (query != MCU_Q_NA) + txd->ext_cid_ack = 1; + } + + txd->set_query = query; + + if (wait_seq) + *wait_seq = seq; + + return mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0); +} + +static int +mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, + int query) +{ + struct mt76_dev *mdev = &dev->mt76; + unsigned long expires = jiffies + 3 * HZ; + struct mt7603_mcu_rxd *rxd; + int ret, seq; + + mutex_lock(&mdev->mmio.mcu.mutex); + + ret = __mt7603_mcu_msg_send(dev, skb, cmd, query, &seq); + if (ret) + goto out; + + while (1) { + bool check_seq = false; + + skb = mt76_mcu_get_response(&dev->mt76, expires); + if (!skb) { + dev_err(mdev->dev, + "MCU message %d (seq %d) timed out\n", + cmd, seq); + dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT; + ret = -ETIMEDOUT; + break; + } + + rxd = (struct mt7603_mcu_rxd *)skb->data; + if (seq == rxd->seq) + check_seq = true; + + dev_kfree_skb(skb); + + if (check_seq) + break; + } + +out: + mutex_unlock(&mdev->mmio.mcu.mutex); + + return ret; +} + +static int +mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len) +{ + struct { + __le32 addr; + __le32 len; + __le32 mode; + } req = { + .addr = cpu_to_le32(addr), + .len = cpu_to_le32(len), + .mode = cpu_to_le32(BIT(31)), + }; + struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); + + return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, + MCU_Q_NA); +} + +static int +mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len) +{ + struct sk_buff *skb; + int ret = 0; + + while (len > 0) { + int cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd), + len); + + skb = mt7603_mcu_msg_alloc(data, cur_len); + if (!skb) + return -ENOMEM; + + ret = __mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER, + MCU_Q_NA, NULL); + if (ret) + break; + + data += cur_len; + len -= cur_len; + } + + return ret; +} + +static int +mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr) +{ + struct { + __le32 override; + __le32 addr; + } req = { + .override = cpu_to_le32(addr ? 1 : 0), + .addr = cpu_to_le32(addr), + }; + struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); + + return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, + MCU_Q_NA); +} + +static int +mt7603_mcu_restart(struct mt7603_dev *dev) +{ + struct sk_buff *skb = mt7603_mcu_msg_alloc(NULL, 0); + + return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, + MCU_Q_NA); +} + +static int +mt7603_load_firmware(struct mt7603_dev *dev) +{ + const struct firmware *fw; + const struct mt7603_fw_trailer *hdr; + const char *firmware; + int dl_len; + u32 addr, val; + int ret; + + if (is_mt7628(dev)) { + if (mt76xx_rev(dev) == MT7628_REV_E1) + firmware = MT7628_FIRMWARE_E1; + else + firmware = MT7628_FIRMWARE_E2; + } else { + if (mt76xx_rev(dev) < MT7603_REV_E2) + firmware = MT7603_FIRMWARE_E1; + else + firmware = MT7603_FIRMWARE_E2; + } + + ret = request_firmware(&fw, firmware, dev->mt76.dev); + if (ret) + return ret; + + if (!fw || !fw->data || fw->size < sizeof(*hdr)) { + dev_err(dev->mt76.dev, "Invalid firmware\n"); + ret = -EINVAL; + goto out; + } + + hdr = (const struct mt7603_fw_trailer *)(fw->data + fw->size - + sizeof(*hdr)); + + dev_info(dev->mt76.dev, "Firmware Version: %.10s\n", hdr->fw_ver); + dev_info(dev->mt76.dev, "Build Time: %.15s\n", hdr->build_date); + + addr = mt7603_reg_map(dev, 0x50012498); + mt76_wr(dev, addr, 0x5); + mt76_wr(dev, addr, 0x5); + udelay(1); + + /* switch to bypass mode */ + mt76_rmw(dev, MT_SCH_4, MT_SCH_4_FORCE_QID, + MT_SCH_4_BYPASS | FIELD_PREP(MT_SCH_4_FORCE_QID, 5)); + + val = mt76_rr(dev, MT_TOP_MISC2); + if (val & BIT(1)) { + dev_info(dev->mt76.dev, "Firmware already running...\n"); + goto running; + } + + if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(0) | BIT(1), BIT(0), 500)) { + dev_err(dev->mt76.dev, "Timeout waiting for ROM code to become ready\n"); + ret = -EIO; + goto out; + } + + dl_len = le32_to_cpu(hdr->dl_len) + 4; + ret = mt7603_mcu_init_download(dev, MCU_FIRMWARE_ADDRESS, dl_len); + if (ret) { + dev_err(dev->mt76.dev, "Download request failed\n"); + goto out; + } + + ret = mt7603_mcu_send_firmware(dev, fw->data, dl_len); + if (ret) { + dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); + goto out; + } + + ret = mt7603_mcu_start_firmware(dev, MCU_FIRMWARE_ADDRESS); + if (ret) { + dev_err(dev->mt76.dev, "Failed to start firmware\n"); + goto out; + } + + if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(1), BIT(1), 500)) { + dev_err(dev->mt76.dev, "Timeout waiting for firmware to initialize\n"); + ret = -EIO; + goto out; + } + +running: + mt76_clear(dev, MT_SCH_4, MT_SCH_4_FORCE_QID | MT_SCH_4_BYPASS); + + mt76_set(dev, MT_SCH_4, BIT(8)); + mt76_clear(dev, MT_SCH_4, BIT(8)); + + dev->mcu_running = true; + dev_info(dev->mt76.dev, "firmware init done\n"); + +out: + release_firmware(fw); + + return ret; +} + +int mt7603_mcu_init(struct mt7603_dev *dev) +{ + mutex_init(&dev->mt76.mmio.mcu.mutex); + + return mt7603_load_firmware(dev); +} + +void mt7603_mcu_exit(struct mt7603_dev *dev) +{ + mt7603_mcu_restart(dev); + skb_queue_purge(&dev->mt76.mmio.mcu.res_q); +} + +int mt7603_mcu_set_eeprom(struct mt7603_dev *dev) +{ + static const u16 req_fields[] = { +#define WORD(_start) \ + _start, \ + _start + 1 +#define GROUP_2G(_start) \ + WORD(_start), \ + WORD(_start + 2), \ + WORD(_start + 4) + + MT_EE_NIC_CONF_0 + 1, + WORD(MT_EE_NIC_CONF_1), + MT_EE_WIFI_RF_SETTING, + MT_EE_TX_POWER_DELTA_BW40, + MT_EE_TX_POWER_DELTA_BW80 + 1, + MT_EE_TX_POWER_EXT_PA_5G, + MT_EE_TEMP_SENSOR_CAL, + GROUP_2G(MT_EE_TX_POWER_0_START_2G), + GROUP_2G(MT_EE_TX_POWER_1_START_2G), + WORD(MT_EE_TX_POWER_CCK), + WORD(MT_EE_TX_POWER_OFDM_2G_6M), + WORD(MT_EE_TX_POWER_OFDM_2G_24M), + WORD(MT_EE_TX_POWER_OFDM_2G_54M), + WORD(MT_EE_TX_POWER_HT_BPSK_QPSK), + WORD(MT_EE_TX_POWER_HT_16_64_QAM), + WORD(MT_EE_TX_POWER_HT_64_QAM), + MT_EE_ELAN_RX_MODE_GAIN, + MT_EE_ELAN_RX_MODE_NF, + MT_EE_ELAN_RX_MODE_P1DB, + MT_EE_ELAN_BYPASS_MODE_GAIN, + MT_EE_ELAN_BYPASS_MODE_NF, + MT_EE_ELAN_BYPASS_MODE_P1DB, + WORD(MT_EE_STEP_NUM_NEG_6_7), + WORD(MT_EE_STEP_NUM_NEG_4_5), + WORD(MT_EE_STEP_NUM_NEG_2_3), + WORD(MT_EE_STEP_NUM_NEG_0_1), + WORD(MT_EE_REF_STEP_24G), + WORD(MT_EE_STEP_NUM_PLUS_1_2), + WORD(MT_EE_STEP_NUM_PLUS_3_4), + WORD(MT_EE_STEP_NUM_PLUS_5_6), + MT_EE_STEP_NUM_PLUS_7, + MT_EE_XTAL_FREQ_OFFSET, + MT_EE_XTAL_TRIM_2_COMP, + MT_EE_XTAL_TRIM_3_COMP, + MT_EE_XTAL_WF_RFCAL, + + /* unknown fields below */ + WORD(0x24), + 0x34, + 0x39, + 0x3b, + WORD(0x42), + WORD(0x9e), + 0xf2, + WORD(0xf8), + 0xfa, + 0x12e, + WORD(0x130), WORD(0x132), WORD(0x134), WORD(0x136), + WORD(0x138), WORD(0x13a), WORD(0x13c), WORD(0x13e), + +#undef GROUP_2G +#undef WORD + + }; + struct req_data { + u16 addr; + u8 val; + u8 pad; + } __packed; + struct { + u8 buffer_mode; + u8 len; + u8 pad[2]; + } req_hdr = { + .buffer_mode = 1, + .len = ARRAY_SIZE(req_fields) - 1, + }; + struct sk_buff *skb; + struct req_data *data; + const int size = 0xff * sizeof(struct req_data); + u8 *eep = (u8 *)dev->mt76.eeprom.data; + int i; + + BUILD_BUG_ON(ARRAY_SIZE(req_fields) * sizeof(*data) > size); + + skb = mt7603_mcu_msg_alloc(NULL, size + sizeof(req_hdr)); + memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); + data = (struct req_data *)skb_put(skb, size); + memset(data, 0, size); + + for (i = 0; i < ARRAY_SIZE(req_fields); i++) { + data[i].addr = cpu_to_le16(req_fields[i]); + data[i].val = eep[req_fields[i]]; + data[i].pad = 0; + } + + return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE, + MCU_Q_SET); +} + +static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) +{ + struct { + u8 center_channel; + u8 tssi; + u8 temp_comp; + u8 target_power[2]; + u8 rate_power_delta[14]; + u8 bw_power_delta; + u8 ch_power_delta[6]; + u8 temp_comp_power[17]; + u8 reserved; + } req = { + .center_channel = dev->mt76.chandef.chan->hw_value, +#define EEP_VAL(n) ((u8 *)dev->mt76.eeprom.data)[n] + .tssi = EEP_VAL(MT_EE_NIC_CONF_1 + 1), + .temp_comp = EEP_VAL(MT_EE_NIC_CONF_1), + .target_power = { + EEP_VAL(MT_EE_TX_POWER_0_START_2G + 2), + EEP_VAL(MT_EE_TX_POWER_1_START_2G + 2) + }, + .bw_power_delta = EEP_VAL(MT_EE_TX_POWER_DELTA_BW40), + .ch_power_delta = { + EEP_VAL(MT_EE_TX_POWER_0_START_2G + 3), + EEP_VAL(MT_EE_TX_POWER_0_START_2G + 4), + EEP_VAL(MT_EE_TX_POWER_0_START_2G + 5), + EEP_VAL(MT_EE_TX_POWER_1_START_2G + 3), + EEP_VAL(MT_EE_TX_POWER_1_START_2G + 4), + EEP_VAL(MT_EE_TX_POWER_1_START_2G + 5) + }, +#undef EEP_VAL + }; + struct sk_buff *skb; + u8 *eep = (u8 *)dev->mt76.eeprom.data; + + memcpy(req.rate_power_delta, eep + MT_EE_TX_POWER_CCK, + sizeof(req.rate_power_delta)); + + memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7, + sizeof(req.temp_comp_power)); + + skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); + return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_TX_POWER_CTRL, + MCU_Q_SET); +} + +int mt7603_mcu_set_channel(struct mt7603_dev *dev) +{ + struct cfg80211_chan_def *chandef = &dev->mt76.chandef; + struct ieee80211_hw *hw = mt76_hw(dev); + int n_chains = __sw_hweight8(dev->mt76.antenna_mask); + struct { + u8 control_chan; + u8 center_chan; + u8 bw; + u8 tx_streams; + u8 rx_streams; + u8 _res0[7]; + u8 txpower[21]; + u8 _res1[3]; + } req = { + .control_chan = chandef->chan->hw_value, + .center_chan = chandef->chan->hw_value, + .bw = MT_BW_20, + .tx_streams = n_chains, + .rx_streams = n_chains, + }; + struct sk_buff *skb; + s8 tx_power; + int ret; + int i; + + if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_40) { + req.bw = MT_BW_40; + if (chandef->center_freq1 > chandef->chan->center_freq) + req.center_chan += 2; + else + req.center_chan -= 2; + } + + tx_power = hw->conf.power_level * 2; + if (dev->mt76.antenna_mask == 3) + tx_power -= 6; + tx_power = min(tx_power, dev->tx_power_limit); + + dev->mt76.txpower_cur = tx_power; + + for (i = 0; i < ARRAY_SIZE(req.txpower); i++) + req.txpower[i] = tx_power; + + skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); + ret = mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, + MCU_Q_SET); + if (ret) + return ret; + + return mt7603_mcu_set_tx_power(dev); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h new file mode 100644 index 000000000000..1bba369d5c8a --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: ISC */ + +#ifndef __MT7603_MCU_H +#define __MT7603_MCU_H + +struct mt7603_mcu_txd { + __le16 len; + __le16 pq_id; + + u8 cid; + u8 pkt_type; + u8 set_query; + u8 seq; + + u8 uc_d2b0_rev; + u8 ext_cid; + u8 uc_d2b2_rev; + u8 ext_cid_ack; + + u32 au4_d3_to_d7_rev[5]; +} __packed __aligned(4); + +struct mt7603_mcu_rxd { + __le16 len; + __le16 pkt_type_id; + + u8 eid; + u8 seq; + __le16 __rsv; + + u8 ext_eid; + u8 __rsv1[3]; +}; + +#define MCU_PKT_ID 0xa0 +#define MCU_PORT_QUEUE 0x8000 +#define MCU_PORT_QUEUE_FW 0xc000 + +#define MCU_FIRMWARE_ADDRESS 0x100000 + +enum { + MCU_Q_QUERY, + MCU_Q_SET, + MCU_Q_RESERVED, + MCU_Q_NA +}; + +enum { + MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01, + MCU_CMD_FW_START_REQ = 0x02, + MCU_CMD_INIT_ACCESS_REG = 0x3, + MCU_CMD_PATCH_START_REQ = 0x05, + MCU_CMD_PATCH_FINISH_REQ = 0x07, + MCU_CMD_PATCH_SEM_CONTROL = 0x10, + MCU_CMD_HIF_LOOPBACK = 0x20, + MCU_CMD_CH_PRIVILEGE = 0x20, + MCU_CMD_ACCESS_REG = 0xC2, + MCU_CMD_EXT_CID = 0xED, + MCU_CMD_FW_SCATTER = 0xEE, + MCU_CMD_RESTART_DL_REQ = 0xEF, +}; + +enum { + MCU_EXT_CMD_RF_REG_ACCESS = 0x02, + MCU_EXT_CMD_RF_TEST = 0x04, + MCU_EXT_CMD_RADIO_ON_OFF_CTRL = 0x05, + MCU_EXT_CMD_WIFI_RX_DISABLE = 0x06, + MCU_EXT_CMD_PM_STATE_CTRL = 0x07, + MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, + MCU_EXT_CMD_NIC_CAPABILITY = 0x09, + MCU_EXT_CMD_PWR_SAVING = 0x0A, + MCU_EXT_CMD_MULTIPLE_REG_ACCESS = 0x0E, + MCU_EXT_CMD_AP_PWR_SAVING_CAPABILITY = 0xF, + MCU_EXT_CMD_SEC_ADDREMOVE_KEY = 0x10, + MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, + MCU_EXT_CMD_FW_LOG_2_HOST = 0x13, + MCU_EXT_CMD_PS_RETRIEVE_START = 0x14, + MCU_EXT_CMD_LED_CTRL = 0x17, + MCU_EXT_CMD_PACKET_FILTER = 0x18, + MCU_EXT_CMD_PWR_MGT_BIT_WIFI = 0x1B, + MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, + MCU_EXT_CMD_THERMAL_PROTECT = 0x23, + MCU_EXT_CMD_EDCA_SET = 0x27, + MCU_EXT_CMD_SLOT_TIME_SET = 0x28, + MCU_EXT_CMD_CONFIG_INTERNAL_SETTING = 0x29, + MCU_EXT_CMD_NOA_OFFLOAD_CTRL = 0x2B, + MCU_EXT_CMD_GET_THEMAL_SENSOR = 0x2C, + MCU_EXT_CMD_WAKEUP_OPTION = 0x2E, + MCU_EXT_CMD_AC_QUEUE_CONTROL = 0x31, + MCU_EXT_CMD_BCN_UPDATE = 0x33 +}; + +enum { + MCU_EXT_EVENT_CMD_RESULT = 0x0, + MCU_EXT_EVENT_RF_REG_ACCESS = 0x2, + MCU_EXT_EVENT_MULTI_CR_ACCESS = 0x0E, + MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13, + MCU_EXT_EVENT_BEACON_LOSS = 0x1A, + MCU_EXT_EVENT_THERMAL_PROTECT = 0x22, + MCU_EXT_EVENT_BCN_UPDATE = 0x31, +}; + +static inline struct sk_buff * +mt7603_mcu_msg_alloc(const void *data, int len) +{ + return mt76_mcu_msg_alloc(data, sizeof(struct mt7603_mcu_txd), + len, 0); +} + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h new file mode 100644 index 000000000000..79f332429432 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: ISC */ + +#ifndef __MT7603_H +#define __MT7603_H + +#include +#include +#include "../mt76.h" +#include "regs.h" + +#define MT7603_MAX_INTERFACES 4 +#define MT7603_WTBL_SIZE 128 +#define MT7603_WTBL_RESERVED (MT7603_WTBL_SIZE - 1) +#define MT7603_WTBL_STA (MT7603_WTBL_RESERVED - MT7603_MAX_INTERFACES) + +#define MT7603_RATE_RETRY 2 + +#define MT7603_RX_RING_SIZE 128 + +#define MT7603_FIRMWARE_E1 "mt7603_e1.bin" +#define MT7603_FIRMWARE_E2 "mt7603_e2.bin" +#define MT7628_FIRMWARE_E1 "mt7628_e1.bin" +#define MT7628_FIRMWARE_E2 "mt7628_e2.bin" + +#define MT7603_EEPROM_SIZE 1024 + +#define MT_AGG_SIZE_LIMIT(_n) (((_n) + 1) * 4) + +#define MT7603_PRE_TBTT_TIME 5000 /* ms */ + +#define MT7603_WATCHDOG_TIME 100 /* ms */ +#define MT7603_WATCHDOG_TIMEOUT 10 /* number of checks */ + +#define MT7603_EDCCA_BLOCK_TH 10 + +#define MT7603_CFEND_RATE_DEFAULT 0x69 /* chip default (24M) */ +#define MT7603_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ + +struct mt7603_vif; +struct mt7603_sta; + +enum { + MT7603_REV_E1 = 0x00, + MT7603_REV_E2 = 0x10, + MT7628_REV_E1 = 0x8a00, +}; + +enum mt7603_bw { + MT_BW_20, + MT_BW_40, + MT_BW_80, +}; + +struct mt7603_sta { + struct mt76_wcid wcid; /* must be first */ + + struct mt7603_vif *vif; + + struct sk_buff_head psq; + + struct ieee80211_tx_rate rates[8]; + u8 rate_count; + u8 n_rates; + + u8 rate_probe; + u8 smps; + + u8 ps; +}; + +struct mt7603_vif { + struct mt7603_sta sta; /* must be first */ + + u8 idx; +}; + +enum mt7603_reset_cause { + RESET_CAUSE_TX_HANG, + RESET_CAUSE_TX_BUSY, + RESET_CAUSE_RX_BUSY, + RESET_CAUSE_BEACON_STUCK, + RESET_CAUSE_RX_PSE_BUSY, + RESET_CAUSE_MCU_HANG, + RESET_CAUSE_RESET_FAILED, + __RESET_CAUSE_MAX +}; + +struct mt7603_dev { + struct mt76_dev mt76; /* must be first */ + + const struct mt76_bus_ops *bus_ops; + + u32 rxfilter; + + u8 vif_mask; + + struct mt7603_sta global_sta; + + u32 agc0, agc3; + u32 false_cca_ofdm, false_cca_cck; + unsigned long last_cca_adj; + + u8 rssi_offset[3]; + + u8 slottime; + s16 coverage_class; + + s8 tx_power_limit; + + ktime_t survey_time; + ktime_t ed_time; + int beacon_int; + + struct mt76_queue q_rx; + + spinlock_t ps_lock; + + u8 mac_work_count; + + u8 mcu_running; + u8 ed_monitor; + + s8 ed_trigger; + u8 ed_strict_mode; + u8 ed_strong_signal; + + s8 sensitivity; + + u8 beacon_mask; + + u8 beacon_check; + u8 tx_hang_check; + u8 tx_dma_check; + u8 rx_dma_check; + u8 rx_pse_check; + u8 mcu_hang; + + enum mt7603_reset_cause cur_reset_cause; + + u16 tx_dma_idx[4]; + u16 rx_dma_idx; + + u32 reset_test; + + unsigned int reset_cause[__RESET_CAUSE_MAX]; + + struct delayed_work mac_work; + struct tasklet_struct tx_tasklet; + struct tasklet_struct pre_tbtt_tasklet; +}; + +extern const struct mt76_driver_ops mt7603_drv_ops; +extern const struct ieee80211_ops mt7603_ops; +extern struct pci_driver mt7603_pci_driver; +extern struct platform_driver mt76_wmac_driver; + +static inline bool is_mt7603(struct mt7603_dev *dev) +{ + return mt76xx_chip(dev) == 0x7603; +} + +static inline bool is_mt7628(struct mt7603_dev *dev) +{ + return mt76xx_chip(dev) == 0x7628; +} + +/* need offset to prevent conflict with ampdu_ack_len */ +#define MT_RATE_DRIVER_DATA_OFFSET 4 + +u32 mt7603_reg_map(struct mt7603_dev *dev, u32 addr); + +irqreturn_t mt7603_irq_handler(int irq, void *dev_instance); + +int mt7603_register_device(struct mt7603_dev *dev); +void mt7603_unregister_device(struct mt7603_dev *dev); +int mt7603_eeprom_init(struct mt7603_dev *dev); +int mt7603_dma_init(struct mt7603_dev *dev); +void mt7603_dma_cleanup(struct mt7603_dev *dev); +int mt7603_mcu_init(struct mt7603_dev *dev); +void mt7603_init_debugfs(struct mt7603_dev *dev); + +void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set); + +static inline void mt7603_irq_enable(struct mt7603_dev *dev, u32 mask) +{ + mt7603_set_irq_mask(dev, 0, mask); +} + +static inline void mt7603_irq_disable(struct mt7603_dev *dev, u32 mask) +{ + mt7603_set_irq_mask(dev, mask, 0); +} + +void mt7603_mac_dma_start(struct mt7603_dev *dev); +void mt7603_mac_start(struct mt7603_dev *dev); +void mt7603_mac_stop(struct mt7603_dev *dev); +void mt7603_mac_work(struct work_struct *work); +void mt7603_mac_set_timing(struct mt7603_dev *dev); +void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval); +int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb); +void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data); +void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid); +void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, + int ba_size); + +void mt7603_pse_client_reset(struct mt7603_dev *dev); + +int mt7603_mcu_set_channel(struct mt7603_dev *dev); +int mt7603_mcu_set_eeprom(struct mt7603_dev *dev); +void mt7603_mcu_exit(struct mt7603_dev *dev); + +void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, int vif, + const u8 *mac_addr); +void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx); +void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta); +void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, + struct ieee80211_tx_rate *probe_rate, + struct ieee80211_tx_rate *rates); +int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid, + struct ieee80211_key_conf *key); +void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, + bool enabled); +void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta, + bool enabled); +void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort); + +int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, + struct sk_buff *skb, struct mt76_queue *q, + struct mt76_wcid *wcid, struct ieee80211_sta *sta, + u32 *tx_info); + +void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, + struct mt76_queue_entry *e, bool flush); + +void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, + struct sk_buff *skb); +void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); +void mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); +int mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); +void mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + +void mt7603_pre_tbtt_tasklet(unsigned long arg); + +void mt7603_update_channel(struct mt76_dev *mdev); + +void mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val); +void mt7603_cca_stats_reset(struct mt7603_dev *dev); + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c new file mode 100644 index 000000000000..4acdbf5d8968 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: ISC */ + +#include +#include +#include + +#include "mt7603.h" + +static const struct pci_device_id mt76pci_device_table[] = { + { PCI_DEVICE(0x14c3, 0x7603) }, + { }, +}; + +static int +mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct mt7603_dev *dev; + struct mt76_dev *mdev; + int ret; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); + if (ret) + return ret; + + pci_set_master(pdev); + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops, + &mt7603_drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7603_dev, mt76); + mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]); + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + ret = devm_request_irq(mdev->dev, pdev->irq, mt7603_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto error; + + ret = mt7603_register_device(dev); + if (ret) + goto error; + + return 0; +error: + ieee80211_free_hw(mt76_hw(dev)); + return ret; +} + +static void +mt76pci_remove(struct pci_dev *pdev) +{ + struct mt76_dev *mdev = pci_get_drvdata(pdev); + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + + mt7603_unregister_device(dev); +} + +MODULE_DEVICE_TABLE(pci, mt76pci_device_table); +MODULE_FIRMWARE(MT7603_FIRMWARE_E1); +MODULE_FIRMWARE(MT7603_FIRMWARE_E2); + +struct pci_driver mt7603_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = mt76pci_device_table, + .probe = mt76pci_probe, + .remove = mt76pci_remove, +}; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h new file mode 100644 index 000000000000..da6827ae6cee --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h @@ -0,0 +1,774 @@ +/* SPDX-License-Identifier: ISC */ + +#ifndef __MT7603_REGS_H +#define __MT7603_REGS_H + +#define MT_HW_REV 0x1000 +#define MT_HW_CHIPID 0x1008 +#define MT_TOP_MISC2 0x1134 + +#define MT_MCU_BASE 0x2000 +#define MT_MCU(ofs) (MT_MCU_BASE + (ofs)) + +#define MT_MCU_PCIE_REMAP_1 MT_MCU(0x500) +#define MT_MCU_PCIE_REMAP_1_OFFSET GENMASK(17, 0) +#define MT_MCU_PCIE_REMAP_1_BASE GENMASK(31, 18) + +#define MT_MCU_PCIE_REMAP_2 MT_MCU(0x504) +#define MT_MCU_PCIE_REMAP_2_OFFSET GENMASK(18, 0) +#define MT_MCU_PCIE_REMAP_2_BASE GENMASK(31, 19) + +#define MT_HIF_BASE 0x4000 +#define MT_HIF(ofs) (MT_HIF_BASE + (ofs)) + +#define MT_INT_SOURCE_CSR MT_HIF(0x200) +#define MT_INT_MASK_CSR MT_HIF(0x204) +#define MT_DELAY_INT_CFG MT_HIF(0x210) + +#define MT_INT_RX_DONE(_n) BIT(_n) +#define MT_INT_RX_DONE_ALL GENMASK(1, 0) +#define MT_INT_TX_DONE_ALL GENMASK(19, 4) +#define MT_INT_TX_DONE(_n) BIT((_n) + 4) + +#define MT_INT_RX_COHERENT BIT(20) +#define MT_INT_TX_COHERENT BIT(21) +#define MT_INT_MAC_IRQ3 BIT(27) + +#define MT_INT_MCU_CMD BIT(30) + +#define MT_WPDMA_GLO_CFG MT_HIF(0x208) +#define MT_WPDMA_GLO_CFG_TX_DMA_EN BIT(0) +#define MT_WPDMA_GLO_CFG_TX_DMA_BUSY BIT(1) +#define MT_WPDMA_GLO_CFG_RX_DMA_EN BIT(2) +#define MT_WPDMA_GLO_CFG_RX_DMA_BUSY BIT(3) +#define MT_WPDMA_GLO_CFG_DMA_BURST_SIZE GENMASK(5, 4) +#define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE BIT(6) +#define MT_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7) +#define MT_WPDMA_GLO_CFG_HDR_SEG_LEN GENMASK(15, 8) +#define MT_WPDMA_GLO_CFG_SW_RESET BIT(24) +#define MT_WPDMA_GLO_CFG_FORCE_TX_EOF BIT(25) +#define MT_WPDMA_GLO_CFG_CLK_GATE_DIS BIT(30) +#define MT_WPDMA_GLO_CFG_RX_2B_OFFSET BIT(31) + +#define MT_WPDMA_RST_IDX MT_HIF(0x20c) + +#define MT_WPDMA_DEBUG MT_HIF(0x244) +#define MT_WPDMA_DEBUG_VALUE GENMASK(17, 0) +#define MT_WPDMA_DEBUG_SEL BIT(27) +#define MT_WPDMA_DEBUG_IDX GENMASK(31, 28) + +#define MT_TX_RING_BASE MT_HIF(0x300) +#define MT_RX_RING_BASE MT_HIF(0x400) + +#define MT_TXTIME_THRESH_BASE MT_HIF(0x500) +#define MT_TXTIME_THRESH(n) (MT_TXTIME_THRESH_BASE + ((n) * 4)) + +#define MT_PAGE_COUNT_BASE MT_HIF(0x540) +#define MT_PAGE_COUNT(n) (MT_PAGE_COUNT_BASE + ((n) * 4)) + +#define MT_SCH_1 MT_HIF(0x588) +#define MT_SCH_2 MT_HIF(0x58c) +#define MT_SCH_3 MT_HIF(0x590) + +#define MT_SCH_4 MT_HIF(0x594) +#define MT_SCH_4_FORCE_QID GENMASK(4, 0) +#define MT_SCH_4_BYPASS BIT(5) +#define MT_SCH_4_RESET BIT(8) + +#define MT_GROUP_THRESH_BASE MT_HIF(0x598) +#define MT_GROUP_THRESH(n) (MT_GROUP_THRESH_BASE + ((n) * 4)) + +#define MT_QUEUE_PRIORITY_1 MT_HIF(0x580) +#define MT_QUEUE_PRIORITY_2 MT_HIF(0x584) + +#define MT_BMAP_0 MT_HIF(0x5b0) +#define MT_BMAP_1 MT_HIF(0x5b4) +#define MT_BMAP_2 MT_HIF(0x5b8) + +#define MT_HIGH_PRIORITY_1 MT_HIF(0x5bc) +#define MT_HIGH_PRIORITY_2 MT_HIF(0x5c0) + +#define MT_PRIORITY_MASK MT_HIF(0x5c4) + +#define MT_RSV_MAX_THRESH MT_HIF(0x5c8) + +#define MT_PSE_BASE 0x8000 +#define MT_PSE(ofs) (MT_PSE_BASE + (ofs)) + +#define MT_MCU_DEBUG_RESET MT_PSE(0x16c) +#define MT_MCU_DEBUG_RESET_PSE BIT(0) +#define MT_MCU_DEBUG_RESET_PSE_S BIT(1) +#define MT_MCU_DEBUG_RESET_QUEUES GENMASK(6, 2) + +#define MT_PSE_FC_P0 MT_PSE(0x120) +#define MT_PSE_FC_P0_MIN_RESERVE GENMASK(11, 0) +#define MT_PSE_FC_P0_MAX_QUOTA GENMASK(27, 16) + +#define MT_PSE_FRP MT_PSE(0x138) +#define MT_PSE_FRP_P0 GENMASK(2, 0) +#define MT_PSE_FRP_P1 GENMASK(5, 3) +#define MT_PSE_FRP_P2_RQ0 GENMASK(8, 6) +#define MT_PSE_FRP_P2_RQ1 GENMASK(11, 9) +#define MT_PSE_FRP_P2_RQ2 GENMASK(14, 12) + +#define MT_FC_RSV_COUNT_0 MT_PSE(0x13c) +#define MT_FC_RSV_COUNT_0_P0 GENMASK(11, 0) +#define MT_FC_RSV_COUNT_0_P1 GENMASK(27, 16) + +#define MT_FC_SP2_Q0Q1 MT_PSE(0x14c) +#define MT_FC_SP2_Q0Q1_SRC_COUNT_Q0 GENMASK(11, 0) +#define MT_FC_SP2_Q0Q1_SRC_COUNT_Q1 GENMASK(27, 16) + +#define MT_PSE_FW_SHARED MT_PSE(0x17c) + +#define MT_PSE_RTA MT_PSE(0x194) +#define MT_PSE_RTA_QUEUE_ID GENMASK(4, 0) +#define MT_PSE_RTA_PORT_ID GENMASK(6, 5) +#define MT_PSE_RTA_REDIRECT_EN BIT(7) +#define MT_PSE_RTA_TAG_ID GENMASK(15, 8) +#define MT_PSE_RTA_WRITE BIT(16) +#define MT_PSE_RTA_BUSY BIT(31) + +#define MT_WF_PHY_BASE 0x10000 +#define MT_WF_PHY_OFFSET 0x1000 +#define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) + +#define MT_AGC_BASE MT_WF_PHY(0x500) +#define MT_AGC(n) (MT_AGC_BASE + ((n) * 4)) + +#define MT_AGC1_BASE MT_WF_PHY(0x1500) +#define MT_AGC1(n) (MT_AGC1_BASE + ((n) * 4)) + +#define MT_AGC_41_RSSI_0 GENMASK(23, 16) +#define MT_AGC_41_RSSI_1 GENMASK(7, 0) + +#define MT_RXTD_BASE MT_WF_PHY(0x600) +#define MT_RXTD(n) (MT_RXTD_BASE + ((n) * 4)) + +#define MT_RXTD_6_ACI_TH GENMASK(4, 0) +#define MT_RXTD_6_CCAED_TH GENMASK(14, 8) + +#define MT_RXTD_8_LOWER_SIGNAL GENMASK(5, 0) + +#define MT_RXTD_13_ACI_TH_EN BIT(0) + +#define MT_WF_PHY_CR_TSSI_BASE MT_WF_PHY(0xd00) +#define MT_WF_PHY_CR_TSSI(phy, n) (MT_WF_PHY_CR_TSSI_BASE + \ + ((phy) * MT_WF_PHY_OFFSET) + \ + ((n) * 4)) + +#define MT_PHYCTRL_BASE MT_WF_PHY(0x4100) +#define MT_PHYCTRL(n) (MT_PHYCTRL_BASE + ((n) * 4)) + +#define MT_PHYCTRL_2_STATUS_RESET BIT(6) +#define MT_PHYCTRL_2_STATUS_EN BIT(7) + +#define MT_PHYCTRL_STAT_PD MT_PHYCTRL(3) +#define MT_PHYCTRL_STAT_PD_OFDM GENMASK(31, 16) +#define MT_PHYCTRL_STAT_PD_CCK GENMASK(15, 0) + +#define MT_PHYCTRL_STAT_MDRDY MT_PHYCTRL(8) +#define MT_PHYCTRL_STAT_MDRDY_OFDM GENMASK(31, 16) +#define MT_PHYCTRL_STAT_MDRDY_CCK GENMASK(15, 0) + +#define MT_WF_AGG_BASE 0x21200 +#define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs)) + +#define MT_AGG_ARCR MT_WF_AGG(0x010) +#define MT_AGG_ARCR_INIT_RATE1 BIT(0) +#define MT_AGG_ARCR_FB_SGI_DISABLE BIT(1) +#define MT_AGG_ARCR_RATE8_DOWN_WRAP BIT(2) +#define MT_AGG_ARCR_RTS_RATE_THR GENMASK(12, 8) +#define MT_AGG_ARCR_RATE_DOWN_RATIO GENMASK(17, 16) +#define MT_AGG_ARCR_RATE_DOWN_RATIO_EN BIT(19) +#define MT_AGG_ARCR_RATE_UP_EXTRA_TH GENMASK(22, 20) +#define MT_AGG_ARCR_SPE_DIS_TH GENMASK(27, 24) + +#define MT_AGG_ARUCR MT_WF_AGG(0x014) +#define MT_AGG_ARDCR MT_WF_AGG(0x018) +#define MT_AGG_ARxCR_LIMIT_SHIFT(_n) (4 * (_n)) +#define MT_AGG_ARxCR_LIMIT(_n) GENMASK(2 + \ + MT_AGG_ARxCR_LIMIT_SHIFT(_n), \ + MT_AGG_ARxCR_LIMIT_SHIFT(_n)) + +#define MT_AGG_LIMIT MT_WF_AGG(0x040) +#define MT_AGG_LIMIT_1 MT_WF_AGG(0x044) +#define MT_AGG_LIMIT_AC(_n) GENMASK(((_n) + 1) * 8 - 1, (_n) * 8) + +#define MT_AGG_BA_SIZE_LIMIT_0 MT_WF_AGG(0x048) +#define MT_AGG_BA_SIZE_LIMIT_1 MT_WF_AGG(0x04c) +#define MT_AGG_BA_SIZE_LIMIT_SHIFT 8 + +#define MT_AGG_PCR MT_WF_AGG(0x050) +#define MT_AGG_PCR_MM BIT(16) +#define MT_AGG_PCR_GF BIT(17) +#define MT_AGG_PCR_BW40 BIT(18) +#define MT_AGG_PCR_RIFS BIT(19) +#define MT_AGG_PCR_BW80 BIT(20) +#define MT_AGG_PCR_BW160 BIT(21) +#define MT_AGG_PCR_ERP BIT(22) + +#define MT_AGG_PCR_RTS MT_WF_AGG(0x054) +#define MT_AGG_PCR_RTS_THR GENMASK(19, 0) +#define MT_AGG_PCR_RTS_PKT_THR GENMASK(31, 25) + +#define MT_AGG_CONTROL MT_WF_AGG(0x070) +#define MT_AGG_CONTROL_NO_BA_RULE BIT(0) +#define MT_AGG_CONTROL_NO_BA_AR_RULE BIT(1) +#define MT_AGG_CONTROL_CFEND_SPE_EN BIT(3) +#define MT_AGG_CONTROL_CFEND_RATE GENMASK(15, 4) +#define MT_AGG_CONTROL_BAR_SPE_EN BIT(19) +#define MT_AGG_CONTROL_BAR_RATE GENMASK(31, 20) + +#define MT_AGG_TMP MT_WF_AGG(0x0d8) + +#define MT_AGG_BWCR MT_WF_AGG(0x0ec) +#define MT_AGG_BWCR_BW GENMASK(3, 2) + +#define MT_AGG_RETRY_CONTROL MT_WF_AGG(0x0f4) +#define MT_AGG_RETRY_CONTROL_RTS_LIMIT GENMASK(11, 7) +#define MT_AGG_RETRY_CONTROL_BAR_LIMIT GENMASK(15, 12) + +#define MT_WF_DMA_BASE 0x21c00 +#define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs)) + +#define MT_DMA_DCR0 MT_WF_DMA(0x000) +#define MT_DMA_DCR1 MT_WF_DMA(0x004) + +#define MT_DMA_FQCR0 MT_WF_DMA(0x008) +#define MT_DMA_FQCR0_TARGET_WCID GENMASK(7, 0) +#define MT_DMA_FQCR0_TARGET_BSS GENMASK(13, 8) +#define MT_DMA_FQCR0_TARGET_QID GENMASK(20, 16) +#define MT_DMA_FQCR0_DEST_PORT_ID GENMASK(23, 22) +#define MT_DMA_FQCR0_DEST_QUEUE_ID GENMASK(28, 24) +#define MT_DMA_FQCR0_MODE BIT(29) +#define MT_DMA_FQCR0_STATUS BIT(30) +#define MT_DMA_FQCR0_BUSY BIT(31) + +#define MT_DMA_RCFR0 MT_WF_DMA(0x070) +#define MT_DMA_VCFR0 MT_WF_DMA(0x07c) + +#define MT_DMA_TCFR0 MT_WF_DMA(0x080) +#define MT_DMA_TCFR1 MT_WF_DMA(0x084) +#define MT_DMA_TCFR_TXS_AGGR_TIMEOUT GENMASK(27, 16) +#define MT_DMA_TCFR_TXS_QUEUE BIT(14) +#define MT_DMA_TCFR_TXS_AGGR_COUNT GENMASK(12, 8) +#define MT_DMA_TCFR_TXS_BIT_MAP GENMASK(6, 0) + +#define MT_DMA_TMCFR0 MT_WF_DMA(0x088) + +#define MT_WF_ARB_BASE 0x21400 +#define MT_WF_ARB(ofs) (MT_WF_ARB_BASE + (ofs)) + +#define MT_WMM_AIFSN MT_WF_ARB(0x020) +#define MT_WMM_AIFSN_MASK GENMASK(3, 0) +#define MT_WMM_AIFSN_SHIFT(_n) ((_n) * 4) + +#define MT_WMM_CWMAX_BASE MT_WF_ARB(0x028) +#define MT_WMM_CWMAX(_n) (MT_WMM_CWMAX_BASE + (((_n) / 2) << 2)) +#define MT_WMM_CWMAX_SHIFT(_n) (((_n) & 1) * 16) +#define MT_WMM_CWMAX_MASK GENMASK(15, 0) + +#define MT_WMM_CWMIN MT_WF_ARB(0x040) +#define MT_WMM_CWMIN_MASK GENMASK(7, 0) +#define MT_WMM_CWMIN_SHIFT(_n) ((_n) * 8) + +#define MT_WF_ARB_RQCR MT_WF_ARB(0x070) +#define MT_WF_ARB_RQCR_RX_START BIT(0) +#define MT_WF_ARB_RQCR_RXV_START BIT(4) +#define MT_WF_ARB_RQCR_RXV_R_EN BIT(7) +#define MT_WF_ARB_RQCR_RXV_T_EN BIT(8) + +#define MT_ARB_SCR MT_WF_ARB(0x080) +#define MT_ARB_SCR_BCNQ_OPMODE_MASK GENMASK(1, 0) +#define MT_ARB_SCR_BCNQ_OPMODE_SHIFT(n) ((n) * 2) +#define MT_ARB_SCR_TX_DISABLE BIT(8) +#define MT_ARB_SCR_RX_DISABLE BIT(9) +#define MT_ARB_SCR_BCNQ_EMPTY_SKIP BIT(28) +#define MT_ARB_SCR_TTTT_BTIM_PRIO BIT(29) +#define MT_ARB_SCR_TBTT_BCN_PRIO BIT(30) +#define MT_ARB_SCR_TBTT_BCAST_PRIO BIT(31) + +enum { + MT_BCNQ_OPMODE_STA = 0, + MT_BCNQ_OPMODE_AP = 1, + MT_BCNQ_OPMODE_ADHOC = 2, +}; + +#define MT_WF_ARB_TX_START_0 MT_WF_ARB(0x100) +#define MT_WF_ARB_TX_START_1 MT_WF_ARB(0x104) +#define MT_WF_ARB_TX_FLUSH_0 MT_WF_ARB(0x108) +#define MT_WF_ARB_TX_FLUSH_1 MT_WF_ARB(0x10c) +#define MT_WF_ARB_TX_STOP_0 MT_WF_ARB(0x110) +#define MT_WF_ARB_TX_STOP_1 MT_WF_ARB(0x114) + +#define MT_WF_ARB_BCN_START MT_WF_ARB(0x118) +#define MT_WF_ARB_BCN_START_BSSn(n) BIT(0 + (n)) +#define MT_WF_ARB_BCN_START_T_PRE_TTTT BIT(10) +#define MT_WF_ARB_BCN_START_T_TTTT BIT(11) +#define MT_WF_ARB_BCN_START_T_PRE_TBTT BIT(12) +#define MT_WF_ARB_BCN_START_T_TBTT BIT(13) +#define MT_WF_ARB_BCN_START_T_SLOT_IDLE BIT(14) +#define MT_WF_ARB_BCN_START_T_TX_START BIT(15) +#define MT_WF_ARB_BCN_START_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0) + +#define MT_WF_ARB_BCN_FLUSH MT_WF_ARB(0x11c) +#define MT_WF_ARB_BCN_FLUSH_BSSn(n) BIT(0 + (n)) +#define MT_WF_ARB_BCN_FLUSH_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0) + +#define MT_WF_ARB_CAB_START MT_WF_ARB(0x120) +#define MT_WF_ARB_CAB_START_BSSn(n) BIT(0 + (n)) +#define MT_WF_ARB_CAB_START_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0) + +#define MT_WF_ARB_CAB_FLUSH MT_WF_ARB(0x124) +#define MT_WF_ARB_CAB_FLUSH_BSSn(n) BIT(0 + (n)) +#define MT_WF_ARB_CAB_FLUSH_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0) + +#define MT_WF_ARB_CAB_COUNT(n) MT_WF_ARB(0x128 + (n) * 4) +#define MT_WF_ARB_CAB_COUNT_SHIFT 4 +#define MT_WF_ARB_CAB_COUNT_MASK GENMASK(3, 0) +#define MT_WF_ARB_CAB_COUNT_B0_REG(n) MT_WF_ARB_CAB_COUNT(((n) > 12 ? 2 : \ + ((n) > 4 ? 1 : 0))) +#define MT_WF_ARB_CAB_COUNT_B0_SHIFT(n) (((n) > 12 ? (n) - 12 : \ + ((n) > 4 ? (n) - 4 : \ + (n) ? (n) + 3 : 0)) * 4) + +#define MT_TX_ABORT MT_WF_ARB(0x134) +#define MT_TX_ABORT_EN BIT(0) +#define MT_TX_ABORT_WCID GENMASK(15, 8) + +#define MT_WF_TMAC_BASE 0x21600 +#define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs)) + +#define MT_TMAC_TCR MT_WF_TMAC(0x000) +#define MT_TMAC_TCR_BLINK_SEL GENMASK(7, 6) +#define MT_TMAC_TCR_PRE_RTS_GUARD GENMASK(11, 8) +#define MT_TMAC_TCR_PRE_RTS_SEC_IDLE GENMASK(13, 12) +#define MT_TMAC_TCR_RTS_SIGTA BIT(14) +#define MT_TMAC_TCR_LDPC_OFS BIT(15) +#define MT_TMAC_TCR_TX_STREAMS GENMASK(17, 16) +#define MT_TMAC_TCR_SCH_IDLE_SEL GENMASK(19, 18) +#define MT_TMAC_TCR_SCH_DET_PER_IOD BIT(20) +#define MT_TMAC_TCR_DCH_DET_DISABLE BIT(21) +#define MT_TMAC_TCR_TX_RIFS BIT(22) +#define MT_TMAC_TCR_RX_RIFS_MODE BIT(23) +#define MT_TMAC_TCR_TXOP_TBTT_CTL BIT(24) +#define MT_TMAC_TCR_TBTT_TX_STOP_CTL BIT(25) +#define MT_TMAC_TCR_TXOP_BURST_STOP BIT(26) +#define MT_TMAC_TCR_RDG_RA_MODE BIT(27) +#define MT_TMAC_TCR_RDG_RESP BIT(29) +#define MT_TMAC_TCR_RDG_NO_PENDING BIT(30) +#define MT_TMAC_TCR_SMOOTHING BIT(31) + +#define MT_WMM_TXOP_BASE MT_WF_TMAC(0x010) +#define MT_WMM_TXOP(_n) (MT_WMM_TXOP_BASE + \ + ((((_n) / 2) ^ 0x1) << 2)) +#define MT_WMM_TXOP_SHIFT(_n) (((_n) & 1) * 16) +#define MT_WMM_TXOP_MASK GENMASK(15, 0) + +#define MT_TIMEOUT_CCK MT_WF_TMAC(0x090) +#define MT_TIMEOUT_OFDM MT_WF_TMAC(0x094) +#define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) +#define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) + +#define MT_TXREQ MT_WF_TMAC(0x09c) +#define MT_TXREQ_CCA_SRC_SEL GENMASK(31, 30) + +#define MT_RXREQ MT_WF_TMAC(0x0a0) +#define MT_RXREQ_DELAY GENMASK(8, 0) + +#define MT_IFS MT_WF_TMAC(0x0a4) +#define MT_IFS_EIFS GENMASK(8, 0) +#define MT_IFS_RIFS GENMASK(14, 10) +#define MT_IFS_SIFS GENMASK(22, 16) +#define MT_IFS_SLOT GENMASK(30, 24) + +#define MT_TMAC_PCR MT_WF_TMAC(0x0b4) +#define MT_TMAC_PCR_RATE GENMASK(8, 0) +#define MT_TMAC_PCR_RATE_FIXED BIT(15) +#define MT_TMAC_PCR_ANT_ID GENMASK(21, 16) +#define MT_TMAC_PCR_ANT_ID_SEL BIT(22) +#define MT_TMAC_PCR_SPE_EN BIT(23) +#define MT_TMAC_PCR_ANT_PRI GENMASK(26, 24) +#define MT_TMAC_PCR_ANT_PRI_SEL GENMASK(27) + +#define MT_WF_RMAC_BASE 0x21800 +#define MT_WF_RMAC(ofs) (MT_WF_RMAC_BASE + (ofs)) + +#define MT_WF_RFCR MT_WF_RMAC(0x000) +#define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) +#define MT_WF_RFCR_DROP_FCSFAIL BIT(1) +#define MT_WF_RFCR_DROP_VERSION BIT(3) +#define MT_WF_RFCR_DROP_PROBEREQ BIT(4) +#define MT_WF_RFCR_DROP_MCAST BIT(5) +#define MT_WF_RFCR_DROP_BCAST BIT(6) +#define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7) +#define MT_WF_RFCR_DROP_A3_MAC BIT(8) +#define MT_WF_RFCR_DROP_A3_BSSID BIT(9) +#define MT_WF_RFCR_DROP_A2_BSSID BIT(10) +#define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11) +#define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12) +#define MT_WF_RFCR_DROP_CTL_RSV BIT(13) +#define MT_WF_RFCR_DROP_CTS BIT(14) +#define MT_WF_RFCR_DROP_RTS BIT(15) +#define MT_WF_RFCR_DROP_DUPLICATE BIT(16) +#define MT_WF_RFCR_DROP_OTHER_BSS BIT(17) +#define MT_WF_RFCR_DROP_OTHER_UC BIT(18) +#define MT_WF_RFCR_DROP_OTHER_TIM BIT(19) +#define MT_WF_RFCR_DROP_NDPA BIT(20) +#define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) + +#define MT_BSSID0(idx) MT_WF_RMAC(0x004 + (idx) * 8) +#define MT_BSSID1(idx) MT_WF_RMAC(0x008 + (idx) * 8) +#define MT_BSSID1_VALID BIT(16) + +#define MT_MAC_ADDR0(idx) MT_WF_RMAC(0x024 + (idx) * 8) +#define MT_MAC_ADDR1(idx) MT_WF_RMAC(0x028 + (idx) * 8) +#define MT_MAC_ADDR1_ADDR GENMASK(15, 0) +#define MT_MAC_ADDR1_VALID BIT(16) + +#define MT_BA_CONTROL_0 MT_WF_RMAC(0x068) +#define MT_BA_CONTROL_1 MT_WF_RMAC(0x06c) +#define MT_BA_CONTROL_1_ADDR GENMASK(15, 0) +#define MT_BA_CONTROL_1_TID GENMASK(19, 16) +#define MT_BA_CONTROL_1_IGNORE_TID BIT(20) +#define MT_BA_CONTROL_1_IGNORE_ALL BIT(21) +#define MT_BA_CONTROL_1_RESET BIT(22) + +#define MT_WF_RMACDR MT_WF_RMAC(0x078) +#define MT_WF_RMACDR_TSF_PROBERSP_DIS BIT(0) +#define MT_WF_RMACDR_TSF_TIM BIT(4) +#define MT_WF_RMACDR_MBSSID_MASK GENMASK(25, 24) +#define MT_WF_RMACDR_CHECK_HTC_BY_RATE BIT(26) +#define MT_WF_RMACDR_MAXLEN_20BIT BIT(30) + +#define MT_WF_RMAC_RMCR MT_WF_RMAC(0x080) +#define MT_WF_RMAC_RMCR_SMPS_MODE GENMASK(21, 20) +#define MT_WF_RMAC_RMCR_RX_STREAMS GENMASK(24, 22) +#define MT_WF_RMAC_RMCR_SMPS_RTS BIT(25) + +#define MT_WF_RMAC_CH_FREQ MT_WF_RMAC(0x090) +#define MT_WF_RMAC_MAXMINLEN MT_WF_RMAC(0x098) +#define MT_WF_RFCR1 MT_WF_RMAC(0x0a4) +#define MT_WF_RMAC_TMR_PA MT_WF_RMAC(0x0e0) + +#define MT_WF_SEC_BASE 0x21a00 +#define MT_WF_SEC(ofs) (MT_WF_SEC_BASE + (ofs)) + +#define MT_SEC_SCR MT_WF_SEC(0x004) +#define MT_SEC_SCR_MASK_ORDER GENMASK(1, 0) + +#define MT_WTBL_OFF_BASE 0x23000 +#define MT_WTBL_OFF(n) (MT_WTBL_OFF_BASE + (n)) + +#define MT_WTBL_UPDATE MT_WTBL_OFF(0x000) +#define MT_WTBL_UPDATE_WLAN_IDX GENMASK(7, 0) +#define MT_WTBL_UPDATE_WTBL2 BIT(11) +#define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) +#define MT_WTBL_UPDATE_RATE_UPDATE BIT(13) +#define MT_WTBL_UPDATE_TX_COUNT_CLEAR BIT(14) +#define MT_WTBL_UPDATE_RX_COUNT_CLEAR BIT(15) +#define MT_WTBL_UPDATE_BUSY BIT(16) + +#define MT_WTBL_RMVTCR MT_WTBL_OFF(0x008) +#define MT_WTBL_RMVTCR_RX_MV_MODE BIT(23) + +#define MT_LPON_BASE 0x24000 +#define MT_LPON(n) (MT_LPON_BASE + (n)) + +#define MT_LPON_BTEIR MT_LPON(0x020) +#define MT_LPON_BTEIR_MBSS_MODE GENMASK(31, 29) + +#define MT_PRE_TBTT MT_LPON(0x030) +#define MT_PRE_TBTT_MASK GENMASK(7, 0) +#define MT_PRE_TBTT_SHIFT 8 + +#define MT_TBTT MT_LPON(0x034) +#define MT_TBTT_PERIOD GENMASK(15, 0) +#define MT_TBTT_DTIM_PERIOD GENMASK(23, 16) +#define MT_TBTT_TBTT_WAKE_PERIOD GENMASK(27, 24) +#define MT_TBTT_DTIM_WAKE_PERIOD GENMASK(30, 28) +#define MT_TBTT_CAL_ENABLE BIT(31) + +#define MT_TBTT_TIMER_CFG MT_LPON(0x05c) + +#define MT_LPON_SBTOR(n) MT_LPON(0x0a0) +#define MT_LPON_SBTOR_SUB_BSS_EN BIT(29) +#define MT_LPON_SBTOR_TIME_OFFSET GENMASK(19, 0) + +#define MT_INT_WAKEUP_BASE 0x24400 +#define MT_INT_WAKEUP(n) (MT_INT_WAKEUP_BASE + (n)) + +#define MT_HW_INT_STATUS(n) MT_INT_WAKEUP(0x3c + (n) * 8) +#define MT_HW_INT_MASK(n) MT_INT_WAKEUP(0x40 + (n) * 8) + +#define MT_HW_INT3_TBTT0 BIT(15) +#define MT_HW_INT3_PRE_TBTT0 BIT(31) + +#define MT_WTBL1_BASE 0x28000 + +#define MT_WTBL_ON_BASE (MT_WTBL1_BASE + 0x2000) +#define MT_WTBL_ON(_n) (MT_WTBL_ON_BASE + (_n)) + +#define MT_WTBL_RIUCR0 MT_WTBL_ON(0x200) + +#define MT_WTBL_RIUCR1 MT_WTBL_ON(0x204) +#define MT_WTBL_RIUCR1_RATE0 GENMASK(11, 0) +#define MT_WTBL_RIUCR1_RATE1 GENMASK(23, 12) +#define MT_WTBL_RIUCR1_RATE2_LO GENMASK(31, 24) + +#define MT_WTBL_RIUCR2 MT_WTBL_ON(0x208) +#define MT_WTBL_RIUCR2_RATE2_HI GENMASK(3, 0) +#define MT_WTBL_RIUCR2_RATE3 GENMASK(15, 4) +#define MT_WTBL_RIUCR2_RATE4 GENMASK(27, 16) +#define MT_WTBL_RIUCR2_RATE5_LO GENMASK(31, 28) + +#define MT_WTBL_RIUCR3 MT_WTBL_ON(0x20c) +#define MT_WTBL_RIUCR3_RATE5_HI GENMASK(7, 0) +#define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8) +#define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20) + +#define MT_MIB_BASE 0x2c000 +#define MT_MIB(_n) (MT_MIB_BASE + (_n)) + +#define MT_MIB_CTL MT_MIB(0x00) +#define MT_MIB_CTL_PSCCA_TIME GENMASK(13, 11) +#define MT_MIB_CTL_CCA_NAV_TX GENMASK(16, 14) +#define MT_MIB_CTL_ED_TIME GENMASK(30, 28) +#define MT_MIB_CTL_READ_CLR_DIS BIT(31) + +#define MT_MIB_STAT(_n) MT_MIB(0x08 + (_n) * 4) + +#define MT_MIB_STAT_CCA MT_MIB_STAT(9) +#define MT_MIB_STAT_CCA_MASK GENMASK(23, 0) + +#define MT_MIB_STAT_PSCCA MT_MIB_STAT(16) +#define MT_MIB_STAT_PSCCA_MASK GENMASK(23, 0) + +#define MT_MIB_STAT_ED MT_MIB_STAT(18) +#define MT_MIB_STAT_ED_MASK GENMASK(23, 0) + +#define MT_PCIE_REMAP_BASE_1 0x40000 +#define MT_PCIE_REMAP_BASE_2 0x80000 + +#define MT_TX_HW_QUEUE_MGMT 4 +#define MT_TX_HW_QUEUE_MCU 5 +#define MT_TX_HW_QUEUE_BCN 7 +#define MT_TX_HW_QUEUE_BMC 8 + +#define MT_LED_BASE_PHYS 0x80024000 +#define MT_LED_PHYS(_n) (MT_LED_BASE_PHYS + (_n)) + +#define MT_LED_CTRL MT_LED_PHYS(0x00) + +#define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n))) +#define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n))) +#define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n))) +#define MT_LED_CTRL_TX_MANUAL_BLINK(_n) BIT(3 + (8 * (_n))) +#define MT_LED_CTRL_TX_OVER_BLINK(_n) BIT(5 + (8 * (_n))) +#define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n))) + +#define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x10 + ((_n) * 8)) +#define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x14 + ((_n) * 8)) +#define MT_LED_STATUS_OFF_MASK GENMASK(31, 24) +#define MT_LED_STATUS_OFF(_v) (((_v) << \ + __ffs(MT_LED_STATUS_OFF_MASK)) & \ + MT_LED_STATUS_OFF_MASK) +#define MT_LED_STATUS_ON_MASK GENMASK(23, 16) +#define MT_LED_STATUS_ON(_v) (((_v) << \ + __ffs(MT_LED_STATUS_ON_MASK)) & \ + MT_LED_STATUS_ON_MASK) +#define MT_LED_STATUS_DURATION_MASK GENMASK(15, 0) +#define MT_LED_STATUS_DURATION(_v) (((_v) << \ + __ffs(MT_LED_STATUS_DURATION_MASK)) &\ + MT_LED_STATUS_DURATION_MASK) + +#define MT_CLIENT_BASE_PHYS_ADDR 0x800c0000 + +#define MT_CLIENT_TMAC_INFO_TEMPLATE 0x040 + +#define MT_CLIENT_STATUS 0x06c + +#define MT_CLIENT_RESET_TX 0x070 +#define MT_CLIENT_RESET_TX_R_E_1 BIT(16) +#define MT_CLIENT_RESET_TX_R_E_2 BIT(17) +#define MT_CLIENT_RESET_TX_R_E_1_S BIT(20) +#define MT_CLIENT_RESET_TX_R_E_2_S BIT(21) + +#define MT_EFUSE_BASE 0x81070000 + +#define MT_EFUSE_BASE_CTRL 0x000 +#define MT_EFUSE_BASE_CTRL_EMPTY BIT(30) + +#define MT_EFUSE_CTRL 0x008 +#define MT_EFUSE_CTRL_AOUT GENMASK(5, 0) +#define MT_EFUSE_CTRL_MODE GENMASK(7, 6) +#define MT_EFUSE_CTRL_LDO_OFF_TIME GENMASK(13, 8) +#define MT_EFUSE_CTRL_LDO_ON_TIME GENMASK(15, 14) +#define MT_EFUSE_CTRL_AIN GENMASK(25, 16) +#define MT_EFUSE_CTRL_VALID BIT(29) +#define MT_EFUSE_CTRL_KICK BIT(30) +#define MT_EFUSE_CTRL_SEL BIT(31) + +#define MT_EFUSE_WDATA(_i) (0x010 + ((_i) * 4)) +#define MT_EFUSE_RDATA(_i) (0x030 + ((_i) * 4)) + +#define MT_CLIENT_RXINF 0x068 +#define MT_CLIENT_RXINF_RXSH_GROUPS GENMASK(2, 0) + +#define MT_PSE_BASE_PHYS_ADDR 0xa0000000 + +#define MT_PSE_WTBL_2_PHYS_ADDR 0xa5000000 + +#define MT_WTBL1_SIZE (8 * 4) +#define MT_WTBL2_SIZE (16 * 4) +#define MT_WTBL3_OFFSET (MT7603_WTBL_SIZE * MT_WTBL2_SIZE) +#define MT_WTBL3_SIZE (16 * 4) +#define MT_WTBL4_OFFSET (MT7603_WTBL_SIZE * MT_WTBL3_SIZE + \ + MT_WTBL3_OFFSET) +#define MT_WTBL4_SIZE (8 * 4) + +#define MT_WTBL1_W0_ADDR_HI GENMASK(15, 0) +#define MT_WTBL1_W0_MUAR_IDX GENMASK(21, 16) +#define MT_WTBL1_W0_RX_CHECK_A1 BIT(22) +#define MT_WTBL1_W0_KEY_IDX GENMASK(24, 23) +#define MT_WTBL1_W0_RX_CHECK_KEY_IDX BIT(25) +#define MT_WTBL1_W0_RX_KEY_VALID BIT(26) +#define MT_WTBL1_W0_RX_IK_VALID BIT(27) +#define MT_WTBL1_W0_RX_VALID BIT(28) +#define MT_WTBL1_W0_RX_CHECK_A2 BIT(29) +#define MT_WTBL1_W0_RX_DATA_VALID BIT(30) +#define MT_WTBL1_W0_WRITE_BURST BIT(31) + +#define MT_WTBL1_W1_ADDR_LO GENMASK(31, 0) + +#define MT_WTBL1_W2_MPDU_DENSITY GENMASK(2, 0) +#define MT_WTBL1_W2_KEY_TYPE GENMASK(6, 3) +#define MT_WTBL1_W2_EVEN_PN BIT(7) +#define MT_WTBL1_W2_TO_DS BIT(8) +#define MT_WTBL1_W2_FROM_DS BIT(9) +#define MT_WTBL1_W2_HEADER_TRANS BIT(10) +#define MT_WTBL1_W2_AMPDU_FACTOR GENMASK(13, 11) +#define MT_WTBL1_W2_PWR_MGMT BIT(14) +#define MT_WTBL1_W2_RDG BIT(15) +#define MT_WTBL1_W2_RTS BIT(16) +#define MT_WTBL1_W2_CFACK BIT(17) +#define MT_WTBL1_W2_RDG_BA BIT(18) +#define MT_WTBL1_W2_SMPS BIT(19) +#define MT_WTBL1_W2_TXS_BAF_REPORT BIT(20) +#define MT_WTBL1_W2_DYN_BW BIT(21) +#define MT_WTBL1_W2_LDPC BIT(22) +#define MT_WTBL1_W2_ITXBF BIT(23) +#define MT_WTBL1_W2_ETXBF BIT(24) +#define MT_WTBL1_W2_TXOP_PS BIT(25) +#define MT_WTBL1_W2_MESH BIT(26) +#define MT_WTBL1_W2_QOS BIT(27) +#define MT_WTBL1_W2_HT BIT(28) +#define MT_WTBL1_W2_VHT BIT(29) +#define MT_WTBL1_W2_ADMISSION_CONTROL BIT(30) +#define MT_WTBL1_W2_GROUP_ID BIT(31) + +#define MT_WTBL1_W3_WTBL2_FRAME_ID GENMASK(10, 0) +#define MT_WTBL1_W3_WTBL2_ENTRY_ID GENMASK(15, 11) +#define MT_WTBL1_W3_WTBL4_FRAME_ID GENMASK(26, 16) +#define MT_WTBL1_W3_CHECK_PER BIT(27) +#define MT_WTBL1_W3_KEEP_I_PSM BIT(28) +#define MT_WTBL1_W3_I_PSM BIT(29) +#define MT_WTBL1_W3_POWER_SAVE BIT(30) +#define MT_WTBL1_W3_SKIP_TX BIT(31) + +#define MT_WTBL1_W4_WTBL3_FRAME_ID GENMASK(10, 0) +#define MT_WTBL1_W4_WTBL3_ENTRY_ID GENMASK(16, 11) +#define MT_WTBL1_W4_WTBL4_ENTRY_ID GENMASK(22, 17) +#define MT_WTBL1_W4_PARTIAL_AID GENMASK(31, 23) + +#define MT_WTBL2_W0_PN_LO GENMASK(31, 0) + +#define MT_WTBL2_W1_PN_HI GENMASK(15, 0) +#define MT_WTBL2_W1_NON_QOS_SEQNO GENMASK(27, 16) + +#define MT_WTBL2_W2_TID0_SN GENMASK(11, 0) +#define MT_WTBL2_W2_TID1_SN GENMASK(23, 12) +#define MT_WTBL2_W2_TID2_SN_LO GENMASK(31, 24) + +#define MT_WTBL2_W3_TID2_SN_HI GENMASK(3, 0) +#define MT_WTBL2_W3_TID3_SN GENMASK(15, 4) +#define MT_WTBL2_W3_TID4_SN GENMASK(27, 16) +#define MT_WTBL2_W3_TID5_SN_LO GENMASK(31, 28) + +#define MT_WTBL2_W4_TID5_SN_HI GENMASK(7, 0) +#define MT_WTBL2_W4_TID6_SN GENMASK(19, 8) +#define MT_WTBL2_W4_TID7_SN GENMASK(31, 20) + +#define MT_WTBL2_W5_TX_COUNT_RATE1 GENMASK(15, 0) +#define MT_WTBL2_W5_FAIL_COUNT_RATE1 GENAMSK(31, 16) + +#define MT_WTBL2_W6_TX_COUNT_RATE2 GENMASK(7, 0) +#define MT_WTBL2_W6_TX_COUNT_RATE3 GENMASK(15, 8) +#define MT_WTBL2_W6_TX_COUNT_RATE4 GENMASK(23, 16) +#define MT_WTBL2_W6_TX_COUNT_RATE5 GENMASK(31, 24) + +#define MT_WTBL2_W7_TX_COUNT_CUR_BW GENMASK(15, 0) +#define MT_WTBL2_W7_FAIL_COUNT_CUR_BW GENMASK(31, 16) + +#define MT_WTBL2_W8_TX_COUNT_OTHER_BW GENMASK(15, 0) +#define MT_WTBL2_W8_FAIL_COUNT_OTHER_BW GENMASK(31, 16) + +#define MT_WTBL2_W9_POWER_OFFSET GENMASK(4, 0) +#define MT_WTBL2_W9_SPATIAL_EXT BIT(5) +#define MT_WTBL2_W9_ANT_PRIORITY GENMASK(8, 6) +#define MT_WTBL2_W9_CC_BW_SEL GENMASK(10, 9) +#define MT_WTBL2_W9_CHANGE_BW_RATE GENMASK(13, 11) +#define MT_WTBL2_W9_BW_CAP GENMASK(15, 14) +#define MT_WTBL2_W9_SHORT_GI_20 BIT(16) +#define MT_WTBL2_W9_SHORT_GI_40 BIT(17) +#define MT_WTBL2_W9_SHORT_GI_80 BIT(18) +#define MT_WTBL2_W9_SHORT_GI_160 BIT(19) +#define MT_WTBL2_W9_MPDU_FAIL_COUNT GENMASK(25, 23) +#define MT_WTBL2_W9_MPDU_OK_COUNT GENMASK(28, 26) +#define MT_WTBL2_W9_RATE_IDX GENMASK(31, 29) + +#define MT_WTBL2_W10_RATE1 GENMASK(11, 0) +#define MT_WTBL2_W10_RATE2 GENMASK(23, 12) +#define MT_WTBL2_W10_RATE3_LO GENMASK(31, 24) + +#define MT_WTBL2_W11_RATE3_HI GENMASK(3, 0) +#define MT_WTBL2_W11_RATE4 GENMASK(15, 4) +#define MT_WTBL2_W11_RATE5 GENMASK(27, 16) +#define MT_WTBL2_W11_RATE6_LO GENMASK(31, 28) + +#define MT_WTBL2_W12_RATE6_HI GENMASK(7, 0) +#define MT_WTBL2_W12_RATE7 GENMASK(19, 8) +#define MT_WTBL2_W12_RATE8 GENMASK(31, 20) + +#define MT_WTBL2_W13_AVG_RCPI0 GENMASK(7, 0) +#define MT_WTBL2_W13_AVG_RCPI1 GENMASK(15, 8) +#define MT_WTBL2_W13_AVG_RCPI2 GENAMSK(23, 16) + +#define MT_WTBL2_W14_CC_NOISE_1S GENMASK(6, 0) +#define MT_WTBL2_W14_CC_NOISE_2S GENMASK(13, 7) +#define MT_WTBL2_W14_CC_NOISE_3S GENMASK(20, 14) +#define MT_WTBL2_W14_CHAN_EST_RMS GENMASK(24, 21) +#define MT_WTBL2_W14_CC_NOISE_SEL BIT(15) +#define MT_WTBL2_W14_ANT_SEL GENMASK(31, 26) + +#define MT_WTBL2_W15_BA_WIN_SIZE GENMASK(2, 0) +#define MT_WTBL2_W15_BA_WIN_SIZE_SHIFT 3 +#define MT_WTBL2_W15_BA_EN_TIDS GENMASK(31, 24) + +#define MT_WTBL1_OR (MT_WTBL1_BASE + 0x2300) +#define MT_WTBL1_OR_PSM_WRITE BIT(31) + +enum mt7603_cipher_type { + MT_CIPHER_NONE, + MT_CIPHER_WEP40, + MT_CIPHER_TKIP, + MT_CIPHER_TKIP_NO_MIC, + MT_CIPHER_AES_CCMP, + MT_CIPHER_WEP104, + MT_CIPHER_BIP_CMAC_128, + MT_CIPHER_WEP128, + MT_CIPHER_WAPI, +}; + +#endif diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c new file mode 100644 index 000000000000..e13fea80d970 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: ISC */ + +#include +#include +#include + +#include "mt7603.h" + +static int +mt76_wmac_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + struct mt7603_dev *dev; + void __iomem *mem_base; + struct mt76_dev *mdev; + int irq; + int ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get device IRQ\n"); + return irq; + } + + mem_base = devm_ioremap_resource(&pdev->dev, res); + if (!mem_base) { + dev_err(&pdev->dev, "Failed to get memory resource\n"); + return -EINVAL; + } + + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops, + &mt7603_drv_ops); + if (!mdev) + return -ENOMEM; + + dev = container_of(mdev, struct mt7603_dev, mt76); + mt76_mmio_init(mdev, mem_base); + + mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | + (mt76_rr(dev, MT_HW_REV) & 0xff); + dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + + ret = devm_request_irq(mdev->dev, irq, mt7603_irq_handler, + IRQF_SHARED, KBUILD_MODNAME, dev); + if (ret) + goto error; + + ret = mt7603_register_device(dev); + if (ret) + goto error; + + return 0; +error: + ieee80211_free_hw(mt76_hw(dev)); + return ret; +} + +static int +mt76_wmac_remove(struct platform_device *pdev) +{ + struct mt76_dev *mdev = platform_get_drvdata(pdev); + struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); + + mt7603_unregister_device(dev); + + return 0; +} + +static const struct of_device_id of_wmac_match[] = { + { .compatible = "mediatek,mt7628-wmac" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_wmac_match); +MODULE_FIRMWARE(MT7628_FIRMWARE_E1); +MODULE_FIRMWARE(MT7628_FIRMWARE_E2); + +struct platform_driver mt76_wmac_driver = { + .probe = mt76_wmac_probe, + .remove = mt76_wmac_remove, + .driver = { + .name = "mt76_wmac", + .of_match_table = of_wmac_match, + }, +}; -- cgit v1.2.3 From 02f73d3a9bdbdf070481118f7af0860e617f2aed Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Mon, 25 Feb 2019 11:45:44 +0200 Subject: ath10k: fix descriptor size in ce tx completion for WCN3990 When the driver receives the tx completion of the descriptor over ce, it clears the nbytes configured for that particular descriptor. WCN3990 uses ce descriptors with 64-bit address. Currently during handling the tx completion of the descriptors, the nbytes are accessed from the descriptors using ce_desc for 32-bit targets. This will lead to clearing of memory at incorrect offset if DMA MASK is set to greater than 32 bits. Attach different ce tx copy completed handler for targets using address above 32-bit address. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01387-QCAHLSWMTPLZ-1 Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 66 ++++++++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/ce.h | 2 ++ 2 files changed, 66 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index cc154a81737d..24b983edb357 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1066,8 +1066,8 @@ EXPORT_SYMBOL(ath10k_ce_revoke_recv_next); * Guts of ath10k_ce_completed_send_next. * The caller takes responsibility for any necessary locking. */ -int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp) +static int _ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, + void **per_transfer_contextp) { struct ath10k_ce_ring *src_ring = ce_state->src_ring; u32 ctrl_addr = ce_state->ctrl_addr; @@ -1118,6 +1118,66 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, return 0; } + +static int _ath10k_ce_completed_send_next_nolock_64(struct ath10k_ce_pipe *ce_state, + void **per_transfer_contextp) +{ + struct ath10k_ce_ring *src_ring = ce_state->src_ring; + u32 ctrl_addr = ce_state->ctrl_addr; + struct ath10k *ar = ce_state->ar; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; + unsigned int read_index; + struct ce_desc_64 *desc; + + if (src_ring->hw_index == sw_index) { + /* + * The SW completion index has caught up with the cached + * version of the HW completion index. + * Update the cached HW completion index to see whether + * the SW has really caught up to the HW, or if the cached + * value of the HW index has become stale. + */ + + read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); + if (read_index == 0xffffffff) + return -ENODEV; + + read_index &= nentries_mask; + src_ring->hw_index = read_index; + } + + if (ar->hw_params.rri_on_ddr) + read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); + else + read_index = src_ring->hw_index; + + if (read_index == sw_index) + return -EIO; + + if (per_transfer_contextp) + *per_transfer_contextp = + src_ring->per_transfer_context[sw_index]; + + /* sanity */ + src_ring->per_transfer_context[sw_index] = NULL; + desc = CE_SRC_RING_TO_DESC_64(src_ring->base_addr_owner_space, + sw_index); + desc->nbytes = 0; + + /* Update sw_index */ + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); + src_ring->sw_index = sw_index; + + return 0; +} + +int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, + void **per_transfer_contextp) +{ + return ce_state->ops->ce_completed_send_next_nolock(ce_state, + per_transfer_contextp); +} EXPORT_SYMBOL(ath10k_ce_completed_send_next_nolock); static void ath10k_ce_extract_desc_data(struct ath10k *ar, @@ -1839,6 +1899,7 @@ static const struct ath10k_ce_ops ce_ops = { .ce_send_nolock = _ath10k_ce_send_nolock, .ce_set_src_ring_base_addr_hi = NULL, .ce_set_dest_ring_base_addr_hi = NULL, + .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock, }; static const struct ath10k_ce_ops ce_64_ops = { @@ -1853,6 +1914,7 @@ static const struct ath10k_ce_ops ce_64_ops = { .ce_send_nolock = _ath10k_ce_send_nolock_64, .ce_set_src_ring_base_addr_hi = ath10k_ce_set_src_ring_base_addr_hi, .ce_set_dest_ring_base_addr_hi = ath10k_ce_set_dest_ring_base_addr_hi, + .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock_64, }; static void ath10k_ce_set_ops(struct ath10k *ar, diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 692b3a8957a9..a7478c240f78 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -329,6 +329,8 @@ struct ath10k_ce_ops { void (*ce_set_dest_ring_base_addr_hi)(struct ath10k *ar, u32 ce_ctrl_addr, u64 addr); + int (*ce_completed_send_next_nolock)(struct ath10k_ce_pipe *ce_state, + void **per_transfer_contextp); }; static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) -- cgit v1.2.3 From 4b816f170b1fe4c2024d530c0d56990413f9ceec Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Mon, 25 Feb 2019 11:45:46 +0200 Subject: ath10k: add support for ack rssi value of management tx packets In WCN3990, WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI service Indicates that the firmware has the capability to send the RSSI value of the ACK for all data and management packets transmitted. If WMI_RSRC_CFG_FLAG_TX_ACK_RSSI is set in host capability then firmware sends RSSI value in "management" tx completion event. Host extracts ack rssi values of management packets from their tx completion event. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1 Signed-off-by: Abhishek Ambure Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 25 +++++++++++++++++- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 25 ++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.c | 42 ++++++++++++++++++++++--------- drivers/net/wireless/ath/ath10k/wmi.h | 11 ++++++++ 4 files changed, 90 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index fc62174a115c..21f9a4617186 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -673,6 +673,10 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb, arg->desc_id = ev->desc_id; arg->status = ev->status; arg->pdev_id = ev->pdev_id; + arg->ppdu_id = ev->ppdu_id; + + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) + arg->ack_rssi = ev->ack_rssi; kfree(tb); return 0; @@ -682,8 +686,12 @@ struct wmi_tlv_tx_bundle_compl_parse { const __le32 *num_reports; const __le32 *desc_ids; const __le32 *status; + const __le32 *ppdu_ids; + const __le32 *ack_rssi; bool desc_ids_done; bool status_done; + bool ppdu_ids_done; + bool ack_rssi_done; }; static int @@ -703,6 +711,12 @@ ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len, } else if (!bundle_tx_compl->status_done) { bundle_tx_compl->status_done = true; bundle_tx_compl->status = ptr; + } else if (!bundle_tx_compl->ppdu_ids_done) { + bundle_tx_compl->ppdu_ids_done = true; + bundle_tx_compl->ppdu_ids = ptr; + } else if (!bundle_tx_compl->ack_rssi_done) { + bundle_tx_compl->ack_rssi_done = true; + bundle_tx_compl->ack_rssi = ptr; } break; default: @@ -733,6 +747,10 @@ static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev( arg->num_reports = *bundle_tx_compl.num_reports; arg->desc_ids = bundle_tx_compl.desc_ids; arg->status = bundle_tx_compl.status; + arg->ppdu_ids = bundle_tx_compl.ppdu_ids; + + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) + arg->ack_rssi = bundle_tx_compl.ack_rssi; return 0; } @@ -1679,6 +1697,9 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) cfg->num_ocb_schedules = __cpu_to_le32(0); cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL); + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) + cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI); + ath10k_wmi_put_host_mem_chunks(ar, chunks); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n"); @@ -2745,7 +2766,9 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu, arvif = (void *)cb->vif->drv_priv; vdev_id = arvif->vdev_id; - if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control))) + if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) && + (!(ieee80211_is_nullfunc(hdr->frame_control) || + ieee80211_is_qos_nullfunc(hdr->frame_control))))) return ERR_PTR(-EINVAL); len = sizeof(*cmd) + 2 * sizeof(*tlv); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index af4cb0e14952..52e0e73ac5f9 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -14,6 +14,8 @@ #define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0 #define WMI_TLV_MGMT_TX_FRAME_MAX_LEN 64 +#define WMI_RSRC_CFG_FLAG_TX_ACK_RSSI BIT(18) + enum wmi_tlv_grp_id { WMI_TLV_GRP_START = 0x3, WMI_TLV_GRP_SCAN = WMI_TLV_GRP_START, @@ -1384,6 +1386,25 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_AP_TWT = 153, WMI_TLV_SERVICE_GMAC_OFFLOAD_SUPPORT = 154, WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT = 155, + WMI_TLV_SERVICE_PEER_TID_CONFIGS_SUPPORT = 156, + WMI_TLV_SERVICE_VDEV_SWRETRY_PER_AC_CONFIG_SUPPORT = 157, + WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_SCC_SUPPORT = 158, + WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_MCC_SUPPORT = 159, + WMI_TLV_SERVICE_MOTION_DET = 160, + WMI_TLV_SERVICE_INFRA_MBSSID = 161, + WMI_TLV_SERVICE_OBSS_SPATIAL_REUSE = 162, + WMI_TLV_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT = 163, + WMI_TLV_SERVICE_NAN_DBS_SUPPORT = 164, + WMI_TLV_SERVICE_NDI_DBS_SUPPORT = 165, + WMI_TLV_SERVICE_NAN_SAP_SUPPORT = 166, + WMI_TLV_SERVICE_NDI_SAP_SUPPORT = 167, + WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT = 168, + WMI_TLV_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1 = 169, + WMI_TLV_SERVICE_ESP_SUPPORT = 170, + WMI_TLV_SERVICE_PEER_CHWIDTH_CHANGE = 171, + WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172, + WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173, + WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174, WMI_TLV_MAX_EXT_SERVICE = 256, }; @@ -1557,6 +1578,8 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len) SVCMAP(WMI_TLV_SERVICE_THERM_THROT, WMI_SERVICE_THERM_THROT, WMI_TLV_MAX_SERVICE); + SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI, + WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE); } #undef SVCMAP @@ -1588,6 +1611,8 @@ struct wmi_tlv_mgmt_tx_compl_ev { __le32 desc_id; __le32 status; __le32 pdev_id; + __le32 ppdu_id; + __le32 ack_rssi; }; #define WMI_TLV_MGMT_RX_NUM_RSSI 4 diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 97e5b2eb8a91..52f1752e2065 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2342,8 +2342,8 @@ static bool ath10k_wmi_rx_is_decrypted(struct ath10k *ar, return true; } -static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id, - u32 status) +static int +wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param) { struct ath10k_mgmt_tx_pkt_addr *pkt_addr; struct ath10k_wmi *wmi = &ar->wmi; @@ -2353,10 +2353,10 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id, spin_lock_bh(&ar->data_lock); - pkt_addr = idr_find(&wmi->mgmt_pending_tx, desc_id); + pkt_addr = idr_find(&wmi->mgmt_pending_tx, param->desc_id); if (!pkt_addr) { ath10k_warn(ar, "received mgmt tx completion for invalid msdu_id: %d\n", - desc_id); + param->desc_id); ret = -ENOENT; goto out; } @@ -2366,17 +2366,21 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id, msdu->len, DMA_TO_DEVICE); info = IEEE80211_SKB_CB(msdu); - if (status) + if (param->status) { info->flags &= ~IEEE80211_TX_STAT_ACK; - else + } else { info->flags |= IEEE80211_TX_STAT_ACK; + info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR + + param->ack_rssi; + info->status.is_valid_ack_signal = true; + } ieee80211_tx_status_irqsafe(ar->hw, msdu); ret = 0; out: - idr_remove(&wmi->mgmt_pending_tx, desc_id); + idr_remove(&wmi->mgmt_pending_tx, param->desc_id); spin_unlock_bh(&ar->data_lock); return ret; } @@ -2384,6 +2388,7 @@ out: int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb) { struct wmi_tlv_mgmt_tx_compl_ev_arg arg; + struct mgmt_tx_compl_params param; int ret; ret = ath10k_wmi_pull_mgmt_tx_compl(ar, skb, &arg); @@ -2392,8 +2397,14 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb) return ret; } - wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_id), - __le32_to_cpu(arg.status)); + memset(¶m, 0, sizeof(struct mgmt_tx_compl_params)); + param.desc_id = __le32_to_cpu(arg.desc_id); + param.status = __le32_to_cpu(arg.status); + + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) + param.ack_rssi = __le32_to_cpu(arg.ack_rssi); + + wmi_process_mgmt_tx_comp(ar, ¶m); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv evnt mgmt tx completion\n"); @@ -2403,6 +2414,7 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb) int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb) { struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg arg; + struct mgmt_tx_compl_params param; u32 num_reports; int i, ret; @@ -2414,9 +2426,15 @@ int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb num_reports = __le32_to_cpu(arg.num_reports); - for (i = 0; i < num_reports; i++) - wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_ids[i]), - __le32_to_cpu(arg.status[i])); + for (i = 0; i < num_reports; i++) { + memset(¶m, 0, sizeof(struct mgmt_tx_compl_params)); + param.desc_id = __le32_to_cpu(arg.desc_ids[i]); + param.status = __le32_to_cpu(arg.desc_ids[i]); + + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) + param.ack_rssi = __le32_to_cpu(arg.ack_rssi[i]); + wmi_process_mgmt_tx_comp(ar, ¶m); + } ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n"); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index d9b646f3dcc2..a1a558b03de7 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -6725,16 +6725,27 @@ struct wmi_scan_ev_arg { __le32 vdev_id; }; +struct mgmt_tx_compl_params { + u32 desc_id; + u32 status; + u32 ppdu_id; + int ack_rssi; +}; + struct wmi_tlv_mgmt_tx_compl_ev_arg { __le32 desc_id; __le32 status; __le32 pdev_id; + __le32 ppdu_id; + __le32 ack_rssi; }; struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg { __le32 num_reports; const __le32 *desc_ids; const __le32 *status; + const __le32 *ppdu_ids; + const __le32 *ack_rssi; }; struct wmi_mgmt_rx_ev_arg { -- cgit v1.2.3 From 6ddc3860a5668808bacbfcb1f1bf50d5d7ad1956 Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Mon, 25 Feb 2019 11:45:48 +0200 Subject: ath10k: add support for ack rssi value of data tx packets In WCN3990, WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI service Indicates that the firmware has the capability to send the RSSI value of the ACK for all data and management packets transmitted. If WMI_RSRC_CFG_FLAG_TX_ACK_RSSI is set in host capability then firmware sends RSSI value in "data" tx completion event. Host extracts ack rssi values of data packets from their tx completion event. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1 Signed-off-by: Abhishek Ambure Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 86 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/htt_rx.c | 12 +++-- drivers/net/wireless/ath/ath10k/hw.c | 32 +++++++++++- drivers/net/wireless/ath/ath10k/hw.h | 22 ++++++++ 4 files changed, 146 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index fef716aa8f3a..4cee5492abc8 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -578,6 +578,10 @@ struct htt_mgmt_tx_completion { #define HTT_TX_CMPL_FLAG_PA_PRESENT BIT(2) #define HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT BIT(3) +#define HTT_TX_DATA_RSSI_ENABLE_WCN3990 BIT(3) +#define HTT_TX_DATA_APPEND_RETRIES BIT(0) +#define HTT_TX_DATA_APPEND_TIMESTAMP BIT(1) + struct htt_rx_indication_hdr { u8 info0; /* %HTT_RX_INDICATION_INFO0_ */ __le16 peer_id; @@ -852,6 +856,88 @@ enum htt_data_tx_flags { #define HTT_TX_COMPL_INV_MSDU_ID 0xFFFF +struct htt_append_retries { + __le16 msdu_id; + u8 tx_retries; + u8 flag; +} __packed; + +struct htt_data_tx_completion_ext { + struct htt_append_retries a_retries; + __le32 t_stamp; + __le16 msdus_rssi[0]; +} __packed; + +/** + * @brief target -> host TX completion indication message definition + * + * @details + * The following diagram shows the format of the TX completion indication sent + * from the target to the host + * + * |31 28|27|26|25|24|23 16| 15 |14 11|10 8|7 0| + * |-------------------------------------------------------------| + * header: |rsvd |A2|TP|A1|A0| num | t_i| tid |status| msg_type | + * |-------------------------------------------------------------| + * payload: | MSDU1 ID | MSDU0 ID | + * |-------------------------------------------------------------| + * : MSDU3 ID : MSDU2 ID : + * |-------------------------------------------------------------| + * | struct htt_tx_compl_ind_append_retries | + * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -| + * | struct htt_tx_compl_ind_append_tx_tstamp | + * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -| + * | MSDU1 ACK RSSI | MSDU0 ACK RSSI | + * |-------------------------------------------------------------| + * : MSDU3 ACK RSSI : MSDU2 ACK RSSI : + * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -| + * -msg_type + * Bits 7:0 + * Purpose: identifies this as HTT TX completion indication + * -status + * Bits 10:8 + * Purpose: the TX completion status of payload fragmentations descriptors + * Value: could be HTT_TX_COMPL_IND_STAT_OK or HTT_TX_COMPL_IND_STAT_DISCARD + * -tid + * Bits 14:11 + * Purpose: the tid associated with those fragmentation descriptors. It is + * valid or not, depending on the tid_invalid bit. + * Value: 0 to 15 + * -tid_invalid + * Bits 15:15 + * Purpose: this bit indicates whether the tid field is valid or not + * Value: 0 indicates valid, 1 indicates invalid + * -num + * Bits 23:16 + * Purpose: the number of payload in this indication + * Value: 1 to 255 + * -A0 = append + * Bits 24:24 + * Purpose: append the struct htt_tx_compl_ind_append_retries which contains + * the number of tx retries for one MSDU at the end of this message + * Value: 0 indicates no appending, 1 indicates appending + * -A1 = append1 + * Bits 25:25 + * Purpose: Append the struct htt_tx_compl_ind_append_tx_tstamp which + * contains the timestamp info for each TX msdu id in payload. + * Value: 0 indicates no appending, 1 indicates appending + * -TP = MSDU tx power presence + * Bits 26:26 + * Purpose: Indicate whether the TX_COMPL_IND includes a tx power report + * for each MSDU referenced by the TX_COMPL_IND message. + * The order of the per-MSDU tx power reports matches the order + * of the MSDU IDs. + * Value: 0 indicates not appending, 1 indicates appending + * -A2 = append2 + * Bits 27:27 + * Purpose: Indicate whether data ACK RSSI is appended for each MSDU in + * TX_COMP_IND message. The order of the per-MSDU ACK RSSI report + * matches the order of the MSDU IDs. + * The ACK RSSI values are valid when status is COMPLETE_OK (and + * this append2 bit is set). + * Value: 0 indicates not appending, 1 indicates appending + */ + struct htt_data_tx_completion { union { u8 flags; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 4fc885617de1..b3d76263417e 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2210,7 +2210,7 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, __le16 msdu_id, *msdus; bool rssi_enabled = false; u8 msdu_count = 0, num_airtime_records, tid; - int i; + int i, htt_pad = 0; struct htt_data_tx_compl_ppdu_dur *ppdu_info; struct ath10k_peer *peer; u16 ppdu_info_offset = 0, peer_id; @@ -2239,9 +2239,11 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, msdu_count = resp->data_tx_completion.num_msdus; msdus = resp->data_tx_completion.msdus; + rssi_enabled = ath10k_is_rssi_enable(&ar->hw_params, resp); - if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI) - rssi_enabled = true; + if (rssi_enabled) + htt_pad = ath10k_tx_data_rssi_get_pad_bytes(&ar->hw_params, + resp); for (i = 0; i < msdu_count; i++) { msdu_id = msdus[i]; @@ -2253,10 +2255,10 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, * last msdu id with 0xffff */ if (msdu_count & 0x01) { - msdu_id = msdus[msdu_count + i + 1]; + msdu_id = msdus[msdu_count + i + 1 + htt_pad]; tx_done.ack_rssi = __le16_to_cpu(msdu_id); } else { - msdu_id = msdus[msdu_count + i]; + msdu_id = msdus[msdu_count + i + htt_pad]; tx_done.ack_rssi = __le16_to_cpu(msdu_id); } } diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index eeaee8e41b28..ad082b7d7643 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -1100,6 +1100,32 @@ int ath10k_hw_diag_fast_download(struct ath10k *ar, return ret; } +static int ath10k_htt_tx_rssi_enable(struct htt_resp *resp) +{ + return (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI); +} + +static int ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp *resp) +{ + return (resp->data_tx_completion.flags2 & + HTT_TX_DATA_RSSI_ENABLE_WCN3990); +} + +static int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp) +{ + struct htt_data_tx_completion_ext extd; + int pad_bytes = 0; + + if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_RETRIES) + pad_bytes += sizeof(extd.a_retries) / + sizeof(extd.msdus_rssi[0]); + + if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_TIMESTAMP) + pad_bytes += sizeof(extd.t_stamp) / sizeof(extd.msdus_rssi[0]); + + return pad_bytes; +} + const struct ath10k_hw_ops qca988x_ops = { .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, }; @@ -1124,6 +1150,10 @@ const struct ath10k_hw_ops qca99x0_ops = { const struct ath10k_hw_ops qca6174_ops = { .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock, + .is_rssi_enable = ath10k_htt_tx_rssi_enable, }; -const struct ath10k_hw_ops wcn3990_ops = {}; +const struct ath10k_hw_ops wcn3990_ops = { + .tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad, + .is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990, +}; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index de7dc01bf51d..97ca42c4e3b4 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -609,6 +609,8 @@ struct ath10k_hw_params { }; struct htt_rx_desc; +struct htt_resp; +struct htt_data_tx_completion_ext; /* Defines needed for Rx descriptor abstraction */ struct ath10k_hw_ops { @@ -616,6 +618,8 @@ struct ath10k_hw_ops { void (*set_coverage_class)(struct ath10k *ar, s16 value); int (*enable_pll_clk)(struct ath10k *ar); bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd); + int (*tx_data_rssi_pad_bytes)(struct htt_resp *htt); + int (*is_rssi_enable)(struct htt_resp *resp); }; extern const struct ath10k_hw_ops qca988x_ops; @@ -643,6 +647,24 @@ ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw, return false; } +static inline int +ath10k_tx_data_rssi_get_pad_bytes(struct ath10k_hw_params *hw, + struct htt_resp *htt) +{ + if (hw->hw_ops->tx_data_rssi_pad_bytes) + return hw->hw_ops->tx_data_rssi_pad_bytes(htt); + return 0; +} + +static inline int +ath10k_is_rssi_enable(struct ath10k_hw_params *hw, + struct htt_resp *resp) +{ + if (hw->hw_ops->is_rssi_enable) + return hw->hw_ops->is_rssi_enable(resp); + return 0; +} + /* Target specific defines for MAIN firmware */ #define TARGET_NUM_VDEVS 8 #define TARGET_NUM_PEER_AST 2 -- cgit v1.2.3 From 1c136e41fb779b6c8127eec19b2a0669a4a7c9a7 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Mon, 25 Feb 2019 11:45:50 +0200 Subject: ath10k: enhance logging for vdev pdev & peer set param Currently after enabling the WMI debug logging, there is no detail printed about the param id and the param value for the pdev, vdev and peer params which are set. Enhance the WMI logging to print the param id and the param value for pdev, vdev and peer set param wmi commands. Tested HW: WCN3990 Tested FW: WLAN.HL.2.0-01387-QCAHLSWMTPLZ-1 WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Signed-off-by: Rakesh Pillai Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 21f9a4617186..c64c6ca7be42 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1583,7 +1583,8 @@ ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id, cmd->param_id = __cpu_to_le32(param_id); cmd->param_value = __cpu_to_le32(param_value); - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param\n"); + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n", + param_id, param_value); return skb; } @@ -2056,7 +2057,8 @@ ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id, cmd->param_id = __cpu_to_le32(param_id); cmd->param_value = __cpu_to_le32(param_value); - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev set param\n"); + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n", + vdev_id, param_id, param_value); return skb; } @@ -2372,7 +2374,9 @@ ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id, cmd->param_value = __cpu_to_le32(param_value); ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer set param\n"); + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi tlv vdev %d peer %pM set param %d value 0x%x\n", + vdev_id, peer_addr, param_id, param_value); return skb; } -- cgit v1.2.3 From d961284df24b8566b473d3828fe299677e155ae6 Mon Sep 17 00:00:00 2001 From: Yu Wang Date: Mon, 25 Feb 2019 11:45:52 +0200 Subject: ath10k: correct the format of host memory chunks in wmi init command This is a theoretical fix, the issue is found in code review. When adding the host memory chunks into wmi-tlv init command, there is no separate tlv header for each host memory chunk in the struct array, which breaches the convention between host and firmware, will result in mismatch between the two. To fix this issue, add separate tlv headers for the host memory chunks in wmi-tlv init command. Signed-off-by: Yu Wang Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 39 ++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index c64c6ca7be42..654ebef67b2d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1588,17 +1588,50 @@ ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id, return skb; } +static void +ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks) +{ + struct host_memory_chunk *chunk; + struct wmi_tlv *tlv; + int i; + __le16 tlv_len, tlv_tag; + + tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK); + tlv_len = __cpu_to_le16(sizeof(*chunk)); + for (i = 0; i < ar->wmi.num_mem_chunks; i++) { + tlv = host_mem_chunks; + tlv->tag = tlv_tag; + tlv->len = tlv_len; + chunk = (void *)tlv->value; + + chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); + chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len); + chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n", + i, + ar->wmi.mem_chunks[i].len, + (unsigned long long)ar->wmi.mem_chunks[i].paddr, + ar->wmi.mem_chunks[i].req_id); + + host_mem_chunks += sizeof(*tlv); + host_mem_chunks += sizeof(*chunk); + } +} + static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) { struct sk_buff *skb; struct wmi_tlv *tlv; struct wmi_tlv_init_cmd *cmd; struct wmi_tlv_resource_config *cfg; - struct wmi_host_mem_chunks *chunks; + void *chunks; size_t len, chunks_len; void *ptr; - chunks_len = ar->wmi.num_mem_chunks * sizeof(struct host_memory_chunk); + chunks_len = ar->wmi.num_mem_chunks * + (sizeof(struct host_memory_chunk) + sizeof(*tlv)); len = (sizeof(*tlv) + sizeof(*cmd)) + (sizeof(*tlv) + sizeof(*cfg)) + (sizeof(*tlv) + chunks_len); @@ -1701,7 +1734,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI); - ath10k_wmi_put_host_mem_chunks(ar, chunks); + ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n"); return skb; -- cgit v1.2.3 From bf1f0a1a4da14bbb7cab3e272e7fd008abde21ef Mon Sep 17 00:00:00 2001 From: Alagu Sankar Date: Mon, 25 Feb 2019 11:45:57 +0200 Subject: ath10k: sdio: set hi_acs_flags The SDIO firmware does not allow transmitting packets with the reduced tx completion HI_ACS option. SDIO firmware uses 1544 as alternate credit size, which is not big enough for the maximum sized mac80211 frames. Disable both these HI_ACS flags for SDIO. Co-developed-by: Wen Gong Signed-off-by: Alagu Sankar Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index ac2cf3f1c7b4..0c62a61b5eac 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -637,10 +637,16 @@ static void ath10k_init_sdio(struct ath10k *ar) ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99); ath10k_bmi_read32(ar, hi_acs_flags, ¶m); - param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET | - HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET | - HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE); + /* Data transfer is not initiated, when reduced Tx completion + * is used for SDIO. disable it until fixed + */ + param &= ~HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET; + /* Alternate credit size of 1544 as used by SDIO firmware is + * not big enough for mac80211 / native wifi frames. disable it + */ + param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; + param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET; ath10k_bmi_write32(ar, hi_acs_flags, param); } -- cgit v1.2.3 From 6cd70c65647b675250ac490bfd7f45bae2cf2aa8 Mon Sep 17 00:00:00 2001 From: Alagu Sankar Date: Mon, 25 Feb 2019 11:45:59 +0200 Subject: ath10k: sdio: disable fwlog prints The SDIO firmware may turn it on based on scratch registers so disable the firmware log to avoid that. Co-developed-by: Wen Gong Signed-off-by: Alagu Sankar Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 0c62a61b5eac..7ccd6741c5b0 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -648,6 +648,13 @@ static void ath10k_init_sdio(struct ath10k *ar) param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET; ath10k_bmi_write32(ar, hi_acs_flags, param); + + /* Explicitly set fwlog prints to zero as target may turn it on + * based on scratch registers. + */ + ath10k_bmi_read32(ar, hi_option_flag, ¶m); + param |= HI_OPTION_DISABLE_DBGLOG; + ath10k_bmi_write32(ar, hi_option_flag, param); } static int ath10k_init_configure_target(struct ath10k *ar) -- cgit v1.2.3 From 55545b08701291b404f79cdc644b99d70e7f486e Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 25 Feb 2019 11:46:01 +0200 Subject: ath10k: sdio: reset chip on power_down() The target device needs to be reset during power_down(), otherwise only the first power_up() will work. And as ath10k calls power_up() during driver initialisation the driver would be otherwise unusable. Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00005-QCARMSWP-1. Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/sdio.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index d62502f386f2..fae56c67766f 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -1382,6 +1382,12 @@ static int ath10k_sdio_hif_power_up(struct ath10k *ar, ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power on\n"); + ret = ath10k_sdio_config(ar); + if (ret) { + ath10k_err(ar, "failed to config sdio: %d\n", ret); + return ret; + } + sdio_claim_host(func); ret = sdio_enable_func(func); @@ -1419,11 +1425,19 @@ static void ath10k_sdio_hif_power_down(struct ath10k *ar) /* Disable the card */ sdio_claim_host(ar_sdio->func); + ret = sdio_disable_func(ar_sdio->func); - sdio_release_host(ar_sdio->func); + if (ret) { + ath10k_warn(ar, "unable to disable sdio function: %d\n", ret); + sdio_release_host(ar_sdio->func); + return; + } + ret = mmc_hw_reset(ar_sdio->func->card->host); if (ret) - ath10k_warn(ar, "unable to disable sdio function: %d\n", ret); + ath10k_warn(ar, "unable to reset sdio: %d\n", ret); + + sdio_release_host(ar_sdio->func); ar_sdio->is_disabled = true; } @@ -2028,12 +2042,6 @@ static int ath10k_sdio_probe(struct sdio_func *func, ath10k_sdio_set_mbox_info(ar); - ret = ath10k_sdio_config(ar); - if (ret) { - ath10k_err(ar, "failed to config sdio: %d\n", ret); - goto err_free_wq; - } - bus_params.dev_type = ATH10K_DEV_TYPE_HL; /* TODO: don't know yet how to get chip_id with SDIO */ bus_params.chip_id = 0; -- cgit v1.2.3 From 7d444522303177f3a3c09b9abb104ddeea470a70 Mon Sep 17 00:00:00 2001 From: Alagu Sankar Date: Mon, 25 Feb 2019 11:46:03 +0200 Subject: ath10k: don't report unset rssi values to mac80211 The SDIO firmware does not provide RSSI value to the host, it's only set to zero. In that case don't report the value to mac80211. One risk here is that value zero might be a valid value with other firmware, currently there's no way to detect that. Without the fix, the rssi value indicated by iw changes between the actual value and -95. Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00005-QCARMSWP-1. Co-developed-by: Wen Gong Signed-off-by: Alagu Sankar Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index b3d76263417e..129fd15e9cc9 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2119,9 +2119,15 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt, hdr = (struct ieee80211_hdr *)skb->data; rx_status = IEEE80211_SKB_RXCB(skb); rx_status->chains |= BIT(0); - rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR + - rx->ppdu.combined_rssi; - rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL; + if (rx->ppdu.combined_rssi == 0) { + /* SDIO firmware does not provide signal */ + rx_status->signal = 0; + rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; + } else { + rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR + + rx->ppdu.combined_rssi; + rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL; + } spin_lock_bh(&ar->data_lock); ch = ar->scan_channel; -- cgit v1.2.3 From 761156ff573d1002983416e4fd1fe8d3489c4bd8 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Fri, 15 Feb 2019 20:49:37 +0530 Subject: ath10k: Fix length of wmi tlv command for protected mgmt frames The length of wmi tlv command for management tx send is calculated incorrectly in case of protected management frames as there is addition of IEEE80211_CCMP_MIC_LEN twice. This leads to improper behaviour of firmware as the wmi tlv mgmt tx send command for protected mgmt frames is formed wrongly. Fix the length calculation of wmi tlv command for mgmt tx send in case of protected management frames by adding the IEEE80211_CCMP_MIC_LEN only once. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Fixes: 1807da49733e "ath10k: wmi: add management tx by reference support over wmi" Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 654ebef67b2d..890887eb886a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -2813,10 +2813,8 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu, if ((ieee80211_is_action(hdr->frame_control) || ieee80211_is_deauth(hdr->frame_control) || ieee80211_is_disassoc(hdr->frame_control)) && - ieee80211_has_protected(hdr->frame_control)) { - len += IEEE80211_CCMP_MIC_LEN; + ieee80211_has_protected(hdr->frame_control)) buf_len += IEEE80211_CCMP_MIC_LEN; - } buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN); buf_len = round_up(buf_len, 4); -- cgit v1.2.3 From 6566abea0b97ec7cc94538e713d3500219be02c5 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 18 Feb 2019 14:14:31 +0800 Subject: ath10k: remove the calibration data fetch for sdio The calibration data fetch will trigger sdio error, then sdio will become fail untill reboot system. If happens when run ifconfig wlan down, then ifconfig wlan up will fail untill reboot system.Remove it fix the ifconfig wlan issue. Tested with QCA6174 SDIO with firmware WLAN.RMH.4.4.1-00005-QCARMSWP-1. Signed-off-by: Wen Gong Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 1b8903280d42..32d967a31c65 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1252,6 +1252,9 @@ static int ath10k_debug_cal_data_fetch(struct ath10k *ar) if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN)) return -EINVAL; + if (ar->hw_params.cal_data_len == 0) + return -EOPNOTSUPP; + hi_addr = host_interest_item_address(HI_ITEM(hi_board_data)); ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr)); -- cgit v1.2.3 From 15493239eacf4487f5744bf88a2f95b09d2a2453 Mon Sep 17 00:00:00 2001 From: Abhishek Ambure Date: Tue, 19 Feb 2019 15:31:08 +0530 Subject: ath10k: update the max num of peers supported for WCN3990 WCN3990 firmware versions WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1 & onwards supports maximum 33 peers including self peer. To support maximum peers, send updated peer param to firmware during initialization. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Signed-off-by: Abhishek Ambure Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 6 +++--- drivers/net/wireless/ath/ath10k/hw.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 7ccd6741c5b0..c2d2155580eb 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -549,10 +549,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .sw_decrypt_mcast_mgmt = true, .hw_ops = &wcn3990_ops, .decap_align_bytes = 1, - .num_peers = TARGET_HL_10_TLV_NUM_PEERS, + .num_peers = TARGET_HL_TLV_NUM_PEERS, .n_cipher_suites = 11, - .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT, - .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES, + .ast_skid_limit = TARGET_HL_TLV_AST_SKID_LIMIT, + .num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES, .target_64bit = true, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC, .per_ce_irq = true, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 97ca42c4e3b4..71314999aa24 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -752,9 +752,9 @@ ath10k_is_rssi_enable(struct ath10k_hw_params *hw, #define TARGET_TLV_MGMT_NUM_MSDU_DESC (50) /* Target specific defines for WMI-HL-1.0 firmware */ -#define TARGET_HL_10_TLV_NUM_PEERS 14 -#define TARGET_HL_10_TLV_AST_SKID_LIMIT 6 -#define TARGET_HL_10_TLV_NUM_WDS_ENTRIES 2 +#define TARGET_HL_TLV_NUM_PEERS 33 +#define TARGET_HL_TLV_AST_SKID_LIMIT 16 +#define TARGET_HL_TLV_NUM_WDS_ENTRIES 2 /* Diagnostic Window */ #define CE_DIAG_PIPE 7 -- cgit v1.2.3 From cc591d77aba12ee69fedd12140b3dfa0816c178a Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Fri, 15 Feb 2019 17:48:55 +0100 Subject: ath9k: Make sure to zero status.tx_time before reporting TX status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since ath9k reports airtime usage directly using the ieee80211_report_airtime() callback, it shouldn't also report it using the tx_time in status. Make sure the field is zeroed before TX status is reported to avoid spurious airtime being accounted by bits being left over from earlier uses of the cb. Fixes: 89cea7493a34 ("ath9k: Switch to mac80211 TXQ scheduling and airtime APIs") Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/xmit.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 06e0c5a6fab6..773d428ff1b0 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2552,6 +2552,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, } tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; + + /* we report airtime in ath_tx_count_airtime(), don't report twice */ + tx_info->status.tx_time = 0; } static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) -- cgit v1.2.3 From d0480d4326e208abd7222803a4d8230d445803ea Mon Sep 17 00:00:00 2001 From: Andrea Greco Date: Fri, 22 Feb 2019 00:12:57 +0100 Subject: ath9k: debugfs: Fix SPUR-DOWN field SPUR DOWN field returns spurup instead of spurdown. Signed-off-by: Andrea Greco Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 0dfea5d6e949..26ea51a72156 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -148,7 +148,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel }, { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel }, { "SPUR UP", ah->stats.ast_ani_spurup }, - { "SPUR DOWN", ah->stats.ast_ani_spurup }, + { "SPUR DOWN", ah->stats.ast_ani_spurdown }, { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon }, { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff }, { "MRC-CCK ON", ah->stats.ast_ani_ccklow }, -- cgit v1.2.3 From 03af21d6ba35e2a95797fc12a3b479856bacc379 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 25 Feb 2019 03:32:46 +0000 Subject: ath9k: remove set but not used variable 'acq' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/ath/ath9k/recv.c: In function 'ath_rx_count_airtime': drivers/net/wireless/ath/ath9k/recv.c:1010:18: warning: variable 'acq' set but not used [-Wunused-but-set-variable] It's not used after 89cea7493a34 ("ath9k: Switch to mac80211 TXQ scheduling and airtime APIs"). Also remove related variables. Signed-off-by: YueHaibing Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/recv.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 285a62d3019d..4e97f7f3b2a3 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1006,9 +1006,6 @@ static void ath_rx_count_airtime(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb) { - struct ath_node *an; - struct ath_acq *acq; - struct ath_vif *avp; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); @@ -1019,7 +1016,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc, int phy; u16 len = rs->rs_datalen; u32 airtime = 0; - u8 tidno, acno; + u8 tidno; if (!ieee80211_is_data(hdr->frame_control)) return; @@ -1029,11 +1026,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc, sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL); if (!sta) goto exit; - an = (struct ath_node *) sta->drv_priv; - avp = (struct ath_vif *) an->vif->drv_priv; tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK; - acno = TID_TO_WME_AC(tidno); - acq = &avp->chanctx->acq[acno]; rxs = IEEE80211_SKB_RXCB(skb); -- cgit v1.2.3 From f4b6bcc7002f0e3a3428bac33cf1945abff95450 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 25 Feb 2019 19:34:02 -0800 Subject: net: devlink: turn devlink into a built-in Being able to build devlink as a module causes growing pains. First all drivers had to add a meta dependency to make sure they are not built in when devlink is built as a module. Now we are struggling to invoke ethtool compat code reliably. Make devlink code built-in, users can still not build it at all but the dynamically loadable module option is removed. Signed-off-by: Jakub Kicinski Reviewed-by: Florian Fainelli Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/infiniband/hw/bnxt_re/Kconfig | 1 - drivers/infiniband/hw/mlx4/Kconfig | 1 - drivers/net/Kconfig | 1 - drivers/net/ethernet/broadcom/Kconfig | 1 - drivers/net/ethernet/cavium/Kconfig | 1 - drivers/net/ethernet/mellanox/mlx4/Kconfig | 1 - drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 1 - drivers/net/ethernet/mellanox/mlxsw/Kconfig | 1 - drivers/net/ethernet/netronome/Kconfig | 1 - include/net/devlink.h | 10 ++++------ net/Kconfig | 11 +---------- net/core/devlink.c | 15 ++------------- net/dsa/Kconfig | 2 +- 13 files changed, 8 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/bnxt_re/Kconfig b/drivers/infiniband/hw/bnxt_re/Kconfig index 18f5ed082f41..19982a4a9bba 100644 --- a/drivers/infiniband/hw/bnxt_re/Kconfig +++ b/drivers/infiniband/hw/bnxt_re/Kconfig @@ -1,7 +1,6 @@ config INFINIBAND_BNXT_RE tristate "Broadcom Netxtreme HCA support" depends on ETHERNET && NETDEVICES && PCI && INET && DCB - depends on MAY_USE_DEVLINK select NET_VENDOR_BROADCOM select BNXT ---help--- diff --git a/drivers/infiniband/hw/mlx4/Kconfig b/drivers/infiniband/hw/mlx4/Kconfig index d1de3285fd88..4e9936731867 100644 --- a/drivers/infiniband/hw/mlx4/Kconfig +++ b/drivers/infiniband/hw/mlx4/Kconfig @@ -2,7 +2,6 @@ config MLX4_INFINIBAND tristate "Mellanox ConnectX HCA support" depends on NETDEVICES && ETHERNET && PCI && INET depends on INFINIBAND_USER_ACCESS || !INFINIBAND_USER_ACCESS - depends on MAY_USE_DEVLINK select NET_VENDOR_MELLANOX select MLX4_CORE ---help--- diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6210757772ed..5e4ca082cfcd 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -505,7 +505,6 @@ source "drivers/net/hyperv/Kconfig" config NETDEVSIM tristate "Simulated networking device" depends on DEBUG_FS - depends on MAY_USE_DEVLINK help This driver is a developer testing tool and software model that can be used to test various control path networking APIs, especially diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index c1d3ee9baf7e..716bfbba59cf 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -194,7 +194,6 @@ config SYSTEMPORT config BNXT tristate "Broadcom NetXtreme-C/E support" depends on PCI - depends on MAY_USE_DEVLINK select FW_LOADER select LIBCRC32C ---help--- diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index 05f4a3b21e29..6650e2a5f171 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -64,7 +64,6 @@ config CAVIUM_PTP config LIQUIDIO tristate "Cavium LiquidIO support" depends on 64BIT && PCI - depends on MAY_USE_DEVLINK depends on PCI imply PTP_1588_CLOCK select FW_LOADER diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig index f200b8c420d5..ff8057ed97ee 100644 --- a/drivers/net/ethernet/mellanox/mlx4/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig @@ -4,7 +4,6 @@ config MLX4_EN tristate "Mellanox Technologies 1/10/40Gbit Ethernet support" - depends on MAY_USE_DEVLINK depends on PCI && NETDEVICES && ETHERNET && INET select MLX4_CORE imply PTP_1588_CLOCK diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index 37a551436e4a..6debffb8336b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -4,7 +4,6 @@ config MLX5_CORE tristate "Mellanox 5th generation network adapters (ConnectX series) core driver" - depends on MAY_USE_DEVLINK depends on PCI imply PTP_1588_CLOCK imply VXLAN diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index b9a25aed5d11..9c195dfed031 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig @@ -4,7 +4,6 @@ config MLXSW_CORE tristate "Mellanox Technologies Switch ASICs support" - depends on MAY_USE_DEVLINK ---help--- This driver supports Mellanox Technologies Switch ASICs family. diff --git a/drivers/net/ethernet/netronome/Kconfig b/drivers/net/ethernet/netronome/Kconfig index 66f15b05b65e..549898d5d450 100644 --- a/drivers/net/ethernet/netronome/Kconfig +++ b/drivers/net/ethernet/netronome/Kconfig @@ -19,7 +19,6 @@ config NFP tristate "Netronome(R) NFP4000/NFP6000 NIC driver" depends on PCI && PCI_MSI depends on VXLAN || VXLAN=n - depends on MAY_USE_DEVLINK ---help--- This driver supports the Netronome(R) NFP4000/NFP6000 based cards working as a advanced Ethernet NIC. It works with both diff --git a/include/net/devlink.h b/include/net/devlink.h index a2da49dd9147..f9f7fe974652 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -707,6 +707,10 @@ devlink_health_reporter_priv(struct devlink_health_reporter *reporter); int devlink_health_report(struct devlink_health_reporter *reporter, const char *msg, void *priv_ctx); +void devlink_compat_running_version(struct net_device *dev, + char *buf, size_t len); +int devlink_compat_flash_update(struct net_device *dev, const char *file_name); + #else static inline struct devlink *devlink_alloc(const struct devlink_ops *ops, @@ -1190,13 +1194,7 @@ devlink_health_report(struct devlink_health_reporter *reporter, { return 0; } -#endif -#if IS_REACHABLE(CONFIG_NET_DEVLINK) -void devlink_compat_running_version(struct net_device *dev, - char *buf, size_t len); -int devlink_compat_flash_update(struct net_device *dev, const char *file_name); -#else static inline void devlink_compat_running_version(struct net_device *dev, char *buf, size_t len) { diff --git a/net/Kconfig b/net/Kconfig index 62da6148e9f8..1efe1f9ee492 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -429,21 +429,12 @@ config NET_SOCK_MSG with the help of BPF programs. config NET_DEVLINK - tristate "Network physical/parent device Netlink interface" + bool "Network physical/parent device Netlink interface" help Network physical/parent device Netlink interface provides infrastructure to support access to physical chip-wide config and monitoring. -config MAY_USE_DEVLINK - tristate - default m if NET_DEVLINK=m - default y if NET_DEVLINK=y || NET_DEVLINK=n - help - Drivers using the devlink infrastructure should have a dependency - on MAY_USE_DEVLINK to ensure they do not cause link errors when - devlink is a loadable module and the driver using it is built-in. - config PAGE_POOL bool diff --git a/net/core/devlink.c b/net/core/devlink.c index 4f31ddc883e7..05e04ea0a5c7 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -6482,20 +6482,9 @@ int devlink_compat_flash_update(struct net_device *dev, const char *file_name) return -EOPNOTSUPP; } -static int __init devlink_module_init(void) +static int __init devlink_init(void) { return genl_register_family(&devlink_nl_family); } -static void __exit devlink_module_exit(void) -{ - genl_unregister_family(&devlink_nl_family); -} - -module_init(devlink_module_init); -module_exit(devlink_module_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Jiri Pirko "); -MODULE_DESCRIPTION("Network physical device Netlink interface"); -MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME); +subsys_initcall(devlink_init); diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 91e52973ee13..fab49132345f 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -6,7 +6,7 @@ config HAVE_NET_DSA config NET_DSA tristate "Distributed Switch Architecture" - depends on HAVE_NET_DSA && MAY_USE_DEVLINK + depends on HAVE_NET_DSA depends on BRIDGE || BRIDGE=n select NET_SWITCHDEV select PHYLINK -- cgit v1.2.3 From 28e8c754135d785f709fc435d8cc3c4493fbff69 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 25 Feb 2019 19:34:04 -0800 Subject: nfp: add .ndo_get_devlink Support getting devlink instance from a new NDO. Signed-off-by: Jakub Kicinski Acked-by: Jiri Pirko Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfp_app.h | 2 ++ drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 11 +++++++++++ drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 1 + drivers/net/ethernet/netronome/nfp/nfp_net_repr.c | 1 + 4 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h index d578d856a009..f8d422713705 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_app.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h @@ -433,4 +433,6 @@ int nfp_app_nic_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, int nfp_app_nic_vnic_init_phy_port(struct nfp_pf *pf, struct nfp_app *app, struct nfp_net *nn, unsigned int id); +struct devlink *nfp_devlink_get_devlink(struct net_device *netdev); + #endif diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index db2da99f6aa7..e9eca99cf493 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -376,3 +376,14 @@ void nfp_devlink_port_unregister(struct nfp_port *port) { devlink_port_unregister(&port->dl_port); } + +struct devlink *nfp_devlink_get_devlink(struct net_device *netdev) +{ + struct nfp_app *app; + + app = nfp_app_from_netdev(netdev); + if (!app) + return NULL; + + return priv_to_devlink(app->pf); +} diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 776f6c07701b..6d1b8816552e 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -3531,6 +3531,7 @@ const struct net_device_ops nfp_net_netdev_ops = { .ndo_udp_tunnel_del = nfp_net_del_vxlan_port, .ndo_bpf = nfp_net_xdp, .ndo_get_port_parent_id = nfp_port_get_port_parent_id, + .ndo_get_devlink = nfp_devlink_get_devlink, }; /** diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c index 62839807e21e..d2c803bb4e56 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c @@ -273,6 +273,7 @@ const struct net_device_ops nfp_repr_netdev_ops = { .ndo_set_features = nfp_port_set_features, .ndo_set_mac_address = eth_mac_addr, .ndo_get_port_parent_id = nfp_port_get_port_parent_id, + .ndo_get_devlink = nfp_devlink_get_devlink, }; void -- cgit v1.2.3 From 03969b941486b208e2e418acbcf7065c740e7a5e Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 25 Feb 2019 19:34:05 -0800 Subject: nfp: remove ethtool flashing fallback Now that devlink fallback will be called reliably, we can remove the ethtool flashing code. Signed-off-by: Jakub Kicinski Acked-by: Jiri Pirko Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfp_net_ethtool.c | 24 ---------------------- 1 file changed, 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 8f189149efc5..690b62718dbb 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -1234,28 +1234,6 @@ static int nfp_net_set_channels(struct net_device *netdev, return nfp_net_set_num_rings(nn, total_rx, total_tx); } -static int -nfp_net_flash_device(struct net_device *netdev, struct ethtool_flash *flash) -{ - struct nfp_app *app; - int ret; - - if (flash->region != ETHTOOL_FLASH_ALL_REGIONS) - return -EOPNOTSUPP; - - app = nfp_app_from_netdev(netdev); - if (!app) - return -EOPNOTSUPP; - - dev_hold(netdev); - rtnl_unlock(); - ret = nfp_flash_update_common(app->pf, flash->data, NULL); - rtnl_lock(); - dev_put(netdev); - - return ret; -} - static const struct ethtool_ops nfp_net_ethtool_ops = { .get_drvinfo = nfp_net_get_drvinfo, .get_link = ethtool_op_get_link, @@ -1266,7 +1244,6 @@ static const struct ethtool_ops nfp_net_ethtool_ops = { .get_sset_count = nfp_net_get_sset_count, .get_rxnfc = nfp_net_get_rxnfc, .set_rxnfc = nfp_net_set_rxnfc, - .flash_device = nfp_net_flash_device, .get_rxfh_indir_size = nfp_net_get_rxfh_indir_size, .get_rxfh_key_size = nfp_net_get_rxfh_key_size, .get_rxfh = nfp_net_get_rxfh, @@ -1292,7 +1269,6 @@ const struct ethtool_ops nfp_port_ethtool_ops = { .get_strings = nfp_port_get_strings, .get_ethtool_stats = nfp_port_get_stats, .get_sset_count = nfp_port_get_sset_count, - .flash_device = nfp_net_flash_device, .set_dump = nfp_app_set_dump, .get_dump_flag = nfp_app_get_dump_flag, .get_dump_data = nfp_app_get_dump_data, -- cgit v1.2.3 From 70fb0828800b45bfb1887223715263440dfb6b23 Mon Sep 17 00:00:00 2001 From: Roopa Prabhu Date: Mon, 25 Feb 2019 22:03:01 -0800 Subject: vxlan: add extack support for create and changelink This patch adds extack coverage in vxlan link create and changelink paths. Introduces a new helper vxlan_nl2flags to consolidate flag attribute validation. thanks to Johannes Berg for some tips to construct the generic vxlan flag extack strings. Signed-off-by: Roopa Prabhu Reviewed-by: Petr Machata Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 208 +++++++++++++++++++++++++++++++++++----------------- include/net/vxlan.h | 31 ++++++++ 2 files changed, 172 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 577201cd880c..a3c46d78d216 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -3583,11 +3583,40 @@ errout: return err; } +/* Set/clear flags based on attribute */ +static int vxlan_nl2flag(struct vxlan_config *conf, struct nlattr *tb[], + int attrtype, unsigned long mask, bool changelink, + bool changelink_supported, + struct netlink_ext_ack *extack) +{ + unsigned long flags; + + if (!tb[attrtype]) + return 0; + + if (changelink && !changelink_supported) { + vxlan_flag_attr_error(attrtype, extack); + return -EOPNOTSUPP; + } + + if (vxlan_policy[attrtype].type == NLA_FLAG) + flags = conf->flags | mask; + else if (nla_get_u8(tb[attrtype])) + flags = conf->flags | mask; + else + flags = conf->flags & ~mask; + + conf->flags = flags; + + return 0; +} + static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], struct net_device *dev, struct vxlan_config *conf, - bool changelink) + bool changelink, struct netlink_ext_ack *extack) { struct vxlan_dev *vxlan = netdev_priv(dev); + int err = 0; memset(conf, 0, sizeof(*conf)); @@ -3598,40 +3627,54 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], if (data[IFLA_VXLAN_ID]) { __be32 vni = cpu_to_be32(nla_get_u32(data[IFLA_VXLAN_ID])); - if (changelink && (vni != conf->vni)) + if (changelink && (vni != conf->vni)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_ID], "Cannot change VNI"); return -EOPNOTSUPP; + } conf->vni = cpu_to_be32(nla_get_u32(data[IFLA_VXLAN_ID])); } if (data[IFLA_VXLAN_GROUP]) { - if (changelink && (conf->remote_ip.sa.sa_family != AF_INET)) + if (changelink && (conf->remote_ip.sa.sa_family != AF_INET)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP], "New group address family does not match old group"); return -EOPNOTSUPP; + } conf->remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]); conf->remote_ip.sa.sa_family = AF_INET; } else if (data[IFLA_VXLAN_GROUP6]) { - if (!IS_ENABLED(CONFIG_IPV6)) + if (!IS_ENABLED(CONFIG_IPV6)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP6], "IPv6 support not enabled in the kernel"); return -EPFNOSUPPORT; + } - if (changelink && (conf->remote_ip.sa.sa_family != AF_INET6)) + if (changelink && (conf->remote_ip.sa.sa_family != AF_INET6)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_GROUP6], "New group address family does not match old group"); return -EOPNOTSUPP; + } conf->remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]); conf->remote_ip.sa.sa_family = AF_INET6; } if (data[IFLA_VXLAN_LOCAL]) { - if (changelink && (conf->saddr.sa.sa_family != AF_INET)) + if (changelink && (conf->saddr.sa.sa_family != AF_INET)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL], "New local address family does not match old"); return -EOPNOTSUPP; + } conf->saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]); conf->saddr.sa.sa_family = AF_INET; } else if (data[IFLA_VXLAN_LOCAL6]) { - if (!IS_ENABLED(CONFIG_IPV6)) + if (!IS_ENABLED(CONFIG_IPV6)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL6], "IPv6 support not enabled in the kernel"); return -EPFNOSUPPORT; + } - if (changelink && (conf->saddr.sa.sa_family != AF_INET6)) + if (changelink && (conf->saddr.sa.sa_family != AF_INET6)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL6], "New local address family does not match old"); return -EOPNOTSUPP; + } /* TODO: respect scope id */ conf->saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]); @@ -3648,9 +3691,12 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], conf->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]); if (data[IFLA_VXLAN_TTL_INHERIT]) { - if (changelink) - return -EOPNOTSUPP; - conf->flags |= VXLAN_F_TTL_INHERIT; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_TTL_INHERIT, + VXLAN_F_TTL_INHERIT, changelink, false, + extack); + if (err) + return err; + } if (data[IFLA_VXLAN_LABEL]) @@ -3658,10 +3704,11 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], IPV6_FLOWLABEL_MASK; if (data[IFLA_VXLAN_LEARNING]) { - if (nla_get_u8(data[IFLA_VXLAN_LEARNING])) - conf->flags |= VXLAN_F_LEARN; - else - conf->flags &= ~VXLAN_F_LEARN; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_LEARNING, + VXLAN_F_LEARN, changelink, true, + extack); + if (err) + return err; } else if (!changelink) { /* default to learn on a new device */ conf->flags |= VXLAN_F_LEARN; @@ -3671,44 +3718,52 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], conf->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]); if (data[IFLA_VXLAN_PROXY]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_PROXY])) - conf->flags |= VXLAN_F_PROXY; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_PROXY, + VXLAN_F_PROXY, changelink, false, + extack); + if (err) + return err; } if (data[IFLA_VXLAN_RSC]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_RSC])) - conf->flags |= VXLAN_F_RSC; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_RSC, + VXLAN_F_RSC, changelink, false, + extack); + if (err) + return err; } if (data[IFLA_VXLAN_L2MISS]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_L2MISS])) - conf->flags |= VXLAN_F_L2MISS; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_L2MISS, + VXLAN_F_L2MISS, changelink, false, + extack); + if (err) + return err; } if (data[IFLA_VXLAN_L3MISS]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_L3MISS])) - conf->flags |= VXLAN_F_L3MISS; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_L3MISS, + VXLAN_F_L3MISS, changelink, false, + extack); + if (err) + return err; } if (data[IFLA_VXLAN_LIMIT]) { - if (changelink) + if (changelink) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LIMIT], + "Cannot change limit"); return -EOPNOTSUPP; + } conf->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]); } if (data[IFLA_VXLAN_COLLECT_METADATA]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_COLLECT_METADATA])) - conf->flags |= VXLAN_F_COLLECT_METADATA; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_COLLECT_METADATA, + VXLAN_F_COLLECT_METADATA, changelink, false, + extack); + if (err) + return err; } if (data[IFLA_VXLAN_PORT_RANGE]) { @@ -3718,72 +3773,92 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], conf->port_min = ntohs(p->low); conf->port_max = ntohs(p->high); } else { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_PORT_RANGE], + "Cannot change port range"); return -EOPNOTSUPP; } } if (data[IFLA_VXLAN_PORT]) { - if (changelink) + if (changelink) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_PORT], + "Cannot change port"); return -EOPNOTSUPP; + } conf->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); } if (data[IFLA_VXLAN_UDP_CSUM]) { - if (changelink) + if (changelink) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_UDP_CSUM], + "Cannot change UDP_CSUM flag"); return -EOPNOTSUPP; + } if (!nla_get_u8(data[IFLA_VXLAN_UDP_CSUM])) conf->flags |= VXLAN_F_UDP_ZERO_CSUM_TX; } if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX])) - conf->flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, + VXLAN_F_UDP_ZERO_CSUM6_TX, changelink, + false, extack); + if (err) + return err; } if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX])) - conf->flags |= VXLAN_F_UDP_ZERO_CSUM6_RX; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, + VXLAN_F_UDP_ZERO_CSUM6_RX, changelink, + false, extack); + if (err) + return err; } if (data[IFLA_VXLAN_REMCSUM_TX]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_REMCSUM_TX])) - conf->flags |= VXLAN_F_REMCSUM_TX; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_TX, + VXLAN_F_REMCSUM_TX, changelink, false, + extack); + if (err) + return err; } if (data[IFLA_VXLAN_REMCSUM_RX]) { - if (changelink) - return -EOPNOTSUPP; - if (nla_get_u8(data[IFLA_VXLAN_REMCSUM_RX])) - conf->flags |= VXLAN_F_REMCSUM_RX; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_RX, + VXLAN_F_REMCSUM_RX, changelink, false, + extack); + if (err) + return err; } if (data[IFLA_VXLAN_GBP]) { - if (changelink) - return -EOPNOTSUPP; - conf->flags |= VXLAN_F_GBP; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_GBP, + VXLAN_F_GBP, changelink, false, extack); + if (err) + return err; } if (data[IFLA_VXLAN_GPE]) { - if (changelink) - return -EOPNOTSUPP; - conf->flags |= VXLAN_F_GPE; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_GPE, + VXLAN_F_GPE, changelink, false, + extack); + if (err) + return err; } if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) { - if (changelink) - return -EOPNOTSUPP; - conf->flags |= VXLAN_F_REMCSUM_NOPARTIAL; + err = vxlan_nl2flag(conf, data, IFLA_VXLAN_REMCSUM_NOPARTIAL, + VXLAN_F_REMCSUM_NOPARTIAL, changelink, + false, extack); + if (err) + return err; } if (tb[IFLA_MTU]) { - if (changelink) + if (changelink) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_MTU], + "Cannot change mtu"); return -EOPNOTSUPP; + } conf->mtu = nla_get_u32(tb[IFLA_MTU]); } @@ -3800,7 +3875,7 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, struct vxlan_config conf; int err; - err = vxlan_nl2conf(tb, data, dev, &conf, false); + err = vxlan_nl2conf(tb, data, dev, &conf, false, extack); if (err) return err; @@ -3817,8 +3892,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], struct vxlan_config conf; int err; - err = vxlan_nl2conf(tb, data, - dev, &conf, true); + err = vxlan_nl2conf(tb, data, dev, &conf, true, extack); if (err) return err; diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 09767819c3d4..00254a58824b 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -453,4 +453,35 @@ vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni) } #endif +static inline void vxlan_flag_attr_error(int attrtype, + struct netlink_ext_ack *extack) +{ +#define VXLAN_FLAG(flg) \ + case IFLA_VXLAN_##flg: \ + NL_SET_ERR_MSG_MOD(extack, \ + "cannot change " #flg " flag"); \ + break + switch (attrtype) { + VXLAN_FLAG(TTL_INHERIT); + VXLAN_FLAG(LEARNING); + VXLAN_FLAG(PROXY); + VXLAN_FLAG(RSC); + VXLAN_FLAG(L2MISS); + VXLAN_FLAG(L3MISS); + VXLAN_FLAG(COLLECT_METADATA); + VXLAN_FLAG(UDP_ZERO_CSUM6_TX); + VXLAN_FLAG(UDP_ZERO_CSUM6_RX); + VXLAN_FLAG(REMCSUM_TX); + VXLAN_FLAG(REMCSUM_RX); + VXLAN_FLAG(GBP); + VXLAN_FLAG(GPE); + VXLAN_FLAG(REMCSUM_NOPARTIAL); + default: + NL_SET_ERR_MSG_MOD(extack, \ + "cannot change flag"); + break; + } +#undef VXLAN_FLAG +} + #endif -- cgit v1.2.3 From bae1320f7afdb08db96884f2caedc62db295ed4e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 25 Feb 2019 02:03:28 +0000 Subject: mlxsw: spectrum: remove set but not used variable 'autoneg_status' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/ethernet/mellanox/mlxsw/spectrum.c: In function 'mlxsw_sp_port_get_link_ksettings': drivers/net/ethernet/mellanox/mlxsw/spectrum.c:3062:5: warning: variable 'autoneg_status' set but not used [-Wunused-but-set-variable] It's not used since commit 475b33cb66c9 ("mlxsw: spectrum: Remove unsupported eth_proto_lp_advertise field in PTYS") Signed-off-by: YueHaibing Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 40177b9834c4..b00f6f74f91a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3059,7 +3059,6 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, const struct mlxsw_sp_port_type_speed_ops *ops; char ptys_pl[MLXSW_REG_PTYS_LEN]; u8 connector_type; - u8 autoneg_status; bool autoneg; int err; @@ -3079,8 +3078,6 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg, cmd); - autoneg_status = mlxsw_reg_ptys_an_status_get(ptys_pl); - cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl); cmd->base.port = mlxsw_sp_port_connector_port(connector_type); -- cgit v1.2.3 From 9836b80208b2253ae8f1130a93566bb2f6d505a9 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 26 Feb 2019 11:46:45 -0800 Subject: Bluetooth: hci_qca: Pass boolean 'on/off' to qca_send_power_pulse() There are only two types of power pulses 'on' or 'off', pass a boolean instead of the power pulse 'command'. Signed-off-by: Matthias Kaehlcke Reviewed-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 26efc2ef98d9..9be3769a4042 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1004,10 +1004,11 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed) hci_uart_set_baudrate(hu, speed); } -static int qca_send_power_pulse(struct hci_uart *hu, u8 cmd) +static int qca_send_power_pulse(struct hci_uart *hu, bool on) { int ret; int timeout = msecs_to_jiffies(POWER_PULSE_TRANS_TIMEOUT_MS); + u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE; /* These power pulses are single byte command which are sent * at required baudrate to wcn3990. On wcn3990, we have an external @@ -1138,12 +1139,12 @@ static int qca_wcn3990_init(struct hci_uart *hu) /* Forcefully enable wcn3990 to enter in to boot mode. */ host_set_baudrate(hu, 2400); - ret = qca_send_power_pulse(hu, QCA_WCN3990_POWEROFF_PULSE); + ret = qca_send_power_pulse(hu, false); if (ret) return ret; qca_set_speed(hu, QCA_INIT_SPEED); - ret = qca_send_power_pulse(hu, QCA_WCN3990_POWERON_PULSE); + ret = qca_send_power_pulse(hu, true); if (ret) return ret; @@ -1290,7 +1291,7 @@ static void qca_power_shutdown(struct hci_uart *hu) spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); host_set_baudrate(hu, 2400); - qca_send_power_pulse(hu, QCA_WCN3990_POWEROFF_PULSE); + qca_send_power_pulse(hu, false); qca_power_setup(hu, false); } -- cgit v1.2.3 From ad571d725c9786a138d663fb26ae91d84e705900 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 26 Feb 2019 11:46:46 -0800 Subject: Bluetooth: hci_qca: Move boot delay to qca_send_power_pulse() After sending a power on pulse the driver has a delay of 100ms to allow the host controller to boot. Move the delay into qca_send_power_pulse(), since it is directly related with the power-on pulse. Signed-off-by: Matthias Kaehlcke Reviewed-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 9be3769a4042..bcc70352eb95 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1036,6 +1036,9 @@ static int qca_send_power_pulse(struct hci_uart *hu, bool on) usleep_range(100, 200); hci_uart_set_flow_control(hu, false); + if (on) + msleep(100); + return 0; } @@ -1148,9 +1151,6 @@ static int qca_wcn3990_init(struct hci_uart *hu) if (ret) return ret; - /* Wait for 100 ms for SoC to boot */ - msleep(100); - /* Now the device is in ready state to communicate with host. * To sync host with device we need to reopen port. * Without this, we will have RTS and CTS synchronization -- cgit v1.2.3 From 0ebcddd8e06e94e476f4718af238e9ae67531b04 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 26 Feb 2019 11:46:47 -0800 Subject: Bluetooth: hci_qca: Add delay after power-off pulse During initialization the power-on pulse is currently sent inmediately after the prior power-off pulse. With this initialization often fails at boot time: [ 15.205224] Bluetooth: hci0: setting up wcn3990 [ 17.341062] Bluetooth: hci0: command 0xfc00 tx timeout [ 22.101453] ERROR: Bluetooth initialization failed [ 25.337740] Bluetooth: hci0: Reading QCA version information failed (-110) After a power-off pulse wait 10ms to give the controller time to power off. Remove the previous short settling delay, it isn't needed anymore. Signed-off-by: Matthias Kaehlcke Reviewed-by: Balakrishna Godavarthi Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index bcc70352eb95..f56d2459ea19 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1031,13 +1031,13 @@ static int qca_send_power_pulse(struct hci_uart *hu, bool on) } serdev_device_wait_until_sent(hu->serdev, timeout); - - /* Wait for 100 uS for SoC to settle down */ - usleep_range(100, 200); hci_uart_set_flow_control(hu, false); + /* Give to controller time to boot/shutdown */ if (on) msleep(100); + else + msleep(10); return 0; } -- cgit v1.2.3 From 6d10cd5cbd6cbd0c4f401bbf3e121ef2240d989b Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Tue, 26 Feb 2019 12:08:47 -0800 Subject: Bluetooth: hci_qca: Use msleep() instead of open coding it Call msleep() in qca_set_baudrate() instead of reimplementing it. Signed-off-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index f56d2459ea19..82f6cec4f71e 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -989,9 +989,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) * controller will come back after they receive this HCI command * then host can communicate with new baudrate to controller */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS)); - set_current_state(TASK_RUNNING); + msleep(BAUDRATE_SETTLE_TIMEOUT_MS); return 0; } -- cgit v1.2.3 From 4c409af04d766e05f154c0e87381dc02858fb78e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 22 Feb 2019 14:53:43 -0800 Subject: Bluetooth: btusb: add QCA6174A compatible properties We may need to specify a GPIO wake pin for this device, so add a compatible property for it. There are at least to USB PID/VID variations of this chip: one with a Lite-On ID and one with an Atheros ID. Signed-off-by: Brian Norris Reviewed-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d4c8d989e714..ded198328f21 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2917,6 +2917,8 @@ static irqreturn_t btusb_oob_wake_handler(int irq, void *priv) static const struct of_device_id btusb_match_table[] = { { .compatible = "usb1286,204e" }, + { .compatible = "usbcf3,e300" }, /* QCA6174A */ + { .compatible = "usb4ca,301a" }, /* QCA6174A (Lite-On) */ { } }; MODULE_DEVICE_TABLE(of, btusb_match_table); -- cgit v1.2.3 From 4f7054867cad2dd050c9e03ab3d5d3a30bb6f6e8 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Feb 2019 11:44:26 -0800 Subject: rocker: Handle SWITCHDEV_PORT_ATTR_SET Following patches will change the way we communicate setting a port's attribute and use notifiers towards that goal. Prepare rocker to support receiving notifier events targeting SWITCHDEV_PORT_ATTR_SET from both atomic and process context and use a small helper to translate the event notifier into something that rocker_port_attr_set() can process. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker_main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 309a6bf9130c..fc772cf079cc 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2710,6 +2710,19 @@ static bool rocker_port_dev_check(const struct net_device *dev) return dev->netdev_ops == &rocker_port_netdev_ops; } +static int +rocker_switchdev_port_attr_set_event(struct net_device *netdev, + struct switchdev_notifier_port_attr_info *port_attr_info) +{ + int err; + + err = rocker_port_attr_set(netdev, port_attr_info->attr, + port_attr_info->trans); + + port_attr_info->handled = true; + return notifier_from_errno(err); +} + struct rocker_switchdev_event_work { struct work_struct work; struct switchdev_notifier_fdb_info fdb_info; @@ -2779,6 +2792,9 @@ static int rocker_switchdev_event(struct notifier_block *unused, if (!rocker_port_dev_check(dev)) return NOTIFY_DONE; + if (event == SWITCHDEV_PORT_ATTR_SET) + return rocker_switchdev_port_attr_set_event(dev, ptr); + rocker_port = netdev_priv(dev); switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); if (WARN_ON(!switchdev_work)) @@ -2841,6 +2857,8 @@ static int rocker_switchdev_blocking_event(struct notifier_block *unused, case SWITCHDEV_PORT_OBJ_ADD: case SWITCHDEV_PORT_OBJ_DEL: return rocker_switchdev_port_obj_event(event, dev, ptr); + case SWITCHDEV_PORT_ATTR_SET: + return rocker_switchdev_port_attr_set_event(dev, ptr); } return NOTIFY_DONE; -- cgit v1.2.3 From 7464251b15d98e31f0c0aec2f883db979d15f9f1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Feb 2019 11:44:28 -0800 Subject: mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_ATTR_SET Following patches will change the way we communicate setting a port's attribute and use a notifier to perform those tasks. Prepare mlxsw to support receiving notifier events targeting SWITCHDEV_PORT_ATTR_SET and utilize the switchdev_handle_port_attr_set() to handle stacking of devices. Reviewed-by: Ido Schimmel Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 766f5b5f1cf5..c1aedfea3a31 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -3123,6 +3123,13 @@ static int mlxsw_sp_switchdev_event(struct notifier_block *unused, struct net_device *br_dev; int err; + if (event == SWITCHDEV_PORT_ATTR_SET) { + err = switchdev_handle_port_attr_set(dev, ptr, + mlxsw_sp_port_dev_check, + mlxsw_sp_port_attr_set); + return notifier_from_errno(err); + } + /* Tunnel devices are not our uppers, so check their master instead */ br_dev = netdev_master_upper_dev_get_rcu(dev); if (!br_dev) @@ -3446,6 +3453,11 @@ static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused, mlxsw_sp_port_dev_check, mlxsw_sp_port_obj_del); return notifier_from_errno(err); + case SWITCHDEV_PORT_ATTR_SET: + err = switchdev_handle_port_attr_set(dev, ptr, + mlxsw_sp_port_dev_check, + mlxsw_sp_port_attr_set); + return notifier_from_errno(err); } return NOTIFY_DONE; -- cgit v1.2.3 From 56da64bc003bb9d39b69017074dd7909c72b68b1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Feb 2019 11:44:29 -0800 Subject: net: mscc: ocelot: Handle SWITCHDEV_PORT_ATTR_SET Following patches will change the way we communicate setting a port's attribute and use notifiers to perform those tasks. Ocelot does not currently have an atomic notifier registered for switchdev events, so we need to register one in order to deal with atomic context SWITCHDEV_PORT_ATTR_SET events. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 27 +++++++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot.h | 1 + drivers/net/ethernet/mscc/ocelot_board.c | 2 ++ 3 files changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 195306d05bcd..83a678b11757 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1582,6 +1582,28 @@ struct notifier_block ocelot_netdevice_nb __read_mostly = { }; EXPORT_SYMBOL(ocelot_netdevice_nb); +static int ocelot_switchdev_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = switchdev_notifier_info_to_dev(ptr); + int err; + + switch (event) { + case SWITCHDEV_PORT_ATTR_SET: + err = switchdev_handle_port_attr_set(dev, ptr, + ocelot_netdevice_dev_check, + ocelot_port_attr_set); + return notifier_from_errno(err); + } + + return NOTIFY_DONE; +} + +struct notifier_block ocelot_switchdev_nb __read_mostly = { + .notifier_call = ocelot_switchdev_event, +}; +EXPORT_SYMBOL(ocelot_switchdev_nb); + static int ocelot_switchdev_blocking_event(struct notifier_block *unused, unsigned long event, void *ptr) { @@ -1600,6 +1622,11 @@ static int ocelot_switchdev_blocking_event(struct notifier_block *unused, ocelot_netdevice_dev_check, ocelot_port_obj_del); return notifier_from_errno(err); + case SWITCHDEV_PORT_ATTR_SET: + err = switchdev_handle_port_attr_set(dev, ptr, + ocelot_netdevice_dev_check, + ocelot_port_attr_set); + return notifier_from_errno(err); } return NOTIFY_DONE; diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h index 086775f7b52f..ba3b3380b4d0 100644 --- a/drivers/net/ethernet/mscc/ocelot.h +++ b/drivers/net/ethernet/mscc/ocelot.h @@ -499,6 +499,7 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port, struct phy_device *phy); extern struct notifier_block ocelot_netdevice_nb; +extern struct notifier_block ocelot_switchdev_nb; extern struct notifier_block ocelot_switchdev_blocking_nb; #endif diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c index ca3ea2fbfcd0..2c1121d86edf 100644 --- a/drivers/net/ethernet/mscc/ocelot_board.c +++ b/drivers/net/ethernet/mscc/ocelot_board.c @@ -329,6 +329,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev) } register_netdevice_notifier(&ocelot_netdevice_nb); + register_switchdev_notifier(&ocelot_switchdev_nb); register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb); dev_info(&pdev->dev, "Ocelot switch probed\n"); @@ -345,6 +346,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev) ocelot_deinit(ocelot); unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb); + unregister_switchdev_notifier(&ocelot_switchdev_nb); unregister_netdevice_notifier(&ocelot_netdevice_nb); return 0; -- cgit v1.2.3 From 570b68c8dddea16b96730f7d5d732e270b6a9189 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Feb 2019 11:44:30 -0800 Subject: staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_ATTR_SET Following patches will change the way we communicate setting a port's attribute and use a blocking notifier to perform those tasks. Prepare ethsw to support receiving notifier events targeting SWITCHDEV_PORT_ATTR_SET and simply translate that into the existing swdev_port_attr_set() call. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 018399ee8731..b0d2d9bf2532 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -929,6 +929,19 @@ static const struct switchdev_ops ethsw_port_switchdev_ops = { .switchdev_port_attr_set = swdev_port_attr_set, }; +static int +ethsw_switchdev_port_attr_set_event(struct net_device *netdev, + struct switchdev_notifier_port_attr_info *port_attr_info) +{ + int err; + + err = swdev_port_attr_set(netdev, port_attr_info->attr, + port_attr_info->trans); + + port_attr_info->handled = true; + return notifier_from_errno(err); +} + /* For the moment, only flood setting needs to be updated */ static int port_bridge_join(struct net_device *netdev, struct net_device *upper_dev) @@ -1047,6 +1060,12 @@ static int port_switchdev_event(struct notifier_block *unused, struct ethsw_switchdev_event_work *switchdev_work; struct switchdev_notifier_fdb_info *fdb_info = ptr; + if (!ethsw_port_dev_check(dev)) + return NOTIFY_DONE; + + if (event == SWITCHDEV_PORT_ATTR_SET) + return ethsw_switchdev_port_attr_set_event(dev, ptr); + switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); if (!switchdev_work) return NOTIFY_BAD; @@ -1115,6 +1134,8 @@ static int port_switchdev_blocking_event(struct notifier_block *unused, case SWITCHDEV_PORT_OBJ_ADD: /* fall through */ case SWITCHDEV_PORT_OBJ_DEL: return ethsw_switchdev_port_obj_event(event, dev, ptr); + case SWITCHDEV_PORT_ATTR_SET: + return ethsw_switchdev_port_attr_set_event(dev, ptr); } return NOTIFY_DONE; -- cgit v1.2.3 From 3d705f07d16b1d872c556b4ebf44deabeca0e9c1 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Feb 2019 11:44:32 -0800 Subject: net: Remove switchdev_ops Now that we have converted all possible callers to using a switchdev notifier for attributes we do not have a need for implementing switchdev_ops anymore, and this can be removed from all drivers the net_device structure. Signed-off-by: Florian Fainelli Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 3 --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 -- .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 12 ------------ drivers/net/ethernet/mscc/ocelot.c | 5 ----- drivers/net/ethernet/rocker/rocker_main.c | 5 ----- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 5 ----- include/linux/netdevice.h | 3 --- include/net/switchdev.h | 17 ----------------- net/dsa/slave.c | 5 ----- 9 files changed, 57 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index b00f6f74f91a..6c797e322be8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3660,7 +3660,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, } mlxsw_sp_port->default_vlan = mlxsw_sp_port_vlan; - mlxsw_sp_port_switchdev_init(mlxsw_sp_port); mlxsw_sp->ports[local_port] = mlxsw_sp_port; err = register_netdev(dev); if (err) { @@ -3677,7 +3676,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, err_register_netdev: mlxsw_sp->ports[local_port] = NULL; - mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan); err_port_vlan_create: err_port_pvid_set: @@ -3720,7 +3718,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp); unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ mlxsw_sp->ports[local_port] = NULL; - mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); mlxsw_sp_port_vlan_flush(mlxsw_sp_port, true); mlxsw_sp_port_nve_fini(mlxsw_sp_port); mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index a61c1130d9e3..da6278b0caa4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -407,8 +407,6 @@ extern const struct mlxsw_sp_sb_vals mlxsw_sp2_sb_vals; /* spectrum_switchdev.c */ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp); -void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port); -void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port); int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid, bool adding); void diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index c1aedfea3a31..f6ce386c3036 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1938,10 +1938,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, return NULL; } -static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { - .switchdev_port_attr_set = mlxsw_sp_port_attr_set, -}; - static int mlxsw_sp_bridge_8021q_port_join(struct mlxsw_sp_bridge_device *bridge_device, struct mlxsw_sp_bridge_port *bridge_port, @@ -3545,11 +3541,3 @@ void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp) kfree(mlxsw_sp->bridge); } -void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port) -{ - mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops; -} - -void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port) -{ -} diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 83a678b11757..a1d0d6e42533 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1324,10 +1324,6 @@ static int ocelot_port_obj_del(struct net_device *dev, return ret; } -static const struct switchdev_ops ocelot_port_switchdev_ops = { - .switchdev_port_attr_set = ocelot_port_attr_set, -}; - static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port, struct net_device *bridge) { @@ -1660,7 +1656,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port, dev->netdev_ops = &ocelot_port_netdev_ops; dev->ethtool_ops = &ocelot_ethtool_ops; - dev->switchdev_ops = &ocelot_port_switchdev_ops; dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_RXFCS; dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index fc772cf079cc..c883aa89b7ca 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2142,10 +2142,6 @@ static int rocker_port_obj_del(struct net_device *dev, return err; } -static const struct switchdev_ops rocker_port_switchdev_ops = { - .switchdev_port_attr_set = rocker_port_attr_set, -}; - struct rocker_fib_event_work { struct work_struct work; union { @@ -2599,7 +2595,6 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) rocker_port_dev_addr_init(rocker_port); dev->netdev_ops = &rocker_port_netdev_ops; dev->ethtool_ops = &rocker_port_ethtool_ops; - dev->switchdev_ops = &rocker_port_switchdev_ops; netif_tx_napi_add(dev, &rocker_port->napi_tx, rocker_port_poll_tx, NAPI_POLL_WEIGHT); netif_napi_add(dev, &rocker_port->napi_rx, rocker_port_poll_rx, diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index b0d2d9bf2532..ad577beeb052 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -925,10 +925,6 @@ static int swdev_port_obj_del(struct net_device *netdev, return err; } -static const struct switchdev_ops ethsw_port_switchdev_ops = { - .switchdev_port_attr_set = swdev_port_attr_set, -}; - static int ethsw_switchdev_port_attr_set_event(struct net_device *netdev, struct switchdev_notifier_port_attr_info *port_attr_info) @@ -1455,7 +1451,6 @@ static int ethsw_probe_port(struct ethsw_core *ethsw, u16 port_idx) SET_NETDEV_DEV(port_netdev, dev); port_netdev->netdev_ops = ðsw_port_ops; port_netdev->ethtool_ops = ðsw_port_ethtool_ops; - port_netdev->switchdev_ops = ðsw_port_switchdev_ops; /* Set MTU limits */ port_netdev->min_mtu = ETH_MIN_MTU; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 58e83bd7a861..c10b60297d28 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1843,9 +1843,6 @@ struct net_device { #endif const struct net_device_ops *netdev_ops; const struct ethtool_ops *ethtool_ops; -#ifdef CONFIG_NET_SWITCHDEV - const struct switchdev_ops *switchdev_ops; -#endif #ifdef CONFIG_NET_L3_MASTER_DEV const struct l3mdev_ops *l3mdev_ops; #endif diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 5087c06ceb4b..e4f751e19ecf 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -112,17 +112,6 @@ void *switchdev_trans_item_dequeue(struct switchdev_trans *trans); typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); -/** - * struct switchdev_ops - switchdev operations - * - * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr). - */ -struct switchdev_ops { - int (*switchdev_port_attr_set)(struct net_device *dev, - const struct switchdev_attr *attr, - struct switchdev_trans *trans); -}; - enum switchdev_notifier_type { SWITCHDEV_FDB_ADD_TO_BRIDGE = 1, SWITCHDEV_FDB_DEL_TO_BRIDGE, @@ -226,9 +215,6 @@ int switchdev_handle_port_attr_set(struct net_device *dev, int (*set_cb)(struct net_device *dev, const struct switchdev_attr *attr, struct switchdev_trans *trans)); - -#define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops)) - #else static inline void switchdev_deferred_process(void) @@ -325,9 +311,6 @@ switchdev_handle_port_attr_set(struct net_device *dev, { return 0; } - -#define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0) - #endif #endif /* _LINUX_SWITCHDEV_H_ */ diff --git a/net/dsa/slave.c b/net/dsa/slave.c index b089b43120e1..1808a2cd6872 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1118,10 +1118,6 @@ static const struct net_device_ops dsa_slave_netdev_ops = { .ndo_vlan_rx_kill_vid = dsa_slave_vlan_rx_kill_vid, }; -static const struct switchdev_ops dsa_slave_switchdev_ops = { - .switchdev_port_attr_set = dsa_slave_port_attr_set, -}; - static struct device_type dsa_type = { .name = "dsa", }; @@ -1382,7 +1378,6 @@ int dsa_slave_create(struct dsa_port *port) eth_hw_addr_inherit(slave_dev, master); slave_dev->priv_flags |= IFF_NO_QUEUE; slave_dev->netdev_ops = &dsa_slave_netdev_ops; - slave_dev->switchdev_ops = &dsa_slave_switchdev_ops; slave_dev->min_mtu = 0; slave_dev->max_mtu = ETH_MAX_MTU; SET_NETDEV_DEVTYPE(slave_dev, &dsa_type); -- cgit v1.2.3 From 24ba14406c5c8e33fcbe064f77b3ab01b84ec830 Mon Sep 17 00:00:00 2001 From: wenxu Date: Sun, 24 Feb 2019 11:36:20 +0800 Subject: route: Add multipath_hash in flowi_common to make user-define hash Current fib_multipath_hash_policy can make hash based on the L3 or L4. But it only work on the outer IP. So a specific tunnel always has the same hash value. But a specific tunnel may contain so many inner connections. This patch provide a generic multipath_hash in floi_common. It can make a user-define hash which can mix with L3 or L4 hash. Signed-off-by: wenxu Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c | 2 +- include/net/flow.h | 2 ++ include/net/ip_tunnels.h | 3 ++- net/ipv4/ip_gre.c | 2 +- net/ipv4/ip_tunnel.c | 6 +++--- net/ipv4/route.c | 4 ++++ 6 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index ad5a9b9e1466..536c23c578c3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c @@ -305,7 +305,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev, parms = mlxsw_sp_ipip_netdev_parms4(to_dev); ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp, - 0, 0, parms.link, tun->fwmark); + 0, 0, parms.link, tun->fwmark, 0); rt = ip_route_output_key(tun->net, &fl4); if (IS_ERR(rt)) diff --git a/include/net/flow.h b/include/net/flow.h index 93f2c9a0f098..a50fb77a0b27 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -40,6 +40,7 @@ struct flowi_common { __u32 flowic_secid; kuid_t flowic_uid; struct flowi_tunnel flowic_tun_key; + __u32 flowic_multipath_hash; }; union flowi_uli { @@ -78,6 +79,7 @@ struct flowi4 { #define flowi4_secid __fl_common.flowic_secid #define flowi4_tun_key __fl_common.flowic_tun_key #define flowi4_uid __fl_common.flowic_uid +#define flowi4_multipath_hash __fl_common.flowic_multipath_hash /* (saddr,daddr) must be grouped, same order as in IP header */ __be32 saddr; diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index f069f64ebf29..af645604f328 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -241,7 +241,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4, int proto, __be32 daddr, __be32 saddr, __be32 key, __u8 tos, int oif, - __u32 mark) + __u32 mark, __u32 tun_inner_hash) { memset(fl4, 0, sizeof(*fl4)); fl4->flowi4_oif = oif; @@ -251,6 +251,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4, fl4->flowi4_proto = proto; fl4->fl4_gre_key = key; fl4->flowi4_mark = mark; + fl4->flowi4_multipath_hash = tun_inner_hash; } int ip_tunnel_init(struct net_device *dev); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 0f4925a0d6b2..fd219f7bd3ea 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -578,7 +578,7 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) key = &info->key; ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src, tunnel_id_to_key32(key->tun_id), key->tos, 0, - skb->mark); + skb->mark, skb_get_hash(skb)); rt = ip_route_output_key(dev_net(dev), &fl4); if (IS_ERR(rt)) return PTR_ERR(rt); diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 2973067b831d..2756fb725bf0 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -310,7 +310,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr, iph->saddr, tunnel->parms.o_key, RT_TOS(iph->tos), tunnel->parms.link, - tunnel->fwmark); + tunnel->fwmark, 0); rt = ip_route_output_key(tunnel->net, &fl4); if (!IS_ERR(rt)) { @@ -584,7 +584,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, } ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, tunnel_id_to_key32(key->tun_id), RT_TOS(tos), - 0, skb->mark); + 0, skb->mark, skb_get_hash(skb)); if (tunnel->encap.type != TUNNEL_ENCAP_NONE) goto tx_error; @@ -744,7 +744,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr, tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link, - tunnel->fwmark); + tunnel->fwmark, skb_get_hash(skb)); if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) goto tx_error; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index ecc12a768191..7cf4c8305071 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1820,6 +1820,7 @@ out: int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, const struct sk_buff *skb, struct flow_keys *flkeys) { + u32 multipath_hash = fl4->flowi4_multipath_hash; struct flow_keys hash_keys; u32 mhash; @@ -1870,6 +1871,9 @@ int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, } mhash = flow_hash_from_keys(&hash_keys); + if (multipath_hash) + mhash = jhash_2words(mhash, multipath_hash, 0); + return mhash >> 1; } #endif /* CONFIG_IP_ROUTE_MULTIPATH */ -- cgit v1.2.3 From 7865ad6551c92779f309ef9e433dd6a00c7aeda7 Mon Sep 17 00:00:00 2001 From: Pankaj Bansal Date: Mon, 25 Feb 2019 06:16:55 +0000 Subject: drivers: net: phy: mdio-mux: Add support for Generic Mux controls Add support for Generic Mux controls, when Mdio mux node is a consumer of mux produced by some other device. Signed-off-by: Pankaj Bansal Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 12 ++++ drivers/net/phy/Makefile | 1 + drivers/net/phy/mdio-mux-multiplexer.c | 122 +++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 drivers/net/phy/mdio-mux-multiplexer.c (limited to 'drivers') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 3d187cd50eb0..7f66af446ec7 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -87,6 +87,18 @@ config MDIO_BUS_MUX_MMIOREG Currently, only 8/16/32 bits registers are supported. +config MDIO_BUS_MUX_MULTIPLEXER + tristate "MDIO bus multiplexer using kernel multiplexer subsystem" + depends on OF + select MULTIPLEXER + select MDIO_BUS_MUX + help + This module provides a driver for MDIO bus multiplexer + that is controlled via the kernel multiplexer subsystem. The + bus multiplexer connects one of several child MDIO busses to + a parent bus. Child bus selection is under the control of + the kernel multiplexer subsystem. + config MDIO_CAVIUM tristate diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 73e9670ef7e0..ece5dae67174 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o obj-$(CONFIG_MDIO_BUS_MUX_BCM_IPROC) += mdio-mux-bcm-iproc.o obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o +obj-$(CONFIG_MDIO_BUS_MUX_MULTIPLEXER) += mdio-mux-multiplexer.o obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o diff --git a/drivers/net/phy/mdio-mux-multiplexer.c b/drivers/net/phy/mdio-mux-multiplexer.c new file mode 100644 index 000000000000..d6564381aa3e --- /dev/null +++ b/drivers/net/phy/mdio-mux-multiplexer.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* MDIO bus multiplexer using kernel multiplexer subsystem + * + * Copyright 2019 NXP + */ + +#include +#include +#include +#include + +struct mdio_mux_multiplexer_state { + struct mux_control *muxc; + bool do_deselect; + void *mux_handle; +}; + +/** + * mdio_mux_multiplexer_switch_fn - This function is called by the mdio-mux + * layer when it thinks the mdio bus + * multiplexer needs to switch. + * @current_child: current value of the mux register. + * @desired_child: value of the 'reg' property of the target child MDIO node. + * @data: Private data used by this switch_fn passed to mdio_mux_init function + * via mdio_mux_init(.., .., .., .., data, ..). + * + * The first time this function is called, current_child == -1. + * If current_child == desired_child, then the mux is already set to the + * correct bus. + */ +static int mdio_mux_multiplexer_switch_fn(int current_child, int desired_child, + void *data) +{ + struct platform_device *pdev; + struct mdio_mux_multiplexer_state *s; + int ret = 0; + + pdev = (struct platform_device *)data; + s = platform_get_drvdata(pdev); + + if (!(current_child ^ desired_child)) + return 0; + + if (s->do_deselect) + ret = mux_control_deselect(s->muxc); + if (ret) { + dev_err(&pdev->dev, "mux_control_deselect failed in %s: %d\n", + __func__, ret); + return ret; + } + + ret = mux_control_select(s->muxc, desired_child); + if (!ret) { + dev_dbg(&pdev->dev, "%s %d -> %d\n", __func__, current_child, + desired_child); + s->do_deselect = true; + } else { + s->do_deselect = false; + } + + return ret; +} + +static int mdio_mux_multiplexer_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mdio_mux_multiplexer_state *s; + int ret = 0; + + s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL); + if (!s) + return -ENOMEM; + + s->muxc = devm_mux_control_get(dev, NULL); + if (IS_ERR(s->muxc)) { + ret = PTR_ERR(s->muxc); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get mux: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, s); + + ret = mdio_mux_init(&pdev->dev, pdev->dev.of_node, + mdio_mux_multiplexer_switch_fn, &s->mux_handle, + pdev, NULL); + + return ret; +} + +static int mdio_mux_multiplexer_remove(struct platform_device *pdev) +{ + struct mdio_mux_multiplexer_state *s = platform_get_drvdata(pdev); + + mdio_mux_uninit(s->mux_handle); + + if (s->do_deselect) + mux_control_deselect(s->muxc); + + return 0; +} + +static const struct of_device_id mdio_mux_multiplexer_match[] = { + { .compatible = "mdio-mux-multiplexer", }, + {}, +}; +MODULE_DEVICE_TABLE(of, mdio_mux_multiplexer_match); + +static struct platform_driver mdio_mux_multiplexer_driver = { + .driver = { + .name = "mdio-mux-multiplexer", + .of_match_table = mdio_mux_multiplexer_match, + }, + .probe = mdio_mux_multiplexer_probe, + .remove = mdio_mux_multiplexer_remove, +}; + +module_platform_driver(mdio_mux_multiplexer_driver); + +MODULE_DESCRIPTION("MDIO bus multiplexer using kernel multiplexer subsystem"); +MODULE_AUTHOR("Pankaj Bansal "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 013ba864b0b55de05ec1a6f4a375a0db9130291c Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Mon, 25 Feb 2019 17:14:06 +0100 Subject: net: phy: marvell10g: Let genphy_c45_pma_read_abilities set Aneg bit The genphy_c45_pma_read_abilities helper now sets the Autoneg ability in phydev->supported according to what the AN MMD reports. We therefore don't need to manually do that in mv3310_get_features(). Signed-off-by: Maxime Chevallier Suggested-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 580e91deadbc..ab71da55c1e0 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -268,16 +268,6 @@ static int mv3310_get_features(struct phy_device *phydev) { int ret, val; - if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) { - val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); - if (val < 0) - return val; - - if (val & MDIO_AN_STAT1_ABLE) - linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - phydev->supported); - } - ret = genphy_c45_pma_read_abilities(phydev); if (ret) return ret; -- cgit v1.2.3 From 41e2a99fb9fa3e786c3f796d502c1babd116266f Mon Sep 17 00:00:00 2001 From: Maxime Chevallier Date: Mon, 25 Feb 2019 17:14:07 +0100 Subject: net: phy: marvell10g: Use the generic C45 helper to read the 2110 features Contrary to the 3310, the 2110 PHY correctly reports it's 2.5G/5G abilities. We can therefore use the genphy_c45_pma_read_abilities helper to build the list of features. Signed-off-by: Maxime Chevallier Signed-off-by: David S. Miller --- drivers/net/phy/marvell10g.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index ab71da55c1e0..79106e70010f 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -472,7 +472,7 @@ static struct phy_driver mv3310_drivers[] = { .phy_id = MARVELL_PHY_ID_88E2110, .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "mv88x2110", - .features = PHY_10GBIT_FEATURES, + .get_features = genphy_c45_pma_read_abilities, .probe = mv3310_probe, .soft_reset = gen10g_no_soft_reset, .config_init = mv3310_config_init, -- cgit v1.2.3 From d89ea4acfc039f6968f8b5a1dfae5d3cbf611444 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 25 Feb 2019 18:27:57 -0600 Subject: net: hns: use struct_size() in devm_kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; struct boo entry[]; }; instance = devm_kzalloc(dev, sizeof(struct foo) + sizeof(struct boo) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = devm_kzalloc(dev, struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c index 0942e4916d9d..3d07c8a7639d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c @@ -83,8 +83,9 @@ static int hns_ppe_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index) else ppe_num = HNS_PPE_DEBUG_NW_ENGINE_NUM; - ppe_common = devm_kzalloc(dsaf_dev->dev, sizeof(*ppe_common) + - ppe_num * sizeof(struct hns_ppe_cb), GFP_KERNEL); + ppe_common = devm_kzalloc(dsaf_dev->dev, + struct_size(ppe_common, ppe_cb, ppe_num), + GFP_KERNEL); if (!ppe_common) return -ENOMEM; -- cgit v1.2.3 From 0c7051610c577b60b01b3b5aec14d6765e177b0d Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 21 Feb 2019 11:33:24 +0100 Subject: brcmfmac: fix size of the struct msgbuf_ring_status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This updates host struct to match the in-firmawre definition. It's a cosmetic change as it only applies to the reserved struct space. Fixes: c988b78244df ("brcmfmac: print firmware reported ring status errors") Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index aef2d4092872..d711dc8ed606 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -139,7 +139,7 @@ struct msgbuf_ring_status { struct msgbuf_common_hdr msg; struct msgbuf_completion_hdr compl_hdr; __le16 write_idx; - __le32 rsvd0[5]; + __le16 rsvd0[5]; }; struct msgbuf_rx_event { -- cgit v1.2.3 From c91377495192cda096e52dc09c266b0d05f16d86 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 21 Feb 2019 11:33:25 +0100 Subject: brcmfmac: print firmware reported general status errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firmware may report general errors using a special message type. Add basic support for it by simply decoding & printing an error number. A sample situation in which firmware reports a buf error: CONSOLE: 027084.733 no host response IOCTL buffer available..so fail the request will now produce a "Firmware reported general error: 9" on the host. Signed-off-by: Rafał Miłecki Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index d711dc8ed606..d3780eae7f19 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -134,6 +134,14 @@ struct msgbuf_completion_hdr { __le16 flow_ring_id; }; +/* Data struct for the MSGBUF_TYPE_GEN_STATUS */ +struct msgbuf_gen_status { + struct msgbuf_common_hdr msg; + struct msgbuf_completion_hdr compl_hdr; + __le16 write_idx; + __le32 rsvd0[3]; +}; + /* Data struct for the MSGBUF_TYPE_RING_STATUS */ struct msgbuf_ring_status { struct msgbuf_common_hdr msg; @@ -1194,6 +1202,18 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) brcmf_netif_rx(ifp, skb); } +static void brcmf_msgbuf_process_gen_status(struct brcmf_msgbuf *msgbuf, + void *buf) +{ + struct msgbuf_gen_status *gen_status = buf; + struct brcmf_pub *drvr = msgbuf->drvr; + int err; + + err = le16_to_cpu(gen_status->compl_hdr.status); + if (err) + bphy_err(drvr, "Firmware reported general error: %d\n", err); +} + static void brcmf_msgbuf_process_ring_status(struct brcmf_msgbuf *msgbuf, void *buf) { @@ -1273,6 +1293,10 @@ static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf) msg = (struct msgbuf_common_hdr *)buf; switch (msg->msgtype) { + case MSGBUF_TYPE_GEN_STATUS: + brcmf_dbg(MSGBUF, "MSGBUF_TYPE_GEN_STATUS\n"); + brcmf_msgbuf_process_gen_status(msgbuf, buf); + break; case MSGBUF_TYPE_RING_STATUS: brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RING_STATUS\n"); brcmf_msgbuf_process_ring_status(msgbuf, buf); -- cgit v1.2.3 From 74ee436f958126f96f2e10d44a8ef13cd8d46ef9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 21 Feb 2019 12:35:49 +0000 Subject: rsi: fix missing null pointer check from a failed ieee80211_probereq_get call The call to ieee80211_probereq_get can return NULL if a skb allocation fails, so add a null pointer check and free an earlier skb on the error exit return path. Fixes: 7fdcb8e12660 ("rsi: add support for hardware scan offload") Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/rsi/rsi_91x_mgmt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 8c17842ac507..844f2fac298f 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -1726,6 +1726,10 @@ int rsi_send_bgscan_probe_req(struct rsi_common *common, probereq_skb = ieee80211_probereq_get(common->priv->hw, vif->addr, ssid, ssid_len, scan_req->ie_len); + if (!probereq_skb) { + dev_kfree_skb(skb); + return -ENOMEM; + } memcpy(&skb->data[frame_len], probereq_skb->data, probereq_skb->len); -- cgit v1.2.3 From 6e5d9041525a39965156f4991dcd7cf8672ca397 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 21 Feb 2019 13:31:08 -0600 Subject: rtlwifi: Fix errors in spacing in wifi.h Checkpatch.pl report problems in wifi.h where spaces are missing, as well as extraneous spaces. There are no changes in the generated code. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/wifi.h | 170 ++++++++++++++-------------- 1 file changed, 85 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 1ad71fb0ebf2..858cd798d5cb 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -413,8 +413,8 @@ enum hw_variables { HW_VAR_MULTICAST_REG = 0x1, HW_VAR_BASIC_RATE = 0x2, HW_VAR_BSSID = 0x3, - HW_VAR_MEDIA_STATUS= 0x4, - HW_VAR_SECURITY_CONF= 0x5, + HW_VAR_MEDIA_STATUS = 0x4, + HW_VAR_SECURITY_CONF = 0x5, HW_VAR_BEACON_INTERVAL = 0x6, HW_VAR_ATIM_WINDOW = 0x7, HW_VAR_LISTEN_INTERVAL = 0x8, @@ -431,7 +431,7 @@ enum hw_variables { HW_VAR_ACK_PREAMBLE = 0x13, HW_VAR_CW_CONFIG = 0x14, HW_VAR_CW_VALUES = 0x15, - HW_VAR_RATE_FALLBACK_CONTROL= 0x16, + HW_VAR_RATE_FALLBACK_CONTROL = 0x16, HW_VAR_CONTENTION_WINDOW = 0x17, HW_VAR_RETRY_COUNT = 0x18, HW_VAR_TR_SWITCH = 0x19, @@ -1456,15 +1456,15 @@ struct rtl_io { /*PCI IO map */ unsigned long pci_base_addr; /*device I/O address */ - void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); - void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val); - void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val); + void (*write8_async)(struct rtl_priv *rtlpriv, u32 addr, u8 val); + void (*write16_async)(struct rtl_priv *rtlpriv, u32 addr, u16 val); + void (*write32_async)(struct rtl_priv *rtlpriv, u32 addr, u32 val); void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf, u16 len); - u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); - u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); - u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); + u8 (*read8_sync)(struct rtl_priv *rtlpriv, u32 addr); + u16 (*read16_sync)(struct rtl_priv *rtlpriv, u32 addr); + u32 (*read32_sync)(struct rtl_priv *rtlpriv, u32 addr); }; @@ -2210,44 +2210,44 @@ struct rtl_int { }; struct rtl_hal_ops { - int (*init_sw_vars) (struct ieee80211_hw *hw); - void (*deinit_sw_vars) (struct ieee80211_hw *hw); + int (*init_sw_vars)(struct ieee80211_hw *hw); + void (*deinit_sw_vars)(struct ieee80211_hw *hw); void (*read_chip_version)(struct ieee80211_hw *hw); - void (*read_eeprom_info) (struct ieee80211_hw *hw); - void (*interrupt_recognized) (struct ieee80211_hw *hw, + void (*read_eeprom_info)(struct ieee80211_hw *hw); + void (*interrupt_recognized)(struct ieee80211_hw *hw, struct rtl_int *intvec); - int (*hw_init) (struct ieee80211_hw *hw); - void (*hw_disable) (struct ieee80211_hw *hw); - void (*hw_suspend) (struct ieee80211_hw *hw); - void (*hw_resume) (struct ieee80211_hw *hw); - void (*enable_interrupt) (struct ieee80211_hw *hw); - void (*disable_interrupt) (struct ieee80211_hw *hw); - int (*set_network_type) (struct ieee80211_hw *hw, + int (*hw_init)(struct ieee80211_hw *hw); + void (*hw_disable)(struct ieee80211_hw *hw); + void (*hw_suspend)(struct ieee80211_hw *hw); + void (*hw_resume)(struct ieee80211_hw *hw); + void (*enable_interrupt)(struct ieee80211_hw *hw); + void (*disable_interrupt)(struct ieee80211_hw *hw); + int (*set_network_type)(struct ieee80211_hw *hw, enum nl80211_iftype type); void (*set_chk_bssid)(struct ieee80211_hw *hw, bool check_bssid); - void (*set_bw_mode) (struct ieee80211_hw *hw, + void (*set_bw_mode)(struct ieee80211_hw *hw, enum nl80211_channel_type ch_type); - u8(*switch_channel) (struct ieee80211_hw *hw); - void (*set_qos) (struct ieee80211_hw *hw, int aci); - void (*set_bcn_reg) (struct ieee80211_hw *hw); - void (*set_bcn_intv) (struct ieee80211_hw *hw); - void (*update_interrupt_mask) (struct ieee80211_hw *hw, + u8 (*switch_channel)(struct ieee80211_hw *hw); + void (*set_qos)(struct ieee80211_hw *hw, int aci); + void (*set_bcn_reg)(struct ieee80211_hw *hw); + void (*set_bcn_intv)(struct ieee80211_hw *hw); + void (*update_interrupt_mask)(struct ieee80211_hw *hw, u32 add_msr, u32 rm_msr); - void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); - void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); - void (*update_rate_tbl) (struct ieee80211_hw *hw, + void (*get_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val); + void (*set_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val); + void (*update_rate_tbl)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 rssi_leve, bool update_bw); void (*pre_fill_tx_bd_desc)(struct ieee80211_hw *hw, u8 *tx_bd_desc, u8 *desc, u8 queue_index, struct sk_buff *skb, dma_addr_t addr); - void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); + void (*update_rate_mask)(struct ieee80211_hw *hw, u8 rssi_level); u16 (*rx_desc_buff_remained_cnt)(struct ieee80211_hw *hw, u8 queue_index); void (*rx_check_dma_ok)(struct ieee80211_hw *hw, u8 *header_desc, u8 queue_index); - void (*fill_tx_desc) (struct ieee80211_hw *hw, + void (*fill_tx_desc)(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, u8 *pbd_desc_tx, struct ieee80211_tx_info *info, @@ -2256,68 +2256,68 @@ struct rtl_hal_ops { struct rtl_tcb_desc *ptcb_desc); void (*fill_fake_txdesc)(struct ieee80211_hw *hw, u8 *pdesc, u32 buffer_len, bool bsspspoll); - void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, + void (*fill_tx_cmddesc)(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, bool lastseg, struct sk_buff *skb); void (*fill_tx_special_desc)(struct ieee80211_hw *hw, u8 *pdesc, u8 *pbd_desc, struct sk_buff *skb, u8 hw_queue); - bool (*query_rx_desc) (struct ieee80211_hw *hw, + bool (*query_rx_desc)(struct ieee80211_hw *hw, struct rtl_stats *stats, struct ieee80211_rx_status *rx_status, u8 *pdesc, struct sk_buff *skb); - void (*set_channel_access) (struct ieee80211_hw *hw); - bool (*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid); - void (*dm_watchdog) (struct ieee80211_hw *hw); - void (*scan_operation_backup) (struct ieee80211_hw *hw, u8 operation); - bool (*set_rf_power_state) (struct ieee80211_hw *hw, + void (*set_channel_access)(struct ieee80211_hw *hw); + bool (*radio_onoff_checking)(struct ieee80211_hw *hw, u8 *valid); + void (*dm_watchdog)(struct ieee80211_hw *hw); + void (*scan_operation_backup)(struct ieee80211_hw *hw, u8 operation); + bool (*set_rf_power_state)(struct ieee80211_hw *hw, enum rf_pwrstate rfpwr_state); - void (*led_control) (struct ieee80211_hw *hw, + void (*led_control)(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); void (*set_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, u8 desc_name, u8 *val); u64 (*get_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, u8 desc_name); - bool (*is_tx_desc_closed) (struct ieee80211_hw *hw, + bool (*is_tx_desc_closed)(struct ieee80211_hw *hw, u8 hw_queue, u16 index); - void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue); - void (*enable_hw_sec) (struct ieee80211_hw *hw); - void (*set_key) (struct ieee80211_hw *hw, u32 key_index, + void (*tx_polling)(struct ieee80211_hw *hw, u8 hw_queue); + void (*enable_hw_sec)(struct ieee80211_hw *hw); + void (*set_key)(struct ieee80211_hw *hw, u32 key_index, u8 *macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all); - void (*init_sw_leds) (struct ieee80211_hw *hw); - void (*deinit_sw_leds) (struct ieee80211_hw *hw); - u32 (*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); - void (*set_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, + void (*init_sw_leds)(struct ieee80211_hw *hw); + void (*deinit_sw_leds)(struct ieee80211_hw *hw); + u32 (*get_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); + void (*set_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, u32 data); - u32 (*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, + u32 (*get_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask); - void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, + void (*set_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath, u32 regaddr, u32 bitmask, u32 data); - void (*linked_set_reg) (struct ieee80211_hw *hw); - void (*chk_switch_dmdp) (struct ieee80211_hw *hw); - void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); - void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); - bool (*phy_rf6052_config) (struct ieee80211_hw *hw); - void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw, + void (*linked_set_reg)(struct ieee80211_hw *hw); + void (*chk_switch_dmdp)(struct ieee80211_hw *hw); + void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw); + void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw); + bool (*phy_rf6052_config)(struct ieee80211_hw *hw); + void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw, u8 *powerlevel); - void (*phy_rf6052_set_ofdm_txpower) (struct ieee80211_hw *hw, + void (*phy_rf6052_set_ofdm_txpower)(struct ieee80211_hw *hw, u8 *ppowerlevel, u8 channel); - bool (*config_bb_with_headerfile) (struct ieee80211_hw *hw, + bool (*config_bb_with_headerfile)(struct ieee80211_hw *hw, u8 configtype); - bool (*config_bb_with_pgheaderfile) (struct ieee80211_hw *hw, + bool (*config_bb_with_pgheaderfile)(struct ieee80211_hw *hw, u8 configtype); - void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t); - void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw); - void (*dm_dynamic_txpower) (struct ieee80211_hw *hw); - void (*c2h_command_handle) (struct ieee80211_hw *hw); - void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw, + void (*phy_lc_calibrate)(struct ieee80211_hw *hw, bool is2t); + void (*phy_set_bw_mode_callback)(struct ieee80211_hw *hw); + void (*dm_dynamic_txpower)(struct ieee80211_hw *hw); + void (*c2h_command_handle)(struct ieee80211_hw *hw); + void (*bt_wifi_media_status_notify)(struct ieee80211_hw *hw, bool mstate); - void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw); - void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id, + void (*bt_coex_off_before_lps)(struct ieee80211_hw *hw); + void (*fill_h2c_cmd)(struct ieee80211_hw *hw, u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); void (*set_default_port_id_cmd)(struct ieee80211_hw *hw); - bool (*get_btc_status) (void); + bool (*get_btc_status)(void); bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr); void (*add_wowlan_pattern)(struct ieee80211_hw *hw, struct rtl_wow_pattern *rtl_pattern, @@ -2330,24 +2330,24 @@ struct rtl_hal_ops { struct rtl_intf_ops { /*com */ void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); - int (*adapter_start) (struct ieee80211_hw *hw); - void (*adapter_stop) (struct ieee80211_hw *hw); + int (*adapter_start)(struct ieee80211_hw *hw); + void (*adapter_stop)(struct ieee80211_hw *hw); bool (*check_buddy_priv)(struct ieee80211_hw *hw, struct rtl_priv **buddy_priv); - int (*adapter_tx) (struct ieee80211_hw *hw, + int (*adapter_tx)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct sk_buff *skb, struct rtl_tcb_desc *ptcb_desc); void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop); - int (*reset_trx_ring) (struct ieee80211_hw *hw); - bool (*waitq_insert) (struct ieee80211_hw *hw, + int (*reset_trx_ring)(struct ieee80211_hw *hw); + bool (*waitq_insert)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, struct sk_buff *skb); /*pci */ - void (*disable_aspm) (struct ieee80211_hw *hw); - void (*enable_aspm) (struct ieee80211_hw *hw); + void (*disable_aspm)(struct ieee80211_hw *hw); + void (*enable_aspm)(struct ieee80211_hw *hw); /*usb */ }; @@ -2666,30 +2666,30 @@ struct bt_coexist_info { }; struct rtl_btc_ops { - void (*btc_init_variables) (struct rtl_priv *rtlpriv); + void (*btc_init_variables)(struct rtl_priv *rtlpriv); void (*btc_init_variables_wifi_only)(struct rtl_priv *rtlpriv); void (*btc_deinit_variables)(struct rtl_priv *rtlpriv); - void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv); + void (*btc_init_hal_vars)(struct rtl_priv *rtlpriv); void (*btc_power_on_setting)(struct rtl_priv *rtlpriv); - void (*btc_init_hw_config) (struct rtl_priv *rtlpriv); + void (*btc_init_hw_config)(struct rtl_priv *rtlpriv); void (*btc_init_hw_config_wifi_only)(struct rtl_priv *rtlpriv); - void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type); + void (*btc_ips_notify)(struct rtl_priv *rtlpriv, u8 type); void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type); - void (*btc_scan_notify) (struct rtl_priv *rtlpriv, u8 scantype); + void (*btc_scan_notify)(struct rtl_priv *rtlpriv, u8 scantype); void (*btc_scan_notify_wifi_only)(struct rtl_priv *rtlpriv, u8 scantype); - void (*btc_connect_notify) (struct rtl_priv *rtlpriv, u8 action); - void (*btc_mediastatus_notify) (struct rtl_priv *rtlpriv, + void (*btc_connect_notify)(struct rtl_priv *rtlpriv, u8 action); + void (*btc_mediastatus_notify)(struct rtl_priv *rtlpriv, enum rt_media_status mstatus); - void (*btc_periodical) (struct rtl_priv *rtlpriv); + void (*btc_periodical)(struct rtl_priv *rtlpriv); void (*btc_halt_notify)(struct rtl_priv *rtlpriv); - void (*btc_btinfo_notify) (struct rtl_priv *rtlpriv, + void (*btc_btinfo_notify)(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length); void (*btc_btmpinfo_notify)(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length); - bool (*btc_is_limited_dig) (struct rtl_priv *rtlpriv); - bool (*btc_is_disable_edca_turbo) (struct rtl_priv *rtlpriv); - bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv); + bool (*btc_is_limited_dig)(struct rtl_priv *rtlpriv); + bool (*btc_is_disable_edca_turbo)(struct rtl_priv *rtlpriv); + bool (*btc_is_bt_disabled)(struct rtl_priv *rtlpriv); void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv, u8 pkt_type); void (*btc_switch_band_notify)(struct rtl_priv *rtlpriv, u8 type, -- cgit v1.2.3 From d3da329c1d8cf97d755b5f13c23511861b170a53 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 21 Feb 2019 13:31:09 -0600 Subject: rtlwifi: Fix problems with block comments in wifi.h Checkpatch.pl reports a number of problems with block comments. These changes do not affect the generated code. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/wifi.h | 93 ++++++++++++++++------------- 1 file changed, 50 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 858cd798d5cb..9fe137fa5ead 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -598,7 +598,8 @@ enum ht_channel_width { }; /* Ref: 802.11i sepc D10.0 7.3.2.25.1 -Cipher Suites Encryption Algorithms */ + * Cipher Suites Encryption Algorithms + */ enum rt_enc_alg { NO_ENCRYPTION = 0, WEP40_ENCRYPTION = 1, @@ -748,7 +749,8 @@ enum rtl_var_map { RTL_IMR_ROK, /*Receive DMA OK Interrupt */ RTL_IMR_HSISR_IND, /*HSISR Interrupt*/ RTL_IBSS_INT_MASKS, /*(RTL_IMR_BCNINT | RTL_IMR_TBDOK | - * RTL_IMR_TBDER) */ + * RTL_IMR_TBDER) + */ RTL_IMR_C2HCMD, /*fw interrupt*/ /*CCK Rates, TxHT = 0 */ @@ -845,8 +847,9 @@ enum band_type { BANDMAX }; -/*aci/aifsn Field. -Ref: WMM spec 2.2.2: WME Parameter Element, p.12.*/ +/* aci/aifsn Field. + * Ref: WMM spec 2.2.2: WME Parameter Element, p.12. + */ union aci_aifsn { u8 char_data; @@ -1062,7 +1065,8 @@ struct rtl_probe_rsp { __le16 beacon_interval; __le16 capability; /*SSID, supported rates, FH params, DS params, - CF params, IBSS params, TIM (if beacon), RSN */ + * CF params, IBSS params, TIM (if beacon), RSN + */ struct rtl_info_element info_element[0]; } __packed; @@ -1136,7 +1140,8 @@ struct wireless_stats { long rx_snr_db[4]; /*Correct smoothed ss in Dbm, only used - in driver to report real power now. */ + * in driver to report real power now. + */ long recv_signal_power; long signal_quality; long last_sigstrength_inpercent; @@ -1144,8 +1149,9 @@ struct wireless_stats { u32 rssi_calculate_cnt; u32 pwdb_all_cnt; - /*Transformed, in dbm. Beautified signal - strength for UI, not correct. */ + /* Transformed, in dbm. Beautified signal + * strength for UI, not correct. + */ long signal_strength; u8 rx_rssi_percentage[4]; @@ -1689,7 +1695,8 @@ struct rtl_hal { bool during_mac1init_radioa; bool reloadtxpowerindex; /* True if IMR or IQK have done - for 2.4G in scan progress */ + * for 2.4G in scan progress + */ bool load_imrandiqk_setting_for2g; bool disable_amsdu_8k; @@ -1728,12 +1735,14 @@ struct rtl_security { u32 hwsec_cam_bitmap; u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; /*local Key buffer, indx 0 is for - pairwise key 1-4 is for agoup key. */ + * pairwise key 1-4 is for agoup key. + */ u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; u8 key_len[KEY_BUF_SIZE]; /*The pointer of Pairwise Key, - it always points to KeyBuf[4] */ + * it always points to KeyBuf[4] + */ u8 *pairwise_key; }; @@ -1997,11 +2006,10 @@ struct rtl_ps_ctl { bool rfchange_inprogress; bool swrf_processing; bool hwradiooff; - /* - * just for PCIE ASPM + /* just for PCIE ASPM * If it supports ASPM, Offset[560h] = 0x40, * otherwise Offset[560h] = 0x00. - * */ + */ bool support_aspm; bool support_backdoor; @@ -2081,10 +2089,9 @@ struct rtl_stats { u8 nic_type; u16 length; u8 signalquality; /*in 0-100 index. */ - /* - * Real power in dBm for this packet, + /* Real power in dBm for this packet, * no beautification and aggregation. - * */ + */ s32 recvsignalpower; s8 rxpower; /*in dBm Translate from PWdB */ u8 signalstrength; /*in 0-100 index. */ @@ -2425,7 +2432,8 @@ struct rtl_hal_cfg { enum rtl_spec_ver spec_ver; /*this map used for some registers or vars - defined int HAL but used in MAIN */ + * defined int HAL but used in MAIN + */ u32 maps[RTL_VAR_MAP_MAX]; }; @@ -2587,7 +2595,8 @@ struct dig_t { struct rtl_global_var { /* from this list we can get - * other adapter's rtl_priv */ + * other adapter's rtl_priv + */ struct list_head glb_priv_list; spinlock_t glb_list_lock; }; @@ -2775,16 +2784,16 @@ struct rtl_priv { struct rtl_debug dbg; int max_fw_size; - /* - *hal_cfg : for diff cards - *intf_ops : for diff interrface usb/pcie + /* hal_cfg : for diff cards + * intf_ops : for diff interrface usb/pcie */ struct rtl_hal_cfg *cfg; const struct rtl_intf_ops *intf_ops; - /*this var will be set by set_bit, - and was used to indicate status of - interface or hardware */ + /* this var will be set by set_bit, + * and was used to indicate status of + * interface or hardware + */ unsigned long status; /* tables for dm */ @@ -2820,10 +2829,11 @@ struct rtl_priv { #ifdef CONFIG_PM struct wiphy_wowlan_support wowlan; #endif - /*This must be the last item so - that it points to the data allocated - beyond this structure like: - rtl_pci_priv or rtl_usb_priv */ + /* This must be the last item so + * that it points to the data allocated + * beyond this structure like: + * rtl_pci_priv or rtl_usb_priv + */ u8 priv[0] __aligned(sizeof(void *)); }; @@ -2834,9 +2844,7 @@ struct rtl_priv { #define rtl_psc(rtlpriv) (&((rtlpriv)->psc)) -/*************************************** - Bluetooth Co-existence Related -****************************************/ +/* Bluetooth Co-existence Related */ enum bt_ant_num { ANT_X2 = 0, @@ -2887,12 +2895,12 @@ enum bt_radio_shared { /**************************************** - mem access macro define start - Call endian free function when - 1. Read/write packet content. - 2. Before write integer to IO. - 3. After read integer from IO. -****************************************/ + * mem access macro define start + * Call endian free function when + * 1. Read/write packet content. + * 2. Before write integer to IO. + * 3. After read integer from IO. + ****************************************/ /* Convert little data endian to host ordering */ #define EF1BYTE(_val) \ ((u8)(_val)) @@ -2948,8 +2956,9 @@ enum bt_radio_shared { (EF1BYTE(*((u8 *)(__pstart)))) /*Description: -Translate subfield (continuous bits in little-endian) of 4-byte -value to host byte ordering.*/ + * Translate subfield (continuous bits in little-endian) of 4-byte + * value to host byte ordering. + */ #define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ ( \ (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ @@ -3011,9 +3020,7 @@ value to host byte ordering.*/ #define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) -/**************************************** - mem access macro define end -****************************************/ +/* mem access macro define end */ #define byte(x, n) ((x >> (8 * n)) & 0xff) -- cgit v1.2.3 From 1dc89bb93c4296a3cb2b7d1a61cd9549002a1dad Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 21 Feb 2019 13:31:10 -0600 Subject: rtlwifi: Fix alignment errors in wifi.h The instances where statement continuations are improperly aligned have been fixed. There are no changes to generated code. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/wifi.h | 84 ++++++++++++++--------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 9fe137fa5ead..88f94662c072 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -1466,7 +1466,7 @@ struct rtl_io { void (*write16_async)(struct rtl_priv *rtlpriv, u32 addr, u16 val); void (*write32_async)(struct rtl_priv *rtlpriv, u32 addr, u32 val); void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf, - u16 len); + u16 len); u8 (*read8_sync)(struct rtl_priv *rtlpriv, u32 addr); u16 (*read16_sync)(struct rtl_priv *rtlpriv, u32 addr); @@ -2222,7 +2222,7 @@ struct rtl_hal_ops { void (*read_chip_version)(struct ieee80211_hw *hw); void (*read_eeprom_info)(struct ieee80211_hw *hw); void (*interrupt_recognized)(struct ieee80211_hw *hw, - struct rtl_int *intvec); + struct rtl_int *intvec); int (*hw_init)(struct ieee80211_hw *hw); void (*hw_disable)(struct ieee80211_hw *hw); void (*hw_suspend)(struct ieee80211_hw *hw); @@ -2230,22 +2230,22 @@ struct rtl_hal_ops { void (*enable_interrupt)(struct ieee80211_hw *hw); void (*disable_interrupt)(struct ieee80211_hw *hw); int (*set_network_type)(struct ieee80211_hw *hw, - enum nl80211_iftype type); + enum nl80211_iftype type); void (*set_chk_bssid)(struct ieee80211_hw *hw, - bool check_bssid); + bool check_bssid); void (*set_bw_mode)(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); + enum nl80211_channel_type ch_type); u8 (*switch_channel)(struct ieee80211_hw *hw); void (*set_qos)(struct ieee80211_hw *hw, int aci); void (*set_bcn_reg)(struct ieee80211_hw *hw); void (*set_bcn_intv)(struct ieee80211_hw *hw); void (*update_interrupt_mask)(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); + u32 add_msr, u32 rm_msr); void (*get_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val); void (*set_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val); void (*update_rate_tbl)(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_leve, - bool update_bw); + struct ieee80211_sta *sta, u8 rssi_leve, + bool update_bw); void (*pre_fill_tx_bd_desc)(struct ieee80211_hw *hw, u8 *tx_bd_desc, u8 *desc, u8 queue_index, struct sk_buff *skb, dma_addr_t addr); @@ -2255,74 +2255,74 @@ struct rtl_hal_ops { void (*rx_check_dma_ok)(struct ieee80211_hw *hw, u8 *header_desc, u8 queue_index); void (*fill_tx_desc)(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, u8 hw_queue, - struct rtl_tcb_desc *ptcb_desc); + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); void (*fill_fake_txdesc)(struct ieee80211_hw *hw, u8 *pdesc, u32 buffer_len, bool bsspspoll); void (*fill_tx_cmddesc)(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, - struct sk_buff *skb); + bool firstseg, bool lastseg, + struct sk_buff *skb); void (*fill_tx_special_desc)(struct ieee80211_hw *hw, u8 *pdesc, u8 *pbd_desc, struct sk_buff *skb, u8 hw_queue); bool (*query_rx_desc)(struct ieee80211_hw *hw, - struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); void (*set_channel_access)(struct ieee80211_hw *hw); bool (*radio_onoff_checking)(struct ieee80211_hw *hw, u8 *valid); void (*dm_watchdog)(struct ieee80211_hw *hw); void (*scan_operation_backup)(struct ieee80211_hw *hw, u8 operation); bool (*set_rf_power_state)(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); + enum rf_pwrstate rfpwr_state); void (*led_control)(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction); + enum led_ctl_mode ledaction); void (*set_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, u8 desc_name, u8 *val); u64 (*get_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, u8 desc_name); bool (*is_tx_desc_closed)(struct ieee80211_hw *hw, - u8 hw_queue, u16 index); + u8 hw_queue, u16 index); void (*tx_polling)(struct ieee80211_hw *hw, u8 hw_queue); void (*enable_hw_sec)(struct ieee80211_hw *hw); void (*set_key)(struct ieee80211_hw *hw, u32 key_index, - u8 *macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); + u8 *macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); void (*init_sw_leds)(struct ieee80211_hw *hw); void (*deinit_sw_leds)(struct ieee80211_hw *hw); u32 (*get_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); void (*set_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, - u32 data); + u32 data); u32 (*get_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask); + u32 regaddr, u32 bitmask); void (*set_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); + u32 regaddr, u32 bitmask, u32 data); void (*linked_set_reg)(struct ieee80211_hw *hw); void (*chk_switch_dmdp)(struct ieee80211_hw *hw); void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw); void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw); bool (*phy_rf6052_config)(struct ieee80211_hw *hw); void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw, - u8 *powerlevel); + u8 *powerlevel); void (*phy_rf6052_set_ofdm_txpower)(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); + u8 *ppowerlevel, u8 channel); bool (*config_bb_with_headerfile)(struct ieee80211_hw *hw, - u8 configtype); + u8 configtype); bool (*config_bb_with_pgheaderfile)(struct ieee80211_hw *hw, - u8 configtype); + u8 configtype); void (*phy_lc_calibrate)(struct ieee80211_hw *hw, bool is2t); void (*phy_set_bw_mode_callback)(struct ieee80211_hw *hw); void (*dm_dynamic_txpower)(struct ieee80211_hw *hw); void (*c2h_command_handle)(struct ieee80211_hw *hw); void (*bt_wifi_media_status_notify)(struct ieee80211_hw *hw, - bool mstate); + bool mstate); void (*bt_coex_off_before_lps)(struct ieee80211_hw *hw); void (*fill_h2c_cmd)(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *p_cmdbuffer); + u32 cmd_len, u8 *p_cmdbuffer); void (*set_default_port_id_cmd)(struct ieee80211_hw *hw); bool (*get_btc_status)(void); bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr); @@ -2343,14 +2343,14 @@ struct rtl_intf_ops { struct rtl_priv **buddy_priv); int (*adapter_tx)(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb, - struct rtl_tcb_desc *ptcb_desc); + struct ieee80211_sta *sta, + struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc); void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop); int (*reset_trx_ring)(struct ieee80211_hw *hw); bool (*waitq_insert)(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb); + struct ieee80211_sta *sta, + struct sk_buff *skb); /*pci */ void (*disable_aspm)(struct ieee80211_hw *hw); @@ -2689,11 +2689,11 @@ struct rtl_btc_ops { u8 scantype); void (*btc_connect_notify)(struct rtl_priv *rtlpriv, u8 action); void (*btc_mediastatus_notify)(struct rtl_priv *rtlpriv, - enum rt_media_status mstatus); + enum rt_media_status mstatus); void (*btc_periodical)(struct rtl_priv *rtlpriv); void (*btc_halt_notify)(struct rtl_priv *rtlpriv); void (*btc_btinfo_notify)(struct rtl_priv *rtlpriv, - u8 *tmp_buf, u8 length); + u8 *tmp_buf, u8 length); void (*btc_btmpinfo_notify)(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length); bool (*btc_is_limited_dig)(struct rtl_priv *rtlpriv); @@ -3155,7 +3155,7 @@ static inline void rtl_set_bbreg(struct ieee80211_hw *hw, u32 regaddr, } static inline void rtl_set_bbreg_with_dwmask(struct ieee80211_hw *hw, - u32 regaddr, u32 data) + u32 regaddr, u32 data) { rtl_set_bbreg(hw, regaddr, 0xffffffff, data); } @@ -3226,7 +3226,7 @@ static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, } static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw, - u8 *mac_addr) + u8 *mac_addr) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); return ieee80211_find_sta(mac->vif, mac_addr); -- cgit v1.2.3 From 93665097ea23c794eac4583bc0c2e248a563bb04 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 21 Feb 2019 13:31:11 -0600 Subject: rtlwifi: Fix blank line errors in main header files The errors consist of multiple blank lines, and a missing blank line after the declarations. There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/usb.h | 5 +---- drivers/net/wireless/realtek/rtlwifi/wifi.h | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h index 09bbcdbe0dbf..3bf85b23eec1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.h +++ b/drivers/net/wireless/realtek/rtlwifi/usb.h @@ -17,7 +17,6 @@ #define USB_HIGH_SPEED_BULK_SIZE 512 #define USB_FULL_SPEED_BULK_SIZE 64 - #define RTL_USB_MAX_TXQ_NUM 4 /* max tx queue */ #define RTL_USB_MAX_EP_NUM 6 /* max ep number */ #define RTL_USB_MAX_TX_URBS_NUM 8 @@ -53,11 +52,11 @@ static inline void _rtl_install_trx_info(struct rtl_usb *rtlusb, u32 ep_num) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + info->rate_driver_data[0] = rtlusb; info->rate_driver_data[1] = (void *)(__kernel_size_t)ep_num; } - /* Add suspend/resume later */ enum rtl_usb_state { USB_STATE_STOP = 0, @@ -133,8 +132,6 @@ struct rtl_usb_priv { #define rtl_usbpriv(hw) (((struct rtl_usb_priv *)(rtl_priv(hw))->priv)) #define rtl_usbdev(usbpriv) (&((usbpriv)->dev)) - - int rtl_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, struct rtl_hal_cfg *rtl92cu_hal_cfg); diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 88f94662c072..e32e9ffa3192 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -2143,7 +2143,6 @@ struct rtl_stats { u32 macid_valid_entry[2]; }; - struct rt_link_detect { /* count for roaming */ u32 bcn_rx_inperiod; @@ -2843,7 +2842,6 @@ struct rtl_priv { #define rtl_efuse(rtlpriv) (&((rtlpriv)->efuse)) #define rtl_psc(rtlpriv) (&((rtlpriv)->psc)) - /* Bluetooth Co-existence Related */ enum bt_ant_num { @@ -2893,7 +2891,6 @@ enum bt_radio_shared { BT_RADIO_INDIVIDUAL = 1, }; - /**************************************** * mem access macro define start * Call endian free function when @@ -3229,6 +3226,7 @@ static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw, u8 *mac_addr) { struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + return ieee80211_find_sta(mac->vif, mac_addr); } -- cgit v1.2.3 From b16abaafea478a73c8007c0a7317fa1e45917d53 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 21 Feb 2019 13:31:12 -0600 Subject: rtlwifi: Fix all blank line irregularities in main code files The types of problems fixed are as follows: WARNING: Missing a blank line after declarations CHECK: Please use a blank line after function/struct/union/enum declarations CHECK: Please don't use multiple blank lines There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/base.c | 7 +++++-- drivers/net/wireless/realtek/rtlwifi/core.c | 8 ++++++++ drivers/net/wireless/realtek/rtlwifi/efuse.c | 8 +++++--- drivers/net/wireless/realtek/rtlwifi/ps.c | 1 + drivers/net/wireless/realtek/rtlwifi/rc.c | 2 ++ drivers/net/wireless/realtek/rtlwifi/regd.c | 1 - drivers/net/wireless/realtek/rtlwifi/usb.c | 3 +++ 7 files changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 672c0b73cb65..217d2a7a43c7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -430,6 +430,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); } else { u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; + get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); SET_IEEE80211_PERM_ADDR(hw, rtlmac1); } @@ -459,7 +460,6 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) (void *)rtl_fwevt_wq_callback); INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq, (void *)rtl_c2hcmd_wq_callback); - } void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq) @@ -618,6 +618,7 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw, u8 rate_flag = info->control.rates[0].flags; u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; u8 sgi_80 = 0, bw_80 = 0; + tcb_desc->use_shortgi = false; if (sta == NULL) @@ -1850,6 +1851,7 @@ int rtl_rx_agg_stop(struct ieee80211_hw *hw, return 0; } + int rtl_tx_agg_oper(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u16 tid) { @@ -2073,7 +2075,6 @@ void rtl_watchdog_wq_callback(void *data) * busytraffic we don't change channel */ if (mac->link_state >= MAC80211_LINKED) { - /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ for (idx = 0; idx <= 2; idx++) { rtlpriv->link_info.num_rx_in4period[idx] = @@ -2233,6 +2234,7 @@ void rtl_watch_dog_timer_callback(struct timer_list *t) mod_timer(&rtlpriv->works.watchdog_timer, jiffies + MSECS(RTL_WATCH_DOG_TIME)); } + void rtl_fwevt_wq_callback(void *data) { struct rtl_works *rtlworks = @@ -2384,6 +2386,7 @@ void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t) rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); } + /********************************************************* * * frame process functions diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 0913f02b7ff1..f73e690bbe8e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -188,6 +188,7 @@ static void rtl_op_tx(struct ieee80211_hw *hw, struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) @@ -346,12 +347,14 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&rtlpriv->locks.conf_mutex); } + static int rtl_op_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum nl80211_iftype new_type, bool p2p) { struct rtl_priv *rtlpriv = rtl_priv(hw); int ret; + rtl_op_remove_interface(hw, vif); vif->type = new_type; @@ -881,6 +884,7 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&mac->rx_conf)); } + static int rtl_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -933,6 +937,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw, { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_sta_info *sta_entry; + if (sta) { RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, "Remove sta addr is %pM\n", sta->addr); @@ -945,6 +950,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw, } return 0; } + static int _rtl_get_hal_qnum(u16 queue) { int qnum; @@ -1066,6 +1072,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, /*TODO: reference to enum ieee80211_bss_change */ if (changed & BSS_CHANGED_ASSOC) { u8 mstatus; + if (bss_conf->assoc) { struct ieee80211_sta *sta = NULL; u8 keep_alive = 10; @@ -1294,6 +1301,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, * set in sta_add, and will be NULL here */ if (vif->type == NL80211_IFTYPE_STATION) { struct rtl_sta_info *sta_entry; + sta_entry = (struct rtl_sta_info *)sta->drv_priv; sta_entry->wireless_mode = mac->mode; } diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c index de0437b3cb95..e68340dfd980 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.c +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c @@ -474,6 +474,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw) if (word_en != 0x0F) { u8 tmpdata[8]; + memcpy(tmpdata, &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base], 8); @@ -487,7 +488,6 @@ bool efuse_shadow_update(struct ieee80211_hw *hw) break; } } - } efuse_power_switch(hw, true, false); @@ -662,6 +662,7 @@ static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse) { struct rtl_priv *rtlpriv = rtl_priv(hw); + efuse_power_switch(hw, false, true); read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); efuse_power_switch(hw, false, false); @@ -812,6 +813,7 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, if (0x0F != (badworden & 0x0F)) { u8 reorg_offset = offset; u8 reorg_worden = badworden; + efuse_pg_packet_write(hw, reorg_offset, reorg_worden, originaldata); @@ -901,6 +903,7 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, if (0x0F != (badworden & 0x0F)) { u8 reorg_offset = tmp_pkt.offset; u8 reorg_worden = badworden; + efuse_pg_packet_write(hw, reorg_offset, reorg_worden, originaldata); @@ -957,7 +960,6 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, while (continual && (efuse_addr < (EFUSE_MAX_SIZE - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { - if (write_state == PG_STATE_HEADER) { dataempty = true; badworden = 0x0F; @@ -1114,7 +1116,6 @@ void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) u16 tmpv16; if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE && rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) { rtl_write_byte(rtlpriv, @@ -1219,6 +1220,7 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw) static u8 efuse_calculate_word_cnts(u8 word_en) { u8 word_cnts = 0; + if (!(word_en & BIT(0))) word_cnts++; if (!(word_en & BIT(1))) diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c index dca70d239760..70f04c2f5b17 100644 --- a/drivers/net/wireless/realtek/rtlwifi/ps.c +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c @@ -718,6 +718,7 @@ static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; u8 noa_num, index , i, noa_index = 0; bool find_p2p_ie = false , find_p2p_ps_ie = false; + pos = (u8 *)mgmt->u.beacon.variable; end = data + len; ie = NULL; diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c index 8fa76eab61d2..cf8e42a01015 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c @@ -236,6 +236,7 @@ static void rtl_tx_status(void *ppriv, !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { if (ieee80211_is_data_qos(fc)) { u8 tid = rtl_get_tid(skb); + if (_rtl_tx_aggr_check(rtlpriv, sta_entry, tid)) { sta_entry->tids[tid].agg.agg_state = @@ -293,6 +294,7 @@ static void rtl_rate_free_sta(void *rtlpriv, struct ieee80211_sta *sta, void *priv_sta) { struct rtl_rate_priv *rate_priv = priv_sta; + kfree(rate_priv); } diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index c7048830decd..6ccb5b93a595 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -41,7 +41,6 @@ static struct country_code_to_enum_rd all_countries[] = { NL80211_RRF_PASSIVE_SCAN | \ NL80211_RRF_NO_OFDM) - /* 5G chan 36 - chan 64*/ #define RTL819x_5GHZ_5150_5350 \ REG_RULE(5150-10, 5350+10, 80, 0, 30, 0) diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 525f72bad433..e24fda5e9087 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -267,6 +267,7 @@ static int _rtl_usb_init_tx(struct ieee80211_hw *hw) for (i = 0; i < __RTL_TXQ_NUM; i++) { u32 ep_num = rtlusb->ep_map.ep_mapping[i]; + if (!ep_num) { RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Invalid endpoint map setting!\n"); @@ -331,6 +332,7 @@ static int _rtl_usb_init(struct ieee80211_hw *hw) rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0; for (epidx = 0; epidx < epnums; epidx++) { struct usb_endpoint_descriptor *pep_desc; + pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc; if (usb_endpoint_dir_in(pep_desc)) @@ -753,6 +755,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw) return err; } + /** * * -- cgit v1.2.3 From 2973af748d4dd58807702d48e6726b025f684395 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 21 Feb 2019 13:31:13 -0600 Subject: rtlwifi: rtl8192ce: Fix missing blank lines The problems filed include the following: WARNING: Missing a blank line after declarations CHECK: Please don't use multiple blank lines There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 7 ++++++- drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c | 1 + drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c | 1 - drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c | 8 ++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index d8f496e2d68b..a52dd64d528d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c @@ -144,6 +144,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_BASIC_RATE:{ u16 rate_cfg = ((u16 *) val)[0]; u8 rate_index = 0; + rate_cfg &= 0x15f; rate_cfg |= 0x01; rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); @@ -197,6 +198,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_ACK_PREAMBLE:{ u8 reg_tmp; u8 short_preamble = (bool)*val; + reg_tmp = (mac->cur_40_prime_sc) << 5; if (short_preamble) reg_tmp |= 0x80; @@ -293,6 +295,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) } case HW_VAR_AC_PARAM:{ u8 e_aci = *(val); + rtl92c_dm_init_edca_turbo(hw); if (rtlpci->acm_method != EACMWAY2_SW) @@ -456,6 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; case HW_VAR_AID:{ u16 u2btmp; + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); u2btmp &= 0xC000; rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | @@ -661,6 +665,7 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); if (rtlpriv->btcoexist.bt_coexistence) { u32 value32; + value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); @@ -1245,6 +1250,7 @@ int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) { struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl92c_dm_init_edca_turbo(hw); switch (aci) { case AC1_BK: @@ -2279,7 +2285,6 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw) rtlpriv->btcoexist.reg_bt_sco = 0; } - void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c index 8d18210dd5c8..f6574f31fa3b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c @@ -443,6 +443,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { bool rtstatus; u32 initializecount = 0; + do { initializecount++; RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c index e258b0803699..58878db404ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c @@ -3,7 +3,6 @@ #include "table.h" - u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH] = { 0x024, 0x0011800f, 0x028, 0x00ffdb83, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index b08fb1bf6709..18a0ab59631a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -36,6 +36,7 @@ static u8 _rtl92c_query_rxpwrpercentage(s8 antpower) static u8 _rtl92c_evm_db_to_percentage(s8 value) { s8 ret_val; + ret_val = value; if (ret_val >= 0) @@ -109,6 +110,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, if (is_cck_rate) { u8 report, cck_highpwr; + cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; if (ppsc->rfpwr_state == ERFON) @@ -120,6 +122,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, if (!cck_highpwr) { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; report = report >> 6; switch (report) { @@ -138,6 +141,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, } } else { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; report = report >> 5; switch (report) { @@ -182,6 +186,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, /* (3) Get Signal Quality (EVM) */ if (packet_match_bssid) { u8 sq; + if (pstats->rx_pwdb_all > 40) sq = 100; else { @@ -318,6 +323,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; struct ieee80211_hdr *hdr; u32 phystatus = GET_RX_DESC_PHYST(pdesc); + stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * RX_DRV_INFO_SIZE_UNIT; @@ -497,6 +503,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); } @@ -733,6 +740,7 @@ bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw, void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) { struct rtl_priv *rtlpriv = rtl_priv(hw); + if (hw_queue == BEACON_QUEUE) { rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); } else { -- cgit v1.2.3 From 6d255202a272a4ec33165a045cc3a9b55573cf0b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 21 Feb 2019 13:31:14 -0600 Subject: rtlwifi: rtl8192cu: Fix problems with blank lines The following problems were found: WARNING: Missing a blank line after declarations CHECK: Please don't use multiple blank lines CHECK: Please use a blank line after function/struct/union/enum declarations There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | 9 ++++++++- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h | 4 ---- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c | 8 +++++++- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h | 3 --- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c | 7 +++++++ drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h | 2 -- 6 files changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index 52ee713d50f5..56cc3bc30860 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -747,6 +747,7 @@ static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw, u8 queue_sel) { struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + if (IS_NORMAL_CHIP(rtlhal->version)) _rtl92cu_init_chipn_queue_priority(hw, wmm_enable, out_ep_num, queue_sel); @@ -813,6 +814,7 @@ static int _rtl92cu_init_mac(struct ieee80211_hw *hw) u8 wmm_enable = false; /* TODO */ u8 out_ep_nums = rtlusb->out_ep_nums; u8 queue_sel = rtlusb->out_queue_sel; + err = _rtl92cu_init_power_on(hw); if (err) { @@ -1013,6 +1015,7 @@ d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine ***************************************/ u8 erfpath = 0, value8 = 0; + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); rtl_set_rfreg(hw, (enum radio_path)erfpath, 0x0, MASKBYTE0, 0x0); @@ -1204,6 +1207,7 @@ static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); u8 tmp1byte = 0; + if (IS_NORMAL_CHIP(rtlhal->version)) { tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, @@ -1353,6 +1357,7 @@ void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) if (check_bssid) { u8 tmp; + if (IS_NORMAL_CHIP(rtlhal->version)) { reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); tmp = BIT(4); @@ -1365,6 +1370,7 @@ void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp); } else { u8 tmp; + if (IS_NORMAL_CHIP(rtlhal->version)) { reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); tmp = BIT(4); @@ -1631,6 +1637,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) case HW_VAR_ACK_PREAMBLE:{ u8 reg_tmp; u8 short_preamble = (bool)*val; + reg_tmp = 0; if (short_preamble) reg_tmp |= 0x80; @@ -1881,6 +1888,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) break; case HW_VAR_KEEP_ALIVE:{ u8 array[2]; + array[0] = 0xff; array[1] = *((u8 *)val); rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2, @@ -1963,7 +1971,6 @@ static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || (!curtxbw_40mhz && curshortgi_20mhz))) { - ratr_value |= 0x10000000; tmp_ratr_value = (ratr_value >> 12); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h index 0ccc47e36652..5c48c3fd45e4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h @@ -14,14 +14,12 @@ #define TX_TOTAL_PAGE_NUMBER 0xF8 #define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1) - #define CHIP_B_PAGE_NUM_PUBQ 0xE7 /* For Test Chip Setting * (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ #define CHIP_A_PAGE_NUM_PUBQ 0x7E - /* For Chip A Setting */ #define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER 0xF5 #define WMM_CHIP_A_TX_PAGE_BOUNDARY \ @@ -31,8 +29,6 @@ #define WMM_CHIP_A_PAGE_NUM_HPQ 0x29 #define WMM_CHIP_A_PAGE_NUM_LPQ 0x29 - - /* Note: For Chip B Setting ,modify later */ #define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER 0xF5 #define WMM_CHIP_B_TX_PAGE_BOUNDARY \ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c index cc2ba74bff81..b3ce8000d52d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c @@ -24,7 +24,6 @@ #define RX_EVM rx_evm_percentage #define RX_SIGQ rx_mimo_sig_qual - void rtl92c_read_chip_version(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -143,6 +142,7 @@ bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) } while (++count); return status; } + /** * rtl92c_init_LLT_table - Init LLT table * @io: io callback @@ -189,6 +189,7 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary) } return rst; } + void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all) @@ -370,6 +371,7 @@ void rtl92c_set_qos(struct ieee80211_hw *hw, int aci) void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size) { struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size); } @@ -647,6 +649,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, pstats->RX_SIGQ[1] = -1; if (is_cck_rate) { u8 report, cck_highpwr; + cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; if (!in_powersavemode) cck_highpwr = rtlphy->cck_high_power; @@ -654,6 +657,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, cck_highpwr = false; if (!cck_highpwr) { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; report = report >> 6; switch (report) { @@ -672,6 +676,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, } } else { u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; report = report >> 5; switch (report) { @@ -694,6 +699,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, pstats->recvsignalpower = rx_pwr_all; if (packet_match_bssid) { u8 sq; + if (pstats->rx_pwdb_all > 40) sq = 100; else { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h index 62eb3c5adec1..dd76a05829d5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h @@ -18,7 +18,6 @@ void rtl92c_enable_interrupt(struct ieee80211_hw *hw); void rtl92c_disable_interrupt(struct ieee80211_hw *hw); void rtl92c_set_qos(struct ieee80211_hw *hw, int aci); - /*--------------------------------------------------------------- * Hardware init functions *---------------------------------------------------------------*/ @@ -130,6 +129,4 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, * Card disable functions *---------------------------------------------------------------*/ - - #endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index 4293d0640310..0020adc004a5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -108,6 +108,7 @@ static void threeoutepmapping(struct ieee80211_hw *hw, bool bwificfg, struct rtl_ep_map *ep_map) { struct rtl_priv *rtlpriv = rtl_priv(hw); + if (bwificfg) { /* for WMM */ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "USB 3EP Setting for WMM.....\n"); @@ -141,6 +142,7 @@ static void oneoutepmapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) ep_map->ep_mapping[RTL_TXQ_BCN] = 2; ep_map->ep_mapping[RTL_TXQ_HI] = 2; } + static int _out_ep_mapping(struct ieee80211_hw *hw) { int err = 0; @@ -174,11 +176,13 @@ err_out: return err; } + /* endpoint mapping */ int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) { struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); int error = 0; + if (likely(IS_NORMAL_CHIP(rtlhal->version))) error = configvernoutep(hw); else @@ -442,6 +446,7 @@ static void _rtl_fill_usb_tx_desc(u8 *txdesc) SET_TX_DESC_LAST_SEG(txdesc, 1); SET_TX_DESC_FIRST_SEG(txdesc, 1); } + /** * For HW recovery information */ @@ -531,11 +536,13 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, sta = ieee80211_find_sta(mac->vif, mac->bssid); if (sta) { u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density); } rcu_read_unlock(); if (info->control.hw_key) { struct ieee80211_key_conf *keyconf = info->control.hw_key; + switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h index 439ced0e18fa..ae2e8aa212de 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h @@ -198,7 +198,6 @@ struct rx_drv_info_92c { #define SET_TX_DESC_OWN(__txdesc, __value) \ SET_BITS_TO_LE_4BYTE(__txdesc, 31, 1, __value) - /* Dword 1 */ #define SET_TX_DESC_MACID(__txdesc, __value) \ SET_BITS_TO_LE_4BYTE(__txdesc + 4, 0, 5, __value) @@ -355,7 +354,6 @@ struct rx_drv_info_92c { #define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value) \ SET_BITS_TO_LE_4BYTE(__txdesc + 28, 28, 4, __value) - int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw); u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index); bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, -- cgit v1.2.3 From 52f886571263a99935826f33984724a3306b0d62 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 21 Feb 2019 13:31:15 -0600 Subject: rtlwifi: rtl8192com: Fix blank line problems The following types of blank line problems are reported: WARNING: Missing a blank line after declarations CHECK: Please don't use multiple blank lines There are no code changes. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c | 6 ++---- drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c | 5 ++--- drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c | 1 - drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c | 1 + 4 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c index 2f633118c717..f2908ee5f860 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c @@ -425,7 +425,6 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || dm_digtable->cursta_cstate == DIG_STA_CONNECT) { - if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); @@ -504,7 +503,6 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) rtl92c_dm_cck_packet_detection_thresh(hw); dm_digtable->presta_cstate = dm_digtable->cursta_cstate; - } static void rtl92c_dm_dig(struct ieee80211_hw *hw) @@ -607,6 +605,7 @@ static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); + rtlpriv->dm.current_turbo_edca = false; rtlpriv->dm.is_any_nonbepkts = false; rtlpriv->dm.is_cur_rdlstate = false; @@ -660,7 +659,6 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && (!rtlpriv->dm.disable_framebursting))) { - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; @@ -685,6 +683,7 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) } else { if (rtlpriv->dm.current_turbo_edca) { u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, &tmp); rtlpriv->dm.current_turbo_edca = false; @@ -1635,7 +1634,6 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte) { struct rtl_priv *rtlpriv = rtl_priv(hw); - /* Only enable HW BT coexist when BT in "Busy" state. */ if (rtlpriv->mac80211.vendor == PEER_CISCO && rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) { diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c index 6af72799e09c..18c76990a089 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c @@ -18,6 +18,7 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) { u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (enable) value32 |= MCUFWDL_EN; else @@ -25,8 +26,8 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) { u8 tmp; - if (enable) { + if (enable) { tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); @@ -37,7 +38,6 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); } else { - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); @@ -622,7 +622,6 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", u1rsvdpageloc, 3); - skb = dev_alloc_skb(totalpacketlen); skb_put_data(skb, &reserved_page_packet, totalpacketlen); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c index e8af1952d243..97ad21c3964f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c @@ -4,7 +4,6 @@ #include "../wifi.h" #include - MODULE_AUTHOR("lizhaoming "); MODULE_AUTHOR("Realtek WlanFAE "); MODULE_AUTHOR("Georgia "); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c index c6a3ed441c3f..0efd19aa4fe5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c @@ -747,6 +747,7 @@ static void _rtl92c_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { if (channel == 6 && rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { -- cgit v1.2.3 From 34e022d8b780a03902d82fb3997ba7c7b1f40c81 Mon Sep 17 00:00:00 2001 From: Wen Yang Date: Fri, 22 Feb 2019 15:15:40 +0800 Subject: mt76: fix a leaked reference by adding a missing of_node_put The call to of_find_node_by_phandle returns a node pointer with refcount incremented thus it must be explicitly decremented after the last usage. Detected by coccinelle with the following warnings: ./drivers/net/wireless/mediatek/mt76/eeprom.c:58:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function. ./drivers/net/wireless/mediatek/mt76/eeprom.c:61:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function. ./drivers/net/wireless/mediatek/mt76/eeprom.c:67:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function. ./drivers/net/wireless/mediatek/mt76/eeprom.c:70:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function. ./drivers/net/wireless/mediatek/mt76/eeprom.c:72:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 48, but without a corresponding object release within this function. Signed-off-by: Wen Yang Cc: Felix Fietkau Cc: Lorenzo Bianconi Cc: Kalle Valo Cc: "David S. Miller" Cc: Matthias Brugger Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mediatek@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Kalle Valo --- drivers/net/wireless/mediatek/mt76/eeprom.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 530e5593765c..a1529920d877 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -54,22 +54,30 @@ mt76_get_of_eeprom(struct mt76_dev *dev, int len) part = np->name; mtd = get_mtd_device_nm(part); - if (IS_ERR(mtd)) - return PTR_ERR(mtd); + if (IS_ERR(mtd)) { + ret = PTR_ERR(mtd); + goto out_put_node; + } - if (size <= sizeof(*list)) - return -EINVAL; + if (size <= sizeof(*list)) { + ret = -EINVAL; + goto out_put_node; + } offset = be32_to_cpup(list); ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data); put_mtd_device(mtd); if (ret) - return ret; + goto out_put_node; - if (retlen < len) - return -EINVAL; + if (retlen < len) { + ret = -EINVAL; + goto out_put_node; + } - return 0; +out_put_node: + of_node_put(np); + return ret; #else return -ENOENT; #endif -- cgit v1.2.3 From f321505656018a389fdf2dc261af4beda2cf9cfd Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 27 Feb 2019 02:23:21 +0000 Subject: rtlwifi: rtl8723be: Remove set but not used variable 'b_last_is_cur_rdlstate' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c: In function 'rtl8723be_dm_check_edca_turbo': drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c:998:7: warning: variable 'b_last_is_cur_rdlstate' set but not used [-Wunused-but-set-variable] It's never used and can be removed. Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c index ef355aa88117..b13fd3c0c832 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c @@ -995,12 +995,9 @@ static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw) u32 edca_be = 0x5ea42b; u32 iot_peer = 0; bool b_is_cur_rdlstate; - bool b_last_is_cur_rdlstate = false; bool b_bias_on_rx = false; bool b_edca_turbo_on = false; - b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate; - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; -- cgit v1.2.3 From 85c6ac33c87c44893ddc561dfd0a8bdc9ec68cd5 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 27 Feb 2019 02:23:34 +0000 Subject: rtlwifi: rtl8723ae: Remove set but not used variable 'bt_retry_cnt' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c: In function '_rtl8723e_dm_bt_coexist_2_ant': drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c:1408:5: warning: variable 'bt_retry_cnt' set but not used [-Wunused-but-set-variable] It's never used and can be removed. Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c index a6b31dae5691..680198280f8f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c @@ -1405,7 +1405,6 @@ static void rtl8723e_dm_bt_reset_action_profile_state(struct ieee80211_hw *hw) static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_retry_cnt; u8 bt_info_original; RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "[BTCoex] Get bt info by fw!!\n"); @@ -1417,7 +1416,6 @@ static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) "[BTCoex] c2h for bt_info not rcvd yet!!\n"); } - bt_retry_cnt = hal_coex_8723.bt_retry_cnt; bt_info_original = hal_coex_8723.c2h_bt_info_original; /* when bt inquiry or page scan, we have to set h2c 0x25 */ -- cgit v1.2.3 From 037e0c5df64980dfffdce1317790730ceda77945 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 27 Feb 2019 02:23:47 +0000 Subject: rtlwifi: rtl8192se: Remove set but not used variable 'seg_ptr' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c: In function '_rtl92s_firmware_downloadcode': drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c:139:17: warning: variable 'seg_ptr' set but not used [-Wunused-but-set-variable] It's not used after commit 59ae1d127ac0 ("networking: introduce and use skb_put_data()") Signed-off-by: YueHaibing Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c index faa307a0b148..541b7881735e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c @@ -136,7 +136,6 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, struct rtl_priv *rtlpriv = rtl_priv(hw); struct sk_buff *skb; struct rtl_tcb_desc *tcb_desc; - unsigned char *seg_ptr; u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; u16 frag_length, frag_offset = 0; u16 extra_descoffset = 0; @@ -166,9 +165,8 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, if (!skb) return false; skb_reserve(skb, extra_descoffset); - seg_ptr = skb_put_data(skb, - code_virtual_address + frag_offset, - (u32)(frag_length - extra_descoffset)); + skb_put_data(skb, code_virtual_address + frag_offset, + (u32)(frag_length - extra_descoffset)); tcb_desc = (struct rtl_tcb_desc *)(skb->cb); tcb_desc->queue_index = TXCMD_QUEUE; -- cgit v1.2.3 From 3a08ac3e79e892e23c936ffea582a63f3fec6c72 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Tue, 26 Feb 2019 14:57:55 +0530 Subject: ath10k: Fix the incorrect updation of NSS data in tx stats The NSS data is updated incorrectly in the tx stats as the array indexing starts from zero. Fix the incorrect updation of NSS data in tx_stats by taking into consideration the array index starting from zero. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Fixes: a904417fc876 ("ath10k: add extended per sta tx statistics support") Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 129fd15e9cc9..9415ff6d0e43 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2977,7 +2977,7 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, } STATS_OP_FMT(AMPDU).bw[0][bw] += pstats->succ_bytes + pstats->retry_bytes; - STATS_OP_FMT(AMPDU).nss[0][nss] += + STATS_OP_FMT(AMPDU).nss[0][nss - 1] += pstats->succ_bytes + pstats->retry_bytes; STATS_OP_FMT(AMPDU).gi[0][gi] += pstats->succ_bytes + pstats->retry_bytes; @@ -2985,7 +2985,7 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, pstats->succ_bytes + pstats->retry_bytes; STATS_OP_FMT(AMPDU).bw[1][bw] += pstats->succ_pkts + pstats->retry_pkts; - STATS_OP_FMT(AMPDU).nss[1][nss] += + STATS_OP_FMT(AMPDU).nss[1][nss - 1] += pstats->succ_pkts + pstats->retry_pkts; STATS_OP_FMT(AMPDU).gi[1][gi] += pstats->succ_pkts + pstats->retry_pkts; @@ -2997,27 +2997,27 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, } STATS_OP_FMT(SUCC).bw[0][bw] += pstats->succ_bytes; - STATS_OP_FMT(SUCC).nss[0][nss] += pstats->succ_bytes; + STATS_OP_FMT(SUCC).nss[0][nss - 1] += pstats->succ_bytes; STATS_OP_FMT(SUCC).gi[0][gi] += pstats->succ_bytes; STATS_OP_FMT(SUCC).bw[1][bw] += pstats->succ_pkts; - STATS_OP_FMT(SUCC).nss[1][nss] += pstats->succ_pkts; + STATS_OP_FMT(SUCC).nss[1][nss - 1] += pstats->succ_pkts; STATS_OP_FMT(SUCC).gi[1][gi] += pstats->succ_pkts; STATS_OP_FMT(FAIL).bw[0][bw] += pstats->failed_bytes; - STATS_OP_FMT(FAIL).nss[0][nss] += pstats->failed_bytes; + STATS_OP_FMT(FAIL).nss[0][nss - 1] += pstats->failed_bytes; STATS_OP_FMT(FAIL).gi[0][gi] += pstats->failed_bytes; STATS_OP_FMT(FAIL).bw[1][bw] += pstats->failed_pkts; - STATS_OP_FMT(FAIL).nss[1][nss] += pstats->failed_pkts; + STATS_OP_FMT(FAIL).nss[1][nss - 1] += pstats->failed_pkts; STATS_OP_FMT(FAIL).gi[1][gi] += pstats->failed_pkts; STATS_OP_FMT(RETRY).bw[0][bw] += pstats->retry_bytes; - STATS_OP_FMT(RETRY).nss[0][nss] += pstats->retry_bytes; + STATS_OP_FMT(RETRY).nss[0][nss - 1] += pstats->retry_bytes; STATS_OP_FMT(RETRY).gi[0][gi] += pstats->retry_bytes; STATS_OP_FMT(RETRY).bw[1][bw] += pstats->retry_pkts; - STATS_OP_FMT(RETRY).nss[1][nss] += pstats->retry_pkts; + STATS_OP_FMT(RETRY).nss[1][nss - 1] += pstats->retry_pkts; STATS_OP_FMT(RETRY).gi[1][gi] += pstats->retry_pkts; if (txrate->flags >= RATE_INFO_FLAGS_MCS) { -- cgit v1.2.3 From ef9051c72ab7bc664e8047c55ac74bdb1c7fa3ee Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Tue, 26 Feb 2019 14:57:56 +0530 Subject: ath10k: Fix the wrong updation of BW in tx_stats debugfs entry Currently, the bandwidth is updated wrongly in BW table in tx_stats debugfs per sta as there is difference in number of bandwidth type in mac80211 and driver stats table. This leads to bandwidth getting updated at wrong index in bandwidth table in tx_stats. Fix this index mismatch between mac80211 and driver stats table (BW table) by making the number of bandwidth type in driver compatible with mac80211. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Fixes: a904417fc876 ("ath10k: add extended per sta tx statistics support") Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debugfs_sta.c | 7 ++++--- drivers/net/wireless/ath/ath10k/wmi.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 8331d8b09987..c704ae371c4d 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -685,11 +685,12 @@ static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file, " %llu ", stats->ht[j][i]); len += scnprintf(buf + len, size - len, "\n"); len += scnprintf(buf + len, size - len, - " BW %s (20,40,80,160 MHz)\n", str[j]); + " BW %s (20,5,10,40,80,160 MHz)\n", str[j]); len += scnprintf(buf + len, size - len, - " %llu %llu %llu %llu\n", + " %llu %llu %llu %llu %llu %llu\n", stats->bw[j][0], stats->bw[j][1], - stats->bw[j][2], stats->bw[j][3]); + stats->bw[j][2], stats->bw[j][3], + stats->bw[j][4], stats->bw[j][5]); len += scnprintf(buf + len, size - len, " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]); len += scnprintf(buf + len, size - len, diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index a1a558b03de7..56da8292605b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -5045,7 +5045,7 @@ enum wmi_rate_preamble { #define ATH10K_FW_SKIPPED_RATE_CTRL(flags) (((flags) >> 6) & 0x1) #define ATH10K_VHT_MCS_NUM 10 -#define ATH10K_BW_NUM 4 +#define ATH10K_BW_NUM 6 #define ATH10K_NSS_NUM 4 #define ATH10K_LEGACY_NUM 12 #define ATH10K_GI_NUM 2 -- cgit v1.2.3 From 8e55fdaa8ea763fc09acef82e6263c8f9b2c9f72 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Tue, 26 Feb 2019 14:57:57 +0530 Subject: ath10k: Fix the wrong updation of SGI in tx_stats debugfs The SGI is updated wrongly in tx stats table in debugfs per sta entry. To know whether the packets/bytes are sent with SHORT GI, test whether the SGI bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT) is set or not in the txrate flags. Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Fixes: a904417fc876 ("ath10k: add extended per sta tx statistics support") Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 4 +++- drivers/net/wireless/ath/ath10k/wmi.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 9415ff6d0e43..1a9892703570 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2921,12 +2921,14 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, struct rate_info *txrate = &arsta->txrate; struct ath10k_htt_tx_stats *tx_stats; int idx, ht_idx, gi, mcs, bw, nss; + unsigned long flags; if (!arsta->tx_stats) return; tx_stats = arsta->tx_stats; - gi = (arsta->txrate.flags & RATE_INFO_FLAGS_SHORT_GI); + flags = txrate->flags; + gi = test_bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT, &flags); ht_idx = txrate->mcs + txrate->nss * 8; mcs = txrate->mcs; bw = txrate->bw; diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 56da8292605b..f6d3e76723d7 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -5051,6 +5051,7 @@ enum wmi_rate_preamble { #define ATH10K_GI_NUM 2 #define ATH10K_HT_MCS_NUM 32 #define ATH10K_RATE_TABLE_NUM 320 +#define ATH10K_RATE_INFO_FLAGS_SGI_BIT 2 /* Value to disable fixed rate setting */ #define WMI_FIXED_RATE_NONE (0xff) -- cgit v1.2.3 From d23c2cdaa01360ddc8ca01cd34b964e4621e6381 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Tue, 26 Feb 2019 14:57:58 +0530 Subject: ath10k: Fix the wrong calculation ht_idx and idx of rate table for tx_stats ht_idx (ht rate index) and idx (rate table index) are calculated based on mcs index. This mcs index used in the above calculation should be 0-9 for getting the correct ht_idx and idx. Currently the mcs index used for the above calculations is mcs index which can be 0-31 (in case of HT), leading to incorrect rate index and ht index values. Fix the issue by obtaining mcs value from the ratecode reported by firmware and use it for calculating ht_idx and idx (rate-table index). Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Fixes: e88975ca37d1 ("ath10k: dump tx stats in rate table format") Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 1a9892703570..a20ea270d519 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2929,11 +2929,11 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, tx_stats = arsta->tx_stats; flags = txrate->flags; gi = test_bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT, &flags); - ht_idx = txrate->mcs + txrate->nss * 8; - mcs = txrate->mcs; + mcs = ATH10K_HW_MCS_RATE(pstats->ratecode); bw = txrate->bw; nss = txrate->nss; - idx = mcs * 8 + 8 * 10 * nss; + ht_idx = mcs + (nss - 1) * 8; + idx = mcs * 8 + 8 * 10 * (nss - 1); idx += bw * 2 + gi; #define STATS_OP_FMT(name) tx_stats->stats[ATH10K_STATS_TYPE_##name] -- cgit v1.2.3 From f40a307eb92c45a4acf813efcda90b17d50d25c3 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Tue, 26 Feb 2019 15:23:16 +0530 Subject: ath10k: Fill rx duration for each peer in fw_stats for WCN3990 Currently, rx_duration for each peer is not getting populated in fw_stats debugfs entry for WCN3990. WCN3990 firmware sends rx duration for each peer as part of peer_extd_stats in WMI_UPDATE_STATS_EVENT. To enable peer_extd_stats, firmware expects host to send fw_stats_req_mask with flag WMI_TLV_PEER_STATS_EXTD set in WMI_REQUEST_STATS_CMD. Send fw_stats_req_mask with flag WMI_TLV_PEER_STATS_EXTD set in WMI_REQUEST_STATS_CMD and parse the peer_extd_stats in WMI_UPDATE_STATS_EVENT to populate the rx_duration of each peer in fw_stats debugfs entry. Currently the driver handles 32-bit rx_duration, but the rx_duration for WCN3990 can be upto 63 bit. The firmware sends rx_duration split into two 32-bit fields, with the upper 32-bits being valid only if its MSB is set. This change handles the 63-bit rx_duration obtained from WCN3990 and maintain the backward compatibility. To get the rx_duration of each connected peer : cat /sys/kernel/debug/ieee80211/phyX/ath10k/fw_stats Tested HW: WCN3990 Tested FW: WLAN.HL.3.1-00784-QCAHLSWMTPLZ-1 Signed-off-by: Surabhi Vishnoi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 4 ++-- drivers/net/wireless/ath/ath10k/core.h | 2 +- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 31 +++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 20 ++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.h | 7 +++++++ 6 files changed, 60 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index c2d2155580eb..835b8de92d55 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2317,8 +2317,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) else ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS; - ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV | - WMI_STAT_PEER; + ar->fw_stats_req_mask = WMI_TLV_STAT_PDEV | WMI_TLV_STAT_VDEV | + WMI_TLV_STAT_PEER | WMI_TLV_STAT_PEER_EXTD; ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM; ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC; break; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 27ec5557de88..e08a17b01e03 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -189,7 +189,7 @@ struct ath10k_fw_stats_peer { u32 peer_rssi; u32 peer_tx_rate; u32 peer_rx_rate; /* 10x only */ - u32 rx_duration; + u64 rx_duration; }; struct ath10k_fw_extd_stats_peer { diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 890887eb886a..582fb11f648a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -13,6 +13,7 @@ #include "wmi-tlv.h" #include "p2p.h" #include "testmode.h" +#include /***************/ /* TLV helpers */ @@ -1296,6 +1297,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, { const void **tb; const struct wmi_tlv_stats_ev *ev; + u32 num_peer_stats_extd; const void *data; u32 num_pdev_stats; u32 num_vdev_stats; @@ -1303,6 +1305,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, u32 num_bcnflt_stats; u32 num_chan_stats; size_t data_len; + u32 stats_id; int ret; int i; @@ -1327,11 +1330,13 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, num_peer_stats = __le32_to_cpu(ev->num_peer_stats); num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats); num_chan_stats = __le32_to_cpu(ev->num_chan_stats); + stats_id = __le32_to_cpu(ev->stats_id); + num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd); ath10k_dbg(ar, ATH10K_DBG_WMI, - "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n", + "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n", num_pdev_stats, num_vdev_stats, num_peer_stats, - num_bcnflt_stats, num_chan_stats); + num_bcnflt_stats, num_chan_stats, num_peer_stats_extd); for (i = 0; i < num_pdev_stats; i++) { const struct wmi_pdev_stats *src; @@ -1396,6 +1401,28 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, ath10k_wmi_pull_peer_stats(&src->old, dst); dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); + + if (stats_id & WMI_TLV_STAT_PEER_EXTD) { + const struct wmi_tlv_peer_stats_extd *extd; + unsigned long rx_duration_high; + + extd = data + sizeof(*src) * (num_peer_stats - i - 1) + + sizeof(*extd) * i; + + dst->rx_duration = __le32_to_cpu(extd->rx_duration); + rx_duration_high = __le32_to_cpu + (extd->rx_duration_high); + + if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT, + &rx_duration_high)) { + rx_duration_high = + FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK, + rx_duration_high); + dst->rx_duration |= (u64)rx_duration_high << + WMI_TLV_PEER_RX_DURATION_SHIFT; + } + } + list_add_tail(&dst->list, &stats->peers); } diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 52e0e73ac5f9..65e6aa520b06 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1889,6 +1889,22 @@ struct wmi_tlv_req_stats_cmd { struct wmi_mac_addr peer_macaddr; } __packed; +#define WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT 31 +#define WMI_TLV_PEER_RX_DURATION_HIGH_MASK GENMASK(30, 0) +#define WMI_TLV_PEER_RX_DURATION_SHIFT 32 + +struct wmi_tlv_peer_stats_extd { + struct wmi_mac_addr peer_macaddr; + __le32 rx_duration; + __le32 peer_tx_bytes; + __le32 peer_rx_bytes; + __le32 last_tx_rate_code; + __le32 last_tx_power; + __le32 rx_mc_bc_cnt; + __le32 rx_duration_high; + __le32 reserved[2]; +} __packed; + struct wmi_tlv_vdev_stats { __le32 vdev_id; __le32 beacon_snr; @@ -1982,6 +1998,10 @@ struct wmi_tlv_stats_ev { __le32 num_peer_stats; __le32 num_bcnflt_stats; __le32 num_chan_stats; + __le32 num_mib_stats; + __le32 pdev_id; + __le32 num_bcn_stats; + __le32 num_peer_stats_extd; } __packed; struct wmi_tlv_p2p_noa_ev { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 52f1752e2065..98a90e49d666 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -8322,7 +8322,7 @@ ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer, "Peer TX rate", peer->peer_tx_rate); len += scnprintf(buf + len, buf_len - len, "%30s %u\n", "Peer RX rate", peer->peer_rx_rate); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + len += scnprintf(buf + len, buf_len - len, "%30s %llu\n", "Peer RX duration", peer->rx_duration); len += scnprintf(buf + len, buf_len - len, "\n"); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index f6d3e76723d7..e1c40bb69932 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4534,6 +4534,13 @@ enum wmi_10_4_stats_id { WMI_10_4_STAT_VDEV_EXTD = BIT(4), }; +enum wmi_tlv_stats_id { + WMI_TLV_STAT_PDEV = BIT(0), + WMI_TLV_STAT_VDEV = BIT(1), + WMI_TLV_STAT_PEER = BIT(2), + WMI_TLV_STAT_PEER_EXTD = BIT(10), +}; + struct wlan_inst_rssi_args { __le16 cfg_retry_count; __le16 retry_count; -- cgit v1.2.3 From 387f3794b8cfbdfe6e627978ae4aec92b91b5fb8 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Fri, 22 Feb 2019 16:20:59 +0200 Subject: wil6210: remove rtap_include_phy_info module param Due to a HW issue in PHY info collection rtap_include_phy_info is not in use, hence can be removed. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/txrx.c | 88 ++++++--------------------------- drivers/net/wireless/ath/wil6210/txrx.h | 7 +-- drivers/net/wireless/ath/wil6210/wmi.c | 4 +- 3 files changed, 18 insertions(+), 81 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 3e1c831ab2fb..4d286fbaa7b7 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -30,11 +30,6 @@ #include "trace.h" #include "txrx_edma.h" -static bool rtap_include_phy_info; -module_param(rtap_include_phy_info, bool, 0444); -MODULE_PARM_DESC(rtap_include_phy_info, - " Include PHY info in the radiotap header, default - no"); - bool rx_align_2; module_param(rx_align_2, bool, 0444); MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no"); @@ -332,87 +327,34 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, u8 mcs_flags; u8 mcs_index; } __packed; - struct wil6210_rtap_vendor { - struct wil6210_rtap rtap; - /* vendor */ - u8 vendor_oui[3] __aligned(2); - u8 vendor_ns; - __le16 vendor_skip; - u8 vendor_data[0]; - } __packed; struct vring_rx_desc *d = wil_skb_rxdesc(skb); - struct wil6210_rtap_vendor *rtap_vendor; + struct wil6210_rtap *rtap; int rtap_len = sizeof(struct wil6210_rtap); - int phy_length = 0; /* phy info header size, bytes */ - static char phy_data[128]; struct ieee80211_channel *ch = wil->monitor_chandef.chan; - if (rtap_include_phy_info) { - rtap_len = sizeof(*rtap_vendor) + sizeof(*d); - /* calculate additional length */ - if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { - /** - * PHY info starts from 8-byte boundary - * there are 8-byte lines, last line may be partially - * written (HW bug), thus FW configures for last line - * to be excessive. Driver skips this last line. - */ - int len = min_t(int, 8 + sizeof(phy_data), - wil_rxdesc_phy_length(d)); - - if (len > 8) { - void *p = skb_tail_pointer(skb); - void *pa = PTR_ALIGN(p, 8); - - if (skb_tailroom(skb) >= len + (pa - p)) { - phy_length = len - 8; - memcpy(phy_data, pa, phy_length); - } - } - } - rtap_len += phy_length; - } - if (skb_headroom(skb) < rtap_len && pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { wil_err(wil, "Unable to expand headroom to %d\n", rtap_len); return; } - rtap_vendor = skb_push(skb, rtap_len); - memset(rtap_vendor, 0, rtap_len); + rtap = skb_push(skb, rtap_len); + memset(rtap, 0, rtap_len); - rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; - rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); - rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( - (1 << IEEE80211_RADIOTAP_FLAGS) | + rtap->rthdr.it_version = PKTHDR_RADIOTAP_VERSION; + rtap->rthdr.it_len = cpu_to_le16(rtap_len); + rtap->rthdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_MCS)); if (d->dma.status & RX_DMA_STATUS_ERROR) - rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; - - rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); - rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); - - rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; - rtap_vendor->rtap.mcs_flags = 0; - rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); - - if (rtap_include_phy_info) { - rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << - IEEE80211_RADIOTAP_VENDOR_NAMESPACE); - /* OUI for Wilocity 04:ce:14 */ - rtap_vendor->vendor_oui[0] = 0x04; - rtap_vendor->vendor_oui[1] = 0xce; - rtap_vendor->vendor_oui[2] = 0x14; - rtap_vendor->vendor_ns = 1; - /* Rx descriptor + PHY data */ - rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + - phy_length); - memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); - memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, - phy_length); - } + rtap->flags |= IEEE80211_RADIOTAP_F_BADFCS; + + rtap->chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); + rtap->chnl_flags = cpu_to_le16(0); + + rtap->mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; + rtap->mcs_flags = 0; + rtap->mcs_index = wil_rxdesc_mcs(d); } static bool wil_is_rx_idle(struct wil6210_priv *wil) diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 9d83be481839..bc81444b7106 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -530,11 +530,6 @@ static inline int wil_rxdesc_mcast(struct vring_rx_desc *d) return WIL_GET_BITS(d->mac.d1, 13, 14); } -static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d) -{ - return WIL_GET_BITS(d->dma.d0, 16, 29); -} - static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) { return (void *)skb->cb; diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 345f05969190..b1ba519b0ca9 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -2516,7 +2516,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring) if (ch) cmd.sniffer_cfg.channel = ch->hw_value - 1; cmd.sniffer_cfg.phy_info_mode = - cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); + cpu_to_le32(WMI_SNIFFER_PHY_INFO_DISABLED); cmd.sniffer_cfg.phy_support = cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS); -- cgit v1.2.3 From 0439a5e035f7180f7ed68ce2face1b7c77be0c6a Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Fri, 22 Feb 2019 16:21:00 +0200 Subject: wil6210: add option to drop Tx packets when Tx ring is full In AP mode with multiple clients, driver stops net queue (netif_tx_stop_queue) upon first ring (serving specific client) becoming full. This can have negative effect on transmission to other clients which may still have room in their corresponding rings. Implement new policy in which stop/wake net queue are not used. In case there is no room in the ring for a transmitted packet, drop the packet. New policy can be helpful to debug performance issues, to guarantee maximum utilization of net queues. New policy is disabled by default and can be enabled by debugfs: echo 1 > drop_if_ring_full Signed-off-by: Dedy Lansky Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/debugfs.c | 3 ++- drivers/net/wireless/ath/wil6210/txrx.c | 9 +++++++++ drivers/net/wireless/ath/wil6210/wil6210.h | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 835c902b84c1..acbf2f0c440e 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -2386,6 +2386,7 @@ static const struct dbg_off dbg_statics[] = { {"led_polarity", 0644, (ulong)&led_polarity, doff_u8}, {"status_index", 0644, (ulong)&dbg_status_msg_index, doff_u32}, {"sring_index", 0644, (ulong)&dbg_sring_index, doff_u32}, + {"drop_if_ring_full", 0644, (ulong)&drop_if_ring_full, doff_u8}, {}, }; diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 4d286fbaa7b7..de259dc7404b 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -38,6 +38,9 @@ bool rx_large_buf; module_param(rx_large_buf, bool, 0444); MODULE_PARM_DESC(rx_large_buf, " allocate 8KB RX buffers, default - no"); +/* Drop Tx packets in case Tx ring is full */ +bool drop_if_ring_full; + static inline uint wil_rx_snaplen(void) { return rx_align_2 ? 6 : 0; @@ -1974,6 +1977,10 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d", check_stop, vif->mid, vif->net_queue_stopped); + if (ring && drop_if_ring_full) + /* no need to stop/wake net queues */ + return; + if (check_stop == vif->net_queue_stopped) /* net queues already in desired state */ return; @@ -2099,6 +2106,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) dev_kfree_skb_any(skb); return NETDEV_TX_OK; case -ENOMEM: + if (drop_if_ring_full) + goto drop; return NETDEV_TX_BUSY; default: break; /* goto drop; */ diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 0f3be3ffc6a2..ba833ac925c3 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -38,6 +38,7 @@ extern bool rx_large_buf; extern bool debug_fw; extern bool disable_ap_sme; extern bool ftm_mode; +extern bool drop_if_ring_full; struct wil6210_priv; struct wil6210_vif; -- cgit v1.2.3 From bf0353a67491c220189ec2ce598d0f54af0e9c17 Mon Sep 17 00:00:00 2001 From: Ahmad Masri Date: Fri, 22 Feb 2019 16:21:01 +0200 Subject: wil6210: support up to 20 stations in AP mode New FW added support for upto 20 clients in AP mode. Change the driver to support this as well. FW reports it's max supported associations in WMI_READY_EVENT. Some WMI commands/events use cidxtid field which is limited to 16 cids. Use new cid/tid fields instead. For Rx packets cid from rx descriptor is limited to 3 bits (0..7), to find the real cid, compare transmitter address with the stored stations mac address in the driver sta array. EDMA FW still supports 8 stations. Extending the support to 20 stations will come later. Signed-off-by: Ahmad Masri Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 6 +- drivers/net/wireless/ath/wil6210/debugfs.c | 20 ++-- drivers/net/wireless/ath/wil6210/main.c | 10 +- drivers/net/wireless/ath/wil6210/rx_reorder.c | 10 +- drivers/net/wireless/ath/wil6210/trace.h | 3 +- drivers/net/wireless/ath/wil6210/txrx.c | 127 +++++++++++++++++++++----- drivers/net/wireless/ath/wil6210/txrx.h | 26 ++++++ drivers/net/wireless/ath/wil6210/txrx_edma.c | 8 +- drivers/net/wireless/ath/wil6210/wil6210.h | 12 ++- drivers/net/wireless/ath/wil6210/wmi.c | 79 ++++++++++++---- 10 files changed, 226 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 9b2f9f543952..9a9d55b36dc3 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -395,7 +395,7 @@ static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx) { int i; - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + for (i = 0; i < max_assoc_sta; i++) { if (wil->sta[i].status == wil_sta_unused) continue; if (wil->sta[i].mid != mid) @@ -3007,7 +3007,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX, sector_type, WIL_CID_ALL); if (rc == -EINVAL) { - for (i = 0; i < WIL6210_MAX_CID; i++) { + for (i = 0; i < max_assoc_sta; i++) { if (wil->sta[i].mid != vif->mid) continue; rc = wil_rf_sector_wmi_set_selected( diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index acbf2f0c440e..7ad4e5328439 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -162,7 +162,7 @@ static int ring_show(struct seq_file *s, void *data) snprintf(name, sizeof(name), "tx_%2d", i); - if (cid < WIL6210_MAX_CID) + if (cid < max_assoc_sta) seq_printf(s, "\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n", wil->sta[cid].addr, cid, tid, @@ -792,14 +792,14 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf, "BACK: del_rx require at least 2 params\n"); return -EINVAL; } - if (p1 < 0 || p1 >= WIL6210_MAX_CID) { + if (p1 < 0 || p1 >= max_assoc_sta) { wil_err(wil, "BACK: invalid CID %d\n", p1); return -EINVAL; } if (rc < 4) p3 = WLAN_REASON_QSTA_LEAVE_QBSS; sta = &wil->sta[p1]; - wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3); + wmi_delba_rx(wil, sta->mid, p1, p2, p3); } else { wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); return -EINVAL; @@ -1243,7 +1243,7 @@ static int bf_show(struct seq_file *s, void *data) memset(&reply, 0, sizeof(reply)); - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + for (i = 0; i < max_assoc_sta; i++) { u32 status; cmd.cid = i; @@ -1340,7 +1340,7 @@ static int link_show(struct seq_file *s, void *data) if (!sinfo) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + for (i = 0; i < max_assoc_sta; i++) { struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; struct wil6210_vif *vif; @@ -1542,7 +1542,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) struct wil6210_priv *wil = s->private; int i, tid, mcs; - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + for (i = 0; i < max_assoc_sta; i++) { struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; u8 aid = 0; @@ -1651,7 +1651,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) struct wil6210_priv *wil = s->private; int i, bin; - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + for (i = 0; i < max_assoc_sta; i++) { struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; u8 aid = 0; @@ -1740,7 +1740,7 @@ static ssize_t wil_tx_latency_write(struct file *file, const char __user *buf, size_t sz = sizeof(u64) * WIL_NUM_LATENCY_BINS; wil->tx_latency_res = val; - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + for (i = 0; i < max_assoc_sta; i++) { struct wil_sta_info *sta = &wil->sta[i]; kfree(sta->tx_latency_bins); @@ -1825,7 +1825,7 @@ static void wil_link_stats_debugfs_show_vif(struct wil6210_vif *vif, } seq_printf(s, "TSF %lld\n", vif->fw_stats_tsf); - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + for (i = 0; i < max_assoc_sta; i++) { if (wil->sta[i].status == wil_sta_unused) continue; if (wil->sta[i].mid != vif->mid) @@ -2440,7 +2440,7 @@ void wil6210_debugfs_remove(struct wil6210_priv *wil) wil->debug = NULL; kfree(wil->dbg_data.data_arr); - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) + for (i = 0; i < max_assoc_sta; i++) kfree(wil->sta[i].tx_latency_bins); /* free pmc memory without sending command to fw, as it will diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 5b7de00affe2..10de16ab7d69 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -219,7 +219,7 @@ static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid) { int i; - for (i = 0; i < WIL6210_MAX_CID; i++) { + for (i = 0; i < max_assoc_sta; i++) { if (wil->sta[i].mid == mid && wil->sta[i].status == wil_sta_connected) return true; @@ -322,7 +322,7 @@ static void _wil6210_disconnect_complete(struct wil6210_vif *vif, wil_disconnect_cid_complete(vif, cid, reason_code); } else { /* all */ wil_dbg_misc(wil, "Disconnect complete all\n"); - for (cid = 0; cid < WIL6210_MAX_CID; cid++) + for (cid = 0; cid < max_assoc_sta; cid++) wil_disconnect_cid_complete(vif, cid, reason_code); } @@ -434,7 +434,7 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, wil_disconnect_cid(vif, cid, reason_code); } else { /* all */ wil_dbg_misc(wil, "Disconnect all\n"); - for (cid = 0; cid < WIL6210_MAX_CID; cid++) + for (cid = 0; cid < max_assoc_sta; cid++) wil_disconnect_cid(vif, cid, reason_code); } @@ -1895,7 +1895,7 @@ int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac) int i; int rc = -ENOENT; - for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { + for (i = 0; i < max_assoc_sta; i++) { if (wil->sta[i].mid == mid && wil->sta[i].status != wil_sta_unused && ether_addr_equal(wil->sta[i].addr, mac)) { diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 983bd001b53b..32b14fc33a59 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -307,8 +307,8 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize) } /* Block Ack - Rx side (recipient) */ -int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, - u8 cidxtid, u8 dialog_token, __le16 ba_param_set, +int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, + u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl) __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) { @@ -316,7 +316,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) u16 agg_timeout = le16_to_cpu(ba_timeout); u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl); struct wil_sta_info *sta; - u8 cid, tid; u16 agg_wsize = 0; /* bit 0: A-MSDU supported * bit 1: policy (should be 0 for us) @@ -335,10 +334,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) int rc = 0; might_sleep(); - parse_cidxtid(cidxtid, &cid, &tid); /* sanity checks */ - if (cid >= WIL6210_MAX_CID) { + if (cid >= max_assoc_sta) { wil_err(wil, "BACK: invalid CID %d\n", cid); rc = -EINVAL; goto out; diff --git a/drivers/net/wireless/ath/wil6210/trace.h b/drivers/net/wireless/ath/wil6210/trace.h index 853abc3a73e4..36ebfcf9ef30 100644 --- a/drivers/net/wireless/ath/wil6210/trace.h +++ b/drivers/net/wireless/ath/wil6210/trace.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2013-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -181,7 +182,7 @@ TRACE_EVENT(wil6210_rx, __entry->seq = wil_rxdesc_seq(d); __entry->mcs = wil_rxdesc_mcs(d); ), - TP_printk("index %d len %d mid %d cid %d tid %d mcs %d seq 0x%03x" + TP_printk("index %d len %d mid %d cid (%%8) %d tid %d mcs %d seq 0x%03x" " type 0x%1x subtype 0x%1x", __entry->index, __entry->len, __entry->mid, __entry->cid, __entry->tid, __entry->mcs, __entry->seq, __entry->type, __entry->subtype) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index de259dc7404b..5aa14276303c 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -372,6 +372,78 @@ static bool wil_is_rx_idle(struct wil6210_priv *wil) return true; } +static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, struct sk_buff *skb) +{ + struct vring_rx_desc *d = wil_skb_rxdesc(skb); + int mid = wil_rxdesc_mid(d); + struct wil6210_vif *vif = wil->vifs[mid]; + /* cid from DMA descriptor is limited to 3 bits. + * In case of cid>=8, the value would be cid modulo 8 and we need to + * find real cid by locating the transmitter (ta) inside sta array + */ + int cid = wil_rxdesc_cid(d); + unsigned int snaplen = wil_rx_snaplen(); + struct ethhdr *eth; + struct ieee80211_hdr_3addr *hdr; + int i; + unsigned char *ta; + u8 ftype; + + /* in monitor mode there are no connections */ + if (vif->wdev.iftype == NL80211_IFTYPE_MONITOR) + return cid; + + ftype = wil_rxdesc_ftype(d) << 2; + if (likely(ftype == IEEE80211_FTYPE_DATA)) { + if (unlikely(skb->len < ETH_HLEN + snaplen)) { + wil_err_ratelimited(wil, + "Short data frame, len = %d\n", + skb->len); + return -ENOENT; + } + eth = (void *)skb->data; + ta = eth->h_source; + } else { + if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { + wil_err_ratelimited(wil, "Short frame, len = %d\n", + skb->len); + return -ENOENT; + } + hdr = (void *)skb->data; + ta = hdr->addr2; + } + + if (max_assoc_sta <= WIL6210_RX_DESC_MAX_CID) + return cid; + + /* assuming no concurrency between AP interfaces and STA interfaces. + * multista is used only in P2P_GO or AP mode. In other modes return + * cid from the rx descriptor + */ + if (vif->wdev.iftype != NL80211_IFTYPE_P2P_GO && + vif->wdev.iftype != NL80211_IFTYPE_AP) + return cid; + + /* For Rx packets cid from rx descriptor is limited to 3 bits (0..7), + * to find the real cid, compare transmitter address with the stored + * stations mac address in the driver sta array + */ + for (i = cid; i < max_assoc_sta; i += WIL6210_RX_DESC_MAX_CID) { + if (wil->sta[i].status != wil_sta_unused && + ether_addr_equal(wil->sta[i].addr, ta)) { + cid = i; + break; + } + } + if (i >= max_assoc_sta) { + wil_err_ratelimited(wil, "Could not find cid for frame with transmit addr = %pM, iftype = %d, frametype = %d, len = %d\n", + ta, vif->wdev.iftype, ftype, skb->len); + cid = -ENOENT; + } + + return cid; +} + /** * reap 1 frame from @swhead * @@ -397,7 +469,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, int i; struct wil_net_stats *stats; - BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); + BUILD_BUG_ON(sizeof(struct skb_rx_info) > sizeof(skb->cb)); again: if (unlikely(wil_ring_is_empty(vring))) @@ -429,7 +501,6 @@ again: wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); - cid = wil_rxdesc_cid(d); mid = wil_rxdesc_mid(d); vif = wil->vifs[mid]; @@ -440,11 +511,9 @@ again: goto again; } ndev = vif_to_ndev(vif); - stats = &wil->sta[cid].stats; - if (unlikely(dmalen > sz)) { - wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); - stats->rx_large_frame++; + wil_err_ratelimited(wil, "Rx size too large: %d bytes!\n", + dmalen); kfree_skb(skb); goto again; } @@ -455,6 +524,14 @@ again: wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb_headlen(skb), false); + cid = wil_rx_get_cid_by_skb(wil, skb); + if (cid == -ENOENT) { + kfree_skb(skb); + goto again; + } + wil_skb_set_cid(skb, (u8)cid); + stats = &wil->sta[cid].stats; + stats->last_mcs_rx = wil_rxdesc_mcs(d); if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) stats->rx_per_mcs[stats->last_mcs_rx]++; @@ -501,13 +578,6 @@ again: goto again; } - if (unlikely(skb->len < ETH_HLEN + snaplen)) { - wil_err(wil, "Short frame, len = %d\n", skb->len); - stats->rx_short_frame++; - kfree_skb(skb); - goto again; - } - /* L4 IDENT is on when HW calculated checksum, check status * and in case of error drop the packet * higher stack layers will handle retransmission (if required) @@ -604,7 +674,7 @@ int reverse_memcmp(const void *cs, const void *ct, size_t count) static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb) { struct vring_rx_desc *d = wil_skb_rxdesc(skb); - int cid = wil_rxdesc_cid(d); + int cid = wil_skb_get_cid(skb); int tid = wil_rxdesc_tid(d); int key_id = wil_rxdesc_key_id(d); int mc = wil_rxdesc_mcast(d); @@ -652,7 +722,7 @@ static void wil_get_netif_rx_params(struct sk_buff *skb, int *cid, { struct vring_rx_desc *d = wil_skb_rxdesc(skb); - *cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */ + *cid = wil_skb_get_cid(skb); *security = wil_rxdesc_security(d); } @@ -916,7 +986,6 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, .ring_size = cpu_to_le16(size), }, .ringid = id, - .cidxtid = mk_cidxtid(cid, tid), .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, .mac_ctrl = 0, .to_resolution = 0, @@ -936,6 +1005,14 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, struct wil_ring *vring = &wil->ring_tx[id]; struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; + if (cid >= WIL6210_RX_DESC_MAX_CID) { + cmd.vring_cfg.cidxtid = CIDXTID_EXTENDED_CID_TID; + cmd.vring_cfg.cid = cid; + cmd.vring_cfg.tid = tid; + } else { + cmd.vring_cfg.cidxtid = mk_cidxtid(cid, tid); + } + wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n", cmd.vring_cfg.tx_sw_ring.max_mpdu_size); lockdep_assert_held(&wil->mutex); @@ -988,7 +1065,7 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, txdata->enabled = 0; spin_unlock_bh(&txdata->lock); wil_vring_free(wil, vring); - wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; + wil->ring2cid_tid[id][0] = max_assoc_sta; wil->ring2cid_tid[id][1] = 0; out: @@ -1073,7 +1150,7 @@ fail: txdata->dot1x_open = false; txdata->enabled = 0; spin_unlock_bh(&txdata->lock); - wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID; + wil->ring2cid_tid[ring_id][0] = max_assoc_sta; wil->ring2cid_tid[ring_id][1] = 0; return rc; } @@ -1120,7 +1197,7 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) if (rc) goto out; - wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; /* CID */ + wil->ring2cid_tid[id][0] = max_assoc_sta; /* CID */ wil->ring2cid_tid[id][1] = 0; /* TID */ cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); @@ -1167,7 +1244,7 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil, int cid = wil_find_cid(wil, vif->mid, eth->h_dest); int min_ring_id = wil_get_min_tx_ring_id(wil); - if (cid < 0) + if (cid < 0 || cid >= max_assoc_sta) return NULL; /* TODO: fix for multiple TID */ @@ -1219,7 +1296,7 @@ static struct wil_ring *wil_find_tx_ring_sta(struct wil6210_priv *wil, continue; cid = wil->ring2cid_tid[i][0]; - if (cid >= WIL6210_MAX_CID) /* skip BCAST */ + if (cid >= max_assoc_sta) /* skip BCAST */ continue; if (!wil->ring_tx_data[i].dot1x_open && @@ -1298,7 +1375,7 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, continue; cid = wil->ring2cid_tid[i][0]; - if (cid >= WIL6210_MAX_CID) /* skip BCAST */ + if (cid >= max_assoc_sta) /* skip BCAST */ continue; if (!wil->ring_tx_data[i].dot1x_open && skb->protocol != cpu_to_be16(ETH_P_PAE)) @@ -1326,7 +1403,7 @@ found: if (!v2->va || txdata2->mid != vif->mid) continue; cid = wil->ring2cid_tid[i][0]; - if (cid >= WIL6210_MAX_CID) /* skip BCAST */ + if (cid >= max_assoc_sta) /* skip BCAST */ continue; if (!wil->ring_tx_data[i].dot1x_open && skb->protocol != cpu_to_be16(ETH_P_PAE)) @@ -2179,7 +2256,7 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid) used_before_complete = wil_ring_used_tx(vring); - if (cid < WIL6210_MAX_CID) + if (cid < max_assoc_sta) stats = &wil->sta[cid].stats; while (!wil_ring_is_empty(vring)) { @@ -2288,7 +2365,7 @@ static void wil_get_reorder_params(struct wil6210_priv *wil, struct vring_rx_desc *d = wil_skb_rxdesc(skb); *tid = wil_rxdesc_tid(d); - *cid = wil_rxdesc_cid(d); + *cid = wil_skb_get_cid(skb); *mid = wil_rxdesc_mid(d); *seq = wil_rxdesc_seq(d); *mcast = wil_rxdesc_mcast(d); diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index bc81444b7106..1aec04d59640 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -458,6 +458,18 @@ union wil_ring_desc { union wil_rx_desc rx; } __packed; +struct packet_rx_info { + u8 cid; +}; + +/* this struct will be stored in the skb cb buffer + * max length of the struct is limited to 48 bytes + */ +struct skb_rx_info { + struct vring_rx_desc rx_desc; + struct packet_rx_info rx_info; +}; + static inline int wil_rxdesc_tid(struct vring_rx_desc *d) { return WIL_GET_BITS(d->mac.d0, 0, 3); @@ -605,6 +617,20 @@ static inline bool wil_val_in_range(int val, int min, int max) return val >= min && val < max; } +static inline u8 wil_skb_get_cid(struct sk_buff *skb) +{ + struct skb_rx_info *skb_rx_info = (void *)skb->cb; + + return skb_rx_info->rx_info.cid; +} + +static inline void wil_skb_set_cid(struct sk_buff *skb, u8 cid) +{ + struct skb_rx_info *skb_rx_info = (void *)skb->cb; + + skb_rx_info->rx_info.cid = cid; +} + void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif, diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 3380aaef456c..c09cd692f910 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -727,7 +727,7 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id, txdata->enabled = 0; spin_unlock_bh(&txdata->lock); wil_ring_free_edma(wil, ring); - wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID; + wil->ring2cid_tid[ring_id][0] = max_assoc_sta; wil->ring2cid_tid[ring_id][1] = 0; out: @@ -932,7 +932,7 @@ again: eop = wil_rx_status_get_eop(msg); cid = wil_rx_status_get_cid(msg); - if (unlikely(!wil_val_in_range(cid, 0, WIL6210_MAX_CID))) { + if (unlikely(!wil_val_in_range(cid, 0, max_assoc_sta))) { wil_err(wil, "Corrupt cid=%d, sring->swhead=%d\n", cid, sring->swhead); rxdata->skipping = true; @@ -1187,7 +1187,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil, ndev = vif_to_ndev(vif); cid = wil->ring2cid_tid[ring_id][0]; - if (cid < WIL6210_MAX_CID) + if (cid < max_assoc_sta) stats = &wil->sta[cid].stats; wil_dbg_txrx(wil, diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index ba833ac925c3..85dca1b05283 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -39,6 +39,7 @@ extern bool debug_fw; extern bool disable_ap_sme; extern bool ftm_mode; extern bool drop_if_ring_full; +extern uint max_assoc_sta; struct wil6210_priv; struct wil6210_vif; @@ -90,7 +91,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) #define WIL_RING_SIZE_ORDER_MIN (5) #define WIL_RING_SIZE_ORDER_MAX (15) #define WIL6210_MAX_TX_RINGS (24) /* HW limit */ -#define WIL6210_MAX_CID (8) /* HW limit */ +#define WIL6210_MAX_CID (20) /* max number of stations */ +#define WIL6210_RX_DESC_MAX_CID (8) /* HW limit */ #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ #define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */ #define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */ @@ -458,7 +460,7 @@ static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid) */ static inline bool wil_cid_valid(u8 cid) { - return cid < WIL6210_MAX_CID; + return (cid >= 0 && cid < max_assoc_sta); } struct wil6210_mbox_ring { @@ -1236,7 +1238,7 @@ int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason, int wmi_addba(struct wil6210_priv *wil, u8 mid, u8 ringid, u8 size, u16 timeout); int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason); -int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason); +int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason); int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u8 token, u16 status, bool amsdu, u16 agg_wsize, u16 timeout); @@ -1249,8 +1251,8 @@ int wmi_port_allocate(struct wil6210_priv *wil, u8 mid, const u8 *mac, enum nl80211_iftype iftype); int wmi_port_delete(struct wil6210_priv *wil, u8 mid); int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval); -int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, - u8 cidxtid, u8 dialog_token, __le16 ba_param_set, +int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, + u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl); int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index b1ba519b0ca9..bda4a9712f91 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -24,8 +24,9 @@ #include "wmi.h" #include "trace.h" -static uint max_assoc_sta = WIL6210_MAX_CID; -module_param(max_assoc_sta, uint, 0644); +/* set the default max assoc sta to max supported by driver */ +uint max_assoc_sta = WIL6210_MAX_CID; +module_param(max_assoc_sta, uint, 0444); MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP"); int agg_wsize; /* = 0; */ @@ -770,6 +771,7 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len) struct wil6210_priv *wil = vif_to_wil(vif); struct wiphy *wiphy = wil_to_wiphy(wil); struct wmi_ready_event *evt = d; + u8 fw_max_assoc_sta; wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n", wil->fw_version, le32_to_cpu(evt->sw_version), @@ -787,6 +789,25 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len) evt->rfc_read_calib_result); wil->fw_calib_result = evt->rfc_read_calib_result; } + + fw_max_assoc_sta = WIL6210_RX_DESC_MAX_CID; + if (len > offsetof(struct wmi_ready_event, max_assoc_sta) && + evt->max_assoc_sta > 0) { + fw_max_assoc_sta = evt->max_assoc_sta; + wil_dbg_wmi(wil, "fw reported max assoc sta %d\n", + fw_max_assoc_sta); + + if (fw_max_assoc_sta > WIL6210_MAX_CID) { + wil_dbg_wmi(wil, + "fw max assoc sta %d exceeds max driver supported %d\n", + fw_max_assoc_sta, WIL6210_MAX_CID); + fw_max_assoc_sta = WIL6210_MAX_CID; + } + } + + max_assoc_sta = min_t(uint, max_assoc_sta, fw_max_assoc_sta); + wil_dbg_wmi(wil, "setting max assoc sta to %d\n", max_assoc_sta); + wil_set_recovery_state(wil, fw_recovery_idle); set_bit(wil_status_fwready, wil->status); /* let the reset sequence continue */ @@ -952,7 +973,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) evt->assoc_req_len, evt->assoc_resp_len); return; } - if (evt->cid >= WIL6210_MAX_CID) { + if (evt->cid >= max_assoc_sta) { wil_err(wil, "Connect CID invalid : %d\n", evt->cid); return; } @@ -1271,9 +1292,16 @@ static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id, void *d, int len) { struct wil6210_priv *wil = vif_to_wil(vif); + u8 cid, tid; struct wmi_rcp_addba_req_event *evt = d; - wil_addba_rx_request(wil, vif->mid, evt->cidxtid, evt->dialog_token, + if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) { + parse_cidxtid(evt->cidxtid, &cid, &tid); + } else { + cid = evt->cid; + tid = evt->tid; + } + wil_addba_rx_request(wil, vif->mid, cid, tid, evt->dialog_token, evt->ba_param_set, evt->ba_timeout, evt->ba_seq_ctrl); } @@ -1289,7 +1317,13 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) struct wil_tid_ampdu_rx *r; might_sleep(); - parse_cidxtid(evt->cidxtid, &cid, &tid); + + if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) { + parse_cidxtid(evt->cidxtid, &cid, &tid); + } else { + cid = evt->cid; + tid = evt->tid; + } wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n", vif->mid, cid, tid, evt->from_initiator ? "originator" : "recipient", @@ -1404,7 +1438,7 @@ static void wil_link_stats_store_basic(struct wil6210_vif *vif, u8 cid = basic->cid; struct wil_sta_info *sta; - if (cid < 0 || cid >= WIL6210_MAX_CID) { + if (cid < 0 || cid >= max_assoc_sta) { wil_err(wil, "invalid cid %d\n", cid); return; } @@ -1554,7 +1588,7 @@ static int wil_find_cid_ringid_sta(struct wil6210_priv *wil, continue; lcid = wil->ring2cid_tid[i][0]; - if (lcid >= WIL6210_MAX_CID) /* skip BCAST */ + if (lcid >= max_assoc_sta) /* skip BCAST */ continue; wil_dbg_wmi(wil, "find sta -> ringid %d cid %d\n", i, lcid); @@ -2120,10 +2154,9 @@ int wmi_pcp_start(struct wil6210_vif *vif, if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) || (cmd.pcp_max_assoc_sta <= 0)) { - wil_info(wil, - "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n", - max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID); - cmd.pcp_max_assoc_sta = WIL6210_MAX_CID; + wil_err(wil, "unexpected max_assoc_sta %d\n", + cmd.pcp_max_assoc_sta); + return -EOPNOTSUPP; } if (disable_ap_sme && @@ -2651,15 +2684,22 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason) return wmi_send(wil, WMI_RING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd)); } -int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason) +int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason) { struct wmi_rcp_delba_cmd cmd = { - .cidxtid = cidxtid, .reason = cpu_to_le16(reason), }; - wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf, - (cidxtid >> 4) & 0xf, reason); + if (cid >= WIL6210_RX_DESC_MAX_CID) { + cmd.cidxtid = CIDXTID_EXTENDED_CID_TID; + cmd.cid = cid; + cmd.tid = tid; + } else { + cmd.cidxtid = mk_cidxtid(cid, tid); + } + + wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cid, + tid, reason); return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd)); } @@ -2670,7 +2710,6 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, { int rc; struct wmi_rcp_addba_resp_cmd cmd = { - .cidxtid = mk_cidxtid(cid, tid), .dialog_token = token, .status_code = cpu_to_le16(status), /* bit 0: A-MSDU supported @@ -2689,6 +2728,14 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, .evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)}, }; + if (cid >= WIL6210_RX_DESC_MAX_CID) { + cmd.cidxtid = CIDXTID_EXTENDED_CID_TID; + cmd.cid = cid; + cmd.tid = tid; + } else { + cmd.cidxtid = mk_cidxtid(cid, tid); + } + wil_dbg_wmi(wil, "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n", mid, cid, tid, agg_wsize, -- cgit v1.2.3 From 6d1ba32c8070bf9e4088b16d3af1eb2b6f05543c Mon Sep 17 00:00:00 2001 From: Ahmad Masri Date: Fri, 22 Feb 2019 16:21:02 +0200 Subject: wil6210: accessing 802.3 addresses via utility functions Rearrange the code by having functions to access 802.3 header members, source and destination addresses. Signed-off-by: Ahmad Masri Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/txrx.c | 36 ++++++++++++++++----------------- drivers/net/wireless/ath/wil6210/txrx.h | 18 +++++++++++++++-- 2 files changed, 33 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 5aa14276303c..4ccfd1404458 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -383,7 +383,6 @@ static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, struct sk_buff *skb) */ int cid = wil_rxdesc_cid(d); unsigned int snaplen = wil_rx_snaplen(); - struct ethhdr *eth; struct ieee80211_hdr_3addr *hdr; int i; unsigned char *ta; @@ -401,8 +400,7 @@ static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, struct sk_buff *skb) skb->len); return -ENOENT; } - eth = (void *)skb->data; - ta = eth->h_source; + ta = wil_skb_get_sa(skb); } else { if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { wil_err_ratelimited(wil, "Short frame, len = %d\n", @@ -739,11 +737,11 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) unsigned int len = skb->len; int cid; int security; - struct ethhdr *eth = (void *)skb->data; + u8 *sa, *da = wil_skb_get_da(skb); /* here looking for DA, not A1, thus Rxdesc's 'mcast' indication * is not suitable, need to look at data */ - int mcast = is_multicast_ether_addr(eth->h_dest); + int mcast = is_multicast_ether_addr(da); struct wil_net_stats *stats; struct sk_buff *xmit_skb = NULL; static const char * const gro_res_str[] = { @@ -774,7 +772,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) } if (wdev->iftype == NL80211_IFTYPE_STATION) { - if (mcast && ether_addr_equal(eth->h_source, ndev->dev_addr)) { + sa = wil_skb_get_sa(skb); + if (mcast && ether_addr_equal(sa, ndev->dev_addr)) { /* mcast packet looped back to us */ rc = GRO_DROP; dev_kfree_skb(skb); @@ -787,8 +786,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) */ xmit_skb = skb_copy(skb, GFP_ATOMIC); } else { - int xmit_cid = wil_find_cid(wil, vif->mid, - eth->h_dest); + int xmit_cid = wil_find_cid(wil, vif->mid, da); if (xmit_cid >= 0) { /* The destination station is associated to @@ -1239,11 +1237,12 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil, struct wil6210_vif *vif, struct sk_buff *skb) { - int i; - struct ethhdr *eth = (void *)skb->data; - int cid = wil_find_cid(wil, vif->mid, eth->h_dest); + int i, cid; + const u8 *da = wil_skb_get_da(skb); int min_ring_id = wil_get_min_tx_ring_id(wil); + cid = wil_find_cid(wil, vif->mid, da); + if (cid < 0 || cid >= max_assoc_sta) return NULL; @@ -1257,7 +1256,7 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil, struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n", - eth->h_dest, i); + da, i); if (v->va && txdata->enabled) { return v; } else { @@ -1348,10 +1347,10 @@ static struct wil_ring *wil_find_tx_bcast_1(struct wil6210_priv *wil, static void wil_set_da_for_vring(struct wil6210_priv *wil, struct sk_buff *skb, int vring_index) { - struct ethhdr *eth = (void *)skb->data; + u8 *da = wil_skb_get_da(skb); int cid = wil->ring2cid_tid[vring_index][0]; - ether_addr_copy(eth->h_dest, wil->sta[cid].addr); + ether_addr_copy(da, wil->sta[cid].addr); } static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, @@ -1362,8 +1361,7 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, struct sk_buff *skb2; int i; u8 cid; - struct ethhdr *eth = (void *)skb->data; - char *src = eth->h_source; + const u8 *src = wil_skb_get_sa(skb); struct wil_ring_tx_data *txdata, *txdata2; int min_ring_id = wil_get_min_tx_ring_id(wil); @@ -2121,8 +2119,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct wil6210_vif *vif = ndev_to_vif(ndev); struct wil6210_priv *wil = vif_to_wil(vif); - struct ethhdr *eth = (void *)skb->data; - bool bcast = is_multicast_ether_addr(eth->h_dest); + const u8 *da = wil_skb_get_da(skb); + bool bcast = is_multicast_ether_addr(da); struct wil_ring *ring; static bool pr_once_fw; int rc; @@ -2169,7 +2167,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) ring = wil_find_tx_ucast(wil, vif, skb); } if (unlikely(!ring)) { - wil_dbg_txrx(wil, "No Tx RING found for %pM\n", eth->h_dest); + wil_dbg_txrx(wil, "No Tx RING found for %pM\n", da); goto drop; } /* set up vring entry */ diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 1aec04d59640..c0da1340c2d2 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -567,11 +567,25 @@ static inline int wil_ring_is_full(struct wil_ring *ring) return wil_ring_next_tail(ring) == ring->swhead; } -static inline bool wil_need_txstat(struct sk_buff *skb) +static inline u8 *wil_skb_get_da(struct sk_buff *skb) +{ + struct ethhdr *eth = (void *)skb->data; + + return eth->h_dest; +} + +static inline u8 *wil_skb_get_sa(struct sk_buff *skb) { struct ethhdr *eth = (void *)skb->data; - return is_unicast_ether_addr(eth->h_dest) && skb->sk && + return eth->h_source; +} + +static inline bool wil_need_txstat(struct sk_buff *skb) +{ + const u8 *da = wil_skb_get_da(skb); + + return is_unicast_ether_addr(da) && skb->sk && (skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS); } -- cgit v1.2.3 From a380eb5736c04942c158b22af04467eb21c27045 Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Fri, 22 Feb 2019 16:21:03 +0200 Subject: wil6210: fix invalid sta statistics update Upon status ring handling, in case there are both unicast and multicast (cid == max) status messages to handle, wrong sta statistics might get updated. Fix this by setting stats to NULL upon invalid cid (e.g. == max_assoc_sta). Signed-off-by: Dedy Lansky Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/txrx_edma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index c09cd692f910..c38773878ae3 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -1137,7 +1137,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil, /* Total number of completed descriptors in all descriptor rings */ int desc_cnt = 0; int cid; - struct wil_net_stats *stats = NULL; + struct wil_net_stats *stats; struct wil_tx_enhanced_desc *_d; unsigned int ring_id; unsigned int num_descs; @@ -1187,8 +1187,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil, ndev = vif_to_ndev(vif); cid = wil->ring2cid_tid[ring_id][0]; - if (cid < max_assoc_sta) - stats = &wil->sta[cid].stats; + stats = (cid < max_assoc_sta ? &wil->sta[cid].stats : NULL); wil_dbg_txrx(wil, "tx_status: completed desc_ring (%d), num_descs (%d)\n", -- cgit v1.2.3 From 979c9d8d01c482b1befb44dc639ecb907b5a37bd Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Fri, 22 Feb 2019 16:21:04 +0200 Subject: wil6210: ignore HALP ICR if already handled HALP ICR is set as long as the FW should stay awake. To prevent its multiple handling the driver masks this IRQ bit. However, if there is a different MISC ICR before the driver clears this bit, there is a risk of race condition between HALP mask and unmask. This race leads to HALP timeout, in case it is mistakenly masked. Add an atomic flag to indicate if HALP ICR should be handled. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/interrupt.c | 12 ++++++++---- drivers/net/wireless/ath/wil6210/main.c | 3 +++ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 5d287a8e1b45..3f5bd177d55f 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -575,10 +575,14 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) } if (isr & BIT_DMA_EP_MISC_ICR_HALP) { - wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n"); - wil6210_mask_halp(wil); isr &= ~BIT_DMA_EP_MISC_ICR_HALP; - complete(&wil->halp.comp); + if (wil->halp.handle_icr) { + /* no need to handle HALP ICRs until next vote */ + wil->halp.handle_icr = false; + wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n"); + wil6210_mask_halp(wil); + complete(&wil->halp.comp); + } } wil->isr_misc = isr; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 10de16ab7d69..277abfdf3322 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1919,11 +1919,14 @@ void wil_halp_vote(struct wil6210_priv *wil) if (++wil->halp.ref_cnt == 1) { reinit_completion(&wil->halp.comp); + /* mark to IRQ context to handle HALP ICR */ + wil->halp.handle_icr = true; wil6210_set_halp(wil); rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); if (!rc) { wil_err(wil, "HALP vote timed out\n"); /* Mask HALP as done in case the interrupt is raised */ + wil->halp.handle_icr = false; wil6210_mask_halp(wil); } else { wil_dbg_irq(wil, diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 85dca1b05283..e1b1039b13ab 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -794,6 +794,7 @@ struct wil_halp { struct mutex lock; /* protect halp ref_cnt */ unsigned int ref_cnt; struct completion comp; + u8 handle_icr; }; struct wil_blob_wrapper { -- cgit v1.2.3 From de77a53c2d1e8fb3621e63e8e1f0f0c9a1a99ff7 Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Fri, 22 Feb 2019 16:21:05 +0200 Subject: wil6210: check null pointer in _wil_cfg80211_merge_extra_ies ies1 or ies2 might be null when code inside _wil_cfg80211_merge_extra_ies access them. Add explicit check for null and make sure ies1/ies2 are not accessed in such a case. spos might be null and be accessed inside _wil_cfg80211_merge_extra_ies. Add explicit check for null in the while condition statement and make sure spos is not accessed in such a case. Signed-off-by: Alexei Avshalom Lazar Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 9a9d55b36dc3..a1e226652b4a 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1580,6 +1580,12 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len, u8 *buf, *dpos; const u8 *spos; + if (!ies1) + ies1_len = 0; + + if (!ies2) + ies2_len = 0; + if (ies1_len == 0 && ies2_len == 0) { *merged_ies = NULL; *merged_len = 0; @@ -1589,17 +1595,19 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len, buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL); if (!buf) return -ENOMEM; - memcpy(buf, ies1, ies1_len); + if (ies1) + memcpy(buf, ies1, ies1_len); dpos = buf + ies1_len; spos = ies2; - while (spos + 1 < ies2 + ies2_len) { + while (spos && (spos + 1 < ies2 + ies2_len)) { /* IE tag at offset 0, length at offset 1 */ u16 ielen = 2 + spos[1]; if (spos + ielen > ies2 + ies2_len) break; if (spos[0] == WLAN_EID_VENDOR_SPECIFIC && - !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) { + (!ies1 || !_wil_cfg80211_find_ie(ies1, ies1_len, + spos, ielen))) { memcpy(dpos, spos, ielen); dpos += ielen; } -- cgit v1.2.3 From 012475e3c59cbe488779e86565807a73ff115f4b Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Thu, 28 Feb 2019 15:06:54 +0530 Subject: cxgb4/cxgb4vf: Fix up netdev->hw_features GRO is done by cxgb4/cxgb4vf. Hence set NETIF_F_GRO flag for both cxgb4/cxgb4vf. Cleaned up VLAN netdev features in cxgb4vf. Also fixed NETIF_F_HIGHDMA being set unconditionally for vlan netdev features. Signed-off-by: Arjun Vynipadath Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 4 ++-- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index bcbac247a73d..200b16034544 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -5303,7 +5303,7 @@ static void free_some_resources(struct adapter *adapter) #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \ - NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA) + NETIF_F_GRO | NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA) #define SEGMENT_SIZE 128 static int t4_get_chip_type(struct adapter *adap, int ver) @@ -5710,7 +5710,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->hw_features = NETIF_F_SG | TSO_FLAGS | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_RXCSUM | NETIF_F_RXHASH | + NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_GRO | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_TC; diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 3300b69a42b3..bcd38ea674ae 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -1932,6 +1932,8 @@ static void cxgb4vf_get_wol(struct net_device *dev, * TCP Segmentation Offload flags which we support. */ #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN) +#define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \ + NETIF_F_GRO | NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA) static const struct ethtool_ops cxgb4vf_ethtool_ops = { .get_link_ksettings = cxgb4vf_get_link_ksettings, @@ -3141,16 +3143,13 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, netif_carrier_off(netdev); netdev->irq = pdev->irq; - netdev->hw_features = NETIF_F_SG | TSO_FLAGS | - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_RXCSUM; - netdev->vlan_features = NETIF_F_SG | TSO_FLAGS | - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_HIGHDMA; - netdev->features = netdev->hw_features | - NETIF_F_HW_VLAN_CTAG_TX; + netdev->hw_features = NETIF_F_SG | TSO_FLAGS | NETIF_F_GRO | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; + netdev->features = netdev->hw_features; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features = netdev->features & VLAN_FEAT; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->min_mtu = 81; -- cgit v1.2.3 From 64f40cdd07e19b509302d5cb53878ed9d9fa3b5b Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Thu, 28 Feb 2019 15:09:28 +0530 Subject: cxgb4: Enable outer UDP checksum offload for T6 T6 adapters support outer UDP checksum offload for encapsulated packets, hence enabling netdev feature flag NETIF_F_GSO_UDP_TUNNEL_CSUM. Signed-off-by: Arjun Vynipadath Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 200b16034544..1754ff794360 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -5719,9 +5719,11 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_TSO | NETIF_F_TSO6; netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_HW_TLS_RECORD; } -- cgit v1.2.3 From 4a8acef78e170854ce6865e216eff82bda92437d Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Thu, 28 Feb 2019 15:33:16 +0530 Subject: cxgb4vf: Enter debugging mode if FW is inaccessible If we are not able to reach firmware, enter debugging mode that will help us to get adapter logs. Signed-off-by: Arjun Vynipadath Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4vf/adapter.h | 1 + .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 45 +++++++++++++++------- 2 files changed, 33 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h index 26f48a14d2f9..86cf68fceceb 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h @@ -411,6 +411,7 @@ enum { /* adapter flags */ USING_MSIX = (1UL << 2), QUEUES_BOUND = (1UL << 3), ROOT_NO_RELAXED_ORDERING = (1UL << 4), + FW_OK = (1UL << 5), }; /* diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index bcd38ea674ae..2c56bd810931 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -844,6 +844,13 @@ static int cxgb4vf_open(struct net_device *dev) struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; + /* + * If we don't have a connection to the firmware there's nothing we + * can do. + */ + if (!(adapter->flags & FW_OK)) + return -ENXIO; + /* * If this is the first interface that we're opening on the "adapter", * bring the "adapter" up now. @@ -2720,6 +2727,7 @@ static int adap_init0(struct adapter *adapter) */ size_nports_qsets(adapter); + adapter->flags |= FW_OK; return 0; } @@ -3084,7 +3092,9 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, err = adap_init0(adapter); if (err) - goto err_unmap_bar; + dev_err(&pdev->dev, + "Adapter initialization failed, error %d. Continuing in debug mode\n", + err); /* Initialize hash mac addr list */ INIT_LIST_HEAD(&adapter->mac_hlist); @@ -3109,13 +3119,6 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, break; port_id = ffs(pmask) - 1; pmask &= ~(1 << port_id); - viid = t4vf_alloc_vi(adapter, port_id); - if (viid < 0) { - dev_err(&pdev->dev, "cannot allocate VI for port %d:" - " err=%d\n", port_id, viid); - err = viid; - goto err_free_dev; - } /* * Allocate our network device and stitch things together. @@ -3123,7 +3126,6 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, netdev = alloc_etherdev_mq(sizeof(struct port_info), MAX_PORT_QSETS); if (netdev == NULL) { - t4vf_free_vi(adapter, viid); err = -ENOMEM; goto err_free_dev; } @@ -3133,7 +3135,6 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, pi->adapter = adapter; pi->pidx = pidx; pi->port_id = port_id; - pi->viid = viid; /* * Initialize the starting state of our "port" and register @@ -3159,6 +3160,23 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, netdev->ethtool_ops = &cxgb4vf_ethtool_ops; netdev->dev_port = pi->port_id; + /* + * If we haven't been able to contact the firmware, there's + * nothing else we can do for this "port" ... + */ + if (!(adapter->flags & FW_OK)) + continue; + + viid = t4vf_alloc_vi(adapter, port_id); + if (viid < 0) { + dev_err(&pdev->dev, + "cannot allocate VI for port %d: err=%d\n", + port_id, viid); + err = viid; + goto err_free_dev; + } + pi->viid = viid; + /* * Initialize the hardware/software state for the port. */ @@ -3302,13 +3320,13 @@ err_free_dev: if (netdev == NULL) continue; pi = netdev_priv(netdev); - t4vf_free_vi(adapter, pi->viid); + if (pi->viid) + t4vf_free_vi(adapter, pi->viid); if (test_bit(pidx, &adapter->registered_device_map)) unregister_netdev(netdev); free_netdev(netdev); } -err_unmap_bar: if (!is_t4(adapter->params.chip)) iounmap(adapter->bar2); @@ -3381,7 +3399,8 @@ static void cxgb4vf_pci_remove(struct pci_dev *pdev) continue; pi = netdev_priv(netdev); - t4vf_free_vi(adapter, pi->viid); + if (pi->viid) + t4vf_free_vi(adapter, pi->viid); free_netdev(netdev); } iounmap(adapter->regs); -- cgit v1.2.3 From d7d543f252994387571462096ec646f5f335c4ee Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:36 +0100 Subject: s390/qeth: remove RECOVER state The offline code uses a specific RECOVER state to indicate that the interface should be brought up when a qeth device is set online again. Rather than having a specific card-state for this, just put it in an internal flag bit and set the state to DOWN. When working with the card's state transitions, this reduces the complexity quite a bit. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 2 +- drivers/s390/net/qeth_core_main.c | 6 ++---- drivers/s390/net/qeth_core_sys.c | 14 ++++---------- drivers/s390/net/qeth_l2_main.c | 19 +++++++------------ drivers/s390/net/qeth_l3_main.c | 19 +++++++------------ drivers/s390/net/qeth_l3_sys.c | 12 ++++-------- 6 files changed, 25 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index c0c46be0b251..79de890010c7 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -553,7 +553,6 @@ enum qeth_card_states { CARD_STATE_HARDSETUP, CARD_STATE_SOFTSETUP, CARD_STATE_UP, - CARD_STATE_RECOVER, }; /** @@ -665,6 +664,7 @@ struct qeth_card_info { unsigned short chpid; __u16 func_level; char mcl_level[QETH_MCL_LENGTH + 1]; + u8 open_when_online:1; int guestlan; int mac_bits; enum qeth_card_types type; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 4708df39f129..a69e31e9bdf1 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -265,8 +265,7 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt) { QETH_CARD_TEXT(card, 2, "realcbp"); - if ((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) + if (card->state != CARD_STATE_DOWN) return -EPERM; /* TODO: steel/add buffers from/to a running card's buffer pool (?) */ @@ -3479,8 +3478,7 @@ int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) goto out; } - if (card->state != CARD_STATE_DOWN && - card->state != CARD_STATE_RECOVER) { + if (card->state != CARD_STATE_DOWN) { rc = -1; goto out; } diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 8b223cc2c19b..e24d204b780a 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -34,8 +34,6 @@ static ssize_t qeth_dev_state_show(struct device *dev, return sprintf(buf, "UP (LAN %s)\n", netif_carrier_ok(card->dev) ? "ONLINE" : "OFFLINE"); - case CARD_STATE_RECOVER: - return sprintf(buf, "RECOVER\n"); default: return sprintf(buf, "UNKNOWN\n"); } @@ -126,8 +124,7 @@ static ssize_t qeth_dev_portno_store(struct device *dev, return -EINVAL; mutex_lock(&card->conf_mutex); - if ((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) { + if (card->state != CARD_STATE_DOWN) { rc = -EPERM; goto out; } @@ -202,8 +199,7 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev, return -EINVAL; mutex_lock(&card->conf_mutex); - if ((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) { + if (card->state != CARD_STATE_DOWN) { rc = -EPERM; goto out; } @@ -285,8 +281,7 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev, return -EINVAL; mutex_lock(&card->conf_mutex); - if ((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) { + if (card->state != CARD_STATE_DOWN) { rc = -EPERM; goto out; } @@ -634,8 +629,7 @@ static ssize_t qeth_dev_blkt_store(struct qeth_card *card, return -EINVAL; mutex_lock(&card->conf_mutex); - if ((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) { + if (card->state != CARD_STATE_DOWN) { rc = -EPERM; goto out; } diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 2c9714215775..f621656f9ea7 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -807,7 +807,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct net_device *dev = card->dev; int rc = 0; - enum qeth_card_states recover_flag; bool carrier_ok; mutex_lock(&card->discipline_mutex); @@ -815,7 +814,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) QETH_DBF_TEXT(SETUP, 2, "setonlin"); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); - recover_flag = card->state; rc = qeth_core_hardsetup_card(card, &carrier_ok); if (rc) { QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc); @@ -881,7 +879,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) netif_device_attach(dev); qeth_enable_hw_features(dev); - if (recover_flag == CARD_STATE_RECOVER) { + if (card->info.open_when_online) { + card->info.open_when_online = 0; if (recovery_mode && !IS_OSN(card)) { if (!qeth_l2_validate_addr(dev)) { qeth_open(dev); @@ -905,10 +904,8 @@ out_remove: ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); qdio_free(CARD_DDEV(card)); - if (recover_flag == CARD_STATE_RECOVER) - card->state = CARD_STATE_RECOVER; - else - card->state = CARD_STATE_DOWN; + card->state = CARD_STATE_DOWN; + mutex_unlock(&card->conf_mutex); mutex_unlock(&card->discipline_mutex); return rc; @@ -924,7 +921,6 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, { struct qeth_card *card = dev_get_drvdata(&cgdev->dev); int rc = 0, rc2 = 0, rc3 = 0; - enum qeth_card_states recover_flag; mutex_lock(&card->discipline_mutex); mutex_lock(&card->conf_mutex); @@ -932,11 +928,11 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); rtnl_lock(); + card->info.open_when_online = card->dev->flags & IFF_UP; netif_device_detach(card->dev); netif_carrier_off(card->dev); rtnl_unlock(); - recover_flag = card->state; if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); card->info.hwtrap = 1; @@ -950,8 +946,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, if (rc) QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); qdio_free(CARD_DDEV(card)); - if (recover_flag == CARD_STATE_UP) - card->state = CARD_STATE_RECOVER; + /* let user_space know that device is offline */ kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE); mutex_unlock(&card->conf_mutex); @@ -1024,7 +1019,7 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev) struct qeth_card *card = dev_get_drvdata(&gdev->dev); int rc = 0; - if (card->state == CARD_STATE_RECOVER) { + if (card->info.open_when_online) { rc = __qeth_l2_set_online(card->gdev, 1); if (rc) { rtnl_lock(); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 07c3149e228c..fe6b9a82f69e 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2304,7 +2304,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct net_device *dev = card->dev; int rc = 0; - enum qeth_card_states recover_flag; bool carrier_ok; mutex_lock(&card->discipline_mutex); @@ -2312,7 +2311,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) QETH_DBF_TEXT(SETUP, 2, "setonlin"); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); - recover_flag = card->state; rc = qeth_core_hardsetup_card(card, &carrier_ok); if (rc) { QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc); @@ -2375,7 +2373,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) netif_device_attach(dev); qeth_enable_hw_features(dev); - if (recover_flag == CARD_STATE_RECOVER) { + if (card->info.open_when_online) { + card->info.open_when_online = 0; if (recovery_mode) { qeth_open(dev); qeth_l3_set_rx_mode(dev); @@ -2397,10 +2396,8 @@ out_remove: ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); qdio_free(CARD_DDEV(card)); - if (recover_flag == CARD_STATE_RECOVER) - card->state = CARD_STATE_RECOVER; - else - card->state = CARD_STATE_DOWN; + card->state = CARD_STATE_DOWN; + mutex_unlock(&card->conf_mutex); mutex_unlock(&card->discipline_mutex); return rc; @@ -2416,7 +2413,6 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, { struct qeth_card *card = dev_get_drvdata(&cgdev->dev); int rc = 0, rc2 = 0, rc3 = 0; - enum qeth_card_states recover_flag; mutex_lock(&card->discipline_mutex); mutex_lock(&card->conf_mutex); @@ -2424,11 +2420,11 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); rtnl_lock(); + card->info.open_when_online = card->dev->flags & IFF_UP; netif_device_detach(card->dev); netif_carrier_off(card->dev); rtnl_unlock(); - recover_flag = card->state; if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); card->info.hwtrap = 1; @@ -2447,8 +2443,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, if (rc) QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); qdio_free(CARD_DDEV(card)); - if (recover_flag == CARD_STATE_UP) - card->state = CARD_STATE_RECOVER; + /* let user_space know that device is offline */ kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE); mutex_unlock(&card->conf_mutex); @@ -2511,7 +2506,7 @@ static int qeth_l3_pm_resume(struct ccwgroup_device *gdev) struct qeth_card *card = dev_get_drvdata(&gdev->dev); int rc = 0; - if (card->state == CARD_STATE_RECOVER) { + if (card->info.open_when_online) { rc = __qeth_l3_set_online(card->gdev, 1); if (rc) { rtnl_lock(); diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 45ac6d8705c6..cff518b0f904 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -167,8 +167,7 @@ static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev, return -EINVAL; mutex_lock(&card->conf_mutex); - if ((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) { + if (card->state != CARD_STATE_DOWN) { rc = -EPERM; goto out; } @@ -213,8 +212,7 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev, return -EPERM; mutex_lock(&card->conf_mutex); - if ((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) { + if (card->state != CARD_STATE_DOWN) { rc = -EPERM; goto out; } @@ -280,8 +278,7 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev, if (card->info.type != QETH_CARD_TYPE_IQD) return -EPERM; - if (card->state != CARD_STATE_DOWN && - card->state != CARD_STATE_RECOVER) + if (card->state != CARD_STATE_DOWN) return -EPERM; if (card->options.sniffer) return -EPERM; @@ -356,8 +353,7 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev, return -EINVAL; mutex_lock(&card->conf_mutex); - if ((card->state != CARD_STATE_DOWN) && - (card->state != CARD_STATE_RECOVER)) { + if (card->state != CARD_STATE_DOWN) { rc = -EPERM; goto out; } -- cgit v1.2.3 From d7ef489f8261208b8a21b3c563e4d3d40b674e01 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:37 +0100 Subject: s390/qeth: enable/disable the HW trap a little earlier When setting a L2 qeth device online, enable the HW trap as soon as the control plane is available. This allows us to catch any error that occurs during the very first commands. In the same spirit, the offline code should disable the HW trap as the very first step of its processing. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 22 ++++++++++++---------- drivers/s390/net/qeth_l3_main.c | 9 +++++---- 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index f621656f9ea7..72e6d08444a7 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -820,12 +820,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) rc = -ENODEV; goto out_remove; } - qeth_bridgeport_query_support(card); - if (card->options.sbp.supported_funcs) - dev_info(&card->gdev->dev, - "The device represents a Bridge Capable Port\n"); - - qeth_l2_register_dev_addr(card); if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { if (card->info.hwtrap && @@ -834,6 +828,13 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) } else card->info.hwtrap = 0; + qeth_bridgeport_query_support(card); + if (card->options.sbp.supported_funcs) + dev_info(&card->gdev->dev, + "The device represents a Bridge Capable Port\n"); + + qeth_l2_register_dev_addr(card); + /* for the rx_bcast characteristic, init VNICC after setmac */ qeth_l2_vnicc_init(card); @@ -927,16 +928,17 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); + if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); + card->info.hwtrap = 1; + } + rtnl_lock(); card->info.open_when_online = card->dev->flags & IFF_UP; netif_device_detach(card->dev); netif_carrier_off(card->dev); rtnl_unlock(); - if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { - qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); - card->info.hwtrap = 1; - } qeth_l2_stop_card(card, recovery_mode); rc = ccw_device_set_offline(CARD_DDEV(card)); rc2 = ccw_device_set_offline(CARD_WDEV(card)); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index fe6b9a82f69e..c299e84cf5d1 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2419,16 +2419,17 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); + if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { + qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); + card->info.hwtrap = 1; + } + rtnl_lock(); card->info.open_when_online = card->dev->flags & IFF_UP; netif_device_detach(card->dev); netif_carrier_off(card->dev); rtnl_unlock(); - if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { - qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); - card->info.hwtrap = 1; - } qeth_l3_stop_card(card, recovery_mode); if ((card->options.cq == QETH_CQ_ENABLED) && card->dev) { rtnl_lock(); -- cgit v1.2.3 From 7bd2275c974f9dd7789ee957a0d1837c4114a910 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:38 +0100 Subject: s390/qeth: unconditionally clear MAC_REGISTERED flag In its attempt to run only the minimal amount of tear down steps, qeth_l2_stop_card() fails to reset the "is dev_addr registered?" flag in some rare scenarios. But a future change to the tear down sequence would cause us to _always_ hit this issue, so patch it up before that code lands. Fix it by unconditionally clearing the flag bit. This also allows us to remove the additional cleanup step in qeth_dev_layer2_store(). Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_sys.c | 1 - drivers/s390/net/qeth_l2_main.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index e24d204b780a..fa575549d288 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -416,7 +416,6 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, goto out; } - card->info.mac_bits = 0; if (card->discipline) { /* start with a new, pristine netdevice: */ ndev = qeth_clone_netdev(card->dev); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 72e6d08444a7..f71d45ea30da 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -301,7 +301,6 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) dev_close(card->dev); rtnl_unlock(); } - card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; card->state = CARD_STATE_SOFTSETUP; } if (card->state == CARD_STATE_SOFTSETUP) { @@ -321,6 +320,7 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) } flush_workqueue(card->event_wq); + card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; } static int qeth_l2_process_inbound_buffer(struct qeth_card *card, -- cgit v1.2.3 From d4560150cb47daba50b0d080550ca4bbe80cf3c3 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:39 +0100 Subject: s390/qeth: call dev_close() during recovery When resetting an interface ("recovery"), qeth currently attempts to elide the call to dev_close(). We initially only call .ndo_close to quiesce the data path, and then offline & online the ccwgroup device. If the reset succeeded, a call to .ndo_open then resumes the data path along with some internal setup (dev_addr validation, RX modeset) that dev_open() would have usually triggered. dev_close() only gets called (via the close_dev worker) if the reset action fails. It's unclear whether this was initially done due to locking concerns, or rather to execute the reset transparently. Either way, temporarily closing the interface without dev_close() is fragile, and means we're susceptible to various races and unexpected behaviour. For instance: - Bypassing dev_deactivate_many() means that the qdiscs are not set to __QDISC_STATE_DEACTIVATED. Consequently any intermittent TX completion can wake up the txq, resulting in calls to .ndo_start_xmit while the data path is down. We have custom state checking to detect this case and drop such packets. - Because the IFF_UP flag doesn't reflect the interface's actual state during a reset, we have custom state checking in .ndo_open and .ndo_close to guard against invalid calls. - Considering that the reset might take a considerable amount of time (in particular if an IO fails and we end up waiting for its timeout), we _do_ want NETDEV_GOING_DOWN and NETDEV_DOWN events so that components like bonding, team, bridge, macvlan, vlan, ... can take appropriate action. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 3 --- drivers/s390/net/qeth_l2_main.c | 47 +++++++++------------------------------ drivers/s390/net/qeth_l3_main.c | 45 +++++++++---------------------------- 3 files changed, 20 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index a69e31e9bdf1..a1a66467b06b 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -89,9 +89,6 @@ static void qeth_close_dev_handler(struct work_struct *work) card = container_of(work, struct qeth_card, close_dev_work); QETH_CARD_TEXT(card, 2, "cldevhdl"); - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); ccwgroup_set_offline(card->gdev); } diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index f71d45ea30da..a42285b1daa3 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -285,7 +285,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN); } -static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) +static void qeth_l2_stop_card(struct qeth_card *card) { QETH_DBF_TEXT(SETUP , 2, "stopcard"); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); @@ -293,16 +293,8 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) qeth_set_allowed_threads(card, 0, 1); if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && - (card->state == CARD_STATE_UP)) { - if (recovery_mode && !IS_OSN(card)) { - qeth_stop(card->dev); - } else { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + card->state == CARD_STATE_UP) card->state = CARD_STATE_SOFTSETUP; - } if (card->state == CARD_STATE_SOFTSETUP) { qeth_l2_del_all_macs(card); qeth_clear_ipacmd_list(card); @@ -802,7 +794,7 @@ static void qeth_l2_trace_features(struct qeth_card *card) sizeof(card->options.vnicc.sup_chars)); } -static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) +static int qeth_l2_set_online(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct net_device *dev = card->dev; @@ -882,14 +874,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) if (card->info.open_when_online) { card->info.open_when_online = 0; - if (recovery_mode && !IS_OSN(card)) { - if (!qeth_l2_validate_addr(dev)) { - qeth_open(dev); - qeth_l2_set_rx_mode(dev); - } - } else { - dev_open(dev, NULL); - } + dev_open(dev, NULL); } rtnl_unlock(); } @@ -900,7 +885,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) return 0; out_remove: - qeth_l2_stop_card(card, 0); + qeth_l2_stop_card(card); ccw_device_set_offline(CARD_DDEV(card)); ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); @@ -912,11 +897,6 @@ out_remove: return rc; } -static int qeth_l2_set_online(struct ccwgroup_device *gdev) -{ - return __qeth_l2_set_online(gdev, 0); -} - static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) { @@ -935,11 +915,12 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, rtnl_lock(); card->info.open_when_online = card->dev->flags & IFF_UP; + dev_close(card->dev); netif_device_detach(card->dev); netif_carrier_off(card->dev); rtnl_unlock(); - qeth_l2_stop_card(card, recovery_mode); + qeth_l2_stop_card(card); rc = ccw_device_set_offline(CARD_DDEV(card)); rc2 = ccw_device_set_offline(CARD_WDEV(card)); rc3 = ccw_device_set_offline(CARD_RDEV(card)); @@ -974,7 +955,7 @@ static int qeth_l2_recover(void *ptr) dev_warn(&card->gdev->dev, "A recovery process has been started for the device\n"); __qeth_l2_set_offline(card->gdev, 1); - rc = __qeth_l2_set_online(card->gdev, 1); + rc = qeth_l2_set_online(card->gdev); if (!rc) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); @@ -1019,17 +1000,9 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) static int qeth_l2_pm_resume(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); - int rc = 0; + int rc; - if (card->info.open_when_online) { - rc = __qeth_l2_set_online(card->gdev, 1); - if (rc) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } - } else - rc = __qeth_l2_set_online(card->gdev, 0); + rc = qeth_l2_set_online(gdev); qeth_set_allowed_threads(card, 0xffffffff, 0); if (rc) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index c299e84cf5d1..1381e7e312cd 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1406,7 +1406,7 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, return work_done; } -static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) +static void qeth_l3_stop_card(struct qeth_card *card) { QETH_DBF_TEXT(SETUP, 2, "stopcard"); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); @@ -1417,16 +1417,8 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE); if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && - (card->state == CARD_STATE_UP)) { - if (recovery_mode) - qeth_stop(card->dev); - else { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + card->state == CARD_STATE_UP) card->state = CARD_STATE_SOFTSETUP; - } if (card->state == CARD_STATE_SOFTSETUP) { qeth_l3_clear_ip_htable(card, 1); qeth_clear_ipacmd_list(card); @@ -2299,7 +2291,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) qeth_l3_clear_ipato_list(card); } -static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) +static int qeth_l3_set_online(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct net_device *dev = card->dev; @@ -2375,12 +2367,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) if (card->info.open_when_online) { card->info.open_when_online = 0; - if (recovery_mode) { - qeth_open(dev); - qeth_l3_set_rx_mode(dev); - } else { - dev_open(dev, NULL); - } + dev_open(dev, NULL); } rtnl_unlock(); } @@ -2391,7 +2378,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) mutex_unlock(&card->discipline_mutex); return 0; out_remove: - qeth_l3_stop_card(card, 0); + qeth_l3_stop_card(card); ccw_device_set_offline(CARD_DDEV(card)); ccw_device_set_offline(CARD_WDEV(card)); ccw_device_set_offline(CARD_RDEV(card)); @@ -2403,11 +2390,6 @@ out_remove: return rc; } -static int qeth_l3_set_online(struct ccwgroup_device *gdev) -{ - return __qeth_l3_set_online(gdev, 0); -} - static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, int recovery_mode) { @@ -2426,11 +2408,12 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, rtnl_lock(); card->info.open_when_online = card->dev->flags & IFF_UP; + dev_close(card->dev); netif_device_detach(card->dev); netif_carrier_off(card->dev); rtnl_unlock(); - qeth_l3_stop_card(card, recovery_mode); + qeth_l3_stop_card(card); if ((card->options.cq == QETH_CQ_ENABLED) && card->dev) { rtnl_lock(); call_netdevice_notifiers(NETDEV_REBOOT, card->dev); @@ -2471,7 +2454,7 @@ static int qeth_l3_recover(void *ptr) dev_warn(&card->gdev->dev, "A recovery process has been started for the device\n"); __qeth_l3_set_offline(card->gdev, 1); - rc = __qeth_l3_set_online(card->gdev, 1); + rc = qeth_l3_set_online(card->gdev); if (!rc) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); @@ -2505,17 +2488,9 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) static int qeth_l3_pm_resume(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); - int rc = 0; + int rc; - if (card->info.open_when_online) { - rc = __qeth_l3_set_online(card->gdev, 1); - if (rc) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } - } else - rc = __qeth_l3_set_online(card->gdev, 0); + rc = qeth_l3_set_online(gdev); qeth_set_allowed_threads(card, 0xffffffff, 0); if (rc) -- cgit v1.2.3 From 464e86dafcca14e5f7a7157fc567c58654ec80b3 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:40 +0100 Subject: s390/qeth: remove a redundant check for card->dev smatch complains that __qeth_l3_set_offline() first accesses card->dev, and then later checks whether the pointer is valid. Since commit d3d1b205e89f ("s390/qeth: allocate netdevice early"), the pointer is _always_ valid - that patch merely missed to remove this one check. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 1381e7e312cd..13d77957404c 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2414,7 +2414,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, rtnl_unlock(); qeth_l3_stop_card(card); - if ((card->options.cq == QETH_CQ_ENABLED) && card->dev) { + if (card->options.cq == QETH_CQ_ENABLED) { rtnl_lock(); call_netdevice_notifiers(NETDEV_REBOOT, card->dev); rtnl_unlock(); -- cgit v1.2.3 From bf42d40b1254afe26015ebdb09d137fb15250fa4 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:41 +0100 Subject: s390/qeth: don't defer close_dev work during recovery The recovery code already runs in a kthread, we don't have to defer the offlining further. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 1 - drivers/s390/net/qeth_core_main.c | 3 +-- drivers/s390/net/qeth_l2_main.c | 2 +- drivers/s390/net/qeth_l3_main.c | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 79de890010c7..8c354cdc86c0 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -1002,7 +1002,6 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback); int qeth_configure_cq(struct qeth_card *, enum qeth_cq); int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); void qeth_trace_features(struct qeth_card *); -void qeth_close_dev(struct qeth_card *); int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long); struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *, enum qeth_ipa_funcs, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index a1a66467b06b..6c2540e3247b 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -92,12 +92,11 @@ static void qeth_close_dev_handler(struct work_struct *work) ccwgroup_set_offline(card->gdev); } -void qeth_close_dev(struct qeth_card *card) +static void qeth_close_dev(struct qeth_card *card) { QETH_CARD_TEXT(card, 2, "cldevsubm"); queue_work(qeth_wq, &card->close_dev_work); } -EXPORT_SYMBOL_GPL(qeth_close_dev); static const char *qeth_get_cardname(struct qeth_card *card) { diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index a42285b1daa3..f34fe983012c 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -960,7 +960,7 @@ static int qeth_l2_recover(void *ptr) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); else { - qeth_close_dev(card); + ccwgroup_set_offline(card->gdev); dev_warn(&card->gdev->dev, "The qeth device driver " "failed to recover an error on the device\n"); } diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 13d77957404c..d424a6704811 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2459,7 +2459,7 @@ static int qeth_l3_recover(void *ptr) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); else { - qeth_close_dev(card); + ccwgroup_set_offline(card->gdev); dev_warn(&card->gdev->dev, "The qeth device driver " "failed to recover an error on the device\n"); } -- cgit v1.2.3 From dcef5cad639e0c24dd562e777b31533f5c97baa1 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:42 +0100 Subject: s390/qeth: remove driver-wide workqueue The qeth-wide workqueue is now only used by a single caller to schedule close_dev work. Just put it on a system queue instead. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6c2540e3247b..4dcb4f91b9c0 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -74,8 +74,6 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf); static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); -static struct workqueue_struct *qeth_wq; - int qeth_card_hw_is_reachable(struct qeth_card *card) { return (card->state == CARD_STATE_SOFTSETUP) || @@ -92,12 +90,6 @@ static void qeth_close_dev_handler(struct work_struct *work) ccwgroup_set_offline(card->gdev); } -static void qeth_close_dev(struct qeth_card *card) -{ - QETH_CARD_TEXT(card, 2, "cldevsubm"); - queue_work(qeth_wq, &card->close_dev_work); -} - static const char *qeth_get_cardname(struct qeth_card *card) { if (card->info.guestlan) { @@ -634,7 +626,7 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, dev_err(&card->gdev->dev, "Interface %s is down because the adjacent port is no longer in reflective relay mode\n", QETH_CARD_IFNAME(card)); - qeth_close_dev(card); + schedule_work(&card->close_dev_work); } else { dev_warn(&card->gdev->dev, "The link for interface %s on CHPID 0x%X failed\n", @@ -6265,12 +6257,6 @@ static int __init qeth_core_init(void) pr_info("loading core functions\n"); - qeth_wq = create_singlethread_workqueue("qeth_wq"); - if (!qeth_wq) { - rc = -ENOMEM; - goto out_err; - } - rc = qeth_register_dbf_views(); if (rc) goto dbf_err; @@ -6312,8 +6298,6 @@ slab_err: register_err: qeth_unregister_dbf_views(); dbf_err: - destroy_workqueue(qeth_wq); -out_err: pr_err("Initializing the qeth device driver failed\n"); return rc; } @@ -6321,7 +6305,6 @@ out_err: static void __exit qeth_core_exit(void) { qeth_clear_dbf_list(); - destroy_workqueue(qeth_wq); ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); ccw_driver_unregister(&qeth_ccw_driver); kmem_cache_destroy(qeth_qdio_outbuf_cache); -- cgit v1.2.3 From 62ca98d475d1839f90d209bb47cc0192dc3db946 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:43 +0100 Subject: s390/qeth: don't special-case HW trap during suspend It makes no difference whether we 1. manually disarm the HW trap and call the offline code with recovery_mode == 1, or 2. call the offline code with recovery_mode == 0, and let it disarm the HW trap for us. So consolidate the two code paths in the suspend callback. Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 8 ++------ drivers/s390/net/qeth_l3_main.c | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index f34fe983012c..6380d29c10f7 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -988,12 +988,8 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (gdev->state == CCWGROUP_OFFLINE) return 0; - if (card->state == CARD_STATE_UP) { - if (card->info.hwtrap) - qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); - __qeth_l2_set_offline(card->gdev, 1); - } else - __qeth_l2_set_offline(card->gdev, 0); + + qeth_l2_set_offline(gdev); return 0; } diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index d424a6704811..375ad03ea4c5 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2476,12 +2476,8 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); if (gdev->state == CCWGROUP_OFFLINE) return 0; - if (card->state == CARD_STATE_UP) { - if (card->info.hwtrap) - qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); - __qeth_l3_set_offline(card->gdev, 1); - } else - __qeth_l3_set_offline(card->gdev, 0); + + qeth_l3_set_offline(gdev); return 0; } -- cgit v1.2.3 From 0f7aedbdf2bb92cf1a3462561b3ff4c3a42bfe7d Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 28 Feb 2019 18:59:44 +0100 Subject: s390/qeth: drop redundant state checking Now that qeth always uses dev_close() to shutdown the interface, we can trust the locking and remove some custom state checks. qeth_l?_stop_card() is no longer called for a card in UP state, so remove the checks there too. This basically makes the UP state obsolete, so rip out the whole thing (except for the sysfs-visible string). Signed-off-by: Julian Wiedmann Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 8 +++++--- drivers/s390/net/qeth_core_main.c | 18 +----------------- drivers/s390/net/qeth_core_sys.c | 8 ++++---- drivers/s390/net/qeth_l2_main.c | 11 +---------- drivers/s390/net/qeth_l3_main.c | 11 ++--------- 5 files changed, 13 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 8c354cdc86c0..c851cf6e01c4 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -483,7 +483,6 @@ struct qeth_out_q_stats { u64 tx_bytes; u64 tx_errors; u64 tx_dropped; - u64 tx_carrier_errors; }; struct qeth_qdio_out_q { @@ -552,7 +551,6 @@ enum qeth_card_states { CARD_STATE_DOWN, CARD_STATE_HARDSETUP, CARD_STATE_SOFTSETUP, - CARD_STATE_UP, }; /** @@ -808,6 +806,11 @@ struct qeth_card { struct work_struct close_dev_work; }; +static inline bool qeth_card_hw_is_reachable(struct qeth_card *card) +{ + return card->state == CARD_STATE_SOFTSETUP; +} + struct qeth_trap_id { __u16 lparnr; char vmname[8]; @@ -942,7 +945,6 @@ extern const struct attribute_group qeth_device_attr_group; extern const struct attribute_group qeth_device_blkt_group; extern const struct device_type qeth_generic_devtype; -int qeth_card_hw_is_reachable(struct qeth_card *); const char *qeth_get_cardname_short(struct qeth_card *); int qeth_realloc_buffer_pool(struct qeth_card *, int); int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 4dcb4f91b9c0..a44a4e0d2b19 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -74,13 +74,6 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf); static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); -int qeth_card_hw_is_reachable(struct qeth_card *card) -{ - return (card->state == CARD_STATE_SOFTSETUP) || - (card->state == CARD_STATE_UP); -} -EXPORT_SYMBOL_GPL(qeth_card_hw_is_reachable); - static void qeth_close_dev_handler(struct work_struct *work) { struct qeth_card *card; @@ -6206,7 +6199,6 @@ void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) stats->tx_bytes += queue->stats.tx_bytes; stats->tx_errors += queue->stats.tx_errors; stats->tx_dropped += queue->stats.tx_dropped; - stats->tx_carrier_errors += queue->stats.tx_carrier_errors; } } EXPORT_SYMBOL_GPL(qeth_get_stats64); @@ -6216,16 +6208,11 @@ int qeth_open(struct net_device *dev) struct qeth_card *card = dev->ml_priv; QETH_CARD_TEXT(card, 4, "qethopen"); - if (card->state == CARD_STATE_UP) - return 0; - if (card->state != CARD_STATE_SOFTSETUP) - return -ENODEV; if (qdio_stop_irq(CARD_DDEV(card), 0) < 0) return -EIO; card->data.state = CH_STATE_UP; - card->state = CARD_STATE_UP; netif_start_queue(dev); napi_enable(&card->napi); @@ -6243,10 +6230,7 @@ int qeth_stop(struct net_device *dev) QETH_CARD_TEXT(card, 4, "qethstop"); netif_tx_disable(dev); - if (card->state == CARD_STATE_UP) { - card->state = CARD_STATE_SOFTSETUP; - napi_disable(&card->napi); - } + napi_disable(&card->napi); return 0; } EXPORT_SYMBOL_GPL(qeth_stop); diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index fa575549d288..56deeb6f7bc0 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -29,11 +29,11 @@ static ssize_t qeth_dev_state_show(struct device *dev, case CARD_STATE_HARDSETUP: return sprintf(buf, "HARDSETUP\n"); case CARD_STATE_SOFTSETUP: + if (card->dev->flags & IFF_UP) + return sprintf(buf, "UP (LAN %s)\n", + netif_carrier_ok(card->dev) ? "ONLINE" : + "OFFLINE"); return sprintf(buf, "SOFTSETUP\n"); - case CARD_STATE_UP: - return sprintf(buf, "UP (LAN %s)\n", - netif_carrier_ok(card->dev) ? "ONLINE" : - "OFFLINE"); default: return sprintf(buf, "UNKNOWN\n"); } diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 6380d29c10f7..8efb2e8ff8f4 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -291,10 +291,7 @@ static void qeth_l2_stop_card(struct qeth_card *card) QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); qeth_set_allowed_threads(card, 0, 1); - if (card->read.state == CH_STATE_UP && - card->write.state == CH_STATE_UP && - card->state == CARD_STATE_UP) - card->state = CARD_STATE_SOFTSETUP; + if (card->state == CARD_STATE_SOFTSETUP) { qeth_l2_del_all_macs(card); qeth_clear_ipacmd_list(card); @@ -614,11 +611,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, queue = qeth_get_tx_queue(card, skb, ipv, cast_type); - if (card->state != CARD_STATE_UP) { - QETH_TXQ_STAT_INC(queue, tx_carrier_errors); - goto tx_drop; - } - netif_stop_queue(dev); if (IS_OSN(card)) @@ -636,7 +628,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } /* else fall through */ -tx_drop: QETH_TXQ_STAT_INC(queue, tx_dropped); QETH_TXQ_STAT_INC(queue, tx_errors); dev_kfree_skb_any(skb); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 375ad03ea4c5..7e68d9d16859 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1412,13 +1412,11 @@ static void qeth_l3_stop_card(struct qeth_card *card) QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); qeth_set_allowed_threads(card, 0, 1); + if (card->options.sniffer && (card->info.promisc_mode == SET_PROMISC_MODE_ON)) qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE); - if (card->read.state == CH_STATE_UP && - card->write.state == CH_STATE_UP && - card->state == CARD_STATE_UP) - card->state = CARD_STATE_SOFTSETUP; + if (card->state == CARD_STATE_SOFTSETUP) { qeth_l3_clear_ip_htable(card, 1); qeth_clear_ipacmd_list(card); @@ -2076,11 +2074,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, goto tx_drop; } - if (card->state != CARD_STATE_UP) { - QETH_TXQ_STAT_INC(queue, tx_carrier_errors); - goto tx_drop; - } - if (cast_type == RTN_BROADCAST && !card->info.broadcast_capable) goto tx_drop; -- cgit v1.2.3 From ebfcb23d62ab100f7ea0b97ed140175824ab2080 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Tue, 26 Feb 2019 15:42:22 +0200 Subject: enetc: Add ENETC PF level external MDIO support Each ENETC PF has its own MDIO interface, the corresponding MDIO registers are mapped in the ENETC's Port register block. The current patch adds a driver for these PF level MDIO buses, so that each PF can manage directly its own external link. Signed-off-by: Alex Marginean Signed-off-by: Claudiu Manoil Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/enetc/Makefile | 3 +- drivers/net/ethernet/freescale/enetc/enetc_mdio.c | 199 ++++++++++++++++++++++ drivers/net/ethernet/freescale/enetc/enetc_pf.c | 12 ++ drivers/net/ethernet/freescale/enetc/enetc_pf.h | 6 + 4 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_mdio.c (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile index 697660294dbc..7139e414dccf 100644 --- a/drivers/net/ethernet/freescale/enetc/Makefile +++ b/drivers/net/ethernet/freescale/enetc/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o -fsl-enetc-$(CONFIG_FSL_ENETC) += enetc.o enetc_cbdr.o enetc_ethtool.o +fsl-enetc-$(CONFIG_FSL_ENETC) += enetc.o enetc_cbdr.o enetc_ethtool.o \ + enetc_mdio.o fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o fsl-enetc-objs := enetc_pf.o $(fsl-enetc-y) diff --git a/drivers/net/ethernet/freescale/enetc/enetc_mdio.c b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c new file mode 100644 index 000000000000..77b9cd10ba2b --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc_mdio.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* Copyright 2019 NXP */ + +#include +#include +#include +#include + +#include "enetc_pf.h" + +struct enetc_mdio_regs { + u32 mdio_cfg; /* MDIO configuration and status */ + u32 mdio_ctl; /* MDIO control */ + u32 mdio_data; /* MDIO data */ + u32 mdio_addr; /* MDIO address */ +}; + +#define bus_to_enetc_regs(bus) (struct enetc_mdio_regs __iomem *)((bus)->priv) + +#define ENETC_MDIO_REG_OFFSET 0x1c00 +#define ENETC_MDC_DIV 258 + +#define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8) +#define MDIO_CFG_BSY BIT(0) +#define MDIO_CFG_RD_ER BIT(1) +#define MDIO_CFG_ENC45 BIT(6) + /* external MDIO only - driven on neg MDC edge */ +#define MDIO_CFG_NEG BIT(23) + +#define MDIO_CTL_DEV_ADDR(x) ((x) & 0x1f) +#define MDIO_CTL_PORT_ADDR(x) (((x) & 0x1f) << 5) +#define MDIO_CTL_READ BIT(15) +#define MDIO_DATA(x) ((x) & 0xffff) + +#define TIMEOUT 1000 +static int enetc_mdio_wait_complete(struct enetc_mdio_regs __iomem *regs) +{ + u32 val; + + return readx_poll_timeout(enetc_rd_reg, ®s->mdio_cfg, val, + !(val & MDIO_CFG_BSY), 10, 10 * TIMEOUT); +} + +static int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, + u16 value) +{ + struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus); + u32 mdio_ctl, mdio_cfg; + u16 dev_addr; + int ret; + + mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG; + if (regnum & MII_ADDR_C45) { + dev_addr = (regnum >> 16) & 0x1f; + mdio_cfg |= MDIO_CFG_ENC45; + } else { + /* clause 22 (ie 1G) */ + dev_addr = regnum & 0x1f; + mdio_cfg &= ~MDIO_CFG_ENC45; + } + + enetc_wr_reg(®s->mdio_cfg, mdio_cfg); + + ret = enetc_mdio_wait_complete(regs); + if (ret) + return ret; + + /* set port and dev addr */ + mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); + enetc_wr_reg(®s->mdio_ctl, mdio_ctl); + + /* set the register address */ + if (regnum & MII_ADDR_C45) { + enetc_wr_reg(®s->mdio_addr, regnum & 0xffff); + + ret = enetc_mdio_wait_complete(regs); + if (ret) + return ret; + } + + /* write the value */ + enetc_wr_reg(®s->mdio_data, MDIO_DATA(value)); + + ret = enetc_mdio_wait_complete(regs); + if (ret) + return ret; + + return 0; +} + +static int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum) +{ + struct enetc_mdio_regs __iomem *regs = bus_to_enetc_regs(bus); + u32 mdio_ctl, mdio_cfg; + u16 dev_addr, value; + int ret; + + mdio_cfg = MDIO_CFG_CLKDIV(ENETC_MDC_DIV) | MDIO_CFG_NEG; + if (regnum & MII_ADDR_C45) { + dev_addr = (regnum >> 16) & 0x1f; + mdio_cfg |= MDIO_CFG_ENC45; + } else { + dev_addr = regnum & 0x1f; + mdio_cfg &= ~MDIO_CFG_ENC45; + } + + enetc_wr_reg(®s->mdio_cfg, mdio_cfg); + + ret = enetc_mdio_wait_complete(regs); + if (ret) + return ret; + + /* set port and device addr */ + mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr); + enetc_wr_reg(®s->mdio_ctl, mdio_ctl); + + /* set the register address */ + if (regnum & MII_ADDR_C45) { + enetc_wr_reg(®s->mdio_addr, regnum & 0xffff); + + ret = enetc_mdio_wait_complete(regs); + if (ret) + return ret; + } + + /* initiate the read */ + enetc_wr_reg(®s->mdio_ctl, mdio_ctl | MDIO_CTL_READ); + + ret = enetc_mdio_wait_complete(regs); + if (ret) + return ret; + + /* return all Fs if nothing was there */ + if (enetc_rd_reg(®s->mdio_cfg) & MDIO_CFG_RD_ER) { + dev_dbg(&bus->dev, + "Error while reading PHY%d reg at %d.%hhu\n", + phy_id, dev_addr, regnum); + return 0xffff; + } + + value = enetc_rd_reg(®s->mdio_data) & 0xffff; + + return value; +} + +int enetc_mdio_probe(struct enetc_pf *pf) +{ + struct device *dev = &pf->si->pdev->dev; + struct enetc_mdio_regs __iomem *regs; + struct device_node *np; + struct mii_bus *bus; + int ret; + + bus = mdiobus_alloc_size(sizeof(regs)); + if (!bus) + return -ENOMEM; + + bus->name = "Freescale ENETC MDIO Bus"; + bus->read = enetc_mdio_read; + bus->write = enetc_mdio_write; + bus->parent = dev; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); + + /* store the enetc mdio base address for this bus */ + regs = pf->si->hw.port + ENETC_MDIO_REG_OFFSET; + bus->priv = regs; + + np = of_get_child_by_name(dev->of_node, "mdio"); + if (!np) { + dev_err(dev, "MDIO node missing\n"); + ret = -EINVAL; + goto err_registration; + } + + ret = of_mdiobus_register(bus, np); + if (ret) { + of_node_put(np); + dev_err(dev, "cannot register MDIO bus\n"); + goto err_registration; + } + + of_node_put(np); + pf->mdio = bus; + + return 0; + +err_registration: + mdiobus_free(bus); + + return ret; +} + +void enetc_mdio_remove(struct enetc_pf *pf) +{ + if (pf->mdio) { + mdiobus_unregister(pf->mdio); + mdiobus_free(pf->mdio); + } +} diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 7d28f5e9b46b..15876a6e7598 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -746,6 +746,7 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, static int enetc_of_get_phy(struct enetc_ndev_priv *priv) { + struct enetc_pf *pf = enetc_si_priv(priv->si); struct device_node *np = priv->dev->of_node; int err; @@ -770,12 +771,22 @@ static int enetc_of_get_phy(struct enetc_ndev_priv *priv) priv->phy_node = of_node_get(np); } + if (!of_phy_is_fixed_link(np)) { + err = enetc_mdio_probe(pf); + if (err) { + of_node_put(priv->phy_node); + return err; + } + } + priv->if_mode = of_get_phy_mode(np); if (priv->if_mode < 0) { dev_err(priv->dev, "missing phy type\n"); of_node_put(priv->phy_node); if (of_phy_is_fixed_link(np)) of_phy_deregister_fixed_link(np); + else + enetc_mdio_remove(pf); return -EINVAL; } @@ -898,6 +909,7 @@ static void enetc_pf_remove(struct pci_dev *pdev) unregister_netdev(si->ndev); + enetc_mdio_remove(pf); enetc_of_put_phy(priv); enetc_free_msix(priv); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h index 2061ae5ccba0..10dd1b53bb08 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h @@ -42,8 +42,14 @@ struct enetc_pf { char vlan_promisc_simap; /* bitmap of SIs in VLAN promisc mode */ DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE); DECLARE_BITMAP(active_vlans, VLAN_N_VID); + + struct mii_bus *mdio; /* saved for cleanup */ }; int enetc_msg_psi_init(struct enetc_pf *pf); void enetc_msg_psi_free(struct enetc_pf *pf); void enetc_msg_handle_rxmsg(struct enetc_pf *pf, int mbox_id, u16 *status); + +/* MDIO */ +int enetc_mdio_probe(struct enetc_pf *pf); +void enetc_mdio_remove(struct enetc_pf *pf); -- cgit v1.2.3 From 031b922bfd60c771588911112f8632783de08e5c Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Mon, 25 Feb 2019 17:43:03 +0100 Subject: net: marvell: neta: disable comphy when setting mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comphy driver for Armada 3700 by Miquèl Raynal (which is currently in linux-next) does not actually set comphy mode when phy_set_mode_ext is called. The mode is set at next call of phy_power_on. Update the driver to semantics similar to mvpp2: helper mvneta_comphy_init sets comphy mode and powers it on. When mode is to be changed in mvneta_mac_config, first power the comphy off, then call mvneta_comphy_init (which sets the mode to new one). Only do this when new mode is different from old mode. This should also work for Armada 38x, since in that comphy driver methods power_on and power_off are unimplemented. Signed-off-by: Marek Behún Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index ff275780040f..c0a3718b2e2a 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3149,11 +3149,26 @@ static int mvneta_setup_txqs(struct mvneta_port *pp) return 0; } +static int mvneta_comphy_init(struct mvneta_port *pp) +{ + int ret; + + if (!pp->comphy) + return 0; + + ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, + pp->phy_interface); + if (ret) + return ret; + + return phy_power_on(pp->comphy); +} + static void mvneta_start_dev(struct mvneta_port *pp) { int cpu; - WARN_ON(phy_power_on(pp->comphy)); + WARN_ON(mvneta_comphy_init(pp)); mvneta_max_rx_size_set(pp, pp->pkt_size); mvneta_txq_max_tx_size_set(pp, pp->pkt_size); @@ -3525,12 +3540,15 @@ static void mvneta_mac_config(struct net_device *ndev, unsigned int mode, if (state->speed == SPEED_2500) new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE; - if (pp->comphy && + if (pp->comphy && pp->phy_interface != state->interface && (state->interface == PHY_INTERFACE_MODE_SGMII || state->interface == PHY_INTERFACE_MODE_1000BASEX || - state->interface == PHY_INTERFACE_MODE_2500BASEX)) - WARN_ON(phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, - state->interface)); + state->interface == PHY_INTERFACE_MODE_2500BASEX)) { + pp->phy_interface = state->interface; + + WARN_ON(phy_power_off(pp->comphy)); + WARN_ON(mvneta_comphy_init(pp)); + } if (new_ctrl0 != gmac_ctrl0) mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); -- cgit v1.2.3 From 1e301a140763c75e9123411b3f7243522c2b6578 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 26 Feb 2019 20:19:29 -0800 Subject: nfp: report RJ45 connector in ethtool Add support for reporting twisted pair port type. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h | 1 + drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h index 246e213f1514..bd9c358c646f 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h @@ -49,6 +49,7 @@ enum nfp_eth_interface { NFP_INTERFACE_SFPP = 10, NFP_INTERFACE_SFP28 = 28, NFP_INTERFACE_QSFP = 40, + NFP_INTERFACE_RJ45 = 45, NFP_INTERFACE_CXP = 100, NFP_INTERFACE_QSFP28 = 112, }; diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c index f6f028fa5db9..311a5be25acb 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c @@ -206,6 +206,9 @@ nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry) if (entry->interface == NFP_INTERFACE_NONE) { entry->port_type = PORT_NONE; return; + } else if (entry->interface == NFP_INTERFACE_RJ45) { + entry->port_type = PORT_TP; + return; } if (entry->media == NFP_MEDIA_FIBRE) -- cgit v1.2.3 From 882cdcb5d3abb99926d474d24902636f87b583c1 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 26 Feb 2019 20:19:30 -0800 Subject: nfp: nsp: use fractional size of the buffer NSP expresses the buffer size in MB and 4 kB blocks. For small buffers the kB part may make a difference, so count it in. Signed-off-by: Jakub Kicinski Reviewed-by: Dirk van der Merwe Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c index a9d53df0070c..22208b03ff49 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c @@ -49,6 +49,7 @@ #define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0) #define NSP_DFLT_BUFFER_CONFIG 0x20 +#define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8) #define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0) #define NSP_MAGIC 0xab10 @@ -413,8 +414,8 @@ static int nfp_nsp_command(struct nfp_nsp *state, u16 code) static int nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) { + unsigned int def_size, max_size; struct nfp_cpp *cpp = nsp->cpp; - unsigned int max_size; u64 reg, cpp_buf; int ret, err; u32 cpp_id; @@ -433,11 +434,11 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) return err; max_size = max(arg->in_size, arg->out_size); - if (FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M < max_size) { - nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%llu < %u)\n", - arg->arg.code, - FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M, - max_size); + def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M + + FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K; + if (def_size < max_size) { + nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n", + arg->arg.code, def_size, max_size); return -EINVAL; } -- cgit v1.2.3 From 66487abe2f02fb7d7fa72c6002eacb13c54c5b6c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 26 Feb 2019 20:19:31 -0800 Subject: nfp: nsp: move default buffer handling into its own function DMA version of NSP communication is coming, move the code which copies data into the NFP buffer into a separate function. Signed-off-by: Jakub Kicinski Reviewed-by: Dirk van der Merwe Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c | 93 ++++++++++++---------- 1 file changed, 51 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c index 22208b03ff49..28262b0fc89a 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c @@ -122,16 +122,14 @@ struct nfp_nsp { * @code: NFP SP Command Code * @timeout_sec:Timeout value to wait for completion in seconds * @option: NFP SP Command Argument - * @buff_cpp: NFP SP Buffer CPP Address info - * @buff_addr: NFP SP Buffer Host address + * @buf: NFP SP Buffer Address * @error_cb: Callback for interpreting option if error occurred */ struct nfp_nsp_command_arg { u16 code; unsigned int timeout_sec; u32 option; - u32 buff_cpp; - u64 buff_addr; + u64 buf; void (*error_cb)(struct nfp_nsp *state, u32 ret_val); }; @@ -345,16 +343,7 @@ __nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg) if (err) return err; - if (!FIELD_FIT(NSP_BUFFER_CPP, arg->buff_cpp >> 8) || - !FIELD_FIT(NSP_BUFFER_ADDRESS, arg->buff_addr)) { - nfp_err(cpp, "Host buffer out of reach %08x %016llx\n", - arg->buff_cpp, arg->buff_addr); - return -EINVAL; - } - - err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, - FIELD_PREP(NSP_BUFFER_CPP, arg->buff_cpp >> 8) | - FIELD_PREP(NSP_BUFFER_ADDRESS, arg->buff_addr)); + err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf); if (err < 0) return err; @@ -412,36 +401,14 @@ static int nfp_nsp_command(struct nfp_nsp *state, u16 code) } static int -nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) +nfp_nsp_command_buf_def(struct nfp_nsp *nsp, + struct nfp_nsp_command_buf_arg *arg) { - unsigned int def_size, max_size; struct nfp_cpp *cpp = nsp->cpp; u64 reg, cpp_buf; - int ret, err; + int err, ret; u32 cpp_id; - if (nsp->ver.minor < 13) { - nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n", - arg->arg.code, nsp->ver.major, nsp->ver.minor); - return -EOPNOTSUPP; - } - - err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), - nfp_resource_address(nsp->res) + - NSP_DFLT_BUFFER_CONFIG, - ®); - if (err < 0) - return err; - - max_size = max(arg->in_size, arg->out_size); - def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M + - FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K; - if (def_size < max_size) { - nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n", - arg->arg.code, def_size, max_size); - return -EINVAL; - } - err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), nfp_resource_address(nsp->res) + NSP_DFLT_BUFFER, @@ -460,15 +427,21 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) } /* Zero out remaining part of the buffer */ if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size) { - memset(arg->out_buf, 0, arg->out_size - arg->in_size); err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size, arg->out_buf, arg->out_size - arg->in_size); if (err < 0) return err; } - arg->arg.buff_cpp = cpp_id; - arg->arg.buff_addr = cpp_buf; + if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) || + !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) { + nfp_err(cpp, "Buffer out of reach %08x %016llx\n", + cpp_id, cpp_buf); + return -EINVAL; + } + + arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) | + FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf); ret = __nfp_nsp_command(nsp, &arg->arg); if (ret < 0) return ret; @@ -483,6 +456,42 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) return ret; } +static int +nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) +{ + unsigned int def_size, max_size; + struct nfp_cpp *cpp = nsp->cpp; + u64 reg; + int err; + + if (nsp->ver.minor < 13) { + nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n", + arg->arg.code, nsp->ver.major, nsp->ver.minor); + return -EOPNOTSUPP; + } + + err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), + nfp_resource_address(nsp->res) + + NSP_DFLT_BUFFER_CONFIG, + ®); + if (err < 0) + return err; + + /* Zero out undefined part of the out buffer */ + if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size) + memset(arg->out_buf, 0, arg->out_size - arg->in_size); + + max_size = max(arg->in_size, arg->out_size); + def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M + + FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K; + if (def_size >= max_size) + return nfp_nsp_command_buf_def(nsp, arg); + + nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n", + arg->arg.code, def_size, max_size); + return -EINVAL; +} + int nfp_nsp_wait(struct nfp_nsp *state) { const unsigned long wait_until = jiffies + NFP_NSP_TIMEOUT_BOOT * HZ; -- cgit v1.2.3 From 345415138d15a42460edb42423c67644ec8bb4a1 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 26 Feb 2019 20:19:32 -0800 Subject: nfp: nsp: allow the use of DMA buffer Newer versions of NSP can access host memory. Simplest access type requires all data to be in one contiguous area. Since we don't have the guarantee on where callers of the NSP ABI will allocate their buffers we allocate a bounce buffer and copy the data in and out. Signed-off-by: Jakub Kicinski Reviewed-by: Dirk van der Merwe Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c | 196 ++++++++++++++++++++- 1 file changed, 191 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c index 28262b0fc89a..dd6256841a37 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,7 @@ #define NSP_COMMAND 0x08 #define NSP_COMMAND_OPTION GENMASK_ULL(63, 32) #define NSP_COMMAND_CODE GENMASK_ULL(31, 16) +#define NSP_COMMAND_DMA_BUF BIT_ULL(1) #define NSP_COMMAND_START BIT_ULL(0) /* CPP address to retrieve the data from */ @@ -49,9 +51,12 @@ #define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0) #define NSP_DFLT_BUFFER_CONFIG 0x20 +#define NSP_DFLT_BUFFER_DMA_CHUNK_ORDER GENMASK_ULL(63, 58) #define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8) #define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0) +#define NFP_CAP_CMD_DMA_SG 0x28 + #define NSP_MAGIC 0xab10 #define NSP_MAJOR 0 #define NSP_MINOR 8 @@ -92,6 +97,16 @@ enum nfp_nsp_cmd { SPCODE_VERSIONS = 21, /* Report FW versions */ }; +struct nfp_nsp_dma_buf { + __le32 chunk_cnt; + __le32 reserved[3]; + struct { + __le32 size; + __le32 reserved; + __le64 addr; + } descs[]; +}; + static const struct { int code; const char *msg; @@ -120,6 +135,7 @@ struct nfp_nsp { /** * struct nfp_nsp_command_arg - NFP command argument structure * @code: NFP SP Command Code + * @dma: @buf points to a host buffer, not NSP buffer * @timeout_sec:Timeout value to wait for completion in seconds * @option: NFP SP Command Argument * @buf: NFP SP Buffer Address @@ -127,6 +143,7 @@ struct nfp_nsp { */ struct nfp_nsp_command_arg { u16 code; + bool dma; unsigned int timeout_sec; u32 option; u64 buf; @@ -350,6 +367,7 @@ __nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg) err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command, FIELD_PREP(NSP_COMMAND_OPTION, arg->option) | FIELD_PREP(NSP_COMMAND_CODE, arg->code) | + FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) | FIELD_PREP(NSP_COMMAND_START, 1)); if (err < 0) return err; @@ -456,10 +474,174 @@ nfp_nsp_command_buf_def(struct nfp_nsp *nsp, return ret; } +static int +nfp_nsp_command_buf_dma_sg(struct nfp_nsp *nsp, + struct nfp_nsp_command_buf_arg *arg, + unsigned int max_size, unsigned int chunk_order, + unsigned int dma_order) +{ + struct nfp_cpp *cpp = nsp->cpp; + struct nfp_nsp_dma_buf *desc; + struct { + dma_addr_t dma_addr; + unsigned long len; + void *chunk; + } *chunks; + size_t chunk_size, dma_size; + dma_addr_t dma_desc; + struct device *dev; + unsigned long off; + int i, ret, nseg; + size_t desc_sz; + + chunk_size = BIT_ULL(chunk_order); + dma_size = BIT_ULL(dma_order); + nseg = DIV_ROUND_UP(max_size, chunk_size); + + chunks = kzalloc(array_size(sizeof(*chunks), nseg), GFP_KERNEL); + if (!chunks) + return -ENOMEM; + + off = 0; + ret = -ENOMEM; + for (i = 0; i < nseg; i++) { + unsigned long coff; + + chunks[i].chunk = kmalloc(chunk_size, + GFP_KERNEL | __GFP_NOWARN); + if (!chunks[i].chunk) + goto exit_free_prev; + + chunks[i].len = min_t(u64, chunk_size, max_size - off); + + coff = 0; + if (arg->in_size > off) { + coff = min_t(u64, arg->in_size - off, chunk_size); + memcpy(chunks[i].chunk, arg->in_buf + off, coff); + } + memset(chunks[i].chunk + coff, 0, chunk_size - coff); + + off += chunks[i].len; + } + + dev = nfp_cpp_device(cpp)->parent; + + for (i = 0; i < nseg; i++) { + dma_addr_t addr; + + addr = dma_map_single(dev, chunks[i].chunk, chunks[i].len, + DMA_BIDIRECTIONAL); + chunks[i].dma_addr = addr; + + ret = dma_mapping_error(dev, addr); + if (ret) + goto exit_unmap_prev; + + if (WARN_ONCE(round_down(addr, dma_size) != + round_down(addr + chunks[i].len - 1, dma_size), + "unaligned DMA address: %pad %lu %zd\n", + &addr, chunks[i].len, dma_size)) { + ret = -EFAULT; + i++; + goto exit_unmap_prev; + } + } + + desc_sz = struct_size(desc, descs, nseg); + desc = kmalloc(desc_sz, GFP_KERNEL); + if (!desc) { + ret = -ENOMEM; + goto exit_unmap_all; + } + + desc->chunk_cnt = cpu_to_le32(nseg); + for (i = 0; i < nseg; i++) { + desc->descs[i].size = cpu_to_le32(chunks[i].len); + desc->descs[i].addr = cpu_to_le64(chunks[i].dma_addr); + } + + dma_desc = dma_map_single(dev, desc, desc_sz, DMA_TO_DEVICE); + ret = dma_mapping_error(dev, dma_desc); + if (ret) + goto exit_free_desc; + + arg->arg.dma = true; + arg->arg.buf = dma_desc; + ret = __nfp_nsp_command(nsp, &arg->arg); + if (ret < 0) + goto exit_unmap_desc; + + i = 0; + off = 0; + while (off < arg->out_size) { + unsigned int len; + + len = min_t(u64, chunks[i].len, arg->out_size - off); + memcpy(arg->out_buf + off, chunks[i].chunk, len); + off += len; + i++; + } + +exit_unmap_desc: + dma_unmap_single(dev, dma_desc, desc_sz, DMA_TO_DEVICE); +exit_free_desc: + kfree(desc); +exit_unmap_all: + i = nseg; +exit_unmap_prev: + while (--i >= 0) + dma_unmap_single(dev, chunks[i].dma_addr, chunks[i].len, + DMA_BIDIRECTIONAL); + i = nseg; +exit_free_prev: + while (--i >= 0) + kfree(chunks[i].chunk); + kfree(chunks); + if (ret < 0) + nfp_err(cpp, "NSP: SG DMA failed for command 0x%04x: %d (sz:%d cord:%d)\n", + arg->arg.code, ret, max_size, chunk_order); + return ret; +} + +static int +nfp_nsp_command_buf_dma(struct nfp_nsp *nsp, + struct nfp_nsp_command_buf_arg *arg, + unsigned int max_size, unsigned int dma_order) +{ + unsigned int chunk_order, buf_order; + struct nfp_cpp *cpp = nsp->cpp; + bool sg_ok; + u64 reg; + int err; + + buf_order = order_base_2(roundup_pow_of_two(max_size)); + + err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), + nfp_resource_address(nsp->res) + NFP_CAP_CMD_DMA_SG, + ®); + if (err < 0) + return err; + sg_ok = reg & BIT_ULL(arg->arg.code - 1); + + if (!sg_ok) { + if (buf_order > dma_order) { + nfp_err(cpp, "NSP: can't service non-SG DMA for command 0x%04x\n", + arg->arg.code); + return -ENOMEM; + } + chunk_order = buf_order; + } else { + chunk_order = min_t(unsigned int, dma_order, PAGE_SHIFT); + } + + return nfp_nsp_command_buf_dma_sg(nsp, arg, max_size, chunk_order, + dma_order); +} + static int nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) { - unsigned int def_size, max_size; + unsigned int dma_order, def_size, max_size; struct nfp_cpp *cpp = nsp->cpp; u64 reg; int err; @@ -484,12 +666,16 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) max_size = max(arg->in_size, arg->out_size); def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M + FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K; - if (def_size >= max_size) + dma_order = FIELD_GET(NSP_DFLT_BUFFER_DMA_CHUNK_ORDER, reg); + if (def_size >= max_size) { return nfp_nsp_command_buf_def(nsp, arg); + } else if (!dma_order) { + nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n", + arg->arg.code, def_size, max_size); + return -EINVAL; + } - nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n", - arg->arg.code, def_size, max_size); - return -EINVAL; + return nfp_nsp_command_buf_dma(nsp, arg, max_size, dma_order); } int nfp_nsp_wait(struct nfp_nsp *state) -- cgit v1.2.3 From 35697764d7315ffce01c6eddf7b079daa16bc248 Mon Sep 17 00:00:00 2001 From: Dirk van der Merwe Date: Tue, 26 Feb 2019 20:19:33 -0800 Subject: nfp: nsp: set higher timeout for flash bundle The management firmware now supports being passed a bundle with multiple components to be stored in flash at once. This makes it easier to update all components to a known state with a single user command, however, this also has the potential to increase the time required to perform the update significantly. The management firmware only updates the components out of a bundle which are outdated, however, we need to make sure we can handle the absolute worst case where a CPLD update can take a long time to perform. We set a very conservative total timeout of 900s which already adds a contingency. Signed-off-by: Dirk van der Merwe Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c index dd6256841a37..3a4e224a64b7 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c @@ -799,10 +799,7 @@ int nfp_nsp_write_flash(struct nfp_nsp *state, const struct firmware *fw) { .code = SPCODE_NSP_WRITE_FLASH, .option = fw->size, - /* The flash time is specified to take a maximum of 70s - * so we add an additional factor to this spec time. - */ - .timeout_sec = 2.5 * 70, + .timeout_sec = 900, }, .in_buf = fw->data, .in_size = fw->size, -- cgit v1.2.3 From 6bdbc1cb6cf084474b44a1dcb6d44cf48d6a42dc Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Sun, 24 Feb 2019 10:31:02 +0200 Subject: net/mlx5e: Declare mlx5e_tx_reporter_recover_from_ctx as static Function mlx5e_tx_reporter_recover_from_ctx is only used within mlx5e tx reporter, move it to be statically declared in en/reporter_tx.c. Fixes: de8650a82071 ("net/mlx5e: Add tx reporter support") Signed-off-by: Eran Ben Elisha Reported-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 75dad8797720..9d38e62cdf24 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -179,7 +179,7 @@ int mlx5e_tx_reporter_timeout(struct mlx5e_txqsq *sq) /* state lock cannot be grabbed within this function. * It can cause a dead lock or a read-after-free. */ -int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_tx_err_ctx *err_ctx) +static int mlx5e_tx_reporter_recover_from_ctx(struct mlx5e_tx_err_ctx *err_ctx) { return err_ctx->recover(err_ctx->sq); } -- cgit v1.2.3 From 733d4f367c34c971ce2d4f466d71ae5a189cbe5f Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Thu, 21 Feb 2019 19:34:15 +0200 Subject: net/mlx5e: Cleanup attach encap function Remove the tunnel info argument which we can get from the other args. Also reorder the args to have input args first and output args later. This patch doesn't change functionality. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 31 ++++++++++++++----------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index b38986e18dd7..7a363e44ec45 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -850,12 +850,11 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, int out_index); static int mlx5e_attach_encap(struct mlx5e_priv *priv, - struct ip_tunnel_info *tun_info, - struct net_device *mirred_dev, - struct net_device **encap_dev, struct mlx5e_tc_flow *flow, + struct net_device *mirred_dev, + int out_index, struct netlink_ext_ack *extack, - int out_index); + struct net_device **encap_dev); static struct mlx5_flow_handle * mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw, @@ -970,10 +969,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, mirred_ifindex = parse_attr->mirred_ifindex[out_index]; out_dev = __dev_get_by_index(dev_net(priv->netdev), mirred_ifindex); - err = mlx5e_attach_encap(priv, - &parse_attr->tun_info[out_index], - out_dev, &encap_dev, flow, - extack, out_index); + err = mlx5e_attach_encap(priv, flow, out_dev, out_index, + extack, &encap_dev); if (err && err != -EAGAIN) goto err_attach_encap; if (err == -EAGAIN) @@ -2342,22 +2339,28 @@ static bool is_merged_eswitch_dev(struct mlx5e_priv *priv, static int mlx5e_attach_encap(struct mlx5e_priv *priv, - struct ip_tunnel_info *tun_info, - struct net_device *mirred_dev, - struct net_device **encap_dev, struct mlx5e_tc_flow *flow, + struct net_device *mirred_dev, + int out_index, struct netlink_ext_ack *extack, - int out_index) + struct net_device **encap_dev) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; - unsigned short family = ip_tunnel_info_af(tun_info); struct mlx5_esw_flow_attr *attr = flow->esw_attr; - struct ip_tunnel_key *key = &tun_info->key; + struct mlx5e_tc_flow_parse_attr *parse_attr; + struct ip_tunnel_info *tun_info; + struct ip_tunnel_key *key; struct mlx5e_encap_entry *e; + unsigned short family; uintptr_t hash_key; bool found = false; int err = 0; + parse_attr = attr->parse_attr; + tun_info = &parse_attr->tun_info[out_index]; + family = ip_tunnel_info_af(tun_info); + key = &tun_info->key; + hash_key = hash_encap_info(key); hash_for_each_possible_rcu(esw->offloads.encap_tbl, e, -- cgit v1.2.3 From 0ad060ee9c8fcf15aa9aa03965276a278247f87e Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 12 Feb 2019 14:05:56 +0200 Subject: net/mlx5e: Don't make internal use of errno to denote missing neigh EAGAIN is treated as a specific case when we consider the attachment successful but wait for neigh event before offloading the flow. This can result in unwanted behavior when sub calls on the offloading path will return EAGAIN and we pass this error up. Instead of attaching to a specific error code return a boolean value from the attach encap operation saying if the encap is valid or not. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 8 +++++-- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 28 ++++++++++++---------- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index bdcc5e79328d..03e5d0d8fd8f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -295,7 +295,9 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv, if (!(nud_state & NUD_VALID)) { neigh_event_send(n, NULL); - err = -EAGAIN; + /* the encap entry will be made valid on neigh update event + * and not used before that. + */ goto out; } @@ -408,7 +410,9 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv, if (!(nud_state & NUD_VALID)) { neigh_event_send(n, NULL); - err = -EAGAIN; + /* the encap entry will be made valid on neigh update event + * and not used before that. + */ goto out; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 7a363e44ec45..ea39083b1596 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -854,7 +854,8 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, struct net_device *mirred_dev, int out_index, struct netlink_ext_ack *extack, - struct net_device **encap_dev); + struct net_device **encap_dev, + bool *encap_valid); static struct mlx5_flow_handle * mlx5e_tc_offload_fdb_rules(struct mlx5_eswitch *esw, @@ -940,7 +941,8 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, struct mlx5_fc *counter = NULL; struct mlx5e_rep_priv *rpriv; struct mlx5e_priv *out_priv; - int err = 0, encap_err = 0; + bool encap_valid = true; + int err = 0; int out_index; if (!mlx5_eswitch_prios_supported(esw) && attr->prio != 1) { @@ -970,11 +972,10 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, out_dev = __dev_get_by_index(dev_net(priv->netdev), mirred_ifindex); err = mlx5e_attach_encap(priv, flow, out_dev, out_index, - extack, &encap_dev); - if (err && err != -EAGAIN) + extack, &encap_dev, &encap_valid); + if (err) goto err_attach_encap; - if (err == -EAGAIN) - encap_err = err; + out_priv = netdev_priv(encap_dev); rpriv = out_priv->ppriv; attr->dests[out_index].rep = rpriv->rep; @@ -1002,10 +1003,11 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, attr->counter = counter; } - /* we get here if (1) there's no error or when - * (2) there's an encap action and we're on -EAGAIN (no valid neigh) + /* we get here if one of the following takes place: + * (1) there's no error + * (2) there's an encap action and we don't have valid neigh */ - if (encap_err == -EAGAIN) { + if (!encap_valid) { /* continue with goto slow path rule instead */ struct mlx5_esw_flow_attr slow_attr; @@ -2343,7 +2345,8 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, struct net_device *mirred_dev, int out_index, struct netlink_ext_ack *extack, - struct net_device **encap_dev) + struct net_device **encap_dev, + bool *encap_valid) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr *attr = flow->esw_attr; @@ -2391,7 +2394,7 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv, else if (family == AF_INET6) err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e); - if (err && err != -EAGAIN) + if (err) goto out_err; hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key); @@ -2403,8 +2406,9 @@ attach_flow: if (e->flags & MLX5_ENCAP_ENTRY_VALID) { attr->dests[out_index].encap_id = e->encap_id; attr->dests[out_index].flags |= MLX5_ESW_DEST_ENCAP_VALID; + *encap_valid = true; } else { - err = -EAGAIN; + *encap_valid = false; } return err; -- cgit v1.2.3 From bb19ad0d8d493e20f6abe615c5e5d00daa9735d7 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Wed, 27 Feb 2019 09:58:26 +0200 Subject: net/mlx5: Use unsigned int bit instead of bool as a struct member This fix checkpatch check CHECK: Avoid using bool structure members because of possible alignment issues Signed-off-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/lag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index 04c5aca7f8c5..44ce4c36485f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c @@ -52,7 +52,7 @@ struct lag_func { struct lag_tracker { enum netdev_lag_tx_type tx_type; struct netdev_lag_lower_state_info netdev_state[MLX5_MAX_PORTS]; - bool is_bonded; + unsigned int is_bonded:1; }; /* LAG data of a ConnectX card. -- cgit v1.2.3 From 10a193ed78adc6667684981697b050c27a3e42db Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Sun, 10 Feb 2019 10:12:28 +0200 Subject: net/mlx5: Expose lag operations in header file The change is a refactoring step towards a multipath use case. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/lag.c | 56 ++++--------------------- drivers/net/ethernet/mellanox/mlx5/core/lag.h | 60 +++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 48 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lag.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index 44ce4c36485f..3b0f7cf822d5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c @@ -35,37 +35,7 @@ #include #include "mlx5_core.h" #include "eswitch.h" - -enum { - MLX5_LAG_FLAG_ROCE = 1 << 0, - MLX5_LAG_FLAG_SRIOV = 1 << 1, -}; - -#define MLX5_LAG_MODE_FLAGS (MLX5_LAG_FLAG_ROCE | MLX5_LAG_FLAG_SRIOV) - -struct lag_func { - struct mlx5_core_dev *dev; - struct net_device *netdev; -}; - -/* Used for collection of netdev event info. */ -struct lag_tracker { - enum netdev_lag_tx_type tx_type; - struct netdev_lag_lower_state_info netdev_state[MLX5_MAX_PORTS]; - unsigned int is_bonded:1; -}; - -/* LAG data of a ConnectX card. - * It serves both its phys functions. - */ -struct mlx5_lag { - u8 flags; - u8 v2p_map[MLX5_MAX_PORTS]; - struct lag_func pf[MLX5_MAX_PORTS]; - struct lag_tracker tracker; - struct delayed_work bond_work; - struct notifier_block nb; -}; +#include "lag.h" /* General purpose, use for short periods of time. * Beware of lock dependencies (preferably, no locks should be acquired @@ -147,13 +117,8 @@ static int mlx5_cmd_query_cong_counter(struct mlx5_core_dev *dev, return mlx5_cmd_exec(dev, in, sizeof(in), out, out_size); } -static struct mlx5_lag *mlx5_lag_dev_get(struct mlx5_core_dev *dev) -{ - return dev->priv.lag; -} - -static int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, - struct net_device *ndev) +int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, + struct net_device *ndev) { int i; @@ -174,11 +139,6 @@ static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev) return !!(ldev->flags & MLX5_LAG_FLAG_SRIOV); } -static bool __mlx5_lag_is_active(struct mlx5_lag *ldev) -{ - return !!(ldev->flags & MLX5_LAG_MODE_FLAGS); -} - static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker, u8 *port1, u8 *port2) { @@ -195,8 +155,8 @@ static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker, *port2 = 1; } -static void mlx5_modify_lag(struct mlx5_lag *ldev, - struct lag_tracker *tracker) +void mlx5_modify_lag(struct mlx5_lag *ldev, + struct lag_tracker *tracker) { struct mlx5_core_dev *dev0 = ldev->pf[0].dev; u8 v2p_port1, v2p_port2; @@ -241,9 +201,9 @@ static int mlx5_create_lag(struct mlx5_lag *ldev, return err; } -static int mlx5_activate_lag(struct mlx5_lag *ldev, - struct lag_tracker *tracker, - u8 flags) +int mlx5_activate_lag(struct mlx5_lag *ldev, + struct lag_tracker *tracker, + u8 flags) { bool roce_lag = !!(flags & MLX5_LAG_FLAG_ROCE); struct mlx5_core_dev *dev0 = ldev->pf[0].dev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag.h new file mode 100644 index 000000000000..a6637016c1ab --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef __MLX5_LAG_H__ +#define __MLX5_LAG_H__ + +#include "mlx5_core.h" + +enum { + MLX5_LAG_FLAG_ROCE = 1 << 0, + MLX5_LAG_FLAG_SRIOV = 1 << 1, +}; + +#define MLX5_LAG_MODE_FLAGS (MLX5_LAG_FLAG_ROCE | MLX5_LAG_FLAG_SRIOV) + +struct lag_func { + struct mlx5_core_dev *dev; + struct net_device *netdev; +}; + +/* Used for collection of netdev event info. */ +struct lag_tracker { + enum netdev_lag_tx_type tx_type; + struct netdev_lag_lower_state_info netdev_state[MLX5_MAX_PORTS]; + unsigned int is_bonded:1; +}; + +/* LAG data of a ConnectX card. + * It serves both its phys functions. + */ +struct mlx5_lag { + u8 flags; + u8 v2p_map[MLX5_MAX_PORTS]; + struct lag_func pf[MLX5_MAX_PORTS]; + struct lag_tracker tracker; + struct delayed_work bond_work; + struct notifier_block nb; +}; + +static inline struct mlx5_lag * +mlx5_lag_dev_get(struct mlx5_core_dev *dev) +{ + return dev->priv.lag; +} + +static inline bool +__mlx5_lag_is_active(struct mlx5_lag *ldev) +{ + return !!(ldev->flags & MLX5_LAG_MODE_FLAGS); +} + +void mlx5_modify_lag(struct mlx5_lag *ldev, + struct lag_tracker *tracker); +int mlx5_activate_lag(struct mlx5_lag *ldev, + struct lag_tracker *tracker, + u8 flags); +int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, + struct net_device *ndev); + +#endif /* __MLX5_LAG_H__ */ -- cgit v1.2.3 From e6ee5e7166275073c66245043c70ec5dc819a956 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Mon, 25 Feb 2019 10:09:05 +0200 Subject: net/mlx5: Use own workqueue for lag netdev events processing Instead of using the system workqueue, allocate our own workqueue. This workqueue will be used to handle more work in the next patch. This patch doesn't change functionality. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/lag.c | 9 ++++++++- drivers/net/ethernet/mellanox/mlx5/core/lag.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index 3b0f7cf822d5..eff5c54818b7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c @@ -346,7 +346,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay) { - schedule_delayed_work(&ldev->bond_work, delay); + queue_delayed_work(ldev->wq, &ldev->bond_work, delay); } static void mlx5_do_bond_work(struct work_struct *work) @@ -498,6 +498,12 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(void) if (!ldev) return NULL; + ldev->wq = create_singlethread_workqueue("mlx5_lag"); + if (!ldev->wq) { + kfree(ldev); + return NULL; + } + INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work); return ldev; @@ -505,6 +511,7 @@ static struct mlx5_lag *mlx5_lag_dev_alloc(void) static void mlx5_lag_dev_free(struct mlx5_lag *ldev) { + destroy_workqueue(ldev->wq); kfree(ldev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag.h index a6637016c1ab..58f93d411ad5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.h @@ -33,6 +33,7 @@ struct mlx5_lag { u8 v2p_map[MLX5_MAX_PORTS]; struct lag_func pf[MLX5_MAX_PORTS]; struct lag_tracker tracker; + struct workqueue_struct *wq; struct delayed_work bond_work; struct notifier_block nb; }; -- cgit v1.2.3 From 724b509ca02367dbd5f5f90b0c8546280c5abc72 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Thu, 21 Feb 2019 18:24:48 +0200 Subject: net/mlx5: Add multipath mode In order to offload ecmp-on-host scheme where next-hop routes are used, we will make use of HW LAG. Add accessor function to let upper layers in the driver to realize if the lag acts in multi-path mode. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +- drivers/net/ethernet/mellanox/mlx5/core/lag.h | 4 +++- drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c | 23 +++++++++++++++++++++++ include/linux/mlx5/driver.h | 1 + 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 17f1a8b28c0a..1a16f6d73cbc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -30,7 +30,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ mlx5_core-$(CONFIG_MLX5_EN_ARFS) += en_arfs.o mlx5_core-$(CONFIG_MLX5_EN_RXNFC) += en_fs_ethtool.o mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o en/port_buffer.o -mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o lib/port_tun.o +mlx5_core-$(CONFIG_MLX5_ESWITCH) += en_rep.o en_tc.o en/tc_tun.o lib/port_tun.o lag_mp.o # # Core extra diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag.h index 58f93d411ad5..f8bea6ed4285 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.h @@ -9,9 +9,11 @@ enum { MLX5_LAG_FLAG_ROCE = 1 << 0, MLX5_LAG_FLAG_SRIOV = 1 << 1, + MLX5_LAG_FLAG_MULTIPATH = 1 << 2, }; -#define MLX5_LAG_MODE_FLAGS (MLX5_LAG_FLAG_ROCE | MLX5_LAG_FLAG_SRIOV) +#define MLX5_LAG_MODE_FLAGS (MLX5_LAG_FLAG_ROCE | MLX5_LAG_FLAG_SRIOV |\ + MLX5_LAG_FLAG_MULTIPATH) struct lag_func { struct mlx5_core_dev *dev; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c new file mode 100644 index 000000000000..2d2861cd4e02 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* Copyright (c) 2019 Mellanox Technologies. */ + +#include +#include "lag.h" +#include "mlx5_core.h" +#include "eswitch.h" + +static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev) +{ + return !!(ldev->flags & MLX5_LAG_FLAG_MULTIPATH); +} + +bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev) +{ + struct mlx5_lag *ldev; + bool res; + + ldev = mlx5_lag_dev_get(dev); + res = ldev && __mlx5_lag_is_multipath(ldev); + + return res; +} diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index c2de50f02b33..ee109b3fbfb8 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -1041,6 +1041,7 @@ int mlx5_cmd_create_vport_lag(struct mlx5_core_dev *dev); int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev); bool mlx5_lag_is_roce(struct mlx5_core_dev *dev); bool mlx5_lag_is_sriov(struct mlx5_core_dev *dev); +bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev); bool mlx5_lag_is_active(struct mlx5_core_dev *dev); struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev); int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, -- cgit v1.2.3 From 544fe7c2e654124870e774157d99da357dce22dc Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Sun, 17 Feb 2019 11:54:06 +0200 Subject: net/mlx5e: Activate HW multipath and handle port affinity based on FIB events To support multipath offload we are going to track SW multipath route and related nexthops. To do that we register to FIB notifier and handle the route and next-hops events and reflect that as port affinity to HW. When there is a new multipath route entry that all next-hops are the ports of an HCA we will activate LAG in HW. Egress wise, we use HW LAG as the means to emulate multipath on current HW which doesn't support port selection based on xmit hash. In the presence of multiple VFs which use multiple SQs (send queues) this yields fairly good distribution. HA wise, HW LAG buys us the ability for a given RQ (receive queue) to receive traffic from both ports and for SQs to migrate xmitting over the active port if their base port fails. When the route entry is being updated to single path we will update the HW port affinity to use that port only. If a next-hop becomes dead we update the HW port affinity to the living port. When all next-hops are alive again we reset the affinity to default. Due to FW/HW limitations, when a route is deleted we are not disabling the HW LAG since doing so will not allow us to enable it again while VFs are bounded. Typically this is just a temporary state when a routing daemon removes dead routes and later adds them back as needed. This patch only handles events for AF_INET. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 7 + drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 2 + drivers/net/ethernet/mellanox/mlx5/core/lag.c | 8 + drivers/net/ethernet/mellanox/mlx5/core/lag.h | 2 + drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c | 281 ++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h | 26 ++ 6 files changed, 326 insertions(+) create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 84200d93cf9d..d0b28251abf2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -2476,3 +2476,10 @@ bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1) return false; } + +bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0, + struct mlx5_core_dev *dev1) +{ + return (dev0->priv.eswitch->mode == SRIOV_OFFLOADS && + dev1->priv.eswitch->mode == SRIOV_OFFLOADS); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 5f82e637410b..3f3cd32ae60a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -371,6 +371,8 @@ static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1); +bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0, + struct mlx5_core_dev *dev1); #define MLX5_DEBUG_ESWITCH_MASK BIT(3) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index eff5c54818b7..48aa6e030bcf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c @@ -36,6 +36,7 @@ #include "mlx5_core.h" #include "eswitch.h" #include "lag.h" +#include "lag_mp.h" /* General purpose, use for short periods of time. * Beware of lock dependencies (preferably, no locks should be acquired @@ -559,6 +560,7 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev) { struct mlx5_lag *ldev = NULL; struct mlx5_core_dev *tmp_dev; + int err; if (!MLX5_CAP_GEN(dev, vport_group_manager) || !MLX5_CAP_GEN(dev, lag_master) || @@ -586,6 +588,11 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev) mlx5_core_err(dev, "Failed to register LAG netdev notifier\n"); } } + + err = mlx5_lag_mp_init(ldev); + if (err) + mlx5_core_err(dev, "Failed to init multipath lag err=%d\n", + err); } int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num) @@ -631,6 +638,7 @@ void mlx5_lag_remove(struct mlx5_core_dev *dev) if (i == MLX5_MAX_PORTS) { if (ldev->nb.notifier_call) unregister_netdevice_notifier(&ldev->nb); + mlx5_lag_mp_cleanup(ldev); cancel_delayed_work_sync(&ldev->bond_work); mlx5_lag_dev_free(ldev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag.h index f8bea6ed4285..1dea0b1c9826 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.h @@ -5,6 +5,7 @@ #define __MLX5_LAG_H__ #include "mlx5_core.h" +#include "lag_mp.h" enum { MLX5_LAG_FLAG_ROCE = 1 << 0, @@ -38,6 +39,7 @@ struct mlx5_lag { struct workqueue_struct *wq; struct delayed_work bond_work; struct notifier_block nb; + struct lag_mp lag_mp; }; static inline struct mlx5_lag * diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c index 2d2861cd4e02..5680beba8c07 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c @@ -3,9 +3,18 @@ #include #include "lag.h" +#include "lag_mp.h" #include "mlx5_core.h" #include "eswitch.h" +static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) +{ + if (!ldev->pf[0].dev || !ldev->pf[1].dev) + return false; + + return mlx5_esw_multipath_prereq(ldev->pf[0].dev, ldev->pf[1].dev); +} + static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev) { return !!(ldev->flags & MLX5_LAG_FLAG_MULTIPATH); @@ -21,3 +30,275 @@ bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev) return res; } + +/** + * Set lag port affinity + * + * @ldev: lag device + * @port: + * 0 - set normal affinity. + * 1 - set affinity to port 1. + * 2 - set affinity to port 2. + * + **/ +static void mlx5_lag_set_port_affinity(struct mlx5_lag *ldev, int port) +{ + struct lag_tracker tracker; + + if (!__mlx5_lag_is_multipath(ldev)) + return; + + switch (port) { + case 0: + tracker.netdev_state[0].tx_enabled = true; + tracker.netdev_state[1].tx_enabled = true; + tracker.netdev_state[0].link_up = true; + tracker.netdev_state[1].link_up = true; + break; + case 1: + tracker.netdev_state[0].tx_enabled = true; + tracker.netdev_state[0].link_up = true; + tracker.netdev_state[1].tx_enabled = false; + tracker.netdev_state[1].link_up = false; + break; + case 2: + tracker.netdev_state[0].tx_enabled = false; + tracker.netdev_state[0].link_up = false; + tracker.netdev_state[1].tx_enabled = true; + tracker.netdev_state[1].link_up = true; + break; + default: + mlx5_core_warn(ldev->pf[0].dev, "Invalid affinity port %d", + port); + return; + } + + mlx5_modify_lag(ldev, &tracker); +} + +static void mlx5_lag_fib_event_flush(struct notifier_block *nb) +{ + struct lag_mp *mp = container_of(nb, struct lag_mp, fib_nb); + struct mlx5_lag *ldev = container_of(mp, struct mlx5_lag, lag_mp); + + flush_workqueue(ldev->wq); +} + +struct mlx5_fib_event_work { + struct work_struct work; + struct mlx5_lag *ldev; + unsigned long event; + union { + struct fib_entry_notifier_info fen_info; + struct fib_nh_notifier_info fnh_info; + }; +}; + +static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, + unsigned long event, + struct fib_info *fi) +{ + struct lag_mp *mp = &ldev->lag_mp; + + /* Handle delete event */ + if (event == FIB_EVENT_ENTRY_DEL) { + /* stop track */ + if (mp->mfi == fi) + mp->mfi = NULL; + return; + } + + /* Handle add/replace event */ + if (fi->fib_nhs == 1) { + if (__mlx5_lag_is_active(ldev)) { + struct net_device *nh_dev = fi->fib_nh[0].nh_dev; + int i = mlx5_lag_dev_get_netdev_idx(ldev, nh_dev); + + mlx5_lag_set_port_affinity(ldev, ++i); + } + return; + } + + if (fi->fib_nhs != 2) + return; + + /* Verify next hops are ports of the same hca */ + if (!(fi->fib_nh[0].nh_dev == ldev->pf[0].netdev && + fi->fib_nh[1].nh_dev == ldev->pf[1].netdev) && + !(fi->fib_nh[0].nh_dev == ldev->pf[1].netdev && + fi->fib_nh[1].nh_dev == ldev->pf[0].netdev)) { + mlx5_core_warn(ldev->pf[0].dev, "Multipath offload require two ports of the same HCA\n"); + return; + } + + /* First time we see multipath route */ + if (!mp->mfi && !__mlx5_lag_is_active(ldev)) { + struct lag_tracker tracker; + + tracker = ldev->tracker; + mlx5_activate_lag(ldev, &tracker, MLX5_LAG_FLAG_MULTIPATH); + } + + mlx5_lag_set_port_affinity(ldev, 0); + mp->mfi = fi; +} + +static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev, + unsigned long event, + struct fib_nh *fib_nh, + struct fib_info *fi) +{ + struct lag_mp *mp = &ldev->lag_mp; + + /* Check the nh event is related to the route */ + if (!mp->mfi || mp->mfi != fi) + return; + + /* nh added/removed */ + if (event == FIB_EVENT_NH_DEL) { + int i = mlx5_lag_dev_get_netdev_idx(ldev, fib_nh->nh_dev); + + if (i >= 0) { + i = (i + 1) % 2 + 1; /* peer port */ + mlx5_lag_set_port_affinity(ldev, i); + } + } else if (event == FIB_EVENT_NH_ADD && + fi->fib_nhs == 2) { + mlx5_lag_set_port_affinity(ldev, 0); + } +} + +static void mlx5_lag_fib_update(struct work_struct *work) +{ + struct mlx5_fib_event_work *fib_work = + container_of(work, struct mlx5_fib_event_work, work); + struct mlx5_lag *ldev = fib_work->ldev; + struct fib_nh *fib_nh; + + /* Protect internal structures from changes */ + rtnl_lock(); + switch (fib_work->event) { + case FIB_EVENT_ENTRY_REPLACE: /* fall through */ + case FIB_EVENT_ENTRY_APPEND: /* fall through */ + case FIB_EVENT_ENTRY_ADD: /* fall through */ + case FIB_EVENT_ENTRY_DEL: + mlx5_lag_fib_route_event(ldev, fib_work->event, + fib_work->fen_info.fi); + fib_info_put(fib_work->fen_info.fi); + break; + case FIB_EVENT_NH_ADD: /* fall through */ + case FIB_EVENT_NH_DEL: + fib_nh = fib_work->fnh_info.fib_nh; + mlx5_lag_fib_nexthop_event(ldev, + fib_work->event, + fib_work->fnh_info.fib_nh, + fib_nh->nh_parent); + fib_info_put(fib_work->fnh_info.fib_nh->nh_parent); + break; + } + + rtnl_unlock(); + kfree(fib_work); +} + +static struct mlx5_fib_event_work * +mlx5_lag_init_fib_work(struct mlx5_lag *ldev, unsigned long event) +{ + struct mlx5_fib_event_work *fib_work; + + fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC); + if (WARN_ON(!fib_work)) + return NULL; + + INIT_WORK(&fib_work->work, mlx5_lag_fib_update); + fib_work->ldev = ldev; + fib_work->event = event; + + return fib_work; +} + +static int mlx5_lag_fib_event(struct notifier_block *nb, + unsigned long event, + void *ptr) +{ + struct lag_mp *mp = container_of(nb, struct lag_mp, fib_nb); + struct mlx5_lag *ldev = container_of(mp, struct mlx5_lag, lag_mp); + struct fib_notifier_info *info = ptr; + struct mlx5_fib_event_work *fib_work; + struct fib_entry_notifier_info *fen_info; + struct fib_nh_notifier_info *fnh_info; + struct fib_info *fi; + + if (info->family != AF_INET) + return NOTIFY_DONE; + + if (!mlx5_lag_multipath_check_prereq(ldev)) + return NOTIFY_DONE; + + switch (event) { + case FIB_EVENT_ENTRY_REPLACE: /* fall through */ + case FIB_EVENT_ENTRY_APPEND: /* fall through */ + case FIB_EVENT_ENTRY_ADD: /* fall through */ + case FIB_EVENT_ENTRY_DEL: + fen_info = container_of(info, struct fib_entry_notifier_info, + info); + fi = fen_info->fi; + if (fi->fib_dev != ldev->pf[0].netdev && + fi->fib_dev != ldev->pf[1].netdev) { + return NOTIFY_DONE; + } + fib_work = mlx5_lag_init_fib_work(ldev, event); + if (!fib_work) + return NOTIFY_DONE; + fib_work->fen_info = *fen_info; + /* Take reference on fib_info to prevent it from being + * freed while work is queued. Release it afterwards. + */ + fib_info_hold(fib_work->fen_info.fi); + break; + case FIB_EVENT_NH_ADD: /* fall through */ + case FIB_EVENT_NH_DEL: + fnh_info = container_of(info, struct fib_nh_notifier_info, + info); + fib_work = mlx5_lag_init_fib_work(ldev, event); + if (!fib_work) + return NOTIFY_DONE; + fib_work->fnh_info = *fnh_info; + fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent); + break; + default: + return NOTIFY_DONE; + } + + queue_work(ldev->wq, &fib_work->work); + + return NOTIFY_DONE; +} + +int mlx5_lag_mp_init(struct mlx5_lag *ldev) +{ + struct lag_mp *mp = &ldev->lag_mp; + int err; + + if (mp->fib_nb.notifier_call) + return 0; + + mp->fib_nb.notifier_call = mlx5_lag_fib_event; + err = register_fib_notifier(&mp->fib_nb, + mlx5_lag_fib_event_flush); + if (err) + mp->fib_nb.notifier_call = NULL; + + return err; +} + +void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev) +{ + struct lag_mp *mp = &ldev->lag_mp; + + if (!mp->fib_nb.notifier_call) + return; + + unregister_fib_notifier(&mp->fib_nb); + mp->fib_nb.notifier_call = NULL; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h new file mode 100644 index 000000000000..6d14b1100be9 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* Copyright (c) 2019 Mellanox Technologies. */ + +#ifndef __MLX5_LAG_MP_H__ +#define __MLX5_LAG_MP_H__ + +#include "lag.h" +#include "mlx5_core.h" + +struct lag_mp { + struct notifier_block fib_nb; + struct fib_info *mfi; /* used in tracking fib events */ +}; + +#ifdef CONFIG_MLX5_ESWITCH + +int mlx5_lag_mp_init(struct mlx5_lag *ldev); +void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev); + +#else /* CONFIG_MLX5_ESWITCH */ + +static inline int mlx5_lag_mp_init(struct mlx5_lag *ldev) { return 0; } +static inline void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev) {} + +#endif /* CONFIG_MLX5_ESWITCH */ +#endif /* __MLX5_LAG_MP_H__ */ -- cgit v1.2.3 From 95dc1902c3739a1a44397ea23b52b81375b711b3 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 19 Feb 2019 16:38:56 +0200 Subject: net/mlx5e: Don't inherit flow flags on peer flow creation Currently the peer flow inherits the flags from the original flow after we've set it. At this time the flags are set according to the flow state, e.g marked as going to slow path and such. Even if not getting us to real bugs now, this opens the door to get us to troubles later. Future proof the code and avoid the inheritance, use the peer flags as were set on input when we started adding the original flow. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index ea39083b1596..c2df3863e82c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2813,7 +2813,8 @@ out: } static int mlx5e_tc_add_fdb_peer_flow(struct tc_cls_flower_offload *f, - struct mlx5e_tc_flow *flow) + struct mlx5e_tc_flow *flow, + u16 flow_flags) { struct mlx5e_priv *priv = flow->priv, *peer_priv; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw; @@ -2842,7 +2843,7 @@ static int mlx5e_tc_add_fdb_peer_flow(struct tc_cls_flower_offload *f, in_mdev = priv->mdev; parse_attr = flow->esw_attr->parse_attr; - peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow->flags, + peer_flow = __mlx5e_add_fdb_flow(peer_priv, f, flow_flags, parse_attr->filter_dev, flow->esw_attr->in_rep, in_mdev); if (IS_ERR(peer_flow)) { @@ -2880,7 +2881,7 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv, return PTR_ERR(flow); if (is_peer_flow_needed(flow)) { - err = mlx5e_tc_add_fdb_peer_flow(f, flow); + err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags); if (err) { mlx5e_tc_del_fdb_flow(priv, flow); goto out; -- cgit v1.2.3 From ef06c9ee8933b182f2ecab101ed697b54171f512 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 5 Feb 2019 17:59:58 +0200 Subject: net/mlx5e: Allow one failure when offloading tc encap rules under multipath In a similar manner to uplink/VF LAG, under multipath we add encap peer rule on the second port as well. However, unlike the LAG case, we do want to allow failure for adding one of the rules. This happens due to using a routing hint while doing the route lookup when one path (next hop device) is down. Introduce a new flag to indicate that route lookup failed for encap flow. Note that a flow may still not be offloaded to hw due to missing neighbour, in that case, the neigh update event will take care of it. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index c2df3863e82c..7fe5f3de3917 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -75,6 +75,7 @@ enum { MLX5E_TC_FLOW_HAIRPIN_RSS = BIT(MLX5E_TC_FLOW_BASE + 2), MLX5E_TC_FLOW_SLOW = BIT(MLX5E_TC_FLOW_BASE + 3), MLX5E_TC_FLOW_DUP = BIT(MLX5E_TC_FLOW_BASE + 4), + MLX5E_TC_FLOW_NOT_READY = BIT(MLX5E_TC_FLOW_BASE + 5), }; #define MLX5E_TC_MAX_SPLITS 1 @@ -1047,6 +1048,11 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, struct mlx5_esw_flow_attr slow_attr; int out_index; + if (flow->flags & MLX5E_TC_FLOW_NOT_READY) { + kvfree(attr->parse_attr); + return; + } + if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { if (flow->flags & MLX5E_TC_FLOW_SLOW) mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr); @@ -2800,8 +2806,12 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, goto err_free; err = mlx5e_tc_add_fdb_flow(priv, flow, extack); - if (err) - goto err_free; + if (err) { + if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev))) + goto err_free; + + flow->flags |= MLX5E_TC_FLOW_NOT_READY; + } return flow; -- cgit v1.2.3 From 6997b1c9cace95c0e67de620a94ab6ba88d044fe Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Thu, 21 Feb 2019 16:29:27 +0200 Subject: net/mlx5: Emit port affinity event for multipath offloads Under multipath offload scheme, as part of handling fib events, emit mlx5 port affinity event on the enabled ports which will be handled by the tc offloads code. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c | 11 +++++++++++ include/linux/mlx5/driver.h | 1 + 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c index 5680beba8c07..5633f8572800 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c @@ -6,6 +6,7 @@ #include "lag_mp.h" #include "mlx5_core.h" #include "eswitch.h" +#include "lib/mlx5.h" static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) { @@ -73,6 +74,16 @@ static void mlx5_lag_set_port_affinity(struct mlx5_lag *ldev, int port) return; } + if (tracker.netdev_state[0].tx_enabled) + mlx5_notifier_call_chain(ldev->pf[0].dev->priv.events, + MLX5_DEV_EVENT_PORT_AFFINITY, + (void *)0); + + if (tracker.netdev_state[1].tx_enabled) + mlx5_notifier_call_chain(ldev->pf[1].dev->priv.events, + MLX5_DEV_EVENT_PORT_AFFINITY, + (void *)0); + mlx5_modify_lag(ldev, &tracker); } diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h index ee109b3fbfb8..5ffb5df1a2c2 100644 --- a/include/linux/mlx5/driver.h +++ b/include/linux/mlx5/driver.h @@ -195,6 +195,7 @@ struct mlx5_rsc_debug { enum mlx5_dev_event { MLX5_DEV_EVENT_SYS_ERROR = 128, /* 0 - 127 are FW events */ + MLX5_DEV_EVENT_PORT_AFFINITY = 129, }; enum mlx5_port_status { -- cgit v1.2.3 From b4a23329e2e940cdec3b5eae781c1f7d4c669533 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Wed, 6 Feb 2019 15:43:51 +0200 Subject: net/mlx5e: Re-attempt to offload flows on multipath port affinity events Under multipath it's possible for us to offload the flow only through the e-switch for which proper route through the uplink exists. When the port is up and the next-hop route is set again we want to offload through it as well. We generate SW event from the FIB event handler when multipath port affinity changes. The tc offloads code gets this event, goes over the flows which were marked as of having missing route and attempts to offload them. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 40 +++++++++++++++++------- drivers/net/ethernet/mellanox/mlx5/core/en_rep.h | 3 ++ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 39 ++++++++++++++++++++++- drivers/net/ethernet/mellanox/mlx5/core/en_tc.h | 1 + 4 files changed, 71 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 4d033e01f6ab..a1a3e2774989 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1573,6 +1573,8 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { uplink_priv = &rpriv->uplink_priv; + INIT_LIST_HEAD(&uplink_priv->unready_flows); + /* init shared tc flow table */ err = mlx5e_tc_esw_init(&uplink_priv->tc_ht); if (err) @@ -1632,27 +1634,38 @@ static void mlx5e_vf_rep_enable(struct mlx5e_priv *priv) static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event, void *data) { struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, events_nb); - struct mlx5_eqe *eqe = data; - if (event != MLX5_EVENT_TYPE_PORT_CHANGE) - return NOTIFY_DONE; + if (event == MLX5_EVENT_TYPE_PORT_CHANGE) { + struct mlx5_eqe *eqe = data; - switch (eqe->sub_type) { - case MLX5_PORT_CHANGE_SUBTYPE_DOWN: - case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE: - queue_work(priv->wq, &priv->update_carrier_work); - break; - default: - return NOTIFY_DONE; + switch (eqe->sub_type) { + case MLX5_PORT_CHANGE_SUBTYPE_DOWN: + case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE: + queue_work(priv->wq, &priv->update_carrier_work); + break; + default: + return NOTIFY_DONE; + } + + return NOTIFY_OK; } - return NOTIFY_OK; + if (event == MLX5_DEV_EVENT_PORT_AFFINITY) { + struct mlx5e_rep_priv *rpriv = priv->ppriv; + + queue_work(priv->wq, &rpriv->uplink_priv.reoffload_flows_work); + + return NOTIFY_OK; + } + + return NOTIFY_DONE; } static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) { struct net_device *netdev = priv->netdev; struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5e_rep_priv *rpriv = priv->ppriv; u16 max_mtu; netdev->min_mtu = ETH_MIN_MTU; @@ -1660,6 +1673,9 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu); mlx5e_set_dev_port_mtu(priv); + INIT_WORK(&rpriv->uplink_priv.reoffload_flows_work, + mlx5e_tc_reoffload_flows_work); + mlx5_lag_add(mdev, netdev); priv->events_nb.notifier_call = uplink_rep_async_event; mlx5_notifier_register(mdev, &priv->events_nb); @@ -1672,11 +1688,13 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) { struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5e_rep_priv *rpriv = priv->ppriv; #ifdef CONFIG_MLX5_CORE_EN_DCB mlx5e_dcbnl_delete_app(priv); #endif mlx5_notifier_unregister(mdev, &priv->events_nb); + cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work); mlx5_lag_remove(mdev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 1aa3e110bb97..83b573b1abac 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -74,6 +74,9 @@ struct mlx5_rep_uplink_priv { struct notifier_block netdevice_nb; struct mlx5_tun_entropy tun_entropy; + + struct list_head unready_flows; + struct work_struct reoffload_flows_work; }; struct mlx5e_rep_priv { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 7fe5f3de3917..2f0c631847fd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -117,6 +117,7 @@ struct mlx5e_tc_flow { struct list_head mod_hdr; /* flows sharing the same mod hdr ID */ struct list_head hairpin; /* flows sharing the same hairpin */ struct list_head peer; /* flows with peer flow */ + struct list_head unready; /* flows not ready to be offloaded (e.g due to missing route) */ union { struct mlx5_esw_flow_attr esw_attr[0]; struct mlx5_nic_flow_attr nic_attr[0]; @@ -928,6 +929,26 @@ mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, flow->flags &= ~MLX5E_TC_FLOW_SLOW; } +static void add_unready_flow(struct mlx5e_tc_flow *flow) +{ + struct mlx5_rep_uplink_priv *uplink_priv; + struct mlx5e_rep_priv *rpriv; + struct mlx5_eswitch *esw; + + esw = flow->priv->mdev->priv.eswitch; + rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); + uplink_priv = &rpriv->uplink_priv; + + flow->flags |= MLX5E_TC_FLOW_NOT_READY; + list_add_tail(&flow->unready, &uplink_priv->unready_flows); +} + +static void remove_unready_flow(struct mlx5e_tc_flow *flow) +{ + list_del(&flow->unready); + flow->flags &= ~MLX5E_TC_FLOW_NOT_READY; +} + static int mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, @@ -1049,6 +1070,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, int out_index; if (flow->flags & MLX5E_TC_FLOW_NOT_READY) { + remove_unready_flow(flow); kvfree(attr->parse_attr); return; } @@ -2810,7 +2832,7 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, if (!(err == -ENETUNREACH && mlx5_lag_is_multipath(in_mdev))) goto err_free; - flow->flags |= MLX5E_TC_FLOW_NOT_READY; + add_unready_flow(flow); } return flow; @@ -3214,3 +3236,18 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw) list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer) __mlx5e_tc_del_fdb_peer_flow(flow); } + +void mlx5e_tc_reoffload_flows_work(struct work_struct *work) +{ + struct mlx5_rep_uplink_priv *rpriv = + container_of(work, struct mlx5_rep_uplink_priv, + reoffload_flows_work); + struct mlx5e_tc_flow *flow, *tmp; + + rtnl_lock(); + list_for_each_entry_safe(flow, tmp, &rpriv->unready_flows, unready) { + if (!mlx5e_tc_add_fdb_flow(flow->priv, flow, NULL)) + remove_unready_flow(flow); + } + rtnl_unlock(); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index d2d87f978c06..f62e81902d27 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -72,6 +72,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe); int mlx5e_tc_num_filters(struct mlx5e_priv *priv, int flags); +void mlx5e_tc_reoffload_flows_work(struct work_struct *work); #else /* CONFIG_MLX5_ESWITCH */ static inline int mlx5e_tc_nic_init(struct mlx5e_priv *priv) { return 0; } -- cgit v1.2.3 From 316d5f72b4c1d4122f83cccbc9002e7b13660077 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Mon, 2 Jul 2018 14:06:02 +0300 Subject: net/mlx5e: Always query offloaded tc peer rule counter Under multipath when encap rules are duplicated to HW in the driver, it's possible for one flow to be currently un-offloaded (e.g. lack of next-hop route or neigh entry) while the other flow is offloaded. As such, we move to query the counters of both flows at all times. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 26 ++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 2f0c631847fd..c44cb5083d55 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3078,23 +3078,25 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, struct mlx5_eswitch *peer_esw; struct mlx5e_tc_flow *flow; struct mlx5_fc *counter; - u64 bytes; - u64 packets; - u64 lastuse; + u64 lastuse = 0; + u64 packets = 0; + u64 bytes = 0; flow = rhashtable_lookup_fast(tc_ht, &f->cookie, tc_ht_params); if (!flow || !same_flow_direction(flow, flags)) return -EINVAL; - if (!(flow->flags & MLX5E_TC_FLOW_OFFLOADED)) - return 0; - - counter = mlx5e_tc_get_counter(flow); - if (!counter) - return 0; + if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { + counter = mlx5e_tc_get_counter(flow); + if (!counter) + return 0; - mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); + mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse); + } + /* Under multipath it's possible for one rule to be currently + * un-offloaded while the other rule is offloaded. + */ peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); if (!peer_esw) goto out; @@ -3106,6 +3108,8 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, u64 lastuse2; counter = mlx5e_tc_get_counter(flow->peer_flow); + if (!counter) + goto no_peer_counter; mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2); bytes += bytes2; @@ -3113,8 +3117,8 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, lastuse = max_t(u64, lastuse, lastuse2); } +no_peer_counter: mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - out: flow_stats_update(&f->stats, bytes, packets, lastuse); -- cgit v1.2.3 From 5fb091e8130bdd3649ca80957e59c87defbb13f9 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 5 Feb 2019 09:48:38 +0200 Subject: net/mlx5e: Use hint to resolve route when in HW multipath mode As part of creating the tunnel headers while offloading TC encap rules, we resolve the route and neighbour in order to get the source / destination mac. Since the way we offload multipath route is by having two HW rules, one per uplink port, doing naive route lookup might get us a "wrong" routing path which goes through the peer uplink and this will get us eventually to create a wrong L2 header for the tunnel. To avoid that, we use a device hint to get the correct route. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index 03e5d0d8fd8f..fa2a3c444cdc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -54,12 +54,24 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv, struct neighbour *n = NULL; #if IS_ENABLED(CONFIG_INET) + struct mlx5_core_dev *mdev = priv->mdev; + struct net_device *uplink_dev; int ret; + if (mlx5_lag_is_multipath(mdev)) { + struct mlx5_eswitch *esw = mdev->priv.eswitch; + + uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH); + fl4->flowi4_oif = uplink_dev->ifindex; + } + rt = ip_route_output_key(dev_net(mirred_dev), fl4); ret = PTR_ERR_OR_ZERO(rt); if (ret) return ret; + + if (mlx5_lag_is_multipath(mdev) && !rt->rt_gateway) + return -ENETUNREACH; #else return -EOPNOTSUPP; #endif -- cgit v1.2.3 From 68931c7dd71efd9be19f0b5777f2c6e78a9f1185 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 5 Feb 2019 09:41:43 +0200 Subject: net/mlx5e: Update check for merged eswitch device The current check only validates if both netdevs use the same ops which means both are vf reps or both uplink reps. Unlike the case where the two uplinks are bonded (VF LAG), under multipath scheme the switchdev parent id is not unified between the uplink reps (and all the associated vf reps). However, we still want to duplicate in the driver encap flows, adjust the merged eswitch check for that matter. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index c44cb5083d55..850cf6ecb4d7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2360,10 +2360,9 @@ static bool is_merged_eswitch_dev(struct mlx5e_priv *priv, peer_priv = netdev_priv(peer_netdev); return (MLX5_CAP_ESW(priv->mdev, merged_eswitch) && - (priv->netdev->netdev_ops == peer_netdev->netdev_ops) && - same_hw_devs(priv, peer_priv) && - MLX5_VPORT_MANAGER(peer_priv->mdev) && - (peer_priv->mdev->priv.eswitch->mode == SRIOV_OFFLOADS)); + mlx5e_eswitch_rep(priv->netdev) && + mlx5e_eswitch_rep(peer_netdev) && + same_hw_devs(priv, peer_priv)); } -- cgit v1.2.3 From 10fbb1cdd0a36347106f6522c941e67cd9c3e7c1 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Thu, 7 Feb 2019 14:09:15 +0200 Subject: net/mlx5e: Set peer flow needed also for multipath Update the predicate that determines if to duplicate rules installed on vport reps to account also for the multipath case. Signed-off-by: Roi Dayan Reviewed-by: Or Gerlitz Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 850cf6ecb4d7..b4967a0ff8c7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2731,8 +2731,15 @@ static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow) bool esw_paired = mlx5_devcom_is_paired(attr->in_mdev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); - return esw_paired && mlx5_lag_is_sriov(attr->in_mdev) && - (is_rep_ingress || act_is_encap); + if (!esw_paired) + return false; + + if ((mlx5_lag_is_sriov(attr->in_mdev) || + mlx5_lag_is_multipath(attr->in_mdev)) && + (is_rep_ingress || act_is_encap)) + return true; + + return false; } static int -- cgit v1.2.3 From 85327a9c415057259b337805d356705d0d0f4200 Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Sun, 27 Jan 2019 15:01:25 +0200 Subject: net/mlx5: Update the list of the PCI supported devices Add the upcoming ConnectX-6 Dx. In addition, add "ConnectX Family mlx5Gen Virtual Function" device ID. Every new HCA VF will be identified with this device ID. Different VF models will be distinguished by their revision id. Signed-off-by: Eran Ben Elisha Reviewed-by: Aya Levin Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 40d591c8e76c..8391dde869a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1486,6 +1486,8 @@ static const struct pci_device_id mlx5_core_pci_table[] = { { PCI_VDEVICE(MELLANOX, 0x101a), MLX5_PCI_DEV_IS_VF}, /* ConnectX-5 Ex VF */ { PCI_VDEVICE(MELLANOX, 0x101b) }, /* ConnectX-6 */ { PCI_VDEVICE(MELLANOX, 0x101c), MLX5_PCI_DEV_IS_VF}, /* ConnectX-6 VF */ + { PCI_VDEVICE(MELLANOX, 0x101d) }, /* ConnectX-6 Dx */ + { PCI_VDEVICE(MELLANOX, 0x101e), MLX5_PCI_DEV_IS_VF}, /* ConnectX Family mlx5Gen Virtual Function */ { PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */ { PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */ { 0, } -- cgit v1.2.3 From ff83dbf21e79d03f3788943a5bce12c39a06a3ab Mon Sep 17 00:00:00 2001 From: Nikita Danilov Date: Wed, 27 Feb 2019 12:10:03 +0000 Subject: net: aquantia: fixed memcpy size Not careful array dereference caused analysis tools to think there could be memory overflow. There was actually no corruption because the array is two dimensional. drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c: 140 aq_ethtool_get_strings() error: memcpy() '*aq_ethtool_stat_names' too small (32 vs 704) Signed-off-by: Nikita Danilov Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c index 38e87eed76b9..a718d7a1f76c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c @@ -138,7 +138,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, u8 *p = data; if (stringset == ETH_SS_STATS) { - memcpy(p, *aq_ethtool_stat_names, + memcpy(p, aq_ethtool_stat_names, sizeof(aq_ethtool_stat_names)); p = p + sizeof(aq_ethtool_stat_names); for (i = 0; i < cfg->vecs; i++) { -- cgit v1.2.3 From ea4854ddbc31247b928376259aaa9460b453acb2 Mon Sep 17 00:00:00 2001 From: Nikita Danilov Date: Wed, 27 Feb 2019 12:10:05 +0000 Subject: net: aquantia: added newline at end of file drivers/net/ethernet/aquantia/atlantic/aq_nic.c: 991:1: warning: no newline at end of file Signed-off-by: Nikita Danilov Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 0147c037ca96..ff83667410bd 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -986,4 +986,4 @@ void aq_nic_shutdown(struct aq_nic_s *self) err_exit: rtnl_unlock(); -} \ No newline at end of file +} -- cgit v1.2.3 From 13b7997a103d90a2174ab93abefe3c9376bb97e5 Mon Sep 17 00:00:00 2001 From: Nikita Danilov Date: Wed, 27 Feb 2019 12:10:07 +0000 Subject: net: aquantia: fixed buffer overflow The overflow is detected by smatch: drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c: 175 aq_pci_func_free_irqs() error: buffer overflow 'self->aq_vec' 8 <= 31 In reality msix_entry_mask always restricts number of iterations. Adding extra condition to make logic clear and smatch happy. Signed-off-by: Nikita Danilov Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index c8b44cdb91c1..0217ff4669a4 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -170,6 +170,8 @@ void aq_pci_func_free_irqs(struct aq_nic_s *self) for (i = 32U; i--;) { if (!((1U << i) & self->msix_entry_mask)) continue; + if (i >= AQ_CFG_VECS_MAX) + continue; if (pdev->msix_enabled) irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL); -- cgit v1.2.3 From 8006e3730b6e900319411e35cee85b4513d298df Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Wed, 27 Feb 2019 12:10:09 +0000 Subject: net: aquantia: fixed instack structure overflow This is a real stack undercorruption found by kasan build. The issue did no harm normally because it only overflowed 2 bytes after `bitary` array which on most architectures were mapped into `err` local. Fixes: bab6de8fd180 ("net: ethernet: aquantia: Atlantic A0 and B0 specific functions.") Signed-off-by: Nikita Danilov Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 4 ++-- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 2469ed4d86b9..30fdcb9b11fd 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -207,8 +207,8 @@ static int hw_atl_a0_hw_rss_set(struct aq_hw_s *self, u32 i = 0U; u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues); int err = 0; - u16 bitary[(HW_ATL_A0_RSS_REDIRECTION_MAX * - HW_ATL_A0_RSS_REDIRECTION_BITS / 16U)]; + u16 bitary[1 + (HW_ATL_A0_RSS_REDIRECTION_MAX * + HW_ATL_A0_RSS_REDIRECTION_BITS / 16U)]; memset(bitary, 0, sizeof(bitary)); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index b58ca7cb8e9d..c4cdc51350b2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -199,8 +199,8 @@ static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, u32 i = 0U; u32 num_rss_queues = max(1U, self->aq_nic_cfg->num_rss_queues); int err = 0; - u16 bitary[(HW_ATL_B0_RSS_REDIRECTION_MAX * - HW_ATL_B0_RSS_REDIRECTION_BITS / 16U)]; + u16 bitary[1 + (HW_ATL_B0_RSS_REDIRECTION_MAX * + HW_ATL_B0_RSS_REDIRECTION_BITS / 16U)]; memset(bitary, 0, sizeof(bitary)); -- cgit v1.2.3 From 6a7f2277313b4a39645c13277efb9337ca441933 Mon Sep 17 00:00:00 2001 From: Nikita Danilov Date: Wed, 27 Feb 2019 12:10:11 +0000 Subject: net: aquantia: replace AQ_HW_WAIT_FOR with readx_poll_timeout_atomic David noticed the original define was hiding 'err' variable reference. Thats confusing and counterintuitive. Andrew noted the whole macro could be replaced with standard readx_poll kernel macro. This makes code more readable. Signed-off-by: Nikita Danilov Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../net/ethernet/aquantia/atlantic/aq_hw_utils.h | 14 +-- .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 21 ++-- .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 12 ++- .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 21 ++++ .../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 12 +++ .../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 2 + .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 110 +++++++++++++++------ .../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 64 ++++++++---- 8 files changed, 184 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h index dc88a1221f1d..bc711238ca0c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h @@ -14,6 +14,8 @@ #ifndef AQ_HW_UTILS_H #define AQ_HW_UTILS_H +#include + #include "aq_common.h" #ifndef HIDWORD @@ -23,18 +25,6 @@ #define AQ_HW_SLEEP(_US_) mdelay(_US_) -#define AQ_HW_WAIT_FOR(_B_, _US_, _N_) \ -do { \ - unsigned int AQ_HW_WAIT_FOR_i; \ - for (AQ_HW_WAIT_FOR_i = _N_; (!(_B_)) && (AQ_HW_WAIT_FOR_i);\ - --AQ_HW_WAIT_FOR_i) {\ - udelay(_US_); \ - } \ - if (!AQ_HW_WAIT_FOR_i) {\ - err = -ETIME; \ - } \ -} while (0) - #define aq_pr_err(...) pr_err(AQ_CFG_DRV_NAME ": " __VA_ARGS__) #define aq_pr_trace(...) pr_info(AQ_CFG_DRV_NAME ": " __VA_ARGS__) diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 30fdcb9b11fd..f6f8338153a2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -85,6 +85,7 @@ const struct aq_hw_caps_s hw_atl_a0_caps_aqc109 = { static int hw_atl_a0_hw_reset(struct aq_hw_s *self) { int err = 0; + u32 val; hw_atl_glb_glb_reg_res_dis_set(self, 1U); hw_atl_pci_pci_reg_res_dis_set(self, 0U); @@ -95,7 +96,9 @@ static int hw_atl_a0_hw_reset(struct aq_hw_s *self) hw_atl_glb_soft_res_set(self, 1); /* check 10 times by 1ms */ - AQ_HW_WAIT_FOR(hw_atl_glb_soft_res_get(self) == 0, 1000U, 10U); + err = readx_poll_timeout_atomic(hw_atl_glb_soft_res_get, + self, val, val == 0, + 1000U, 10000U); if (err < 0) goto err_exit; @@ -103,7 +106,9 @@ static int hw_atl_a0_hw_reset(struct aq_hw_s *self) hw_atl_itr_res_irq_set(self, 1U); /* check 10 times by 1ms */ - AQ_HW_WAIT_FOR(hw_atl_itr_res_irq_get(self) == 0, 1000U, 10U); + err = readx_poll_timeout_atomic(hw_atl_itr_res_irq_get, + self, val, val == 0, + 1000U, 10000U); if (err < 0) goto err_exit; @@ -181,6 +186,7 @@ static int hw_atl_a0_hw_rss_hash_set(struct aq_hw_s *self, int err = 0; unsigned int i = 0U; unsigned int addr = 0U; + u32 val; for (i = 10, addr = 0U; i--; ++addr) { u32 key_data = cfg->is_rss ? @@ -188,8 +194,9 @@ static int hw_atl_a0_hw_rss_hash_set(struct aq_hw_s *self, hw_atl_rpf_rss_key_wr_data_set(self, key_data); hw_atl_rpf_rss_key_addr_set(self, addr); hw_atl_rpf_rss_key_wr_en_set(self, 1U); - AQ_HW_WAIT_FOR(hw_atl_rpf_rss_key_wr_en_get(self) == 0, - 1000U, 10U); + err = readx_poll_timeout_atomic(hw_atl_rpf_rss_key_wr_en_get, + self, val, val == 0, + 1000U, 10000U); if (err < 0) goto err_exit; } @@ -209,6 +216,7 @@ static int hw_atl_a0_hw_rss_set(struct aq_hw_s *self, int err = 0; u16 bitary[1 + (HW_ATL_A0_RSS_REDIRECTION_MAX * HW_ATL_A0_RSS_REDIRECTION_BITS / 16U)]; + u32 val; memset(bitary, 0, sizeof(bitary)); @@ -222,8 +230,9 @@ static int hw_atl_a0_hw_rss_set(struct aq_hw_s *self, hw_atl_rpf_rss_redir_tbl_wr_data_set(self, bitary[i]); hw_atl_rpf_rss_redir_tbl_addr_set(self, i); hw_atl_rpf_rss_redir_wr_en_set(self, 1U); - AQ_HW_WAIT_FOR(hw_atl_rpf_rss_redir_wr_en_get(self) == 0, - 1000U, 10U); + err = readx_poll_timeout_atomic(hw_atl_rpf_rss_redir_wr_en_get, + self, val, val == 0, + 1000U, 10000U); if (err < 0) goto err_exit; } diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index c4cdc51350b2..7eb5ea948d61 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -173,6 +173,7 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, int err = 0; unsigned int i = 0U; unsigned int addr = 0U; + u32 val; for (i = 10, addr = 0U; i--; ++addr) { u32 key_data = cfg->is_rss ? @@ -180,8 +181,9 @@ static int hw_atl_b0_hw_rss_hash_set(struct aq_hw_s *self, hw_atl_rpf_rss_key_wr_data_set(self, key_data); hw_atl_rpf_rss_key_addr_set(self, addr); hw_atl_rpf_rss_key_wr_en_set(self, 1U); - AQ_HW_WAIT_FOR(hw_atl_rpf_rss_key_wr_en_get(self) == 0, - 1000U, 10U); + err = readx_poll_timeout_atomic(hw_atl_rpf_rss_key_wr_en_get, + self, val, val == 0, + 1000U, 10000U); if (err < 0) goto err_exit; } @@ -201,6 +203,7 @@ static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, int err = 0; u16 bitary[1 + (HW_ATL_B0_RSS_REDIRECTION_MAX * HW_ATL_B0_RSS_REDIRECTION_BITS / 16U)]; + u32 val; memset(bitary, 0, sizeof(bitary)); @@ -214,8 +217,9 @@ static int hw_atl_b0_hw_rss_set(struct aq_hw_s *self, hw_atl_rpf_rss_redir_tbl_wr_data_set(self, bitary[i]); hw_atl_rpf_rss_redir_tbl_addr_set(self, i); hw_atl_rpf_rss_redir_wr_en_set(self, 1U); - AQ_HW_WAIT_FOR(hw_atl_rpf_rss_redir_wr_en_get(self) == 0, - 1000U, 10U); + err = readx_poll_timeout_atomic(hw_atl_rpf_rss_redir_wr_en_get, + self, val, val == 0, + 1000U, 10000U); if (err < 0) goto err_exit; } diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c index 939f77e2e117..f72194c77f5f 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c @@ -1585,3 +1585,24 @@ void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location, HW_ATL_RPF_L3_DSTA_ADR(location + i), ipv6_dest[i]); } + +u32 hw_atl_sem_ram_get(struct aq_hw_s *self) +{ + return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); +} + +u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp) +{ + return aq_hw_read_reg(aq_hw, + HW_ATL_GLB_CPU_SCRATCH_SCP_ADR(scratch_scp)); +} + +u32 hw_atl_scrpad12_get(struct aq_hw_s *self) +{ + return hw_atl_scrpad_get(self, 0xB); +} + +u32 hw_atl_scrpad25_get(struct aq_hw_s *self) +{ + return hw_atl_scrpad_get(self, 0x18); +} diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h index 03c570d115fe..40e6c1e44b5b 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h @@ -752,4 +752,16 @@ void hw_atl_rpfl3l4_ipv6_src_addr_set(struct aq_hw_s *aq_hw, u8 location, void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location, u32 *ipv6_dest); +/* get global microprocessor ram semaphore */ +u32 hw_atl_sem_ram_get(struct aq_hw_s *self); + +/* get global microprocessor scratch pad register */ +u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp); + +/* get global microprocessor scratch pad 12 register */ +u32 hw_atl_scrpad12_get(struct aq_hw_s *self); + +/* get global microprocessor scratch pad 25 register */ +u32 hw_atl_scrpad25_get(struct aq_hw_s *self); + #endif /* HW_ATL_LLH_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h index 8470d92db812..50b4dee5562d 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h @@ -2519,4 +2519,6 @@ /* Default value of bitfield l3_da0[1F:0] */ #define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0 +#define HW_ATL_FW_SM_RAM 0x2U + #endif /* HW_ATL_LLH_INTERNAL_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index 9b74a3197d7f..e5df40b00afd 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -25,7 +25,9 @@ #define HW_ATL_MIF_ADDR 0x0208U #define HW_ATL_MIF_VAL 0x020CU -#define HW_ATL_FW_SM_RAM 0x2U +#define HW_ATL_RPC_CONTROL_ADR 0x0338U +#define HW_ATL_RPC_STATE_ADR 0x033CU + #define HW_ATL_MPI_FW_VERSION 0x18 #define HW_ATL_MPI_CONTROL_ADR 0x0368U #define HW_ATL_MPI_STATE_ADR 0x036CU @@ -53,6 +55,12 @@ static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, enum hal_atl_utils_fw_state_e state); +static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self); +static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self); +static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self); +static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self); +static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self); + int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) { int err = 0; @@ -234,6 +242,7 @@ int hw_atl_utils_soft_reset(struct aq_hw_s *self) { int k; u32 boot_exit_code = 0; + u32 val; for (k = 0; k < 1000; ++k) { u32 flb_status = aq_hw_read_reg(self, @@ -260,9 +269,11 @@ int hw_atl_utils_soft_reset(struct aq_hw_s *self) int err = 0; hw_atl_utils_mpi_set_state(self, MPI_DEINIT); - AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR) & - HW_ATL_MPI_STATE_MSK) == MPI_DEINIT, - 10, 1000U); + err = readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state, + self, val, + (val & HW_ATL_MPI_STATE_MSK) == + MPI_DEINIT, + 10, 10000U); if (err) return err; } @@ -277,10 +288,11 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) { int err = 0; + u32 val; - AQ_HW_WAIT_FOR(hw_atl_reg_glb_cpu_sem_get(self, - HW_ATL_FW_SM_RAM) == 1U, - 1U, 10000U); + err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, + self, val, val == 1U, + 1U, 10000U); if (err < 0) { bool is_locked; @@ -299,13 +311,14 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U); if (IS_CHIP_FEATURE(REVISION_B1)) - AQ_HW_WAIT_FOR(a != aq_hw_read_reg(self, - HW_ATL_MIF_ADDR), - 1, 1000U); + err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get, + self, val, val != a, + 1U, 1000U); else - AQ_HW_WAIT_FOR(!(0x100 & aq_hw_read_reg(self, - HW_ATL_MIF_CMD)), - 1, 1000U); + err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get, + self, val, + !(val & 0x100), + 1U, 1000U); *(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL); a += 4; @@ -320,6 +333,7 @@ err_exit: static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) { + u32 val; int err = 0; bool is_locked; @@ -337,10 +351,11 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, (0x80000000 | (0xFFFF & (offset * 4)))); hw_atl_mcp_up_force_intr_set(self, 1); /* 1000 times by 10us = 10ms */ - AQ_HW_WAIT_FOR((aq_hw_read_reg(self, - 0x32C) & 0xF0000000) != - 0x80000000, - 10, 1000); + err = readx_poll_timeout_atomic(hw_atl_scrpad12_get, + self, val, + (val & 0xF0000000) == + 0x80000000, + 10U, 10000U); } } else { u32 offset = 0; @@ -351,8 +366,10 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, aq_hw_write_reg(self, 0x20C, p[offset]); aq_hw_write_reg(self, 0x200, 0xC000); - AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U) & - 0x100) == 0, 10, 1000); + err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get, + self, val, + (val & 0x100) == 0, + 1000U, 10000U); } } @@ -395,15 +412,14 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self, hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U); /* check 10 times by 1ms */ - AQ_HW_WAIT_FOR(0U != (self->mbox_addr = - aq_hw_read_reg(self, 0x360U)), 1000U, 10U); + err = readx_poll_timeout_atomic(hw_atl_scrpad25_get, + self, self->mbox_addr, + self->mbox_addr != 0U, + 1000U, 10000U); return err; } -#define HW_ATL_RPC_CONTROL_ADR 0x0338U -#define HW_ATL_RPC_STATE_ADR 0x033CU - struct aq_hw_atl_utils_fw_rpc_tid_s { union { u32 val; @@ -452,10 +468,10 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, self->rpc_tid = sw.tid; - AQ_HW_WAIT_FOR(sw.tid == - (fw.val = - aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR), - fw.tid), 1000U, 100U); + err = readx_poll_timeout_atomic(hw_atl_utils_rpc_state_get, + self, fw.val, + sw.tid == fw.tid, + 1000U, 100000U); if (fw.len == 0xFFFFU) { err = hw_atl_utils_fw_rpc_call(self, sw.len); @@ -559,10 +575,11 @@ static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, transaction_id = mbox.transaction_id; - AQ_HW_WAIT_FOR(transaction_id != - (hw_atl_utils_mpi_read_mbox(self, &mbox), - mbox.transaction_id), - 1000U, 100U); + err = readx_poll_timeout_atomic(hw_atl_utils_get_mpi_mbox_tid, + self, mbox.transaction_id, + transaction_id != + mbox.transaction_id, + 1000U, 100000U); if (err < 0) goto err_exit; } @@ -905,6 +922,35 @@ err_exit: return err; } +static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self) +{ + struct hw_atl_utils_mbox_header mbox; + + hw_atl_utils_mpi_read_mbox(self, &mbox); + + return mbox.transaction_id; +} + +static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self) +{ + return aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR); +} + +static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self) +{ + return aq_hw_read_reg(self, HW_ATL_MIF_CMD); +} + +static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self) +{ + return aq_hw_read_reg(self, HW_ATL_MIF_ADDR); +} + +static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self) +{ + return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR); +} + const struct aq_fw_ops aq_fw_1x_ops = { .init = hw_atl_utils_mpi_create, .deinit = hw_atl_fw1x_deinit, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c index 7de3220d9cab..c628290d7546 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -20,15 +20,14 @@ #include "hw_atl_utils.h" #include "hw_atl_llh.h" -#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 -#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 #define HW_ATL_FW2X_MPI_RPC_ADDR 0x334 +#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 +#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 #define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368 #define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C - #define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 -#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 +#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 #define HW_ATL_FW2X_CAP_PAUSE BIT(CAPS_HI_PAUSE) #define HW_ATL_FW2X_CAP_ASYM_PAUSE BIT(CAPS_HI_ASYMMETRIC_PAUSE) @@ -72,17 +71,24 @@ static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed); static int aq_fw2x_set_state(struct aq_hw_s *self, enum hal_atl_utils_fw_state_e state); +static u32 aq_fw2x_mbox_get(struct aq_hw_s *self); +static u32 aq_fw2x_rpc_get(struct aq_hw_s *self); +static u32 aq_fw2x_state2_get(struct aq_hw_s *self); + static int aq_fw2x_init(struct aq_hw_s *self) { int err = 0; /* check 10 times by 1ms */ - AQ_HW_WAIT_FOR(0U != (self->mbox_addr = - aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR)), - 1000U, 10U); - AQ_HW_WAIT_FOR(0U != (self->rpc_addr = - aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR)), - 1000U, 100U); + err = readx_poll_timeout_atomic(aq_fw2x_mbox_get, + self, self->mbox_addr, + self->mbox_addr != 0U, + 1000U, 10000U); + + err = readx_poll_timeout_atomic(aq_fw2x_rpc_get, + self, self->rpc_addr, + self->rpc_addr != 0U, + 1000U, 100000U); return err; } @@ -286,16 +292,18 @@ static int aq_fw2x_update_stats(struct aq_hw_s *self) int err = 0; u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS); + u32 stats_val; /* Toggle statistics bit for FW to update */ mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS); aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); /* Wait FW to report back */ - AQ_HW_WAIT_FOR(orig_stats_val != - (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) & - BIT(CAPS_HI_STATISTICS)), - 1U, 10000U); + err = readx_poll_timeout_atomic(aq_fw2x_state2_get, + self, stats_val, + orig_stats_val != (stats_val & + BIT(CAPS_HI_STATISTICS)), + 1U, 10000U); if (err) return err; @@ -309,6 +317,7 @@ static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac) unsigned int rpc_size = 0U; u32 mpi_opts; int err = 0; + u32 val; rpc_size = sizeof(rpc->msg_id) + sizeof(*cfg); @@ -337,8 +346,10 @@ static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac) mpi_opts |= HW_ATL_FW2X_CTRL_SLEEP_PROXY; aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); - AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) & - HW_ATL_FW2X_CTRL_SLEEP_PROXY), 1U, 10000U); + err = readx_poll_timeout_atomic(aq_fw2x_state2_get, + self, val, + val & HW_ATL_FW2X_CTRL_SLEEP_PROXY, + 1U, 10000U); err_exit: return err; @@ -350,6 +361,7 @@ static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac) struct fw2x_msg_wol *msg = NULL; u32 mpi_opts; int err = 0; + u32 val; err = hw_atl_utils_fw_rpc_wait(self, &rpc); if (err < 0) @@ -374,8 +386,9 @@ static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac) mpi_opts |= HW_ATL_FW2X_CTRL_WOL; aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); - AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) & - HW_ATL_FW2X_CTRL_WOL), 1U, 10000U); + err = readx_poll_timeout_atomic(aq_fw2x_state2_get, + self, val, val & HW_ATL_FW2X_CTRL_WOL, + 1U, 10000U); err_exit: return err; @@ -471,6 +484,21 @@ static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode) return 0; } +static u32 aq_fw2x_mbox_get(struct aq_hw_s *self) +{ + return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR); +} + +static u32 aq_fw2x_rpc_get(struct aq_hw_s *self) +{ + return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR); +} + +static u32 aq_fw2x_state2_get(struct aq_hw_s *self) +{ + return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); +} + const struct aq_fw_ops aq_fw_2x_ops = { .init = aq_fw2x_init, .deinit = aq_fw2x_deinit, -- cgit v1.2.3 From 0b926d461f097e65bb96859d0a3ce4b374f65a21 Mon Sep 17 00:00:00 2001 From: Nikita Danilov Date: Wed, 27 Feb 2019 12:10:13 +0000 Subject: net: aquantia: use better wrappers for state registers Replace some direct registers reads with better online functions. Signed-off-by: Nikita Danilov Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c | 6 +++--- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index e5df40b00afd..eb4b99d56081 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -298,7 +298,7 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, bool is_locked; hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); - is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); + is_locked = hw_atl_sem_ram_get(self); if (!is_locked) { err = -ETIME; goto err_exit; @@ -337,7 +337,7 @@ static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, int err = 0; bool is_locked; - is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); + is_locked = hw_atl_sem_ram_get(self); if (!is_locked) { err = -ETIME; goto err_exit; @@ -602,7 +602,7 @@ err_exit: int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) { - u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR); + u32 cp0x036C = hw_atl_utils_mpi_get_state(self); u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT; struct aq_hw_link_status_s *link_status = &self->aq_link_status; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c index c628290d7546..fe6c5658e016 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -438,7 +438,7 @@ static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate, *supported_rates = fw2x_to_eee_mask(caps_hi); - mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); + mpi_state = aq_fw2x_state2_get(self); *rate = fw2x_to_eee_mask(mpi_state); return err; @@ -468,7 +468,7 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self) static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode) { - u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); + u32 mpi_state = aq_fw2x_state2_get(self); if (mpi_state & HW_ATL_FW2X_CAP_PAUSE) if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) -- cgit v1.2.3 From f9b274ce014421899b62cb0e41e5e7b72773782b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:16 +0000 Subject: mlxsw: spectrum_acl: Push rehash dw struct into rehash sub-struct More rehash related fields are going to come. Push "dw" into sub-struct that will accommodate the others as well. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index c9d9cded1724..e2699373dfa7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -192,7 +192,9 @@ struct mlxsw_sp_acl_tcam_vregion { struct mlxsw_afk_key_info *key_info; struct mlxsw_sp_acl_tcam *tcam; struct mlxsw_sp_acl_tcam_vgroup *vgroup; - struct delayed_work rehash_dw; + struct { + struct delayed_work dw; + } rehash; struct mlxsw_sp *mlxsw_sp; bool failed_rollback; /* Indicates failed rollback during migration */ unsigned int ref_count; @@ -718,7 +720,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion if (!interval) return; - mlxsw_core_schedule_dw(&vregion->rehash_dw, + mlxsw_core_schedule_dw(&vregion->rehash.dw, msecs_to_jiffies(interval)); } @@ -730,7 +732,7 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) { struct mlxsw_sp_acl_tcam_vregion *vregion = container_of(work, struct mlxsw_sp_acl_tcam_vregion, - rehash_dw.work); + rehash.dw.work); mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion); mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); @@ -778,7 +780,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) { /* Create the delayed work for vregion periodic rehash */ - INIT_DELAYED_WORK(&vregion->rehash_dw, + INIT_DELAYED_WORK(&vregion->rehash.dw, mlxsw_sp_acl_tcam_vregion_rehash_work); mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); mutex_lock(&tcam->lock); @@ -809,7 +811,7 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, mutex_lock(&tcam->lock); list_del(&vregion->tlist); mutex_unlock(&tcam->lock); - cancel_delayed_work_sync(&vregion->rehash_dw); + cancel_delayed_work_sync(&vregion->rehash.dw); } mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion); if (vregion->region2) @@ -847,9 +849,9 @@ int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, mutex_lock(&tcam->lock); list_for_each_entry(vregion, &tcam->vregion_list, tlist) { if (val) - mlxsw_core_schedule_dw(&vregion->rehash_dw, 0); + mlxsw_core_schedule_dw(&vregion->rehash.dw, 0); else - cancel_delayed_work_sync(&vregion->rehash_dw); + cancel_delayed_work_sync(&vregion->rehash.dw); } mutex_unlock(&tcam->lock); return 0; -- cgit v1.2.3 From 6ca219e7de9fb54b4eac9c3f14a0cdf2b39d723d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:17 +0000 Subject: mlxsw: spectrum_acl: Don't migrate already migrated entry Check if the entry is already in a chunk where we want it to be. In that case, skip migration. This is preparation for "per parts" migration where this situation may occur. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index e2699373dfa7..30131ea2e324 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1174,6 +1174,10 @@ mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_entry *entry2; + /* First check if the entry is not already where we want it to be. */ + if (ventry->entry->chunk == chunk2) + return 0; + entry2 = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk2); if (IS_ERR(entry2)) return PTR_ERR(entry2); -- cgit v1.2.3 From 559c27681058783c4c3d50ddb5ed8a64792e78ec Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:18 +0000 Subject: mlxsw: spectrum_acl: Introduce new rehash context struct and save hint_priv there Prepare for continued migration. Introduce a new structure to track rehash context and save hint_priv into it. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 30131ea2e324..ae1101c17f2c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -180,6 +180,10 @@ struct mlxsw_sp_acl_tcam_vgroup { bool vregion_rehash_enabled; }; +struct mlxsw_sp_acl_tcam_rehash_ctx { + void *hints_priv; +}; + struct mlxsw_sp_acl_tcam_vregion { struct mutex lock; /* Protects consistency of region, region2 pointers * and vchunk_list. @@ -194,6 +198,7 @@ struct mlxsw_sp_acl_tcam_vregion { struct mlxsw_sp_acl_tcam_vgroup *vgroup; struct { struct delayed_work dw; + struct mlxsw_sp_acl_tcam_rehash_ctx ctx; } rehash; struct mlxsw_sp *mlxsw_sp; bool failed_rollback; /* Indicates failed rollback during migration */ @@ -1270,7 +1275,7 @@ rollback: static int mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, - void *hints_priv) + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion); struct mlxsw_sp_acl_tcam_region *region2, *unused_region; @@ -1279,7 +1284,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam, - vregion, hints_priv); + vregion, ctx->hints_priv); if (IS_ERR(region2)) { err = PTR_ERR(region2); goto out; @@ -1333,6 +1338,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx; void *hints_priv; int err; @@ -1347,8 +1353,9 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n"); return err; } + ctx->hints_priv = hints_priv; - err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, hints_priv); + err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, ctx); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); if (vregion->failed_rollback) { @@ -1358,7 +1365,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, } } - ops->region_rehash_hints_put(hints_priv); + ops->region_rehash_hints_put(ctx->hints_priv); + ctx->hints_priv = NULL; return err; } -- cgit v1.2.3 From 1667f7667d85e184bc731884bf9588bed89cca80 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:19 +0000 Subject: mlxsw: spectrum_acl: Push rehash start/end code into separate functions In preparations for interrupt/continue of rehash work, put the code at the beginning/end of the rehash function into separate functions. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 41 +++++++++++++++++----- 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index ae1101c17f2c..fa204003bc84 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1334,26 +1334,50 @@ out: } static int -mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vregion *vregion) +mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion, + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx; void *hints_priv; - int err; trace_mlxsw_sp_acl_tcam_vregion_rehash(mlxsw_sp, vregion); if (vregion->failed_rollback) return -EBUSY; hints_priv = ops->region_rehash_hints_get(vregion->region->priv); - if (IS_ERR(hints_priv)) { - err = PTR_ERR(hints_priv); + if (IS_ERR(hints_priv)) + return PTR_ERR(hints_priv); + + ctx->hints_priv = hints_priv; + + return 0; +} + +static void +mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion, + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) +{ + const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + + ops->region_rehash_hints_put(ctx->hints_priv); + ctx->hints_priv = NULL; +} + +static int +mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vregion *vregion) +{ + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx; + int err; + + err = mlxsw_sp_acl_tcam_vregion_rehash_start(mlxsw_sp, vregion, ctx); + if (err) { if (err != -EAGAIN) dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n"); return err; } - ctx->hints_priv = hints_priv; err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, ctx); if (err) { @@ -1365,8 +1389,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, } } - ops->region_rehash_hints_put(ctx->hints_priv); - ctx->hints_priv = NULL; + mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx); return err; } -- cgit v1.2.3 From a9550d0f075a0c59dc199c817d31354bacde9906 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:19 +0000 Subject: mlxsw: spectrum_acl: Push code start/end from mlxsw_sp_acl_tcam_vregion_migrate() Push code from the beginning and end of function mlxsw_sp_acl_tcam_vregion_migrate() into rehash_start()/end() functions. Then all the things needed to be done before and after the actual migration process will be grouped together. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 74 ++++++++++------------ 1 file changed, 35 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index fa204003bc84..cf901a1504c4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1277,59 +1277,24 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { - unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion); - struct mlxsw_sp_acl_tcam_region *region2, *unused_region; int err; trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); - - region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam, - vregion, ctx->hints_priv); - if (IS_ERR(region2)) { - err = PTR_ERR(region2); - goto out; - } - - vregion->region2 = region2; - err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, - vregion->region->group, - region2, priority, - vregion->region); - if (err) - goto err_group_region_attach; - mutex_lock(&vregion->lock); err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion); if (!vregion->failed_rollback) { if (!err) { /* In case of successful migration, region2 is used and - * the original is unused. - */ - unused_region = vregion->region; - vregion->region = vregion->region2; - } else { - /* In case of failure during migration, the original - * region is still used. + * the original is unused. So swap them. */ - unused_region = vregion->region2; + swap(vregion->region, vregion->region2); } - mutex_unlock(&vregion->lock); - vregion->region2 = NULL; - mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, unused_region); - mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, unused_region); - } else { - mutex_unlock(&vregion->lock); + /* vregion->region2 contains pointer to unused region now. */ } - goto out; - -err_group_region_attach: - vregion->region2 = NULL; - mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2); -out: + mutex_unlock(&vregion->lock); trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion); - return err; } @@ -1339,7 +1304,10 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion); + struct mlxsw_sp_acl_tcam_region *region2; void *hints_priv; + int err; trace_mlxsw_sp_acl_tcam_vregion_rehash(mlxsw_sp, vregion); if (vregion->failed_rollback) @@ -1349,9 +1317,31 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, if (IS_ERR(hints_priv)) return PTR_ERR(hints_priv); + region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam, + vregion, hints_priv); + if (IS_ERR(region2)) { + err = PTR_ERR(region2); + goto err_region_create; + } + + vregion->region2 = region2; + err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, + vregion->region->group, + region2, priority, + vregion->region); + if (err) + goto err_group_region_attach; + ctx->hints_priv = hints_priv; return 0; + +err_group_region_attach: + vregion->region2 = NULL; + mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2); +err_region_create: + ops->region_rehash_hints_put(hints_priv); + return err; } static void @@ -1359,8 +1349,14 @@ mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { + struct mlxsw_sp_acl_tcam_region *unused_region = vregion->region2; const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + if (!vregion->failed_rollback) { + vregion->region2 = NULL; + mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, unused_region); + mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, unused_region); + } ops->region_rehash_hints_put(ctx->hints_priv); ctx->hints_priv = NULL; } -- cgit v1.2.3 From a86838e46b1dc1f7ecc2eb769ea1966380409025 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:20 +0000 Subject: mlxsw: spectrum_acl: assign vregion->region by the newly created region Make the vregion->region contain pointer of a new region we migrate to. In case of a rollback, it contains the original region. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 42 +++++++++++----------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index cf901a1504c4..72734ee60a1e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1256,7 +1256,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, list_for_each_entry(vchunk, &vregion->vchunk_list, list) { err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, - vregion->region2, + vregion->region, false); if (err) goto rollback; @@ -1264,6 +1264,10 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, return 0; rollback: + /* In case migration was not successful, we need to swap + * so the original region pointer is assigned again to vregion->region. + */ + swap(vregion->region, vregion->region2); list_for_each_entry_continue_reverse(vchunk, &vregion->vchunk_list, list) { mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, @@ -1281,18 +1285,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); mutex_lock(&vregion->lock); - err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion); - if (!vregion->failed_rollback) { - if (!err) { - /* In case of successful migration, region2 is used and - * the original is unused. So swap them. - */ - swap(vregion->region, vregion->region2); - } - /* vregion->region2 contains pointer to unused region now. */ - } - mutex_unlock(&vregion->lock); trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion); return err; @@ -1305,7 +1298,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, { const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; unsigned int priority = mlxsw_sp_acl_tcam_vregion_prio(vregion); - struct mlxsw_sp_acl_tcam_region *region2; + struct mlxsw_sp_acl_tcam_region *new_region; void *hints_priv; int err; @@ -1317,18 +1310,22 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, if (IS_ERR(hints_priv)) return PTR_ERR(hints_priv); - region2 = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam, - vregion, hints_priv); - if (IS_ERR(region2)) { - err = PTR_ERR(region2); + new_region = mlxsw_sp_acl_tcam_region_create(mlxsw_sp, vregion->tcam, + vregion, hints_priv); + if (IS_ERR(new_region)) { + err = PTR_ERR(new_region); goto err_region_create; } - vregion->region2 = region2; + /* vregion->region contains the pointer to the new region + * we are going to migrate to. + */ + vregion->region2 = vregion->region; + vregion->region = new_region; err = mlxsw_sp_acl_tcam_group_region_attach(mlxsw_sp, - vregion->region->group, - region2, priority, - vregion->region); + vregion->region2->group, + new_region, priority, + vregion->region2); if (err) goto err_group_region_attach; @@ -1337,8 +1334,9 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, return 0; err_group_region_attach: + vregion->region = vregion->region2; vregion->region2 = NULL; - mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, region2); + mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, new_region); err_region_create: ops->region_rehash_hints_put(hints_priv); return err; -- cgit v1.2.3 From e1d2f7a97261dc0e5bec44edb64fe5bcfb994971 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:21 +0000 Subject: mlxsw: spectrum_acl: assign vchunk->chunk by the newly created chunk Make the vchunk->chunk contain pointer of a new chunk we migrate to. In case of a rollback, it contains the original chunk. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 72734ee60a1e..6a50266b6809 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1197,21 +1197,23 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_region *region, bool this_is_rollback) { + struct mlxsw_sp_acl_tcam_chunk *new_chunk; struct mlxsw_sp_acl_tcam_ventry *ventry; - struct mlxsw_sp_acl_tcam_chunk *chunk2; int err; int err2; - chunk2 = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region); - if (IS_ERR(chunk2)) { + new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region); + if (IS_ERR(new_chunk)) { if (this_is_rollback) vchunk->vregion->failed_rollback = true; - return PTR_ERR(chunk2); + return PTR_ERR(new_chunk); } - vchunk->chunk2 = chunk2; + vchunk->chunk2 = vchunk->chunk; + vchunk->chunk = new_chunk; + list_for_each_entry(ventry, &vchunk->ventry_list, list) { err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, - vchunk->chunk2); + vchunk->chunk); if (err) { if (this_is_rollback) { vchunk->vregion->failed_rollback = true; @@ -1220,8 +1222,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, goto rollback; } } - mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk); - vchunk->chunk = chunk2; + mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); vchunk->chunk2 = NULL; return 0; @@ -1230,6 +1231,7 @@ rollback: * migration fails, there's no good way how to proceed. Set the * vregion with "failed_rollback" flag. */ + swap(vchunk->chunk, vchunk->chunk2); list_for_each_entry_continue_reverse(ventry, &vchunk->ventry_list, list) { err2 = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, -- cgit v1.2.3 From 2c331593c99e0c9bf9bb27b8afa92d96d4decac8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:22 +0000 Subject: mlxsw: spectrum_acl: Rename variables in mlxsw_sp_acl_tcam_ventry_migrate() Remove some of variables in function mlxsw_sp_acl_tcam_ventry_migrate() so the names are aligned with the rest of the code. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 6a50266b6809..0bc04016c6d0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1175,19 +1175,19 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_ventry *ventry, - struct mlxsw_sp_acl_tcam_chunk *chunk2) + struct mlxsw_sp_acl_tcam_chunk *chunk) { - struct mlxsw_sp_acl_tcam_entry *entry2; + struct mlxsw_sp_acl_tcam_entry *new_entry; /* First check if the entry is not already where we want it to be. */ - if (ventry->entry->chunk == chunk2) + if (ventry->entry->chunk == chunk) return 0; - entry2 = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk2); - if (IS_ERR(entry2)) - return PTR_ERR(entry2); + new_entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk); + if (IS_ERR(new_entry)) + return PTR_ERR(new_entry); mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry); - ventry->entry = entry2; + ventry->entry = new_entry; return 0; } -- cgit v1.2.3 From 220f4fba3d64b484840d451cd1367de03dbb836e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:23 +0000 Subject: mlxsw: spectrum_acl: Put this_is_rollback to rehash context struct Put the this_is_rollback flag into rehash context struct in preparations for interrupt/continue of rehash work. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 0bc04016c6d0..db80b20e4a13 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -182,6 +182,7 @@ struct mlxsw_sp_acl_tcam_vgroup { struct mlxsw_sp_acl_tcam_rehash_ctx { void *hints_priv; + bool this_is_rollback; }; struct mlxsw_sp_acl_tcam_vregion { @@ -1195,7 +1196,7 @@ static int mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vchunk *vchunk, struct mlxsw_sp_acl_tcam_region *region, - bool this_is_rollback) + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { struct mlxsw_sp_acl_tcam_chunk *new_chunk; struct mlxsw_sp_acl_tcam_ventry *ventry; @@ -1204,7 +1205,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region); if (IS_ERR(new_chunk)) { - if (this_is_rollback) + if (ctx->this_is_rollback) vchunk->vregion->failed_rollback = true; return PTR_ERR(new_chunk); } @@ -1215,7 +1216,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, vchunk->chunk); if (err) { - if (this_is_rollback) { + if (ctx->this_is_rollback) { vchunk->vregion->failed_rollback = true; return err; } @@ -1251,7 +1252,8 @@ err_rollback: static int mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vregion *vregion) + struct mlxsw_sp_acl_tcam_vregion *vregion, + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; @@ -1259,7 +1261,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, list_for_each_entry(vchunk, &vregion->vchunk_list, list) { err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, vregion->region, - false); + ctx); if (err) goto rollback; } @@ -1270,10 +1272,12 @@ rollback: * so the original region pointer is assigned again to vregion->region. */ swap(vregion->region, vregion->region2); + ctx->this_is_rollback = true; list_for_each_entry_continue_reverse(vchunk, &vregion->vchunk_list, list) { mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, - vregion->region, true); + vregion->region, + ctx); } return err; } @@ -1287,7 +1291,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); mutex_lock(&vregion->lock); - err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion); + err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx); mutex_unlock(&vregion->lock); trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion); return err; @@ -1332,6 +1336,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, goto err_group_region_attach; ctx->hints_priv = hints_priv; + ctx->this_is_rollback = false; return 0; -- cgit v1.2.3 From 844f01da9301a71fbed1e768837f4a1a6aa60529 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:24 +0000 Subject: mlxsw: spectrum_acl: Put vchunk migrate start/end code into separate functions In preparations of interrupt/continue of rehash work, put the code that is done at the beginning/end of vchunk migrate function into separate functions. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 43 ++++++++++++++++------ 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index db80b20e4a13..1f308ad4b635 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1193,15 +1193,12 @@ mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp, } static int -mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vchunk *vchunk, - struct mlxsw_sp_acl_tcam_region *region, - struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) +mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vchunk *vchunk, + struct mlxsw_sp_acl_tcam_region *region, + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { struct mlxsw_sp_acl_tcam_chunk *new_chunk; - struct mlxsw_sp_acl_tcam_ventry *ventry; - int err; - int err2; new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region); if (IS_ERR(new_chunk)) { @@ -1211,6 +1208,31 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, } vchunk->chunk2 = vchunk->chunk; vchunk->chunk = new_chunk; + return 0; +} + +static void +mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vchunk *vchunk) +{ + mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); + vchunk->chunk2 = NULL; +} + +static int +mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, + struct mlxsw_sp_acl_tcam_vchunk *vchunk, + struct mlxsw_sp_acl_tcam_region *region, + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) +{ + struct mlxsw_sp_acl_tcam_ventry *ventry; + int err; + int err2; + + err = mlxsw_sp_acl_tcam_vchunk_migrate_start(mlxsw_sp, vchunk, + region, ctx); + if (err) + return err; list_for_each_entry(ventry, &vchunk->ventry_list, list) { err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, @@ -1223,8 +1245,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, goto rollback; } } - mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); - vchunk->chunk2 = NULL; + + mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk); return 0; rollback: @@ -1243,8 +1265,7 @@ rollback: } } - mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); - vchunk->chunk2 = NULL; + mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk); err_rollback: return err; -- cgit v1.2.3 From 843500518509128a935edab96bd8efef7c54669e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:24 +0000 Subject: mlxsw: spectrum_acl: Do rollback as another call to mlxsw_sp_acl_tcam_vchunk_migrate_all() In order to simplify the code and to prepare it for interrupted/continued migration process, do the rollback in case of migration error as another call to mlxsw_sp_acl_tcam_vchunk_migrate_all(). It can be understood as "migrate all back". Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 75 +++++++++------------- 1 file changed, 29 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 1f308ad4b635..9dc83815644e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1227,48 +1227,34 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_ventry *ventry; int err; - int err2; - err = mlxsw_sp_acl_tcam_vchunk_migrate_start(mlxsw_sp, vchunk, - region, ctx); - if (err) - return err; + if (vchunk->chunk->region != region) { + err = mlxsw_sp_acl_tcam_vchunk_migrate_start(mlxsw_sp, vchunk, + region, ctx); + if (err) + return err; + } else if (!vchunk->chunk2) { + /* The chunk is already as it should be, nothing to do. */ + return 0; + } list_for_each_entry(ventry, &vchunk->ventry_list, list) { err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, vchunk->chunk); if (err) { - if (ctx->this_is_rollback) { - vchunk->vregion->failed_rollback = true; + if (ctx->this_is_rollback) return err; - } - goto rollback; + /* Swap the chunk and chunk2 pointers so the follow-up + * rollback call will see the original chunk pointer + * in vchunk->chunk. + */ + swap(vchunk->chunk, vchunk->chunk2); + return err; } } mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk); return 0; - -rollback: - /* Migrate the entries back to the original chunk. If some entry - * migration fails, there's no good way how to proceed. Set the - * vregion with "failed_rollback" flag. - */ - swap(vchunk->chunk, vchunk->chunk2); - list_for_each_entry_continue_reverse(ventry, &vchunk->ventry_list, - list) { - err2 = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, - vchunk->chunk); - if (err2) { - vchunk->vregion->failed_rollback = true; - goto err_rollback; - } - } - - mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk); - -err_rollback: - return err; } static int @@ -1284,23 +1270,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, vregion->region, ctx); if (err) - goto rollback; + return err; } return 0; - -rollback: - /* In case migration was not successful, we need to swap - * so the original region pointer is assigned again to vregion->region. - */ - swap(vregion->region, vregion->region2); - ctx->this_is_rollback = true; - list_for_each_entry_continue_reverse(vchunk, &vregion->vchunk_list, - list) { - mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, - vregion->region, - ctx); - } - return err; } static int @@ -1308,11 +1280,22 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { - int err; + int err, err2; trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); mutex_lock(&vregion->lock); err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx); + if (err) { + /* In case migration was not successful, we need to swap + * so the original region pointer is assigned again + * to vregion->region. + */ + swap(vregion->region, vregion->region2); + ctx->this_is_rollback = true; + err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx); + if (err2) + vregion->failed_rollback = true; + } mutex_unlock(&vregion->lock); trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion); return err; -- cgit v1.2.3 From c9c9af91f1d9a636aecc55302c792538e549a430 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:25 +0000 Subject: mlxsw: spectrum_acl: Allow to interrupt/continue rehash work Currently, migration of vregions with many entries may take long time during which insertions and removals of the rules are blocked due to wait to acquire vregion->lock. To overcome this, allow to interrupt and continue rehash work according to the set credits - number of rules to migrate. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 82 ++++++++++++++++------ 1 file changed, 62 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 9dc83815644e..cfd05af3f0f6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -27,6 +27,7 @@ size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp) #define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT 5000 /* ms */ #define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN 3000 /* ms */ +#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS 100 /* number of entries */ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam) @@ -732,16 +733,26 @@ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion static int mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vregion *vregion); + struct mlxsw_sp_acl_tcam_vregion *vregion, + int *credits); static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) { struct mlxsw_sp_acl_tcam_vregion *vregion = container_of(work, struct mlxsw_sp_acl_tcam_vregion, rehash.dw.work); + int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS; + int err; - mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion); - mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); + err = mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, + vregion, &credits); + if (credits < 0) + /* Rehash gone out of credits so it was interrupted. + * Schedule the work as soon as possible to continue. + */ + mlxsw_core_schedule_dw(&vregion->rehash.dw, 0); + else + mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); } static struct mlxsw_sp_acl_tcam_vregion * @@ -1176,7 +1187,8 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_ventry *ventry, - struct mlxsw_sp_acl_tcam_chunk *chunk) + struct mlxsw_sp_acl_tcam_chunk *chunk, + int *credits) { struct mlxsw_sp_acl_tcam_entry *new_entry; @@ -1184,6 +1196,9 @@ mlxsw_sp_acl_tcam_ventry_migrate(struct mlxsw_sp *mlxsw_sp, if (ventry->entry->chunk == chunk) return 0; + if (--(*credits) < 0) + return 0; + new_entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry, chunk); if (IS_ERR(new_entry)) return PTR_ERR(new_entry); @@ -1223,7 +1238,8 @@ static int mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vchunk *vchunk, struct mlxsw_sp_acl_tcam_region *region, - struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx, + int *credits) { struct mlxsw_sp_acl_tcam_ventry *ventry; int err; @@ -1240,7 +1256,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, list_for_each_entry(ventry, &vchunk->ventry_list, list) { err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, - vchunk->chunk); + vchunk->chunk, credits); if (err) { if (ctx->this_is_rollback) return err; @@ -1250,6 +1266,11 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, */ swap(vchunk->chunk, vchunk->chunk2); return err; + } else if (*credits < 0) { + /* We are out of credits, the rest of the ventries + * will be migrated later. + */ + return 0; } } @@ -1260,7 +1281,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, - struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx, + int *credits) { struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; @@ -1268,8 +1290,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, list_for_each_entry(vchunk, &vregion->vchunk_list, list) { err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, vregion->region, - ctx); - if (err) + ctx, credits); + if (err || *credits < 0) return err; } return 0; @@ -1278,13 +1300,15 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, - struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx, + int *credits) { int err, err2; trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); mutex_lock(&vregion->lock); - err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx); + err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, + ctx, credits); if (err) { /* In case migration was not successful, we need to swap * so the original region pointer is assigned again @@ -1292,7 +1316,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, */ swap(vregion->region, vregion->region2); ctx->this_is_rollback = true; - err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx); + err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, + ctx, credits); if (err2) vregion->failed_rollback = true; } @@ -1301,6 +1326,12 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, return err; } +static bool +mlxsw_sp_acl_tcam_vregion_rehash_in_progress(const struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) +{ + return ctx->hints_priv; +} + static int mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, @@ -1372,19 +1403,28 @@ mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vregion *vregion) + struct mlxsw_sp_acl_tcam_vregion *vregion, + int *credits) { struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx; int err; - err = mlxsw_sp_acl_tcam_vregion_rehash_start(mlxsw_sp, vregion, ctx); - if (err) { - if (err != -EAGAIN) - dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n"); - return err; + /* Check if the previous rehash work was interrupted + * which means we have to continue it now. + * If not, start a new rehash. + */ + if (!mlxsw_sp_acl_tcam_vregion_rehash_in_progress(ctx)) { + err = mlxsw_sp_acl_tcam_vregion_rehash_start(mlxsw_sp, + vregion, ctx); + if (err) { + if (err != -EAGAIN) + dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n"); + return err; + } } - err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, ctx); + err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, + ctx, credits); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); if (vregion->failed_rollback) { @@ -1394,7 +1434,9 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, } } - mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx); + if (*credits >= 0) + mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx); + return err; } -- cgit v1.2.3 From 6f9579d4e3021b17b0a4cde6b04a6c94c9575cdf Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:26 +0000 Subject: mlxsw: spectrum_acl: Remember where to continue rehash migration Store pointer to vchunk where the migration was interrupted, as well as ventry pointer to start from and to stop at (during rollback). This saved pointers need to be forgotten in case of ventries list or vchunk list changes, which is done by couple of "changed" helpers. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 91 ++++++++++++++++++++-- 1 file changed, 86 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index cfd05af3f0f6..dc118ed714b2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -184,6 +184,19 @@ struct mlxsw_sp_acl_tcam_vgroup { struct mlxsw_sp_acl_tcam_rehash_ctx { void *hints_priv; bool this_is_rollback; + struct mlxsw_sp_acl_tcam_vchunk *current_vchunk; /* vchunk being + * currently migrated. + */ + struct mlxsw_sp_acl_tcam_ventry *start_ventry; /* ventry to start + * migration from in + * a vchunk being + * currently migrated. + */ + struct mlxsw_sp_acl_tcam_ventry *stop_ventry; /* ventry to stop + * migration at + * a vchunk being + * currently migrated. + */ }; struct mlxsw_sp_acl_tcam_vregion { @@ -755,6 +768,31 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); } +static void +mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk) +{ + struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion; + + /* If a rule was added or deleted from vchunk which is currently + * under rehash migration, we have to reset the ventry pointers + * to make sure all rules are properly migrated. + */ + if (vregion->rehash.ctx.current_vchunk == vchunk) { + vregion->rehash.ctx.start_ventry = NULL; + vregion->rehash.ctx.stop_ventry = NULL; + } +} + +static void +mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *vregion) +{ + /* If a chunk was added or deleted from vregion we have to reset + * the current chunk pointer to make sure all chunks + * are properly migrated. + */ + vregion->rehash.ctx.current_vchunk = NULL; +} + static struct mlxsw_sp_acl_tcam_vregion * mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vgroup *vgroup, @@ -989,6 +1027,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp, goto err_chunk_create; } + mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(vregion); list_add_tail(&vchunk->list, &vregion->vchunk_list); mutex_unlock(&vregion->lock); @@ -1012,6 +1051,7 @@ mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup; mutex_lock(&vregion->lock); + mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(vregion); list_del(&vchunk->list); if (vchunk->chunk2) mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); @@ -1141,6 +1181,7 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp, } list_add_tail(&ventry->list, &vchunk->ventry_list); + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(vchunk); mutex_unlock(&vregion->lock); return 0; @@ -1157,6 +1198,7 @@ static void mlxsw_sp_acl_tcam_ventry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion; mutex_lock(&vregion->lock); + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(vchunk); list_del(&ventry->list); mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry); mutex_unlock(&vregion->lock); @@ -1223,15 +1265,20 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp, } vchunk->chunk2 = vchunk->chunk; vchunk->chunk = new_chunk; + ctx->current_vchunk = vchunk; + ctx->start_ventry = NULL; + ctx->stop_ventry = NULL; return 0; } static void mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp, - struct mlxsw_sp_acl_tcam_vchunk *vchunk) + struct mlxsw_sp_acl_tcam_vchunk *vchunk, + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) { mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); vchunk->chunk2 = NULL; + ctx->current_vchunk = NULL; } static int @@ -1254,7 +1301,22 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, return 0; } - list_for_each_entry(ventry, &vchunk->ventry_list, list) { + /* If the migration got interrupted, we have the ventry to start from + * stored in context. + */ + if (ctx->start_ventry) + ventry = ctx->start_ventry; + else + ventry = list_first_entry(&vchunk->ventry_list, + typeof(*ventry), list); + + list_for_each_entry_from(ventry, &vchunk->ventry_list, list) { + /* During rollback, once we reach the ventry that failed + * to migrate, we are done. + */ + if (ventry == ctx->stop_ventry) + break; + err = mlxsw_sp_acl_tcam_ventry_migrate(mlxsw_sp, ventry, vchunk->chunk, credits); if (err) { @@ -1265,16 +1327,25 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, * in vchunk->chunk. */ swap(vchunk->chunk, vchunk->chunk2); + /* The rollback has to be done from beginning of the + * chunk, that is why we have to null the start_ventry. + * However, we know where to stop the rollback, + * at the current ventry. + */ + ctx->start_ventry = NULL; + ctx->stop_ventry = ventry; return err; } else if (*credits < 0) { /* We are out of credits, the rest of the ventries - * will be migrated later. + * will be migrated later. Save the ventry + * which we ended with. */ + ctx->start_ventry = ventry; return 0; } } - mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk); + mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx); return 0; } @@ -1287,7 +1358,16 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; - list_for_each_entry(vchunk, &vregion->vchunk_list, list) { + /* If the migration got interrupted, we have the vchunk + * we are working on stored in context. + */ + if (ctx->current_vchunk) + vchunk = ctx->current_vchunk; + else + vchunk = list_first_entry(&vregion->vchunk_list, + typeof(*vchunk), list); + + list_for_each_entry_from(vchunk, &vregion->vchunk_list, list) { err = mlxsw_sp_acl_tcam_vchunk_migrate_one(mlxsw_sp, vchunk, vregion->region, ctx, credits); @@ -1315,6 +1395,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, * to vregion->region. */ swap(vregion->region, vregion->region2); + ctx->current_vchunk = NULL; ctx->this_is_rollback = true; err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx, credits); -- cgit v1.2.3 From b2c091ce46a7e08d776160d2f1b8ccabc85410b3 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 28 Feb 2019 06:59:27 +0000 Subject: mlxsw: spectrum_acl: Make mlxsw_sp_acl_tcam_vregion_rehash() return void The return value is ignored anyway, so just return void. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index dc118ed714b2..8811f6513e36 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -744,7 +744,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion msecs_to_jiffies(interval)); } -static int +static void mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, int *credits); @@ -755,10 +755,8 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) container_of(work, struct mlxsw_sp_acl_tcam_vregion, rehash.dw.work); int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS; - int err; - err = mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, - vregion, &credits); + mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits); if (credits < 0) /* Rehash gone out of credits so it was interrupted. * Schedule the work as soon as possible to continue. @@ -1482,7 +1480,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp, ctx->hints_priv = NULL; } -static int +static void mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vregion *vregion, int *credits) @@ -1500,7 +1498,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, if (err) { if (err != -EAGAIN) dev_err(mlxsw_sp->bus_info->dev, "Failed get rehash hints\n"); - return err; + return; } } @@ -1517,8 +1515,6 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, if (*credits >= 0) mlxsw_sp_acl_tcam_vregion_rehash_end(mlxsw_sp, vregion, ctx); - - return err; } static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = { -- cgit v1.2.3 From f819cd926ca7c9105fa0086dcb7e5930c200d6c6 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 1 Mar 2019 16:09:00 +0800 Subject: drivers: net: Remove unnecessary semicolon drivers/net/dsa/mt7530.c:649:3-4: Unneeded semicolon drivers/net/ethernet/cisco/enic/enic_clsf.c:35:2-3: Unneeded semicolon drivers/net/ethernet/faraday/ftgmac100.c:1640:2-3: Unneeded semicolon drivers/net/ethernet/mediatek/mtk_eth_soc.c:229:2-3: Unneeded semicolon drivers/net/usb/sr9700.c:437:2-3: Unneeded semicolon Remove unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Signed-off-by: YueHaibing Acked-by: Sean Wang for mt7530 and mtk_eth_soc Signed-off-by: David S. Miller --- drivers/net/dsa/mt7530.c | 2 +- drivers/net/ethernet/cisco/enic/enic_clsf.c | 3 ++- drivers/net/ethernet/faraday/ftgmac100.c | 2 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- drivers/net/usb/sr9700.c | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 0390c5e8271a..7357b4fc0185 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -646,7 +646,7 @@ static void mt7530_adjust_link(struct dsa_switch *ds, int port, case SPEED_100: mcr |= PMCR_FORCE_SPEED_100; break; - }; + } if (phydev->link) mcr |= PMCR_FORCE_LNK; diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c index 99038dfc7fbe..9900993b6aea 100644 --- a/drivers/net/ethernet/cisco/enic/enic_clsf.c +++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c @@ -32,7 +32,8 @@ int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq) break; default: return -EPROTONOSUPPORT; - }; + } + data.type = FILTER_IPV4_5TUPLE; data.u.ipv4.src_addr = ntohl(keys->addrs.v4addrs.src); data.u.ipv4.dst_addr = ntohl(keys->addrs.v4addrs.dst); diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index 3e5e97186fc4..b17b79e612a3 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -1637,7 +1637,7 @@ static int ftgmac100_setup_mdio(struct net_device *netdev) reg = ioread32(priv->base + FTGMAC100_OFFSET_REVR); reg &= ~FTGMAC100_REVR_NEW_MDIO_INTERFACE; iowrite32(reg, priv->base + FTGMAC100_OFFSET_REVR); - }; + } /* Get PHY mode from device-tree */ if (np) { diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 94d4663e3933..549d36497b8c 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -226,7 +226,7 @@ static void mtk_phy_link_adjust(struct net_device *dev) case SPEED_100: mcr |= MAC_MCR_SPEED_100; break; - }; + } if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) && !mac->id && !mac->trgmii) diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c index 6ac232e52bf7..e04c8054c2cf 100644 --- a/drivers/net/usb/sr9700.c +++ b/drivers/net/usb/sr9700.c @@ -434,7 +434,7 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb) usbnet_skb_return(dev, sr_skb); skb_pull(skb, len + SR_RX_OVERHEAD); - }; + } return 0; } -- cgit v1.2.3 From 3d78bfaa2eb92845c0595b09ec7b3dde572009bd Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Fri, 1 Mar 2019 15:42:39 +0530 Subject: cxgb4vf: Prefix adapter flags with CXGB4VF Some of these macros were conflicting with global namespace, hence prefixing them with CXGB4VF. Signed-off-by: Arjun Vynipadath Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4vf/adapter.h | 12 ++-- .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 68 +++++++++++----------- drivers/net/ethernet/chelsio/cxgb4vf/sge.c | 10 ++-- 3 files changed, 47 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h index 86cf68fceceb..3782e48dada2 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h +++ b/drivers/net/ethernet/chelsio/cxgb4vf/adapter.h @@ -406,12 +406,12 @@ struct adapter { }; enum { /* adapter flags */ - FULL_INIT_DONE = (1UL << 0), - USING_MSI = (1UL << 1), - USING_MSIX = (1UL << 2), - QUEUES_BOUND = (1UL << 3), - ROOT_NO_RELAXED_ORDERING = (1UL << 4), - FW_OK = (1UL << 5), + CXGB4VF_FULL_INIT_DONE = (1UL << 0), + CXGB4VF_USING_MSI = (1UL << 1), + CXGB4VF_USING_MSIX = (1UL << 2), + CXGB4VF_QUEUES_BOUND = (1UL << 3), + CXGB4VF_ROOT_NO_RELAXED_ORDERING = (1UL << 4), + CXGB4VF_FW_OK = (1UL << 5), }; /* diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 2c56bd810931..6b2754a574d6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -469,7 +469,7 @@ static void enable_rx(struct adapter *adapter) * The interrupt queue doesn't use NAPI so we do the 0-increment of * its Going To Sleep register here to get it started. */ - if (adapter->flags & USING_MSI) + if (adapter->flags & CXGB4VF_USING_MSI) t4_write_reg(adapter, T4VF_SGE_BASE_ADDR + SGE_VF_GTS, CIDXINC_V(0) | SEINTARM_V(s->intrq.intr_params) | @@ -613,7 +613,7 @@ static int setup_sge_queues(struct adapter *adapter) * the intrq's queue ID as the interrupt forwarding queue for the * subsequent calls ... */ - if (adapter->flags & USING_MSI) { + if (adapter->flags & CXGB4VF_USING_MSI) { err = t4vf_sge_alloc_rxq(adapter, &s->intrq, false, adapter->port[0], 0, NULL, NULL); if (err) @@ -773,7 +773,7 @@ static int adapter_up(struct adapter *adapter) * adapter setup. Once we've done this, many of our adapter * parameters can no longer be changed ... */ - if ((adapter->flags & FULL_INIT_DONE) == 0) { + if ((adapter->flags & CXGB4VF_FULL_INIT_DONE) == 0) { err = setup_sge_queues(adapter); if (err) return err; @@ -783,17 +783,18 @@ static int adapter_up(struct adapter *adapter) return err; } - if (adapter->flags & USING_MSIX) + if (adapter->flags & CXGB4VF_USING_MSIX) name_msix_vecs(adapter); - adapter->flags |= FULL_INIT_DONE; + adapter->flags |= CXGB4VF_FULL_INIT_DONE; } /* * Acquire our interrupt resources. We only support MSI-X and MSI. */ - BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0); - if (adapter->flags & USING_MSIX) + BUG_ON((adapter->flags & + (CXGB4VF_USING_MSIX | CXGB4VF_USING_MSI)) == 0); + if (adapter->flags & CXGB4VF_USING_MSIX) err = request_msix_queue_irqs(adapter); else err = request_irq(adapter->pdev->irq, @@ -824,7 +825,7 @@ static void adapter_down(struct adapter *adapter) /* * Free interrupt resources. */ - if (adapter->flags & USING_MSIX) + if (adapter->flags & CXGB4VF_USING_MSIX) free_msix_queue_irqs(adapter); else free_irq(adapter->pdev->irq, adapter); @@ -848,7 +849,7 @@ static int cxgb4vf_open(struct net_device *dev) * If we don't have a connection to the firmware there's nothing we * can do. */ - if (!(adapter->flags & FW_OK)) + if (!(adapter->flags & CXGB4VF_FW_OK)) return -ENXIO; /* @@ -1240,7 +1241,7 @@ static void cxgb4vf_poll_controller(struct net_device *dev) struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; - if (adapter->flags & USING_MSIX) { + if (adapter->flags & CXGB4VF_USING_MSIX) { struct sge_eth_rxq *rxq; int nqsets; @@ -1655,7 +1656,7 @@ static int cxgb4vf_set_ringparam(struct net_device *dev, rp->tx_pending < MIN_TXQ_ENTRIES) return -EINVAL; - if (adapter->flags & FULL_INIT_DONE) + if (adapter->flags & CXGB4VF_FULL_INIT_DONE) return -EBUSY; for (qs = pi->first_qset; qs < pi->first_qset + pi->nqsets; qs++) { @@ -2172,7 +2173,7 @@ static int sge_qinfo_show(struct seq_file *seq, void *v) static int sge_queue_entries(const struct adapter *adapter) { return DIV_ROUND_UP(adapter->sge.ethqsets, QPL) + 1 + - ((adapter->flags & USING_MSI) != 0); + ((adapter->flags & CXGB4VF_USING_MSI) != 0); } static void *sge_queue_start(struct seq_file *seq, loff_t *pos) @@ -2318,7 +2319,7 @@ static int sge_qstats_show(struct seq_file *seq, void *v) static int sge_qstats_entries(const struct adapter *adapter) { return DIV_ROUND_UP(adapter->sge.ethqsets, QPL) + 1 + - ((adapter->flags & USING_MSI) != 0); + ((adapter->flags & CXGB4VF_USING_MSI) != 0); } static void *sge_qstats_start(struct seq_file *seq, loff_t *pos) @@ -2727,7 +2728,7 @@ static int adap_init0(struct adapter *adapter) */ size_nports_qsets(adapter); - adapter->flags |= FW_OK; + adapter->flags |= CXGB4VF_FW_OK; return 0; } @@ -2762,7 +2763,8 @@ static void cfg_queues(struct adapter *adapter) * support. In particular, this means that we need to know what kind * of interrupts we'll be using ... */ - BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0); + BUG_ON((adapter->flags & + (CXGB4VF_USING_MSIX | CXGB4VF_USING_MSI)) == 0); /* * Count the number of 10GbE Virtual Interfaces that we have. @@ -3088,7 +3090,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, * using Relaxed Ordering. */ if (!pcie_relaxed_ordering_enabled(pdev)) - adapter->flags |= ROOT_NO_RELAXED_ORDERING; + adapter->flags |= CXGB4VF_ROOT_NO_RELAXED_ORDERING; err = adap_init0(adapter); if (err) @@ -3164,7 +3166,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, * If we haven't been able to contact the firmware, there's * nothing else we can do for this "port" ... */ - if (!(adapter->flags & FW_OK)) + if (!(adapter->flags & CXGB4VF_FW_OK)) continue; viid = t4vf_alloc_vi(adapter, port_id); @@ -3214,7 +3216,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, * get MSI interrupts we bail with the error. */ if (msi == MSI_MSIX && enable_msix(adapter) == 0) - adapter->flags |= USING_MSIX; + adapter->flags |= CXGB4VF_USING_MSIX; else { if (msi == MSI_MSIX) { dev_info(adapter->pdev_dev, @@ -3234,7 +3236,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, " err=%d\n", err); goto err_free_dev; } - adapter->flags |= USING_MSI; + adapter->flags |= CXGB4VF_USING_MSI; } /* Now that we know how many "ports" we have and what interrupt @@ -3292,8 +3294,8 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, for_each_port(adapter, pidx) { dev_info(adapter->pdev_dev, "%s: Chelsio VF NIC PCIe %s\n", adapter->port[pidx]->name, - (adapter->flags & USING_MSIX) ? "MSI-X" : - (adapter->flags & USING_MSI) ? "MSI" : ""); + (adapter->flags & CXGB4VF_USING_MSIX) ? "MSI-X" : + (adapter->flags & CXGB4VF_USING_MSI) ? "MSI" : ""); } /* @@ -3306,12 +3308,12 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, * so far and return the error. */ err_disable_interrupts: - if (adapter->flags & USING_MSIX) { + if (adapter->flags & CXGB4VF_USING_MSIX) { pci_disable_msix(adapter->pdev); - adapter->flags &= ~USING_MSIX; - } else if (adapter->flags & USING_MSI) { + adapter->flags &= ~CXGB4VF_USING_MSIX; + } else if (adapter->flags & CXGB4VF_USING_MSI) { pci_disable_msi(adapter->pdev); - adapter->flags &= ~USING_MSI; + adapter->flags &= ~CXGB4VF_USING_MSI; } err_free_dev: @@ -3371,12 +3373,12 @@ static void cxgb4vf_pci_remove(struct pci_dev *pdev) if (test_bit(pidx, &adapter->registered_device_map)) unregister_netdev(adapter->port[pidx]); t4vf_sge_stop(adapter); - if (adapter->flags & USING_MSIX) { + if (adapter->flags & CXGB4VF_USING_MSIX) { pci_disable_msix(adapter->pdev); - adapter->flags &= ~USING_MSIX; - } else if (adapter->flags & USING_MSI) { + adapter->flags &= ~CXGB4VF_USING_MSIX; + } else if (adapter->flags & CXGB4VF_USING_MSI) { pci_disable_msi(adapter->pdev); - adapter->flags &= ~USING_MSI; + adapter->flags &= ~CXGB4VF_USING_MSI; } /* @@ -3448,12 +3450,12 @@ static void cxgb4vf_pci_shutdown(struct pci_dev *pdev) * Interrupts allowing various internal pathways to drain. */ t4vf_sge_stop(adapter); - if (adapter->flags & USING_MSIX) { + if (adapter->flags & CXGB4VF_USING_MSIX) { pci_disable_msix(adapter->pdev); - adapter->flags &= ~USING_MSIX; - } else if (adapter->flags & USING_MSI) { + adapter->flags &= ~CXGB4VF_USING_MSIX; + } else if (adapter->flags & CXGB4VF_USING_MSI) { pci_disable_msi(adapter->pdev); - adapter->flags &= ~USING_MSI; + adapter->flags &= ~CXGB4VF_USING_MSI; } /* diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index 11d2ba0a2bf5..f71c973398ec 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -2044,8 +2044,9 @@ static irqreturn_t t4vf_intr_msi(int irq, void *cookie) */ irq_handler_t t4vf_intr_handler(struct adapter *adapter) { - BUG_ON((adapter->flags & (USING_MSIX|USING_MSI)) == 0); - if (adapter->flags & USING_MSIX) + BUG_ON((adapter->flags & + (CXGB4VF_USING_MSIX | CXGB4VF_USING_MSI)) == 0); + if (adapter->flags & CXGB4VF_USING_MSIX) return t4vf_sge_intr_msix; else return t4vf_intr_msi; @@ -2209,7 +2210,7 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, struct port_info *pi = netdev_priv(dev); struct fw_iq_cmd cmd, rpl; int ret, iqandst, flsz = 0; - int relaxed = !(adapter->flags & ROOT_NO_RELAXED_ORDERING); + int relaxed = !(adapter->flags & CXGB4VF_ROOT_NO_RELAXED_ORDERING); /* * If we're using MSI interrupts and we're not initializing the @@ -2218,7 +2219,8 @@ int t4vf_sge_alloc_rxq(struct adapter *adapter, struct sge_rspq *rspq, * the Forwarded Interrupt Queue must be set up before any other * ingress queue ... */ - if ((adapter->flags & USING_MSI) && rspq != &adapter->sge.intrq) { + if ((adapter->flags & CXGB4VF_USING_MSI) && + rspq != &adapter->sge.intrq) { iqandst = SGE_INTRDST_IQ; intr_dest = adapter->sge.intrq.abs_id; } else -- cgit v1.2.3 From 8b965f3f649c50d68a7fbc3a7771fcc368d2b7b8 Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Fri, 1 Mar 2019 15:44:47 +0530 Subject: cxgb4: Add VF Link state support Use ndo_set_vf_link_state to control the link states associated with the virtual interfaces. Signed-off-by: Arjun Vynipadath Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 1 + drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 57 ++++++++++++++++++++++--- drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 8 ++++ 3 files changed, 60 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index b7b0eb104430..dd6379809c74 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -885,6 +885,7 @@ struct vf_info { unsigned int tx_rate; bool pf_set_mac; u16 vlan; + int link_state; }; enum { diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 1754ff794360..45093a620c3f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2740,6 +2740,7 @@ static int cxgb4_mgmt_get_vf_config(struct net_device *dev, ivi->min_tx_rate = 0; ether_addr_copy(ivi->mac, vfinfo->vf_mac_addr); ivi->vlan = vfinfo->vlan; + ivi->linkstate = vfinfo->link_state; return 0; } @@ -2879,6 +2880,49 @@ static int cxgb4_mgmt_set_vf_vlan(struct net_device *dev, int vf, ret, (vlan ? "setting" : "clearing"), adap->pf, vf); return ret; } + +static int cxgb4_mgmt_set_vf_link_state(struct net_device *dev, int vf, + int link) +{ + struct port_info *pi = netdev_priv(dev); + struct adapter *adap = pi->adapter; + u32 param, val; + int ret = 0; + + if (vf >= adap->num_vfs) + return -EINVAL; + + switch (link) { + case IFLA_VF_LINK_STATE_AUTO: + val = FW_VF_LINK_STATE_AUTO; + break; + + case IFLA_VF_LINK_STATE_ENABLE: + val = FW_VF_LINK_STATE_ENABLE; + break; + + case IFLA_VF_LINK_STATE_DISABLE: + val = FW_VF_LINK_STATE_DISABLE; + break; + + default: + return -EINVAL; + } + + param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_LINK_STATE)); + ret = t4_set_params(adap, adap->mbox, adap->pf, vf + 1, 1, + ¶m, &val); + if (ret) { + dev_err(adap->pdev_dev, + "Error %d in setting PF %d VF %d link state\n", + ret, adap->pf, vf); + return -EINVAL; + } + + adap->vfinfo[vf].link_state = link; + return ret; +} #endif /* CONFIG_PCI_IOV */ static int cxgb_set_mac_addr(struct net_device *dev, void *p) @@ -3294,12 +3338,13 @@ static const struct net_device_ops cxgb4_netdev_ops = { #ifdef CONFIG_PCI_IOV static const struct net_device_ops cxgb4_mgmt_netdev_ops = { - .ndo_open = cxgb4_mgmt_open, - .ndo_set_vf_mac = cxgb4_mgmt_set_vf_mac, - .ndo_get_vf_config = cxgb4_mgmt_get_vf_config, - .ndo_set_vf_rate = cxgb4_mgmt_set_vf_rate, - .ndo_get_phys_port_id = cxgb4_mgmt_get_phys_port_id, - .ndo_set_vf_vlan = cxgb4_mgmt_set_vf_vlan, + .ndo_open = cxgb4_mgmt_open, + .ndo_set_vf_mac = cxgb4_mgmt_set_vf_mac, + .ndo_get_vf_config = cxgb4_mgmt_get_vf_config, + .ndo_set_vf_rate = cxgb4_mgmt_set_vf_rate, + .ndo_get_phys_port_id = cxgb4_mgmt_get_phys_port_id, + .ndo_set_vf_vlan = cxgb4_mgmt_set_vf_vlan, + .ndo_set_vf_link_state = cxgb4_mgmt_set_vf_link_state, }; #endif diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 631f1663f4e0..b2a618e72fcf 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -1312,6 +1312,14 @@ enum fw_params_param_pfvf { FW_PARAMS_PARAM_PFVF_RAWF_END = 0x37, FW_PARAMS_PARAM_PFVF_NCRYPTO_LOOKASIDE = 0x39, FW_PARAMS_PARAM_PFVF_PORT_CAPS32 = 0x3A, + FW_PARAMS_PARAM_PFVF_LINK_STATE = 0x40, +}; + +/* Virtual link state as seen by the specified VF */ +enum vf_link_states { + FW_VF_LINK_STATE_AUTO = 0x00, + FW_VF_LINK_STATE_ENABLE = 0x01, + FW_VF_LINK_STATE_DISABLE = 0x02, }; /* -- cgit v1.2.3 From 502c1a1612747b911ae07b48530f09a54af35a95 Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Fri, 1 Mar 2019 15:44:48 +0530 Subject: cxgb4vf: Revert force link up behaviour Reverting force link up changes since this behaviour can be achieved using VF link state feature. Reverts: commit 0913667ab3ad ("cxgb4vf: Forcefully link up virtual interfaces") Signed-off-by: Arjun Vynipadath Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 6b2754a574d6..62fd1250ff7e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -155,6 +155,8 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok) const char *fc; const struct port_info *pi = netdev_priv(dev); + netif_carrier_on(dev); + switch (pi->link_cfg.speed) { case 100: s = "100Mbps"; @@ -200,6 +202,7 @@ void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok) netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s, fc); } else { + netif_carrier_off(dev); netdev_info(dev, "link down\n"); } } @@ -339,16 +342,6 @@ static int link_start(struct net_device *dev) if (ret == 0) ret = t4vf_enable_pi(pi->adapter, pi, true, true); - /* The Virtual Interfaces are connected to an internal switch on the - * chip which allows VIs attached to the same port to talk to each - * other even when the port link is down. As a result, we generally - * want to always report a VI's link as being "up", provided there are - * no errors in enabling vi. - */ - - if (ret == 0) - netif_carrier_on(dev); - return ret; } -- cgit v1.2.3 From 57d37aea0e2e0a8330ebf4f41150a641a8ccd869 Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Fri, 1 Mar 2019 16:07:01 +0530 Subject: cxgb4vf: Call netif_carrier_off properly in pci_probe netif_carrier_off() should be called only after register_netdev(). Signed-off-by: Arjun Vynipadath Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 62fd1250ff7e..adc4d481815b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -3136,7 +3136,6 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, * it. */ pi->xact_addr_filt = -1; - netif_carrier_off(netdev); netdev->irq = pdev->irq; netdev->hw_features = NETIF_F_SG | TSO_FLAGS | NETIF_F_GRO | @@ -3259,6 +3258,7 @@ static int cxgb4vf_pci_probe(struct pci_dev *pdev, continue; } + netif_carrier_off(netdev); set_bit(pidx, &adapter->registered_device_map); } if (adapter->registered_device_map == 0) { -- cgit v1.2.3 From 6bdb87ef9f95d9986199367acd15103c6918a756 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:03 +0100 Subject: net: mvpp2: fix a typo in the header This cosmetic patch fixes a typo made in a comment in the Marvell PPv2 Ethernet driver header. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 96e3f0669032..83fb2b03e789 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -549,7 +549,7 @@ #define MVPP2_MAX_TSO_SEGS 300 #define MVPP2_MAX_SKB_DESCS (MVPP2_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) -/* Dfault number of RXQs in use */ +/* Default number of RXQs in use */ #define MVPP2_DEFAULT_RXQ 1 /* Max number of Rx descriptors */ -- cgit v1.2.3 From 31383c03c03193220132dfedbe9052183fbfd86c Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:04 +0100 Subject: net: mvpp2: update the port documentation regarding the GoP The Marvell PPv2 port structure stores the GoP id of a given port. This information is specific to PPv2.2, but cannot be used by PPv2.1. Update its comment to denote this specificity. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 83fb2b03e789..9b05fcbc6953 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -803,7 +803,7 @@ struct mvpp2_port { u8 id; /* Index of the port from the "group of ports" complex point - * of view + * of view. This is specific to PPv2.2. */ int gop_id; -- cgit v1.2.3 From 0caa756b7745ff5d2b839ea69be9a1d94f3b779f Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:05 +0100 Subject: net: mvpp2: fix alignment of MVPP2_GMAC_CONFIG_MII_SPEED definition Cosmetic patch fix the alignment of the MVPP2_GMAC_CONFIG_MII_SPEED macro definition. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 9b05fcbc6953..17ff330cce5f 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -389,7 +389,7 @@ #define MVPP2_GMAC_IN_BAND_AUTONEG BIT(2) #define MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS BIT(3) #define MVPP2_GMAC_IN_BAND_RESTART_AN BIT(4) -#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5) +#define MVPP2_GMAC_CONFIG_MII_SPEED BIT(5) #define MVPP2_GMAC_CONFIG_GMII_SPEED BIT(6) #define MVPP2_GMAC_AN_SPEED_EN BIT(7) #define MVPP2_GMAC_FC_ADV_EN BIT(9) -- cgit v1.2.3 From 052f7c8bac4440bc5e3b2086e4134055b862453a Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:06 +0100 Subject: net: mvpp2: a port can be disabled even if we use the link IRQ We had a check in the mvpp2_mac_link_down() function (called by phylink) to avoid disabling the port when link interrupts are used. It turned out the interrupt can still be used with the port disabled. We can thus remove this check. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 6638a3339efc..5a2638b7443a 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4738,13 +4738,6 @@ static void mvpp2_mac_link_down(struct net_device *dev, unsigned int mode, mvpp2_egress_disable(port); mvpp2_ingress_disable(port); - /* When using link interrupts to notify phylink of a MAC state change, - * we do not want the port to be disabled (we want to receive further - * interrupts, to be notified when the port will have a link later). - */ - if (!port->has_phy) - return; - mvpp2_port_disable(port); } -- cgit v1.2.3 From d78a18091f42122d4094e8ddcaeee083198a9c17 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:07 +0100 Subject: net: mvpp2: reconfiguring the port interface is PPv2.2 specific This patch adds a check on the PPv2 version in-use not to reconfigure the port mode when an interface is updated when using PPv2.1 as the functions called are PPv2.2 specific. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 5a2638b7443a..9467a2258ee0 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4672,16 +4672,14 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, /* Make sure the port is disabled when reconfiguring the mode */ mvpp2_port_disable(port); - if (change_interface) { + if (port->priv->hw_version == MVPP22 && change_interface) { mvpp22_gop_mask_irq(port); - if (port->priv->hw_version == MVPP22) { - port->phy_interface = state->interface; + port->phy_interface = state->interface; - /* Reconfigure the serdes lanes */ - phy_power_off(port->comphy); - mvpp22_mode_reconfigure(port); - } + /* Reconfigure the serdes lanes */ + phy_power_off(port->comphy); + mvpp22_mode_reconfigure(port); } /* mac (re)configuration */ @@ -4695,7 +4693,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, if (port->priv->hw_version == MVPP21 && port->flags & MVPP2_F_LOOPBACK) mvpp2_port_loopback_set(port, state); - if (change_interface) + if (port->priv->hw_version == MVPP22 && change_interface) mvpp22_gop_unmask_irq(port); mvpp2_port_enable(port); -- cgit v1.2.3 From 8b318f30ab4ef9bbc1241e6f8c1db366dbd347f2 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:08 +0100 Subject: net: mvpp2: fix validate for PPv2.1 The Phylink validate function is the Marvell PPv2 driver makes a check on the GoP id. This is valid an has to be done when using PPv2.2 engines but makes no sense when using PPv2.1. The check done when using an RGMII interface makes sure the GoP id is not 0, but this breaks PPv2.1. Fixes it. Fixes: 0fb628f0f250 ("net: mvpp2: fix phylink handling of invalid PHY modes") Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 9467a2258ee0..e7d768381f4f 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4363,7 +4363,7 @@ static void mvpp2_phylink_validate(struct net_device *dev, case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: - if (port->gop_id == 0) + if (port->priv->hw_version == MVPP22 && port->gop_id == 0) goto empty_set; break; default: -- cgit v1.2.3 From 3f13684948aed6214842d6f864d94c9a36080041 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:09 +0100 Subject: net: mvpp2: fix the computation of the RXQs The patch fixes the computation of RXQs being used by the PPv2 driver, which is set depending on the PPv2 engine version and the queue mode used. There are three cases: - PPv2.1: 1 RXQ per CPU. - PPV2.2 with MVPP2_QDIST_MULTI_MODE: 1 RXQ per CPU. - PPv2.2 with MVPP2_QDIST_SINGLE_MODE: 1 RXQ is shared between the CPUs. The PPv2 engine supports a maximum of 32 queues per port. This patch adds a check so that we do not overstep this maximum. It appeared the calculation was broken for PPv2.1 engines since f8c6ba8424b0, as PPv2.1 ports ended up with a single RXQ while they needed 4. This patch fixes it. Fixes: f8c6ba8424b0 ("net: mvpp2: use only one rx queue per port per CPU") Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 4 ++-- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 23 +++++++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 17ff330cce5f..687e011de5ef 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -549,8 +549,8 @@ #define MVPP2_MAX_TSO_SEGS 300 #define MVPP2_MAX_SKB_DESCS (MVPP2_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS) -/* Default number of RXQs in use */ -#define MVPP2_DEFAULT_RXQ 1 +/* Max number of RXQs per port */ +#define MVPP2_PORT_MAX_RXQ 32 /* Max number of Rx descriptors */ #define MVPP2_MAX_RXD_MAX 1024 diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index e7d768381f4f..2a6faddeb95f 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4061,8 +4061,8 @@ static int mvpp2_multi_queue_vectors_init(struct mvpp2_port *port, snprintf(irqname, sizeof(irqname), "hif%d", i); if (queue_mode == MVPP2_QDIST_MULTI_MODE) { - v->first_rxq = i * MVPP2_DEFAULT_RXQ; - v->nrxqs = MVPP2_DEFAULT_RXQ; + v->first_rxq = i; + v->nrxqs = 1; } else if (queue_mode == MVPP2_QDIST_SINGLE_MODE && i == (port->nqvecs - 1)) { v->first_rxq = 0; @@ -4155,8 +4155,7 @@ static int mvpp2_port_init(struct mvpp2_port *port) MVPP2_MAX_PORTS * priv->max_port_rxqs) return -EINVAL; - if (port->nrxqs % MVPP2_DEFAULT_RXQ || - port->nrxqs > priv->max_port_rxqs || port->ntxqs > MVPP2_MAX_TXQ) + if (port->nrxqs > priv->max_port_rxqs || port->ntxqs > MVPP2_MAX_TXQ) return -EINVAL; /* Disable port */ @@ -4777,10 +4776,18 @@ static int mvpp2_port_probe(struct platform_device *pdev, } ntxqs = MVPP2_MAX_TXQ; - if (priv->hw_version == MVPP22 && queue_mode == MVPP2_QDIST_MULTI_MODE) - nrxqs = MVPP2_DEFAULT_RXQ * num_possible_cpus(); - else - nrxqs = MVPP2_DEFAULT_RXQ; + if (priv->hw_version == MVPP22 && queue_mode == MVPP2_QDIST_SINGLE_MODE) { + nrxqs = 1; + } else { + /* According to the PPv2.2 datasheet and our experiments on + * PPv2.1, RX queues have an allocation granularity of 4 (when + * more than a single one on PPv2.2). + * Round up to nearest multiple of 4. + */ + nrxqs = (num_possible_cpus() + 3) & ~0x3; + if (nrxqs > MVPP2_PORT_MAX_RXQ) + nrxqs = MVPP2_PORT_MAX_RXQ; + } dev = alloc_etherdev_mqs(sizeof(*port), ntxqs, nrxqs); if (!dev) -- cgit v1.2.3 From 9a490e34069dff988d38327360862a622a149bd0 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:10 +0100 Subject: net: mvpp2: some AN fields require the link to be down when updated The GMAC configuration helper modifies values in the auto-negotiation register. Some of its values require the port to be forced down when modifying their values. This patches fixes the check made on the bit to be updated in this register, so that the port is forced down when needed. This fix cases where some of those parameters were updated, but not taken into account, such as when using RGMII interfaces. Fixes: d14e078f23cc ("net: marvell: mvpp2: only reprogram what is necessary on mac_config") Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 2a6faddeb95f..908dfe86db92 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4626,9 +4626,19 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, } } +/* Some fields of the auto-negotiation register require the port to be down when + * their value is updated. + */ +#define MVPP2_GMAC_AN_PORT_DOWN_MASK \ + (MVPP2_GMAC_IN_BAND_AUTONEG | \ + MVPP2_GMAC_IN_BAND_AUTONEG_BYPASS | \ + MVPP2_GMAC_CONFIG_MII_SPEED | MVPP2_GMAC_CONFIG_GMII_SPEED | \ + MVPP2_GMAC_AN_SPEED_EN | MVPP2_GMAC_CONFIG_FULL_DUPLEX | \ + MVPP2_GMAC_AN_DUPLEX_EN) + if ((old_ctrl0 ^ ctrl0) & MVPP2_GMAC_PORT_TYPE_MASK || (old_ctrl2 ^ ctrl2) & MVPP2_GMAC_INBAND_AN_MASK || - (old_an ^ an) & MVPP2_GMAC_IN_BAND_AUTONEG) { + (old_an ^ an) & MVPP2_GMAC_AN_PORT_DOWN_MASK) { /* Force link down */ old_an &= ~MVPP2_GMAC_FORCE_LINK_PASS; old_an |= MVPP2_GMAC_FORCE_LINK_DOWN; -- cgit v1.2.3 From 6b10bfc51c494e0a2b2c0871797a1d825da9997c Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:11 +0100 Subject: net: mvpp2: always disable both MACs when disabling a port This patch modifies the port_disable() helper to always disable both the GMAC and the XLG MAC when called. At boot time we do not know of a port was enabled in the firmware/bootloader, and if so what mode was used (hence which of the two MACs was used). This also help in implementing a logic where all blocks are disabled when not used, and only enabled regarding the current mode used on a given port. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 908dfe86db92..e9cbbe871a1a 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1213,11 +1213,11 @@ static void mvpp2_port_disable(struct mvpp2_port *port) /* Disable & reset should be done separately */ val &= ~MVPP22_XLG_CTRL0_MAC_RESET_DIS; writel(val, port->base + MVPP22_XLG_CTRL0_REG); - } else { - val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); - val &= ~(MVPP2_GMAC_PORT_EN_MASK); - writel(val, port->base + MVPP2_GMAC_CTRL_0_REG); } + + val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); + val &= ~(MVPP2_GMAC_PORT_EN_MASK); + writel(val, port->base + MVPP2_GMAC_CTRL_0_REG); } /* Set IEEE 802.3x Flow Control Xon Packet Transmission Mode */ -- cgit v1.2.3 From f17e70d2586a81d69d7b011e81af0456fe65d658 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:12 +0100 Subject: net: mvpp2: only update the XLG configuration when needed This patch improves the XLG configuration function, to only update the XLG configuration register when a change is needed. This helps not writing over and over the same XLG configuration each time phylink request the MAC to be configured. This mimics the GMAC configuration function. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index e9cbbe871a1a..b1add5c6b75c 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4505,10 +4505,11 @@ static void mvpp2_mac_an_restart(struct net_device *dev) static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, const struct phylink_link_state *state) { - u32 ctrl0, ctrl4; + u32 old_ctrl0, ctrl0; + u32 old_ctrl4, ctrl4; - ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG); - ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG); + old_ctrl0 = ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG); + old_ctrl4 = ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG); if (state->pause & MLO_PAUSE_TX) ctrl0 |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN; @@ -4524,8 +4525,10 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, ctrl4 |= MVPP22_XLG_CTRL4_FWD_FC | MVPP22_XLG_CTRL4_FWD_PFC | MVPP22_XLG_CTRL4_EN_IDLE_CHECK; - writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG); - writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG); + if (old_ctrl0 != ctrl0) + writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG); + if (old_ctrl4 != ctrl4) + writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG); } static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, -- cgit v1.2.3 From 1970ee9614d89df88a263f56c3a55d34633fe181 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:13 +0100 Subject: net: mvpp2: force the XLG MAC link up or down when not using in-band This patch force the XLG MAC link state in the phylink link_up() and link_down() helpers when not using in-band auto-negotiation. This mimics what's already done for the GMAC and follows what's advised in the phylink documentation. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 ++ drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 35 ++++++++++++++++++------- 2 files changed, 27 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 687e011de5ef..c9edeac9ec01 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -430,6 +430,8 @@ #define MVPP22_XLG_CTRL0_REG 0x100 #define MVPP22_XLG_CTRL0_PORT_EN BIT(0) #define MVPP22_XLG_CTRL0_MAC_RESET_DIS BIT(1) +#define MVPP22_XLG_CTRL0_FORCE_LINK_DOWN BIT(2) +#define MVPP22_XLG_CTRL0_FORCE_LINK_PASS BIT(3) #define MVPP22_XLG_CTRL0_RX_FLOW_CTRL_EN BIT(7) #define MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN BIT(8) #define MVPP22_XLG_CTRL0_MIB_CNT_DIS BIT(14) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index b1add5c6b75c..ba40b06d3ca3 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -4684,6 +4684,7 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, /* Make sure the port is disabled when reconfiguring the mode */ mvpp2_port_disable(port); + if (port->priv->hw_version == MVPP22 && change_interface) { mvpp22_gop_mask_irq(port); @@ -4717,11 +4718,18 @@ static void mvpp2_mac_link_up(struct net_device *dev, unsigned int mode, struct mvpp2_port *port = netdev_priv(dev); u32 val; - if (!phylink_autoneg_inband(mode) && !mvpp2_is_xlg(interface)) { - val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); - val &= ~MVPP2_GMAC_FORCE_LINK_DOWN; - val |= MVPP2_GMAC_FORCE_LINK_PASS; - writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + if (!phylink_autoneg_inband(mode)) { + if (mvpp2_is_xlg(interface)) { + val = readl(port->base + MVPP22_XLG_CTRL0_REG); + val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_DOWN; + val |= MVPP22_XLG_CTRL0_FORCE_LINK_PASS; + writel(val, port->base + MVPP22_XLG_CTRL0_REG); + } else { + val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); + val &= ~MVPP2_GMAC_FORCE_LINK_DOWN; + val |= MVPP2_GMAC_FORCE_LINK_PASS; + writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + } } mvpp2_port_enable(port); @@ -4737,11 +4745,18 @@ static void mvpp2_mac_link_down(struct net_device *dev, unsigned int mode, struct mvpp2_port *port = netdev_priv(dev); u32 val; - if (!phylink_autoneg_inband(mode) && !mvpp2_is_xlg(interface)) { - val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); - val &= ~MVPP2_GMAC_FORCE_LINK_PASS; - val |= MVPP2_GMAC_FORCE_LINK_DOWN; - writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + if (!phylink_autoneg_inband(mode)) { + if (mvpp2_is_xlg(interface)) { + val = readl(port->base + MVPP22_XLG_CTRL0_REG); + val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_PASS; + val |= MVPP22_XLG_CTRL0_FORCE_LINK_DOWN; + writel(val, port->base + MVPP22_XLG_CTRL0_REG); + } else { + val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG); + val &= ~MVPP2_GMAC_FORCE_LINK_PASS; + val |= MVPP2_GMAC_FORCE_LINK_DOWN; + writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG); + } } netif_tx_stop_all_queues(dev); -- cgit v1.2.3 From 649e51d5607b502242c387302523741030354ea5 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:14 +0100 Subject: net: mvpp2: rework the XLG MAC reset handling This patch reworks the way the XLG MAC is set in reset: the XLG MAC is set in reset at probe time and taken out of this state only when used. The idea is to move forward a situation where only the blocks used are taken out of reset. This also has the effect to handle the GMAC and the XLG MAC in a similar way (the GMAC already is set in reset at boot time). Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 27 ++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index ba40b06d3ca3..c64ddad6b2b3 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1188,8 +1188,7 @@ static void mvpp2_port_enable(struct mvpp2_port *port) /* Only GOP port 0 has an XLG MAC */ if (port->gop_id == 0 && mvpp2_is_xlg(port->phy_interface)) { val = readl(port->base + MVPP22_XLG_CTRL0_REG); - val |= MVPP22_XLG_CTRL0_PORT_EN | - MVPP22_XLG_CTRL0_MAC_RESET_DIS; + val |= MVPP22_XLG_CTRL0_PORT_EN; val &= ~MVPP22_XLG_CTRL0_MIB_CNT_DIS; writel(val, port->base + MVPP22_XLG_CTRL0_REG); } else { @@ -1209,10 +1208,6 @@ static void mvpp2_port_disable(struct mvpp2_port *port) val = readl(port->base + MVPP22_XLG_CTRL0_REG); val &= ~MVPP22_XLG_CTRL0_PORT_EN; writel(val, port->base + MVPP22_XLG_CTRL0_REG); - - /* Disable & reset should be done separately */ - val &= ~MVPP22_XLG_CTRL0_MAC_RESET_DIS; - writel(val, port->base + MVPP22_XLG_CTRL0_REG); } val = readl(port->base + MVPP2_GMAC_CTRL_0_REG); @@ -1369,10 +1364,10 @@ static int mvpp2_ethtool_get_sset_count(struct net_device *dev, int sset) return -EOPNOTSUPP; } -static void mvpp2_port_reset(struct mvpp2_port *port) +static void mvpp2_mac_reset_assert(struct mvpp2_port *port) { - u32 val; unsigned int i; + u32 val; /* Read the GOP statistics to reset the hardware counters */ for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_regs); i++) @@ -1381,6 +1376,12 @@ static void mvpp2_port_reset(struct mvpp2_port *port) val = readl(port->base + MVPP2_GMAC_CTRL_2_REG) | MVPP2_GMAC_PORT_RESET_MASK; writel(val, port->base + MVPP2_GMAC_CTRL_2_REG); + + if (port->priv->hw_version == MVPP22 && port->gop_id == 0) { + val = readl(port->base + MVPP22_XLG_CTRL0_REG) & + ~MVPP22_XLG_CTRL0_MAC_RESET_DIS; + writel(val, port->base + MVPP22_XLG_CTRL0_REG); + } } /* Change maximum receive size of the port */ @@ -4511,6 +4512,8 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, old_ctrl0 = ctrl0 = readl(port->base + MVPP22_XLG_CTRL0_REG); old_ctrl4 = ctrl4 = readl(port->base + MVPP22_XLG_CTRL4_REG); + ctrl0 |= MVPP22_XLG_CTRL0_MAC_RESET_DIS; + if (state->pause & MLO_PAUSE_TX) ctrl0 |= MVPP22_XLG_CTRL0_TX_FLOW_CTRL_EN; else @@ -4529,6 +4532,12 @@ static void mvpp2_xlg_config(struct mvpp2_port *port, unsigned int mode, writel(ctrl0, port->base + MVPP22_XLG_CTRL0_REG); if (old_ctrl4 != ctrl4) writel(ctrl4, port->base + MVPP22_XLG_CTRL4_REG); + + if (!(old_ctrl0 & MVPP22_XLG_CTRL0_MAC_RESET_DIS)) { + while (!(readl(port->base + MVPP22_XLG_CTRL0_REG) & + MVPP22_XLG_CTRL0_MAC_RESET_DIS)) + continue; + } } static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, @@ -4946,7 +4955,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, mvpp2_port_periodic_xon_disable(port); - mvpp2_port_reset(port); + mvpp2_mac_reset_assert(port); port->pcpu = alloc_percpu(struct mvpp2_port_pcpu); if (!port->pcpu) { -- cgit v1.2.3 From 5434e8faf05a3a9514b0a3698245764780be41e0 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:15 +0100 Subject: net: mvpp2: reset the MACs when reconfiguring a port This patch makes sure both PPv2 MACs (GMAC + XLG MAC) are set in reset while a port is reconfigured. This is done so that we make sure a MAC is in a reset state when not used, as only one of the two will be set out of reset after the port is configured properly. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index c64ddad6b2b3..57a23c96ad4d 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -3136,6 +3136,9 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) { u32 ctrl3; + /* Set the GMAC & XLG MAC in reset */ + mvpp2_mac_reset_assert(port); + /* comphy reconfiguration */ mvpp22_comphy_init(port); -- cgit v1.2.3 From 7409e66e9eee89f75d6eec6142279146f0999977 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:16 +0100 Subject: net: mvpp2: set the XPCS and MPCS in reset when not used This patch sets both the XPCS and MPCS blocks in reset when they aren't used. This is done both at boot time and when reconfiguring a port mode. The advantage now is that only the PCS used is set out of reset when the port is configured (10GKR uses the MCPS while RXAUI uses the XPCS). Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 1 + drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 66 ++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index c9edeac9ec01..ff0f4c503f53 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -483,6 +483,7 @@ /* XPCS registers. PPv2.2 only */ #define MVPP22_XPCS_BASE(port) (0x7400 + (port) * 0x1000) #define MVPP22_XPCS_CFG0 0x0 +#define MVPP22_XPCS_CFG0_RESET_DIS BIT(0) #define MVPP22_XPCS_CFG0_PCS_MODE(n) ((n) << 3) #define MVPP22_XPCS_CFG0_ACTIVE_LANE(n) ((n) << 5) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 57a23c96ad4d..18ca3257a3ad 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -1015,27 +1015,20 @@ static void mvpp22_gop_init_10gkr(struct mvpp2_port *port) void __iomem *xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id); u32 val; - /* XPCS */ val = readl(xpcs + MVPP22_XPCS_CFG0); val &= ~(MVPP22_XPCS_CFG0_PCS_MODE(0x3) | MVPP22_XPCS_CFG0_ACTIVE_LANE(0x3)); val |= MVPP22_XPCS_CFG0_ACTIVE_LANE(2); writel(val, xpcs + MVPP22_XPCS_CFG0); - /* MPCS */ val = readl(mpcs + MVPP22_MPCS_CTRL); val &= ~MVPP22_MPCS_CTRL_FWD_ERR_CONN; writel(val, mpcs + MVPP22_MPCS_CTRL); val = readl(mpcs + MVPP22_MPCS_CLK_RESET); - val &= ~(MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7) | MAC_CLK_RESET_MAC | - MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX); + val &= ~MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7); val |= MVPP22_MPCS_CLK_RESET_DIV_RATIO(1); writel(val, mpcs + MVPP22_MPCS_CLK_RESET); - - val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET; - val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX; - writel(val, mpcs + MVPP22_MPCS_CLK_RESET); } static int mvpp22_gop_init(struct mvpp2_port *port) @@ -1384,6 +1377,57 @@ static void mvpp2_mac_reset_assert(struct mvpp2_port *port) } } +static void mvpp22_pcs_reset_assert(struct mvpp2_port *port) +{ + struct mvpp2 *priv = port->priv; + void __iomem *mpcs, *xpcs; + u32 val; + + if (port->priv->hw_version != MVPP22 || port->gop_id != 0) + return; + + mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id); + xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id); + + val = readl(mpcs + MVPP22_MPCS_CLK_RESET); + val &= ~(MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX); + val |= MVPP22_MPCS_CLK_RESET_DIV_SET; + writel(val, mpcs + MVPP22_MPCS_CLK_RESET); + + val = readl(xpcs + MVPP22_XPCS_CFG0); + writel(val & ~MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0); +} + +static void mvpp22_pcs_reset_deassert(struct mvpp2_port *port) +{ + struct mvpp2 *priv = port->priv; + void __iomem *mpcs, *xpcs; + u32 val; + + if (port->priv->hw_version != MVPP22 || port->gop_id != 0) + return; + + mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id); + xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id); + + switch (port->phy_interface) { + case PHY_INTERFACE_MODE_10GKR: + val = readl(mpcs + MVPP22_MPCS_CLK_RESET); + val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | + MAC_CLK_RESET_SD_TX; + val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET; + writel(val, mpcs + MVPP22_MPCS_CLK_RESET); + break; + case PHY_INTERFACE_MODE_XAUI: + case PHY_INTERFACE_MODE_RXAUI: + val = readl(xpcs + MVPP22_XPCS_CFG0); + writel(val | MVPP22_XPCS_CFG0_RESET_DIS, xpcs + MVPP22_XPCS_CFG0); + break; + default: + break; + } +} + /* Change maximum receive size of the port */ static inline void mvpp2_gmac_max_rx_size_set(struct mvpp2_port *port) { @@ -3139,12 +3183,17 @@ static void mvpp22_mode_reconfigure(struct mvpp2_port *port) /* Set the GMAC & XLG MAC in reset */ mvpp2_mac_reset_assert(port); + /* Set the MPCS and XPCS in reset */ + mvpp22_pcs_reset_assert(port); + /* comphy reconfiguration */ mvpp22_comphy_init(port); /* gop reconfiguration */ mvpp22_gop_init(port); + mvpp22_pcs_reset_deassert(port); + /* Only GOP port 0 has an XLG MAC */ if (port->gop_id == 0) { ctrl3 = readl(port->base + MVPP22_XLG_CTRL3_REG); @@ -4959,6 +5008,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, mvpp2_port_periodic_xon_disable(port); mvpp2_mac_reset_assert(port); + mvpp22_pcs_reset_assert(port); port->pcpu = alloc_percpu(struct mvpp2_port_pcpu); if (!port->pcpu) { -- cgit v1.2.3 From 1f69afce382f2858c825f027ed5afa97ec532f3e Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Fri, 1 Mar 2019 11:52:17 +0100 Subject: net: mvpp2: set the GMAC, XLG MAC, XPCS and MPCS in reset when a port is down This patch adds calls in the stop() helper to ensure both MACs and both PCS blocks are set in reset when the user manually sets a port down. This is done so that we have the exact same block reset states at boot time and when a port is set down. Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 18ca3257a3ad..25fbed2b8d94 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -3525,6 +3525,9 @@ static int mvpp2_stop(struct net_device *dev) cancel_delayed_work_sync(&port->stats_work); + mvpp2_mac_reset_assert(port); + mvpp22_pcs_reset_assert(port); + return 0; } -- cgit v1.2.3 From 94d66714739242d5f6f7410bf044239e33226073 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Wed, 27 Feb 2019 15:52:23 -0800 Subject: Bluetooth: hci_qca: Reduce delay after sending baudrate request for WCN3990 The current 300ms delay after a baudrate change is extremely long. For WCN3990 it is sufficient to wait 10ms after the baudrate change request has been sent over the wire. Signed-off-by: Matthias Kaehlcke Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_qca.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 82f6cec4f71e..237aea34b69f 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -59,8 +59,7 @@ #define IBS_WAKE_RETRANS_TIMEOUT_MS 100 #define IBS_TX_IDLE_TIMEOUT_MS 2000 -#define BAUDRATE_SETTLE_TIMEOUT_MS 300 -#define POWER_PULSE_TRANS_TIMEOUT_MS 100 +#define CMD_TRANS_TIMEOUT_MS 100 /* susclk rate */ #define SUSCLK_RATE_32KHZ 32768 @@ -964,6 +963,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) { struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; + struct qca_serdev *qcadev; struct sk_buff *skb; u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; @@ -985,11 +985,21 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) skb_queue_tail(&qca->txq, skb); hci_uart_tx_wakeup(hu); - /* wait 300ms to change new baudrate on controller side - * controller will come back after they receive this HCI command - * then host can communicate with new baudrate to controller - */ - msleep(BAUDRATE_SETTLE_TIMEOUT_MS); + qcadev = serdev_device_get_drvdata(hu->serdev); + + /* Wait for the baudrate change request to be sent */ + + while (!skb_queue_empty(&qca->txq)) + usleep_range(100, 200); + + serdev_device_wait_until_sent(hu->serdev, + msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); + + /* Give the controller time to process the request */ + if (qcadev->btsoc_type == QCA_WCN3990) + msleep(10); + else + msleep(300); return 0; } @@ -1005,7 +1015,7 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed) static int qca_send_power_pulse(struct hci_uart *hu, bool on) { int ret; - int timeout = msecs_to_jiffies(POWER_PULSE_TRANS_TIMEOUT_MS); + int timeout = msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS); u8 cmd = on ? QCA_WCN3990_POWERON_PULSE : QCA_WCN3990_POWEROFF_PULSE; /* These power pulses are single byte command which are sent -- cgit v1.2.3 From 22eaf6c9946ae269061d95bb9ceee02524166474 Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Sun, 3 Mar 2019 02:44:09 +0800 Subject: Bluetooth: mediatek: add support for MediaTek MT7663U and MT7668U UART devices This adds the support of enabling MT7663U and MT7668U Bluetooth function running on the top of btmtkuart driver. There are a few differences between MT766[3,8]U and MT7622 where MT766[3,8]U are standalone devices based on UART transport while MT7622 bluetooth is a built-in device on MediaTek SoC communicating with the host through BTIF serial transport. Thus, extra setup sequence is necessary for these standalone devices such as remote regulator and reset control via GPIO, baud rate changing handshake between the host and device and so on. Signed-off-by: Sean Wang Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmtkuart.c | 281 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 271 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index e73b1013ba73..b0b680dd69f4 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -12,11 +12,15 @@ #include #include #include +#include #include #include #include #include +#include +#include #include +#include #include #include @@ -25,18 +29,26 @@ #include "h4_recv.h" -#define VERSION "0.1" +#define VERSION "0.2" #define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin" +#define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" +#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" #define MTK_STP_TLR_SIZE 2 #define BTMTKUART_TX_STATE_ACTIVE 1 #define BTMTKUART_TX_STATE_WAKEUP 2 #define BTMTKUART_TX_WAIT_VND_EVT 3 +#define BTMTKUART_REQUIRED_WAKEUP 4 + +#define BTMTKUART_FLAG_STANDALONE_HW BIT(0) enum { MTK_WMT_PATCH_DWNLD = 0x1, + MTK_WMT_TEST = 0x2, + MTK_WMT_WAKEUP = 0x3, + MTK_WMT_HIF = 0x4, MTK_WMT_FUNC_CTRL = 0x6, MTK_WMT_RST = 0x7, MTK_WMT_SEMAPHORE = 0x17, @@ -57,6 +69,11 @@ struct mtk_stp_hdr { u8 cs; } __packed; +struct btmtkuart_data { + unsigned int flags; + const char *fwname; +}; + struct mtk_wmt_hdr { u8 dir; u8 op; @@ -100,6 +117,14 @@ struct btmtkuart_dev { struct serdev_device *serdev; struct clk *clk; + struct regulator *vcc; + struct gpio_desc *reset; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_runtime; + struct pinctrl_state *pins_boot; + speed_t desired_speed; + speed_t curr_speed; + struct work_struct tx_work; unsigned long tx_state; struct sk_buff_head txq; @@ -110,8 +135,15 @@ struct btmtkuart_dev { u8 stp_pad[6]; u8 stp_cursor; u16 stp_dlen; + + const struct btmtkuart_data *data; }; +#define btmtkuart_is_standalone(bdev) \ + ((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW) +#define btmtkuart_is_builtin_soc(bdev) \ + !((bdev)->data->flags & BTMTKUART_FLAG_STANDALONE_HW) + static int mtk_hci_wmt_sync(struct hci_dev *hdev, struct btmtk_hci_wmt_params *wmt_params) { @@ -202,7 +234,7 @@ err_free_skb: return err; } -static int mtk_setup_fw(struct hci_dev *hdev) +static int mtk_setup_firmware(struct hci_dev *hdev, const char *fwname) { struct btmtk_hci_wmt_params wmt_params; const struct firmware *fw; @@ -211,7 +243,7 @@ static int mtk_setup_fw(struct hci_dev *hdev) int err, dlen; u8 flag; - err = request_firmware(&fw, FIRMWARE_MT7622, &hdev->dev); + err = request_firmware(&fw, fwname, &hdev->dev); if (err < 0) { bt_dev_err(hdev, "Failed to load firmware file (%d)", err); return err; @@ -523,6 +555,23 @@ static int btmtkuart_open(struct hci_dev *hdev) goto err_open; } + if (btmtkuart_is_standalone(bdev)) { + if (bdev->curr_speed != bdev->desired_speed) + err = serdev_device_set_baudrate(bdev->serdev, + 115200); + else + err = serdev_device_set_baudrate(bdev->serdev, + bdev->desired_speed); + + if (err < 0) { + bt_dev_err(hdev, "Unable to set baudrate UART device %s", + dev_name(&bdev->serdev->dev)); + goto err_serdev_close; + } + + serdev_device_set_flow_control(bdev->serdev, false); + } + bdev->stp_cursor = 2; bdev->stp_dlen = 0; @@ -546,6 +595,8 @@ err_put_rpm: pm_runtime_put_sync(dev); err_disable_rpm: pm_runtime_disable(dev); +err_serdev_close: + serdev_device_close(bdev->serdev); err_open: return err; } @@ -606,8 +657,74 @@ static int btmtkuart_func_query(struct hci_dev *hdev) return status; } +static int btmtkuart_change_baudrate(struct hci_dev *hdev) +{ + struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); + struct btmtk_hci_wmt_params wmt_params; + u32 baudrate; + u8 param; + int err; + + /* Indicate the device to enter the probe state the host is + * ready to change a new baudrate. + */ + baudrate = cpu_to_le32(bdev->desired_speed); + wmt_params.op = MTK_WMT_HIF; + wmt_params.flag = 1; + wmt_params.dlen = 4; + wmt_params.data = &baudrate; + wmt_params.status = NULL; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to device baudrate (%d)", err); + return err; + } + + err = serdev_device_set_baudrate(bdev->serdev, + bdev->desired_speed); + if (err < 0) { + bt_dev_err(hdev, "Failed to set up host baudrate (%d)", + err); + return err; + } + + serdev_device_set_flow_control(bdev->serdev, false); + + /* Send a dummy byte 0xff to activate the new baudrate */ + param = 0xff; + err = serdev_device_write(bdev->serdev, ¶m, sizeof(param), + MAX_SCHEDULE_TIMEOUT); + if (err < 0 || err < sizeof(param)) + return err; + + serdev_device_wait_until_sent(bdev->serdev, 0); + + /* Wait some time for the device changing baudrate done */ + usleep_range(20000, 22000); + + /* Test the new baudrate */ + wmt_params.op = MTK_WMT_TEST; + wmt_params.flag = 7; + wmt_params.dlen = 0; + wmt_params.data = NULL; + wmt_params.status = NULL; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to test new baudrate (%d)", + err); + return err; + } + + bdev->curr_speed = bdev->desired_speed; + + return 0; +} + static int btmtkuart_setup(struct hci_dev *hdev) { + struct btmtkuart_dev *bdev = hci_get_drvdata(hdev); struct btmtk_hci_wmt_params wmt_params; ktime_t calltime, delta, rettime; struct btmtk_tci_sleep tci_sleep; @@ -618,6 +735,28 @@ static int btmtkuart_setup(struct hci_dev *hdev) calltime = ktime_get(); + /* Wakeup MCUSYS is required for certain devices before we start to + * do any setups. + */ + if (test_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state)) { + wmt_params.op = MTK_WMT_WAKEUP; + wmt_params.flag = 3; + wmt_params.dlen = 0; + wmt_params.data = NULL; + wmt_params.status = NULL; + + err = mtk_hci_wmt_sync(hdev, &wmt_params); + if (err < 0) { + bt_dev_err(hdev, "Failed to wakeup the chip (%d)", err); + return err; + } + + clear_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state); + } + + if (btmtkuart_is_standalone(bdev)) + btmtkuart_change_baudrate(hdev); + /* Query whether the firmware is already download */ wmt_params.op = MTK_WMT_SEMAPHORE; wmt_params.flag = 1; @@ -637,7 +776,7 @@ static int btmtkuart_setup(struct hci_dev *hdev) } /* Setup a firmware which the device definitely requires */ - err = mtk_setup_fw(hdev); + err = mtk_setup_firmware(hdev, bdev->data->fwname); if (err < 0) return err; @@ -754,24 +893,82 @@ static int btmtkuart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) return 0; } +static int btmtkuart_parse_dt(struct serdev_device *serdev) +{ + struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); + struct device_node *node = serdev->dev.of_node; + u32 speed = 921600; + int err; + + if (btmtkuart_is_standalone(bdev)) { + of_property_read_u32(node, "current-speed", &speed); + + bdev->desired_speed = speed; + + bdev->vcc = devm_regulator_get(&serdev->dev, "vcc"); + if (IS_ERR(bdev->vcc)) { + err = PTR_ERR(bdev->vcc); + return err; + } + + bdev->pinctrl = devm_pinctrl_get(&serdev->dev); + if (IS_ERR(bdev->pinctrl)) { + err = PTR_ERR(bdev->pinctrl); + return err; + } + + bdev->pins_boot = pinctrl_lookup_state(bdev->pinctrl, + "default"); + if (IS_ERR(bdev->pins_boot)) { + err = PTR_ERR(bdev->pins_boot); + return err; + } + + bdev->pins_runtime = pinctrl_lookup_state(bdev->pinctrl, + "runtime"); + if (IS_ERR(bdev->pins_runtime)) { + err = PTR_ERR(bdev->pins_runtime); + return err; + } + + bdev->reset = devm_gpiod_get_optional(&serdev->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(bdev->reset)) { + err = PTR_ERR(bdev->reset); + return err; + } + } else if (btmtkuart_is_builtin_soc(bdev)) { + bdev->clk = devm_clk_get(&serdev->dev, "ref"); + if (IS_ERR(bdev->clk)) + return PTR_ERR(bdev->clk); + } + + return 0; +} + static int btmtkuart_probe(struct serdev_device *serdev) { struct btmtkuart_dev *bdev; struct hci_dev *hdev; + int err; bdev = devm_kzalloc(&serdev->dev, sizeof(*bdev), GFP_KERNEL); if (!bdev) return -ENOMEM; - bdev->clk = devm_clk_get(&serdev->dev, "ref"); - if (IS_ERR(bdev->clk)) - return PTR_ERR(bdev->clk); + bdev->data = of_device_get_match_data(&serdev->dev); + if (!bdev->data) + return -ENODEV; bdev->serdev = serdev; serdev_device_set_drvdata(serdev, bdev); serdev_device_set_client_ops(serdev, &btmtkuart_client_ops); + err = btmtkuart_parse_dt(serdev); + if (err < 0) + return err; + INIT_WORK(&bdev->tx_work, btmtkuart_tx_work); skb_queue_head_init(&bdev->txq); @@ -798,13 +995,54 @@ static int btmtkuart_probe(struct serdev_device *serdev) hdev->manufacturer = 70; set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); - if (hci_register_dev(hdev) < 0) { + if (btmtkuart_is_standalone(bdev)) { + /* Switch to the specific pin state for the booting requires */ + pinctrl_select_state(bdev->pinctrl, bdev->pins_boot); + + /* Power on */ + err = regulator_enable(bdev->vcc); + if (err < 0) + return err; + + /* Reset if the reset-gpios is available otherwise the board + * -level design should be guaranteed. + */ + if (bdev->reset) { + gpiod_set_value_cansleep(bdev->reset, 1); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(bdev->reset, 0); + } + + /* Wait some time until device got ready and switch to the pin + * mode the device requires for UART transfers. + */ + msleep(50); + pinctrl_select_state(bdev->pinctrl, bdev->pins_runtime); + + /* A standalone device doesn't depends on power domain on SoC, + * so mark it as no callbacks. + */ + pm_runtime_no_callbacks(&serdev->dev); + + set_bit(BTMTKUART_REQUIRED_WAKEUP, &bdev->tx_state); + } + + err = hci_register_dev(hdev); + if (err < 0) { dev_err(&serdev->dev, "Can't register HCI device\n"); hci_free_dev(hdev); - return -ENODEV; + goto err_regulator_disable; } return 0; + +err_regulator_disable: + if (btmtkuart_is_standalone(bdev)) { + pinctrl_select_state(bdev->pinctrl, bdev->pins_boot); + regulator_disable(bdev->vcc); + } + + return err; } static void btmtkuart_remove(struct serdev_device *serdev) @@ -812,13 +1050,34 @@ static void btmtkuart_remove(struct serdev_device *serdev) struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev); struct hci_dev *hdev = bdev->hdev; + if (btmtkuart_is_standalone(bdev)) { + pinctrl_select_state(bdev->pinctrl, bdev->pins_boot); + regulator_disable(bdev->vcc); + } + hci_unregister_dev(hdev); hci_free_dev(hdev); } +static const struct btmtkuart_data mt7622_data = { + .fwname = FIRMWARE_MT7622, +}; + +static const struct btmtkuart_data mt7663_data = { + .flags = BTMTKUART_FLAG_STANDALONE_HW, + .fwname = FIRMWARE_MT7663, +}; + +static const struct btmtkuart_data mt7668_data = { + .flags = BTMTKUART_FLAG_STANDALONE_HW, + .fwname = FIRMWARE_MT7668, +}; + #ifdef CONFIG_OF static const struct of_device_id mtk_of_match_table[] = { - { .compatible = "mediatek,mt7622-bluetooth"}, + { .compatible = "mediatek,mt7622-bluetooth", .data = &mt7622_data}, + { .compatible = "mediatek,mt7663u-bluetooth", .data = &mt7663_data}, + { .compatible = "mediatek,mt7668u-bluetooth", .data = &mt7668_data}, { } }; MODULE_DEVICE_TABLE(of, mtk_of_match_table); @@ -840,3 +1099,5 @@ MODULE_DESCRIPTION("MediaTek Bluetooth Serial driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FIRMWARE_MT7622); +MODULE_FIRMWARE(FIRMWARE_MT7663); +MODULE_FIRMWARE(FIRMWARE_MT7668); -- cgit v1.2.3 From 084e5bb16bd7dc2b551bbd9fb358bf73e03ee8d8 Mon Sep 17 00:00:00 2001 From: Kavya Sree Kotagiri Date: Thu, 28 Feb 2019 07:32:22 +0000 Subject: net: mscc: Enable all ports in QSGMII When Ocelot phy-mode is QSGMII, all 4 ports involved in QSGMII shall be kept out of reset and Tx lanes shall be enabled to pass the data. Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support") Signed-off-by: Kavya Sree Kotagiri Signed-off-by: Steen Hegelund Co-developed-by: Steen Hegelund Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot_board.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c index ca3ea2fbfcd0..80d87798c62b 100644 --- a/drivers/net/ethernet/mscc/ocelot_board.c +++ b/drivers/net/ethernet/mscc/ocelot_board.c @@ -267,6 +267,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev) struct phy *serdes; void __iomem *regs; char res_name[8]; + int phy_mode; u32 port; if (of_property_read_u32(portnp, "reg", &port)) @@ -292,11 +293,11 @@ static int mscc_ocelot_probe(struct platform_device *pdev) if (err) return err; - err = of_get_phy_mode(portnp); - if (err < 0) + phy_mode = of_get_phy_mode(portnp); + if (phy_mode < 0) ocelot->ports[port]->phy_mode = PHY_INTERFACE_MODE_NA; else - ocelot->ports[port]->phy_mode = err; + ocelot->ports[port]->phy_mode = phy_mode; switch (ocelot->ports[port]->phy_mode) { case PHY_INTERFACE_MODE_NA: @@ -304,6 +305,13 @@ static int mscc_ocelot_probe(struct platform_device *pdev) case PHY_INTERFACE_MODE_SGMII: break; case PHY_INTERFACE_MODE_QSGMII: + /* Ensure clock signals and speed is set on all + * QSGMII links + */ + ocelot_port_writel(ocelot->ports[port], + DEV_CLOCK_CFG_LINK_SPEED + (OCELOT_SPEED_1000), + DEV_CLOCK_CFG); break; default: dev_err(ocelot->dev, -- cgit v1.2.3 From 8c29bebb1f8a68556db70088fd8f5938527a7346 Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Thu, 28 Feb 2019 19:57:24 -0800 Subject: net: dsa: microchip: add KSZ9893 switch support Add KSZ9893 switch support in KSZ9477 driver. This switch is similar to KSZ9477 except the ingress tail tag has 1 byte instead of 2 bytes, so KSZ9893 tagging will be used. The XMII register that governs how the host port communicates with the MAC also has different register definitions. Signed-off-by: Tristram Ha Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz9477.c | 242 ++++++++++++++++++++++++++++++-- drivers/net/dsa/microchip/ksz9477_spi.c | 4 +- drivers/net/dsa/microchip/ksz_common.c | 4 +- 3 files changed, 235 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 03de50e62beb..f16e1d7d8615 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -18,6 +18,11 @@ #include "ksz9477_reg.h" #include "ksz_common.h" +/* Used with variable features to indicate capabilities. */ +#define GBIT_SUPPORT BIT(0) +#define NEW_XMII BIT(1) +#define IS_9893 BIT(2) + static const struct { int index; char string[ETH_GSTRING_LEN]; @@ -328,7 +333,12 @@ static void ksz9477_port_init_cnt(struct ksz_device *dev, int port) static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds, int port) { - return DSA_TAG_PROTO_KSZ9477; + enum dsa_tag_protocol proto = DSA_TAG_PROTO_KSZ9477; + struct ksz_device *dev = ds->priv; + + if (dev->features & IS_9893) + proto = DSA_TAG_PROTO_KSZ9893; + return proto; } static int ksz9477_phy_read16(struct dsa_switch *ds, int addr, int reg) @@ -389,6 +399,10 @@ static int ksz9477_phy_write16(struct dsa_switch *ds, int addr, int reg, /* No real PHY after this. */ if (addr >= dev->phy_port_cnt) return 0; + + /* No gigabit support. Do not write to this register. */ + if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000) + return 0; ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val); return 0; @@ -998,11 +1012,156 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port, static void ksz9477_phy_setup(struct ksz_device *dev, int port, struct phy_device *phy) { - if (port < dev->phy_port_cnt) { - /* The MAC actually cannot run in 1000 half-duplex mode. */ + /* Only apply to port with PHY. */ + if (port >= dev->phy_port_cnt) + return; + + /* The MAC actually cannot run in 1000 half-duplex mode. */ + phy_remove_link_mode(phy, + ETHTOOL_LINK_MODE_1000baseT_Half_BIT); + + /* PHY does not support gigabit. */ + if (!(dev->features & GBIT_SUPPORT)) phy_remove_link_mode(phy, - ETHTOOL_LINK_MODE_1000baseT_Half_BIT); + ETHTOOL_LINK_MODE_1000baseT_Full_BIT); +} + +static bool ksz9477_get_gbit(struct ksz_device *dev, u8 data) +{ + bool gbit; + + if (dev->features & NEW_XMII) + gbit = !(data & PORT_MII_NOT_1GBIT); + else + gbit = !!(data & PORT_MII_1000MBIT_S1); + return gbit; +} + +static void ksz9477_set_gbit(struct ksz_device *dev, bool gbit, u8 *data) +{ + if (dev->features & NEW_XMII) { + if (gbit) + *data &= ~PORT_MII_NOT_1GBIT; + else + *data |= PORT_MII_NOT_1GBIT; + } else { + if (gbit) + *data |= PORT_MII_1000MBIT_S1; + else + *data &= ~PORT_MII_1000MBIT_S1; + } +} + +static int ksz9477_get_xmii(struct ksz_device *dev, u8 data) +{ + int mode; + + if (dev->features & NEW_XMII) { + switch (data & PORT_MII_SEL_M) { + case PORT_MII_SEL: + mode = 0; + break; + case PORT_RMII_SEL: + mode = 1; + break; + case PORT_GMII_SEL: + mode = 2; + break; + default: + mode = 3; + } + } else { + switch (data & PORT_MII_SEL_M) { + case PORT_MII_SEL_S1: + mode = 0; + break; + case PORT_RMII_SEL_S1: + mode = 1; + break; + case PORT_GMII_SEL_S1: + mode = 2; + break; + default: + mode = 3; + } + } + return mode; +} + +static void ksz9477_set_xmii(struct ksz_device *dev, int mode, u8 *data) +{ + u8 xmii; + + if (dev->features & NEW_XMII) { + switch (mode) { + case 0: + xmii = PORT_MII_SEL; + break; + case 1: + xmii = PORT_RMII_SEL; + break; + case 2: + xmii = PORT_GMII_SEL; + break; + default: + xmii = PORT_RGMII_SEL; + break; + } + } else { + switch (mode) { + case 0: + xmii = PORT_MII_SEL_S1; + break; + case 1: + xmii = PORT_RMII_SEL_S1; + break; + case 2: + xmii = PORT_GMII_SEL_S1; + break; + default: + xmii = PORT_RGMII_SEL_S1; + break; + } + } + *data &= ~PORT_MII_SEL_M; + *data |= xmii; +} + +static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port) +{ + phy_interface_t interface; + bool gbit; + int mode; + u8 data8; + + if (port < dev->phy_port_cnt) + return PHY_INTERFACE_MODE_NA; + ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8); + gbit = ksz9477_get_gbit(dev, data8); + mode = ksz9477_get_xmii(dev, data8); + switch (mode) { + case 2: + interface = PHY_INTERFACE_MODE_GMII; + if (gbit) + break; + case 0: + interface = PHY_INTERFACE_MODE_MII; + break; + case 1: + interface = PHY_INTERFACE_MODE_RMII; + break; + default: + interface = PHY_INTERFACE_MODE_RGMII; + if (data8 & PORT_RGMII_ID_EG_ENABLE) + interface = PHY_INTERFACE_MODE_RGMII_TXID; + if (data8 & PORT_RGMII_ID_IG_ENABLE) { + interface = PHY_INTERFACE_MODE_RGMII_RXID; + if (data8 & PORT_RGMII_ID_EG_ENABLE) + interface = PHY_INTERFACE_MODE_RGMII_ID; + } + break; } + return interface; } static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) @@ -1051,24 +1210,25 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) /* configure MAC to 1G & RGMII mode */ ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8); - data8 &= ~PORT_MII_NOT_1GBIT; - data8 &= ~PORT_MII_SEL_M; switch (dev->interface) { case PHY_INTERFACE_MODE_MII: - data8 |= PORT_MII_NOT_1GBIT; - data8 |= PORT_MII_SEL; + ksz9477_set_xmii(dev, 0, &data8); + ksz9477_set_gbit(dev, false, &data8); p->phydev.speed = SPEED_100; break; case PHY_INTERFACE_MODE_RMII: - data8 |= PORT_MII_NOT_1GBIT; - data8 |= PORT_RMII_SEL; + ksz9477_set_xmii(dev, 1, &data8); + ksz9477_set_gbit(dev, false, &data8); p->phydev.speed = SPEED_100; break; case PHY_INTERFACE_MODE_GMII: - data8 |= PORT_GMII_SEL; + ksz9477_set_xmii(dev, 2, &data8); + ksz9477_set_gbit(dev, true, &data8); p->phydev.speed = SPEED_1000; break; default: + ksz9477_set_xmii(dev, 3, &data8); + ksz9477_set_gbit(dev, true, &data8); data8 &= ~PORT_RGMII_ID_IG_ENABLE; data8 &= ~PORT_RGMII_ID_EG_ENABLE; if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID || @@ -1077,7 +1237,6 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID || dev->interface == PHY_INTERFACE_MODE_RGMII_TXID) data8 |= PORT_RGMII_ID_EG_ENABLE; - data8 |= PORT_RGMII_SEL; p->phydev.speed = SPEED_1000; break; } @@ -1115,10 +1274,25 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds) for (i = 0; i < dev->port_cnt; i++) { if (dsa_is_cpu_port(ds, i) && (dev->cpu_ports & (1 << i))) { + phy_interface_t interface; + dev->cpu_port = i; dev->host_mask = (1 << dev->cpu_port); dev->port_mask |= dev->host_mask; + /* Read from XMII register to determine host port + * interface. If set specifically in device tree + * note the difference to help debugging. + */ + interface = ksz9477_get_interface(dev, i); + if (!dev->interface) + dev->interface = interface; + if (interface && interface != dev->interface) + dev_info(dev->dev, + "use %s instead of %s\n", + phy_modes(dev->interface), + phy_modes(interface)); + /* enable cpu port */ ksz9477_port_setup(dev, i, true); p = &dev->ports[dev->cpu_port]; @@ -1172,6 +1346,9 @@ static int ksz9477_setup(struct dsa_switch *ds) ksz9477_cfg32(dev, REG_SW_QM_CTRL__4, UNICAST_VLAN_BOUNDARY, true); + /* Do not work correctly with tail tagging. */ + ksz_cfg(dev, REG_SW_MAC_CTRL_0, SW_CHECK_LENGTH, false); + /* accept packet up to 2000bytes */ ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_LEGAL_PACKET_DISABLE, true); @@ -1230,6 +1407,8 @@ static u32 ksz9477_get_port_addr(int port, int offset) static int ksz9477_switch_detect(struct ksz_device *dev) { u8 data8; + u8 id_hi; + u8 id_lo; u32 id32; int ret; @@ -1245,6 +1424,9 @@ static int ksz9477_switch_detect(struct ksz_device *dev) /* read chip id */ ret = ksz_read32(dev, REG_CHIP_ID0__1, &id32); + if (ret) + return ret; + ret = ksz_read8(dev, REG_GLOBAL_OPTIONS, &data8); if (ret) return ret; @@ -1252,6 +1434,32 @@ static int ksz9477_switch_detect(struct ksz_device *dev) dev->mib_port_cnt = TOTAL_PORT_NUM; dev->phy_port_cnt = 5; + /* Default capability is gigabit capable. */ + dev->features = GBIT_SUPPORT; + + id_hi = (u8)(id32 >> 16); + id_lo = (u8)(id32 >> 8); + if ((id_lo & 0xf) == 3) { + /* Chip is from KSZ9893 design. */ + dev->features |= IS_9893; + + /* Chip does not support gigabit. */ + if (data8 & SW_QW_ABLE) + dev->features &= ~GBIT_SUPPORT; + dev->mib_port_cnt = 3; + dev->phy_port_cnt = 2; + } else { + /* Chip uses new XMII register definitions. */ + dev->features |= NEW_XMII; + + /* Chip does not support gigabit. */ + if (!(data8 & SW_GIGABIT_ABLE)) + dev->features &= ~GBIT_SUPPORT; + } + + /* Change chip id to known ones so it can be matched against them. */ + id32 = (id_hi << 16) | (id_lo << 8); + dev->chip_id = id32; return 0; @@ -1286,6 +1494,15 @@ static const struct ksz_chip_data ksz9477_switch_chips[] = { .cpu_ports = 0x7F, /* can be configured as cpu port */ .port_cnt = 7, /* total physical port count */ }, + { + .chip_id = 0x00989300, + .dev_name = "KSZ9893", + .num_vlans = 4096, + .num_alus = 4096, + .num_statics = 16, + .cpu_ports = 0x07, /* can be configured as cpu port */ + .port_cnt = 3, /* total port count */ + }, }; static int ksz9477_switch_init(struct ksz_device *dev) @@ -1333,7 +1550,6 @@ static int ksz9477_switch_init(struct ksz_device *dev) if (!dev->ports[i].mib.counters) return -ENOMEM; } - dev->interface = PHY_INTERFACE_MODE_RGMII_TXID; return 0; } diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c index d757ba151cb1..75178624d3f5 100644 --- a/drivers/net/dsa/microchip/ksz9477_spi.c +++ b/drivers/net/dsa/microchip/ksz9477_spi.c @@ -2,7 +2,7 @@ /* * Microchip KSZ9477 series register access through SPI * - * Copyright (C) 2017-2018 Microchip Technology Inc. + * Copyright (C) 2017-2019 Microchip Technology Inc. */ #include @@ -155,6 +155,8 @@ static void ksz9477_spi_shutdown(struct spi_device *spi) static const struct of_device_id ksz9477_dt_ids[] = { { .compatible = "microchip,ksz9477" }, { .compatible = "microchip,ksz9897" }, + { .compatible = "microchip,ksz9893" }, + { .compatible = "microchip,ksz9563" }, {}, }; MODULE_DEVICE_TABLE(of, ksz9477_dt_ids); diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 9328b88849d2..39dace8e3512 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -453,7 +453,9 @@ int ksz_switch_register(struct ksz_device *dev, if (ret) return ret; - dev->interface = PHY_INTERFACE_MODE_MII; + /* Host port interface will be self detected, or specifically set in + * device tree. + */ if (dev->dev->of_node) { ret = of_get_phy_mode(dev->dev->of_node); if (ret >= 0) -- cgit v1.2.3 From 8beb79b7ae937632db1d2721d33b46526d41f153 Mon Sep 17 00:00:00 2001 From: Harini Katakam Date: Fri, 1 Mar 2019 16:20:32 +0530 Subject: net: macb: Check MDIO state before read/write and use timeouts Replace the while loop in MDIO read/write functions with a timeout. In addition, add a check for MDIO bus busy before initiating a new operation as well to make sure there is no ongoing MDIO operation. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Sai Pavan Boddu Signed-off-by: Harini Katakam Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.h | 2 ++ drivers/net/ethernet/cadence/macb_main.c | 33 ++++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 9bbaad9f3d63..f51040fedcf5 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -715,6 +715,8 @@ __v; \ }) +#define MACB_READ_NSR(bp) macb_readl(bp, NSR) + /* struct macb_dma_desc - Hardware DMA descriptor * @addr: DMA address of data buffer * @ctrl: Control and status bits diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index f2915f2fe21a..a19ed2b62181 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "macb.h" #define MACB_RX_BUFFER_SIZE 128 @@ -79,6 +80,8 @@ */ #define MACB_HALT_TIMEOUT 1230 +#define MACB_MDIO_TIMEOUT 1000000 /* in usecs */ + /* DMA buffer descriptor might be different size * depends on hardware configuration: * @@ -318,10 +321,23 @@ static void macb_get_hwaddr(struct macb *bp) eth_hw_addr_random(bp->dev); } +static int macb_mdio_wait_for_idle(struct macb *bp) +{ + u32 val; + + return readx_poll_timeout(MACB_READ_NSR, bp, val, val & MACB_BIT(IDLE), + 1, MACB_MDIO_TIMEOUT); +} + static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct macb *bp = bus->priv; int value; + int err; + + err = macb_mdio_wait_for_idle(bp); + if (err < 0) + return err; macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_READ) @@ -329,9 +345,9 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | MACB_BF(REGA, regnum) | MACB_BF(CODE, MACB_MAN_CODE))); - /* wait for end of transfer */ - while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR))) - cpu_relax(); + err = macb_mdio_wait_for_idle(bp); + if (err < 0) + return err; value = MACB_BFEXT(DATA, macb_readl(bp, MAN)); @@ -342,6 +358,11 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { struct macb *bp = bus->priv; + int err; + + err = macb_mdio_wait_for_idle(bp); + if (err < 0) + return err; macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_WRITE) @@ -350,9 +371,9 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum, | MACB_BF(CODE, MACB_MAN_CODE) | MACB_BF(DATA, value))); - /* wait for end of transfer */ - while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR))) - cpu_relax(); + err = macb_mdio_wait_for_idle(bp); + if (err < 0) + return err; return 0; } -- cgit v1.2.3 From f5473d1d44e4b427b72824436b74a705f9eaf4b4 Mon Sep 17 00:00:00 2001 From: Harini Katakam Date: Fri, 1 Mar 2019 16:20:33 +0530 Subject: net: macb: Support clock management for tsu_clk TSU clock needs to be enabled/disabled as per support in devicetree and it should also be controlled during suspend/resume (WOL has no dependency on this clock). Signed-off-by: Harini Katakam Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.h | 3 ++- drivers/net/ethernet/cadence/macb_main.c | 30 +++++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index f51040fedcf5..acc66a7e7b95 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -1085,7 +1085,7 @@ struct macb_config { unsigned int dma_burst_length; int (*clk_init)(struct platform_device *pdev, struct clk **pclk, struct clk **hclk, struct clk **tx_clk, - struct clk **rx_clk); + struct clk **rx_clk, struct clk **tsu_clk); int (*init)(struct platform_device *pdev); int jumbo_max_len; }; @@ -1165,6 +1165,7 @@ struct macb { struct clk *hclk; struct clk *tx_clk; struct clk *rx_clk; + struct clk *tsu_clk; struct net_device *dev; union { struct macb_stats macb; diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index a19ed2b62181..be10ee4c791f 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3325,7 +3325,7 @@ static void macb_probe_queues(void __iomem *mem, static int macb_clk_init(struct platform_device *pdev, struct clk **pclk, struct clk **hclk, struct clk **tx_clk, - struct clk **rx_clk) + struct clk **rx_clk, struct clk **tsu_clk) { struct macb_platform_data *pdata; int err; @@ -3359,6 +3359,10 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk, if (IS_ERR(*rx_clk)) *rx_clk = NULL; + *tsu_clk = devm_clk_get(&pdev->dev, "tsu_clk"); + if (IS_ERR(*tsu_clk)) + *tsu_clk = NULL; + err = clk_prepare_enable(*pclk); if (err) { dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err); @@ -3383,8 +3387,17 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk, goto err_disable_txclk; } + err = clk_prepare_enable(*tsu_clk); + if (err) { + dev_err(&pdev->dev, "failed to enable tsu_clk (%u)\n", err); + goto err_disable_rxclk; + } + return 0; +err_disable_rxclk: + clk_disable_unprepare(*rx_clk); + err_disable_txclk: clk_disable_unprepare(*tx_clk); @@ -3835,13 +3848,14 @@ static const struct net_device_ops at91ether_netdev_ops = { static int at91ether_clk_init(struct platform_device *pdev, struct clk **pclk, struct clk **hclk, struct clk **tx_clk, - struct clk **rx_clk) + struct clk **rx_clk, struct clk **tsu_clk) { int err; *hclk = NULL; *tx_clk = NULL; *rx_clk = NULL; + *tsu_clk = NULL; *pclk = devm_clk_get(&pdev->dev, "ether_clk"); if (IS_ERR(*pclk)) @@ -3992,11 +4006,12 @@ static int macb_probe(struct platform_device *pdev) { const struct macb_config *macb_config = &default_gem_config; int (*clk_init)(struct platform_device *, struct clk **, - struct clk **, struct clk **, struct clk **) - = macb_config->clk_init; + struct clk **, struct clk **, struct clk **, + struct clk **) = macb_config->clk_init; int (*init)(struct platform_device *) = macb_config->init; struct device_node *np = pdev->dev.of_node; struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL; + struct clk *tsu_clk = NULL; unsigned int queue_mask, num_queues; struct macb_platform_data *pdata; bool native_io; @@ -4024,7 +4039,7 @@ static int macb_probe(struct platform_device *pdev) } } - err = clk_init(pdev, &pclk, &hclk, &tx_clk, &rx_clk); + err = clk_init(pdev, &pclk, &hclk, &tx_clk, &rx_clk, &tsu_clk); if (err) return err; @@ -4061,6 +4076,7 @@ static int macb_probe(struct platform_device *pdev) bp->hclk = hclk; bp->tx_clk = tx_clk; bp->rx_clk = rx_clk; + bp->tsu_clk = tsu_clk; if (macb_config) bp->jumbo_max_len = macb_config->jumbo_max_len; @@ -4180,6 +4196,7 @@ err_disable_clocks: clk_disable_unprepare(hclk); clk_disable_unprepare(pclk); clk_disable_unprepare(rx_clk); + clk_disable_unprepare(tsu_clk); return err; } @@ -4207,6 +4224,7 @@ static int macb_remove(struct platform_device *pdev) clk_disable_unprepare(bp->hclk); clk_disable_unprepare(bp->pclk); clk_disable_unprepare(bp->rx_clk); + clk_disable_unprepare(bp->tsu_clk); of_node_put(bp->phy_node); free_netdev(dev); } @@ -4232,6 +4250,7 @@ static int __maybe_unused macb_suspend(struct device *dev) clk_disable_unprepare(bp->pclk); clk_disable_unprepare(bp->rx_clk); } + clk_disable_unprepare(bp->tsu_clk); return 0; } @@ -4251,6 +4270,7 @@ static int __maybe_unused macb_resume(struct device *dev) clk_prepare_enable(bp->tx_clk); clk_prepare_enable(bp->rx_clk); } + clk_prepare_enable(bp->tsu_clk); netif_device_attach(netdev); -- cgit v1.2.3 From d54f89af6cc4d6dd6a0bec2e21e1bafa8bd27c8e Mon Sep 17 00:00:00 2001 From: Harini Katakam Date: Fri, 1 Mar 2019 16:20:34 +0530 Subject: net: macb: Add pm runtime support Add runtime pm functions and move clock handling there. Add runtime PM calls to mdio functions to allow for active mdio bus. Signed-off-by: Shubhrajyoti Datta Signed-off-by: Harini Katakam Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 148 +++++++++++++++++++++++-------- 1 file changed, 112 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index be10ee4c791f..5173c02e292e 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "macb.h" #define MACB_RX_BUFFER_SIZE 128 @@ -80,6 +81,8 @@ */ #define MACB_HALT_TIMEOUT 1230 +#define MACB_PM_TIMEOUT 100 /* ms */ + #define MACB_MDIO_TIMEOUT 1000000 /* in usecs */ /* DMA buffer descriptor might be different size @@ -332,12 +335,15 @@ static int macb_mdio_wait_for_idle(struct macb *bp) static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct macb *bp = bus->priv; - int value; - int err; + int status; - err = macb_mdio_wait_for_idle(bp); - if (err < 0) - return err; + status = pm_runtime_get_sync(&bp->pdev->dev); + if (status < 0) + goto mdio_pm_exit; + + status = macb_mdio_wait_for_idle(bp); + if (status < 0) + goto mdio_read_exit; macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_READ) @@ -345,24 +351,32 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | MACB_BF(REGA, regnum) | MACB_BF(CODE, MACB_MAN_CODE))); - err = macb_mdio_wait_for_idle(bp); - if (err < 0) - return err; + status = macb_mdio_wait_for_idle(bp); + if (status < 0) + goto mdio_read_exit; - value = MACB_BFEXT(DATA, macb_readl(bp, MAN)); + status = MACB_BFEXT(DATA, macb_readl(bp, MAN)); - return value; +mdio_read_exit: + pm_runtime_mark_last_busy(&bp->pdev->dev); + pm_runtime_put_autosuspend(&bp->pdev->dev); +mdio_pm_exit: + return status; } static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { struct macb *bp = bus->priv; - int err; + int status; - err = macb_mdio_wait_for_idle(bp); - if (err < 0) - return err; + status = pm_runtime_get_sync(&bp->pdev->dev); + if (status < 0) + goto mdio_pm_exit; + + status = macb_mdio_wait_for_idle(bp); + if (status < 0) + goto mdio_write_exit; macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_WRITE) @@ -371,11 +385,15 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum, | MACB_BF(CODE, MACB_MAN_CODE) | MACB_BF(DATA, value))); - err = macb_mdio_wait_for_idle(bp); - if (err < 0) - return err; + status = macb_mdio_wait_for_idle(bp); + if (status < 0) + goto mdio_write_exit; - return 0; +mdio_write_exit: + pm_runtime_mark_last_busy(&bp->pdev->dev); + pm_runtime_put_autosuspend(&bp->pdev->dev); +mdio_pm_exit: + return status; } /** @@ -2418,12 +2436,18 @@ static int macb_open(struct net_device *dev) netdev_dbg(bp->dev, "open\n"); + err = pm_runtime_get_sync(&bp->pdev->dev); + if (err < 0) + goto pm_exit; + /* carrier starts down */ netif_carrier_off(dev); /* if the phy is not yet register, retry later*/ - if (!dev->phydev) - return -EAGAIN; + if (!dev->phydev) { + err = -EAGAIN; + goto pm_exit; + } /* RX buffers initialization */ macb_init_rx_buffer_size(bp, bufsz); @@ -2432,7 +2456,7 @@ static int macb_open(struct net_device *dev) if (err) { netdev_err(dev, "Unable to allocate DMA memory (error %d)\n", err); - return err; + goto pm_exit; } bp->macbgem_ops.mog_init_rings(bp); @@ -2449,6 +2473,11 @@ static int macb_open(struct net_device *dev) if (bp->ptp_info) bp->ptp_info->ptp_init(dev); +pm_exit: + if (err) { + pm_runtime_put_sync(&bp->pdev->dev); + return err; + } return 0; } @@ -2477,6 +2506,8 @@ static int macb_close(struct net_device *dev) if (bp->ptp_info) bp->ptp_info->ptp_remove(dev); + pm_runtime_put(&bp->pdev->dev); + return 0; } @@ -4043,6 +4074,11 @@ static int macb_probe(struct platform_device *pdev) if (err) return err; + pm_runtime_set_autosuspend_delay(&pdev->dev, MACB_PM_TIMEOUT); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); native_io = hw_is_native_io(mem); macb_probe_queues(mem, native_io, &queue_mask, &num_queues); @@ -4178,6 +4214,9 @@ static int macb_probe(struct platform_device *pdev) macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID), dev->base_addr, dev->irq, dev->dev_addr); + pm_runtime_mark_last_busy(&bp->pdev->dev); + pm_runtime_put_autosuspend(&bp->pdev->dev); + return 0; err_out_unregister_mdio: @@ -4197,6 +4236,9 @@ err_disable_clocks: clk_disable_unprepare(pclk); clk_disable_unprepare(rx_clk); clk_disable_unprepare(tsu_clk); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); return err; } @@ -4220,11 +4262,16 @@ static int macb_remove(struct platform_device *pdev) mdiobus_free(bp->mii_bus); unregister_netdev(dev); - clk_disable_unprepare(bp->tx_clk); - clk_disable_unprepare(bp->hclk); - clk_disable_unprepare(bp->pclk); - clk_disable_unprepare(bp->rx_clk); - clk_disable_unprepare(bp->tsu_clk); + pm_runtime_disable(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); + if (!pm_runtime_suspended(&pdev->dev)) { + clk_disable_unprepare(bp->tx_clk); + clk_disable_unprepare(bp->hclk); + clk_disable_unprepare(bp->pclk); + clk_disable_unprepare(bp->rx_clk); + clk_disable_unprepare(bp->tsu_clk); + pm_runtime_set_suspended(&pdev->dev); + } of_node_put(bp->phy_node); free_netdev(dev); } @@ -4244,13 +4291,9 @@ static int __maybe_unused macb_suspend(struct device *dev) macb_writel(bp, IER, MACB_BIT(WOL)); macb_writel(bp, WOL, MACB_BIT(MAG)); enable_irq_wake(bp->queues[0].irq); - } else { - clk_disable_unprepare(bp->tx_clk); - clk_disable_unprepare(bp->hclk); - clk_disable_unprepare(bp->pclk); - clk_disable_unprepare(bp->rx_clk); } - clk_disable_unprepare(bp->tsu_clk); + + pm_runtime_force_suspend(dev); return 0; } @@ -4260,11 +4303,43 @@ static int __maybe_unused macb_resume(struct device *dev) struct net_device *netdev = dev_get_drvdata(dev); struct macb *bp = netdev_priv(netdev); + pm_runtime_force_resume(dev); + if (bp->wol & MACB_WOL_ENABLED) { macb_writel(bp, IDR, MACB_BIT(WOL)); macb_writel(bp, WOL, 0); disable_irq_wake(bp->queues[0].irq); - } else { + } + + netif_device_attach(netdev); + + return 0; +} + +static int __maybe_unused macb_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *netdev = platform_get_drvdata(pdev); + struct macb *bp = netdev_priv(netdev); + + if (!(device_may_wakeup(&bp->dev->dev))) { + clk_disable_unprepare(bp->tx_clk); + clk_disable_unprepare(bp->hclk); + clk_disable_unprepare(bp->pclk); + clk_disable_unprepare(bp->rx_clk); + } + clk_disable_unprepare(bp->tsu_clk); + + return 0; +} + +static int __maybe_unused macb_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct net_device *netdev = platform_get_drvdata(pdev); + struct macb *bp = netdev_priv(netdev); + + if (!(device_may_wakeup(&bp->dev->dev))) { clk_prepare_enable(bp->pclk); clk_prepare_enable(bp->hclk); clk_prepare_enable(bp->tx_clk); @@ -4272,12 +4347,13 @@ static int __maybe_unused macb_resume(struct device *dev) } clk_prepare_enable(bp->tsu_clk); - netif_device_attach(netdev); - return 0; } -static SIMPLE_DEV_PM_OPS(macb_pm_ops, macb_suspend, macb_resume); +static const struct dev_pm_ops macb_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(macb_suspend, macb_resume) + SET_RUNTIME_PM_OPS(macb_runtime_suspend, macb_runtime_resume, NULL) +}; static struct platform_driver macb_driver = { .probe = macb_probe, -- cgit v1.2.3 From de991c58b3761e4ddb8eeb204987155111332f59 Mon Sep 17 00:00:00 2001 From: Harini Katakam Date: Fri, 1 Mar 2019 16:20:35 +0530 Subject: net: macb: Add support for suspend/resume with full power down When macb device is suspended and system is powered down, the clocks are removed and hence macb should be closed gracefully and restored upon resume. This patch does the same by switching off the net device, suspending phy and performing necessary cleanup of interrupts and BDs. Upon resume, all these are reinitialized again. Reset of macb device is done only when GEM is not a wake device. Even when gem is a wake device, tx queues can be stopped and ptp device can be closed (tsu clock will be disabled in pm_runtime_suspend) as wake event detection has no dependency on this. Signed-off-by: Kedareswara rao Appana Signed-off-by: Harini Katakam Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 40 ++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 5173c02e292e..ad099fd01b45 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -4283,16 +4283,34 @@ static int __maybe_unused macb_suspend(struct device *dev) { struct net_device *netdev = dev_get_drvdata(dev); struct macb *bp = netdev_priv(netdev); + struct macb_queue *queue = bp->queues; + unsigned long flags; + unsigned int q; + + if (!netif_running(netdev)) + return 0; - netif_carrier_off(netdev); - netif_device_detach(netdev); if (bp->wol & MACB_WOL_ENABLED) { macb_writel(bp, IER, MACB_BIT(WOL)); macb_writel(bp, WOL, MACB_BIT(MAG)); enable_irq_wake(bp->queues[0].irq); + netif_device_detach(netdev); + } else { + netif_device_detach(netdev); + for (q = 0, queue = bp->queues; q < bp->num_queues; + ++q, ++queue) + napi_disable(&queue->napi); + phy_stop(netdev->phydev); + phy_suspend(netdev->phydev); + spin_lock_irqsave(&bp->lock, flags); + macb_reset_hw(bp); + spin_unlock_irqrestore(&bp->lock, flags); } + netif_carrier_off(netdev); + if (bp->ptp_info) + bp->ptp_info->ptp_remove(netdev); pm_runtime_force_suspend(dev); return 0; @@ -4302,6 +4320,11 @@ static int __maybe_unused macb_resume(struct device *dev) { struct net_device *netdev = dev_get_drvdata(dev); struct macb *bp = netdev_priv(netdev); + struct macb_queue *queue = bp->queues; + unsigned int q; + + if (!netif_running(netdev)) + return 0; pm_runtime_force_resume(dev); @@ -4309,9 +4332,22 @@ static int __maybe_unused macb_resume(struct device *dev) macb_writel(bp, IDR, MACB_BIT(WOL)); macb_writel(bp, WOL, 0); disable_irq_wake(bp->queues[0].irq); + } else { + macb_writel(bp, NCR, MACB_BIT(MPE)); + for (q = 0, queue = bp->queues; q < bp->num_queues; + ++q, ++queue) + napi_enable(&queue->napi); + phy_resume(netdev->phydev); + phy_init_hw(netdev->phydev); + phy_start(netdev->phydev); } + bp->macbgem_ops.mog_init_rings(bp); + macb_init_hw(bp); + macb_set_rx_mode(netdev); netif_device_attach(netdev); + if (bp->ptp_info) + bp->ptp_info->ptp_init(netdev); return 0; } -- cgit v1.2.3 From e3fdf6ba09a082175d3b0f85a4253702918e7582 Mon Sep 17 00:00:00 2001 From: Ioana Radulescu Date: Fri, 1 Mar 2019 17:47:23 +0000 Subject: dpaa2-eth: Add software annotation types We write different metadata information in the software annotation area of Tx frames, depending on frame type. Make this more explicit by introducing a type field and separate structures for single buffer and scatter-gather frames. Signed-off-by: Ioana Radulescu Signed-off-by: Ioana Ciornei Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 38 +++++++++++++----------- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 24 ++++++++++++--- 2 files changed, 40 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 87777b09f5e0..3acfd8cb437a 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -571,10 +571,11 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv, * all of them on Tx Conf. */ swa = (struct dpaa2_eth_swa *)sgt_buf; - swa->skb = skb; - swa->scl = scl; - swa->num_sg = num_sg; - swa->sgt_size = sgt_buf_size; + swa->type = DPAA2_ETH_SWA_SG; + swa->sg.skb = skb; + swa->sg.scl = scl; + swa->sg.num_sg = num_sg; + swa->sg.sgt_size = sgt_buf_size; /* Separately map the SGT buffer */ addr = dma_map_single(dev, sgt_buf, sgt_buf_size, DMA_BIDIRECTIONAL); @@ -609,7 +610,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv, { struct device *dev = priv->net_dev->dev.parent; u8 *buffer_start, *aligned_start; - struct sk_buff **skbh; + struct dpaa2_eth_swa *swa; dma_addr_t addr; buffer_start = skb->data - dpaa2_eth_needed_headroom(priv, skb); @@ -626,8 +627,9 @@ static int build_single_fd(struct dpaa2_eth_priv *priv, * (in the private data area) such that we can release it * on Tx confirm */ - skbh = (struct sk_buff **)buffer_start; - *skbh = skb; + swa = (struct dpaa2_eth_swa *)buffer_start; + swa->type = DPAA2_ETH_SWA_SINGLE; + swa->single.skb = skb; addr = dma_map_single(dev, buffer_start, skb_tail_pointer(skb) - buffer_start, @@ -659,17 +661,17 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv, { struct device *dev = priv->net_dev->dev.parent; dma_addr_t fd_addr; - struct sk_buff **skbh, *skb; + struct sk_buff *skb; unsigned char *buffer_start; struct dpaa2_eth_swa *swa; u8 fd_format = dpaa2_fd_get_format(fd); fd_addr = dpaa2_fd_get_addr(fd); - skbh = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr); + buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr); + swa = (struct dpaa2_eth_swa *)buffer_start; if (fd_format == dpaa2_fd_single) { - skb = *skbh; - buffer_start = (unsigned char *)skbh; + skb = swa->single.skb; /* Accessing the skb buffer is safe before dma unmap, because * we didn't map the actual skb shell. */ @@ -677,15 +679,15 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv, skb_tail_pointer(skb) - buffer_start, DMA_BIDIRECTIONAL); } else if (fd_format == dpaa2_fd_sg) { - swa = (struct dpaa2_eth_swa *)skbh; - skb = swa->skb; + skb = swa->sg.skb; /* Unmap the scatterlist */ - dma_unmap_sg(dev, swa->scl, swa->num_sg, DMA_BIDIRECTIONAL); - kfree(swa->scl); + dma_unmap_sg(dev, swa->sg.scl, swa->sg.num_sg, + DMA_BIDIRECTIONAL); + kfree(swa->sg.scl); /* Unmap the SGT buffer */ - dma_unmap_single(dev, fd_addr, swa->sgt_size, + dma_unmap_single(dev, fd_addr, swa->sg.sgt_size, DMA_BIDIRECTIONAL); } else { netdev_dbg(priv->net_dev, "Invalid FD format\n"); @@ -695,7 +697,7 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv, /* Get the timestamp value */ if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { struct skb_shared_hwtstamps shhwtstamps; - __le64 *ts = dpaa2_get_ts(skbh, true); + __le64 *ts = dpaa2_get_ts(buffer_start, true); u64 ns; memset(&shhwtstamps, 0, sizeof(shhwtstamps)); @@ -707,7 +709,7 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv, /* Free SGT buffer allocated on tx */ if (fd_format != dpaa2_fd_single) - skb_free_frag(skbh); + skb_free_frag(buffer_start); /* Move on with skb release */ napi_consume_skb(skb, in_napi); diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h index 9510928b7cca..423976d97fa6 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h @@ -89,12 +89,28 @@ */ #define DPAA2_ETH_SWA_SIZE 64 +/* We store different information in the software annotation area of a Tx frame + * based on what type of frame it is + */ +enum dpaa2_eth_swa_type { + DPAA2_ETH_SWA_SINGLE, + DPAA2_ETH_SWA_SG, +}; + /* Must keep this struct smaller than DPAA2_ETH_SWA_SIZE */ struct dpaa2_eth_swa { - struct sk_buff *skb; - struct scatterlist *scl; - int num_sg; - int sgt_size; + enum dpaa2_eth_swa_type type; + union { + struct { + struct sk_buff *skb; + } single; + struct { + struct sk_buff *skb; + struct scatterlist *scl; + int num_sg; + int sgt_size; + } sg; + }; }; /* Annotation valid bits in FD FRC */ -- cgit v1.2.3 From d678be1dc1ec59eee1f733ff603f601469ff368d Mon Sep 17 00:00:00 2001 From: Ioana Radulescu Date: Fri, 1 Mar 2019 17:47:24 +0000 Subject: dpaa2-eth: add XDP_REDIRECT support Implement support for the XDP_REDIRECT action. The redirected frame is transmitted and confirmed on the regular Tx/Tx conf queues. Frame is marked with the "XDP" type in the software annotation, since it requires special treatment. We don't have good hardware support for TX batching, so the XDP_XMIT_FLUSH flag doesn't make a difference for now; ndo_xdp_xmit performs the actual Tx operation on the spot. Signed-off-by: Ioana Ciornei Signed-off-by: Ioana Radulescu Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 175 +++++++++++++++++++-- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h | 14 ++ .../net/ethernet/freescale/dpaa2/dpaa2-ethtool.c | 1 + 3 files changed, 176 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 3acfd8cb437a..81085e70c239 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -296,6 +296,7 @@ static u32 run_xdp(struct dpaa2_eth_priv *priv, xdp.data_end = xdp.data + dpaa2_fd_get_len(fd); xdp.data_hard_start = xdp.data - XDP_PACKET_HEADROOM; xdp_set_data_meta_invalid(&xdp); + xdp.rxq = &ch->xdp_rxq; xdp_act = bpf_prog_run_xdp(xdp_prog, &xdp); @@ -328,8 +329,20 @@ static u32 run_xdp(struct dpaa2_eth_priv *priv, xdp_release_buf(priv, ch, addr); ch->stats.xdp_drop++; break; + case XDP_REDIRECT: + dma_unmap_page(priv->net_dev->dev.parent, addr, + DPAA2_ETH_RX_BUF_SIZE, DMA_BIDIRECTIONAL); + ch->buf_count--; + xdp.data_hard_start = vaddr; + err = xdp_do_redirect(priv->net_dev, &xdp, xdp_prog); + if (unlikely(err)) + ch->stats.xdp_drop++; + else + ch->stats.xdp_redirect++; + break; } + ch->xdp.res |= xdp_act; out: rcu_read_unlock(); return xdp_act; @@ -657,27 +670,35 @@ static int build_single_fd(struct dpaa2_eth_priv *priv, * dpaa2_eth_tx(). */ static void free_tx_fd(const struct dpaa2_eth_priv *priv, + struct dpaa2_eth_fq *fq, const struct dpaa2_fd *fd, bool in_napi) { struct device *dev = priv->net_dev->dev.parent; dma_addr_t fd_addr; - struct sk_buff *skb; + struct sk_buff *skb = NULL; unsigned char *buffer_start; struct dpaa2_eth_swa *swa; u8 fd_format = dpaa2_fd_get_format(fd); + u32 fd_len = dpaa2_fd_get_len(fd); fd_addr = dpaa2_fd_get_addr(fd); buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr); swa = (struct dpaa2_eth_swa *)buffer_start; if (fd_format == dpaa2_fd_single) { - skb = swa->single.skb; - /* Accessing the skb buffer is safe before dma unmap, because - * we didn't map the actual skb shell. - */ - dma_unmap_single(dev, fd_addr, - skb_tail_pointer(skb) - buffer_start, - DMA_BIDIRECTIONAL); + if (swa->type == DPAA2_ETH_SWA_SINGLE) { + skb = swa->single.skb; + /* Accessing the skb buffer is safe before dma unmap, + * because we didn't map the actual skb shell. + */ + dma_unmap_single(dev, fd_addr, + skb_tail_pointer(skb) - buffer_start, + DMA_BIDIRECTIONAL); + } else { + WARN_ONCE(swa->type != DPAA2_ETH_SWA_XDP, "Wrong SWA type"); + dma_unmap_single(dev, fd_addr, swa->xdp.dma_size, + DMA_BIDIRECTIONAL); + } } else if (fd_format == dpaa2_fd_sg) { skb = swa->sg.skb; @@ -694,6 +715,16 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv, return; } + if (swa->type != DPAA2_ETH_SWA_XDP && in_napi) { + fq->dq_frames++; + fq->dq_bytes += fd_len; + } + + if (swa->type == DPAA2_ETH_SWA_XDP) { + xdp_return_frame(swa->xdp.xdpf); + return; + } + /* Get the timestamp value */ if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { struct skb_shared_hwtstamps shhwtstamps; @@ -793,7 +824,7 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) if (unlikely(err < 0)) { percpu_stats->tx_errors++; /* Clean up everything, including freeing the skb */ - free_tx_fd(priv, &fd, false); + free_tx_fd(priv, fq, &fd, false); } else { fd_len = dpaa2_fd_get_len(&fd); percpu_stats->tx_packets++; @@ -830,12 +861,9 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv, percpu_extras->tx_conf_frames++; percpu_extras->tx_conf_bytes += fd_len; - fq->dq_frames++; - fq->dq_bytes += fd_len; - /* Check frame errors in the FD field */ fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK; - free_tx_fd(priv, fd, true); + free_tx_fd(priv, fq, fd, true); if (likely(!fd_errors)) return; @@ -1083,6 +1111,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget) int err; ch = container_of(napi, struct dpaa2_eth_channel, napi); + ch->xdp.res = 0; priv = ch->priv; do { @@ -1128,7 +1157,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget) work_done = max(rx_cleaned, 1); out: - if (txc_fq) { + if (txc_fq && txc_fq->dq_frames) { nq = netdev_get_tx_queue(priv->net_dev, txc_fq->flowid); netdev_tx_completed_queue(nq, txc_fq->dq_frames, txc_fq->dq_bytes); @@ -1136,6 +1165,9 @@ out: txc_fq->dq_bytes = 0; } + if (ch->xdp.res & XDP_REDIRECT) + xdp_do_flush_map(); + return work_done; } @@ -1730,6 +1762,105 @@ static int dpaa2_eth_xdp(struct net_device *dev, struct netdev_bpf *xdp) return 0; } +static int dpaa2_eth_xdp_xmit_frame(struct net_device *net_dev, + struct xdp_frame *xdpf) +{ + struct dpaa2_eth_priv *priv = netdev_priv(net_dev); + struct device *dev = net_dev->dev.parent; + struct rtnl_link_stats64 *percpu_stats; + struct dpaa2_eth_drv_stats *percpu_extras; + unsigned int needed_headroom; + struct dpaa2_eth_swa *swa; + struct dpaa2_eth_fq *fq; + struct dpaa2_fd fd; + void *buffer_start, *aligned_start; + dma_addr_t addr; + int err, i; + + /* We require a minimum headroom to be able to transmit the frame. + * Otherwise return an error and let the original net_device handle it + */ + needed_headroom = dpaa2_eth_needed_headroom(priv, NULL); + if (xdpf->headroom < needed_headroom) + return -EINVAL; + + percpu_stats = this_cpu_ptr(priv->percpu_stats); + percpu_extras = this_cpu_ptr(priv->percpu_extras); + + /* Setup the FD fields */ + memset(&fd, 0, sizeof(fd)); + + /* Align FD address, if possible */ + buffer_start = xdpf->data - needed_headroom; + aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN, + DPAA2_ETH_TX_BUF_ALIGN); + if (aligned_start >= xdpf->data - xdpf->headroom) + buffer_start = aligned_start; + + swa = (struct dpaa2_eth_swa *)buffer_start; + /* fill in necessary fields here */ + swa->type = DPAA2_ETH_SWA_XDP; + swa->xdp.dma_size = xdpf->data + xdpf->len - buffer_start; + swa->xdp.xdpf = xdpf; + + addr = dma_map_single(dev, buffer_start, + swa->xdp.dma_size, + DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(dev, addr))) { + percpu_stats->tx_dropped++; + return -ENOMEM; + } + + dpaa2_fd_set_addr(&fd, addr); + dpaa2_fd_set_offset(&fd, xdpf->data - buffer_start); + dpaa2_fd_set_len(&fd, xdpf->len); + dpaa2_fd_set_format(&fd, dpaa2_fd_single); + dpaa2_fd_set_ctrl(&fd, FD_CTRL_PTA); + + fq = &priv->fq[smp_processor_id()]; + for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { + err = priv->enqueue(priv, fq, &fd, 0); + if (err != -EBUSY) + break; + } + percpu_extras->tx_portal_busy += i; + if (unlikely(err < 0)) { + percpu_stats->tx_errors++; + /* let the Rx device handle the cleanup */ + return err; + } + + percpu_stats->tx_packets++; + percpu_stats->tx_bytes += dpaa2_fd_get_len(&fd); + + return 0; +} + +static int dpaa2_eth_xdp_xmit(struct net_device *net_dev, int n, + struct xdp_frame **frames, u32 flags) +{ + int drops = 0; + int i, err; + + if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) + return -EINVAL; + + if (!netif_running(net_dev)) + return -ENETDOWN; + + for (i = 0; i < n; i++) { + struct xdp_frame *xdpf = frames[i]; + + err = dpaa2_eth_xdp_xmit_frame(net_dev, xdpf); + if (err) { + xdp_return_frame_rx_napi(xdpf); + drops++; + } + } + + return n - drops; +} + static const struct net_device_ops dpaa2_eth_ops = { .ndo_open = dpaa2_eth_open, .ndo_start_xmit = dpaa2_eth_tx, @@ -1741,6 +1872,7 @@ static const struct net_device_ops dpaa2_eth_ops = { .ndo_do_ioctl = dpaa2_eth_ioctl, .ndo_change_mtu = dpaa2_eth_change_mtu, .ndo_bpf = dpaa2_eth_xdp, + .ndo_xdp_xmit = dpaa2_eth_xdp_xmit, }; static void cdan_cb(struct dpaa2_io_notification_ctx *ctx) @@ -2353,6 +2485,21 @@ static int setup_rx_flow(struct dpaa2_eth_priv *priv, return err; } + /* xdp_rxq setup */ + err = xdp_rxq_info_reg(&fq->channel->xdp_rxq, priv->net_dev, + fq->flowid); + if (err) { + dev_err(dev, "xdp_rxq_info_reg failed\n"); + return err; + } + + err = xdp_rxq_info_reg_mem_model(&fq->channel->xdp_rxq, + MEM_TYPE_PAGE_ORDER0, NULL); + if (err) { + dev_err(dev, "xdp_rxq_info_reg_mem_model failed\n"); + return err; + } + return 0; } diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h index 423976d97fa6..7879622aa3e6 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h @@ -95,6 +95,7 @@ enum dpaa2_eth_swa_type { DPAA2_ETH_SWA_SINGLE, DPAA2_ETH_SWA_SG, + DPAA2_ETH_SWA_XDP, }; /* Must keep this struct smaller than DPAA2_ETH_SWA_SIZE */ @@ -110,6 +111,10 @@ struct dpaa2_eth_swa { int num_sg; int sgt_size; } sg; + struct { + int dma_size; + struct xdp_frame *xdpf; + } xdp; }; }; @@ -273,6 +278,7 @@ struct dpaa2_eth_ch_stats { __u64 xdp_drop; __u64 xdp_tx; __u64 xdp_tx_err; + __u64 xdp_redirect; }; /* Maximum number of queues associated with a DPNI */ @@ -312,6 +318,7 @@ struct dpaa2_eth_ch_xdp { struct bpf_prog *prog; u64 drop_bufs[DPAA2_ETH_BUFS_PER_CMD]; int drop_cnt; + unsigned int res; }; struct dpaa2_eth_channel { @@ -326,6 +333,7 @@ struct dpaa2_eth_channel { int buf_count; struct dpaa2_eth_ch_stats stats; struct dpaa2_eth_ch_xdp xdp; + struct xdp_rxq_info xdp_rxq; }; struct dpaa2_eth_dist_fields { @@ -446,6 +454,12 @@ unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv, { unsigned int headroom = DPAA2_ETH_SWA_SIZE; + /* If we don't have an skb (e.g. XDP buffer), we only need space for + * the software annotation area + */ + if (!skb) + return headroom; + /* For non-linear skbs we have no headroom requirement, as we build a * SG frame with a newly allocated SGT buffer */ diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c index a7389e722c49..591dfcf76adb 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c @@ -48,6 +48,7 @@ static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = { "[drv] xdp drop", "[drv] xdp tx", "[drv] xdp tx errors", + "[drv] xdp redirect", /* FQ stats */ "[qbman] rx pending frames", "[qbman] rx pending bytes", -- cgit v1.2.3 From c6195a8bdfc62a7cecf7df685e64847a4b700275 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 1 Mar 2019 19:53:57 +0100 Subject: net: dsa: mv88e6xxx: handle unknown duplex modes gracefully in mv88e6xxx_port_set_duplex When testing another issue I faced the problem that mv88e6xxx_port_setup_mac() failed due to DUPLEX_UNKNOWN being passed as argument to mv88e6xxx_port_set_duplex(). We should handle this case gracefully and return -EOPNOTSUPP, like e.g. mv88e6xxx_port_set_speed() is doing it. Fixes: 7f1ae07b51e8 ("net: dsa: mv88e6xxx: add port duplex setter") Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 79ab51e69aee..184c2b1b3115 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -190,7 +190,7 @@ int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup) /* normal duplex detection */ break; default: - return -EINVAL; + return -EOPNOTSUPP; } err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg); -- cgit v1.2.3 From 6bfc1128d58bf74cc864870d680325b330725806 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 1 Mar 2019 16:37:25 -0800 Subject: fsl/fman: Use vsprintf extension %pM Make logging of an ethernet address more consistent with the rest of the kernel. Miscellanea: The %02hx use also did not quite match the u8 definition of addr though that did not actually matter given normal integer promotion rules. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fman/mac.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c index 71f4205f14e7..3c21486c6c84 100644 --- a/drivers/net/ethernet/freescale/fman/mac.c +++ b/drivers/net/ethernet/freescale/fman/mac.c @@ -855,9 +855,7 @@ static int mac_probe(struct platform_device *_of_dev) if (err < 0) dev_err(dev, "fman_set_mac_active_pause() = %d\n", err); - dev_info(dev, "FMan MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n", - mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2], - mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]); + dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); if (IS_ERR(priv->eth_dev)) { -- cgit v1.2.3 From 95150f29ae480276e76368cdf8a9524b5a96c0ca Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 2 Mar 2019 10:06:05 +0100 Subject: net: dsa: mv8e6xxx: fix number of internal PHYs for 88E6x90 family Ports 9 and 10 don't have internal PHY's but are (dependent on the version) SERDES/SGMII/XAUI/RXAUI ports. v2: - fix it for all 88E6x90 family members Fixes: bc3931557d1d ("net: dsa: mv88e6xxx: Add number of internal PHYs") Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 7e3c00bd9532..e7763e25ed8f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4222,7 +4222,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6190", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 11, + .num_internal_phys = 9, .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, @@ -4245,7 +4245,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6190X", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 11, + .num_internal_phys = 9, .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, @@ -4268,7 +4268,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6191", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 11, + .num_internal_phys = 9, .max_vid = 8191, .port_base_addr = 0x0, .phy_base_addr = 0x0, @@ -4315,7 +4315,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6290", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 11, + .num_internal_phys = 9, .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, @@ -4477,7 +4477,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6390", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 11, + .num_internal_phys = 9, .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, @@ -4500,7 +4500,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6390X", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 11, + .num_internal_phys = 9, .num_gpio = 16, .max_vid = 8191, .port_base_addr = 0x0, -- cgit v1.2.3 From 822e44b45eb991c63487c5e2ce7d636411870a8d Mon Sep 17 00:00:00 2001 From: Kristian Evensen Date: Sat, 2 Mar 2019 13:32:26 +0100 Subject: qmi_wwan: Add support for Quectel EG12/EM12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Quectel EG12 (module)/EM12 (M.2 card) is a Cat. 12 LTE modem. The modem behaves in the same way as the EP06, so the "set DTR"-quirk must be applied and the diagnostic-interface check performed. Since the diagnostic-check now applies to more modems, I have renamed the function from quectel_ep06_diag_detected() to quectel_diag_detected(). Signed-off-by: Kristian Evensen Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 18af2f8eee96..74bebbdb4b15 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -976,6 +976,13 @@ static const struct usb_device_id products[] = { 0xff), .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr, }, + { /* Quectel EG12/EM12 */ + USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x0512, + USB_CLASS_VENDOR_SPEC, + USB_SUBCLASS_VENDOR_SPEC, + 0xff), + .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr, + }, /* 3. Combined interface devices matching on interface number */ {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ @@ -1343,17 +1350,20 @@ static bool quectel_ec20_detected(struct usb_interface *intf) return false; } -static bool quectel_ep06_diag_detected(struct usb_interface *intf) +static bool quectel_diag_detected(struct usb_interface *intf) { struct usb_device *dev = interface_to_usbdev(intf); struct usb_interface_descriptor intf_desc = intf->cur_altsetting->desc; + u16 id_vendor = le16_to_cpu(dev->descriptor.idVendor); + u16 id_product = le16_to_cpu(dev->descriptor.idProduct); - if (le16_to_cpu(dev->descriptor.idVendor) == 0x2c7c && - le16_to_cpu(dev->descriptor.idProduct) == 0x0306 && - intf_desc.bNumEndpoints == 2) - return true; + if (id_vendor != 0x2c7c || intf_desc.bNumEndpoints != 2) + return false; - return false; + if (id_product == 0x0306 || id_product == 0x0512) + return true; + else + return false; } static int qmi_wwan_probe(struct usb_interface *intf, @@ -1390,13 +1400,13 @@ static int qmi_wwan_probe(struct usb_interface *intf, return -ENODEV; } - /* Quectel EP06/EM06/EG06 supports dynamic interface configuration, so + /* Several Quectel modems supports dynamic interface configuration, so * we need to match on class/subclass/protocol. These values are * identical for the diagnostic- and QMI-interface, but bNumEndpoints is * different. Ignore the current interface if the number of endpoints * the number for the diag interface (two). */ - if (quectel_ep06_diag_detected(intf)) + if (quectel_diag_detected(intf)) return -ENODEV; return usbnet_probe(intf, id); -- cgit v1.2.3 From d7bed825ba1264ab2244be5b547d7feedfacf811 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 2 Mar 2019 17:10:00 +0100 Subject: net: phy: use genphy_c45_aneg_done in genphy_aneg_done Now that we have it let's use genphy_c45_aneg_done() in phy_aneg_done(). Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 69dc64a4dbf8..3745220c5c98 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -144,14 +144,10 @@ int phy_aneg_done(struct phy_device *phydev) { if (phydev->drv && phydev->drv->aneg_done) return phydev->drv->aneg_done(phydev); - - /* Avoid genphy_aneg_done() if the Clause 45 PHY does not - * implement Clause 22 registers - */ - if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0))) - return -EINVAL; - - return genphy_aneg_done(phydev); + else if (phydev->is_c45) + return genphy_c45_aneg_done(phydev); + else + return genphy_aneg_done(phydev); } EXPORT_SYMBOL(phy_aneg_done); -- cgit v1.2.3 From a6d0aa97f453cc1a13ba93428590ef4fd29d005a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 2 Mar 2019 17:10:36 +0100 Subject: net: phy: remove gen10g_suspend and gen10g_resume phy_suspend() and phy_resume() are no-ops anyway if no callback is defined. Therefore we don't need these stubs. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 14 -------------- include/linux/phy.h | 2 -- 2 files changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 49e7cd08b05f..3ddbb9c32dda 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -529,18 +529,6 @@ int gen10g_config_init(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(gen10g_config_init); -int gen10g_suspend(struct phy_device *phydev) -{ - return 0; -} -EXPORT_SYMBOL_GPL(gen10g_suspend); - -int gen10g_resume(struct phy_device *phydev) -{ - return 0; -} -EXPORT_SYMBOL_GPL(gen10g_resume); - struct phy_driver genphy_10g_driver = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, @@ -550,6 +538,4 @@ struct phy_driver genphy_10g_driver = { .features = PHY_10GBIT_FEATURES, .config_aneg = gen10g_config_aneg, .read_status = gen10g_read_status, - .suspend = gen10g_suspend, - .resume = gen10g_resume, }; diff --git a/include/linux/phy.h b/include/linux/phy.h index bfe60e2a5174..c69de3b87e87 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1122,8 +1122,6 @@ int gen10g_config_aneg(struct phy_device *phydev); int gen10g_read_status(struct phy_device *phydev); int gen10g_no_soft_reset(struct phy_device *phydev); int gen10g_config_init(struct phy_device *phydev); -int gen10g_suspend(struct phy_device *phydev); -int gen10g_resume(struct phy_device *phydev); static inline int phy_read_status(struct phy_device *phydev) { -- cgit v1.2.3 From c5e91d39427d1759d6205599e145553b5b2bc19e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 2 Mar 2019 17:11:40 +0100 Subject: net: phy: remove gen10g_config_init ETHTOOL_LINK_MODE_10000baseT_Full_BIT is set anyway in the supported and advertising bitmap because it's part of PHY_10GBIT_FEATURES. And all users of gen10g_config_init use PHY_10GBIT_FEATURES. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/cortina.c | 1 - drivers/net/phy/phy-c45.c | 14 -------------- drivers/net/phy/teranetics.c | 1 - include/linux/phy.h | 1 - 4 files changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c index c291dc014769..a64eb211cc56 100644 --- a/drivers/net/phy/cortina.c +++ b/drivers/net/phy/cortina.c @@ -80,7 +80,6 @@ static struct phy_driver cortina_driver[] = { .phy_id_mask = 0xffffffff, .name = "Cortina CS4340", .features = PHY_10GBIT_FEATURES, - .config_init = gen10g_config_init, .config_aneg = gen10g_config_aneg, .read_status = cortina_read_status, .soft_reset = gen10g_no_soft_reset, diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 3ddbb9c32dda..cdbcea8609df 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -516,25 +516,11 @@ int gen10g_no_soft_reset(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(gen10g_no_soft_reset); -int gen10g_config_init(struct phy_device *phydev) -{ - /* Temporarily just say we support everything */ - linkmode_zero(phydev->supported); - - linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, - phydev->supported); - linkmode_copy(phydev->advertising, phydev->supported); - - return 0; -} -EXPORT_SYMBOL_GPL(gen10g_config_init); - struct phy_driver genphy_10g_driver = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, .name = "Generic 10G PHY", .soft_reset = gen10g_no_soft_reset, - .config_init = gen10g_config_init, .features = PHY_10GBIT_FEATURES, .config_aneg = gen10g_config_aneg, .read_status = gen10g_read_status, diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index 145c328b00fa..95280212d5d5 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -80,7 +80,6 @@ static struct phy_driver teranetics_driver[] = { .features = PHY_10GBIT_FEATURES, .soft_reset = gen10g_no_soft_reset, .aneg_done = teranetics_aneg_done, - .config_init = gen10g_config_init, .config_aneg = gen10g_config_aneg, .read_status = teranetics_read_status, .match_phy_device = teranetics_match_phy_device, diff --git a/include/linux/phy.h b/include/linux/phy.h index c69de3b87e87..817c8453aeb5 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1121,7 +1121,6 @@ int genphy_c45_read_status(struct phy_device *phydev); int gen10g_config_aneg(struct phy_device *phydev); int gen10g_read_status(struct phy_device *phydev); int gen10g_no_soft_reset(struct phy_device *phydev); -int gen10g_config_init(struct phy_device *phydev); static inline int phy_read_status(struct phy_device *phydev) { -- cgit v1.2.3 From d81210c25e17b5cca71138f3990ed8071d510ba9 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 2 Mar 2019 17:15:56 +0100 Subject: net: phy: don't export gen10g_read_status gen10g_read_status is deprecated, therefore stop exporting it. We don't want to encourage anybody to use it. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 3 +-- include/linux/phy.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index cdbcea8609df..6cd4bd5e9e43 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -499,7 +499,7 @@ int gen10g_config_aneg(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(gen10g_config_aneg); -int gen10g_read_status(struct phy_device *phydev) +static int gen10g_read_status(struct phy_device *phydev) { /* For now just lie and say it's 10G all the time */ phydev->speed = SPEED_10000; @@ -507,7 +507,6 @@ int gen10g_read_status(struct phy_device *phydev) return genphy_c45_read_link(phydev); } -EXPORT_SYMBOL_GPL(gen10g_read_status); int gen10g_no_soft_reset(struct phy_device *phydev) { diff --git a/include/linux/phy.h b/include/linux/phy.h index 817c8453aeb5..60794240141f 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1119,7 +1119,6 @@ int genphy_c45_read_status(struct phy_device *phydev); /* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev); -int gen10g_read_status(struct phy_device *phydev); int gen10g_no_soft_reset(struct phy_device *phydev); static inline int phy_read_status(struct phy_device *phydev) -- cgit v1.2.3 From 7be3ad848f77eba893bd08b97e7383e8d5e873ac Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 2 Mar 2019 17:13:11 +0100 Subject: net: phy: remove gen10g_no_soft_reset genphy_no_soft_reset and gen10g_no_soft_reset are both the same no-ops, one is enough. Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/cortina.c | 2 +- drivers/net/phy/marvell10g.c | 4 ++-- drivers/net/phy/phy-c45.c | 9 +-------- drivers/net/phy/teranetics.c | 2 +- include/linux/phy.h | 1 - 5 files changed, 5 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c index a64eb211cc56..856cdc36aacd 100644 --- a/drivers/net/phy/cortina.c +++ b/drivers/net/phy/cortina.c @@ -82,7 +82,7 @@ static struct phy_driver cortina_driver[] = { .features = PHY_10GBIT_FEATURES, .config_aneg = gen10g_config_aneg, .read_status = cortina_read_status, - .soft_reset = gen10g_no_soft_reset, + .soft_reset = genphy_no_soft_reset, .probe = cortina_probe, }, }; diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 79106e70010f..100b401b1f4a 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -459,7 +459,7 @@ static struct phy_driver mv3310_drivers[] = { .phy_id_mask = MARVELL_PHY_ID_MASK, .name = "mv88x3310", .get_features = mv3310_get_features, - .soft_reset = gen10g_no_soft_reset, + .soft_reset = genphy_no_soft_reset, .config_init = mv3310_config_init, .probe = mv3310_probe, .suspend = mv3310_suspend, @@ -474,7 +474,7 @@ static struct phy_driver mv3310_drivers[] = { .name = "mv88x2110", .get_features = genphy_c45_pma_read_abilities, .probe = mv3310_probe, - .soft_reset = gen10g_no_soft_reset, + .soft_reset = genphy_no_soft_reset, .config_init = mv3310_config_init, .config_aneg = mv3310_config_aneg, .aneg_done = mv3310_aneg_done, diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index 6cd4bd5e9e43..c596eb54e4ac 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -508,18 +508,11 @@ static int gen10g_read_status(struct phy_device *phydev) return genphy_c45_read_link(phydev); } -int gen10g_no_soft_reset(struct phy_device *phydev) -{ - /* Do nothing for now */ - return 0; -} -EXPORT_SYMBOL_GPL(gen10g_no_soft_reset); - struct phy_driver genphy_10g_driver = { .phy_id = 0xffffffff, .phy_id_mask = 0xffffffff, .name = "Generic 10G PHY", - .soft_reset = gen10g_no_soft_reset, + .soft_reset = genphy_no_soft_reset, .features = PHY_10GBIT_FEATURES, .config_aneg = gen10g_config_aneg, .read_status = gen10g_read_status, diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index 95280212d5d5..beb054b931ee 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -78,7 +78,7 @@ static struct phy_driver teranetics_driver[] = { .phy_id_mask = 0xffffffff, .name = "Teranetics TN2020", .features = PHY_10GBIT_FEATURES, - .soft_reset = gen10g_no_soft_reset, + .soft_reset = genphy_no_soft_reset, .aneg_done = teranetics_aneg_done, .config_aneg = gen10g_config_aneg, .read_status = teranetics_read_status, diff --git a/include/linux/phy.h b/include/linux/phy.h index 60794240141f..34084892a466 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1119,7 +1119,6 @@ int genphy_c45_read_status(struct phy_device *phydev); /* The gen10g_* functions are the old Clause 45 stub */ int gen10g_config_aneg(struct phy_device *phydev); -int gen10g_no_soft_reset(struct phy_device *phydev); static inline int phy_read_status(struct phy_device *phydev) { -- cgit v1.2.3 From 1b1c6c1a3802bf9e7a698d359771e29897c369e5 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 3 Mar 2019 09:12:08 +0000 Subject: mlxsw: core: Move ethtool module callbacks to a common location Move the implementation of ethtool module callbacks - .get_module_info() and .get_module_eeprom() - to a common location to allow reuse by the different mlxsw drivers. Signed-off-by: Vadim Pasternak Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core_env.c | 121 +++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core_env.h | 7 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 118 +++--------------------- 3 files changed, 139 insertions(+), 107 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 160d6cd164f4..7a15e932ed2f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -41,6 +41,47 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, return 0; } +static int +mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, + u16 offset, u16 size, void *data, + unsigned int *p_read_size) +{ + char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE]; + char mcia_pl[MLXSW_REG_MCIA_LEN]; + u16 i2c_addr; + int status; + int err; + + size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE); + + if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH && + offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) + /* Cross pages read, read until offset 256 in low page */ + size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset; + + i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW; + if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) { + i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH; + offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH; + } + + mlxsw_reg_mcia_pack(mcia_pl, module, 0, 0, offset, size, i2c_addr); + + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl); + if (err) + return err; + + status = mlxsw_reg_mcia_status_get(mcia_pl); + if (status) + return -EIO; + + mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp); + memcpy(data, eeprom_tmp, size); + *p_read_size = size; + + return 0; +} + int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, int off, int *temp) { @@ -115,3 +156,83 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, return 0; } + +int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, + struct ethtool_modinfo *modinfo) +{ + u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE]; + u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE; + u8 module_rev_id, module_id; + unsigned int read_size; + int err; + + err = mlxsw_env_query_module_eeprom(mlxsw_core, module, 0, offset, + module_info, &read_size); + if (err) + return err; + + if (read_size < offset) + return -EIO; + + module_rev_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID]; + module_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID]; + + switch (module_id) { + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + break; + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */ + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: + if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 || + module_rev_id >= + MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) { + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + } else { + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + } + break; + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: + modinfo->type = ETH_MODULE_SFF_8472; + modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; + break; + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(mlxsw_env_get_module_info); + +int mlxsw_env_get_module_eeprom(struct net_device *netdev, + struct mlxsw_core *mlxsw_core, int module, + struct ethtool_eeprom *ee, u8 *data) +{ + int offset = ee->offset; + unsigned int read_size; + int i = 0; + int err; + + if (!ee->len) + return -EINVAL; + + memset(data, 0, ee->len); + + while (i < ee->len) { + err = mlxsw_env_query_module_eeprom(mlxsw_core, module, offset, + ee->len - i, data + i, + &read_size); + if (err) { + netdev_err(netdev, "Eeprom query failed\n"); + return err; + } + + i += read_size; + offset += read_size; + } + + return 0; +} +EXPORT_SYMBOL(mlxsw_env_get_module_eeprom); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.h b/drivers/net/ethernet/mellanox/mlxsw/core_env.h index 6dbdf63f3ee1..064d0e770c01 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.h @@ -7,4 +7,11 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module, int off, int *temp); +int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, + struct ethtool_modinfo *modinfo); + +int mlxsw_env_get_module_eeprom(struct net_device *netdev, + struct mlxsw_core *mlxsw_core, int module, + struct ethtool_eeprom *ee, u8 *data); + #endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 6c797e322be8..9eb63300c1d3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -32,6 +32,7 @@ #include "spectrum.h" #include "pci.h" #include "core.h" +#include "core_env.h" #include "reg.h" #include "port.h" #include "trap.h" @@ -3161,99 +3162,18 @@ out: return err; } -#define MLXSW_SP_I2C_ADDR_LOW 0x50 -#define MLXSW_SP_I2C_ADDR_HIGH 0x51 -#define MLXSW_SP_EEPROM_PAGE_LENGTH 256 - -static int mlxsw_sp_query_module_eeprom(struct mlxsw_sp_port *mlxsw_sp_port, - u16 offset, u16 size, void *data, - unsigned int *p_read_size) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE]; - char mcia_pl[MLXSW_REG_MCIA_LEN]; - u16 i2c_addr; - int status; - int err; - - size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE); - - if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH && - offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) - /* Cross pages read, read until offset 256 in low page */ - size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset; - - i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW; - if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) { - i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH; - offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH; - } - - mlxsw_reg_mcia_pack(mcia_pl, mlxsw_sp_port->mapping.module, - 0, 0, offset, size, i2c_addr); - - err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcia), mcia_pl); - if (err) - return err; - - status = mlxsw_reg_mcia_status_get(mcia_pl); - if (status) - return -EIO; - - mlxsw_reg_mcia_eeprom_memcpy_from(mcia_pl, eeprom_tmp); - memcpy(data, eeprom_tmp, size); - *p_read_size = size; - - return 0; -} - static int mlxsw_sp_get_module_info(struct net_device *netdev, struct ethtool_modinfo *modinfo) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev); - u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE]; - u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE; - u8 module_rev_id, module_id; - unsigned int read_size; + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; int err; - err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, 0, offset, - module_info, &read_size); - if (err) - return err; - - if (read_size < offset) - return -EIO; + err = mlxsw_env_get_module_info(mlxsw_sp->core, + mlxsw_sp_port->mapping.module, + modinfo); - module_rev_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID]; - module_id = module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID]; - - switch (module_id) { - case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: - modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; - break; - case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */ - case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: - if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 || - module_rev_id >= - MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) { - modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; - } else { - modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; - } - break; - case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: - modinfo->type = ETH_MODULE_SFF_8472; - modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; - break; - default: - return -EINVAL; - } - - return 0; + return err; } static int mlxsw_sp_get_module_eeprom(struct net_device *netdev, @@ -3261,30 +3181,14 @@ static int mlxsw_sp_get_module_eeprom(struct net_device *netdev, u8 *data) { struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev); - int offset = ee->offset; - unsigned int read_size; - int i = 0; + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; int err; - if (!ee->len) - return -EINVAL; - - memset(data, 0, ee->len); + err = mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core, + mlxsw_sp_port->mapping.module, ee, + data); - while (i < ee->len) { - err = mlxsw_sp_query_module_eeprom(mlxsw_sp_port, offset, - ee->len - i, data + i, - &read_size); - if (err) { - netdev_err(mlxsw_sp_port->dev, "Eeprom query failed\n"); - return err; - } - - i += read_size; - offset += read_size; - } - - return 0; + return err; } static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { -- cgit v1.2.3 From 1ded391df0972fb712fcf9887e4322d600824580 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 3 Mar 2019 09:12:09 +0000 Subject: mlxsw: minimal: Make structures and variables names shorter Replace "mlxsw_minimal" by "mlxsw_m" in order to improve code readability. Signed-off-by: Vadim Pasternak Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index 5a6c4457fb55..907e294d65b6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -10,57 +10,57 @@ #include "core.h" #include "i2c.h" -static const char mlxsw_minimal_driver_name[] = "mlxsw_minimal"; +static const char mlxsw_m_driver_name[] = "mlxsw_minimal"; -static const struct mlxsw_config_profile mlxsw_minimal_config_profile; +static const struct mlxsw_config_profile mlxsw_m_config_profile; -static struct mlxsw_driver mlxsw_minimal_driver = { - .kind = mlxsw_minimal_driver_name, +static struct mlxsw_driver mlxsw_m_driver = { + .kind = mlxsw_m_driver_name, .priv_size = 1, - .profile = &mlxsw_minimal_config_profile, + .profile = &mlxsw_m_config_profile, }; -static const struct i2c_device_id mlxsw_minimal_i2c_id[] = { +static const struct i2c_device_id mlxsw_m_i2c_id[] = { { "mlxsw_minimal", 0}, { }, }; -static struct i2c_driver mlxsw_minimal_i2c_driver = { +static struct i2c_driver mlxsw_m_i2c_driver = { .driver.name = "mlxsw_minimal", .class = I2C_CLASS_HWMON, - .id_table = mlxsw_minimal_i2c_id, + .id_table = mlxsw_m_i2c_id, }; -static int __init mlxsw_minimal_module_init(void) +static int __init mlxsw_m_module_init(void) { int err; - err = mlxsw_core_driver_register(&mlxsw_minimal_driver); + err = mlxsw_core_driver_register(&mlxsw_m_driver); if (err) return err; - err = mlxsw_i2c_driver_register(&mlxsw_minimal_i2c_driver); + err = mlxsw_i2c_driver_register(&mlxsw_m_i2c_driver); if (err) goto err_i2c_driver_register; return 0; err_i2c_driver_register: - mlxsw_core_driver_unregister(&mlxsw_minimal_driver); + mlxsw_core_driver_unregister(&mlxsw_m_driver); return err; } -static void __exit mlxsw_minimal_module_exit(void) +static void __exit mlxsw_m_module_exit(void) { - mlxsw_i2c_driver_unregister(&mlxsw_minimal_i2c_driver); - mlxsw_core_driver_unregister(&mlxsw_minimal_driver); + mlxsw_i2c_driver_unregister(&mlxsw_m_i2c_driver); + mlxsw_core_driver_unregister(&mlxsw_m_driver); } -module_init(mlxsw_minimal_module_init); -module_exit(mlxsw_minimal_module_exit); +module_init(mlxsw_m_module_init); +module_exit(mlxsw_m_module_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Vadim Pasternak "); MODULE_DESCRIPTION("Mellanox minimal driver"); -MODULE_DEVICE_TABLE(i2c, mlxsw_minimal_i2c_id); +MODULE_DEVICE_TABLE(i2c, mlxsw_m_i2c_id); -- cgit v1.2.3 From c100e47caa8efe818f92c55f50933632f0af0e93 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 3 Mar 2019 09:12:10 +0000 Subject: mlxsw: minimal: Add ethtool support The minimal driver is chip independent and uses I2C bus for chip access. Its purpose is to support chassis management on systems equipped with Mellanox switch ASICs. For example from BMC (Board Management Controller) device. Expose a dummy netdev for each front panel port and implement basic ethtool operations to obtain QSFP/SFP module info through ethtool. Signed-off-by: Vadim Pasternak Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 324 +++++++++++++++++++++++++- 1 file changed, 322 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index 907e294d65b6..9108149640b2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 -/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */ +/* Copyright (c) 2016-2019 Mellanox Technologies. All rights reserved */ +#include +#include +#include #include #include #include @@ -8,15 +11,332 @@ #include #include "core.h" +#include "core_env.h" #include "i2c.h" static const char mlxsw_m_driver_name[] = "mlxsw_minimal"; +struct mlxsw_m_port; + +struct mlxsw_m { + struct mlxsw_m_port **ports; + int *module_to_port; + struct mlxsw_core *core; + const struct mlxsw_bus_info *bus_info; + u8 base_mac[ETH_ALEN]; + u8 max_ports; +}; + +struct mlxsw_m_port { + struct net_device *dev; + struct mlxsw_m *mlxsw_m; + u8 local_port; + u8 module; +}; + +static int mlxsw_m_port_dummy_open_stop(struct net_device *dev) +{ + return 0; +} + +static int +mlxsw_m_port_get_phys_port_name(struct net_device *dev, char *name, size_t len) +{ + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + u8 local_port = mlxsw_m_port->local_port; + + return mlxsw_core_port_get_phys_port_name(core, local_port, name, len); +} + +static int mlxsw_m_port_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) +{ + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev); + struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m; + + ppid->id_len = sizeof(mlxsw_m->base_mac); + memcpy(&ppid->id, &mlxsw_m->base_mac, ppid->id_len); + + return 0; +} + +static const struct net_device_ops mlxsw_m_port_netdev_ops = { + .ndo_open = mlxsw_m_port_dummy_open_stop, + .ndo_stop = mlxsw_m_port_dummy_open_stop, + .ndo_get_phys_port_name = mlxsw_m_port_get_phys_port_name, + .ndo_get_port_parent_id = mlxsw_m_port_get_port_parent_id, +}; + +static int mlxsw_m_get_module_info(struct net_device *netdev, + struct ethtool_modinfo *modinfo) +{ + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + + return mlxsw_env_get_module_info(core, mlxsw_m_port->module, modinfo); +} + +static int +mlxsw_m_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee, + u8 *data) +{ + struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); + struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; + + return mlxsw_env_get_module_eeprom(netdev, core, mlxsw_m_port->module, + ee, data); +} + +static const struct ethtool_ops mlxsw_m_port_ethtool_ops = { + .get_module_info = mlxsw_m_get_module_info, + .get_module_eeprom = mlxsw_m_get_module_eeprom, +}; + +static int +mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u8 local_port, + u8 *p_module, u8 *p_width) +{ + char pmlp_pl[MLXSW_REG_PMLP_LEN]; + int err; + + mlxsw_reg_pmlp_pack(pmlp_pl, local_port); + err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(pmlp), pmlp_pl); + if (err) + return err; + *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); + *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); + + return 0; +} + +static int +mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port) +{ + struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m; + struct net_device *dev = mlxsw_m_port->dev; + char ppad_pl[MLXSW_REG_PPAD_LEN]; + int err; + + mlxsw_reg_ppad_pack(ppad_pl, false, 0); + err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(ppad), ppad_pl); + if (err) + return err; + mlxsw_reg_ppad_mac_memcpy_from(ppad_pl, dev->dev_addr); + /* The last byte value in base mac address is guaranteed + * to be such it does not overflow when adding local_port + * value. + */ + dev->dev_addr[ETH_ALEN - 1] += mlxsw_m_port->module + 1; + return 0; +} + +static int +mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u8 local_port, u8 module) +{ + struct mlxsw_m_port *mlxsw_m_port; + struct net_device *dev; + int err; + + err = mlxsw_core_port_init(mlxsw_m->core, local_port); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Port %d: Failed to init core port\n", + local_port); + return err; + } + + dev = alloc_etherdev(sizeof(struct mlxsw_m_port)); + if (!dev) { + err = -ENOMEM; + goto err_alloc_etherdev; + } + + SET_NETDEV_DEV(dev, mlxsw_m->bus_info->dev); + mlxsw_m_port = netdev_priv(dev); + mlxsw_m_port->dev = dev; + mlxsw_m_port->mlxsw_m = mlxsw_m; + mlxsw_m_port->local_port = local_port; + mlxsw_m_port->module = module; + + dev->netdev_ops = &mlxsw_m_port_netdev_ops; + dev->ethtool_ops = &mlxsw_m_port_ethtool_ops; + + err = mlxsw_m_port_dev_addr_get(mlxsw_m_port); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Port %d: Unable to get port mac address\n", + mlxsw_m_port->local_port); + goto err_dev_addr_get; + } + + netif_carrier_off(dev); + mlxsw_m->ports[local_port] = mlxsw_m_port; + err = register_netdev(dev); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Port %d: Failed to register netdev\n", + mlxsw_m_port->local_port); + goto err_register_netdev; + } + + mlxsw_core_port_eth_set(mlxsw_m->core, mlxsw_m_port->local_port, + mlxsw_m_port, dev, module + 1, false, 0); + + return 0; + +err_register_netdev: + mlxsw_m->ports[local_port] = NULL; + free_netdev(dev); +err_dev_addr_get: +err_alloc_etherdev: + mlxsw_core_port_fini(mlxsw_m->core, local_port); + return err; +} + +static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u8 local_port) +{ + struct mlxsw_m_port *mlxsw_m_port = mlxsw_m->ports[local_port]; + + mlxsw_core_port_clear(mlxsw_m->core, local_port, mlxsw_m); + unregister_netdev(mlxsw_m_port->dev); /* This calls ndo_stop */ + mlxsw_m->ports[local_port] = NULL; + free_netdev(mlxsw_m_port->dev); + mlxsw_core_port_fini(mlxsw_m->core, local_port); +} + +static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port, + u8 *last_module) +{ + u8 module, width; + int err; + + /* Fill out to local port mapping array */ + err = mlxsw_m_port_module_info_get(mlxsw_m, local_port, &module, + &width); + if (err) + return err; + + if (!width) + return 0; + /* Skip, if port belongs to the cluster */ + if (module == *last_module) + return 0; + *last_module = module; + mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports; + + return 0; +} + +static void mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 module) +{ + mlxsw_m->module_to_port[module] = -1; +} + +static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) +{ + unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); + u8 last_module = max_ports; + int i; + int err; + + mlxsw_m->ports = kcalloc(max_ports, sizeof(*mlxsw_m->ports), + GFP_KERNEL); + if (!mlxsw_m->ports) + return -ENOMEM; + + mlxsw_m->module_to_port = kmalloc_array(max_ports, sizeof(int), + GFP_KERNEL); + if (!mlxsw_m->module_to_port) { + err = -ENOMEM; + goto err_module_to_port_alloc; + } + + /* Invalidate the entries of module to local port mapping array */ + for (i = 0; i < max_ports; i++) + mlxsw_m->module_to_port[i] = -1; + + /* Fill out module to local port mapping array */ + for (i = 1; i < max_ports; i++) { + err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module); + if (err) + goto err_module_to_port_map; + } + + /* Create port objects for each valid entry */ + for (i = 0; i < mlxsw_m->max_ports; i++) { + if (mlxsw_m->module_to_port[i] > 0) { + err = mlxsw_m_port_create(mlxsw_m, + mlxsw_m->module_to_port[i], + i); + if (err) + goto err_module_to_port_create; + } + } + + return 0; + +err_module_to_port_create: + for (i--; i >= 0; i--) { + if (mlxsw_m->module_to_port[i] > 0) + mlxsw_m_port_remove(mlxsw_m, + mlxsw_m->module_to_port[i]); + } + i = max_ports; +err_module_to_port_map: + for (i--; i > 0; i--) + mlxsw_m_port_module_unmap(mlxsw_m, i); + kfree(mlxsw_m->module_to_port); +err_module_to_port_alloc: + kfree(mlxsw_m->ports); + return err; +} + +static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m) +{ + int i; + + for (i = 0; i < mlxsw_m->max_ports; i++) { + if (mlxsw_m->module_to_port[i] > 0) { + mlxsw_m_port_remove(mlxsw_m, + mlxsw_m->module_to_port[i]); + mlxsw_m_port_module_unmap(mlxsw_m, i); + } + } + + kfree(mlxsw_m->module_to_port); + kfree(mlxsw_m->ports); +} + +static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info) +{ + struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core); + int err; + + mlxsw_m->core = mlxsw_core; + mlxsw_m->bus_info = mlxsw_bus_info; + + err = mlxsw_m_ports_create(mlxsw_m); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n"); + return err; + } + + return 0; +} + +static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core) +{ + struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core); + + mlxsw_m_ports_remove(mlxsw_m); +} + static const struct mlxsw_config_profile mlxsw_m_config_profile; static struct mlxsw_driver mlxsw_m_driver = { .kind = mlxsw_m_driver_name, - .priv_size = 1, + .priv_size = sizeof(struct mlxsw_m), + .init = mlxsw_m_init, + .fini = mlxsw_m_fini, .profile = &mlxsw_m_config_profile, }; -- cgit v1.2.3 From e5ba7803baea3dda36251ed2e2f55b884b0e18fa Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 3 Mar 2019 09:12:11 +0000 Subject: mlxsw: core: Move resource query API to common location Move mlxsw_pci_resources_query() to a common location to allow reuse by the different drivers and over all the supported physical buses. Rename it to mlxsw_core_resources_query(). Signed-off-by: Vadim Pasternak Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 37 +++++++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/pci.c | 38 +----------------------------- 3 files changed, 40 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index b505d3858235..d23d53c0e284 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1917,6 +1917,43 @@ void mlxsw_core_fw_flash_end(struct mlxsw_core *mlxsw_core) } EXPORT_SYMBOL(mlxsw_core_fw_flash_end); +int mlxsw_core_resources_query(struct mlxsw_core *mlxsw_core, char *mbox, + struct mlxsw_res *res) +{ + int index, i; + u64 data; + u16 id; + int err; + + if (!res) + return 0; + + mlxsw_cmd_mbox_zero(mbox); + + for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES; + index++) { + err = mlxsw_cmd_query_resources(mlxsw_core, mbox, index); + if (err) + return err; + + for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) { + id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i); + data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i); + + if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID) + return 0; + + mlxsw_res_parse(res, id, data); + } + } + + /* If after MLXSW_RESOURCES_QUERY_MAX_QUERIES we still didn't get + * MLXSW_RESOURCES_TABLE_END_ID, something went bad in the FW. + */ + return -EIO; +} +EXPORT_SYMBOL(mlxsw_core_resources_query); + static int __init mlxsw_core_module_init(void) { int err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index cd0c6aa0dff9..8ec53f027575 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -182,6 +182,8 @@ int mlxsw_core_port_get_phys_port_name(struct mlxsw_core *mlxsw_core, int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay); bool mlxsw_core_schedule_work(struct work_struct *work); void mlxsw_core_flush_owq(void); +int mlxsw_core_resources_query(struct mlxsw_core *mlxsw_core, char *mbox, + struct mlxsw_res *res); #define MLXSW_CONFIG_PROFILE_SWID_COUNT 8 diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index a2321fe8d6a0..b40455f8293d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1039,42 +1039,6 @@ mlxsw_pci_config_profile_swid_config(struct mlxsw_pci *mlxsw_pci, mlxsw_cmd_mbox_config_profile_swid_config_mask_set(mbox, index, mask); } -static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox, - struct mlxsw_res *res) -{ - int index, i; - u64 data; - u16 id; - int err; - - if (!res) - return 0; - - mlxsw_cmd_mbox_zero(mbox); - - for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES; - index++) { - err = mlxsw_cmd_query_resources(mlxsw_pci->core, mbox, index); - if (err) - return err; - - for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) { - id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i); - data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i); - - if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID) - return 0; - - mlxsw_res_parse(res, id, data); - } - } - - /* If after MLXSW_RESOURCES_QUERY_MAX_QUERIES we still didn't get - * MLXSW_RESOURCES_TABLE_END_ID, something went bad in the FW. - */ - return -EIO; -} - static int mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_pci *mlxsw_pci, const struct mlxsw_config_profile *profile, @@ -1459,7 +1423,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, if (err) goto err_boardinfo; - err = mlxsw_pci_resources_query(mlxsw_pci, mbox, res); + err = mlxsw_core_resources_query(mlxsw_core, mbox, res); if (err) goto err_query_resources; -- cgit v1.2.3 From 27758c801663d17eafcd4e45179e7294a9c290b8 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 3 Mar 2019 09:12:12 +0000 Subject: mlxsw: i2c: Fix comment misspelling Fix comment for mlxsw_i2c_write_cmd(). Signed-off-by: Vadim Pasternak Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index a87ca6b6580d..68a23b212378 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -167,7 +167,7 @@ static int mlxsw_i2c_wait_go_bit(struct i2c_client *client, return err > 0 ? 0 : err; } -/* Routine posts a command to ASIC though mail box. */ +/* Routine posts a command to ASIC through mail box. */ static int mlxsw_i2c_write_cmd(struct i2c_client *client, struct mlxsw_i2c *mlxsw_i2c, int immediate) -- cgit v1.2.3 From f43d9d9b4eb869b1c1513ce8b931389b64b92db1 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 3 Mar 2019 09:12:14 +0000 Subject: mlxsw: i2c: Modify input parameter name in initialization API Change input parameter name "resource" to "res" in mlxsw_i2c_init() in order to align it with mlxsw_pci_init(). Signed-off-by: Vadim Pasternak Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index 68a23b212378..eb46e0c747d2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -414,7 +414,7 @@ static int mlxsw_i2c_skb_transmit(void *bus_priv, struct sk_buff *skb, static int mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core, const struct mlxsw_config_profile *profile, - struct mlxsw_res *resources) + struct mlxsw_res *res) { struct mlxsw_i2c *mlxsw_i2c = bus_priv; -- cgit v1.2.3 From 95b75cbd1bc57ec5898517a3fb2f7621f16b26cd Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 3 Mar 2019 09:12:15 +0000 Subject: mlxsw: i2c: Extend input parameters list of command API Extend input parameters list of command API in mlxsw_i2c_cmd() in order to support initialization commands. Up until now, only access commands were supported by I2C driver. Signed-off-by: Vadim Pasternak Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/i2c.c | 120 +++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index eb46e0c747d2..4708acc778e0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -20,8 +20,10 @@ #define MLXSW_I2C_CIR2_OFF_STATUS (MLXSW_I2C_CIR2_BASE + \ MLXSW_I2C_CIR_STATUS_OFF) #define MLXSW_I2C_OPMOD_SHIFT 12 +#define MLXSW_I2C_EVENT_BIT_SHIFT 22 #define MLXSW_I2C_GO_BIT_SHIFT 23 #define MLXSW_I2C_CIR_CTRL_STATUS_SHIFT 24 +#define MLXSW_I2C_EVENT_BIT BIT(MLXSW_I2C_EVENT_BIT_SHIFT) #define MLXSW_I2C_GO_BIT BIT(MLXSW_I2C_GO_BIT_SHIFT) #define MLXSW_I2C_GO_OPMODE BIT(MLXSW_I2C_OPMOD_SHIFT) #define MLXSW_I2C_SET_IMM_CMD (MLXSW_I2C_GO_OPMODE | \ @@ -33,6 +35,9 @@ #define MLXSW_I2C_TLV_HDR_SIZE 0x10 #define MLXSW_I2C_ADDR_WIDTH 4 #define MLXSW_I2C_PUSH_CMD_SIZE (MLXSW_I2C_ADDR_WIDTH + 4) +#define MLXSW_I2C_SET_EVENT_CMD (MLXSW_I2C_EVENT_BIT) +#define MLXSW_I2C_PUSH_EVENT_CMD (MLXSW_I2C_GO_BIT | \ + MLXSW_I2C_SET_EVENT_CMD) #define MLXSW_I2C_READ_SEMA_SIZE 4 #define MLXSW_I2C_PREP_SIZE (MLXSW_I2C_ADDR_WIDTH + 28) #define MLXSW_I2C_MBOX_SIZE 20 @@ -44,6 +49,7 @@ #define MLXSW_I2C_BLK_MAX 32 #define MLXSW_I2C_RETRY 5 #define MLXSW_I2C_TIMEOUT_MSECS 5000 +#define MLXSW_I2C_MAX_DATA_SIZE 256 /** * struct mlxsw_i2c - device private data: @@ -213,6 +219,66 @@ static int mlxsw_i2c_write_cmd(struct i2c_client *client, return 0; } +/* Routine posts initialization command to ASIC through mail box. */ +static int +mlxsw_i2c_write_init_cmd(struct i2c_client *client, + struct mlxsw_i2c *mlxsw_i2c, u16 opcode, u32 in_mod) +{ + __be32 push_cmd_buf[MLXSW_I2C_PUSH_CMD_SIZE / 4] = { + 0, cpu_to_be32(MLXSW_I2C_PUSH_EVENT_CMD) + }; + __be32 prep_cmd_buf[MLXSW_I2C_PREP_SIZE / 4] = { + 0, 0, 0, 0, 0, 0, + cpu_to_be32(client->adapter->nr & 0xffff), + cpu_to_be32(MLXSW_I2C_SET_EVENT_CMD) + }; + struct i2c_msg push_cmd = + MLXSW_I2C_WRITE_MSG(client, push_cmd_buf, + MLXSW_I2C_PUSH_CMD_SIZE); + struct i2c_msg prep_cmd = + MLXSW_I2C_WRITE_MSG(client, prep_cmd_buf, MLXSW_I2C_PREP_SIZE); + u8 status; + int err; + + push_cmd_buf[1] = cpu_to_be32(MLXSW_I2C_PUSH_EVENT_CMD | opcode); + prep_cmd_buf[3] = cpu_to_be32(in_mod); + prep_cmd_buf[7] = cpu_to_be32(MLXSW_I2C_GO_BIT | opcode); + mlxsw_i2c_set_slave_addr((u8 *)prep_cmd_buf, + MLXSW_I2C_CIR2_BASE); + mlxsw_i2c_set_slave_addr((u8 *)push_cmd_buf, + MLXSW_I2C_CIR2_OFF_STATUS); + + /* Prepare Command Interface Register for transaction */ + err = i2c_transfer(client->adapter, &prep_cmd, 1); + if (err < 0) + return err; + else if (err != 1) + return -EIO; + + /* Write out Command Interface Register GO bit to push transaction */ + err = i2c_transfer(client->adapter, &push_cmd, 1); + if (err < 0) + return err; + else if (err != 1) + return -EIO; + + /* Wait until go bit is cleared. */ + err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, &status); + if (err) { + dev_err(&client->dev, "HW semaphore is not released"); + return err; + } + + /* Validate transaction completion status. */ + if (status) { + dev_err(&client->dev, "Bad transaction completion status %x\n", + status); + return -EIO; + } + + return 0; +} + /* Routine obtains mail box offsets from ASIC register space. */ static int mlxsw_i2c_get_mbox(struct i2c_client *client, struct mlxsw_i2c *mlxsw_i2c) @@ -310,8 +376,8 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num, /* Routine executes I2C command. */ static int -mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox, - size_t out_mbox_size, u8 *out_mbox, u8 *status) +mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size, + u8 *in_mbox, size_t out_mbox_size, u8 *out_mbox, u8 *status) { struct i2c_client *client = to_i2c_client(dev); struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); @@ -326,24 +392,40 @@ mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox, WARN_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32)); - reg_size = mlxsw_i2c_get_reg_size(in_mbox); - num = reg_size / MLXSW_I2C_BLK_MAX; - if (reg_size % MLXSW_I2C_BLK_MAX) - num++; + if (in_mbox) { + reg_size = mlxsw_i2c_get_reg_size(in_mbox); + num = reg_size / MLXSW_I2C_BLK_MAX; + if (reg_size % MLXSW_I2C_BLK_MAX) + num++; - if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { - dev_err(&client->dev, "Could not acquire lock"); - return -EINVAL; - } + if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { + dev_err(&client->dev, "Could not acquire lock"); + return -EINVAL; + } - err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status); - if (err) - goto cmd_fail; + err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status); + if (err) + goto cmd_fail; + + /* No out mailbox is case of write transaction. */ + if (!out_mbox) { + mutex_unlock(&mlxsw_i2c->cmd.lock); + return 0; + } + } else { + /* No input mailbox is case of initialization query command. */ + reg_size = MLXSW_I2C_MAX_DATA_SIZE; + num = reg_size / MLXSW_I2C_BLK_MAX; - /* No out mailbox is case of write transaction. */ - if (!out_mbox) { - mutex_unlock(&mlxsw_i2c->cmd.lock); - return 0; + if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { + dev_err(&client->dev, "Could not acquire lock"); + return -EINVAL; + } + + err = mlxsw_i2c_write_init_cmd(client, mlxsw_i2c, opcode, + in_mod); + if (err) + goto cmd_fail; } /* Send read transaction to get output mailbox content. */ @@ -395,8 +477,8 @@ static int mlxsw_i2c_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod, { struct mlxsw_i2c *mlxsw_i2c = bus_priv; - return mlxsw_i2c_cmd(mlxsw_i2c->dev, in_mbox_size, in_mbox, - out_mbox_size, out_mbox, status); + return mlxsw_i2c_cmd(mlxsw_i2c->dev, opcode, in_mod, in_mbox_size, + in_mbox, out_mbox_size, out_mbox, status); } static bool mlxsw_i2c_skb_transmit_busy(void *bus_priv, -- cgit v1.2.3 From 6a986993e43f176e07c28df560b1cfc3e9b80505 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 3 Mar 2019 09:12:16 +0000 Subject: mlxsw: i2c: Extend initialization by querying resources data Extend initialization flow by query requests for chip resources data in order to obtain chip's specific capabilities, like the number of ports. Signed-off-by: Vadim Pasternak Acked-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/i2c.c | 12 +++++++++++- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 11 ++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index 4708acc778e0..06aea1999518 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -14,6 +14,7 @@ #include "cmd.h" #include "core.h" #include "i2c.h" +#include "resources.h" #define MLXSW_I2C_CIR2_BASE 0x72000 #define MLXSW_I2C_CIR_STATUS_OFF 0x18 @@ -499,10 +500,19 @@ mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core, struct mlxsw_res *res) { struct mlxsw_i2c *mlxsw_i2c = bus_priv; + char *mbox; + int err; mlxsw_i2c->core = mlxsw_core; - return 0; + mbox = mlxsw_cmd_mbox_alloc(); + if (!mbox) + return -ENOMEM; + + err = mlxsw_core_resources_query(mlxsw_core, mbox, res); + + mlxsw_cmd_mbox_free(mbox); + return err; } static void mlxsw_i2c_fini(void *bus_priv) diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index 9108149640b2..68bee9572a1b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -333,11 +333,12 @@ static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core) static const struct mlxsw_config_profile mlxsw_m_config_profile; static struct mlxsw_driver mlxsw_m_driver = { - .kind = mlxsw_m_driver_name, - .priv_size = sizeof(struct mlxsw_m), - .init = mlxsw_m_init, - .fini = mlxsw_m_fini, - .profile = &mlxsw_m_config_profile, + .kind = mlxsw_m_driver_name, + .priv_size = sizeof(struct mlxsw_m), + .init = mlxsw_m_init, + .fini = mlxsw_m_fini, + .profile = &mlxsw_m_config_profile, + .res_query_enabled = true, }; static const struct i2c_device_id mlxsw_m_i2c_id[] = { -- cgit v1.2.3 From 214fa1c43758bcc5f488bbe558c3e7dd325ac077 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 4 Mar 2019 10:57:00 +0200 Subject: mellanox: Switch to bitmap_zalloc() Switch to bitmap_zalloc() to show clearly what we are allocating. Besides that it returns pointer of bitmap type instead of opaque void *. Signed-off-by: Andy Shevchenko Acked-by: Jiri Pirko Reviewed-by: Tariq Toukan Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/alloc.c | 5 ++--- drivers/net/ethernet/mellanox/mlx5/core/alloc.c | 9 +++------ drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c | 5 ++--- drivers/net/ethernet/mellanox/mlx5/core/uar.c | 12 ++++++------ drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c | 7 +++---- 5 files changed, 16 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index dbc483e4a2ef..b330020dc0d6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c @@ -185,8 +185,7 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, bitmap->avail = num - reserved_top - reserved_bot; bitmap->effective_len = bitmap->avail; spin_lock_init(&bitmap->lock); - bitmap->table = kcalloc(BITS_TO_LONGS(bitmap->max), sizeof(long), - GFP_KERNEL); + bitmap->table = bitmap_zalloc(bitmap->max, GFP_KERNEL); if (!bitmap->table) return -ENOMEM; @@ -197,7 +196,7 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap) { - kfree(bitmap->table); + bitmap_free(bitmap->table); } struct mlx4_zone_allocator { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c index 421b9c3c8bf7..9008e17126db 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/alloc.c @@ -186,10 +186,7 @@ static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev, if (!pgdir) return NULL; - pgdir->bitmap = kcalloc(BITS_TO_LONGS(db_per_page), - sizeof(unsigned long), - GFP_KERNEL); - + pgdir->bitmap = bitmap_zalloc(db_per_page, GFP_KERNEL); if (!pgdir->bitmap) { kfree(pgdir); return NULL; @@ -200,7 +197,7 @@ static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev, pgdir->db_page = mlx5_dma_zalloc_coherent_node(dev, PAGE_SIZE, &pgdir->db_dma, node); if (!pgdir->db_page) { - kfree(pgdir->bitmap); + bitmap_free(pgdir->bitmap); kfree(pgdir); return NULL; } @@ -280,7 +277,7 @@ void mlx5_db_free(struct mlx5_core_dev *dev, struct mlx5_db *db) dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, db->u.pgdir->db_page, db->u.pgdir->db_dma); list_del(&db->u.pgdir->list); - kfree(db->u.pgdir->bitmap); + bitmap_free(db->u.pgdir->bitmap); kfree(db->u.pgdir); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c index 98359559c77e..a71d5b9c7ab2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c @@ -108,8 +108,7 @@ int mlx5_mpfs_init(struct mlx5_core_dev *dev) mutex_init(&mpfs->lock); mpfs->size = l2table_size; - mpfs->bitmap = kcalloc(BITS_TO_LONGS(l2table_size), - sizeof(uintptr_t), GFP_KERNEL); + mpfs->bitmap = bitmap_zalloc(l2table_size, GFP_KERNEL); if (!mpfs->bitmap) { kfree(mpfs); return -ENOMEM; @@ -127,7 +126,7 @@ void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev) return; WARN_ON(!hlist_empty(mpfs->hash)); - kfree(mpfs->bitmap); + bitmap_free(mpfs->bitmap); kfree(mpfs); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/uar.c b/drivers/net/ethernet/mellanox/mlx5/core/uar.c index 8b97066dd1f1..94464723ff77 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/uar.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/uar.c @@ -90,8 +90,8 @@ static void up_rel_func(struct kref *kref) iounmap(up->map); if (mlx5_cmd_free_uar(up->mdev, up->index)) mlx5_core_warn(up->mdev, "failed to free uar index %d\n", up->index); - kfree(up->reg_bitmap); - kfree(up->fp_bitmap); + bitmap_free(up->reg_bitmap); + bitmap_free(up->fp_bitmap); kfree(up); } @@ -110,11 +110,11 @@ static struct mlx5_uars_page *alloc_uars_page(struct mlx5_core_dev *mdev, return ERR_PTR(err); up->mdev = mdev; - up->reg_bitmap = kcalloc(BITS_TO_LONGS(bfregs), sizeof(unsigned long), GFP_KERNEL); + up->reg_bitmap = bitmap_zalloc(bfregs, GFP_KERNEL); if (!up->reg_bitmap) goto error1; - up->fp_bitmap = kcalloc(BITS_TO_LONGS(bfregs), sizeof(unsigned long), GFP_KERNEL); + up->fp_bitmap = bitmap_zalloc(bfregs, GFP_KERNEL); if (!up->fp_bitmap) goto error1; @@ -157,8 +157,8 @@ error2: if (mlx5_cmd_free_uar(mdev, up->index)) mlx5_core_warn(mdev, "failed to free uar index %d\n", up->index); error1: - kfree(up->fp_bitmap); - kfree(up->reg_bitmap); + bitmap_free(up->fp_bitmap); + bitmap_free(up->reg_bitmap); kfree(up); return ERR_PTR(err); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c index 9d9aa28684af..46baf3b44309 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c @@ -1188,8 +1188,7 @@ static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp, fid_family->mlxsw_sp = mlxsw_sp; INIT_LIST_HEAD(&fid_family->fids_list); - fid_family->fids_bitmap = kcalloc(BITS_TO_LONGS(nr_fids), - sizeof(unsigned long), GFP_KERNEL); + fid_family->fids_bitmap = bitmap_zalloc(nr_fids, GFP_KERNEL); if (!fid_family->fids_bitmap) { err = -ENOMEM; goto err_alloc_fids_bitmap; @@ -1206,7 +1205,7 @@ static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp, return 0; err_fid_flood_tables_init: - kfree(fid_family->fids_bitmap); + bitmap_free(fid_family->fids_bitmap); err_alloc_fids_bitmap: kfree(fid_family); return err; @@ -1217,7 +1216,7 @@ mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid_family *fid_family) { mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL; - kfree(fid_family->fids_bitmap); + bitmap_free(fid_family->fids_bitmap); WARN_ON_ONCE(!list_empty(&fid_family->fids_list)); kfree(fid_family); } -- cgit v1.2.3 From 80f61f19e542aed04cdc6cf9b748ca92bf394333 Mon Sep 17 00:00:00 2001 From: Arjun Vynipadath Date: Mon, 4 Mar 2019 17:43:02 +0530 Subject: cxgb4/chtls: Prefix adapter flags with CXGB4 Some of these macros were conflicting with global namespace, hence prefixing them with CXGB4. Signed-off-by: Arjun Vynipadath Signed-off-by: Vishal Kulkarni Signed-off-by: David S. Miller --- drivers/crypto/chelsio/chtls/chtls_cm.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 24 ++--- drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 16 ++-- drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c | 4 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 101 +++++++++++---------- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c | 30 +++--- drivers/net/ethernet/chelsio/cxgb4/sge.c | 12 +-- drivers/net/ethernet/chelsio/cxgb4/srq.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 14 +-- 12 files changed, 106 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c index 2e11b0d6a9bb..4e22332496c5 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.c +++ b/drivers/crypto/chelsio/chtls/chtls_cm.c @@ -616,7 +616,7 @@ int chtls_listen_start(struct chtls_dev *cdev, struct sock *sk) pi = netdev_priv(ndev); adap = pi->adapter; - if (!(adap->flags & FULL_INIT_DONE)) + if (!(adap->flags & CXGB4_FULL_INIT_DONE)) return -EBADF; if (listen_hash_find(cdev, sk) >= 0) /* already have it */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c index 127b1f624413..7c5bfc931128 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c @@ -81,7 +81,7 @@ static int is_fw_attached(struct cudbg_init *pdbg_init) { struct adapter *padap = pdbg_init->adap; - if (!(padap->flags & FW_OK) || padap->use_bd) + if (!(padap->flags & CXGB4_FW_OK) || padap->use_bd) return 0; return 1; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index dd6379809c74..956219c178e1 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -606,18 +606,18 @@ struct dentry; struct work_struct; enum { /* adapter flags */ - FULL_INIT_DONE = (1 << 0), - DEV_ENABLED = (1 << 1), - USING_MSI = (1 << 2), - USING_MSIX = (1 << 3), - FW_OK = (1 << 4), - RSS_TNLALLLOOKUP = (1 << 5), - USING_SOFT_PARAMS = (1 << 6), - MASTER_PF = (1 << 7), - FW_OFLD_CONN = (1 << 9), - ROOT_NO_RELAXED_ORDERING = (1 << 10), - SHUTTING_DOWN = (1 << 11), - SGE_DBQ_TIMER = (1 << 12), + CXGB4_FULL_INIT_DONE = (1 << 0), + CXGB4_DEV_ENABLED = (1 << 1), + CXGB4_USING_MSI = (1 << 2), + CXGB4_USING_MSIX = (1 << 3), + CXGB4_FW_OK = (1 << 4), + CXGB4_RSS_TNLALLLOOKUP = (1 << 5), + CXGB4_USING_SOFT_PARAMS = (1 << 6), + CXGB4_MASTER_PF = (1 << 7), + CXGB4_FW_OFLD_CONN = (1 << 9), + CXGB4_ROOT_NO_RELAXED_ORDERING = (1 << 10), + CXGB4_SHUTTING_DOWN = (1 << 11), + CXGB4_SGE_DBQ_TIMER = (1 << 12), }; enum { diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index b0ff9fa183f4..3130b43bba52 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -3143,7 +3143,7 @@ static int tid_info_show(struct seq_file *seq, void *v) seq_printf(seq, ", in use: %u/%u\n", atomic_read(&t->tids_in_use), atomic_read(&t->hash_tids_in_use)); - } else if (adap->flags & FW_OFLD_CONN) { + } else if (adap->flags & CXGB4_FW_OFLD_CONN) { seq_printf(seq, "TID range: %u..%u/%u..%u", t->aftid_base, t->aftid_end, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 65b8dc706c1d..bec4711005cc 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -875,7 +875,7 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) e->rx_pending < MIN_FL_ENTRIES || e->tx_pending < MIN_TXQ_ENTRIES) return -EINVAL; - if (adapter->flags & FULL_INIT_DONE) + if (adapter->flags & CXGB4_FULL_INIT_DONE) return -EBUSY; for (i = 0; i < pi->nqsets; ++i) { @@ -940,7 +940,7 @@ static int get_dbqtimer_tick(struct net_device *dev) struct port_info *pi = netdev_priv(dev); struct adapter *adap = pi->adapter; - if (!(adap->flags & SGE_DBQ_TIMER)) + if (!(adap->flags & CXGB4_SGE_DBQ_TIMER)) return 0; return adap->sge.dbqtimer_tick; @@ -957,7 +957,7 @@ static int get_dbqtimer(struct net_device *dev) txq = &adap->sge.ethtxq[pi->first_qset]; - if (!(adap->flags & SGE_DBQ_TIMER)) + if (!(adap->flags & CXGB4_SGE_DBQ_TIMER)) return 0; /* all of the TX Queues use the same Timer Index */ @@ -979,7 +979,7 @@ static int set_dbqtimer_tick(struct net_device *dev, int usecs) u32 param, val; int ret; - if (!(adap->flags & SGE_DBQ_TIMER)) + if (!(adap->flags & CXGB4_SGE_DBQ_TIMER)) return 0; /* return early if it's the same Timer Tick we're already using */ @@ -1015,7 +1015,7 @@ static int set_dbqtimer(struct net_device *dev, int usecs) u32 param, val; int ret; - if (!(adap->flags & SGE_DBQ_TIMER)) + if (!(adap->flags & CXGB4_SGE_DBQ_TIMER)) return 0; /* Find the SGE Doorbell Timer Value that's closest to the requested @@ -1042,7 +1042,7 @@ static int set_dbqtimer(struct net_device *dev, int usecs) return 0; for (qix = 0; qix < pi->nqsets; qix++, txq++) { - if (adap->flags & FULL_INIT_DONE) { + if (adap->flags & CXGB4_FULL_INIT_DONE) { param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) | FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DMAQ_EQ_TIMERIX) | @@ -1263,7 +1263,7 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef) * firmware image otherwise we'll try to do the entire job from the * host ... and we always "force" the operation in this path. */ - if (adap->flags & FULL_INIT_DONE) + if (adap->flags & CXGB4_FULL_INIT_DONE) mbox = adap->mbox; ret = t4_fw_upgrade(adap, mbox, fw->data, fw->size, 1); @@ -1342,7 +1342,7 @@ static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key, return 0; /* Interface must be brought up atleast once */ - if (pi->adapter->flags & FULL_INIT_DONE) { + if (pi->adapter->flags & CXGB4_FULL_INIT_DONE) { for (i = 0; i < pi->rss_size; i++) pi->rss[i] = p[i]; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c index 6c8a62eefe51..33b2c0c45509 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_fcoe.c @@ -74,7 +74,7 @@ int cxgb_fcoe_enable(struct net_device *netdev) if (is_t4(adap->params.chip)) return -EINVAL; - if (!(adap->flags & FULL_INIT_DONE)) + if (!(adap->flags & CXGB4_FULL_INIT_DONE)) return -EINVAL; dev_info(adap->pdev_dev, "Enabling FCoE offload features\n"); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c index 7dddb9e748b8..5afb43000049 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c @@ -524,7 +524,7 @@ static int del_filter_wr(struct adapter *adapter, int fidx) return -ENOMEM; fwr = __skb_put(skb, len); - t4_mk_filtdelwr(f->tid, fwr, (adapter->flags & SHUTTING_DOWN) ? -1 + t4_mk_filtdelwr(f->tid, fwr, (adapter->flags & CXGB4_SHUTTING_DOWN) ? -1 : adapter->sge.fw_evtq.abs_id); /* Mark the filter as "pending" and ship off the Filter Work Request. @@ -1569,7 +1569,7 @@ int cxgb4_del_filter(struct net_device *dev, int filter_id, int ret; /* If we are shutting down the adapter do not wait for completion */ - if (netdev2adap(dev)->flags & SHUTTING_DOWN) + if (netdev2adap(dev)->flags & CXGB4_SHUTTING_DOWN) return __cxgb4_del_filter(dev, filter_id, fs, NULL); init_completion(&ctx.completion); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 45093a620c3f..89179e316687 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -651,12 +651,12 @@ out: static void disable_msi(struct adapter *adapter) { - if (adapter->flags & USING_MSIX) { + if (adapter->flags & CXGB4_USING_MSIX) { pci_disable_msix(adapter->pdev); - adapter->flags &= ~USING_MSIX; - } else if (adapter->flags & USING_MSI) { + adapter->flags &= ~CXGB4_USING_MSIX; + } else if (adapter->flags & CXGB4_USING_MSI) { pci_disable_msi(adapter->pdev); - adapter->flags &= ~USING_MSI; + adapter->flags &= ~CXGB4_USING_MSI; } } @@ -672,7 +672,7 @@ static irqreturn_t t4_nondata_intr(int irq, void *cookie) adap->swintr = 1; t4_write_reg(adap, MYPF_REG(PL_PF_INT_CAUSE_A), v); } - if (adap->flags & MASTER_PF) + if (adap->flags & CXGB4_MASTER_PF) t4_slow_intr_handler(adap); return IRQ_HANDLED; } @@ -837,9 +837,9 @@ static void quiesce_rx(struct adapter *adap) /* Disable interrupt and napi handler */ static void disable_interrupts(struct adapter *adap) { - if (adap->flags & FULL_INIT_DONE) { + if (adap->flags & CXGB4_FULL_INIT_DONE) { t4_intr_disable(adap); - if (adap->flags & USING_MSIX) { + if (adap->flags & CXGB4_USING_MSIX) { free_msix_queue_irqs(adap); free_irq(adap->msix_info[0].vec, adap); } else { @@ -880,7 +880,7 @@ static int setup_fw_sge_queues(struct adapter *adap) bitmap_zero(s->starving_fl, s->egr_sz); bitmap_zero(s->txq_maperr, s->egr_sz); - if (adap->flags & USING_MSIX) + if (adap->flags & CXGB4_USING_MSIX) adap->msi_idx = 1; /* vector 0 is for non-queue interrupts */ else { err = t4_sge_alloc_rxq(adap, &s->intrq, false, adap->port[0], 0, @@ -939,7 +939,7 @@ static int setup_sge_queues(struct adapter *adap) err = t4_sge_alloc_eth_txq(adap, t, dev, netdev_get_tx_queue(dev, j), q->rspq.cntxt_id, - !!(adap->flags & SGE_DBQ_TIMER)); + !!(adap->flags & CXGB4_SGE_DBQ_TIMER)); if (err) goto freeout; } @@ -2280,7 +2280,7 @@ static int cxgb_up(struct adapter *adap) if (err) goto freeq; - if (adap->flags & USING_MSIX) { + if (adap->flags & CXGB4_USING_MSIX) { name_msix_vecs(adap); err = request_irq(adap->msix_info[0].vec, t4_nondata_intr, 0, adap->msix_info[0].desc, adap); @@ -2293,7 +2293,8 @@ static int cxgb_up(struct adapter *adap) } } else { err = request_irq(adap->pdev->irq, t4_intr_handler(adap), - (adap->flags & USING_MSI) ? 0 : IRQF_SHARED, + (adap->flags & CXGB4_USING_MSI) ? 0 + : IRQF_SHARED, adap->port[0]->name, adap); if (err) goto irq_err; @@ -2302,7 +2303,7 @@ static int cxgb_up(struct adapter *adap) enable_rx(adap); t4_sge_start(adap); t4_intr_enable(adap); - adap->flags |= FULL_INIT_DONE; + adap->flags |= CXGB4_FULL_INIT_DONE; mutex_unlock(&uld_mutex); notify_ulds(adap, CXGB4_STATE_UP); @@ -2331,7 +2332,7 @@ static void cxgb_down(struct adapter *adapter) t4_sge_stop(adapter); t4_free_sge_resources(adapter); - adapter->flags &= ~FULL_INIT_DONE; + adapter->flags &= ~CXGB4_FULL_INIT_DONE; } /* @@ -2345,7 +2346,7 @@ static int cxgb_open(struct net_device *dev) netif_carrier_off(dev); - if (!(adapter->flags & FULL_INIT_DONE)) { + if (!(adapter->flags & CXGB4_FULL_INIT_DONE)) { err = cxgb_up(adapter); if (err < 0) return err; @@ -2950,7 +2951,7 @@ static void cxgb_netpoll(struct net_device *dev) struct port_info *pi = netdev_priv(dev); struct adapter *adap = pi->adapter; - if (adap->flags & USING_MSIX) { + if (adap->flags & CXGB4_USING_MSIX) { int i; struct sge_eth_rxq *rx = &adap->sge.ethrxq[pi->first_qset]; @@ -2977,7 +2978,7 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate) if (index < 0 || index > pi->nqsets - 1) return -EINVAL; - if (!(adap->flags & FULL_INIT_DONE)) { + if (!(adap->flags & CXGB4_FULL_INIT_DONE)) { dev_err(adap->pdev_dev, "Failed to rate limit on queue %d. Link Down?\n", index); @@ -3078,7 +3079,7 @@ static int cxgb_setup_tc_block_cb(enum tc_setup_type type, void *type_data, struct port_info *pi = netdev2pinfo(dev); struct adapter *adap = netdev2adap(dev); - if (!(adap->flags & FULL_INIT_DONE)) { + if (!(adap->flags & CXGB4_FULL_INIT_DONE)) { dev_err(adap->pdev_dev, "Failed to setup tc on port %d. Link Down?\n", pi->port_id); @@ -4210,7 +4211,7 @@ static int adap_init0(struct adapter *adap) return ret; } if (ret == adap->mbox) - adap->flags |= MASTER_PF; + adap->flags |= CXGB4_MASTER_PF; /* * If we're the Master PF Driver and the device is uninitialized, @@ -4225,7 +4226,7 @@ static int adap_init0(struct adapter *adap) /* If firmware is too old (not supported by driver) force an update. */ if (ret) state = DEV_STATE_UNINIT; - if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) { + if ((adap->flags & CXGB4_MASTER_PF) && state != DEV_STATE_INIT) { struct fw_info *fw_info; struct fw_hdr *card_fw; const struct firmware *fw; @@ -4287,7 +4288,7 @@ static int adap_init0(struct adapter *adap) ret); dev_info(adap->pdev_dev, "Coming up as %s: "\ "Adapter already initialized\n", - adap->flags & MASTER_PF ? "MASTER" : "SLAVE"); + adap->flags & CXGB4_MASTER_PF ? "MASTER" : "SLAVE"); } else { dev_info(adap->pdev_dev, "Coming up as MASTER: "\ "Initializing adapter\n"); @@ -4389,7 +4390,7 @@ static int adap_init0(struct adapter *adap) } if (!ret) - adap->flags |= SGE_DBQ_TIMER; + adap->flags |= CXGB4_SGE_DBQ_TIMER; if (is_bypass_device(adap->pdev->device)) adap->params.bypass = 1; @@ -4513,7 +4514,7 @@ static int adap_init0(struct adapter *adap) * offload connection through firmware work request */ if ((val[0] != val[1]) && (ret >= 0)) { - adap->flags |= FW_OFLD_CONN; + adap->flags |= CXGB4_FW_OFLD_CONN; adap->tids.aftid_base = val[0]; adap->tids.aftid_end = val[1]; } @@ -4606,7 +4607,7 @@ static int adap_init0(struct adapter *adap) * 2. Server filter: This are special filters which are used * to redirect SYN packets to offload queue. */ - if (adap->flags & FW_OFLD_CONN && !is_bypass(adap)) { + if (adap->flags & CXGB4_FW_OFLD_CONN && !is_bypass(adap)) { adap->tids.sftid_base = adap->tids.ftid_base + DIV_ROUND_UP(adap->tids.nftids, 3); adap->tids.nsftids = adap->tids.nftids - @@ -4785,7 +4786,7 @@ static int adap_init0(struct adapter *adap) adap->params.b_wnd); } t4_init_sge_params(adap); - adap->flags |= FW_OK; + adap->flags |= CXGB4_FW_OK; t4_init_tp_params(adap, true); return 0; @@ -4820,7 +4821,7 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev, goto out; rtnl_lock(); - adap->flags &= ~FW_OK; + adap->flags &= ~CXGB4_FW_OK; notify_ulds(adap, CXGB4_STATE_START_RECOVERY); spin_lock(&adap->stats_lock); for_each_port(adap, i) { @@ -4832,12 +4833,12 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev, } spin_unlock(&adap->stats_lock); disable_interrupts(adap); - if (adap->flags & FULL_INIT_DONE) + if (adap->flags & CXGB4_FULL_INIT_DONE) cxgb_down(adap); rtnl_unlock(); - if ((adap->flags & DEV_ENABLED)) { + if ((adap->flags & CXGB4_DEV_ENABLED)) { pci_disable_device(pdev); - adap->flags &= ~DEV_ENABLED; + adap->flags &= ~CXGB4_DEV_ENABLED; } out: return state == pci_channel_io_perm_failure ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; @@ -4855,13 +4856,13 @@ static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_RECOVERED; } - if (!(adap->flags & DEV_ENABLED)) { + if (!(adap->flags & CXGB4_DEV_ENABLED)) { if (pci_enable_device(pdev)) { dev_err(&pdev->dev, "Cannot reenable PCI " "device after reset\n"); return PCI_ERS_RESULT_DISCONNECT; } - adap->flags |= DEV_ENABLED; + adap->flags |= CXGB4_DEV_ENABLED; } pci_set_master(pdev); @@ -4872,7 +4873,7 @@ static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_DISCONNECT; if (t4_fw_hello(adap, adap->mbox, adap->pf, MASTER_MUST, NULL) < 0) return PCI_ERS_RESULT_DISCONNECT; - adap->flags |= FW_OK; + adap->flags |= CXGB4_FW_OK; if (adap_init1(adap, &c)) return PCI_ERS_RESULT_DISCONNECT; @@ -4984,7 +4985,7 @@ static int cfg_queues(struct adapter *adap) * at all is problematic ... */ niqflint = adap->params.pfres.niqflint - 1; - if (!(adap->flags & USING_MSIX)) + if (!(adap->flags & CXGB4_USING_MSIX)) niqflint--; neq = adap->params.pfres.neq / 2; avail_eth_qsets = min(niqflint, neq); @@ -5266,8 +5267,8 @@ static void print_adapter_info(struct adapter *adapter) /* Software/Hardware configuration */ dev_info(adapter->pdev_dev, "Configuration: %sNIC %s, %s capable\n", is_offload(adapter) ? "R" : "", - ((adapter->flags & USING_MSIX) ? "MSI-X" : - (adapter->flags & USING_MSI) ? "MSI" : ""), + ((adapter->flags & CXGB4_USING_MSIX) ? "MSI-X" : + (adapter->flags & CXGB4_USING_MSI) ? "MSI" : ""), is_offload(adapter) ? "Offload" : "non-Offload"); } @@ -5342,7 +5343,7 @@ static void free_some_resources(struct adapter *adapter) kfree(adap2pinfo(adapter, i)->rss); free_netdev(adapter->port[i]); } - if (adapter->flags & FW_OK) + if (adapter->flags & CXGB4_FW_OK) t4_fw_bye(adapter, adapter->pf); } @@ -5646,7 +5647,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* PCI device has been enabled */ - adapter->flags |= DEV_ENABLED; + adapter->flags |= CXGB4_DEV_ENABLED; memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map)); /* If possible, we use PCIe Relaxed Ordering Attribute to deliver @@ -5664,7 +5665,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * using Relaxed Ordering. */ if (!pcie_relaxed_ordering_enabled(pdev)) - adapter->flags |= ROOT_NO_RELAXED_ORDERING; + adapter->flags |= CXGB4_ROOT_NO_RELAXED_ORDERING; spin_lock_init(&adapter->stats_lock); spin_lock_init(&adapter->tid_release_lock); @@ -5796,7 +5797,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, adapter); - if (adapter->flags & FW_OK) { + if (adapter->flags & CXGB4_FW_OK) { err = t4_port_init(adapter, func, func, 0); if (err) goto out_free_dev; @@ -5818,7 +5819,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } } - if (!(adapter->flags & FW_OK)) + if (!(adapter->flags & CXGB4_FW_OK)) goto fw_attach_fail; /* Configure queues and allocate tables now, they can be needed as @@ -5912,9 +5913,9 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* See what interrupts we'll be using */ if (msi > 1 && enable_msix(adapter) == 0) - adapter->flags |= USING_MSIX; + adapter->flags |= CXGB4_USING_MSIX; else if (msi > 0 && pci_enable_msi(pdev) == 0) { - adapter->flags |= USING_MSI; + adapter->flags |= CXGB4_USING_MSI; if (msi > 1) free_msix_info(adapter); } @@ -5982,7 +5983,7 @@ fw_attach_fail: cxgb4_ptp_init(adapter); if (IS_REACHABLE(CONFIG_THERMAL) && - !is_t4(adapter->params.chip) && (adapter->flags & FW_OK)) + !is_t4(adapter->params.chip) && (adapter->flags & CXGB4_FW_OK)) cxgb4_thermal_init(adapter); print_adapter_info(adapter); @@ -5991,7 +5992,7 @@ fw_attach_fail: out_free_dev: t4_free_sge_resources(adapter); free_some_resources(adapter); - if (adapter->flags & USING_MSIX) + if (adapter->flags & CXGB4_USING_MSIX) free_msix_info(adapter); if (adapter->num_uld || adapter->num_ofld_uld) t4_uld_mem_free(adapter); @@ -6024,7 +6025,7 @@ static void remove_one(struct pci_dev *pdev) return; } - adapter->flags |= SHUTTING_DOWN; + adapter->flags |= CXGB4_SHUTTING_DOWN; if (adapter->pf == 4) { int i; @@ -6059,10 +6060,10 @@ static void remove_one(struct pci_dev *pdev) */ clear_all_filters(adapter); - if (adapter->flags & FULL_INIT_DONE) + if (adapter->flags & CXGB4_FULL_INIT_DONE) cxgb_down(adapter); - if (adapter->flags & USING_MSIX) + if (adapter->flags & CXGB4_USING_MSIX) free_msix_info(adapter); if (adapter->num_uld || adapter->num_ofld_uld) t4_uld_mem_free(adapter); @@ -6086,9 +6087,9 @@ static void remove_one(struct pci_dev *pdev) #endif iounmap(adapter->regs); pci_disable_pcie_error_reporting(pdev); - if ((adapter->flags & DEV_ENABLED)) { + if ((adapter->flags & CXGB4_DEV_ENABLED)) { pci_disable_device(pdev); - adapter->flags &= ~DEV_ENABLED; + adapter->flags &= ~CXGB4_DEV_ENABLED; } pci_release_regions(pdev); kfree(adapter->mbox_log); @@ -6114,7 +6115,7 @@ static void shutdown_one(struct pci_dev *pdev) return; } - adapter->flags |= SHUTTING_DOWN; + adapter->flags |= CXGB4_SHUTTING_DOWN; if (adapter->pf == 4) { int i; @@ -6132,7 +6133,7 @@ static void shutdown_one(struct pci_dev *pdev) disable_msi(adapter); t4_sge_stop(adapter); - if (adapter->flags & FW_OK) + if (adapter->flags & CXGB4_FW_OK) t4_fw_bye(adapter, adapter->mbox); } } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c index b3654598a2d5..6c685b920713 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c @@ -147,7 +147,7 @@ static int alloc_uld_rxqs(struct adapter *adap, per_chan = rxq_info->nrxq / adap->params.nports; - if (adap->flags & USING_MSIX) + if (adap->flags & CXGB4_USING_MSIX) msi_idx = 1; else msi_idx = -((int)s->intrq.abs_id + 1); @@ -195,7 +195,7 @@ setup_sge_queues_uld(struct adapter *adap, unsigned int uld_type, bool lro) struct sge_uld_rxq_info *rxq_info = adap->sge.uld_rxq_info[uld_type]; int i, ret = 0; - if (adap->flags & USING_MSIX) { + if (adap->flags & CXGB4_USING_MSIX) { rxq_info->msix_tbl = kcalloc((rxq_info->nrxq + rxq_info->nciq), sizeof(unsigned short), GFP_KERNEL); @@ -206,7 +206,7 @@ setup_sge_queues_uld(struct adapter *adap, unsigned int uld_type, bool lro) ret = !(!alloc_uld_rxqs(adap, rxq_info, lro)); /* Tell uP to route control queue completions to rdma rspq */ - if (adap->flags & FULL_INIT_DONE && + if (adap->flags & CXGB4_FULL_INIT_DONE && !ret && uld_type == CXGB4_ULD_RDMA) { struct sge *s = &adap->sge; unsigned int cmplqid; @@ -239,7 +239,7 @@ static void free_sge_queues_uld(struct adapter *adap, unsigned int uld_type) { struct sge_uld_rxq_info *rxq_info = adap->sge.uld_rxq_info[uld_type]; - if (adap->flags & FULL_INIT_DONE && uld_type == CXGB4_ULD_RDMA) { + if (adap->flags & CXGB4_FULL_INIT_DONE && uld_type == CXGB4_ULD_RDMA) { struct sge *s = &adap->sge; u32 param, cmdop, cmplqid = 0; int i; @@ -258,7 +258,7 @@ static void free_sge_queues_uld(struct adapter *adap, unsigned int uld_type) t4_free_uld_rxqs(adap, rxq_info->nciq, rxq_info->uldrxq + rxq_info->nrxq); t4_free_uld_rxqs(adap, rxq_info->nrxq, rxq_info->uldrxq); - if (adap->flags & USING_MSIX) + if (adap->flags & CXGB4_USING_MSIX) kfree(rxq_info->msix_tbl); } @@ -273,7 +273,7 @@ static int cfg_queues_uld(struct adapter *adap, unsigned int uld_type, if (!rxq_info) return -ENOMEM; - if (adap->flags & USING_MSIX && uld_info->nrxq > s->nqs_per_uld) { + if (adap->flags & CXGB4_USING_MSIX && uld_info->nrxq > s->nqs_per_uld) { i = s->nqs_per_uld; rxq_info->nrxq = roundup(i, adap->params.nports); } else { @@ -284,7 +284,7 @@ static int cfg_queues_uld(struct adapter *adap, unsigned int uld_type, if (!uld_info->ciq) { rxq_info->nciq = 0; } else { - if (adap->flags & USING_MSIX) + if (adap->flags & CXGB4_USING_MSIX) rxq_info->nciq = min_t(int, s->nqs_per_uld, num_online_cpus()); else @@ -611,10 +611,10 @@ static void cxgb4_shutdown_uld_adapter(struct adapter *adap, enum cxgb4_uld type adap->uld[type].add = NULL; release_sge_txq_uld(adap, type); - if (adap->flags & FULL_INIT_DONE) + if (adap->flags & CXGB4_FULL_INIT_DONE) quiesce_rx_uld(adap, type); - if (adap->flags & USING_MSIX) + if (adap->flags & CXGB4_USING_MSIX) free_msix_queue_irqs_uld(adap, type); free_sge_queues_uld(adap, type); @@ -673,7 +673,7 @@ static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld) lld->sge_egrstatuspagesize = adap->sge.stat_len; lld->sge_pktshift = adap->sge.pktshift; lld->ulp_crypto = adap->params.crypto; - lld->enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN; + lld->enable_fw_ofld_conn = adap->flags & CXGB4_FW_OFLD_CONN; lld->max_ordird_qp = adap->params.max_ordird_qp; lld->max_ird_adapter = adap->params.max_ird_adapter; lld->ulptx_memwrite_dsgl = adap->params.ulptx_memwrite_dsgl; @@ -702,7 +702,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) adap->uld[uld].handle = handle; t4_register_netevent_notifier(); - if (adap->flags & FULL_INIT_DONE) + if (adap->flags & CXGB4_FULL_INIT_DONE) adap->uld[uld].state_change(handle, CXGB4_STATE_UP); } @@ -737,13 +737,13 @@ void cxgb4_register_uld(enum cxgb4_uld type, ret = setup_sge_queues_uld(adap, type, p->lro); if (ret) goto free_queues; - if (adap->flags & USING_MSIX) { + if (adap->flags & CXGB4_USING_MSIX) { name_msix_vecs_uld(adap, type); ret = request_msix_queue_irqs_uld(adap, type); if (ret) goto free_rxq; } - if (adap->flags & FULL_INIT_DONE) + if (adap->flags & CXGB4_FULL_INIT_DONE) enable_rx_uld(adap, type); if (adap->uld[type].add) goto free_irq; @@ -754,9 +754,9 @@ void cxgb4_register_uld(enum cxgb4_uld type, uld_attach(adap, type); continue; free_irq: - if (adap->flags & FULL_INIT_DONE) + if (adap->flags & CXGB4_FULL_INIT_DONE) quiesce_rx_uld(adap, type); - if (adap->flags & USING_MSIX) + if (adap->flags & CXGB4_USING_MSIX) free_msix_queue_irqs_uld(adap, type); free_rxq: free_sge_queues_uld(adap, type); diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index f18493fb32aa..88773ca58e6b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -3375,7 +3375,7 @@ static irqreturn_t t4_intr_msi(int irq, void *cookie) { struct adapter *adap = cookie; - if (adap->flags & MASTER_PF) + if (adap->flags & CXGB4_MASTER_PF) t4_slow_intr_handler(adap); process_intrq(adap); return IRQ_HANDLED; @@ -3391,7 +3391,7 @@ static irqreturn_t t4_intr_intx(int irq, void *cookie) struct adapter *adap = cookie; t4_write_reg(adap, MYPF_REG(PCIE_PF_CLI_A), 0); - if (((adap->flags & MASTER_PF) && t4_slow_intr_handler(adap)) | + if (((adap->flags & CXGB4_MASTER_PF) && t4_slow_intr_handler(adap)) | process_intrq(adap)) return IRQ_HANDLED; return IRQ_NONE; /* probably shared interrupt */ @@ -3406,9 +3406,9 @@ static irqreturn_t t4_intr_intx(int irq, void *cookie) */ irq_handler_t t4_intr_handler(struct adapter *adap) { - if (adap->flags & USING_MSIX) + if (adap->flags & CXGB4_USING_MSIX) return t4_sge_intr_msix; - if (adap->flags & USING_MSI) + if (adap->flags & CXGB4_USING_MSI) return t4_intr_msi; return t4_intr_intx; } @@ -3441,7 +3441,7 @@ static void sge_rx_timer_cb(struct timer_list *t) * global Master PF activities like checking for chip ingress stalls, * etc. */ - if (!(adap->flags & MASTER_PF)) + if (!(adap->flags & CXGB4_MASTER_PF)) goto done; t4_idma_monitor(adap, &s->idma_monitor, HZ, RX_QCHECK_PERIOD); @@ -3549,7 +3549,7 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, struct fw_iq_cmd c; struct sge *s = &adap->sge; struct port_info *pi = netdev_priv(dev); - int relaxed = !(adap->flags & ROOT_NO_RELAXED_ORDERING); + int relaxed = !(adap->flags & CXGB4_ROOT_NO_RELAXED_ORDERING); /* Size needs to be multiple of 16, including status entry. */ iq->size = roundup(iq->size, 16); diff --git a/drivers/net/ethernet/chelsio/cxgb4/srq.c b/drivers/net/ethernet/chelsio/cxgb4/srq.c index 82b70a565e24..9a54302bb046 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/srq.c +++ b/drivers/net/ethernet/chelsio/cxgb4/srq.c @@ -77,7 +77,7 @@ int cxgb4_get_srq_entry(struct net_device *dev, adap = netdev2adap(dev); s = adap->srq; - if (!(adap->flags & FULL_INIT_DONE) || !s) + if (!(adap->flags & CXGB4_FULL_INIT_DONE) || !s) goto out; skb = alloc_skb(sizeof(*req), GFP_KERNEL); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 49e4374d584c..a3544041ad32 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -198,7 +198,7 @@ static void t4_report_fw_error(struct adapter *adap) if (pcie_fw & PCIE_FW_ERR_F) { dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n", reason[PCIE_FW_EVAL_G(pcie_fw)]); - adap->flags &= ~FW_OK; + adap->flags &= ~CXGB4_FW_OK; } } @@ -5243,7 +5243,7 @@ int t4_read_rss(struct adapter *adapter, u16 *map) static unsigned int t4_use_ldst(struct adapter *adap) { - return (adap->flags & FW_OK) && !adap->use_bd; + return (adap->flags & CXGB4_FW_OK) && !adap->use_bd; } /** @@ -6132,7 +6132,7 @@ unsigned int t4_get_mps_bg_map(struct adapter *adapter, int pidx) * ( MPSBGMAP[Port 1] << 8 ) | * ( MPSBGMAP[Port 0] << 0 )) */ - if (adapter->flags & FW_OK) { + if (adapter->flags & CXGB4_FW_OK) { u32 param, val; int ret; @@ -7093,10 +7093,10 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, if (!t4_fw_matches_chip(adap, fw_hdr)) return -EINVAL; - /* Disable FW_OK flag so that mbox commands with FW_OK flag set - * wont be sent when we are flashing FW. + /* Disable CXGB4_FW_OK flag so that mbox commands with CXGB4_FW_OK flag + * set wont be sent when we are flashing FW. */ - adap->flags &= ~FW_OK; + adap->flags &= ~CXGB4_FW_OK; ret = t4_fw_halt(adap, mbox, force); if (ret < 0 && !force) @@ -7135,7 +7135,7 @@ int t4_fw_upgrade(struct adapter *adap, unsigned int mbox, */ (void)t4_init_devlog_params(adap); out: - adap->flags |= FW_OK; + adap->flags |= CXGB4_FW_OK; return ret; } -- cgit v1.2.3 From 72d8b4fdbfb6192cec1ce25c46020fb48b62fa1e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 1 Mar 2019 20:41:00 +0100 Subject: net: dsa: mv88e6xxx: support in-band signalling on SGMII ports with external PHYs If an external PHY is connected via SGMII and uses in-band signalling then the auto-negotiated values aren't propagated to the port, resulting in a broken link. See discussion in [0]. This patch adds this propagation. We need to call mv88e6xxx_port_setup_mac(), therefore export it from chip.c. Successfully tested on a ZII DTU with 88E6390 switch and an Aquantia AQCS109 PHY connected via SGMII to port 9. [0] https://marc.info/?t=155130287200001&r=1&w=2 Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 6 ++--- drivers/net/dsa/mv88e6xxx/chip.h | 3 +++ drivers/net/dsa/mv88e6xxx/serdes.c | 49 +++++++++++++++++++++++++++++--------- drivers/net/dsa/mv88e6xxx/serdes.h | 8 +++++++ 4 files changed, 52 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index e4ad16b2dc38..cb2b9c3bc08c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -549,9 +549,9 @@ int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update) return mv88e6xxx_write(chip, addr, reg, val); } -static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, - int link, int speed, int duplex, int pause, - phy_interface_t mode) +int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, + int speed, int duplex, int pause, + phy_interface_t mode) { int err; diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 546651d8c3e1..adcf60779895 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -579,6 +579,9 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, u16 update); int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask); +int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, + int speed, int duplex, int pause, + phy_interface_t mode); struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip); #endif /* _MV88E6XXX_CHIP_H */ diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 1bfc5ff8d81d..6a5de1b72f6c 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -510,21 +510,48 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, int port, int lane) { struct dsa_switch *ds = chip->ds; + int duplex = DUPLEX_UNKNOWN; + int speed = SPEED_UNKNOWN; + int link, err; u16 status; - bool up; - mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_STATUS, &status); + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_SGMII_PHY_STATUS, &status); + if (err) { + dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err); + return; + } - /* Status must be read twice in order to give the current link - * status. Otherwise the change in link status since the last - * read of the register is returned. - */ - mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6390_SGMII_STATUS, &status); - up = status & MV88E6390_SGMII_STATUS_LINK; + link = status & MV88E6390_SGMII_PHY_STATUS_LINK ? + LINK_FORCED_UP : LINK_FORCED_DOWN; + + if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { + duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? + DUPLEX_FULL : DUPLEX_HALF; + + switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) { + case MV88E6390_SGMII_PHY_STATUS_SPEED_1000: + speed = SPEED_1000; + break; + case MV88E6390_SGMII_PHY_STATUS_SPEED_100: + speed = SPEED_100; + break; + case MV88E6390_SGMII_PHY_STATUS_SPEED_10: + speed = SPEED_10; + break; + default: + dev_err(chip->dev, "invalid PHY speed\n"); + return; + } + } - dsa_port_phylink_mac_change(ds, port, up); + err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex, + PAUSE_OFF, PHY_INTERFACE_MODE_NA); + if (err) + dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n", + err); + else + dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP); } static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 573dce8b1eb4..c2e7eedfa9b9 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -69,6 +69,14 @@ #define MV88E6390_SGMII_INT_SYMBOL_ERROR BIT(8) #define MV88E6390_SGMII_INT_FALSE_CARRIER BIT(7) #define MV88E6390_SGMII_INT_STATUS 0xa002 +#define MV88E6390_SGMII_PHY_STATUS 0xa003 +#define MV88E6390_SGMII_PHY_STATUS_SPEED_MASK GENMASK(15, 14) +#define MV88E6390_SGMII_PHY_STATUS_SPEED_1000 0x8000 +#define MV88E6390_SGMII_PHY_STATUS_SPEED_100 0x4000 +#define MV88E6390_SGMII_PHY_STATUS_SPEED_10 0x0000 +#define MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL BIT(13) +#define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11) +#define MV88E6390_SGMII_PHY_STATUS_LINK BIT(10) int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); int mv88e6341_serdes_power(struct mv88e6xxx_chip *chip, int port, bool on); -- cgit v1.2.3 From 38d22659803a033b1b66cd2624c33570c0dde77d Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Sat, 2 Mar 2019 15:20:43 -0600 Subject: isdn: mISDN: Fix potential NULL pointer dereference of kzalloc Allocating memory via kzalloc for phi may fail and causes a NULL pointer dereference. This patch avoids such a scenario. Signed-off-by: Aditya Pakki Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcsusb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 124ff530da82..26e3182bbca8 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -263,6 +263,9 @@ hfcsusb_ph_info(struct hfcsusb *hw) int i; phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC); + if (!phi) + return; + phi->dch.ch.protocol = hw->protocol; phi->dch.ch.Flags = dch->Flags; phi->dch.state = dch->state; -- cgit v1.2.3 From 692c31bd4054212312396b1d303bffab2c5b93a7 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 3 Mar 2019 07:35:51 +0000 Subject: team: Free BPF filter when unregistering netdev When team is used in loadbalance mode a BPF filter can be used to provide a hash which will determine the Tx port. When the netdev is later unregistered the filter is not freed which results in memory leaks [1]. Fix by freeing the program and the corresponding filter when unregistering the netdev. [1] unreferenced object 0xffff8881dbc47cc8 (size 16): comm "teamd", pid 3068, jiffies 4294997779 (age 438.247s) hex dump (first 16 bytes): a3 00 6b 6b 6b 6b 6b 6b 88 a5 82 e1 81 88 ff ff ..kkkkkk........ backtrace: [<000000008a3b47e3>] team_nl_cmd_options_set+0x88f/0x11b0 [<00000000c4f4f27e>] genl_family_rcv_msg+0x78f/0x1080 [<00000000610ef838>] genl_rcv_msg+0xca/0x170 [<00000000a281df93>] netlink_rcv_skb+0x132/0x380 [<000000004d9448a2>] genl_rcv+0x29/0x40 [<000000000321b2f4>] netlink_unicast+0x4c0/0x690 [<000000008c25dffb>] netlink_sendmsg+0x929/0xe10 [<00000000068298c5>] sock_sendmsg+0xc8/0x110 [<0000000082a61ff0>] ___sys_sendmsg+0x77a/0x8f0 [<00000000663ae29d>] __sys_sendmsg+0xf7/0x250 [<0000000027c5f11a>] do_syscall_64+0x14d/0x610 [<000000006cfbc8d3>] entry_SYSCALL_64_after_hwframe+0x49/0xbe [<00000000e23197e2>] 0xffffffffffffffff unreferenced object 0xffff8881e182a588 (size 2048): comm "teamd", pid 3068, jiffies 4294997780 (age 438.247s) hex dump (first 32 bytes): 20 00 00 00 02 00 00 00 30 00 00 00 28 f0 ff ff .......0...(... 07 00 00 00 00 00 00 00 28 00 00 00 00 00 00 00 ........(....... backtrace: [<000000002daf01fb>] lb_bpf_func_set+0x45c/0x6d0 [<000000008a3b47e3>] team_nl_cmd_options_set+0x88f/0x11b0 [<00000000c4f4f27e>] genl_family_rcv_msg+0x78f/0x1080 [<00000000610ef838>] genl_rcv_msg+0xca/0x170 [<00000000a281df93>] netlink_rcv_skb+0x132/0x380 [<000000004d9448a2>] genl_rcv+0x29/0x40 [<000000000321b2f4>] netlink_unicast+0x4c0/0x690 [<000000008c25dffb>] netlink_sendmsg+0x929/0xe10 [<00000000068298c5>] sock_sendmsg+0xc8/0x110 [<0000000082a61ff0>] ___sys_sendmsg+0x77a/0x8f0 [<00000000663ae29d>] __sys_sendmsg+0xf7/0x250 [<0000000027c5f11a>] do_syscall_64+0x14d/0x610 [<000000006cfbc8d3>] entry_SYSCALL_64_after_hwframe+0x49/0xbe [<00000000e23197e2>] 0xffffffffffffffff Fixes: 01d7f30a9f96 ("team: add loadbalance mode") Signed-off-by: Ido Schimmel Reported-by: Amit Cohen Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/team/team_mode_loadbalance.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c index a5ef97010eb3..5541e1c19936 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -325,6 +325,20 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx) return 0; } +static void lb_bpf_func_free(struct team *team) +{ + struct lb_priv *lb_priv = get_lb_priv(team); + struct bpf_prog *fp; + + if (!lb_priv->ex->orig_fprog) + return; + + __fprog_destroy(lb_priv->ex->orig_fprog); + fp = rcu_dereference_protected(lb_priv->fp, + lockdep_is_held(&team->lock)); + bpf_prog_destroy(fp); +} + static int lb_tx_method_get(struct team *team, struct team_gsetter_ctx *ctx) { struct lb_priv *lb_priv = get_lb_priv(team); @@ -639,6 +653,7 @@ static void lb_exit(struct team *team) team_options_unregister(team, lb_options, ARRAY_SIZE(lb_options)); + lb_bpf_func_free(team); cancel_delayed_work_sync(&lb_priv->ex->stats.refresh_dw); free_percpu(lb_priv->pcpu_stats); kfree(lb_priv->ex); -- cgit v1.2.3 From 86d7e714993edf36f6739dabdefb06102d26dd2d Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Sun, 3 Mar 2019 10:57:31 +0200 Subject: net/mlx5e: Update tx reporter status in case channels were successfully opened Once channels were successfully opened, update tx reporter health state to healthy. This is needed for the following scenario: - SQ has an un-recovered error reported to the devlink health, resulting tx reporter state to be error. - Current channels (including this SQ) are closed - New channels are opened After that flow, the original error was "solved", and tx reporter state should be healthy. However, as it was resolved as a side effect, and not via tx reporter recover method, driver needs to inform devlink health about it. Signed-off-by: Eran Ben Elisha Acked-by: Jiri Pirko Acked-by: Saeed Mahameed Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index e5f74eb986b3..b5fdbd3190d9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2302,6 +2302,10 @@ int mlx5e_open_channels(struct mlx5e_priv *priv, goto err_close_channels; } + if (!IS_ERR_OR_NULL(priv->tx_reporter)) + devlink_health_reporter_state_update(priv->tx_reporter, + DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); + kvfree(cparam); return 0; -- cgit v1.2.3 From b33b7cd6fd86478dd2890a9abeb6f036aa01fdf7 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Mon, 4 Mar 2019 15:00:03 +0800 Subject: sky2: Disable MSI on Dell Inspiron 1545 and Gateway P-79 Some sky2 chips fire IRQ after S3, before the driver is fully resumed: [ 686.804877] do_IRQ: 1.37 No irq handler for vector This is likely a platform bug that device isn't fully quiesced during S3. Use MSI-X, maskable MSI or INTx can prevent this issue from happening. Since MSI-X and maskable MSI are not supported by this device, fallback to use INTx on affected platforms. BugLink: https://bugs.launchpad.net/bugs/1807259 BugLink: https://bugs.launchpad.net/bugs/1809843 Signed-off-by: Kai-Heng Feng Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 57727fe1501e..8b3495ee2b6e 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -46,6 +46,7 @@ #include #include #include +#include #include @@ -93,7 +94,7 @@ static int copybreak __read_mostly = 128; module_param(copybreak, int, 0); MODULE_PARM_DESC(copybreak, "Receive copy threshold"); -static int disable_msi = 0; +static int disable_msi = -1; module_param(disable_msi, int, 0); MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); @@ -4917,6 +4918,24 @@ static const char *sky2_name(u8 chipid, char *buf, int sz) return buf; } +static const struct dmi_system_id msi_blacklist[] = { + { + .ident = "Dell Inspiron 1545", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1545"), + }, + }, + { + .ident = "Gateway P-79", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Gateway"), + DMI_MATCH(DMI_PRODUCT_NAME, "P-79"), + }, + }, + {} +}; + static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev, *dev1; @@ -5028,6 +5047,9 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_free_pci; } + if (disable_msi == -1) + disable_msi = !!dmi_check_system(msi_blacklist); + if (!disable_msi && pci_enable_msi(pdev) == 0) { err = sky2_test_msi(hw); if (err) { -- cgit v1.2.3 From 3acca1dd17060332cfab15693733cdaf9fba1c90 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 4 Mar 2019 19:39:03 +0100 Subject: net: dsa: mv88e6xxx: add call to mv88e6xxx_ports_cmode_init to probe for new DSA framework In the original patch I missed to add mv88e6xxx_ports_cmode_init() to the second probe function, the one for the new DSA framework. Fixes: ed8fe20205ac ("net: dsa: mv88e6xxx: prevent interrupt storm caused by mv88e6390x_port_set_cmode") Reported-by: Shaokun Zhang Suggested-by: Andrew Lunn Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index cb2b9c3bc08c..47e1c24073b5 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -4904,6 +4904,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) if (err) goto out; + mv88e6xxx_ports_cmode_init(chip); mv88e6xxx_phy_init(chip); if (chip->info->ops->get_eeprom) { -- cgit v1.2.3 From 9731ea06298b2059b168076a9ddbf3e048fd42b5 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 4 Mar 2019 19:50:40 +0100 Subject: net: phy: use phy_modify_mmd_changed in genphy_c45_an_config_aneg As can be seen from the usage of the return value, we should use phy_modify_mmd_changed() here. Fixes: 9a5dc8af4416 ("net: phy: add genphy_c45_an_config_aneg") Signed-off-by: Heiner Kallweit Signed-off-by: David S. Miller --- drivers/net/phy/phy-c45.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c index c596eb54e4ac..9e24d9569424 100644 --- a/drivers/net/phy/phy-c45.c +++ b/drivers/net/phy/phy-c45.c @@ -99,10 +99,10 @@ int genphy_c45_an_config_aneg(struct phy_device *phydev) adv = linkmode_adv_to_mii_adv_t(phydev->advertising); - ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_100BASE4 | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, - adv); + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_100BASE4 | + ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM, + adv); if (ret < 0) return ret; if (ret > 0) @@ -110,11 +110,10 @@ int genphy_c45_an_config_aneg(struct phy_device *phydev) adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising); - ret = phy_modify_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV10G | - MDIO_AN_10GBT_CTRL_ADV5G | - MDIO_AN_10GBT_CTRL_ADV2_5G, - adv); + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + MDIO_AN_10GBT_CTRL_ADV10G | + MDIO_AN_10GBT_CTRL_ADV5G | + MDIO_AN_10GBT_CTRL_ADV2_5G, adv); if (ret < 0) return ret; if (ret > 0) -- cgit v1.2.3 From 64af7dc35f0fc8d3435327c44ef50359bdbe2c67 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 4 Mar 2019 21:35:10 +0100 Subject: phy: mdio-mux: fix Kconfig dependencies MDIO_BUS_MUX can only be selected if OF_MDIO is already turned on: WARNING: unmet direct dependencies detected for MDIO_BUS_MUX Depends on [n]: NETDEVICES [=y] && MDIO_BUS [=m] && OF_MDIO [=n] Selected by [m]: - MDIO_BUS_MUX_MULTIPLEXER [=m] && NETDEVICES [=y] && MDIO_BUS [=m] && OF [=y] Fixes: 7865ad6551c9 ("drivers: net: phy: mdio-mux: Add support for Generic Mux controls") Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 7f66af446ec7..071869db44cf 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -89,7 +89,7 @@ config MDIO_BUS_MUX_MMIOREG config MDIO_BUS_MUX_MULTIPLEXER tristate "MDIO bus multiplexer using kernel multiplexer subsystem" - depends on OF + depends on OF_MDIO select MULTIPLEXER select MDIO_BUS_MUX help -- cgit v1.2.3