Merge tag 'wireless-drivers-next-for-davem-2015-06-03' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says: ==================== new driver mt7601u for MediaTek Wi-Fi devices MT7601U ath10k: * qca6174 power consumption improvements, enable ASPM etc (Michal) wil6210: * support Wi-Fi Simple Configuration in STA mode iwlwifi: * a few fixes (re-enablement of interrupts for certain new platforms that have special power states) * Rework completely the RBD allocation model towards new multi RX hardware. * cleanups * scan reworks continuation (Luca) mwifiex: * improve firmware debug functionality rtlwifi: * update regulatory database brcmfmac: * cleanup and new feature support in PCIe code * alternative nvram loading for router support ==================== Conflicts: drivers/net/wireless/iwlwifi/Kconfig Trivial conflict in iwlwifi Kconfig, two commits adding the same two chip numbers to the help text, but order transposed. Signed-off-by: David S. Miller <davem@davemloft.net>
这个提交包含在:
@@ -33,6 +33,7 @@
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
#include <defs.h>
|
||||
@@ -1116,12 +1117,25 @@ MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
|
||||
static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata;
|
||||
|
||||
|
||||
static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
|
||||
int val)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_ACPI)
|
||||
struct acpi_device *adev;
|
||||
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (adev)
|
||||
adev->flags.power_manageable = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
int err;
|
||||
struct brcmf_sdio_dev *sdiodev;
|
||||
struct brcmf_bus *bus_if;
|
||||
struct device *dev;
|
||||
|
||||
brcmf_dbg(SDIO, "Enter\n");
|
||||
brcmf_dbg(SDIO, "Class=%x\n", func->class);
|
||||
@@ -1129,6 +1143,10 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
|
||||
brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
|
||||
brcmf_dbg(SDIO, "Function#: %d\n", func->num);
|
||||
|
||||
dev = &func->dev;
|
||||
/* prohibit ACPI power management for this device */
|
||||
brcmf_sdiod_acpi_set_power_manageable(dev, 0);
|
||||
|
||||
/* Consume func num 1 but dont do anything with it. */
|
||||
if (func->num == 1)
|
||||
return 0;
|
||||
|
@@ -22,17 +22,6 @@
|
||||
#include "core.h"
|
||||
#include "commonring.h"
|
||||
|
||||
|
||||
/* dma flushing needs implementation for mips and arm platforms. Should
|
||||
* be put in util. Note, this is not real flushing. It is virtual non
|
||||
* cached memory. Only write buffers should have to be drained. Though
|
||||
* this may be different depending on platform......
|
||||
* SEE ALSO msgbuf.c
|
||||
*/
|
||||
#define brcmf_dma_flush(addr, len)
|
||||
#define brcmf_dma_invalidate_cache(addr, len)
|
||||
|
||||
|
||||
void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
|
||||
int (*cr_ring_bell)(void *ctx),
|
||||
int (*cr_update_rptr)(void *ctx),
|
||||
@@ -206,14 +195,9 @@ int brcmf_commonring_write_complete(struct brcmf_commonring *commonring)
|
||||
address = commonring->buf_addr;
|
||||
address += (commonring->f_ptr * commonring->item_len);
|
||||
if (commonring->f_ptr > commonring->w_ptr) {
|
||||
brcmf_dma_flush(address,
|
||||
(commonring->depth - commonring->f_ptr) *
|
||||
commonring->item_len);
|
||||
address = commonring->buf_addr;
|
||||
commonring->f_ptr = 0;
|
||||
}
|
||||
brcmf_dma_flush(address, (commonring->w_ptr - commonring->f_ptr) *
|
||||
commonring->item_len);
|
||||
|
||||
commonring->f_ptr = commonring->w_ptr;
|
||||
|
||||
@@ -258,8 +242,6 @@ void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
|
||||
if (commonring->r_ptr == commonring->depth)
|
||||
commonring->r_ptr = 0;
|
||||
|
||||
brcmf_dma_invalidate_cache(ret_addr, *n_ items * commonring->item_len);
|
||||
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
|
@@ -25,7 +25,7 @@
|
||||
|
||||
#define BRCMF_FW_MAX_NVRAM_SIZE 64000
|
||||
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
|
||||
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 9 /* pcie/1/4/ */
|
||||
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
|
||||
|
||||
char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
|
||||
module_param_string(firmware_path, brcmf_firmware_path,
|
||||
@@ -66,6 +66,12 @@ struct nvram_parser {
|
||||
bool multi_dev_v2;
|
||||
};
|
||||
|
||||
/**
|
||||
* is_nvram_char() - check if char is a valid one for NVRAM entry
|
||||
*
|
||||
* It accepts all printable ASCII chars except for '#' which opens a comment.
|
||||
* Please note that ' ' (space) while accepted is not a valid key name char.
|
||||
*/
|
||||
static bool is_nvram_char(char c)
|
||||
{
|
||||
/* comment marker excluded */
|
||||
@@ -73,7 +79,7 @@ static bool is_nvram_char(char c)
|
||||
return false;
|
||||
|
||||
/* key and value may have any other readable character */
|
||||
return (c > 0x20 && c < 0x7f);
|
||||
return (c >= 0x20 && c < 0x7f);
|
||||
}
|
||||
|
||||
static bool is_whitespace(char c)
|
||||
@@ -120,7 +126,7 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
|
||||
nvp->multi_dev_v1 = true;
|
||||
if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
|
||||
nvp->multi_dev_v2 = true;
|
||||
} else if (!is_nvram_char(c)) {
|
||||
} else if (!is_nvram_char(c) || c == ' ') {
|
||||
brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
|
||||
nvp->line, nvp->column);
|
||||
return COMMENT;
|
||||
@@ -162,17 +168,20 @@ brcmf_nvram_handle_value(struct nvram_parser *nvp)
|
||||
static enum nvram_parser_state
|
||||
brcmf_nvram_handle_comment(struct nvram_parser *nvp)
|
||||
{
|
||||
char *eol, *sol;
|
||||
char *eoc, *sol;
|
||||
|
||||
sol = (char *)&nvp->fwnv->data[nvp->pos];
|
||||
eol = strchr(sol, '\n');
|
||||
if (eol == NULL)
|
||||
return END;
|
||||
eoc = strchr(sol, '\n');
|
||||
if (!eoc) {
|
||||
eoc = strchr(sol, '\0');
|
||||
if (!eoc)
|
||||
return END;
|
||||
}
|
||||
|
||||
/* eat all moving to next line */
|
||||
nvp->line++;
|
||||
nvp->column = 1;
|
||||
nvp->pos += (eol - sol) + 1;
|
||||
nvp->pos += (eoc - sol) + 1;
|
||||
return IDLE;
|
||||
}
|
||||
|
||||
@@ -222,6 +231,10 @@ static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
|
||||
static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
||||
u16 bus_nr)
|
||||
{
|
||||
/* Device path with a leading '=' key-value separator */
|
||||
char pcie_path[] = "=pcie/?/?";
|
||||
size_t pcie_len;
|
||||
|
||||
u32 i, j;
|
||||
bool found;
|
||||
u8 *nvram;
|
||||
@@ -238,6 +251,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
||||
/* First search for the devpathX and see if it is the configuration
|
||||
* for domain_nr/bus_nr. Search complete nvp
|
||||
*/
|
||||
snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
|
||||
bus_nr);
|
||||
pcie_len = strlen(pcie_path);
|
||||
found = false;
|
||||
i = 0;
|
||||
while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
|
||||
@@ -245,13 +261,10 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
|
||||
* Y = domain_nr, Z = bus_nr, X = virtual ID
|
||||
*/
|
||||
if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
|
||||
(strncmp(&nvp->nvram[i + 8], "=pcie/", 6) == 0)) {
|
||||
if (((nvp->nvram[i + 14] - '0') == domain_nr) &&
|
||||
((nvp->nvram[i + 16] - '0') == bus_nr)) {
|
||||
id = nvp->nvram[i + 7] - '0';
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
(strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
|
||||
id = nvp->nvram[i + 7] - '0';
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
while (nvp->nvram[i] != 0)
|
||||
i++;
|
||||
@@ -297,6 +310,8 @@ fail:
|
||||
static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
|
||||
u16 bus_nr)
|
||||
{
|
||||
char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN];
|
||||
size_t len;
|
||||
u32 i, j;
|
||||
u8 *nvram;
|
||||
|
||||
@@ -308,14 +323,13 @@ static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
|
||||
* Valid entries are of type pcie/X/Y/ where X = domain_nr and
|
||||
* Y = bus_nr.
|
||||
*/
|
||||
snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr);
|
||||
len = strlen(prefix);
|
||||
i = 0;
|
||||
j = 0;
|
||||
while (i < nvp->nvram_len - BRCMF_FW_NVRAM_PCIEDEV_LEN) {
|
||||
if ((strncmp(&nvp->nvram[i], "pcie/", 5) == 0) &&
|
||||
(nvp->nvram[i + 6] == '/') && (nvp->nvram[i + 8] == '/') &&
|
||||
((nvp->nvram[i + 5] - '0') == domain_nr) &&
|
||||
((nvp->nvram[i + 7] - '0') == bus_nr)) {
|
||||
i += BRCMF_FW_NVRAM_PCIEDEV_LEN;
|
||||
while (i < nvp->nvram_len - len) {
|
||||
if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
|
||||
i += len;
|
||||
while (nvp->nvram[i] != 0) {
|
||||
nvram[j] = nvp->nvram[i];
|
||||
i++;
|
||||
|
@@ -249,8 +249,8 @@ void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid)
|
||||
}
|
||||
|
||||
|
||||
void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
struct sk_buff *skb)
|
||||
u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct brcmf_flowring_ring *ring;
|
||||
|
||||
@@ -271,6 +271,7 @@ void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)
|
||||
brcmf_flowring_block(flow, flowid, false);
|
||||
}
|
||||
return skb_queue_len(&ring->skblist);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -64,8 +64,8 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
|
||||
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);
|
||||
void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid,
|
||||
struct sk_buff *skb);
|
||||
u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 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 *skb);
|
||||
|
@@ -635,7 +635,7 @@ static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
|
||||
static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
|
||||
u32 slot_id, struct sk_buff **pktout,
|
||||
bool remove_item)
|
||||
{
|
||||
|
@@ -73,7 +73,7 @@
|
||||
#define BRCMF_MSGBUF_TX_FLUSH_CNT1 32
|
||||
#define BRCMF_MSGBUF_TX_FLUSH_CNT2 96
|
||||
|
||||
#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 64
|
||||
#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96
|
||||
#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
|
||||
|
||||
struct msgbuf_common_hdr {
|
||||
@@ -278,16 +278,6 @@ struct brcmf_msgbuf_pktids {
|
||||
struct brcmf_msgbuf_pktid *array;
|
||||
};
|
||||
|
||||
|
||||
/* dma flushing needs implementation for mips and arm platforms. Should
|
||||
* be put in util. Note, this is not real flushing. It is virtual non
|
||||
* cached memory. Only write buffers should have to be drained. Though
|
||||
* this may be different depending on platform......
|
||||
*/
|
||||
#define brcmf_dma_flush(addr, len)
|
||||
#define brcmf_dma_invalidate_cache(addr, len)
|
||||
|
||||
|
||||
static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf);
|
||||
|
||||
|
||||
@@ -462,7 +452,6 @@ static int brcmf_msgbuf_tx_ioctl(struct brcmf_pub *drvr, int ifidx,
|
||||
memcpy(msgbuf->ioctbuf, buf, buf_len);
|
||||
else
|
||||
memset(msgbuf->ioctbuf, 0, buf_len);
|
||||
brcmf_dma_flush(ioctl_buf, buf_len);
|
||||
|
||||
err = brcmf_commonring_write_complete(commonring);
|
||||
brcmf_commonring_unlock(commonring);
|
||||
@@ -795,6 +784,8 @@ static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
|
||||
struct brcmf_flowring *flow = msgbuf->flow;
|
||||
struct ethhdr *eh = (struct ethhdr *)(skb->data);
|
||||
u32 flowid;
|
||||
u32 queue_count;
|
||||
bool force;
|
||||
|
||||
flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
|
||||
if (flowid == BRCMF_FLOWRING_INVALID_ID) {
|
||||
@@ -802,8 +793,9 @@ static int brcmf_msgbuf_txdata(struct brcmf_pub *drvr, int ifidx,
|
||||
if (flowid == BRCMF_FLOWRING_INVALID_ID)
|
||||
return -ENOMEM;
|
||||
}
|
||||
brcmf_flowring_enqueue(flow, flowid, skb);
|
||||
brcmf_msgbuf_schedule_txdata(msgbuf, flowid, false);
|
||||
queue_count = brcmf_flowring_enqueue(flow, flowid, skb);
|
||||
force = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0);
|
||||
brcmf_msgbuf_schedule_txdata(msgbuf, flowid, force);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -39,10 +39,16 @@ void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
|
||||
if (!sdiodev->pdata)
|
||||
return;
|
||||
|
||||
if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
|
||||
sdiodev->pdata->drive_strength = val;
|
||||
|
||||
/* make sure there are interrupts defined in the node */
|
||||
if (!of_find_property(np, "interrupts", NULL))
|
||||
return;
|
||||
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq) {
|
||||
brcmf_err("interrupt could not be mapped\n");
|
||||
devm_kfree(dev, sdiodev->pdata);
|
||||
return;
|
||||
}
|
||||
irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
|
||||
@@ -50,7 +56,4 @@ void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
|
||||
sdiodev->pdata->oob_irq_supported = true;
|
||||
sdiodev->pdata->oob_irq_nr = irq;
|
||||
sdiodev->pdata->oob_irq_flags = irqf;
|
||||
|
||||
if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
|
||||
sdiodev->pdata->drive_strength = val;
|
||||
}
|
||||
|
@@ -112,10 +112,11 @@ enum brcmf_pcie_state {
|
||||
BRCMF_PCIE_MB_INT_D2H3_DB0 | \
|
||||
BRCMF_PCIE_MB_INT_D2H3_DB1)
|
||||
|
||||
#define BRCMF_PCIE_MIN_SHARED_VERSION 4
|
||||
#define BRCMF_PCIE_MIN_SHARED_VERSION 5
|
||||
#define BRCMF_PCIE_MAX_SHARED_VERSION 5
|
||||
#define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF
|
||||
#define BRCMF_PCIE_SHARED_TXPUSH_SUPPORT 0x4000
|
||||
#define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000
|
||||
#define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000
|
||||
|
||||
#define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000
|
||||
#define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000
|
||||
@@ -147,6 +148,10 @@ enum brcmf_pcie_state {
|
||||
#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
|
||||
|
||||
@@ -248,6 +253,13 @@ struct brcmf_pciedev_info {
|
||||
bool mbdata_completed;
|
||||
bool irq_allocated;
|
||||
bool wowl_enabled;
|
||||
u8 dma_idx_sz;
|
||||
void *idxbuf;
|
||||
u32 idxbuf_sz;
|
||||
dma_addr_t idxbuf_dmahandle;
|
||||
u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
|
||||
void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
|
||||
u16 value);
|
||||
};
|
||||
|
||||
struct brcmf_pcie_ringbuf {
|
||||
@@ -277,15 +289,6 @@ static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
|
||||
};
|
||||
|
||||
|
||||
/* dma flushing needs implementation for mips and arm platforms. Should
|
||||
* be put in util. Note, this is not real flushing. It is virtual non
|
||||
* cached memory. Only write buffers should have to be drained. Though
|
||||
* this may be different depending on platform......
|
||||
*/
|
||||
#define brcmf_dma_flush(addr, len)
|
||||
#define brcmf_dma_invalidate_cache(addr, len)
|
||||
|
||||
|
||||
static u32
|
||||
brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
|
||||
{
|
||||
@@ -333,6 +336,25 @@ brcmf_pcie_write_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
|
||||
}
|
||||
|
||||
|
||||
static u16
|
||||
brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
|
||||
{
|
||||
u16 *address = devinfo->idxbuf + mem_offset;
|
||||
|
||||
return (*(address));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
|
||||
u16 value)
|
||||
{
|
||||
u16 *address = devinfo->idxbuf + mem_offset;
|
||||
|
||||
*(address) = value;
|
||||
}
|
||||
|
||||
|
||||
static u32
|
||||
brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
|
||||
{
|
||||
@@ -878,7 +900,7 @@ static int brcmf_pcie_ring_mb_write_rptr(void *ctx)
|
||||
brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
|
||||
commonring->w_ptr, ring->id);
|
||||
|
||||
brcmf_pcie_write_tcm16(devinfo, ring->r_idx_addr, commonring->r_ptr);
|
||||
devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -896,7 +918,7 @@ static int brcmf_pcie_ring_mb_write_wptr(void *ctx)
|
||||
brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
|
||||
commonring->r_ptr, ring->id);
|
||||
|
||||
brcmf_pcie_write_tcm16(devinfo, ring->w_idx_addr, commonring->w_ptr);
|
||||
devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -925,7 +947,7 @@ static int brcmf_pcie_ring_mb_update_rptr(void *ctx)
|
||||
if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
|
||||
return -EIO;
|
||||
|
||||
commonring->r_ptr = brcmf_pcie_read_tcm16(devinfo, ring->r_idx_addr);
|
||||
commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr);
|
||||
|
||||
brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
|
||||
commonring->w_ptr, ring->id);
|
||||
@@ -943,7 +965,7 @@ static int brcmf_pcie_ring_mb_update_wptr(void *ctx)
|
||||
if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
|
||||
return -EIO;
|
||||
|
||||
commonring->w_ptr = brcmf_pcie_read_tcm16(devinfo, ring->w_idx_addr);
|
||||
commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr);
|
||||
|
||||
brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
|
||||
commonring->r_ptr, ring->id);
|
||||
@@ -1048,6 +1070,13 @@ static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
}
|
||||
kfree(devinfo->shared.flowrings);
|
||||
devinfo->shared.flowrings = NULL;
|
||||
if (devinfo->idxbuf) {
|
||||
dma_free_coherent(&devinfo->pdev->dev,
|
||||
devinfo->idxbuf_sz,
|
||||
devinfo->idxbuf,
|
||||
devinfo->idxbuf_dmahandle);
|
||||
devinfo->idxbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1063,19 +1092,72 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
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);
|
||||
|
||||
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);
|
||||
if (devinfo->dma_idx_sz != 0) {
|
||||
bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) *
|
||||
devinfo->dma_idx_sz * 2;
|
||||
devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
|
||||
&devinfo->idxbuf_dmahandle,
|
||||
GFP_KERNEL);
|
||||
if (!devinfo->idxbuf)
|
||||
devinfo->dma_idx_sz = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
idx_offset = sizeof(u32);
|
||||
devinfo->write_ptr = brcmf_pcie_write_tcm16;
|
||||
devinfo->read_ptr = brcmf_pcie_read_tcm16;
|
||||
brcmf_dbg(PCIE, "Using TCM indices\n");
|
||||
} else {
|
||||
memset(devinfo->idxbuf, 0, bufsz);
|
||||
devinfo->idxbuf_sz = bufsz;
|
||||
idx_offset = devinfo->dma_idx_sz;
|
||||
devinfo->write_ptr = brcmf_pcie_write_idx;
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
@@ -1089,8 +1171,8 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
ring->id = i;
|
||||
devinfo->shared.commonrings[i] = ring;
|
||||
|
||||
h2d_w_idx_ptr += sizeof(u32);
|
||||
h2d_r_idx_ptr += sizeof(u32);
|
||||
h2d_w_idx_ptr += idx_offset;
|
||||
h2d_r_idx_ptr += idx_offset;
|
||||
ring_mem_ptr += BRCMF_RING_MEM_SZ;
|
||||
}
|
||||
|
||||
@@ -1104,13 +1186,11 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
ring->id = i;
|
||||
devinfo->shared.commonrings[i] = ring;
|
||||
|
||||
d2h_w_idx_ptr += sizeof(u32);
|
||||
d2h_r_idx_ptr += sizeof(u32);
|
||||
d2h_w_idx_ptr += idx_offset;
|
||||
d2h_r_idx_ptr += idx_offset;
|
||||
ring_mem_ptr += BRCMF_RING_MEM_SZ;
|
||||
}
|
||||
|
||||
addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES;
|
||||
max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr);
|
||||
devinfo->shared.nrof_flowrings =
|
||||
max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS;
|
||||
rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring),
|
||||
@@ -1134,15 +1214,15 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
ring);
|
||||
ring->w_idx_addr = h2d_w_idx_ptr;
|
||||
ring->r_idx_addr = h2d_r_idx_ptr;
|
||||
h2d_w_idx_ptr += sizeof(u32);
|
||||
h2d_r_idx_ptr += sizeof(u32);
|
||||
h2d_w_idx_ptr += idx_offset;
|
||||
h2d_r_idx_ptr += idx_offset;
|
||||
}
|
||||
devinfo->shared.flowrings = rings;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
brcmf_err("Allocating commonring buffers failed\n");
|
||||
brcmf_err("Allocating ring buffers failed\n");
|
||||
brcmf_pcie_release_ringbuffers(devinfo);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -1175,7 +1255,6 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
goto fail;
|
||||
|
||||
memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
|
||||
brcmf_dma_flush(devinfo->shared.scratch, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
|
||||
|
||||
addr = devinfo->shared.tcm_base_address +
|
||||
BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
|
||||
@@ -1193,7 +1272,6 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
|
||||
goto fail;
|
||||
|
||||
memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
|
||||
brcmf_dma_flush(devinfo->shared.ringupd, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
|
||||
|
||||
addr = devinfo->shared.tcm_base_address +
|
||||
BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
|
||||
@@ -1280,10 +1358,13 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
|
||||
brcmf_err("Unsupported PCIE version %d\n", version);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT) {
|
||||
brcmf_err("Unsupported legacy TX mode 0x%x\n",
|
||||
shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT);
|
||||
return -EINVAL;
|
||||
|
||||
/* check firmware support dma indicies */
|
||||
if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) {
|
||||
if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX)
|
||||
devinfo->dma_idx_sz = sizeof(u16);
|
||||
else
|
||||
devinfo->dma_idx_sz = sizeof(u32);
|
||||
}
|
||||
|
||||
addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
|
||||
|
在新工单中引用
屏蔽一个用户