From patchwork Sun Feb 7 23:00:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 8245811 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id D44029F38B for ; Sun, 7 Feb 2016 23:01:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 85496200E7 for ; Sun, 7 Feb 2016 23:01:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 097A7201E4 for ; Sun, 7 Feb 2016 23:01:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754817AbcBGXBE (ORCPT ); Sun, 7 Feb 2016 18:01:04 -0500 Received: from mail-wm0-f54.google.com ([74.125.82.54]:36084 "EHLO mail-wm0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754645AbcBGXBB (ORCPT ); Sun, 7 Feb 2016 18:01:01 -0500 Received: by mail-wm0-f54.google.com with SMTP id p63so91784371wmp.1; Sun, 07 Feb 2016 15:01:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:mime-version:content-type :content-transfer-encoding; bh=JAUCpp+i5tiw3YwXi9qIi0lp3A47OpNzVR8gWK9E1NA=; b=M+c9okGTUP4llYGVOstKiqQFEZ1DXLjIdIm+BYczBbYjfz8WWAQFEorPlvXoJb2SbF rdCpzx5QyEchYg+ypuNIoI4/31XIweQZ40GRJIEPIdGZLeHt/vqIC4gwqXsIbN+cI1o7 tXEeQse4iM71NmeKUETTgQzD+DMBGVhZuGfJBjCZaevOSkXNbv+h9/2Yf4k2NvW17Oyz FLWEKT8QRAOlTl10PRUy6nWeh0XI4XD7xrnhu5SVGhYRLXuIt8k5vhE6NKPWJctJovx8 wuk2YbkeW4fbW1WoQtk2r0QAPfkA7mu91cCZWcNfl/nV3cueBRVgW4jZlRsGsPQsAQYz muSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-type:content-transfer-encoding; bh=JAUCpp+i5tiw3YwXi9qIi0lp3A47OpNzVR8gWK9E1NA=; b=CscksOimM8cAuL7YK9/4NArdR6KiW/mRh6iPRk1tB0MrqKLWa5mAkPclxgSqjOSZQW lH9WhrbCv5LODgy/lsH9/JURlwtW/giXQLs6CMt7BZZe6q0scVrvwlyErwgPOC3SysJH tngwjA6yiIX0quNnWOVNC8uHju+UD6dbGaMuKKlQ/r3MTcNhUqqWl7Vw3Gsm5sCn4+io CIXeWb35nCcUmSJJ3nDhigqnePJmRbvfdDzIQ4v1UgScdtW/rNzsuh/18pUSubYhTiEC B9OMk9+XXJjo1fB6qTSMaRSOEZPa+22vYdRa3y50zyVZ+Bj3pZVWVeGNeChwx47zj9v3 HELw== X-Gm-Message-State: AG10YORo753TZyA8QIveZSjhYbL8LbCqmHt+rhUFxS1v5hC1Km8FkYzbYXYGVpYzkjyEvw== X-Received: by 10.28.63.200 with SMTP id m191mr26259578wma.21.1454886059506; Sun, 07 Feb 2016 15:00:59 -0800 (PST) Received: from linux-tdhb.lan (evp17.neoplus.adsl.tpnet.pl. [83.20.213.17]) by smtp.gmail.com with ESMTPSA id r62sm9651148wmd.15.2016.02.07.15.00.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 07 Feb 2016 15:00:58 -0800 (PST) From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= To: Kalle Valo , linux-wireless@vger.kernel.org Cc: Brett Rudley , Arend van Spriel , "Franky (Zhenhui) Lin" , Hante Meuleman , brcm80211-dev-list@broadcom.com, , =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Subject: [PATCH] brcmfmac: Increase nr of supported flowrings. Date: Mon, 8 Feb 2016 00:00:30 +0100 Message-Id: <1454886030-16406-1-git-send-email-zajec5@gmail.com> X-Mailer: git-send-email 1.8.4.5 MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Spam-Status: No, score=-7.0 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Hante Meuleman New generation devices have firmware which has more than 256 flowrings. E.g. following debugging message comes from 14e4:4365 BCM4366: [ 194.606245] brcmfmac: brcmf_pcie_init_ringbuffers Nr of flowrings is 264 At various code places (related to flowrings) we were using u8 which could lead to storing wrong number or infinite loops when indexing with this type. This issue was quite easy to spot in brcmf_flowring_detach where it led to infinite loop e.g. on failed initialization. This patch switches code to proper types and increases the maximum number of supported flowrings to 512. Originally this change was sent in September 2015, but back it was causing a regression on BCM43602 resulting in: Unable to handle kernel NULL pointer dereference at virtual address ... The reason for this regression was missing update (s/u8/u16) of struct brcmf_flowring_ring. This problem was handled in 9f64df9 ("brcmfmac: Fix bug in flowring management."). Starting with that it's safe to apply this original patch as it doesn't cause a regression anymore. This patch fixes an infinite loop on BCM4366 which is supported since 4.4 so it makes sense to apply it to stable 4.4+. Cc: # 4.4+ Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Rafa? Mi?ecki --- .../broadcom/brcm80211/brcmfmac/flowring.c | 38 ++++++++++++---------- .../broadcom/brcm80211/brcmfmac/flowring.h | 20 ++++++------ .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 11 +++++-- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 2 +- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c index 2ca783f..7e269f9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c @@ -32,7 +32,7 @@ #define BRCMF_FLOWRING_LOW (BRCMF_FLOWRING_HIGH - 256) #define BRCMF_FLOWRING_INVALID_IFIDX 0xff -#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16) +#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] * 2 + fifo + ifidx * 16) #define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16) static const u8 brcmf_flowring_prio2fifo[] = { @@ -68,7 +68,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], u8 prio, u8 ifidx) { struct brcmf_flowring_hash *hash; - u8 hash_idx; + u16 hash_idx; u32 i; bool found; bool sta; @@ -88,6 +88,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], } hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); found = false; hash = flow->hash; for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { @@ -98,6 +99,7 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], break; } hash_idx++; + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); } if (found) return hash[hash_idx].flowid; @@ -111,7 +113,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], { struct brcmf_flowring_ring *ring; struct brcmf_flowring_hash *hash; - u8 hash_idx; + u16 hash_idx; u32 i; bool found; u8 fifo; @@ -131,6 +133,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], } hash_idx = sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) : BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx); + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); found = false; hash = flow->hash; for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) { @@ -140,6 +143,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], break; } hash_idx++; + hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1); } if (found) { for (i = 0; i < flow->nrofrings; i++) { @@ -169,7 +173,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], } -u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid) +u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; @@ -179,7 +183,7 @@ u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid) } -static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid, +static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid, bool blocked) { struct brcmf_flowring_ring *ring; @@ -228,10 +232,10 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid, } -void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid) +void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; - u8 hash_idx; + u16 hash_idx; struct sk_buff *skb; ring = flow->rings[flowid]; @@ -253,7 +257,7 @@ void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid) } -u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, +u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid, struct sk_buff *skb) { struct brcmf_flowring_ring *ring; @@ -279,7 +283,7 @@ u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, } -struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid) +struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; struct sk_buff *skb; @@ -300,7 +304,7 @@ struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid) } -void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, +void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid, struct sk_buff *skb) { struct brcmf_flowring_ring *ring; @@ -311,7 +315,7 @@ void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, } -u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid) +u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; @@ -326,7 +330,7 @@ u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid) } -void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid) +void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; @@ -340,10 +344,10 @@ void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid) } -u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid) +u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid) { struct brcmf_flowring_ring *ring; - u8 hash_idx; + u16 hash_idx; ring = flow->rings[flowid]; hash_idx = ring->hash_id; @@ -384,7 +388,7 @@ void brcmf_flowring_detach(struct brcmf_flowring *flow) struct brcmf_pub *drvr = bus_if->drvr; struct brcmf_flowring_tdls_entry *search; struct brcmf_flowring_tdls_entry *remove; - u8 flowid; + u16 flowid; for (flowid = 0; flowid < flow->nrofrings; flowid++) { if (flow->rings[flowid]) @@ -408,7 +412,7 @@ void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx, struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev); struct brcmf_pub *drvr = bus_if->drvr; u32 i; - u8 flowid; + u16 flowid; if (flow->addr_mode[ifidx] != addr_mode) { for (i = 0; i < ARRAY_SIZE(flow->hash); i++) { @@ -434,7 +438,7 @@ void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx, struct brcmf_flowring_tdls_entry *prev; struct brcmf_flowring_tdls_entry *search; u32 i; - u8 flowid; + u16 flowid; bool sta; sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h index 95fd1c9..068e68d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h @@ -16,7 +16,7 @@ #define BRCMFMAC_FLOWRING_H -#define BRCMF_FLOWRING_HASHSIZE 256 +#define BRCMF_FLOWRING_HASHSIZE 512 /* has to be 2^x */ #define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF @@ -24,7 +24,7 @@ struct brcmf_flowring_hash { u8 mac[ETH_ALEN]; u8 fifo; u8 ifidx; - u8 flowid; + u16 flowid; }; enum ring_status { @@ -61,16 +61,16 @@ u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN], u8 prio, u8 ifidx); u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN], u8 prio, u8 ifidx); -void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid); -void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid); -u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid); -u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, +void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid); +void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid); +u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid); +u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid, struct sk_buff *skb); -struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid); -void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, +struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid); +void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid, struct sk_buff *skb); -u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u8 flowid); -u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u8 flowid); +u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid); +u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid); struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings); void brcmf_flowring_detach(struct brcmf_flowring *flow); void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index c2bdb91..9229667 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -677,7 +677,7 @@ static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx, } -static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid) +static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid) { struct brcmf_flowring *flow = msgbuf->flow; struct brcmf_commonring *commonring; @@ -1310,7 +1310,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev) } -void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid) +void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid) { struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; struct msgbuf_tx_flowring_delete_req *delete; @@ -1415,6 +1415,13 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) u32 count; if_msgbuf = drvr->bus_if->msgbuf; + + if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) { + brcmf_err("driver not configured for this many flowrings %d\n", + if_msgbuf->nrof_flowrings); + if_msgbuf->nrof_flowrings = BRCMF_FLOWRING_HASHSIZE - 1; + } + msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL); if (!msgbuf) goto fail; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h index 3d513e4..ee6906a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h @@ -33,7 +33,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev); -void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid); +void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid); int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr); void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr); #else