From patchwork Wed Dec 21 12:19:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Valo X-Patchwork-Id: 9482989 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C9C9F60237 for ; Wed, 21 Dec 2016 12:20:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B790527F8F for ; Wed, 21 Dec 2016 12:20:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AC261283FC; Wed, 21 Dec 2016 12:20:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2F2D627F8F for ; Wed, 21 Dec 2016 12:20:12 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1cJfsE-0008Vk-UO; Wed, 21 Dec 2016 12:19:58 +0000 Received: from wolverine01.qualcomm.com ([199.106.114.254]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1cJfsB-0008OJ-K7 for ath10k@lists.infradead.org; Wed, 21 Dec 2016 12:19:57 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=qca.qualcomm.com; i=@qca.qualcomm.com; q=dns/txt; s=qcdkim; t=1482322795; x=1513858795; h=subject:from:to:cc:date:message-id:mime-version: content-transfer-encoding; bh=Jncs4b8mw0x03LyL4CHOYP18PFWtAZn8XsBPjOHbNd8=; b=O1rvasnhnJs64hUUfGkpY4QBmMlz3Ixs6O/qhn3MwW22f394fuhrcxTf OvdpnA//RfotZeupIn9ABvW2VRATFQ4le9m5HYObkS07+QKdvdM56XPf9 lrWCltr62PetPOp0Z6aOH1QZ4OOGLNvNnzuttmhV5FZ3AlK2aS0RHXn4E M=; X-IronPort-AV: E=Sophos;i="5.33,383,1477983600"; d="scan'208";a="250134120" Received: from unknown (HELO ironmsg02-R.qualcomm.com) ([10.53.140.106]) by wolverine01.qualcomm.com with ESMTP; 21 Dec 2016 04:19:33 -0800 X-IronPort-AV: E=McAfee;i="5700,7163,8385"; a="868857958" X-Amp-Result: CLEAN Received: from nasanexm02f.na.qualcomm.com ([10.85.0.87]) by ironmsg02-R.qualcomm.com with ESMTP/TLS/RC4-SHA; 21 Dec 2016 04:19:33 -0800 Received: from euamsexm01a.eu.qualcomm.com (10.251.127.40) by nasanexm02f.na.qualcomm.com (10.85.0.87) with Microsoft SMTP Server (TLS) id 15.0.1178.4; Wed, 21 Dec 2016 04:19:32 -0800 Received: from potku.adurom.net (10.80.80.8) by euamsexm01a.eu.qualcomm.com (10.251.127.40) with Microsoft SMTP Server (TLS) id 15.0.1178.4; Wed, 21 Dec 2016 13:19:28 +0100 Subject: [PATCH] ath10k: support dev_coredump for crash dump From: Kalle Valo To: Date: Wed, 21 Dec 2016 14:19:21 +0200 Message-ID: <20161221121921.25119.93932.stgit@potku.adurom.net> User-Agent: StGit/0.17.1-17-ge4e0 MIME-Version: 1.0 X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: NASANEXM01F.na.qualcomm.com (10.85.0.32) To euamsexm01a.eu.qualcomm.com (10.251.127.40) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161221_041955_890639_903D0A47 X-CRM114-Status: GOOD ( 13.66 ) X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-wireless@vger.kernel.org Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Arun Khandavalli Whenever firmware crashes, and both CONFIG_ATH10K_DEBUGFS and CONFIG_ALLOW_DEV_COREDUMP are enabled, dump information about the crash via a devcoredump device. Dump can be read from userspace for further analysis from: /sys/class/devcoredump/devcd*/data As until now we have provided the firmware crash dump file via fw_crash_dump debugfs keep it still available but deprecate and a warning print that the user should switch to using dev_coredump. Future improvement would be not to depend on CONFIG_ATH10K_DEBUGFS, as there might be systems which want to get the firmware crash dump but not enable debugfs. How to handle memory consumption is also something which needs to be taken into account. Signed-off-by: Arun Khandavalli [kvalo@qca.qualcomm.com: rebase, fixes, improve commit log] Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 6 ++++ drivers/net/wireless/ath/ath10k/debug.c | 43 +++++++++++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/debug.h | 8 ++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 749e381edd38..3319db178c2e 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1510,6 +1510,7 @@ static int ath10k_init_hw_params(struct ath10k *ar) static void ath10k_core_restart(struct work_struct *work) { struct ath10k *ar = container_of(work, struct ath10k, restart_work); + int ret; set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); @@ -1561,6 +1562,11 @@ static void ath10k_core_restart(struct work_struct *work) } mutex_unlock(&ar->conf_mutex); + + ret = ath10k_debug_fw_devcoredump(ar); + if (ret) + ath10k_warn(ar, "failed to send firmware crash dump via devcoredump: %d", + ret); } static void ath10k_core_set_coverage_class_work(struct work_struct *work) diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 82a4c67f3672..e1a70dffc52a 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "core.h" #include "debug.h" @@ -721,7 +722,8 @@ struct ath10k_fw_crash_data * } EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data); -static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar) +static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar, + bool mark_read) { struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data; struct ath10k_dump_file_data *dump_data; @@ -790,19 +792,54 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar) sizeof(crash_data->registers)); sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers); - ar->debug.fw_crash_data->crashed_since_read = false; + ar->debug.fw_crash_data->crashed_since_read = !mark_read; spin_unlock_bh(&ar->data_lock); return dump_data; } +int ath10k_debug_fw_devcoredump(struct ath10k *ar) +{ + struct ath10k_dump_file_data *dump; + void *dump_ptr; + u32 dump_len; + + /* To keep the dump file available also for debugfs don't mark the + * file read, only debugfs should do that. + */ + dump = ath10k_build_dump_file(ar, false); + if (!dump) { + ath10k_warn(ar, "no crash dump data found for devcoredump"); + return -ENODATA; + } + + /* Make a copy of the dump file for dev_coredumpv() as during the + * transition period we need to own the original file. Once + * fw_crash_dump debugfs file is removed no need to have a copy + * anymore. + */ + dump_len = le32_to_cpu(dump->len); + dump_ptr = vzalloc(dump_len); + + if (!dump_ptr) + return -ENOMEM; + + memcpy(dump_ptr, dump, dump_len); + + dev_coredumpv(ar->dev, dump_ptr, dump_len, GFP_KERNEL); + + return 0; +} + static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; struct ath10k_dump_file_data *dump; - dump = ath10k_build_dump_file(ar); + ath10k_warn(ar, "fw_crash_dump debugfs file is deprecated, please use /sys/class/devcoredump instead."); + + dump = ath10k_build_dump_file(ar, true); if (!dump) return -ENODATA; diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 335512b11ca2..2368f47314ae 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -84,6 +84,9 @@ struct ath10k_fw_crash_data * ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); + +int ath10k_debug_fw_devcoredump(struct ath10k *ar); + #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, @@ -166,6 +169,11 @@ static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar) return 0; } +static inline int ath10k_debug_fw_devcoredump(struct ath10k *ar) +{ + return 0; +} + #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0) #define ath10k_debug_get_et_strings NULL