From 0db96de6258ca3851c95c7c4349b7188ac524891 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 22 Feb 2013 20:19:55 +0530 Subject: ath6kl: Cosmetic change in checking for free vif slot A minor optimization is done in finding the free slot available for the new virtual interface in the firmware. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 752ffc4f4166..ad79880ebfaf 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -402,7 +402,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type, if (type == NL80211_IFTYPE_STATION || type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) { for (i = 0; i < ar->vif_max; i++) { - if ((ar->avail_idx_map >> i) & BIT(0)) { + if ((ar->avail_idx_map) & BIT(i)) { *if_idx = i; return true; } @@ -412,7 +412,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type, if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO) { for (i = ar->max_norm_iface; i < ar->vif_max; i++) { - if ((ar->avail_idx_map >> i) & BIT(0)) { + if ((ar->avail_idx_map) & BIT(i)) { *if_idx = i; return true; } -- cgit v1.2.1 From bc52aab380c7beb49d20ea6e77e8239b9ffe74a9 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 22 Feb 2013 20:20:09 +0530 Subject: ath6kl: Protect ath6kl_cfg80211_vif_cleanup using rtnl_locks ath6kl_cfg80211_vif_cleanup calls 'unregister_netdevice' which inturn calls 'unregister_netdevice_queue' and it requires holding rtnl_lock semaphore protection. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index ad79880ebfaf..982dbf666a15 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1535,7 +1535,9 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag)); + rtnl_lock(); ath6kl_cfg80211_vif_cleanup(vif); + rtnl_unlock(); return 0; } -- cgit v1.2.1 From bf9781454731c17085bc4708c09ada50f1b63120 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 22 Feb 2013 20:20:21 +0530 Subject: ath6kl: Return error from ath6kl_bmi_done() This addresses a FIXME in the driver. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 6 ++---- drivers/net/wireless/ath/ath6kl/sdio.c | 6 ++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 5d434cf88f35..072a2295eff8 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1569,11 +1569,9 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) goto err_power_off; /* Do we need to finish the BMI phase */ - /* FIXME: return error from ath6kl_bmi_done() */ - if (ath6kl_bmi_done(ar)) { - ret = -EIO; + ret = ath6kl_bmi_done(ar); + if (ret) goto err_power_off; - } /* * The reason we have to wait for the target here is that the diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index d111980d44c0..0bd8ff69461a 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -1123,10 +1123,12 @@ static int ath6kl_sdio_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) ret = ath6kl_sdio_read_write_sync(ar, addr, buf, len, HIF_WR_SYNC_BYTE_INC); - if (ret) + if (ret) { ath6kl_err("unable to send the bmi data to the device\n"); + return ret; + } - return ret; + return 0; } static int ath6kl_sdio_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) -- cgit v1.2.1 From 4ce720b6f0302aae5c47fa4a6493fb86ec730c96 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Fri, 22 Feb 2013 20:20:33 +0530 Subject: ath6kl: Remove NETDEV_REGISTERED flag Currently its no where used. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 1 - drivers/net/wireless/ath/ath6kl/core.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 982dbf666a15..538c6a1cf8cc 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3661,7 +3661,6 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, vif->sme_state = SME_DISCONNECTED; set_bit(WLAN_ENABLED, &vif->flags); ar->wlan_pwr_state = WLAN_POWER_STATE_ON; - set_bit(NETDEV_REGISTERED, &vif->flags); if (type == NL80211_IFTYPE_ADHOC) ar->ibss_if_active = true; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 61b2f98b4e77..1c9ed40358d8 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -560,7 +560,6 @@ enum ath6kl_vif_state { WMM_ENABLED, NETQ_STOPPED, DTIM_EXPIRED, - NETDEV_REGISTERED, CLEAR_BSSFILTER_ON_BEACON, DTIM_PERIOD_AVAIL, WLAN_ENABLED, -- cgit v1.2.1 From 1fdc7fe18e396d02f9c2dfec3de6975dc8314b60 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 28 Feb 2013 07:45:47 +0300 Subject: ath6kl: small cleanup in ath6kl_htc_pipe_rx_complete() It's harmless, but Smatch complains if we use "htc_hdr->eid" before doing the bounds check. Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/htc_pipe.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index 281390178e3d..9adb56741bc3 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c @@ -988,8 +988,6 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, htc_hdr = (struct htc_frame_hdr *) netdata; - ep = &target->endpoint[htc_hdr->eid]; - if (htc_hdr->eid >= ENDPOINT_MAX) { ath6kl_dbg(ATH6KL_DBG_HTC, "HTC Rx: invalid EndpointID=%d\n", @@ -997,6 +995,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb, status = -EINVAL; goto free_skb; } + ep = &target->endpoint[htc_hdr->eid]; payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len)); -- cgit v1.2.1 From e72c27464cce59be432e6322a407a4d94626f8df Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 6 Mar 2013 08:56:06 +0200 Subject: ath6kl: print firmware capabilities Printin the firmware capabilities during the first firmware boot makes it easier to find out what features firmware supports. Obligatory screenshot: [21025.678481] ath6kl: ar6003 hw 2.1.1 sdio fw 3.2.0.144 api 3 [21025.678667] ath6kl: firmware supports: sched-scan,sta-p2pdev-duplex,rsn-cap-override Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 73 ++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 072a2295eff8..3e45adc4a5c2 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1549,10 +1549,81 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type) return NULL; } + +static const struct fw_capa_str_map { + int id; + const char *name; +} fw_capa_map[] = { + { ATH6KL_FW_CAPABILITY_HOST_P2P, "host-p2p" }, + { ATH6KL_FW_CAPABILITY_SCHED_SCAN, "sched-scan" }, + { ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, "sta-p2pdev-duplex" }, + { ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, "inactivity-timeout" }, + { ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, "rsn-cap-override" }, + { ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, "wow-mc-filter" }, + { ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, "bmiss-enhance" }, + { ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, "sscan-match-list" }, + { ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, "rssi-scan-thold" }, + { ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR, "custom-mac-addr" }, + { ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, "tx-err-notify" }, + { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" }, + { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" }, + { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" }, +}; + +static const char *ath6kl_init_get_fw_capa_name(unsigned int id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(fw_capa_map); i++) { + if (fw_capa_map[i].id == id) + return fw_capa_map[i].name; + } + + return ""; +} + +static void ath6kl_init_get_fwcaps(struct ath6kl *ar, char *buf, size_t buf_len) +{ + u8 *data = (u8 *) ar->fw_capabilities; + size_t trunc_len, len = 0; + int i, index, bit; + char *trunc = "..."; + + for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) { + index = i / 8; + bit = i % 8; + + if (index >= sizeof(ar->fw_capabilities) * 4) + break; + + if (buf_len - len < 4) { + ath6kl_warn("firmware capability buffer too small!\n"); + + /* add "..." to the end of string */ + trunc_len = strlen(trunc) + 1; + strncpy(buf + buf_len - trunc_len, trunc, trunc_len); + + return; + } + + if (data[index] & (1 << bit)) { + len += scnprintf(buf + len, buf_len - len, "%s,", + ath6kl_init_get_fw_capa_name(i)); + } + } + + /* overwrite the last comma */ + if (len > 0) + len--; + + buf[len] = '\0'; +} + static int __ath6kl_init_hw_start(struct ath6kl *ar) { long timeleft; int ret, i; + char buf[200]; ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n"); @@ -1615,6 +1686,8 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) ar->wiphy->fw_version, ar->fw_api, test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); + ath6kl_init_get_fwcaps(ar, buf, sizeof(buf)); + ath6kl_info("firmware supports: %s\n", buf); } if (ar->version.abi_ver != ATH6KL_ABI_VERSION) { -- cgit v1.2.1 From ec1461dc30feb422af65ee849137f56e7f87f55e Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sat, 9 Mar 2013 12:01:35 +0200 Subject: ath6kl: cleanup ath6kl_reset_device() Move it to init.c, make it static, remove all useless checks and force it to always do cold reset. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 2 -- drivers/net/wireless/ath/ath6kl/init.c | 12 +++++++++--- drivers/net/wireless/ath/ath6kl/main.c | 33 -------------------------------- drivers/net/wireless/ath/ath6kl/target.h | 2 +- 4 files changed, 10 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 1c9ed40358d8..26b0f92424e1 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -935,8 +935,6 @@ void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, u8 win_sz); void ath6kl_wakeup_event(void *dev); -void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, - bool wait_fot_compltn, bool cold_reset); void ath6kl_init_control_info(struct ath6kl_vif *vif); struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); void ath6kl_cfg80211_vif_stop(struct ath6kl_vif *vif, bool wmi_ready); diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 3e45adc4a5c2..ae1e477ec0d2 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1619,6 +1619,14 @@ static void ath6kl_init_get_fwcaps(struct ath6kl *ar, char *buf, size_t buf_len) buf[len] = '\0'; } +static int ath6kl_init_hw_reset(struct ath6kl *ar) +{ + ath6kl_dbg(ATH6KL_DBG_BOOT, "cold resetting the device"); + + return ath6kl_diag_write32(ar, RESET_CONTROL_ADDRESS, + cpu_to_le32(RESET_CONTROL_COLD_RST)); +} + static int __ath6kl_init_hw_start(struct ath6kl *ar) { long timeleft; @@ -1836,9 +1844,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar) * Try to reset the device if we can. The driver may have been * configure NOT to reset the target during a debug session. */ - ath6kl_dbg(ATH6KL_DBG_TRC, - "attempting to reset target on instance destroy\n"); - ath6kl_reset_device(ar, ar->target_type, true, true); + ath6kl_init_hw_reset(ar); up(&ar->sem); } diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index bd50b6b7b492..bad62b3357b9 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -345,39 +345,6 @@ out: return ret; } -/* FIXME: move to a better place, target.h? */ -#define AR6003_RESET_CONTROL_ADDRESS 0x00004000 -#define AR6004_RESET_CONTROL_ADDRESS 0x00004000 - -void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, - bool wait_fot_compltn, bool cold_reset) -{ - int status = 0; - u32 address; - __le32 data; - - if (target_type != TARGET_TYPE_AR6003 && - target_type != TARGET_TYPE_AR6004) - return; - - data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) : - cpu_to_le32(RESET_CONTROL_MBOX_RST); - - switch (target_type) { - case TARGET_TYPE_AR6003: - address = AR6003_RESET_CONTROL_ADDRESS; - break; - case TARGET_TYPE_AR6004: - address = AR6004_RESET_CONTROL_ADDRESS; - break; - } - - status = ath6kl_diag_write32(ar, address, data); - - if (status) - ath6kl_err("failed to reset target\n"); -} - static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif) { u8 index; diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h index a98c12ba70c1..a580a629a0da 100644 --- a/drivers/net/wireless/ath/ath6kl/target.h +++ b/drivers/net/wireless/ath/ath6kl/target.h @@ -25,7 +25,7 @@ #define AR6004_BOARD_DATA_SZ 6144 #define AR6004_BOARD_EXT_DATA_SZ 0 -#define RESET_CONTROL_ADDRESS 0x00000000 +#define RESET_CONTROL_ADDRESS 0x00004000 #define RESET_CONTROL_COLD_RST 0x00000100 #define RESET_CONTROL_MBOX_RST 0x00000004 -- cgit v1.2.1 From 4e1609c9eec2bf9971004fce8b65c0877d5ae600 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sat, 9 Mar 2013 12:01:43 +0200 Subject: ath6kl: fix usb related error handling and warnings It was annoying to debug usb warm reboot initialisation problems as many usb related functions just ignored errors and it wasn't obvious from the kernel logs what was failing. Fix all that so that error messages are printed and errors are handled properly. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/htc_pipe.c | 10 ++++----- drivers/net/wireless/ath/ath6kl/init.c | 10 +++++---- drivers/net/wireless/ath/ath6kl/usb.c | 34 +++++++++++++++++++----------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index 9adb56741bc3..c02d9d34f74d 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c @@ -1167,7 +1167,7 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target) } if (count <= 0) { - ath6kl_dbg(ATH6KL_DBG_HTC, "%s: Timeout!\n", __func__); + ath6kl_warn("htc pipe control receive timeout!\n"); return -ECOMM; } @@ -1581,16 +1581,16 @@ static int ath6kl_htc_pipe_wait_target(struct htc_target *target) return status; if (target->pipe.ctrl_response_len < sizeof(*ready_msg)) { - ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg len:%d!\n", - target->pipe.ctrl_response_len); + ath6kl_warn("invalid htc pipe ready msg len: %d\n", + target->pipe.ctrl_response_len); return -ECOMM; } ready_msg = (struct htc_ready_ext_msg *) target->pipe.ctrl_response_buf; if (ready_msg->ver2_0_info.msg_id != cpu_to_le16(HTC_MSG_READY_ID)) { - ath6kl_dbg(ATH6KL_DBG_HTC, "invalid htc ready msg : 0x%X !\n", - ready_msg->ver2_0_info.msg_id); + ath6kl_warn("invalid htc pipe ready msg: 0x%x\n", + ready_msg->ver2_0_info.msg_id); return -ECOMM; } diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index ae1e477ec0d2..8b01ec3d2b8c 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1657,13 +1657,15 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) * driver layer has to init BMI in order to set the host block * size. */ - if (ath6kl_htc_wait_target(ar->htc_target)) { - ret = -EIO; + ret = ath6kl_htc_wait_target(ar->htc_target); + if (ret) { + ath6kl_err("htc wait target failed: %d\n", ret); goto err_power_off; } - if (ath6kl_init_service_ep(ar)) { - ret = -EIO; + ret = ath6kl_init_service_ep(ar); + if (ret) { + ath6kl_err("Endpoint service initilisation failed: %d\n", ret); goto err_cleanup_scatter; } diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index 5fcd342762de..63948f6c9f17 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -872,8 +872,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, size, 1000); if (ret < 0) { - ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", - __func__, ret); + ath6kl_warn("Failed to submit usb control message: %d\n", ret); + kfree(buf); + return ret; } kfree(buf); @@ -903,8 +904,9 @@ static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, size, 2 * HZ); if (ret < 0) { - ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", - __func__, ret); + ath6kl_warn("Failed to read usb control message: %d\n", ret); + kfree(buf); + return ret; } memcpy((u8 *) data, buf, size); @@ -961,8 +963,10 @@ static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data) ATH6KL_USB_CONTROL_REQ_DIAG_RESP, ar_usb->diag_resp_buffer, &resp_len); - if (ret) + if (ret) { + ath6kl_warn("diag read32 failed: %d\n", ret); return ret; + } resp = (struct ath6kl_usb_ctrl_diag_resp_read *) ar_usb->diag_resp_buffer; @@ -976,6 +980,7 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) { struct ath6kl_usb *ar_usb = ar->hif_priv; struct ath6kl_usb_ctrl_diag_cmd_write *cmd; + int ret; cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; @@ -984,12 +989,17 @@ static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) cmd->address = cpu_to_le32(address); cmd->value = data; - return ath6kl_usb_ctrl_msg_exchange(ar_usb, - ATH6KL_USB_CONTROL_REQ_DIAG_CMD, - (u8 *) cmd, - sizeof(*cmd), - 0, NULL, NULL); + ret = ath6kl_usb_ctrl_msg_exchange(ar_usb, + ATH6KL_USB_CONTROL_REQ_DIAG_CMD, + (u8 *) cmd, + sizeof(*cmd), + 0, NULL, NULL); + if (ret) { + ath6kl_warn("diag_write32 failed: %d\n", ret); + return ret; + } + return 0; } static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) @@ -1001,7 +1011,7 @@ static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) ret = ath6kl_usb_submit_ctrl_in(ar_usb, ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, 0, 0, buf, len); - if (ret != 0) { + if (ret) { ath6kl_err("Unable to read the bmi data from the device: %d\n", ret); return ret; @@ -1019,7 +1029,7 @@ static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) ret = ath6kl_usb_submit_ctrl_out(ar_usb, ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, 0, 0, buf, len); - if (ret != 0) { + if (ret) { ath6kl_err("unable to send the bmi data to the device: %d\n", ret); return ret; -- cgit v1.2.1 From 44af34428dfdce0472cb229b013c72710285d2db Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sat, 9 Mar 2013 12:01:50 +0200 Subject: ath6kl: cold reset target after host warm boot Julien reported that ar6004 usb device fails to initialise after host has been rebooted and power is still on for the ar6004 device. He found out that doing a cold reset fixes the issue. I wasn't sure what would be the best way to detect if target needs a reset so I settled on checking a timeout from htc_wait_recv_ctrl_message(). Reported-by: Julien Massot Tested-by: Julien Massot Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/htc_pipe.c | 2 +- drivers/net/wireless/ath/ath6kl/init.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index c02d9d34f74d..67aa924ed8b3 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c @@ -1168,7 +1168,7 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target) if (count <= 0) { ath6kl_warn("htc pipe control receive timeout!\n"); - return -ECOMM; + return -ETIMEDOUT; } return 0; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 8b01ec3d2b8c..4ad45bb3cf55 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1658,7 +1658,18 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar) * size. */ ret = ath6kl_htc_wait_target(ar->htc_target); - if (ret) { + + if (ret == -ETIMEDOUT) { + /* + * Most likely USB target is in odd state after reboot and + * needs a reset. A cold reset makes the whole device + * disappear from USB bus and initialisation starts from + * beginning. + */ + ath6kl_warn("htc wait target timed out, resetting device\n"); + ath6kl_init_hw_reset(ar); + goto err_power_off; + } else if (ret) { ath6kl_err("htc wait target failed: %d\n", ret); goto err_power_off; } -- cgit v1.2.1 From 416cf0b49e67254676b4762d1bab88df5130f909 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 18 Mar 2013 13:42:20 +0200 Subject: ath6kl: add tracing support and tracing points for wmi packets Add basic tracing infrastructure support to ath6kl and which can be enabled with CONFIG_ATH6KL_TRACING. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Kconfig | 9 ++++ drivers/net/wireless/ath/ath6kl/Makefile | 5 ++ drivers/net/wireless/ath/ath6kl/trace.c | 18 +++++++ drivers/net/wireless/ath/ath6kl/trace.h | 87 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/txrx.c | 3 ++ drivers/net/wireless/ath/ath6kl/wmi.c | 3 ++ 6 files changed, 125 insertions(+) create mode 100644 drivers/net/wireless/ath/ath6kl/trace.c create mode 100644 drivers/net/wireless/ath/ath6kl/trace.h diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index 26c4b7220859..6971b7a395fe 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig @@ -31,6 +31,15 @@ config ATH6KL_DEBUG ---help--- Enables debug support +config ATH6KL_TRACING + bool "Atheros ath6kl tracing support" + depends on ATH6KL + depends on EVENT_TRACING + ---help--- + Select this to ath6kl use tracing infrastructure. + + If unsure, say Y to make it easier to debug problems. + config ATH6KL_REGDOMAIN bool "Atheros ath6kl regdomain support" depends on ATH6KL diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index cab0ec0d5380..dc2b3b46781e 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -35,10 +35,15 @@ ath6kl_core-y += txrx.o ath6kl_core-y += wmi.o ath6kl_core-y += core.o ath6kl_core-y += recovery.o + ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o +ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o ath6kl_sdio-y += sdio.o obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o ath6kl_usb-y += usb.o + +# for tracing framework to find trace.h +CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/ath/ath6kl/trace.c b/drivers/net/wireless/ath/ath6kl/trace.c new file mode 100644 index 000000000000..4118a29500c1 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/trace.c @@ -0,0 +1,18 @@ +/* + * 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. + */ + +#define CREATE_TRACE_POINTS +#include "trace.h" diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h new file mode 100644 index 000000000000..07876190ce05 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/trace.h @@ -0,0 +1,87 @@ +#if !defined(_ATH6KL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) + +#include +#include +#include +#include "wmi.h" + +#if !defined(_ATH6KL_TRACE_H) +static inline unsigned int ath6kl_get_wmi_id(void *buf, size_t buf_len) +{ + struct wmi_cmd_hdr *hdr = buf; + + if (buf_len < sizeof(*hdr)) + return 0; + + return le16_to_cpu(hdr->cmd_id); +} +#endif /* __ATH6KL_TRACE_H */ + +#define _ATH6KL_TRACE_H + +/* create empty functions when tracing is disabled */ +#if !defined(CONFIG_ATH6KL_TRACING) +#undef TRACE_EVENT +#define TRACE_EVENT(name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#endif /* !CONFIG_ATH6KL_TRACING || __CHECKER__ */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ath6kl + +TRACE_EVENT(ath6kl_wmi_cmd, + TP_PROTO(void *buf, size_t buf_len), + + TP_ARGS(buf, buf_len), + + TP_STRUCT__entry( + __field(unsigned int, id) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->id = ath6kl_get_wmi_id(buf, buf_len); + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "id %d len %d", + __entry->id, __entry->buf_len + ) +); + +TRACE_EVENT(ath6kl_wmi_event, + TP_PROTO(void *buf, size_t buf_len), + + TP_ARGS(buf, buf_len), + + TP_STRUCT__entry( + __field(unsigned int, id) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->id = ath6kl_get_wmi_id(buf, buf_len); + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "id %d len %d", + __entry->id, __entry->buf_len + ) +); + +#endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/ + +/* we don't want to use include/trace/events */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace + +/* This part must be outside protection */ +#include diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 78b369286579..43dbdaadf577 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -20,6 +20,7 @@ #include "core.h" #include "debug.h" #include "htc-ops.h" +#include "trace.h" /* * tid - tid_mux0..tid_mux3 @@ -288,6 +289,8 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb, int status = 0; struct ath6kl_cookie *cookie = NULL; + trace_ath6kl_wmi_cmd(skb->data, skb->len); + if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) { dev_kfree_skb(skb); return -EACCES; diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index d76b5bd81a0d..31a308103f4c 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -20,6 +20,7 @@ #include "core.h" #include "debug.h" #include "testmode.h" +#include "trace.h" #include "../regd.h" #include "../regd_common.h" @@ -4086,6 +4087,8 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) return -EINVAL; } + trace_ath6kl_wmi_event(skb->data, skb->len); + return ath6kl_wmi_proc_events(wmi, skb); } -- cgit v1.2.1 From e60c81543fd4edabe5b6fd2ea68d2db6f6204177 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 18 Mar 2013 13:42:20 +0200 Subject: ath6kl: add tracing points for sdio transfers Add tracing points for sdio transfers, just dump the address, flags and the buffer. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 10 ++++ drivers/net/wireless/ath/ath6kl/trace.c | 5 ++ drivers/net/wireless/ath/ath6kl/trace.h | 90 +++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 0bd8ff69461a..fb141454c6d2 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -28,6 +28,7 @@ #include "target.h" #include "debug.h" #include "cfg80211.h" +#include "trace.h" struct ath6kl_sdio { struct sdio_func *func; @@ -179,6 +180,8 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr, request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len); ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len); + trace_ath6kl_sdio(addr, request, buf, len); + return ret; } @@ -309,6 +312,13 @@ static int ath6kl_sdio_scat_rw(struct ath6kl_sdio *ar_sdio, sdio_claim_host(ar_sdio->func); mmc_set_data_timeout(&data, ar_sdio->func->card); + + trace_ath6kl_sdio_scat(scat_req->addr, + scat_req->req, + scat_req->len, + scat_req->scat_entries, + scat_req->scat_list); + /* synchronous call to process request */ mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req); diff --git a/drivers/net/wireless/ath/ath6kl/trace.c b/drivers/net/wireless/ath/ath6kl/trace.c index 4118a29500c1..e7d64b1285cb 100644 --- a/drivers/net/wireless/ath/ath6kl/trace.c +++ b/drivers/net/wireless/ath/ath6kl/trace.c @@ -14,5 +14,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + #define CREATE_TRACE_POINTS #include "trace.h" + +EXPORT_TRACEPOINT_SYMBOL(ath6kl_sdio); +EXPORT_TRACEPOINT_SYMBOL(ath6kl_sdio_scat); diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h index 07876190ce05..9db616c2ac96 100644 --- a/drivers/net/wireless/ath/ath6kl/trace.h +++ b/drivers/net/wireless/ath/ath6kl/trace.h @@ -4,6 +4,7 @@ #include #include #include "wmi.h" +#include "hif.h" #if !defined(_ATH6KL_TRACE_H) static inline unsigned int ath6kl_get_wmi_id(void *buf, size_t buf_len) @@ -75,6 +76,95 @@ TRACE_EVENT(ath6kl_wmi_event, ) ); +TRACE_EVENT(ath6kl_sdio, + TP_PROTO(unsigned int addr, int flags, + void *buf, size_t buf_len), + + TP_ARGS(addr, flags, buf, buf_len), + + TP_STRUCT__entry( + __field(unsigned int, tx) + __field(unsigned int, addr) + __field(int, flags) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->addr = addr; + __entry->flags = flags; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + + if (flags & HIF_WRITE) + __entry->tx = 1; + else + __entry->tx = 0; + ), + + TP_printk( + "%s addr 0x%x flags 0x%x len %d\n", + __entry->tx ? "tx" : "rx", + __entry->addr, + __entry->flags, + __entry->buf_len + ) +); + +TRACE_EVENT(ath6kl_sdio_scat, + TP_PROTO(unsigned int addr, int flags, unsigned int total_len, + unsigned int entries, struct hif_scatter_item *list), + + TP_ARGS(addr, flags, total_len, entries, list), + + TP_STRUCT__entry( + __field(unsigned int, tx) + __field(unsigned int, addr) + __field(int, flags) + __field(unsigned int, entries) + __field(size_t, total_len) + __dynamic_array(unsigned int, len_array, entries) + __dynamic_array(u8, data, total_len) + ), + + TP_fast_assign( + unsigned int *len_array; + int i, offset = 0; + size_t len; + + __entry->addr = addr; + __entry->flags = flags; + __entry->entries = entries; + __entry->total_len = total_len; + + if (flags & HIF_WRITE) + __entry->tx = 1; + else + __entry->tx = 0; + + len_array = __get_dynamic_array(len_array); + + for (i = 0; i < entries; i++) { + len = list[i].len; + + memcpy((u8 *) __get_dynamic_array(data) + offset, + list[i].buf, len); + + len_array[i] = len; + offset += len; + } + ), + + TP_printk( + "%s addr 0x%x flags 0x%x entries %d total_len %d\n", + __entry->tx ? "tx" : "rx", + __entry->addr, + __entry->flags, + __entry->entries, + __entry->total_len + ) +); + #endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/ /* we don't want to use include/trace/events */ -- cgit v1.2.1 From d57f093aababe358c9c9248fffb554722c15e837 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 18 Mar 2013 13:42:21 +0200 Subject: ath6kl: add tracing point for hif irqs Add a tracing point for hif irq and dump the register content to user space. This is in hif.c as we could use the same code also with SPI but, as ath6kl doesn't SPI and most likely never will be, this is used just by SDIO so name the trace point as ath6kl_sdio_irq to make it easier to manage filters. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/hif.c | 3 +++ drivers/net/wireless/ath/ath6kl/trace.h | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index a6b614421fa4..fea7709b5dda 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c @@ -22,6 +22,7 @@ #include "target.h" #include "hif-ops.h" #include "debug.h" +#include "trace.h" #define MAILBOX_FOR_BLOCK_SIZE 1 @@ -436,6 +437,8 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) ath6kl_dump_registers(dev, &dev->irq_proc_reg, &dev->irq_en_reg); + trace_ath6kl_sdio_irq(&dev->irq_en_reg, + sizeof(dev->irq_en_reg)); /* Update only those registers that are enabled */ host_int_status = dev->irq_proc_reg.host_int_status & diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h index 9db616c2ac96..541729b3d4c3 100644 --- a/drivers/net/wireless/ath/ath6kl/trace.h +++ b/drivers/net/wireless/ath/ath6kl/trace.h @@ -165,6 +165,26 @@ TRACE_EVENT(ath6kl_sdio_scat, ) ); +TRACE_EVENT(ath6kl_sdio_irq, + TP_PROTO(void *buf, size_t buf_len), + + TP_ARGS(buf, buf_len), + + TP_STRUCT__entry( + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "irq len %d\n", __entry->buf_len + ) +); + #endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/ /* we don't want to use include/trace/events */ -- cgit v1.2.1 From 4771979aab5ef964ef12803793fbb7884829944d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 18 Mar 2013 13:42:21 +0200 Subject: ath6kl: adding tracing points for htc_mbox Add tracing points for htc layer, just dumping the packets to user space. I wasn't really sure what to do with the status value, it might not always be accurate, but I included it anyway. I skipped htc_pipe (and usb) implementation for now. Need to add those tracepoints later. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/htc_mbox.c | 21 ++++++++++- drivers/net/wireless/ath/ath6kl/trace.h | 56 ++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index fbb78dfe078f..65e5b719093d 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c @@ -19,6 +19,8 @@ #include "hif.h" #include "debug.h" #include "hif-ops.h" +#include "trace.h" + #include #define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) @@ -537,6 +539,8 @@ static int ath6kl_htc_tx_issue(struct htc_target *target, packet->buf, padded_len, HIF_WR_ASYNC_BLOCK_INC, packet); + trace_ath6kl_htc_tx(status, packet->endpoint, packet->buf, send_len); + return status; } @@ -757,7 +761,8 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, { struct htc_target *target = endpoint->target; struct hif_scatter_req *scat_req = NULL; - int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; + int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0, i; + struct htc_packet *packet; int status; u32 txb_mask; u8 ac = WMM_NUM_AC; @@ -832,6 +837,13 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx scatter bytes %d entries %d\n", scat_req->len, scat_req->scat_entries); + + for (i = 0; i < scat_req->scat_entries; i++) { + packet = scat_req->scat_list[i].packet; + trace_ath6kl_htc_tx(packet->status, packet->endpoint, + packet->buf, packet->act_len); + } + ath6kl_hif_submit_scat_req(target->dev, scat_req, false); if (status) @@ -1903,6 +1915,7 @@ static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint, ath6kl_dbg(ATH6KL_DBG_HTC, "htc rx complete ep %d packet 0x%p\n", endpoint->eid, packet); + endpoint->ep_cb.rx(endpoint->target, packet); } @@ -2011,6 +2024,9 @@ static int ath6kl_htc_rx_process_packets(struct htc_target *target, list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) { ep = &target->endpoint[packet->endpoint]; + trace_ath6kl_htc_rx(packet->status, packet->endpoint, + packet->buf, packet->act_len); + /* process header for each of the recv packet */ status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds, n_lk_ahd); @@ -2291,6 +2307,9 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target) if (ath6kl_htc_rx_packet(target, packet, packet->act_len)) goto fail_ctrl_rx; + trace_ath6kl_htc_rx(packet->status, packet->endpoint, + packet->buf, packet->act_len); + /* process receive header */ packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL); diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h index 541729b3d4c3..306d58d89cc8 100644 --- a/drivers/net/wireless/ath/ath6kl/trace.h +++ b/drivers/net/wireless/ath/ath6kl/trace.h @@ -185,6 +185,62 @@ TRACE_EVENT(ath6kl_sdio_irq, ) ); +TRACE_EVENT(ath6kl_htc_rx, + TP_PROTO(int status, int endpoint, void *buf, + size_t buf_len), + + TP_ARGS(status, endpoint, buf, buf_len), + + TP_STRUCT__entry( + __field(int, status) + __field(int, endpoint) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->status = status; + __entry->endpoint = endpoint; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "status %d endpoint %d len %d\n", + __entry->status, + __entry->endpoint, + __entry->buf_len + ) +); + +TRACE_EVENT(ath6kl_htc_tx, + TP_PROTO(int status, int endpoint, void *buf, + size_t buf_len), + + TP_ARGS(status, endpoint, buf, buf_len), + + TP_STRUCT__entry( + __field(int, status) + __field(int, endpoint) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __entry->status = status; + __entry->endpoint = endpoint; + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "status %d endpoint %d len %d\n", + __entry->status, + __entry->endpoint, + __entry->buf_len + ) +); + #endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/ /* we don't want to use include/trace/events */ -- cgit v1.2.1 From d470b4bcc18a8209972f85a257631e96c3cad3a4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 18 Mar 2013 13:42:21 +0200 Subject: ath6kl: convert ath6kl_info/err/warn macros to real functions After this it's cleaner to add trace calls. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 51 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/debug.h | 10 ++----- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 15cfe30e54fd..2e248fac8523 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -56,6 +56,57 @@ int ath6kl_printk(const char *level, const char *fmt, ...) } EXPORT_SYMBOL(ath6kl_printk); +int ath6kl_info(const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + int ret; + + va_start(args, fmt); + vaf.va = &args; + ret = ath6kl_printk(KERN_INFO, "%pV", &vaf); + va_end(args); + + return ret; +} +EXPORT_SYMBOL(ath6kl_info); + +int ath6kl_err(const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + int ret; + + va_start(args, fmt); + vaf.va = &args; + ret = ath6kl_printk(KERN_ERR, "%pV", &vaf); + va_end(args); + + return ret; +} +EXPORT_SYMBOL(ath6kl_err); + +int ath6kl_warn(const char *fmt, ...) +{ + struct va_format vaf = { + .fmt = fmt, + }; + va_list args; + int ret; + + va_start(args, fmt); + vaf.va = &args; + ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf); + va_end(args); + + return ret; +} +EXPORT_SYMBOL(ath6kl_warn); + #ifdef CONFIG_ATH6KL_DEBUG void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index f97cd4ead543..c6ca781900da 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -51,13 +51,9 @@ enum ATH6K_DEBUG_MASK { extern unsigned int debug_mask; extern __printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...); - -#define ath6kl_info(fmt, ...) \ - ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) -#define ath6kl_err(fmt, ...) \ - ath6kl_printk(KERN_ERR, fmt, ##__VA_ARGS__) -#define ath6kl_warn(fmt, ...) \ - ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) +extern __printf(1, 2) int ath6kl_info(const char *fmt, ...); +extern __printf(1, 2) int ath6kl_err(const char *fmt, ...); +extern __printf(1, 2) int ath6kl_warn(const char *fmt, ...); enum ath6kl_war { ATH6KL_WAR_INVALID_RATE, -- cgit v1.2.1 From da01d53cfb8a7e23121572004336723d64d3ace6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 18 Mar 2013 13:42:22 +0200 Subject: ath6kl: add tracing support to log functions All log messages are now sent through tracing interface as well if ATH6KL_TRACING is enabled. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 3 +++ drivers/net/wireless/ath/ath6kl/debug.h | 1 + drivers/net/wireless/ath/ath6kl/trace.h | 37 +++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 2e248fac8523..80f23e398acd 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -67,6 +67,7 @@ int ath6kl_info(const char *fmt, ...) va_start(args, fmt); vaf.va = &args; ret = ath6kl_printk(KERN_INFO, "%pV", &vaf); + trace_ath6kl_log_info(&vaf); va_end(args); return ret; @@ -84,6 +85,7 @@ int ath6kl_err(const char *fmt, ...) va_start(args, fmt); vaf.va = &args; ret = ath6kl_printk(KERN_ERR, "%pV", &vaf); + trace_ath6kl_log_err(&vaf); va_end(args); return ret; @@ -101,6 +103,7 @@ int ath6kl_warn(const char *fmt, ...) va_start(args, fmt); vaf.va = &args; ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf); + trace_ath6kl_log_warn(&vaf); va_end(args); return ret; diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index c6ca781900da..74369de00fb5 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -19,6 +19,7 @@ #define DEBUG_H #include "hif.h" +#include "trace.h" enum ATH6K_DEBUG_MASK { ATH6KL_DBG_CREDIT = BIT(0), diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h index 306d58d89cc8..ea55b2abbdb3 100644 --- a/drivers/net/wireless/ath/ath6kl/trace.h +++ b/drivers/net/wireless/ath/ath6kl/trace.h @@ -25,6 +25,11 @@ static inline unsigned int ath6kl_get_wmi_id(void *buf, size_t buf_len) #undef TRACE_EVENT #define TRACE_EVENT(name, proto, ...) \ static inline void trace_ ## name(proto) {} +#undef DECLARE_EVENT_CLASS +#define DECLARE_EVENT_CLASS(...) +#undef DEFINE_EVENT +#define DEFINE_EVENT(evt_class, name, proto, ...) \ +static inline void trace_ ## name(proto) {} #endif /* !CONFIG_ATH6KL_TRACING || __CHECKER__ */ #undef TRACE_SYSTEM @@ -241,6 +246,38 @@ TRACE_EVENT(ath6kl_htc_tx, ) ); +#define ATH6KL_MSG_MAX 200 + +DECLARE_EVENT_CLASS(ath6kl_log_event, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf), + TP_STRUCT__entry( + __dynamic_array(char, msg, ATH6KL_MSG_MAX) + ), + TP_fast_assign( + WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), + ATH6KL_MSG_MAX, + vaf->fmt, + *vaf->va) >= ATH6KL_MSG_MAX); + ), + TP_printk("%s", __get_str(msg)) +); + +DEFINE_EVENT(ath6kl_log_event, ath6kl_log_err, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + +DEFINE_EVENT(ath6kl_log_event, ath6kl_log_warn, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + +DEFINE_EVENT(ath6kl_log_event, ath6kl_log_info, + TP_PROTO(struct va_format *vaf), + TP_ARGS(vaf) +); + #endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/ /* we don't want to use include/trace/events */ -- cgit v1.2.1 From aa8705fc65a395d79bdc8bb82a89bcf9abe9f3a4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 18 Mar 2013 13:42:22 +0200 Subject: ath6kl: add tracing support to debug message macros Now all log messages are sent through the tracing infrastruture as well. Tracing point doesn't follow debug_mask module parameter, instead it sends all debug messages, so once you enable ath6kl_log_dbg tracing point you will get a lot of messages. Needs to be discussed if this is sensible or not. The overhead should be small enough and we anyway include debug level as well so it's easy to filter in user space. I wasn't really sure what to do with ath6kl_dbg_dump() and for now decided that it also sends the buffer to user space. But most likely in the future ath6kl_dbg_dump() should go away in favor of using proper tracing points, but we will see. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 12 ++++++---- drivers/net/wireless/ath/ath6kl/trace.h | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 80f23e398acd..42a887d06ba2 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -117,15 +117,15 @@ void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) struct va_format vaf; va_list args; - if (!(debug_mask & mask)) - return; - va_start(args, fmt); vaf.fmt = fmt; vaf.va = &args; - ath6kl_printk(KERN_DEBUG, "%pV", &vaf); + if (debug_mask & mask) + ath6kl_printk(KERN_DEBUG, "%pV", &vaf); + + trace_ath6kl_log_dbg(mask, &vaf); va_end(args); } @@ -141,6 +141,10 @@ void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); } + + /* tracing code doesn't like null strings :/ */ + trace_ath6kl_log_dbg_dump(msg ? msg : "", prefix ? prefix : "", + buf, len); } EXPORT_SYMBOL(ath6kl_dbg_dump); diff --git a/drivers/net/wireless/ath/ath6kl/trace.h b/drivers/net/wireless/ath/ath6kl/trace.h index ea55b2abbdb3..6af6fa038312 100644 --- a/drivers/net/wireless/ath/ath6kl/trace.h +++ b/drivers/net/wireless/ath/ath6kl/trace.h @@ -278,6 +278,48 @@ DEFINE_EVENT(ath6kl_log_event, ath6kl_log_info, TP_ARGS(vaf) ); +TRACE_EVENT(ath6kl_log_dbg, + TP_PROTO(unsigned int level, struct va_format *vaf), + TP_ARGS(level, vaf), + TP_STRUCT__entry( + __field(unsigned int, level) + __dynamic_array(char, msg, ATH6KL_MSG_MAX) + ), + TP_fast_assign( + __entry->level = level; + WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), + ATH6KL_MSG_MAX, + vaf->fmt, + *vaf->va) >= ATH6KL_MSG_MAX); + ), + TP_printk("%s", __get_str(msg)) +); + +TRACE_EVENT(ath6kl_log_dbg_dump, + TP_PROTO(const char *msg, const char *prefix, + const void *buf, size_t buf_len), + + TP_ARGS(msg, prefix, buf, buf_len), + + TP_STRUCT__entry( + __string(msg, msg) + __string(prefix, prefix) + __field(size_t, buf_len) + __dynamic_array(u8, buf, buf_len) + ), + + TP_fast_assign( + __assign_str(msg, msg); + __assign_str(prefix, prefix); + __entry->buf_len = buf_len; + memcpy(__get_dynamic_array(buf), buf, buf_len); + ), + + TP_printk( + "%s/%s\n", __get_str(prefix), __get_str(msg) + ) +); + #endif /* _ ATH6KL_TRACE_H || TRACE_HEADER_MULTI_READ*/ /* we don't want to use include/trace/events */ -- cgit v1.2.1 From 99089ab756a26c8f1be5942178bf9b3fa9ae54d6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 10 Mar 2013 07:51:29 +0200 Subject: ath6kl: add an extra band check to ath6kl_wmi_beginscan_cmd() Dan reported that smatch found a possible issue in ath6kl_wmi_beginscan_cmd() where we might access sc->supp_rates beyond the end. It shouldn't happen as ar->wiphy->bands always have just the first two bands set, but add an extra check just to be sure. Reported-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/wmi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 31a308103f4c..87aefb4c4c23 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2029,6 +2029,9 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, if (!sband) continue; + if (WARN_ON(band >= ATH6KL_NUM_BANDS)) + break; + ratemask = rates[band]; supp_rates = sc->supp_rates[band].rates; num_rates = 0; -- cgit v1.2.1 From 15ac0778a65322c8c39eb2a6636218554d348690 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 10 Mar 2013 07:51:39 +0200 Subject: ath6kl: remove false check from ath6kl_rx() Dan found a check from ath6kl_rx() which doesn't make any sense at all: " 1327 if (status || !(skb->data + HTC_HDR_LENGTH)) { ^^^^^^^^^^^^^^^^^^^^^^^^^^ skb->data is a pointer. This pointer math is always going to be false. Should it be testing "packet->act_len < HTC_HDR_LENGTH" or something?" I don't know what the check really was supposed to do, but I think Dan's guess is right. Fix it accordingly. Reported-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 43dbdaadf577..ebb24045a8ae 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -1327,7 +1327,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) __func__, ar, ept, skb, packet->buf, packet->act_len, status); - if (status || !(skb->data + HTC_HDR_LENGTH)) { + if (status || packet->act_len < HTC_HDR_LENGTH) { dev_kfree_skb(skb); return; } -- cgit v1.2.1 From 6a3e4e06a1a2238d5a2668d4a5bad58fc92c7a77 Mon Sep 17 00:00:00 2001 From: Myoungje Kim Date: Sun, 10 Mar 2013 08:16:05 +0200 Subject: ath6kl: Fix the byte alignment rule to avoid loss of bytes in a TCP segment Either first 3 bytes of the first received tcp segment or last one over MTU size file can be loss due to the byte alignment problem. Although ATH6KL_HTC_ALIGN_BYTES was defined for 'extra bytes for htc header alignment' in the patch "Fix buffer alignment for scatter-gather I/O"(1df94a857), there exists the bytes loss issue which means that it will be truncated 3 bytes in the transmitted file contents if a file which has over MTU size is transferred through TCP/IP stack. It doesn't look like TCP/IP stack bug of 3.5 or the latest version of kernel but the byte alignment issue. This patch is to use the roundup() function for the byte alignment rather than the predefined ATH6KL_HTC_ALIGN_BYTES. kvalo: fixed indentation Signed-off-by: Myoungje Kim Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 4 ++-- drivers/net/wireless/ath/ath6kl/main.c | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 4ad45bb3cf55..40ffee6184fd 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -201,8 +201,8 @@ struct sk_buff *ath6kl_buf_alloc(int size) u16 reserved; /* Add chacheline space at front and back of buffer */ - reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + - sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES; + reserved = roundup((2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET + + sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES, 4); skb = dev_alloc_skb(size + reserved); if (skb) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index bad62b3357b9..d4fcfcad57d0 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1294,9 +1294,11 @@ void init_netdev(struct net_device *dev) dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; dev->needed_headroom = ETH_HLEN; - dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) + - sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH - + WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES; + dev->needed_headroom += roundup(sizeof(struct ath6kl_llc_snap_hdr) + + sizeof(struct wmi_data_hdr) + + HTC_HDR_LENGTH + + WMI_MAX_TX_META_SZ + + ATH6KL_HTC_ALIGN_BYTES, 4); dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; -- cgit v1.2.1 From a41d9a91e35f0ca7a55ecf3b6de5901e24d9e7ae Mon Sep 17 00:00:00 2001 From: Andrei Epure Date: Sun, 10 Mar 2013 14:39:58 +0200 Subject: ath: changed kmalloc to kmemdup Signed-off-by: Andrei Epure Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/usb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index 63948f6c9f17..bed0d337712d 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -856,11 +856,9 @@ static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, int ret; if (size > 0) { - buf = kmalloc(size, GFP_KERNEL); + buf = kmemdup(data, size, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - - memcpy(buf, data, size); } /* note: if successful returns number of bytes transfered */ -- cgit v1.2.1 From 243c028099c467186d126859848bdac3bbfe8da0 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Tue, 12 Mar 2013 22:03:03 +0530 Subject: ath6kl: Fix a debugfs crash for USB devices Credit distribution stats is currently implemented only for SDIO. This fixes a crash in debugfs for USB interface. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] read_file_credit_dist_stats+0x38/0x330 [ath6kl_core] *pde = b62bd067 Oops: 0000 [#1] SMP EIP: 0060:[] EFLAGS: 00210246 CPU: 0 EIP is at read_file_credit_dist_stats+0x38/0x330 [ath6kl_core] EAX: 00000000 EBX: e6f7a9c0 ECX: e7b148b8 EDX: 00000000 ESI: 000000c8 EDI: e7b14000 EBP: e6e09f64 ESP: e6e09f30 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Process cat (pid: 4058, ti=e6e08000 task=e50cf230 task.ti=e6e08000) Stack: 00008000 00000000 e6e09f64 c1132d3c 00004e71 e50cf230 00008000 089e4000 e7b148b8 00000000 e6f7a9c0 00008000 089e4000 e6e09f8c c11331fc e6e09f98 00000001 e6e09f7c f91c2010 e6e09fac e6f7a9c0 089e4877 089e4000 e6e09fac Call Trace: [] ? rw_verify_area+0x6c/0x120 [] vfs_read+0x8c/0x160 [] ? read_file_war_stats+0x130/0x130 [ath6kl_core] [] sys_read+0x3d/0x70 [] syscall_call+0x7/0xb [] ? fill_powernow_table_pstate+0x127/0x127 Cc: Ryan Hsu Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 42a887d06ba2..fe38b836cb26 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -1810,8 +1810,10 @@ int ath6kl_debug_init_fs(struct ath6kl *ar) debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, &fops_tgt_stats); - debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, - &fops_credit_dist_stats); + if (ar->hif_type == ATH6KL_HIF_TYPE_SDIO) + debugfs_create_file("credit_dist_stats", S_IRUSR, + ar->debugfs_phy, ar, + &fops_credit_dist_stats); debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar, &fops_endpoint_stats); -- cgit v1.2.1