Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp3818457yba; Mon, 29 Apr 2019 09:02:25 -0700 (PDT) X-Google-Smtp-Source: APXvYqx4VxfPSQMriptnEIX5ve0VQGyOndKKh/yceGjqtgSe85JvzWWi+q7gXTtXj/151p+qZRrc X-Received: by 2002:a17:902:a585:: with SMTP id az5mr28613374plb.261.1556553745266; Mon, 29 Apr 2019 09:02:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1556553745; cv=none; d=google.com; s=arc-20160816; b=zU+75lQoVCY2TMDXqPRlxMdpbIGwAHom4OrTQYWulBdOb+L3b0Es9r+AtCPSMgYB6w Uhta8IDWC08ZU6PymVxVmNG4zjXujAsEE05pkd9XZ/NqHoyeWFKK466vSdV40TjFyuY5 +CnOdOuOPWxdDJLWPWF7wa+IALGZoFYg4QAPCRjrjHgGTE4mGIGVsBMyycli6zyd1r0L gaOVSQvMenRFTPeug/bd45dYo/qrRFX47S49+x2dBQ1tCSNABfenI8fQ8SfpBqZHFfvh Zz3TwqHplBxWL7UI3w60gWCUBXy6Tr3sstzUPYy0itlvoloqSE6flzyBLcxS9ors/Am5 Cw/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature:dkim-filter; bh=zteiYEt0MD8nnqkEUpncEEy0MQ2HY8EOZ10D0fH6I7M=; b=tTwMxtvRS/9GFz0Ig6qCo5jBoL3Asu0NbEONsKl0smbWElu1nJbt5js4RVrNFmCRQG nAiFSMP11suvVLND+dKrB1l5x59x2kq8Qxv78Z6V9aY+HyCPxralDYVmMZ88AjMyRorF dsHT97UeL4sbSQE0qkrPS6ywheDDR43gvvRw/jGDdYG5v3zHn6Xgspuv/SSvZx6jSDEq Ph+xuZDk4O31IV95qk8Tc6/yYliUIfO0qJv9qJuoOAB789pxEHOogZb5GNU+9ZuEDUKE uDHhH0LV2ub0TOVay8nbNexXNRFhCC8IS1R09Ox5SyrGPk/By4PPqaQL3+hGbKlEKTpu hAwg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@broadcom.com header.s=dkimrelay header.b=a7GdwgbW; spf=pass (google.com: best guess record for domain of linux-wireless-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-wireless-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=broadcom.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id cj5si28486679plb.76.2019.04.29.09.02.09; Mon, 29 Apr 2019 09:02:25 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-wireless-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@broadcom.com header.s=dkimrelay header.b=a7GdwgbW; spf=pass (google.com: best guess record for domain of linux-wireless-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-wireless-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=broadcom.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728787AbfD2QCB (ORCPT + 99 others); Mon, 29 Apr 2019 12:02:01 -0400 Received: from rnd-relay.smtp.broadcom.com ([192.19.229.170]:37006 "EHLO rnd-relay.smtp.broadcom.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728506AbfD2QCB (ORCPT ); Mon, 29 Apr 2019 12:02:01 -0400 Received: from mail-irv-17.broadcom.com (mail-irv-17.lvn.broadcom.net [10.75.224.233]) by rnd-relay.smtp.broadcom.com (Postfix) with ESMTP id 518B830C074; Mon, 29 Apr 2019 09:01:52 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.10.3 rnd-relay.smtp.broadcom.com 518B830C074 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=broadcom.com; s=dkimrelay; t=1556553718; bh=+njzF/MkWyQUo99XszOttuAyYfxImuTEyzZXCSrj/MA=; h=From:To:Cc:Subject:Date:From; b=a7GdwgbWO9R9knYpZ2uZJJ0jqRQrckASvGvNfieMnGRtZ/50AxI3ijhZ4iGZMh3Y5 9KZLiERHpzK0AtHJk4dKF8mp7+1LUj9kGlz3GHDM2EX0g3HIUirkoi9imcc2nnZa+b jq8LtYL5xFS0CSvlBi0ednWceQwT66JnjZ0IXJfg= Received: from bld-bun-01.bun.broadcom.com (bld-bun-01.bun.broadcom.com [10.176.128.83]) by mail-irv-17.broadcom.com (Postfix) with ESMTP id E74AF868B7; Mon, 29 Apr 2019 03:09:35 -0700 (PDT) Received: by bld-bun-01.bun.broadcom.com (Postfix, from userid 25152) id 30A91B02A68; Mon, 29 Apr 2019 12:09:33 +0200 (CEST) From: Arend van Spriel To: Piotr Figiel Cc: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= , linux-wireless@vger.kernel.org, Arend van Spriel Subject: [PATCH] brcmfmac: change the order of things in brcmf_detach() Date: Mon, 29 Apr 2019 12:09:21 +0200 Message-Id: <1556532561-24428-1-git-send-email-arend.vanspriel@broadcom.com> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org When brcmf_detach() from the bus layer upon rmmod we can no longer communicate. Hence we will set the bus state to DOWN and cleanup the event and protocol layer. The network interfaces need to be deleted before brcmf_cfg80211_detach() because the latter does the wiphy_unregister() which issues a warning if there are still network devices linked to the wiphy instance. This change solves a null pointer dereference issue which happened upon issueing rmmod while there are packets queued in bus protocol layer. Reported-by: Rafał Miłecki Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky Lin Signed-off-by: Arend van Spriel --- Hi Piotr, While working on an issue with msgbuf protocol (used for PCIe devices) your change 5cdb0ef6144f ("brcmfmac: fix NULL pointer derefence during USB disconnect") conflicted. I suspect my reordering stuff in brcmf_detach() also fixes your issue so could you retest this patch, which basically reverts your change and applies my reordering, and see whether my suspicion can be confirmed. Regards, Arend --- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 ++------- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.h | 6 ++--- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 27 +++++++++++----------- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 16 ++++--------- .../broadcom/brcm80211/brcmfmac/fwsignal.h | 3 +-- .../wireless/broadcom/brcm80211/brcmfmac/proto.c | 10 ++------ .../wireless/broadcom/brcm80211/brcmfmac/proto.h | 3 +-- 7 files changed, 25 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 98b1687..73d3c1a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -490,18 +490,11 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) return -ENOMEM; } -void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) -{ - struct brcmf_bcdc *bcdc = drvr->proto->pd; - - brcmf_fws_detach_pre_delif(bcdc->fws); -} - -void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) +void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) { struct brcmf_bcdc *bcdc = drvr->proto->pd; drvr->proto->pd = NULL; - brcmf_fws_detach_post_delif(bcdc->fws); + brcmf_fws_detach(bcdc->fws); kfree(bcdc); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h index 4bc5224..3b0e9ef 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h @@ -18,16 +18,14 @@ #ifdef CONFIG_BRCMFMAC_PROTO_BCDC int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr); -void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr); -void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr); +void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr); void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state); void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp, bool success); struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr); #else static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; } -static void brcmf_proto_bcdc_detach_pre_delif(struct brcmf_pub *drvr) {}; -static inline void brcmf_proto_bcdc_detach_post_delif(struct brcmf_pub *drvr) {} +static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {} #endif #endif /* BRCMFMAC_BCDC_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index bc73a2e..db49381 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -1322,27 +1322,26 @@ void brcmf_detach(struct device *dev) unregister_inet6addr_notifier(&drvr->inet6addr_notifier); #endif - /* stop firmware event handling */ - brcmf_fweh_detach(drvr); - if (drvr->config) - brcmf_p2p_detach(&drvr->config->p2p); - brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); + brcmf_bus_stop(drvr->bus_if); - brcmf_proto_detach_pre_delif(drvr); + brcmf_fweh_detach(drvr); + brcmf_proto_detach(drvr); /* make sure primary interface removed last */ - for (i = BRCMF_MAX_IFS-1; i > -1; i--) - brcmf_remove_interface(drvr->iflist[i], false); - - brcmf_cfg80211_detach(drvr->config); - drvr->config = NULL; - - brcmf_bus_stop(drvr->bus_if); + for (i = BRCMF_MAX_IFS-1; i > -1; i--) { + if (drvr->iflist[i]) + brcmf_del_if(drvr, drvr->iflist[i]->bsscfgidx, false); + } - brcmf_proto_detach_post_delif(drvr); + if (drvr->config) { + brcmf_p2p_detach(&drvr->config->p2p); + brcmf_cfg80211_detach(drvr->config); + drvr->config = NULL; + } bus_if->drvr = NULL; + wiphy_free(drvr->wiphy); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index c22c49a..d48b8b2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -2443,25 +2443,17 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr) return fws; fail: - brcmf_fws_detach_pre_delif(fws); - brcmf_fws_detach_post_delif(fws); + brcmf_fws_detach(fws); return ERR_PTR(rc); } -void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws) +void brcmf_fws_detach(struct brcmf_fws_info *fws) { if (!fws) return; - if (fws->fws_wq) { - destroy_workqueue(fws->fws_wq); - fws->fws_wq = NULL; - } -} -void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws) -{ - if (!fws) - return; + if (fws->fws_wq) + destroy_workqueue(fws->fws_wq); /* cleanup */ brcmf_fws_lock(fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h index 749c06d..4e68357 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h @@ -19,8 +19,7 @@ #define FWSIGNAL_H_ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr); -void brcmf_fws_detach_pre_delif(struct brcmf_fws_info *fws); -void brcmf_fws_detach_post_delif(struct brcmf_fws_info *fws); +void brcmf_fws_detach(struct brcmf_fws_info *fws); void brcmf_fws_debugfs_create(struct brcmf_pub *drvr); bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws); bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c index c7964cc..024c643 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c @@ -67,22 +67,16 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) return -ENOMEM; } -void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr) +void brcmf_proto_detach(struct brcmf_pub *drvr) { brcmf_dbg(TRACE, "Enter\n"); if (drvr->proto) { if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) - brcmf_proto_bcdc_detach_post_delif(drvr); + brcmf_proto_bcdc_detach(drvr); else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) brcmf_proto_msgbuf_detach(drvr); kfree(drvr->proto); drvr->proto = NULL; } } - -void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr) -{ - if (drvr->proto && drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) - brcmf_proto_bcdc_detach_pre_delif(drvr); -} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h index 72355ae..d3c3b9a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h @@ -54,8 +54,7 @@ struct brcmf_proto { int brcmf_proto_attach(struct brcmf_pub *drvr); -void brcmf_proto_detach_pre_delif(struct brcmf_pub *drvr); -void brcmf_proto_detach_post_delif(struct brcmf_pub *drvr); +void brcmf_proto_detach(struct brcmf_pub *drvr); static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, struct sk_buff *skb, -- 1.9.1