From: Rafał Miłecki Date: Thu, 2 Feb 2017 08:27:20 +0000 (+0100) Subject: mac80211: brcmfmac: backport scheduled scan cleanup and chip support X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=863a06b0a4ed3939d81fb49d3b8a88db9e807d41;p=openwrt%2Fstaging%2Fjow.git mac80211: brcmfmac: backport scheduled scan cleanup and chip support Signed-off-by: Rafał Miłecki --- diff --git a/package/kernel/mac80211/patches/357-0001-brcmfmac-add-pcie-host-dongle-interface-rev6-support.patch b/package/kernel/mac80211/patches/357-0001-brcmfmac-add-pcie-host-dongle-interface-rev6-support.patch new file mode 100644 index 0000000000..e09391332b --- /dev/null +++ b/package/kernel/mac80211/patches/357-0001-brcmfmac-add-pcie-host-dongle-interface-rev6-support.patch @@ -0,0 +1,490 @@ +From be4b092cab84b2ecc01ee7f4da6a044279430b6f Mon Sep 17 00:00:00 2001 +From: Franky Lin +Date: Wed, 23 Nov 2016 10:25:20 +0000 +Subject: [PATCH] brcmfmac: add pcie host dongle interface rev6 support + +In rev6 of pcie host dongle interface protocol, host needs to maximum +supported ring number from dongle shared memory and set up ring buffer +and ring indices offset accordingly. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Arend van Spriel +Signed-off-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 +- + .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 38 +++-- + .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 4 + + .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 171 ++++++++++++--------- + 4 files changed, 132 insertions(+), 91 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +@@ -22,10 +22,12 @@ + /* IDs of the 6 default common rings of msgbuf protocol */ + #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0 + #define BRCMF_H2D_MSGRING_RXPOST_SUBMIT 1 ++#define BRCMF_H2D_MSGRING_FLOWRING_IDSTART 2 + #define BRCMF_D2H_MSGRING_CONTROL_COMPLETE 2 + #define BRCMF_D2H_MSGRING_TX_COMPLETE 3 + #define BRCMF_D2H_MSGRING_RX_COMPLETE 4 + ++ + #define BRCMF_NROF_H2D_COMMON_MSGRINGS 2 + #define BRCMF_NROF_D2H_COMMON_MSGRINGS 3 + #define BRCMF_NROF_COMMON_MSGRINGS (BRCMF_NROF_H2D_COMMON_MSGRINGS + \ +@@ -95,14 +97,18 @@ struct brcmf_bus_ops { + * @flowrings: commonrings which are dynamically created and destroyed for data. + * @rx_dataoffset: if set then all rx data has this this offset. + * @max_rxbufpost: maximum number of buffers to post for rx. +- * @nrof_flowrings: number of flowrings. ++ * @max_flowrings: maximum number of tx flow rings supported. ++ * @max_submissionrings: maximum number of submission rings(h2d) supported. ++ * @max_completionrings: maximum number of completion rings(d2h) supported. + */ + struct brcmf_bus_msgbuf { + struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS]; + struct brcmf_commonring **flowrings; + u32 rx_dataoffset; + u32 max_rxbufpost; +- u32 nrof_flowrings; ++ u16 max_flowrings; ++ u16 max_submissionrings; ++ u16 max_completionrings; + }; + + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +@@ -87,11 +87,6 @@ struct msgbuf_common_hdr { + __le32 request_id; + }; + +-struct msgbuf_buf_addr { +- __le32 low_addr; +- __le32 high_addr; +-}; +- + struct msgbuf_ioctl_req_hdr { + struct msgbuf_common_hdr msg; + __le32 cmd; +@@ -227,7 +222,10 @@ struct brcmf_msgbuf { + struct brcmf_commonring **commonrings; + struct brcmf_commonring **flowrings; + dma_addr_t *flowring_dma_handle; +- u16 nrof_flowrings; ++ ++ u16 max_flowrings; ++ u16 max_submissionrings; ++ u16 max_completionrings; + + u16 rx_dataoffset; + u32 max_rxbufpost; +@@ -610,7 +608,7 @@ brcmf_msgbuf_flowring_create_worker(stru + create->msg.request_id = 0; + create->tid = brcmf_flowring_tid(msgbuf->flow, flowid); + create->flow_ring_id = cpu_to_le16(flowid + +- BRCMF_NROF_H2D_COMMON_MSGRINGS); ++ BRCMF_H2D_MSGRING_FLOWRING_IDSTART); + memcpy(create->sa, work->sa, ETH_ALEN); + memcpy(create->da, work->da, ETH_ALEN); + address = (u64)msgbuf->flowring_dma_handle[flowid]; +@@ -760,7 +758,7 @@ static void brcmf_msgbuf_txflow_worker(s + u32 flowid; + + msgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work); +- for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->nrof_flowrings) { ++ for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->max_flowrings) { + clear_bit(flowid, msgbuf->flow_map); + brcmf_msgbuf_txflow(msgbuf, flowid); + } +@@ -866,7 +864,7 @@ brcmf_msgbuf_process_txstatus(struct brc + tx_status = (struct msgbuf_tx_status *)buf; + idx = le32_to_cpu(tx_status->msg.request_id); + flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id); +- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS; ++ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART; + skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev, + msgbuf->tx_pktids, idx); + if (!skb) +@@ -1174,7 +1172,7 @@ brcmf_msgbuf_process_flow_ring_create_re + flowring_create_resp = (struct msgbuf_flowring_create_resp *)buf; + + flowid = le16_to_cpu(flowring_create_resp->compl_hdr.flow_ring_id); +- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS; ++ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART; + status = le16_to_cpu(flowring_create_resp->compl_hdr.status); + + if (status) { +@@ -1202,7 +1200,7 @@ brcmf_msgbuf_process_flow_ring_delete_re + flowring_delete_resp = (struct msgbuf_flowring_delete_resp *)buf; + + flowid = le16_to_cpu(flowring_delete_resp->compl_hdr.flow_ring_id); +- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS; ++ flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART; + status = le16_to_cpu(flowring_delete_resp->compl_hdr.status); + + if (status) { +@@ -1307,7 +1305,7 @@ int brcmf_proto_msgbuf_rx_trigger(struct + brcmf_msgbuf_process_rx(msgbuf, buf); + + for_each_set_bit(flowid, msgbuf->txstatus_done_map, +- msgbuf->nrof_flowrings) { ++ msgbuf->max_flowrings) { + clear_bit(flowid, msgbuf->txstatus_done_map); + commonring = msgbuf->flowrings[flowid]; + qlen = brcmf_flowring_qlen(msgbuf->flow, flowid); +@@ -1349,7 +1347,7 @@ void brcmf_msgbuf_delete_flowring(struct + delete->msg.request_id = 0; + + delete->flow_ring_id = cpu_to_le16(flowid + +- BRCMF_NROF_H2D_COMMON_MSGRINGS); ++ BRCMF_H2D_MSGRING_FLOWRING_IDSTART); + delete->reason = 0; + + brcmf_dbg(MSGBUF, "Send Flow Delete Req flow ID %d, ifindex %d\n", +@@ -1427,10 +1425,10 @@ int brcmf_proto_msgbuf_attach(struct brc + + if_msgbuf = drvr->bus_if->msgbuf; + +- if (if_msgbuf->nrof_flowrings >= BRCMF_FLOWRING_HASHSIZE) { ++ if (if_msgbuf->max_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; ++ if_msgbuf->max_flowrings); ++ if_msgbuf->max_flowrings = BRCMF_FLOWRING_HASHSIZE - 1; + } + + msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL); +@@ -1443,7 +1441,7 @@ int brcmf_proto_msgbuf_attach(struct brc + goto fail; + } + INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker); +- count = BITS_TO_LONGS(if_msgbuf->nrof_flowrings); ++ count = BITS_TO_LONGS(if_msgbuf->max_flowrings); + count = count * sizeof(unsigned long); + msgbuf->flow_map = kzalloc(count, GFP_KERNEL); + if (!msgbuf->flow_map) +@@ -1479,8 +1477,8 @@ int brcmf_proto_msgbuf_attach(struct brc + msgbuf->commonrings = + (struct brcmf_commonring **)if_msgbuf->commonrings; + msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings; +- msgbuf->nrof_flowrings = if_msgbuf->nrof_flowrings; +- msgbuf->flowring_dma_handle = kzalloc(msgbuf->nrof_flowrings * ++ msgbuf->max_flowrings = if_msgbuf->max_flowrings; ++ msgbuf->flowring_dma_handle = kzalloc(msgbuf->max_flowrings * + sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL); + if (!msgbuf->flowring_dma_handle) + goto fail; +@@ -1501,7 +1499,7 @@ int brcmf_proto_msgbuf_attach(struct brc + goto fail; + + msgbuf->flow = brcmf_flowring_attach(drvr->bus_if->dev, +- if_msgbuf->nrof_flowrings); ++ if_msgbuf->max_flowrings); + if (!msgbuf->flow) + goto fail; + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h +@@ -31,6 +31,10 @@ + #define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 32 + #define BRCMF_H2D_TXFLOWRING_ITEMSIZE 48 + ++struct msgbuf_buf_addr { ++ __le32 low_addr; ++ __le32 high_addr; ++}; + + int brcmf_proto_msgbuf_rx_trigger(struct device *dev); + void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -135,7 +135,7 @@ static struct brcmf_firmware_mapping brc + BRCMF_PCIE_MB_INT_D2H3_DB1) + + #define BRCMF_PCIE_MIN_SHARED_VERSION 5 +-#define BRCMF_PCIE_MAX_SHARED_VERSION 5 ++#define BRCMF_PCIE_MAX_SHARED_VERSION 6 + #define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF + #define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000 + #define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000 +@@ -166,17 +166,6 @@ static struct brcmf_firmware_mapping brc + #define BRCMF_RING_MEM_SZ 16 + #define BRCMF_RING_STATE_SZ 8 + +-#define BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET 4 +-#define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8 +-#define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12 +-#define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16 +-#define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET 20 +-#define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET 28 +-#define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET 36 +-#define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET 44 +-#define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET 0 +-#define BRCMF_SHARED_RING_MAX_SUB_QUEUES 52 +- + #define BRCMF_DEF_MAX_RXBUFPOST 255 + + #define BRCMF_CONSOLE_BUFADDR_OFFSET 8 +@@ -231,7 +220,9 @@ struct brcmf_pcie_shared_info { + struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS]; + struct brcmf_pcie_ringbuf *flowrings; + u16 max_rxbufpost; +- u32 nrof_flowrings; ++ u16 max_flowrings; ++ u16 max_submissionrings; ++ u16 max_completionrings; + u32 rx_dataoffset; + u32 htod_mb_data_addr; + u32 dtoh_mb_data_addr; +@@ -241,6 +232,7 @@ struct brcmf_pcie_shared_info { + dma_addr_t scratch_dmahandle; + void *ringupd; + dma_addr_t ringupd_dmahandle; ++ u8 version; + }; + + struct brcmf_pcie_core_info { +@@ -284,6 +276,36 @@ struct brcmf_pcie_ringbuf { + u8 id; + }; + ++/** ++ * struct brcmf_pcie_dhi_ringinfo - dongle/host interface shared ring info ++ * ++ * @ringmem: dongle memory pointer to ring memory location ++ * @h2d_w_idx_ptr: h2d ring write indices dongle memory pointers ++ * @h2d_r_idx_ptr: h2d ring read indices dongle memory pointers ++ * @d2h_w_idx_ptr: d2h ring write indices dongle memory pointers ++ * @d2h_r_idx_ptr: d2h ring read indices dongle memory pointers ++ * @h2d_w_idx_hostaddr: h2d ring write indices host memory pointers ++ * @h2d_r_idx_hostaddr: h2d ring read indices host memory pointers ++ * @d2h_w_idx_hostaddr: d2h ring write indices host memory pointers ++ * @d2h_r_idx_hostaddr: d2h ring reaD indices host memory pointers ++ * @max_flowrings: maximum number of tx flow rings supported. ++ * @max_submissionrings: maximum number of submission rings(h2d) supported. ++ * @max_completionrings: maximum number of completion rings(d2h) supported. ++ */ ++struct brcmf_pcie_dhi_ringinfo { ++ __le32 ringmem; ++ __le32 h2d_w_idx_ptr; ++ __le32 h2d_r_idx_ptr; ++ __le32 d2h_w_idx_ptr; ++ __le32 d2h_r_idx_ptr; ++ struct msgbuf_buf_addr h2d_w_idx_hostaddr; ++ struct msgbuf_buf_addr h2d_r_idx_hostaddr; ++ struct msgbuf_buf_addr d2h_w_idx_hostaddr; ++ struct msgbuf_buf_addr d2h_r_idx_hostaddr; ++ __le16 max_flowrings; ++ __le16 max_submissionrings; ++ __le16 max_completionrings; ++}; + + static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = { + BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM, +@@ -1054,26 +1076,35 @@ static int brcmf_pcie_init_ringbuffers(s + { + struct brcmf_pcie_ringbuf *ring; + struct brcmf_pcie_ringbuf *rings; +- u32 ring_addr; + u32 d2h_w_idx_ptr; + u32 d2h_r_idx_ptr; + u32 h2d_w_idx_ptr; + u32 h2d_r_idx_ptr; +- u32 addr; + u32 ring_mem_ptr; + u32 i; + u64 address; + u32 bufsz; +- u16 max_sub_queues; + u8 idx_offset; +- +- ring_addr = devinfo->shared.ring_info_addr; +- brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr); +- addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES; +- max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr); ++ struct brcmf_pcie_dhi_ringinfo ringinfo; ++ u16 max_flowrings; ++ u16 max_submissionrings; ++ u16 max_completionrings; ++ ++ memcpy_fromio(&ringinfo, devinfo->tcm + devinfo->shared.ring_info_addr, ++ sizeof(ringinfo)); ++ if (devinfo->shared.version >= 6) { ++ max_submissionrings = le16_to_cpu(ringinfo.max_submissionrings); ++ max_flowrings = le16_to_cpu(ringinfo.max_flowrings); ++ max_completionrings = le16_to_cpu(ringinfo.max_completionrings); ++ } else { ++ max_submissionrings = le16_to_cpu(ringinfo.max_flowrings); ++ max_flowrings = max_submissionrings - ++ BRCMF_NROF_H2D_COMMON_MSGRINGS; ++ max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS; ++ } + + if (devinfo->dma_idx_sz != 0) { +- bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) * ++ bufsz = (max_submissionrings + max_completionrings) * + devinfo->dma_idx_sz * 2; + devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz, + &devinfo->idxbuf_dmahandle, +@@ -1083,14 +1114,10 @@ static int brcmf_pcie_init_ringbuffers(s + } + + if (devinfo->dma_idx_sz == 0) { +- addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET; +- d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +- addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET; +- d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +- addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET; +- h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +- addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET; +- h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); ++ d2h_w_idx_ptr = le32_to_cpu(ringinfo.d2h_w_idx_ptr); ++ d2h_r_idx_ptr = le32_to_cpu(ringinfo.d2h_r_idx_ptr); ++ h2d_w_idx_ptr = le32_to_cpu(ringinfo.h2d_w_idx_ptr); ++ h2d_r_idx_ptr = le32_to_cpu(ringinfo.h2d_r_idx_ptr); + idx_offset = sizeof(u32); + devinfo->write_ptr = brcmf_pcie_write_tcm16; + devinfo->read_ptr = brcmf_pcie_read_tcm16; +@@ -1103,34 +1130,42 @@ static int brcmf_pcie_init_ringbuffers(s + devinfo->read_ptr = brcmf_pcie_read_idx; + + h2d_w_idx_ptr = 0; +- addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET; + address = (u64)devinfo->idxbuf_dmahandle; +- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); +- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); +- +- h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset; +- addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET; +- address += max_sub_queues * idx_offset; +- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); +- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); +- +- d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset; +- addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET; +- address += max_sub_queues * idx_offset; +- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); +- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); ++ ringinfo.h2d_w_idx_hostaddr.low_addr = ++ cpu_to_le32(address & 0xffffffff); ++ ringinfo.h2d_w_idx_hostaddr.high_addr = ++ cpu_to_le32(address >> 32); ++ ++ h2d_r_idx_ptr = h2d_w_idx_ptr + ++ max_submissionrings * idx_offset; ++ address += max_submissionrings * idx_offset; ++ ringinfo.h2d_r_idx_hostaddr.low_addr = ++ cpu_to_le32(address & 0xffffffff); ++ ringinfo.h2d_r_idx_hostaddr.high_addr = ++ cpu_to_le32(address >> 32); ++ ++ d2h_w_idx_ptr = h2d_r_idx_ptr + ++ max_submissionrings * idx_offset; ++ address += max_submissionrings * idx_offset; ++ ringinfo.d2h_w_idx_hostaddr.low_addr = ++ cpu_to_le32(address & 0xffffffff); ++ ringinfo.d2h_w_idx_hostaddr.high_addr = ++ cpu_to_le32(address >> 32); + + d2h_r_idx_ptr = d2h_w_idx_ptr + +- BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset; +- addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET; +- address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset; +- brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); +- brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); ++ max_completionrings * idx_offset; ++ address += max_completionrings * idx_offset; ++ ringinfo.d2h_r_idx_hostaddr.low_addr = ++ cpu_to_le32(address & 0xffffffff); ++ ringinfo.d2h_r_idx_hostaddr.high_addr = ++ cpu_to_le32(address >> 32); ++ ++ memcpy_toio(devinfo->tcm + devinfo->shared.ring_info_addr, ++ &ringinfo, sizeof(ringinfo)); + brcmf_dbg(PCIE, "Using host memory indices\n"); + } + +- addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET; +- ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr); ++ ring_mem_ptr = le32_to_cpu(ringinfo.ringmem); + + for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) { + ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr); +@@ -1161,20 +1196,19 @@ static int brcmf_pcie_init_ringbuffers(s + ring_mem_ptr += BRCMF_RING_MEM_SZ; + } + +- devinfo->shared.nrof_flowrings = +- max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS; +- rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring), +- GFP_KERNEL); ++ devinfo->shared.max_flowrings = max_flowrings; ++ devinfo->shared.max_submissionrings = max_submissionrings; ++ devinfo->shared.max_completionrings = max_completionrings; ++ rings = kcalloc(max_flowrings, sizeof(*ring), GFP_KERNEL); + if (!rings) + goto fail; + +- brcmf_dbg(PCIE, "Nr of flowrings is %d\n", +- devinfo->shared.nrof_flowrings); ++ brcmf_dbg(PCIE, "Nr of flowrings is %d\n", max_flowrings); + +- for (i = 0; i < devinfo->shared.nrof_flowrings; i++) { ++ for (i = 0; i < max_flowrings; i++) { + ring = &rings[i]; + ring->devinfo = devinfo; +- ring->id = i + BRCMF_NROF_COMMON_MSGRINGS; ++ ring->id = i + BRCMF_H2D_MSGRING_FLOWRING_IDSTART; + brcmf_commonring_register_cb(&ring->commonring, + brcmf_pcie_ring_mb_ring_bell, + brcmf_pcie_ring_mb_update_rptr, +@@ -1357,17 +1391,16 @@ brcmf_pcie_init_share_ram_info(struct br + { + struct brcmf_pcie_shared_info *shared; + u32 addr; +- u32 version; + + shared = &devinfo->shared; + shared->tcm_base_address = sharedram_addr; + + shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr); +- version = shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK; +- brcmf_dbg(PCIE, "PCIe protocol version %d\n", version); +- if ((version > BRCMF_PCIE_MAX_SHARED_VERSION) || +- (version < BRCMF_PCIE_MIN_SHARED_VERSION)) { +- brcmf_err("Unsupported PCIE version %d\n", version); ++ shared->version = (u8)(shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK); ++ brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version); ++ if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) || ++ (shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) { ++ brcmf_err("Unsupported PCIE version %d\n", shared->version); + return -EINVAL; + } + +@@ -1661,18 +1694,18 @@ static void brcmf_pcie_setup(struct devi + bus->msgbuf->commonrings[i] = + &devinfo->shared.commonrings[i]->commonring; + +- flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*flowrings), ++ flowrings = kcalloc(devinfo->shared.max_flowrings, sizeof(*flowrings), + GFP_KERNEL); + if (!flowrings) + goto fail; + +- for (i = 0; i < devinfo->shared.nrof_flowrings; i++) ++ for (i = 0; i < devinfo->shared.max_flowrings; i++) + flowrings[i] = &devinfo->shared.flowrings[i].commonring; + bus->msgbuf->flowrings = flowrings; + + bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset; + bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost; +- bus->msgbuf->nrof_flowrings = devinfo->shared.nrof_flowrings; ++ bus->msgbuf->max_flowrings = devinfo->shared.max_flowrings; + + init_waitqueue_head(&devinfo->mbdata_resp_wait); + diff --git a/package/kernel/mac80211/patches/357-0002-brcmfmac-add-support-for-43341-chip.patch b/package/kernel/mac80211/patches/357-0002-brcmfmac-add-support-for-43341-chip.patch new file mode 100644 index 0000000000..edd7de33c7 --- /dev/null +++ b/package/kernel/mac80211/patches/357-0002-brcmfmac-add-support-for-43341-chip.patch @@ -0,0 +1,39 @@ +From dc630dc5c753ccba97ce174f9c2894f802f9bd93 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:21 +0000 +Subject: [PATCH] brcmfmac: add support for 43341 chip + +This chip was already supported, but seems a device came up giving +a different chip identifier. So adding that effectively mapping to +the same firmware file as for 43340 chip. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 + + drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -621,6 +621,7 @@ static struct brcmf_firmware_mapping brc + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), ++ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -36,6 +36,7 @@ + #define BRCM_CC_4330_CHIP_ID 0x4330 + #define BRCM_CC_4334_CHIP_ID 0x4334 + #define BRCM_CC_43340_CHIP_ID 43340 ++#define BRCM_CC_43341_CHIP_ID 43341 + #define BRCM_CC_43362_CHIP_ID 43362 + #define BRCM_CC_4335_CHIP_ID 0x4335 + #define BRCM_CC_4339_CHIP_ID 0x4339 diff --git a/package/kernel/mac80211/patches/357-0003-brcmfmac-move-pno-helper-functions-in-separate-sourc.patch b/package/kernel/mac80211/patches/357-0003-brcmfmac-move-pno-helper-functions-in-separate-sourc.patch new file mode 100644 index 0000000000..94f2e6b972 --- /dev/null +++ b/package/kernel/mac80211/patches/357-0003-brcmfmac-move-pno-helper-functions-in-separate-sourc.patch @@ -0,0 +1,319 @@ +From ac55136f43d3336c7b40238b779c404008229929 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:22 +0000 +Subject: [PATCH] brcmfmac: move pno helper functions in separate source file + +Introducing new source file for pno related functionality. Moving +existing pno functions. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/Makefile | 3 +- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 93 ++----------------- + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 100 +++++++++++++++++++++ + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 40 +++++++++ + 4 files changed, 150 insertions(+), 86 deletions(-) + create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c + create mode 100644 drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile +@@ -35,7 +35,8 @@ brcmfmac-objs += \ + firmware.o \ + feature.o \ + btcoex.o \ +- vendor.o ++ vendor.o \ ++ pno.o + brcmfmac-$(CPTCFG_BRCMFMAC_PROTO_BCDC) += \ + bcdc.o + brcmfmac-$(CPTCFG_BRCMFMAC_PROTO_MSGBUF) += \ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -32,6 +32,7 @@ + #include "fwil_types.h" + #include "p2p.h" + #include "btcoex.h" ++#include "pno.h" + #include "cfg80211.h" + #include "feature.h" + #include "fwil.h" +@@ -41,16 +42,6 @@ + #include "common.h" + + #define BRCMF_SCAN_IE_LEN_MAX 2048 +-#define BRCMF_PNO_VERSION 2 +-#define BRCMF_PNO_TIME 30 +-#define BRCMF_PNO_REPEAT 4 +-#define BRCMF_PNO_FREQ_EXPO_MAX 3 +-#define BRCMF_PNO_MAX_PFN_COUNT 16 +-#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 +-#define BRCMF_PNO_HIDDEN_BIT 2 +-#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF +-#define BRCMF_PNO_SCAN_COMPLETE 1 +-#define BRCMF_PNO_SCAN_INCOMPLETE 0 + + #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ + #define WPA_OUI_TYPE 1 +@@ -3323,76 +3314,6 @@ out_err: + return err; + } + +-static int brcmf_dev_pno_clean(struct net_device *ndev) +-{ +- int ret; +- +- /* Disable pfn */ +- ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0); +- if (ret == 0) { +- /* clear pfn */ +- ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear", +- NULL, 0); +- } +- if (ret < 0) +- brcmf_err("failed code %d\n", ret); +- +- return ret; +-} +- +-static int brcmf_dev_pno_config(struct brcmf_if *ifp, +- struct cfg80211_sched_scan_request *request) +-{ +- struct brcmf_pno_param_le pfn_param; +- struct brcmf_pno_macaddr_le pfn_mac; +- s32 err; +- u8 *mac_mask; +- int i; +- +- memset(&pfn_param, 0, sizeof(pfn_param)); +- pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); +- +- /* set extra pno params */ +- pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); +- pfn_param.repeat = BRCMF_PNO_REPEAT; +- pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; +- +- /* set up pno scan fr */ +- pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); +- +- err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, +- sizeof(pfn_param)); +- if (err) { +- brcmf_err("pfn_set failed, err=%d\n", err); +- return err; +- } +- +- /* Find out if mac randomization should be turned on */ +- if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) +- return 0; +- +- pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; +- pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC; +- +- memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN); +- mac_mask = request->mac_addr_mask; +- for (i = 0; i < ETH_ALEN; i++) { +- pfn_mac.mac[i] &= mac_mask[i]; +- pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]); +- } +- /* Clear multi bit */ +- pfn_mac.mac[0] &= 0xFE; +- /* Set locally administered */ +- pfn_mac.mac[0] |= 0x02; +- +- err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac, +- sizeof(pfn_mac)); +- if (err) +- brcmf_err("pfn_macaddr failed, err=%d\n", err); +- +- return err; +-} +- + static int + brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *ndev, +@@ -3436,15 +3357,16 @@ brcmf_cfg80211_sched_scan_start(struct w + + if (request->n_match_sets > 0) { + /* clean up everything */ +- ret = brcmf_dev_pno_clean(ndev); ++ ret = brcmf_pno_clean(ifp); + if (ret < 0) { + brcmf_err("failed error=%d\n", ret); + return ret; + } + + /* configure pno */ +- if (brcmf_dev_pno_config(ifp, request)) +- return -EINVAL; ++ ret = brcmf_pno_config(ifp, request); ++ if (ret < 0) ++ return ret; + + /* configure each match set */ + for (i = 0; i < request->n_match_sets; i++) { +@@ -3486,11 +3408,12 @@ static int brcmf_cfg80211_sched_scan_sto + struct net_device *ndev) + { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); ++ struct brcmf_if *ifp = netdev_priv(ndev); + + brcmf_dbg(SCAN, "enter\n"); +- brcmf_dev_pno_clean(ndev); ++ brcmf_pno_clean(ifp); + if (cfg->sched_escan) +- brcmf_notify_escan_complete(cfg, netdev_priv(ndev), true, true); ++ brcmf_notify_escan_complete(cfg, ifp, true, true); + return 0; + } + +--- /dev/null ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +@@ -0,0 +1,100 @@ ++/* ++ * Copyright (c) 2016 Broadcom ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#include ++#include ++ ++#include "core.h" ++#include "debug.h" ++#include "pno.h" ++#include "fwil.h" ++#include "fwil_types.h" ++ ++#define BRCMF_PNO_VERSION 2 ++#define BRCMF_PNO_TIME 30 ++#define BRCMF_PNO_REPEAT 4 ++#define BRCMF_PNO_FREQ_EXPO_MAX 3 ++#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 ++#define BRCMF_PNO_SCAN_INCOMPLETE 0 ++ ++int brcmf_pno_clean(struct brcmf_if *ifp) ++{ ++ int ret; ++ ++ /* Disable pfn */ ++ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0); ++ if (ret == 0) { ++ /* clear pfn */ ++ ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); ++ } ++ if (ret < 0) ++ brcmf_err("failed code %d\n", ret); ++ ++ return ret; ++} ++ ++int brcmf_pno_config(struct brcmf_if *ifp, ++ struct cfg80211_sched_scan_request *request) ++{ ++ struct brcmf_pno_param_le pfn_param; ++ struct brcmf_pno_macaddr_le pfn_mac; ++ s32 err; ++ u8 *mac_mask; ++ int i; ++ ++ memset(&pfn_param, 0, sizeof(pfn_param)); ++ pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); ++ ++ /* set extra pno params */ ++ pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); ++ pfn_param.repeat = BRCMF_PNO_REPEAT; ++ pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; ++ ++ /* set up pno scan fr */ ++ pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); ++ ++ err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, ++ sizeof(pfn_param)); ++ if (err) { ++ brcmf_err("pfn_set failed, err=%d\n", err); ++ return err; ++ } ++ ++ /* Find out if mac randomization should be turned on */ ++ if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) ++ return 0; ++ ++ pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; ++ pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC; ++ ++ memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN); ++ mac_mask = request->mac_addr_mask; ++ for (i = 0; i < ETH_ALEN; i++) { ++ pfn_mac.mac[i] &= mac_mask[i]; ++ pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]); ++ } ++ /* Clear multi bit */ ++ pfn_mac.mac[0] &= 0xFE; ++ /* Set locally administered */ ++ pfn_mac.mac[0] |= 0x02; ++ ++ err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac, ++ sizeof(pfn_mac)); ++ if (err) ++ brcmf_err("pfn_macaddr failed, err=%d\n", err); ++ ++ return err; ++} ++ +--- /dev/null ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (c) 2016 Broadcom ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION ++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++#ifndef _BRCMF_PNO_H ++#define _BRCMF_PNO_H ++ ++#define BRCMF_PNO_SCAN_COMPLETE 1 ++#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF ++#define BRCMF_PNO_HIDDEN_BIT 2 ++#define BRCMF_PNO_MAX_PFN_COUNT 16 ++ ++/** ++ * brcmf_pno_clean - disable and clear pno in firmware. ++ * ++ * @ifp: interface object used. ++ */ ++int brcmf_pno_clean(struct brcmf_if *ifp); ++ ++/** ++ * brcmf_pno_config - configure pno parameters. ++ * ++ * @ifp: interface object used. ++ * @request: scheduled scan parameters. ++ */ ++int brcmf_pno_config(struct brcmf_if *ifp, ++ struct cfg80211_sched_scan_request *request); ++ ++#endif /* _BRCMF_PNO_H */ diff --git a/package/kernel/mac80211/patches/357-0004-brcmfmac-fix-handling-ssids-in-.sched_scan_start-cal.patch b/package/kernel/mac80211/patches/357-0004-brcmfmac-fix-handling-ssids-in-.sched_scan_start-cal.patch new file mode 100644 index 0000000000..f1934af71c --- /dev/null +++ b/package/kernel/mac80211/patches/357-0004-brcmfmac-fix-handling-ssids-in-.sched_scan_start-cal.patch @@ -0,0 +1,221 @@ +From 3e2e86ab19c2a43953de30089c5411c580ddb5f7 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:23 +0000 +Subject: [PATCH] brcmfmac: fix handling ssids in .sched_scan_start() callback + +The ssids list in the scheduled scan request were not properly taken +into account when configuring in firmware. The hidden bit was set for +any ssid resulting in active scanning for all. Only set it for ssids +that are in the ssids list. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 103 ++++++++++----------- + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 18 ++++ + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 12 ++- + 3 files changed, 76 insertions(+), 57 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -3314,19 +3314,37 @@ out_err: + return err; + } + ++static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid, ++ struct cfg80211_sched_scan_request *req) ++{ ++ int i; ++ ++ if (!ssid || !req->ssids || !req->n_ssids) ++ return false; ++ ++ for (i = 0; i < req->n_ssids; i++) { ++ if (ssid->ssid_len == req->ssids[i].ssid_len) { ++ if (!strncmp(ssid->ssid, req->ssids[i].ssid, ++ ssid->ssid_len)) ++ return true; ++ } ++ } ++ return false; ++} ++ + static int + brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *ndev, +- struct cfg80211_sched_scan_request *request) ++ struct cfg80211_sched_scan_request *req) + { + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); +- struct brcmf_pno_net_param_le pfn; ++ struct cfg80211_ssid *ssid; + int i; + int ret = 0; + + brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", +- request->n_match_sets, request->n_ssids); ++ req->n_match_sets, req->n_ssids); + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { + brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); + return -EAGAIN; +@@ -3337,71 +3355,46 @@ brcmf_cfg80211_sched_scan_start(struct w + return -EAGAIN; + } + +- if (!request->n_ssids || !request->n_match_sets) { +- brcmf_dbg(SCAN, "Invalid sched scan req!! n_ssids:%d\n", +- request->n_ssids); ++ if (req->n_match_sets <= 0) { ++ brcmf_dbg(SCAN, "invalid number of matchsets specified: %d\n", ++ req->n_match_sets); + return -EINVAL; + } + +- if (request->n_ssids > 0) { +- for (i = 0; i < request->n_ssids; i++) { +- /* Active scan req for ssids */ +- brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n", +- request->ssids[i].ssid); +- +- /* match_set ssids is a supert set of n_ssid list, +- * so we need not add these set separately. +- */ +- } ++ /* clean up everything */ ++ ret = brcmf_pno_clean(ifp); ++ if (ret < 0) { ++ brcmf_err("failed error=%d\n", ret); ++ return ret; + } + +- if (request->n_match_sets > 0) { +- /* clean up everything */ +- ret = brcmf_pno_clean(ifp); +- if (ret < 0) { +- brcmf_err("failed error=%d\n", ret); +- return ret; ++ /* configure pno */ ++ ret = brcmf_pno_config(ifp, req); ++ if (ret < 0) ++ return ret; ++ ++ /* configure each match set */ ++ for (i = 0; i < req->n_match_sets; i++) { ++ ++ ssid = &req->match_sets[i].ssid; ++ ++ if (!ssid->ssid_len) { ++ brcmf_err("skip broadcast ssid\n"); ++ continue; + } + +- /* configure pno */ +- ret = brcmf_pno_config(ifp, request); ++ ret = brcmf_pno_add_ssid(ifp, ssid, ++ brcmf_is_ssid_active(ssid, req)); + if (ret < 0) +- return ret; +- +- /* configure each match set */ +- for (i = 0; i < request->n_match_sets; i++) { +- struct cfg80211_ssid *ssid; +- u32 ssid_len; +- +- ssid = &request->match_sets[i].ssid; +- ssid_len = ssid->ssid_len; +- +- if (!ssid_len) { +- brcmf_err("skip broadcast ssid\n"); +- continue; +- } +- pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN); +- pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY); +- pfn.wsec = cpu_to_le32(0); +- pfn.infra = cpu_to_le32(1); +- pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); +- pfn.ssid.SSID_len = cpu_to_le32(ssid_len); +- memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len); +- ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, +- sizeof(pfn)); + brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n", + ret == 0 ? "set" : "failed", ssid->ssid); +- } +- /* Enable the PNO */ +- if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) { +- brcmf_err("PNO enable failed!! ret=%d\n", ret); +- return -EINVAL; +- } +- } else { +- return -EINVAL; + } ++ /* Enable the PNO */ ++ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1); ++ if (ret < 0) ++ brcmf_err("PNO enable failed!! ret=%d\n", ret); + +- return 0; ++ return ret; + } + + static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +@@ -28,6 +28,8 @@ + #define BRCMF_PNO_FREQ_EXPO_MAX 3 + #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 + #define BRCMF_PNO_SCAN_INCOMPLETE 0 ++#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF ++#define BRCMF_PNO_HIDDEN_BIT 2 + + int brcmf_pno_clean(struct brcmf_if *ifp) + { +@@ -98,3 +100,19 @@ int brcmf_pno_config(struct brcmf_if *if + return err; + } + ++int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, ++ bool active) ++{ ++ struct brcmf_pno_net_param_le pfn; ++ ++ pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN); ++ pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY); ++ pfn.wsec = cpu_to_le32(0); ++ pfn.infra = cpu_to_le32(1); ++ if (active) ++ pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); ++ pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len); ++ memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len); ++ return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn)); ++} ++ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +@@ -17,8 +17,6 @@ + #define _BRCMF_PNO_H + + #define BRCMF_PNO_SCAN_COMPLETE 1 +-#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF +-#define BRCMF_PNO_HIDDEN_BIT 2 + #define BRCMF_PNO_MAX_PFN_COUNT 16 + + /** +@@ -37,4 +35,14 @@ int brcmf_pno_clean(struct brcmf_if *ifp + int brcmf_pno_config(struct brcmf_if *ifp, + struct cfg80211_sched_scan_request *request); + ++/** ++ * brcmf_pno_add_ssid - add ssid for pno in firmware. ++ * ++ * @ifp: interface object used. ++ * @ssid: ssid information. ++ * @active: indicate this ssid needs to be actively probed. ++ */ ++int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, ++ bool active); ++ + #endif /* _BRCMF_PNO_H */ diff --git a/package/kernel/mac80211/patches/357-0005-brcmfmac-change-prototype-for-brcmf_do_escan.patch b/package/kernel/mac80211/patches/357-0005-brcmfmac-change-prototype-for-brcmf_do_escan.patch new file mode 100644 index 0000000000..07b353ba3b --- /dev/null +++ b/package/kernel/mac80211/patches/357-0005-brcmfmac-change-prototype-for-brcmf_do_escan.patch @@ -0,0 +1,58 @@ +From ab5981c830339b945ddbedc314567a9e5f506d72 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:24 +0000 +Subject: [PATCH] brcmfmac: change prototype for brcmf_do_escan() + +Reduce the number of parameters as the removed ones can be obtained +through struct brcmf_if parameter. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1080,9 +1080,9 @@ exit: + } + + static s32 +-brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, +- struct brcmf_if *ifp, struct cfg80211_scan_request *request) ++brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request) + { ++ struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + s32 err; + u32 passive_scan; + struct brcmf_scan_results *results; +@@ -1090,7 +1090,7 @@ brcmf_do_escan(struct brcmf_cfg80211_inf + + brcmf_dbg(SCAN, "Enter\n"); + escan->ifp = ifp; +- escan->wiphy = wiphy; ++ escan->wiphy = cfg->wiphy; + escan->escan_state = WL_ESCAN_STATE_SCANNING; + passive_scan = cfg->active_scan ? 0 : 1; + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, +@@ -1170,7 +1170,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy + if (err) + goto scan_out; + +- err = brcmf_do_escan(cfg, wiphy, vif->ifp, request); ++ err = brcmf_do_escan(vif->ifp, request); + if (err) + goto scan_out; + } else { +@@ -3289,7 +3289,7 @@ brcmf_notify_sched_scan_results(struct b + + set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); + cfg->escan_info.run = brcmf_run_escan; +- err = brcmf_do_escan(cfg, wiphy, ifp, request); ++ err = brcmf_do_escan(ifp, request); + if (err) { + clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); + goto out_err; diff --git a/package/kernel/mac80211/patches/357-0006-brcmfmac-make-internal-escan-more-generic.patch b/package/kernel/mac80211/patches/357-0006-brcmfmac-make-internal-escan-more-generic.patch new file mode 100644 index 0000000000..84a69f0739 --- /dev/null +++ b/package/kernel/mac80211/patches/357-0006-brcmfmac-make-internal-escan-more-generic.patch @@ -0,0 +1,306 @@ +From fa85b30a908455ff25def3a5f319aad272ef4862 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:25 +0000 +Subject: [PATCH] brcmfmac: make internal escan more generic + +For scheduled scan we initiate an escan in firmware to obtain more +info missing from the scheduled scan notification we get from firmware. +For upcoming functionality this is also required so make it a bit +more generic. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 187 ++++++++++++--------- + .../broadcom/brcm80211/brcmfmac/cfg80211.h | 4 +- + 2 files changed, 109 insertions(+), 82 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -757,12 +757,12 @@ s32 brcmf_notify_escan_complete(struct b + brcmf_scan_config_mpc(ifp, 1); + + /* +- * e-scan can be initiated by scheduled scan ++ * e-scan can be initiated internally + * which takes precedence. + */ +- if (cfg->sched_escan) { ++ if (cfg->internal_escan) { + brcmf_dbg(SCAN, "scheduled scan completed\n"); +- cfg->sched_escan = false; ++ cfg->internal_escan = false; + if (!aborted) + cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); + } else if (scan_request) { +@@ -3013,7 +3013,7 @@ void brcmf_abort_scanning(struct brcmf_c + struct escan_info *escan = &cfg->escan_info; + + set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); +- if (cfg->scan_request) { ++ if (cfg->internal_escan || cfg->scan_request) { + escan->escan_state = WL_ESCAN_STATE_IDLE; + brcmf_notify_escan_complete(cfg, escan->ifp, true, true); + } +@@ -3036,7 +3036,7 @@ static void brcmf_escan_timeout(unsigned + struct brcmf_cfg80211_info *cfg = + (struct brcmf_cfg80211_info *)data; + +- if (cfg->scan_request) { ++ if (cfg->internal_escan || cfg->scan_request) { + brcmf_err("timer expired\n"); + schedule_work(&cfg->escan_timeout_work); + } +@@ -3119,7 +3119,7 @@ brcmf_cfg80211_escan_handler(struct brcm + if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le)) + goto exit; + +- if (!cfg->scan_request) { ++ if (!cfg->internal_escan && !cfg->scan_request) { + brcmf_dbg(SCAN, "result without cfg80211 request\n"); + goto exit; + } +@@ -3165,7 +3165,7 @@ brcmf_cfg80211_escan_handler(struct brcm + cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; + if (brcmf_p2p_scan_finding_common_channel(cfg, NULL)) + goto exit; +- if (cfg->scan_request) { ++ if (cfg->internal_escan || cfg->scan_request) { + brcmf_inform_bss(cfg); + aborted = status != BRCMF_E_STATUS_SUCCESS; + brcmf_notify_escan_complete(cfg, ifp, aborted, false); +@@ -3190,6 +3190,73 @@ static void brcmf_init_escan(struct brcm + brcmf_cfg80211_escan_timeout_worker); + } + ++static struct cfg80211_scan_request * ++brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) { ++ struct cfg80211_scan_request *req; ++ size_t req_size; ++ ++ req_size = sizeof(*req) + ++ n_netinfo * sizeof(req->channels[0]) + ++ n_netinfo * sizeof(*req->ssids); ++ ++ req = kzalloc(req_size, GFP_KERNEL); ++ if (req) { ++ req->wiphy = wiphy; ++ req->ssids = (void *)(&req->channels[0]) + ++ n_netinfo * sizeof(req->channels[0]); ++ } ++ return req; ++} ++ ++static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req, ++ u8 *ssid, u8 ssid_len, u8 channel) ++{ ++ struct ieee80211_channel *chan; ++ enum nl80211_band band; ++ int freq; ++ ++ if (channel <= CH_MAX_2G_CHANNEL) ++ band = NL80211_BAND_2GHZ; ++ else ++ band = NL80211_BAND_5GHZ; ++ ++ freq = ieee80211_channel_to_frequency(channel, band); ++ if (!freq) ++ return -EINVAL; ++ ++ chan = ieee80211_get_channel(req->wiphy, freq); ++ if (!chan) ++ return -EINVAL; ++ ++ req->channels[req->n_channels++] = chan; ++ memcpy(req->ssids[req->n_ssids].ssid, ssid, ssid_len); ++ req->ssids[req->n_ssids++].ssid_len = ssid_len; ++ ++ return 0; ++} ++ ++static int brcmf_start_internal_escan(struct brcmf_if *ifp, ++ struct cfg80211_scan_request *request) ++{ ++ struct brcmf_cfg80211_info *cfg = ifp->drvr->config; ++ int err; ++ ++ if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { ++ /* Abort any on-going scan */ ++ brcmf_abort_scanning(cfg); ++ } ++ ++ set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); ++ cfg->escan_info.run = brcmf_run_escan; ++ err = brcmf_do_escan(ifp, request); ++ if (err) { ++ clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); ++ return err; ++ } ++ cfg->internal_escan = true; ++ return 0; ++} ++ + /* PFN result doesn't have all the info which are required by the supplicant + * (For e.g IEs) Do a target Escan so that sched scan results are reported + * via wl_inform_single_bss in the required format. Escan does require the +@@ -3203,12 +3270,8 @@ brcmf_notify_sched_scan_results(struct b + struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + struct brcmf_pno_net_info_le *netinfo, *netinfo_start; + struct cfg80211_scan_request *request = NULL; +- struct cfg80211_ssid *ssid = NULL; +- struct ieee80211_channel *channel = NULL; + struct wiphy *wiphy = cfg_to_wiphy(cfg); +- int err = 0; +- int channel_req = 0; +- int band = 0; ++ int i, err = 0; + struct brcmf_pno_scanresults_le *pfn_result; + u32 result_count; + u32 status; +@@ -3234,83 +3297,47 @@ brcmf_notify_sched_scan_results(struct b + */ + WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE); + brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count); +- if (result_count > 0) { +- int i; +- +- request = kzalloc(sizeof(*request), GFP_KERNEL); +- ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL); +- channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL); +- if (!request || !ssid || !channel) { +- err = -ENOMEM; +- goto out_err; +- } ++ if (!result_count) { ++ brcmf_err("FALSE PNO Event. (pfn_count == 0)\n"); ++ goto out_err; ++ } ++ request = brcmf_alloc_internal_escan_request(wiphy, ++ result_count); ++ if (!request) { ++ err = -ENOMEM; ++ goto out_err; ++ } + +- request->wiphy = wiphy; +- data += sizeof(struct brcmf_pno_scanresults_le); +- netinfo_start = (struct brcmf_pno_net_info_le *)data; +- +- for (i = 0; i < result_count; i++) { +- netinfo = &netinfo_start[i]; +- if (!netinfo) { +- brcmf_err("Invalid netinfo ptr. index: %d\n", +- i); +- err = -EINVAL; +- goto out_err; +- } ++ data += sizeof(struct brcmf_pno_scanresults_le); ++ netinfo_start = (struct brcmf_pno_net_info_le *)data; + +- brcmf_dbg(SCAN, "SSID:%s Channel:%d\n", +- netinfo->SSID, netinfo->channel); +- memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len); +- ssid[i].ssid_len = netinfo->SSID_len; +- request->n_ssids++; +- +- channel_req = netinfo->channel; +- if (channel_req <= CH_MAX_2G_CHANNEL) +- band = NL80211_BAND_2GHZ; +- else +- band = NL80211_BAND_5GHZ; +- channel[i].center_freq = +- ieee80211_channel_to_frequency(channel_req, +- band); +- channel[i].band = band; +- channel[i].flags |= IEEE80211_CHAN_NO_HT40; +- request->channels[i] = &channel[i]; +- request->n_channels++; +- } +- +- /* assign parsed ssid array */ +- if (request->n_ssids) +- request->ssids = &ssid[0]; +- +- if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { +- /* Abort any on-going scan */ +- brcmf_abort_scanning(cfg); ++ for (i = 0; i < result_count; i++) { ++ netinfo = &netinfo_start[i]; ++ if (!netinfo) { ++ brcmf_err("Invalid netinfo ptr. index: %d\n", ++ i); ++ err = -EINVAL; ++ goto out_err; + } + +- set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); +- cfg->escan_info.run = brcmf_run_escan; +- err = brcmf_do_escan(ifp, request); +- if (err) { +- clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); ++ brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n", ++ netinfo->SSID, netinfo->channel); ++ err = brcmf_internal_escan_add_info(request, ++ netinfo->SSID, ++ netinfo->SSID_len, ++ netinfo->channel); ++ if (err) + goto out_err; +- } +- cfg->sched_escan = true; +- cfg->scan_request = request; +- } else { +- brcmf_err("FALSE PNO Event. (pfn_count == 0)\n"); +- goto out_err; + } + +- kfree(ssid); +- kfree(channel); +- kfree(request); +- return 0; ++ err = brcmf_start_internal_escan(ifp, request); ++ if (!err) ++ goto free_req; + + out_err: +- kfree(ssid); +- kfree(channel); +- kfree(request); + cfg80211_sched_scan_stopped(wiphy); ++free_req: ++ kfree(request); + return err; + } + +@@ -3405,7 +3432,7 @@ static int brcmf_cfg80211_sched_scan_sto + + brcmf_dbg(SCAN, "enter\n"); + brcmf_pno_clean(ifp); +- if (cfg->sched_escan) ++ if (cfg->internal_escan) + brcmf_notify_escan_complete(cfg, ifp, true, true); + return 0; + } +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +@@ -271,7 +271,7 @@ struct brcmf_cfg80211_wowl { + * @pub: common driver information. + * @channel: current channel. + * @active_scan: current scan mode. +- * @sched_escan: e-scan for scheduled scan support running. ++ * @internal_escan: indicates internally initiated e-scan is running. + * @ibss_starter: indicates this sta is ibss starter. + * @pwr_save: indicate whether dongle to support power save mode. + * @dongle_up: indicate whether dongle up or not. +@@ -303,7 +303,7 @@ struct brcmf_cfg80211_info { + struct brcmf_pub *pub; + u32 channel; + bool active_scan; +- bool sched_escan; ++ bool internal_escan; + bool ibss_starter; + bool pwr_save; + bool dongle_up; diff --git a/package/kernel/mac80211/patches/357-0007-brcmfmac-split-up-brcmf_pno_config-function.patch b/package/kernel/mac80211/patches/357-0007-brcmfmac-split-up-brcmf_pno_config-function.patch new file mode 100644 index 0000000000..f81523aa01 --- /dev/null +++ b/package/kernel/mac80211/patches/357-0007-brcmfmac-split-up-brcmf_pno_config-function.patch @@ -0,0 +1,176 @@ +From fca6cb2f059e51dec3fcf3589a5abbbcce5b4043 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:26 +0000 +Subject: [PATCH] brcmfmac: split up brcmf_pno_config() function + +The brcmf_pno_config() function handles two configurations in +firmware. Split it and have caller sort out what is needed. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 11 +++- + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 60 ++++++++++++++++------ + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 17 ++++-- + 3 files changed, 68 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -42,6 +42,7 @@ + #include "common.h" + + #define BRCMF_SCAN_IE_LEN_MAX 2048 ++#define BRCMF_SCHED_SCAN_PERIOD 30 + + #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ + #define WPA_OUI_TYPE 1 +@@ -3396,10 +3397,18 @@ brcmf_cfg80211_sched_scan_start(struct w + } + + /* configure pno */ +- ret = brcmf_pno_config(ifp, req); ++ ret = brcmf_pno_config(ifp, BRCMF_SCHED_SCAN_PERIOD, 0, 0); + if (ret < 0) + return ret; + ++ /* configure random mac */ ++ if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { ++ ret = brcmf_pno_set_random(ifp, req->mac_addr, ++ req->mac_addr_mask); ++ if (ret < 0) ++ return ret; ++ } ++ + /* configure each match set */ + for (i = 0; i < req->n_match_sets; i++) { + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +@@ -23,10 +23,12 @@ + #include "fwil_types.h" + + #define BRCMF_PNO_VERSION 2 +-#define BRCMF_PNO_TIME 30 + #define BRCMF_PNO_REPEAT 4 + #define BRCMF_PNO_FREQ_EXPO_MAX 3 ++#define BRCMF_PNO_IMMEDIATE_SCAN_BIT 3 ++#define BRCMF_PNO_ENABLE_BD_SCAN_BIT 5 + #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6 ++#define BRCMF_PNO_REPORT_SEPARATELY_BIT 11 + #define BRCMF_PNO_SCAN_INCOMPLETE 0 + #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF + #define BRCMF_PNO_HIDDEN_BIT 2 +@@ -47,42 +49,68 @@ int brcmf_pno_clean(struct brcmf_if *ifp + return ret; + } + +-int brcmf_pno_config(struct brcmf_if *ifp, +- struct cfg80211_sched_scan_request *request) ++int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, ++ u32 mscan, u32 bestn) + { + struct brcmf_pno_param_le pfn_param; +- struct brcmf_pno_macaddr_le pfn_mac; ++ u16 flags; ++ u32 pfnmem; + s32 err; +- u8 *mac_mask; +- int i; + + memset(&pfn_param, 0, sizeof(pfn_param)); + pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); + + /* set extra pno params */ +- pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); ++ flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) | ++ BIT(BRCMF_PNO_REPORT_SEPARATELY_BIT) | ++ BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT); + pfn_param.repeat = BRCMF_PNO_REPEAT; + pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; + + /* set up pno scan fr */ +- pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); ++ pfn_param.scan_freq = cpu_to_le32(scan_freq); ++ ++ if (mscan) { ++ pfnmem = bestn; + ++ /* set bestn in firmware */ ++ err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem); ++ if (err < 0) { ++ brcmf_err("failed to set pfnmem\n"); ++ goto exit; ++ } ++ /* get max mscan which the firmware supports */ ++ err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem); ++ if (err < 0) { ++ brcmf_err("failed to get pfnmem\n"); ++ goto exit; ++ } ++ mscan = min_t(u32, mscan, pfnmem); ++ pfn_param.mscan = mscan; ++ pfn_param.bestn = bestn; ++ flags |= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT); ++ brcmf_dbg(INFO, "mscan=%d, bestn=%d\n", mscan, bestn); ++ } ++ ++ pfn_param.flags = cpu_to_le16(flags); + err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param, + sizeof(pfn_param)); +- if (err) { ++ if (err) + brcmf_err("pfn_set failed, err=%d\n", err); +- return err; +- } + +- /* Find out if mac randomization should be turned on */ +- if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) +- return 0; ++exit: ++ return err; ++} ++ ++int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask) ++{ ++ struct brcmf_pno_macaddr_le pfn_mac; ++ int err, i; + + pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER; + pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC; + +- memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN); +- mac_mask = request->mac_addr_mask; ++ memcpy(pfn_mac.mac, mac_addr, ETH_ALEN); + for (i = 0; i < ETH_ALEN; i++) { + pfn_mac.mac[i] &= mac_mask[i]; + pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +@@ -30,10 +30,21 @@ int brcmf_pno_clean(struct brcmf_if *ifp + * brcmf_pno_config - configure pno parameters. + * + * @ifp: interface object used. +- * @request: scheduled scan parameters. ++ * @scan_freq: scan frequency period in seconds. ++ * @mscan: maximum number of scans stored in firmware. ++ * @bestn: maximum number of APs per scan stored in firmware. + */ +-int brcmf_pno_config(struct brcmf_if *ifp, +- struct cfg80211_sched_scan_request *request); ++int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, ++ u32 mscan, u32 bestn); ++ ++/** ++ * brcmf_pno_set_random - setup randomisation mac address for pno. ++ * ++ * @ifp: interface object used. ++ * @mac_addr: MAC address used with randomisation. ++ * @mac_mask: MAC address mask used for randomisation. ++ */ ++int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask); + + /** + * brcmf_pno_add_ssid - add ssid for pno in firmware. diff --git a/package/kernel/mac80211/patches/357-0008-brcmfmac-move-scheduled-scan-activation-to-pno-sourc.patch b/package/kernel/mac80211/patches/357-0008-brcmfmac-move-scheduled-scan-activation-to-pno-sourc.patch new file mode 100644 index 0000000000..6dcea2832a --- /dev/null +++ b/package/kernel/mac80211/patches/357-0008-brcmfmac-move-scheduled-scan-activation-to-pno-sourc.patch @@ -0,0 +1,292 @@ +From 3e48611d31dd333be01576902f2dc11adefc9a06 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:27 +0000 +Subject: [PATCH] brcmfmac: move scheduled scan activation to pno source file + +Rework .sched_scan_start() callback moving actual configuration of +the device in pno source file. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 65 +----------- + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 110 +++++++++++++++++---- + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 29 +----- + 3 files changed, 94 insertions(+), 110 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -42,7 +42,6 @@ + #include "common.h" + + #define BRCMF_SCAN_IE_LEN_MAX 2048 +-#define BRCMF_SCHED_SCAN_PERIOD 30 + + #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ + #define WPA_OUI_TYPE 1 +@@ -3342,24 +3341,6 @@ free_req: + return err; + } + +-static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid, +- struct cfg80211_sched_scan_request *req) +-{ +- int i; +- +- if (!ssid || !req->ssids || !req->n_ssids) +- return false; +- +- for (i = 0; i < req->n_ssids; i++) { +- if (ssid->ssid_len == req->ssids[i].ssid_len) { +- if (!strncmp(ssid->ssid, req->ssids[i].ssid, +- ssid->ssid_len)) +- return true; +- } +- } +- return false; +-} +- + static int + brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *ndev, +@@ -3367,9 +3348,6 @@ brcmf_cfg80211_sched_scan_start(struct w + { + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); +- struct cfg80211_ssid *ssid; +- int i; +- int ret = 0; + + brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", + req->n_match_sets, req->n_ssids); +@@ -3389,48 +3367,7 @@ brcmf_cfg80211_sched_scan_start(struct w + return -EINVAL; + } + +- /* clean up everything */ +- ret = brcmf_pno_clean(ifp); +- if (ret < 0) { +- brcmf_err("failed error=%d\n", ret); +- return ret; +- } +- +- /* configure pno */ +- ret = brcmf_pno_config(ifp, BRCMF_SCHED_SCAN_PERIOD, 0, 0); +- if (ret < 0) +- return ret; +- +- /* configure random mac */ +- if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { +- ret = brcmf_pno_set_random(ifp, req->mac_addr, +- req->mac_addr_mask); +- if (ret < 0) +- return ret; +- } +- +- /* configure each match set */ +- for (i = 0; i < req->n_match_sets; i++) { +- +- ssid = &req->match_sets[i].ssid; +- +- if (!ssid->ssid_len) { +- brcmf_err("skip broadcast ssid\n"); +- continue; +- } +- +- ret = brcmf_pno_add_ssid(ifp, ssid, +- brcmf_is_ssid_active(ssid, req)); +- if (ret < 0) +- brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n", +- ret == 0 ? "set" : "failed", ssid->ssid); +- } +- /* Enable the PNO */ +- ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1); +- if (ret < 0) +- brcmf_err("PNO enable failed!! ret=%d\n", ret); +- +- return ret; ++ return brcmf_pno_start_sched_scan(ifp, req); + } + + static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +@@ -32,25 +32,10 @@ + #define BRCMF_PNO_SCAN_INCOMPLETE 0 + #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF + #define BRCMF_PNO_HIDDEN_BIT 2 ++#define BRCMF_PNO_SCHED_SCAN_PERIOD 30 + +-int brcmf_pno_clean(struct brcmf_if *ifp) +-{ +- int ret; +- +- /* Disable pfn */ +- ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0); +- if (ret == 0) { +- /* clear pfn */ +- ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); +- } +- if (ret < 0) +- brcmf_err("failed code %d\n", ret); +- +- return ret; +-} +- +-int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, +- u32 mscan, u32 bestn) ++static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, ++ u32 mscan, u32 bestn) + { + struct brcmf_pno_param_le pfn_param; + u16 flags; +@@ -102,7 +87,8 @@ exit: + return err; + } + +-int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask) ++static int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, ++ u8 *mac_mask) + { + struct brcmf_pno_macaddr_le pfn_mac; + int err, i; +@@ -128,8 +114,8 @@ int brcmf_pno_set_random(struct brcmf_if + return err; + } + +-int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, +- bool active) ++static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, ++ bool active) + { + struct brcmf_pno_net_param_le pfn; + +@@ -144,3 +130,85 @@ int brcmf_pno_add_ssid(struct brcmf_if * + return brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn)); + } + ++static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid, ++ struct cfg80211_sched_scan_request *req) ++{ ++ int i; ++ ++ if (!ssid || !req->ssids || !req->n_ssids) ++ return false; ++ ++ for (i = 0; i < req->n_ssids; i++) { ++ if (ssid->ssid_len == req->ssids[i].ssid_len) { ++ if (!strncmp(ssid->ssid, req->ssids[i].ssid, ++ ssid->ssid_len)) ++ return true; ++ } ++ } ++ return false; ++} ++ ++int brcmf_pno_clean(struct brcmf_if *ifp) ++{ ++ int ret; ++ ++ /* Disable pfn */ ++ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0); ++ if (ret == 0) { ++ /* clear pfn */ ++ ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); ++ } ++ if (ret < 0) ++ brcmf_err("failed code %d\n", ret); ++ ++ return ret; ++} ++ ++int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, ++ struct cfg80211_sched_scan_request *req) ++{ ++ struct cfg80211_ssid *ssid; ++ int i, ret; ++ ++ /* clean up everything */ ++ ret = brcmf_pno_clean(ifp); ++ if (ret < 0) { ++ brcmf_err("failed error=%d\n", ret); ++ return ret; ++ } ++ ++ /* configure pno */ ++ ret = brcmf_pno_config(ifp, BRCMF_PNO_SCHED_SCAN_PERIOD, 0, 0); ++ if (ret < 0) ++ return ret; ++ ++ /* configure random mac */ ++ if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { ++ ret = brcmf_pno_set_random(ifp, req->mac_addr, ++ req->mac_addr_mask); ++ if (ret < 0) ++ return ret; ++ } ++ ++ /* configure each match set */ ++ for (i = 0; i < req->n_match_sets; i++) { ++ ssid = &req->match_sets[i].ssid; ++ if (!ssid->ssid_len) { ++ brcmf_err("skip broadcast ssid\n"); ++ continue; ++ } ++ ++ ret = brcmf_pno_add_ssid(ifp, ssid, ++ brcmf_is_ssid_active(ssid, req)); ++ if (ret < 0) ++ brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n", ++ ret == 0 ? "set" : "failed", ssid->ssid); ++ } ++ /* Enable the PNO */ ++ ret = brcmf_fil_iovar_int_set(ifp, "pfn", 1); ++ if (ret < 0) ++ brcmf_err("PNO enable failed!! ret=%d\n", ret); ++ ++ return ret; ++} ++ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +@@ -27,33 +27,12 @@ + int brcmf_pno_clean(struct brcmf_if *ifp); + + /** +- * brcmf_pno_config - configure pno parameters. ++ * brcmf_pno_start_sched_scan - initiate scheduled scan on device. + * + * @ifp: interface object used. +- * @scan_freq: scan frequency period in seconds. +- * @mscan: maximum number of scans stored in firmware. +- * @bestn: maximum number of APs per scan stored in firmware. ++ * @req: configuration parameters for scheduled scan. + */ +-int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, +- u32 mscan, u32 bestn); +- +-/** +- * brcmf_pno_set_random - setup randomisation mac address for pno. +- * +- * @ifp: interface object used. +- * @mac_addr: MAC address used with randomisation. +- * @mac_mask: MAC address mask used for randomisation. +- */ +-int brcmf_pno_set_random(struct brcmf_if *ifp, u8 *mac_addr, u8 *mac_mask); +- +-/** +- * brcmf_pno_add_ssid - add ssid for pno in firmware. +- * +- * @ifp: interface object used. +- * @ssid: ssid information. +- * @active: indicate this ssid needs to be actively probed. +- */ +-int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid, +- bool active); ++int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, ++ struct cfg80211_sched_scan_request *req); + + #endif /* _BRCMF_PNO_H */ diff --git a/package/kernel/mac80211/patches/357-0009-brcmfmac-use-provided-channels-for-scheduled-scan.patch b/package/kernel/mac80211/patches/357-0009-brcmfmac-use-provided-channels-for-scheduled-scan.patch new file mode 100644 index 0000000000..fae844c02a --- /dev/null +++ b/package/kernel/mac80211/patches/357-0009-brcmfmac-use-provided-channels-for-scheduled-scan.patch @@ -0,0 +1,111 @@ +From 331e789443618ca9cc3ed48ada4e670225cca036 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:28 +0000 +Subject: [PATCH] brcmfmac: use provided channels for scheduled scan + +User-space can provide list of channels in the schedule scan request. +This was ignored so all channels supported and allowed by the device +were used. This patch configures the device to use the channels as +listed in the request. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 16 +++++++++++++ + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 26 +++++++++++++++++++++- + 2 files changed, 41 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +@@ -131,6 +131,7 @@ + #define BRCMF_TXBF_MU_BFR_CAP BIT(1) + + #define BRCMF_MAXPMKID 16 /* max # PMKID cache entries */ ++#define BRCMF_NUMCHANNELS 64 + + #define BRCMF_PFN_MACADDR_CFG_VER 1 + #define BRCMF_PFN_MAC_OUI_ONLY BIT(0) +@@ -719,6 +720,21 @@ struct brcmf_pno_param_le { + }; + + /** ++ * struct brcmf_pno_config_le - PNO channel configuration. ++ * ++ * @reporttype: determines what is reported. ++ * @channel_num: number of channels specified in @channel_list. ++ * @channel_list: channels to use in PNO scan. ++ * @flags: reserved. ++ */ ++struct brcmf_pno_config_le { ++ __le32 reporttype; ++ __le32 channel_num; ++ __le16 channel_list[BRCMF_NUMCHANNELS]; ++ __le32 flags; ++}; ++ ++/** + * struct brcmf_pno_net_param_le - scan parameters per preferred network. + * + * @ssid: ssid name and its length. +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +@@ -18,9 +18,10 @@ + + #include "core.h" + #include "debug.h" +-#include "pno.h" + #include "fwil.h" + #include "fwil_types.h" ++#include "cfg80211.h" ++#include "pno.h" + + #define BRCMF_PNO_VERSION 2 + #define BRCMF_PNO_REPEAT 4 +@@ -34,6 +35,15 @@ + #define BRCMF_PNO_HIDDEN_BIT 2 + #define BRCMF_PNO_SCHED_SCAN_PERIOD 30 + ++static int brcmf_pno_channel_config(struct brcmf_if *ifp, ++ struct brcmf_pno_config_le *cfg) ++{ ++ cfg->reporttype = 0; ++ cfg->flags = 0; ++ ++ return brcmf_fil_iovar_data_set(ifp, "pfn_cfg", cfg, sizeof(*cfg)); ++} ++ + static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq, + u32 mscan, u32 bestn) + { +@@ -167,7 +177,10 @@ int brcmf_pno_clean(struct brcmf_if *ifp + int brcmf_pno_start_sched_scan(struct brcmf_if *ifp, + struct cfg80211_sched_scan_request *req) + { ++ struct brcmu_d11inf *d11inf; ++ struct brcmf_pno_config_le pno_cfg; + struct cfg80211_ssid *ssid; ++ u16 chan; + int i, ret; + + /* clean up everything */ +@@ -190,6 +203,17 @@ int brcmf_pno_start_sched_scan(struct br + return ret; + } + ++ /* configure channels to use */ ++ d11inf = &ifp->drvr->config->d11inf; ++ for (i = 0; i < req->n_channels; i++) { ++ chan = req->channels[i]->hw_value; ++ pno_cfg.channel_list[i] = cpu_to_le16(chan); ++ } ++ if (req->n_channels) { ++ pno_cfg.channel_num = cpu_to_le32(req->n_channels); ++ brcmf_pno_channel_config(ifp, &pno_cfg); ++ } ++ + /* configure each match set */ + for (i = 0; i < req->n_match_sets; i++) { + ssid = &req->match_sets[i].ssid; diff --git a/package/kernel/mac80211/patches/357-0010-brcmfmac-remove-restriction-from-.sched_scan_start-c.patch b/package/kernel/mac80211/patches/357-0010-brcmfmac-remove-restriction-from-.sched_scan_start-c.patch new file mode 100644 index 0000000000..d14a60a826 --- /dev/null +++ b/package/kernel/mac80211/patches/357-0010-brcmfmac-remove-restriction-from-.sched_scan_start-c.patch @@ -0,0 +1,34 @@ +From dfe5b0d52d5880bd9d4b427e1a53c9e9e4c3c820 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:29 +0000 +Subject: [PATCH] brcmfmac: remove restriction from .sched_scan_start() + callback + +In the .sched_scan_start() callback a condition was checked whether a +normal scan was ongoing. However, there is no need for this check as +it is ok to start the scheduled scan irrespective whether or not a +normal scan is ongoing. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -3351,10 +3351,7 @@ brcmf_cfg80211_sched_scan_start(struct w + + brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n", + req->n_match_sets, req->n_ssids); +- if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { +- brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status); +- return -EAGAIN; +- } ++ + if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) { + brcmf_err("Scanning suppressed: status (%lu)\n", + cfg->scan_status); diff --git a/package/kernel/mac80211/patches/357-0011-brcmfmac-use-requested-scan-interval-in-scheduled-sc.patch b/package/kernel/mac80211/patches/357-0011-brcmfmac-use-requested-scan-interval-in-scheduled-sc.patch new file mode 100644 index 0000000000..eb1d5d304e --- /dev/null +++ b/package/kernel/mac80211/patches/357-0011-brcmfmac-use-requested-scan-interval-in-scheduled-sc.patch @@ -0,0 +1,67 @@ +From c6989fd55ceb633d2f18c12ffae01b9123125c89 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:30 +0000 +Subject: [PATCH] brcmfmac: use requested scan interval in scheduled scan + +User-space can specify the interval for the scheduled scan. This +interval is found in scheduled scan plan. The driver supports only +one plan, which is legacy behaviour. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 1 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 6 +++++- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h | 6 ++++-- + 3 files changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -6312,6 +6312,7 @@ static void brcmf_wiphy_pno_params(struc + wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; + wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; + wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; ++ wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD; + wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + } + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +@@ -63,6 +63,10 @@ static int brcmf_pno_config(struct brcmf + pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX; + + /* set up pno scan fr */ ++ if (scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) { ++ brcmf_dbg(SCAN, "scan period too small, using minimum\n"); ++ scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD; ++ } + pfn_param.scan_freq = cpu_to_le32(scan_freq); + + if (mscan) { +@@ -191,7 +195,7 @@ int brcmf_pno_start_sched_scan(struct br + } + + /* configure pno */ +- ret = brcmf_pno_config(ifp, BRCMF_PNO_SCHED_SCAN_PERIOD, 0, 0); ++ ret = brcmf_pno_config(ifp, req->scan_plans[0].interval, 0, 0); + if (ret < 0) + return ret; + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +@@ -16,8 +16,10 @@ + #ifndef _BRCMF_PNO_H + #define _BRCMF_PNO_H + +-#define BRCMF_PNO_SCAN_COMPLETE 1 +-#define BRCMF_PNO_MAX_PFN_COUNT 16 ++#define BRCMF_PNO_SCAN_COMPLETE 1 ++#define BRCMF_PNO_MAX_PFN_COUNT 16 ++#define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD 10 ++#define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD 508 + + /** + * brcmf_pno_clean - disable and clear pno in firmware. diff --git a/package/kernel/mac80211/patches/357-0012-brcmfmac-fix-scheduled-scan-result-handling-for-newe.patch b/package/kernel/mac80211/patches/357-0012-brcmfmac-fix-scheduled-scan-result-handling-for-newe.patch new file mode 100644 index 0000000000..bbd877426e --- /dev/null +++ b/package/kernel/mac80211/patches/357-0012-brcmfmac-fix-scheduled-scan-result-handling-for-newe.patch @@ -0,0 +1,76 @@ +From 53e3a80d80c80bf50ab64cf6c44fb0fa41aa22d8 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 23 Nov 2016 10:25:31 +0000 +Subject: [PATCH] brcmfmac: fix scheduled scan result handling for newer chips + +The scan results for scheduled scan as retrieved from the device +have changed. A field has been added which is not needed. However, +the appended info is. Luckily they are versioned so check that to +find out the location of the appended data. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 24 +++++++++++++++++++++- + .../broadcom/brcm80211/brcmfmac/fwil_types.h | 7 +++++++ + 2 files changed, 30 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -3257,6 +3257,28 @@ static int brcmf_start_internal_escan(st + return 0; + } + ++static struct brcmf_pno_net_info_le * ++brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1) ++{ ++ struct brcmf_pno_scanresults_v2_le *pfn_v2; ++ struct brcmf_pno_net_info_le *netinfo; ++ ++ switch (pfn_v1->version) { ++ default: ++ WARN_ON(1); ++ /* fall-thru */ ++ case cpu_to_le32(1): ++ netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1); ++ break; ++ case cpu_to_le32(2): ++ pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1; ++ netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1); ++ break; ++ } ++ ++ return netinfo; ++} ++ + /* PFN result doesn't have all the info which are required by the supplicant + * (For e.g IEs) Do a target Escan so that sched scan results are reported + * via wl_inform_single_bss in the required format. Escan does require the +@@ -3309,7 +3331,7 @@ brcmf_notify_sched_scan_results(struct b + } + + data += sizeof(struct brcmf_pno_scanresults_le); +- netinfo_start = (struct brcmf_pno_net_info_le *)data; ++ netinfo_start = brcmf_get_netinfo_array(pfn_result); + + for (i = 0; i < result_count; i++) { + netinfo = &netinfo_start[i]; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +@@ -785,6 +785,13 @@ struct brcmf_pno_scanresults_le { + __le32 count; + }; + ++struct brcmf_pno_scanresults_v2_le { ++ __le32 version; ++ __le32 status; ++ __le32 count; ++ __le32 scan_ch_bucket; ++}; ++ + /** + * struct brcmf_pno_macaddr_le - to configure PNO macaddr randomization. + * diff --git a/package/kernel/mac80211/patches/360-0001-brcmfmac-avoid-writing-channel-out-of-allocated-arra.patch b/package/kernel/mac80211/patches/360-0001-brcmfmac-avoid-writing-channel-out-of-allocated-arra.patch index 58af4d9078..c2ea368323 100644 --- a/package/kernel/mac80211/patches/360-0001-brcmfmac-avoid-writing-channel-out-of-allocated-arra.patch +++ b/package/kernel/mac80211/patches/360-0001-brcmfmac-avoid-writing-channel-out-of-allocated-arra.patch @@ -28,7 +28,7 @@ Signed-off-by: Kalle Valo --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -5915,7 +5915,6 @@ static int brcmf_construct_chaninfo(stru +@@ -5823,7 +5823,6 @@ static int brcmf_construct_chaninfo(stru u32 i, j; u32 total; u32 chaninfo; @@ -36,7 +36,7 @@ Signed-off-by: Kalle Valo pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); -@@ -5963,33 +5962,36 @@ static int brcmf_construct_chaninfo(stru +@@ -5871,33 +5870,36 @@ static int brcmf_construct_chaninfo(stru ch.bw == BRCMU_CHAN_BW_80) continue; @@ -85,7 +85,7 @@ Signed-off-by: Kalle Valo ch.bw = BRCMU_CHAN_BW_20; cfg->d11inf.encchspec(&ch); chaninfo = ch.chspec; -@@ -5997,11 +5999,11 @@ static int brcmf_construct_chaninfo(stru +@@ -5905,11 +5907,11 @@ static int brcmf_construct_chaninfo(stru &chaninfo); if (!err) { if (chaninfo & WL_CHAN_RADAR) diff --git a/package/kernel/mac80211/patches/360-0002-brcmfmac-don-t-preset-all-channels-as-disabled.patch b/package/kernel/mac80211/patches/360-0002-brcmfmac-don-t-preset-all-channels-as-disabled.patch index dbe45642f3..5a66a3518e 100644 --- a/package/kernel/mac80211/patches/360-0002-brcmfmac-don-t-preset-all-channels-as-disabled.patch +++ b/package/kernel/mac80211/patches/360-0002-brcmfmac-don-t-preset-all-channels-as-disabled.patch @@ -17,7 +17,7 @@ Signed-off-by: Kalle Valo --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -147,7 +147,6 @@ static struct ieee80211_rate __wl_rates[ +@@ -138,7 +138,6 @@ static struct ieee80211_rate __wl_rates[ .band = NL80211_BAND_2GHZ, \ .center_freq = (_freq), \ .hw_value = (_channel), \ @@ -25,7 +25,7 @@ Signed-off-by: Kalle Valo .max_antenna_gain = 0, \ .max_power = 30, \ } -@@ -156,7 +155,6 @@ static struct ieee80211_rate __wl_rates[ +@@ -147,7 +146,6 @@ static struct ieee80211_rate __wl_rates[ .band = NL80211_BAND_5GHZ, \ .center_freq = 5000 + (5 * (_channel)), \ .hw_value = (_channel), \ diff --git a/package/kernel/mac80211/patches/360-0003-brcmfmac-setup-wiphy-bands-after-registering-it-firs.patch b/package/kernel/mac80211/patches/360-0003-brcmfmac-setup-wiphy-bands-after-registering-it-firs.patch index 9c773bd16f..29ebad7ba2 100644 --- a/package/kernel/mac80211/patches/360-0003-brcmfmac-setup-wiphy-bands-after-registering-it-firs.patch +++ b/package/kernel/mac80211/patches/360-0003-brcmfmac-setup-wiphy-bands-after-registering-it-firs.patch @@ -25,7 +25,7 @@ Signed-off-by: Kalle Valo --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -6566,8 +6566,7 @@ static int brcmf_setup_wiphy(struct wiph +@@ -6475,8 +6475,7 @@ static int brcmf_setup_wiphy(struct wiph wiphy->bands[NL80211_BAND_5GHZ] = band; } } @@ -35,7 +35,7 @@ Signed-off-by: Kalle Valo } static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) -@@ -6932,6 +6931,12 @@ struct brcmf_cfg80211_info *brcmf_cfg802 +@@ -6841,6 +6840,12 @@ struct brcmf_cfg80211_info *brcmf_cfg802 goto priv_out; } diff --git a/package/kernel/mac80211/patches/841-brcmfmac-use-wiphy_read_of_freq_limits.patch b/package/kernel/mac80211/patches/841-brcmfmac-use-wiphy_read_of_freq_limits.patch index 9f26a49640..c23d4c070e 100644 --- a/package/kernel/mac80211/patches/841-brcmfmac-use-wiphy_read_of_freq_limits.patch +++ b/package/kernel/mac80211/patches/841-brcmfmac-use-wiphy_read_of_freq_limits.patch @@ -9,7 +9,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -5976,6 +5976,9 @@ static int brcmf_construct_chaninfo(stru +@@ -5884,6 +5884,9 @@ static int brcmf_construct_chaninfo(stru continue; } @@ -19,7 +19,7 @@ Signed-off-by: Rafał Miłecki /* assuming the chanspecs order is HT20, * HT40 upper, HT40 lower, and VHT80. */ -@@ -6566,6 +6569,9 @@ static int brcmf_setup_wiphy(struct wiph +@@ -6475,6 +6478,9 @@ static int brcmf_setup_wiphy(struct wiph wiphy->bands[NL80211_BAND_5GHZ] = band; } } diff --git a/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch index 7551b7dfa3..c7b13892a4 100644 --- a/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch +++ b/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -663,9 +663,37 @@ static struct wireless_dev *brcmf_cfg802 +@@ -654,9 +654,37 @@ static struct wireless_dev *brcmf_cfg802 u32 *flags, struct vif_params *params) { diff --git a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch index 70b8844e63..83bc7fe1fd 100644 --- a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch +++ b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2782,6 +2782,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip +@@ -2773,6 +2773,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip * preference in cfg struct to apply this to * FW later while initializing the dongle */