summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/pcie.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-20 18:58:50 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-20 18:58:50 -0800
commita0b1c42951dd06ec83cc1bc2c9788131d9fefcd8 (patch)
treea572f1523cf904c93020c9cdb32f3bc84ec3ac16 /drivers/net/wireless/mwifiex/pcie.c
parent8ec4942212a6d337982967778a3dc3b60aea782e (diff)
parentecd9883724b78cc72ed92c98bcb1a46c764fff21 (diff)
downloadblackbird-op-linux-a0b1c42951dd06ec83cc1bc2c9788131d9fefcd8.tar.gz
blackbird-op-linux-a0b1c42951dd06ec83cc1bc2c9788131d9fefcd8.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking update from David Miller: 1) Checkpoint/restarted TCP sockets now can properly propagate the TCP timestamp offset. From Andrey Vagin. 2) VMWARE VM VSOCK layer, from Andy King. 3) Much improved support for virtual functions and SR-IOV in bnx2x, from Ariel ELior. 4) All protocols on ipv4 and ipv6 are now network namespace aware, and all the compatability checks for initial-namespace-only protocols is removed. Thanks to Tom Parkin for helping deal with the last major holdout, L2TP. 5) IPV6 support in netpoll and network namespace support in pktgen, from Cong Wang. 6) Multiple Registration Protocol (MRP) and Multiple VLAN Registration Protocol (MVRP) support, from David Ward. 7) Compute packet lengths more accurately in the packet scheduler, from Eric Dumazet. 8) Use per-task page fragment allocator in skb_append_datato_frags(), also from Eric Dumazet. 9) Add support for connection tracking labels in netfilter, from Florian Westphal. 10) Fix default multicast group joining on ipv6, and add anti-spoofing checks to 6to4 and 6rd. From Hannes Frederic Sowa. 11) Make ipv4/ipv6 fragmentation memory limits more reasonable in modern times, rearrange inet frag datastructures for better cacheline locality, and move more operations outside of locking. From Jesper Dangaard Brouer. 12) Instead of strict master <--> slave relationships, allow arbitrary scenerios with "upper device lists". From Jiri Pirko. 13) Improve rate limiting accuracy in TBF and act_police, also from Jiri Pirko. 14) Add a BPF filter netfilter match target, from Willem de Bruijn. 15) Orphan and delete a bunch of pre-historic networking drivers from Paul Gortmaker. 16) Add TSO support for GRE tunnels, from Pravin B SHelar. Although this still needs some minor bug fixing before it's %100 correct in all cases. 17) Handle unresolved IPSEC states like ARP, with a resolution packet queue. From Steffen Klassert. 18) Remove TCP Appropriate Byte Count support (ABC), from Stephen Hemminger. This was long overdue. 19) Support SO_REUSEPORT, from Tom Herbert. 20) Allow locking a socket BPF filter, so that it cannot change after a process drops capabilities. 21) Add VLAN filtering to bridge, from Vlad Yasevich. 22) Bring ipv6 on-par with ipv4 and do not cache neighbour entries in the ipv6 routes, from YOSHIFUJI Hideaki. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1538 commits) ipv6: fix race condition regarding dst->expires and dst->from. net: fix a wrong assignment in skb_split() ip_gre: remove an extra dst_release() ppp: set qdisc_tx_busylock to avoid LOCKDEP splat atl1c: restore buffer state net: fix a build failure when !CONFIG_PROC_FS net: ipv4: fix waring -Wunused-variable net: proc: fix build failed when procfs is not configured Revert "xen: netback: remove redundant xenvif_put" net: move procfs code to net/core/net-procfs.c qmi_wwan, cdc-ether: add ADU960S bonding: set sysfs device_type to 'bond' bonding: fix bond_release_all inconsistencies b44: use netdev_alloc_skb_ip_align() xen: netback: remove redundant xenvif_put net: fec: Do a sanity check on the gpio number ip_gre: propogate target device GSO capability to the tunnel device ip_gre: allow CSUM capable devices to handle packets bonding: Fix initialize after use for 3ad machine state spinlock bonding: Fix race condition between bond_enslave() and bond_3ad_update_lacp_rate() ...
Diffstat (limited to 'drivers/net/wireless/mwifiex/pcie.c')
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c1262
1 files changed, 871 insertions, 391 deletions
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index b879e1338a54..4b54bcf382f3 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -39,17 +39,20 @@ static struct semaphore add_remove_card_sem;
static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter);
static int mwifiex_pcie_resume(struct pci_dev *pdev);
-/*
- * This function is called after skb allocation to update
- * "skb->cb" with physical address of data pointer.
- */
-static phys_addr_t *mwifiex_update_sk_buff_pa(struct sk_buff *skb)
+static int
+mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
+ int size, int flags)
{
- phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb);
-
- *buf_pa = (phys_addr_t)virt_to_phys(skb->data);
+ struct pcie_service_card *card = adapter->card;
+ dma_addr_t buf_pa;
- return buf_pa;
+ buf_pa = pci_map_single(card->dev, skb->data, size, flags);
+ if (pci_dma_mapping_error(card->dev, buf_pa)) {
+ dev_err(adapter->dev, "failed to map pci memory!\n");
+ return -1;
+ }
+ memcpy(skb->cb, &buf_pa, sizeof(dma_addr_t));
+ return 0;
}
/*
@@ -59,9 +62,13 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
{
u32 *cookie_addr;
struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+
+ if (!reg->sleep_cookie)
+ return true;
- if (card->sleep_cookie) {
- cookie_addr = (u32 *)card->sleep_cookie->data;
+ if (card->sleep_cookie_vbase) {
+ cookie_addr = (u32 *)card->sleep_cookie_vbase;
dev_dbg(adapter->dev, "info: ACCESS_HW: sleep cookie=0x%x\n",
*cookie_addr);
if (*cookie_addr == FW_AWAKE_COOKIE)
@@ -91,6 +98,13 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
card->dev = pdev;
+ if (ent->driver_data) {
+ struct mwifiex_pcie_device *data = (void *)ent->driver_data;
+ card->pcie.firmware = data->firmware;
+ card->pcie.reg = data->reg;
+ card->pcie.blksz_fw_dl = data->blksz_fw_dl;
+ }
+
if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
MWIFIEX_PCIE)) {
pr_err("%s failed\n", __func__);
@@ -227,13 +241,16 @@ static int mwifiex_pcie_resume(struct pci_dev *pdev)
return 0;
}
-#define PCIE_VENDOR_ID_MARVELL (0x11ab)
-#define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30)
-
static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = {
{
PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ .driver_data = (unsigned long) &mwifiex_pcie8766,
+ },
+ {
+ PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ .driver_data = (unsigned long) &mwifiex_pcie8897,
},
{},
};
@@ -286,8 +303,10 @@ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data)
static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
{
int i = 0;
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
- while (mwifiex_pcie_ok_to_access_hw(adapter)) {
+ while (reg->sleep_cookie && mwifiex_pcie_ok_to_access_hw(adapter)) {
i++;
usleep_range(10, 20);
/* 50ms max wait */
@@ -361,14 +380,246 @@ static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter)
}
/*
- * This function creates buffer descriptor ring for TX
+ * This function initializes TX buffer ring descriptors
*/
-static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
+static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ struct mwifiex_pcie_buf_desc *desc;
+ struct mwifiex_pfu_buf_desc *desc2;
+ int i;
+
+ for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+ card->tx_buf_list[i] = NULL;
+ if (reg->pfu_enabled) {
+ card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
+ (sizeof(*desc2) * i);
+ desc2 = card->txbd_ring[i];
+ memset(desc2, 0, sizeof(*desc2));
+ } else {
+ card->txbd_ring[i] = (void *)card->txbd_ring_vbase +
+ (sizeof(*desc) * i);
+ desc = card->txbd_ring[i];
+ memset(desc, 0, sizeof(*desc));
+ }
+ }
+
+ return 0;
+}
+
+/* This function initializes RX buffer ring descriptors. Each SKB is allocated
+ * here and after mapping PCI memory, its physical address is assigned to
+ * PCIE Rx buffer descriptor's physical address.
+ */
+static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ struct sk_buff *skb;
+ struct mwifiex_pcie_buf_desc *desc;
+ struct mwifiex_pfu_buf_desc *desc2;
+ dma_addr_t buf_pa;
+ int i;
+
+ for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+ /* Allocate skb here so that firmware can DMA data from it */
+ skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
+ if (!skb) {
+ dev_err(adapter->dev,
+ "Unable to allocate skb for RX ring.\n");
+ kfree(card->rxbd_ring_vbase);
+ return -ENOMEM;
+ }
+
+ if (mwifiex_map_pci_memory(adapter, skb,
+ MWIFIEX_RX_DATA_BUF_SIZE,
+ PCI_DMA_FROMDEVICE))
+ return -1;
+
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+
+ dev_dbg(adapter->dev,
+ "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
+ skb, skb->len, skb->data, (u32)buf_pa,
+ (u32)((u64)buf_pa >> 32));
+
+ card->rx_buf_list[i] = skb;
+ if (reg->pfu_enabled) {
+ card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase +
+ (sizeof(*desc2) * i);
+ desc2 = card->rxbd_ring[i];
+ desc2->paddr = buf_pa;
+ desc2->len = (u16)skb->len;
+ desc2->frag_len = (u16)skb->len;
+ desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop;
+ desc2->offset = 0;
+ } else {
+ card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase +
+ (sizeof(*desc) * i));
+ desc = card->rxbd_ring[i];
+ desc->paddr = buf_pa;
+ desc->len = (u16)skb->len;
+ desc->flags = 0;
+ }
+ }
+
+ return 0;
+}
+
+/* This function initializes event buffer ring descriptors. Each SKB is
+ * allocated here and after mapping PCI memory, its physical address is assigned
+ * to PCIE Rx buffer descriptor's physical address
+ */
+static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ struct mwifiex_evt_buf_desc *desc;
+ struct sk_buff *skb;
+ dma_addr_t buf_pa;
+ int i;
+
+ for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
+ /* Allocate skb here so that firmware can DMA data from it */
+ skb = dev_alloc_skb(MAX_EVENT_SIZE);
+ if (!skb) {
+ dev_err(adapter->dev,
+ "Unable to allocate skb for EVENT buf.\n");
+ kfree(card->evtbd_ring_vbase);
+ return -ENOMEM;
+ }
+ skb_put(skb, MAX_EVENT_SIZE);
+
+ if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
+ PCI_DMA_FROMDEVICE))
+ return -1;
+
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+
+ dev_dbg(adapter->dev,
+ "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n",
+ skb, skb->len, skb->data, (u32)buf_pa,
+ (u32)((u64)buf_pa >> 32));
+
+ card->evt_buf_list[i] = skb;
+ card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase +
+ (sizeof(*desc) * i));
+ desc = card->evtbd_ring[i];
+ desc->paddr = buf_pa;
+ desc->len = (u16)skb->len;
+ desc->flags = 0;
+ }
+
+ return 0;
+}
+
+/* This function cleans up TX buffer rings. If any of the buffer list has valid
+ * SKB address, associated SKB is freed.
+ */
+static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ struct sk_buff *skb;
+ struct mwifiex_pcie_buf_desc *desc;
+ struct mwifiex_pfu_buf_desc *desc2;
+ int i;
+
+ for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+ if (reg->pfu_enabled) {
+ desc2 = card->txbd_ring[i];
+ if (card->tx_buf_list[i]) {
+ skb = card->tx_buf_list[i];
+ pci_unmap_single(card->dev, desc2->paddr,
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
+ }
+ memset(desc2, 0, sizeof(*desc2));
+ } else {
+ desc = card->txbd_ring[i];
+ if (card->tx_buf_list[i]) {
+ skb = card->tx_buf_list[i];
+ pci_unmap_single(card->dev, desc->paddr,
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
+ }
+ memset(desc, 0, sizeof(*desc));
+ }
+ card->tx_buf_list[i] = NULL;
+ }
+
+ return;
+}
+
+/* This function cleans up RX buffer rings. If any of the buffer list has valid
+ * SKB address, associated SKB is freed.
+ */
+static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ struct mwifiex_pcie_buf_desc *desc;
+ struct mwifiex_pfu_buf_desc *desc2;
struct sk_buff *skb;
int i;
- phys_addr_t *buf_pa;
+
+ for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
+ if (reg->pfu_enabled) {
+ desc2 = card->rxbd_ring[i];
+ if (card->rx_buf_list[i]) {
+ skb = card->rx_buf_list[i];
+ pci_unmap_single(card->dev, desc2->paddr,
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
+ }
+ memset(desc2, 0, sizeof(*desc2));
+ } else {
+ desc = card->rxbd_ring[i];
+ if (card->rx_buf_list[i]) {
+ skb = card->rx_buf_list[i];
+ pci_unmap_single(card->dev, desc->paddr,
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
+ }
+ memset(desc, 0, sizeof(*desc));
+ }
+ card->rx_buf_list[i] = NULL;
+ }
+
+ return;
+}
+
+/* This function cleans up event buffer rings. If any of the buffer list has
+ * valid SKB address, associated SKB is freed.
+ */
+static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ struct mwifiex_evt_buf_desc *desc;
+ struct sk_buff *skb;
+ int i;
+
+ for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
+ desc = card->evtbd_ring[i];
+ if (card->evt_buf_list[i]) {
+ skb = card->evt_buf_list[i];
+ pci_unmap_single(card->dev, desc->paddr, MAX_EVENT_SIZE,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb_any(skb);
+ }
+ card->evt_buf_list[i] = NULL;
+ memset(desc, 0, sizeof(*desc));
+ }
+
+ return;
+}
+
+/* This function creates buffer descriptor ring for TX
+ */
+static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
/*
* driver maintaines the write pointer and firmware maintaines the read
@@ -376,76 +627,56 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter)
* starts at zero with rollover bit set
*/
card->txbd_wrptr = 0;
- card->txbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND;
+
+ if (reg->pfu_enabled)
+ card->txbd_rdptr = 0;
+ else
+ card->txbd_rdptr |= reg->tx_rollover_ind;
/* allocate shared memory for the BD ring and divide the same in to
several descriptors */
- card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
- MWIFIEX_MAX_TXRX_BD;
+ if (reg->pfu_enabled)
+ card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
+ MWIFIEX_MAX_TXRX_BD;
+ else
+ card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
+ MWIFIEX_MAX_TXRX_BD;
+
dev_dbg(adapter->dev, "info: txbd_ring: Allocating %d bytes\n",
card->txbd_ring_size);
- card->txbd_ring_vbase = kzalloc(card->txbd_ring_size, GFP_KERNEL);
+ card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
+ card->txbd_ring_size,
+ &card->txbd_ring_pbase);
if (!card->txbd_ring_vbase) {
- dev_err(adapter->dev, "Unable to alloc buffer for txbd ring\n");
+ dev_err(adapter->dev,
+ "allocate consistent memory (%d bytes) failed!\n",
+ card->txbd_ring_size);
return -ENOMEM;
}
- card->txbd_ring_pbase = virt_to_phys(card->txbd_ring_vbase);
-
dev_dbg(adapter->dev,
"info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n",
- card->txbd_ring_vbase, (u32)card->txbd_ring_pbase,
+ card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase,
(u32)((u64)card->txbd_ring_pbase >> 32), card->txbd_ring_size);
- for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
- card->txbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
- (card->txbd_ring_vbase +
- (sizeof(struct mwifiex_pcie_buf_desc)
- * i));
-
- /* Allocate buffer here so that firmware can DMA data from it */
- skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
- if (!skb) {
- dev_err(adapter->dev, "Unable to allocate skb for TX ring.\n");
- kfree(card->txbd_ring_vbase);
- return -ENOMEM;
- }
- buf_pa = mwifiex_update_sk_buff_pa(skb);
-
- skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE);
- dev_dbg(adapter->dev, "info: TX ring: add new skb base: %p, "
- "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n",
- skb, skb->data, (u32)*buf_pa,
- (u32)(((u64)*buf_pa >> 32)), skb->len);
-
- card->tx_buf_list[i] = skb;
- card->txbd_ring[i]->paddr = *buf_pa;
- card->txbd_ring[i]->len = (u16)skb->len;
- card->txbd_ring[i]->flags = 0;
- }
-
- return 0;
+ return mwifiex_init_txq_ring(adapter);
}
static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- int i;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
- for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
- if (card->tx_buf_list[i])
- dev_kfree_skb_any(card->tx_buf_list[i]);
- card->tx_buf_list[i] = NULL;
- card->txbd_ring[i]->paddr = 0;
- card->txbd_ring[i]->len = 0;
- card->txbd_ring[i]->flags = 0;
- card->txbd_ring[i] = NULL;
- }
+ mwifiex_cleanup_txq_ring(adapter);
- kfree(card->txbd_ring_vbase);
+ if (card->txbd_ring_vbase)
+ pci_free_consistent(card->dev, card->txbd_ring_size,
+ card->txbd_ring_vbase,
+ card->txbd_ring_pbase);
card->txbd_ring_size = 0;
card->txbd_wrptr = 0;
- card->txbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND;
+ card->txbd_rdptr = 0 | reg->tx_rollover_ind;
card->txbd_ring_vbase = NULL;
+ card->txbd_ring_pbase = 0;
return 0;
}
@@ -456,9 +687,7 @@ static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter)
static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- struct sk_buff *skb;
- int i;
- phys_addr_t *buf_pa;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
/*
* driver maintaines the read pointer and firmware maintaines the write
@@ -466,19 +695,26 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
* starts at zero with rollover bit set
*/
card->rxbd_wrptr = 0;
- card->rxbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND;
+ card->rxbd_rdptr = reg->rx_rollover_ind;
+
+ if (reg->pfu_enabled)
+ card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) *
+ MWIFIEX_MAX_TXRX_BD;
+ else
+ card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
+ MWIFIEX_MAX_TXRX_BD;
- card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
- MWIFIEX_MAX_TXRX_BD;
dev_dbg(adapter->dev, "info: rxbd_ring: Allocating %d bytes\n",
card->rxbd_ring_size);
- card->rxbd_ring_vbase = kzalloc(card->rxbd_ring_size, GFP_KERNEL);
+ card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
+ card->rxbd_ring_size,
+ &card->rxbd_ring_pbase);
if (!card->rxbd_ring_vbase) {
- dev_err(adapter->dev, "Unable to allocate buffer for "
- "rxbd_ring.\n");
+ dev_err(adapter->dev,
+ "allocate consistent memory (%d bytes) failed!\n",
+ card->rxbd_ring_size);
return -ENOMEM;
}
- card->rxbd_ring_pbase = virt_to_phys(card->rxbd_ring_vbase);
dev_dbg(adapter->dev,
"info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n",
@@ -486,35 +722,7 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
(u32)((u64)card->rxbd_ring_pbase >> 32),
card->rxbd_ring_size);
- for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
- card->rxbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
- (card->rxbd_ring_vbase +
- (sizeof(struct mwifiex_pcie_buf_desc)
- * i));
-
- /* Allocate skb here so that firmware can DMA data from it */
- skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
- if (!skb) {
- dev_err(adapter->dev,
- "Unable to allocate skb for RX ring.\n");
- kfree(card->rxbd_ring_vbase);
- return -ENOMEM;
- }
- buf_pa = mwifiex_update_sk_buff_pa(skb);
- skb_put(skb, MWIFIEX_RX_DATA_BUF_SIZE);
-
- dev_dbg(adapter->dev, "info: RX ring: add new skb base: %p, "
- "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n",
- skb, skb->data, (u32)*buf_pa, (u32)((u64)*buf_pa >> 32),
- skb->len);
-
- card->rx_buf_list[i] = skb;
- card->rxbd_ring[i]->paddr = *buf_pa;
- card->rxbd_ring[i]->len = (u16)skb->len;
- card->rxbd_ring[i]->flags = 0;
- }
-
- return 0;
+ return mwifiex_init_rxq_ring(adapter);
}
/*
@@ -523,23 +731,19 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- int i;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
- for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) {
- if (card->rx_buf_list[i])
- dev_kfree_skb_any(card->rx_buf_list[i]);
- card->rx_buf_list[i] = NULL;
- card->rxbd_ring[i]->paddr = 0;
- card->rxbd_ring[i]->len = 0;
- card->rxbd_ring[i]->flags = 0;
- card->rxbd_ring[i] = NULL;
- }
+ mwifiex_cleanup_rxq_ring(adapter);
- kfree(card->rxbd_ring_vbase);
+ if (card->rxbd_ring_vbase)
+ pci_free_consistent(card->dev, card->rxbd_ring_size,
+ card->rxbd_ring_vbase,
+ card->rxbd_ring_pbase);
card->rxbd_ring_size = 0;
card->rxbd_wrptr = 0;
- card->rxbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND;
+ card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
card->rxbd_ring_vbase = NULL;
+ card->rxbd_ring_pbase = 0;
return 0;
}
@@ -550,9 +754,7 @@ static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter)
static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- struct sk_buff *skb;
- int i;
- phys_addr_t *buf_pa;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
/*
* driver maintaines the read pointer and firmware maintaines the write
@@ -560,19 +762,22 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
* starts at zero with rollover bit set
*/
card->evtbd_wrptr = 0;
- card->evtbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND;
+ card->evtbd_rdptr = reg->evt_rollover_ind;
+
+ card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) *
+ MWIFIEX_MAX_EVT_BD;
- card->evtbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) *
- MWIFIEX_MAX_EVT_BD;
dev_dbg(adapter->dev, "info: evtbd_ring: Allocating %d bytes\n",
card->evtbd_ring_size);
- card->evtbd_ring_vbase = kzalloc(card->evtbd_ring_size, GFP_KERNEL);
+ card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
+ card->evtbd_ring_size,
+ &card->evtbd_ring_pbase);
if (!card->evtbd_ring_vbase) {
dev_err(adapter->dev,
- "Unable to allocate buffer. Terminating download\n");
+ "allocate consistent memory (%d bytes) failed!\n",
+ card->evtbd_ring_size);
return -ENOMEM;
}
- card->evtbd_ring_pbase = virt_to_phys(card->evtbd_ring_vbase);
dev_dbg(adapter->dev,
"info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n",
@@ -580,35 +785,7 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
(u32)((u64)card->evtbd_ring_pbase >> 32),
card->evtbd_ring_size);
- for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
- card->evtbd_ring[i] = (struct mwifiex_pcie_buf_desc *)
- (card->evtbd_ring_vbase +
- (sizeof(struct mwifiex_pcie_buf_desc)
- * i));
-
- /* Allocate skb here so that firmware can DMA data from it */
- skb = dev_alloc_skb(MAX_EVENT_SIZE);
- if (!skb) {
- dev_err(adapter->dev,
- "Unable to allocate skb for EVENT buf.\n");
- kfree(card->evtbd_ring_vbase);
- return -ENOMEM;
- }
- buf_pa = mwifiex_update_sk_buff_pa(skb);
- skb_put(skb, MAX_EVENT_SIZE);
-
- dev_dbg(adapter->dev, "info: Evt ring: add new skb. base: %p, "
- "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n",
- skb, skb->data, (u32)*buf_pa, (u32)((u64)*buf_pa >> 32),
- skb->len);
-
- card->evt_buf_list[i] = skb;
- card->evtbd_ring[i]->paddr = *buf_pa;
- card->evtbd_ring[i]->len = (u16)skb->len;
- card->evtbd_ring[i]->flags = 0;
- }
-
- return 0;
+ return mwifiex_pcie_init_evt_ring(adapter);
}
/*
@@ -617,23 +794,19 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- int i;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
- for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) {
- if (card->evt_buf_list[i])
- dev_kfree_skb_any(card->evt_buf_list[i]);
- card->evt_buf_list[i] = NULL;
- card->evtbd_ring[i]->paddr = 0;
- card->evtbd_ring[i]->len = 0;
- card->evtbd_ring[i]->flags = 0;
- card->evtbd_ring[i] = NULL;
- }
+ mwifiex_cleanup_evt_ring(adapter);
- kfree(card->evtbd_ring_vbase);
+ if (card->evtbd_ring_vbase)
+ pci_free_consistent(card->dev, card->evtbd_ring_size,
+ card->evtbd_ring_vbase,
+ card->evtbd_ring_pbase);
card->evtbd_wrptr = 0;
- card->evtbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND;
+ card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
card->evtbd_ring_size = 0;
card->evtbd_ring_vbase = NULL;
+ card->evtbd_ring_pbase = 0;
return 0;
}
@@ -653,21 +826,12 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
"Unable to allocate skb for command response data.\n");
return -ENOMEM;
}
- mwifiex_update_sk_buff_pa(skb);
skb_put(skb, MWIFIEX_UPLD_SIZE);
- card->cmdrsp_buf = skb;
+ if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_FROMDEVICE))
+ return -1;
- skb = NULL;
- /* Allocate memory for sending command to firmware */
- skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER);
- if (!skb) {
- dev_err(adapter->dev,
- "Unable to allocate skb for command data.\n");
- return -ENOMEM;
- }
- mwifiex_update_sk_buff_pa(skb);
- skb_put(skb, MWIFIEX_SIZE_OF_CMD_BUFFER);
- card->cmd_buf = skb;
+ card->cmdrsp_buf = skb;
return 0;
}
@@ -678,18 +842,26 @@ static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter)
static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card;
+ dma_addr_t buf_pa;
if (!adapter)
return 0;
card = adapter->card;
- if (card && card->cmdrsp_buf)
+ if (card && card->cmdrsp_buf) {
+ MWIFIEX_SKB_PACB(card->cmdrsp_buf, &buf_pa);
+ pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(card->cmdrsp_buf);
+ }
- if (card && card->cmd_buf)
+ if (card && card->cmd_buf) {
+ MWIFIEX_SKB_PACB(card->cmd_buf, &buf_pa);
+ pci_unmap_single(card->dev, buf_pa, MWIFIEX_SIZE_OF_CMD_BUFFER,
+ PCI_DMA_TODEVICE);
dev_kfree_skb_any(card->cmd_buf);
-
+ }
return 0;
}
@@ -698,27 +870,19 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
*/
static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
{
- struct sk_buff *skb;
struct pcie_service_card *card = adapter->card;
- /* Allocate memory for sleep cookie */
- skb = dev_alloc_skb(sizeof(u32));
- if (!skb) {
- dev_err(adapter->dev,
- "Unable to allocate skb for sleep cookie!\n");
+ card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
+ &card->sleep_cookie_pbase);
+ if (!card->sleep_cookie_vbase) {
+ dev_err(adapter->dev, "pci_alloc_consistent failed!\n");
return -ENOMEM;
}
- mwifiex_update_sk_buff_pa(skb);
- skb_put(skb, sizeof(u32));
-
/* Init val of Sleep Cookie */
- *(u32 *)skb->data = FW_AWAKE_COOKIE;
+ *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE;
dev_dbg(adapter->dev, "alloc_scook: sleep cookie=0x%x\n",
- *((u32 *)skb->data));
-
- /* Save the sleep cookie */
- card->sleep_cookie = skb;
+ *((u32 *)card->sleep_cookie_vbase));
return 0;
}
@@ -735,86 +899,246 @@ static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
card = adapter->card;
- if (card && card->sleep_cookie) {
- dev_kfree_skb_any(card->sleep_cookie);
- card->sleep_cookie = NULL;
+ if (card && card->sleep_cookie_vbase) {
+ pci_free_consistent(card->dev, sizeof(u32),
+ card->sleep_cookie_vbase,
+ card->sleep_cookie_pbase);
+ card->sleep_cookie_vbase = NULL;
}
return 0;
}
+/* This function flushes the TX buffer descriptor ring
+ * This function defined as handler is also called while cleaning TXRX
+ * during disconnect/ bss stop.
+ */
+static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ u32 rdptr;
+
+ /* Read the TX ring read pointer set by firmware */
+ if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
+ dev_err(adapter->dev,
+ "Flush TXBD: failed to read reg->tx_rdptr\n");
+ return -1;
+ }
+
+ if (!mwifiex_pcie_txbd_empty(card, rdptr)) {
+ card->txbd_flush = 1;
+ /* write pointer already set at last send
+ * send dnld-rdy intr again, wait for completion.
+ */
+ if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+ CPU_INTR_DNLD_RDY)) {
+ dev_err(adapter->dev,
+ "failed to assert dnld-rdy interrupt.\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
/*
- * This function sends data buffer to device
+ * This function unmaps and frees downloaded data buffer
*/
-static int
-mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb)
+static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
{
+ struct sk_buff *skb;
+ dma_addr_t buf_pa;
+ u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0;
+ struct mwifiex_pcie_buf_desc *desc;
+ struct mwifiex_pfu_buf_desc *desc2;
struct pcie_service_card *card = adapter->card;
- u32 wrindx, rdptr;
- phys_addr_t *buf_pa;
- __le16 *tmp;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
if (!mwifiex_pcie_ok_to_access_hw(adapter))
mwifiex_pm_wakeup_card(adapter);
/* Read the TX ring read pointer set by firmware */
- if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) {
+ if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) {
dev_err(adapter->dev,
- "SEND DATA: failed to read REG_TXBD_RDPTR\n");
+ "SEND COMP: failed to read reg->tx_rdptr\n");
return -1;
}
- wrindx = card->txbd_wrptr & MWIFIEX_TXBD_MASK;
+ dev_dbg(adapter->dev, "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n",
+ card->txbd_rdptr, rdptr);
- dev_dbg(adapter->dev, "info: SEND DATA: <Rd: %#x, Wr: %#x>\n", rdptr,
- card->txbd_wrptr);
- if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) !=
- (rdptr & MWIFIEX_TXBD_MASK)) ||
- ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) !=
- (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) {
- struct sk_buff *skb_data;
+ num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
+ /* free from previous txbd_rdptr to current txbd_rdptr */
+ while (((card->txbd_rdptr & reg->tx_mask) !=
+ (rdptr & reg->tx_mask)) ||
+ ((card->txbd_rdptr & reg->tx_rollover_ind) !=
+ (rdptr & reg->tx_rollover_ind))) {
+ wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >>
+ reg->tx_start_ptr;
+
+ skb = card->tx_buf_list[wrdoneidx];
+ if (skb) {
+ dev_dbg(adapter->dev,
+ "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
+ skb, wrdoneidx);
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+ pci_unmap_single(card->dev, buf_pa, skb->len,
+ PCI_DMA_TODEVICE);
+
+ unmap_count++;
+
+ if (card->txbd_flush)
+ mwifiex_write_data_complete(adapter, skb, 0,
+ -1);
+ else
+ mwifiex_write_data_complete(adapter, skb, 0, 0);
+ }
+
+ card->tx_buf_list[wrdoneidx] = NULL;
+
+ if (reg->pfu_enabled) {
+ desc2 = (void *)card->txbd_ring[wrdoneidx];
+ memset(desc2, 0, sizeof(*desc2));
+ } else {
+ desc = card->txbd_ring[wrdoneidx];
+ memset(desc, 0, sizeof(*desc));
+ }
+ switch (card->dev->device) {
+ case PCIE_DEVICE_ID_MARVELL_88W8766P:
+ card->txbd_rdptr++;
+ break;
+ case PCIE_DEVICE_ID_MARVELL_88W8897:
+ card->txbd_rdptr += reg->ring_tx_start_ptr;
+ break;
+ }
+
+
+ if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs)
+ card->txbd_rdptr = ((card->txbd_rdptr &
+ reg->tx_rollover_ind) ^
+ reg->tx_rollover_ind);
+ }
+
+ if (unmap_count)
+ adapter->data_sent = false;
+
+ if (card->txbd_flush) {
+ if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr))
+ card->txbd_flush = 0;
+ else
+ mwifiex_clean_pcie_ring_buf(adapter);
+ }
+
+ return 0;
+}
+
+/* This function sends data buffer to device. First 4 bytes of payload
+ * are filled with payload length and payload type. Then this payload
+ * is mapped to PCI device memory. Tx ring pointers are advanced accordingly.
+ * Download ready interrupt to FW is deffered if Tx ring is not full and
+ * additional payload can be accomodated.
+ */
+static int
+mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
+ struct mwifiex_tx_param *tx_param)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ u32 wrindx, num_tx_buffs, rx_val;
+ int ret;
+ dma_addr_t buf_pa;
+ struct mwifiex_pcie_buf_desc *desc;
+ struct mwifiex_pfu_buf_desc *desc2;
+ __le16 *tmp;
+
+ if (!(skb->data && skb->len)) {
+ dev_err(adapter->dev, "%s(): invalid parameter <%p, %#x>\n",
+ __func__, skb->data, skb->len);
+ return -1;
+ }
+
+ if (!mwifiex_pcie_ok_to_access_hw(adapter))
+ mwifiex_pm_wakeup_card(adapter);
+
+ num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr;
+ dev_dbg(adapter->dev, "info: SEND DATA: <Rd: %#x, Wr: %#x>\n",
+ card->txbd_rdptr, card->txbd_wrptr);
+ if (mwifiex_pcie_txbd_not_full(card)) {
u8 *payload;
adapter->data_sent = true;
- skb_data = card->tx_buf_list[wrindx];
- memcpy(skb_data->data, skb->data, skb->len);
- payload = skb_data->data;
+ payload = skb->data;
tmp = (__le16 *)&payload[0];
*tmp = cpu_to_le16((u16)skb->len);
tmp = (__le16 *)&payload[2];
*tmp = cpu_to_le16(MWIFIEX_TYPE_DATA);
- skb_put(skb_data, MWIFIEX_RX_DATA_BUF_SIZE - skb_data->len);
- skb_trim(skb_data, skb->len);
- buf_pa = MWIFIEX_SKB_PACB(skb_data);
- card->txbd_ring[wrindx]->paddr = *buf_pa;
- card->txbd_ring[wrindx]->len = (u16)skb_data->len;
- card->txbd_ring[wrindx]->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
- MWIFIEX_BD_FLAG_LAST_DESC;
-
- if ((++card->txbd_wrptr & MWIFIEX_TXBD_MASK) ==
- MWIFIEX_MAX_TXRX_BD)
- card->txbd_wrptr = ((card->txbd_wrptr &
- MWIFIEX_BD_FLAG_ROLLOVER_IND) ^
- MWIFIEX_BD_FLAG_ROLLOVER_IND);
- /* Write the TX ring write pointer in to REG_TXBD_WRPTR */
- if (mwifiex_write_reg(adapter, REG_TXBD_WRPTR,
- card->txbd_wrptr)) {
- dev_err(adapter->dev,
- "SEND DATA: failed to write REG_TXBD_WRPTR\n");
- return 0;
+ if (mwifiex_map_pci_memory(adapter, skb, skb->len ,
+ PCI_DMA_TODEVICE))
+ return -1;
+
+ wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+ card->tx_buf_list[wrindx] = skb;
+
+ if (reg->pfu_enabled) {
+ desc2 = (void *)card->txbd_ring[wrindx];
+ desc2->paddr = buf_pa;
+ desc2->len = (u16)skb->len;
+ desc2->frag_len = (u16)skb->len;
+ desc2->offset = 0;
+ desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
+ MWIFIEX_BD_FLAG_LAST_DESC;
+ } else {
+ desc = card->txbd_ring[wrindx];
+ desc->paddr = buf_pa;
+ desc->len = (u16)skb->len;
+ desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC |
+ MWIFIEX_BD_FLAG_LAST_DESC;
}
- /* Send the TX ready interrupt */
- if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
- CPU_INTR_DNLD_RDY)) {
+ switch (card->dev->device) {
+ case PCIE_DEVICE_ID_MARVELL_88W8766P:
+ card->txbd_wrptr++;
+ break;
+ case PCIE_DEVICE_ID_MARVELL_88W8897:
+ card->txbd_wrptr += reg->ring_tx_start_ptr;
+ break;
+ }
+
+ if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs)
+ card->txbd_wrptr = ((card->txbd_wrptr &
+ reg->tx_rollover_ind) ^
+ reg->tx_rollover_ind);
+
+ rx_val = card->rxbd_rdptr & reg->rx_wrap_mask;
+ /* Write the TX ring write pointer in to reg->tx_wrptr */
+ if (mwifiex_write_reg(adapter, reg->tx_wrptr,
+ card->txbd_wrptr | rx_val)) {
dev_err(adapter->dev,
- "SEND DATA: failed to assert door-bell intr\n");
- return -1;
+ "SEND DATA: failed to write reg->tx_wrptr\n");
+ ret = -1;
+ goto done_unmap;
+ }
+ if ((mwifiex_pcie_txbd_not_full(card)) &&
+ tx_param->next_pkt_len) {
+ /* have more packets and TxBD still can hold more */
+ dev_dbg(adapter->dev,
+ "SEND DATA: delay dnld-rdy interrupt.\n");
+ adapter->data_sent = false;
+ } else {
+ /* Send the TX ready interrupt */
+ if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+ CPU_INTR_DNLD_RDY)) {
+ dev_err(adapter->dev,
+ "SEND DATA: failed to assert dnld-rdy interrupt.\n");
+ ret = -1;
+ goto done_unmap;
+ }
}
dev_dbg(adapter->dev, "info: SEND DATA: Updated <Rd: %#x, Wr: "
"%#x> and sent packet to firmware successfully\n",
- rdptr, card->txbd_wrptr);
+ card->txbd_rdptr, card->txbd_wrptr);
} else {
dev_dbg(adapter->dev,
"info: TX Ring full, can't send packets to fw\n");
@@ -827,7 +1151,17 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb)
return -EBUSY;
}
- return 0;
+ return -EINPROGRESS;
+done_unmap:
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+ pci_unmap_single(card->dev, buf_pa, skb->len, PCI_DMA_TODEVICE);
+ card->tx_buf_list[wrindx] = NULL;
+ if (reg->pfu_enabled)
+ memset(desc2, 0, sizeof(*desc2));
+ else
+ memset(desc, 0, sizeof(*desc));
+
+ return ret;
}
/*
@@ -837,78 +1171,119 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb)
static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
- u32 wrptr, rd_index;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ u32 wrptr, rd_index, tx_val;
+ dma_addr_t buf_pa;
int ret = 0;
struct sk_buff *skb_tmp = NULL;
+ struct mwifiex_pcie_buf_desc *desc;
+ struct mwifiex_pfu_buf_desc *desc2;
+
+ if (!mwifiex_pcie_ok_to_access_hw(adapter))
+ mwifiex_pm_wakeup_card(adapter);
/* Read the RX ring Write pointer set by firmware */
- if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) {
+ if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
dev_err(adapter->dev,
- "RECV DATA: failed to read REG_TXBD_RDPTR\n");
+ "RECV DATA: failed to read reg->rx_wrptr\n");
ret = -1;
goto done;
}
+ card->rxbd_wrptr = wrptr;
- while (((wrptr & MWIFIEX_RXBD_MASK) !=
- (card->rxbd_rdptr & MWIFIEX_RXBD_MASK)) ||
- ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) ==
- (card->rxbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) {
+ while (((wrptr & reg->rx_mask) !=
+ (card->rxbd_rdptr & reg->rx_mask)) ||
+ ((wrptr & reg->rx_rollover_ind) ==
+ (card->rxbd_rdptr & reg->rx_rollover_ind))) {
struct sk_buff *skb_data;
u16 rx_len;
+ __le16 pkt_len;
- rd_index = card->rxbd_rdptr & MWIFIEX_RXBD_MASK;
+ rd_index = card->rxbd_rdptr & reg->rx_mask;
skb_data = card->rx_buf_list[rd_index];
+ MWIFIEX_SKB_PACB(skb_data, &buf_pa);
+ pci_unmap_single(card->dev, buf_pa, MWIFIEX_RX_DATA_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
+ card->rx_buf_list[rd_index] = NULL;
+
/* Get data length from interface header -
- first byte is len, second byte is type */
- rx_len = *((u16 *)skb_data->data);
+ * first 2 bytes for len, next 2 bytes is for type
+ */
+ pkt_len = *((__le16 *)skb_data->data);
+ rx_len = le16_to_cpu(pkt_len);
+ skb_put(skb_data, rx_len);
dev_dbg(adapter->dev,
"info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n",
card->rxbd_rdptr, wrptr, rx_len);
- skb_tmp = dev_alloc_skb(rx_len);
+ skb_pull(skb_data, INTF_HEADER_LEN);
+ mwifiex_handle_rx_packet(adapter, skb_data);
+
+ skb_tmp = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE);
if (!skb_tmp) {
- dev_dbg(adapter->dev,
- "info: Failed to alloc skb for RX\n");
- ret = -EBUSY;
- goto done;
+ dev_err(adapter->dev,
+ "Unable to allocate skb.\n");
+ return -ENOMEM;
}
- skb_put(skb_tmp, rx_len);
+ if (mwifiex_map_pci_memory(adapter, skb_tmp,
+ MWIFIEX_RX_DATA_BUF_SIZE,
+ PCI_DMA_FROMDEVICE))
+ return -1;
+
+ MWIFIEX_SKB_PACB(skb_tmp, &buf_pa);
+
+ dev_dbg(adapter->dev,
+ "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n",
+ skb_tmp, rd_index);
+ card->rx_buf_list[rd_index] = skb_tmp;
+
+ if (reg->pfu_enabled) {
+ desc2 = (void *)card->rxbd_ring[rd_index];
+ desc2->paddr = buf_pa;
+ desc2->len = skb_tmp->len;
+ desc2->frag_len = skb_tmp->len;
+ desc2->offset = 0;
+ desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop;
+ } else {
+ desc = card->rxbd_ring[rd_index];
+ desc->paddr = buf_pa;
+ desc->len = skb_tmp->len;
+ desc->flags = 0;
+ }
- memcpy(skb_tmp->data, skb_data->data + INTF_HEADER_LEN, rx_len);
- if ((++card->rxbd_rdptr & MWIFIEX_RXBD_MASK) ==
+ if ((++card->rxbd_rdptr & reg->rx_mask) ==
MWIFIEX_MAX_TXRX_BD) {
card->rxbd_rdptr = ((card->rxbd_rdptr &
- MWIFIEX_BD_FLAG_ROLLOVER_IND) ^
- MWIFIEX_BD_FLAG_ROLLOVER_IND);
+ reg->rx_rollover_ind) ^
+ reg->rx_rollover_ind);
}
dev_dbg(adapter->dev, "info: RECV DATA: <Rd: %#x, Wr: %#x>\n",
card->rxbd_rdptr, wrptr);
- /* Write the RX ring read pointer in to REG_RXBD_RDPTR */
- if (mwifiex_write_reg(adapter, REG_RXBD_RDPTR,
- card->rxbd_rdptr)) {
+ tx_val = card->txbd_wrptr & reg->tx_wrap_mask;
+ /* Write the RX ring read pointer in to reg->rx_rdptr */
+ if (mwifiex_write_reg(adapter, reg->rx_rdptr,
+ card->rxbd_rdptr | tx_val)) {
dev_err(adapter->dev,
- "RECV DATA: failed to write REG_RXBD_RDPTR\n");
+ "RECV DATA: failed to write reg->rx_rdptr\n");
ret = -1;
goto done;
}
/* Read the RX ring Write pointer set by firmware */
- if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) {
+ if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) {
dev_err(adapter->dev,
- "RECV DATA: failed to read REG_TXBD_RDPTR\n");
+ "RECV DATA: failed to read reg->rx_wrptr\n");
ret = -1;
goto done;
}
dev_dbg(adapter->dev,
"info: RECV DATA: Rcvd packet from fw successfully\n");
- mwifiex_handle_rx_packet(adapter, skb_tmp);
+ card->rxbd_wrptr = wrptr;
}
done:
- if (ret && skb_tmp)
- dev_kfree_skb_any(skb_tmp);
return ret;
}
@@ -918,40 +1293,54 @@ done:
static int
mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
{
- phys_addr_t *buf_pa = MWIFIEX_SKB_PACB(skb);
+ dma_addr_t buf_pa;
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
- if (!(skb->data && skb->len && *buf_pa)) {
+ if (!(skb->data && skb->len)) {
dev_err(adapter->dev,
- "Invalid parameter in %s <%p, %#x:%x, %x>\n",
- __func__, skb->data, skb->len,
- (u32)*buf_pa, (u32)((u64)*buf_pa >> 32));
+ "Invalid parameter in %s <%p. len %d>\n",
+ __func__, skb->data, skb->len);
return -1;
}
- /* Write the lower 32bits of the physical address to scratch
- * register 0 */
- if (mwifiex_write_reg(adapter, PCIE_SCRATCH_0_REG, (u32)*buf_pa)) {
+ if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE))
+ return -1;
+
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+
+ /* Write the lower 32bits of the physical address to low command
+ * address scratch register
+ */
+ if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) {
dev_err(adapter->dev,
"%s: failed to write download command to boot code.\n",
__func__);
+ pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_TODEVICE);
return -1;
}
- /* Write the upper 32bits of the physical address to scratch
- * register 1 */
- if (mwifiex_write_reg(adapter, PCIE_SCRATCH_1_REG,
- (u32)((u64)*buf_pa >> 32))) {
+ /* Write the upper 32bits of the physical address to high command
+ * address scratch register
+ */
+ if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
+ (u32)((u64)buf_pa >> 32))) {
dev_err(adapter->dev,
"%s: failed to write download command to boot code.\n",
__func__);
+ pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_TODEVICE);
return -1;
}
- /* Write the command length to scratch register 2 */
- if (mwifiex_write_reg(adapter, PCIE_SCRATCH_2_REG, skb->len)) {
+ /* Write the command length to cmd_size scratch register */
+ if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) {
dev_err(adapter->dev,
- "%s: failed to write command len to scratch reg 2\n",
+ "%s: failed to write command len to cmd_size scratch reg\n",
__func__);
+ pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_TODEVICE);
return -1;
}
@@ -960,22 +1349,43 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
CPU_INTR_DOOR_BELL)) {
dev_err(adapter->dev,
"%s: failed to assert door-bell intr\n", __func__);
+ pci_unmap_single(card->dev, buf_pa,
+ MWIFIEX_UPLD_SIZE, PCI_DMA_TODEVICE);
return -1;
}
return 0;
}
-/*
- * This function downloads commands to the device
+/* This function init rx port in firmware which in turn enables to receive data
+ * from device before transmitting any packet.
+ */
+static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
+ int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask;
+
+ /* Write the RX ring read pointer in to reg->rx_rdptr */
+ if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr |
+ tx_wrap)) {
+ dev_err(adapter->dev,
+ "RECV DATA: failed to write reg->rx_rdptr\n");
+ return -1;
+ }
+ return 0;
+}
+
+/* This function downloads commands to the device
*/
static int
mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
{
struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
int ret = 0;
- phys_addr_t *cmd_buf_pa;
- phys_addr_t *cmdrsp_buf_pa;
+ dma_addr_t cmd_buf_pa, cmdrsp_buf_pa;
+ u8 *payload = (u8 *)skb->data;
if (!(skb->data && skb->len)) {
dev_err(adapter->dev, "Invalid parameter in %s <%p, %#x>\n",
@@ -990,21 +1400,22 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
return -EBUSY;
}
- /* Make sure a command buffer is available */
- if (!card->cmd_buf) {
- dev_err(adapter->dev, "Command buffer not available\n");
- return -EBUSY;
- }
+ if (!mwifiex_pcie_ok_to_access_hw(adapter))
+ mwifiex_pm_wakeup_card(adapter);
adapter->cmd_sent = true;
- /* Copy the given skb in to DMA accessable shared buffer */
- skb_put(card->cmd_buf, MWIFIEX_SIZE_OF_CMD_BUFFER - card->cmd_buf->len);
- skb_trim(card->cmd_buf, skb->len);
- memcpy(card->cmd_buf->data, skb->data, skb->len);
+
+ *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len);
+ *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD);
+
+ if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
+ return -1;
+
+ card->cmd_buf = skb;
/* To send a command, the driver will:
1. Write the 64bit physical address of the data buffer to
- SCRATCH1 + SCRATCH0
+ cmd response address low + cmd response address high
2. Ring the door bell (i.e. set the door bell interrupt)
In response to door bell interrupt, the firmware will perform
@@ -1013,11 +1424,11 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
*/
if (card->cmdrsp_buf) {
- cmdrsp_buf_pa = MWIFIEX_SKB_PACB(card->cmdrsp_buf);
+ MWIFIEX_SKB_PACB(card->cmdrsp_buf, &cmdrsp_buf_pa);
/* Write the lower 32bits of the cmdrsp buffer physical
address */
- if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO,
- (u32)*cmdrsp_buf_pa)) {
+ if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo,
+ (u32)cmdrsp_buf_pa)) {
dev_err(adapter->dev,
"Failed to write download cmd to boot code.\n");
ret = -1;
@@ -1025,8 +1436,8 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
}
/* Write the upper 32bits of the cmdrsp buffer physical
address */
- if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI,
- (u32)((u64)*cmdrsp_buf_pa >> 32))) {
+ if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi,
+ (u32)((u64)cmdrsp_buf_pa >> 32))) {
dev_err(adapter->dev,
"Failed to write download cmd to boot code.\n");
ret = -1;
@@ -1034,27 +1445,29 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb)
}
}
- cmd_buf_pa = MWIFIEX_SKB_PACB(card->cmd_buf);
- /* Write the lower 32bits of the physical address to REG_CMD_ADDR_LO */
- if (mwifiex_write_reg(adapter, REG_CMD_ADDR_LO, (u32)*cmd_buf_pa)) {
+ MWIFIEX_SKB_PACB(card->cmd_buf, &cmd_buf_pa);
+ /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */
+ if (mwifiex_write_reg(adapter, reg->cmd_addr_lo,
+ (u32)cmd_buf_pa)) {
dev_err(adapter->dev,
"Failed to write download cmd to boot code.\n");
ret = -1;
goto done;
}
- /* Write the upper 32bits of the physical address to REG_CMD_ADDR_HI */
- if (mwifiex_write_reg(adapter, REG_CMD_ADDR_HI,
- (u32)((u64)*cmd_buf_pa >> 32))) {
+ /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */
+ if (mwifiex_write_reg(adapter, reg->cmd_addr_hi,
+ (u32)((u64)cmd_buf_pa >> 32))) {
dev_err(adapter->dev,
"Failed to write download cmd to boot code.\n");
ret = -1;
goto done;
}
- /* Write the command length to REG_CMD_SIZE */
- if (mwifiex_write_reg(adapter, REG_CMD_SIZE, card->cmd_buf->len)) {
+ /* Write the command length to reg->cmd_size */
+ if (mwifiex_write_reg(adapter, reg->cmd_size,
+ card->cmd_buf->len)) {
dev_err(adapter->dev,
- "Failed to write cmd len to REG_CMD_SIZE\n");
+ "Failed to write cmd len to reg->cmd_size\n");
ret = -1;
goto done;
}
@@ -1081,18 +1494,30 @@ done:
static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
struct sk_buff *skb = card->cmdrsp_buf;
int count = 0;
+ u16 rx_len;
+ __le16 pkt_len;
+ dma_addr_t buf_pa;
dev_dbg(adapter->dev, "info: Rx CMD Response\n");
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+ pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_FROMDEVICE);
+
+ pkt_len = *((__le16 *)skb->data);
+ rx_len = le16_to_cpu(pkt_len);
+ skb_trim(skb, rx_len);
+ skb_pull(skb, INTF_HEADER_LEN);
+
if (!adapter->curr_cmd) {
- skb_pull(skb, INTF_HEADER_LEN);
if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
mwifiex_process_sleep_confirm_resp(adapter, skb->data,
skb->len);
- while (mwifiex_pcie_ok_to_access_hw(adapter) &&
- (count++ < 10))
+ while (reg->sleep_cookie && (count++ < 10) &&
+ mwifiex_pcie_ok_to_access_hw(adapter))
usleep_range(50, 60);
} else {
dev_err(adapter->dev,
@@ -1100,9 +1525,12 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
}
memcpy(adapter->upld_buf, skb->data,
min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
- skb_push(skb, INTF_HEADER_LEN);
+ if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_FROMDEVICE))
+ return -1;
+
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
} else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
- skb_pull(skb, INTF_HEADER_LEN);
adapter->curr_cmd->resp_skb = skb;
adapter->cmd_resp_received = true;
/* Take the pointer and set it to CMD node and will
@@ -1112,14 +1540,14 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
/* Clear the cmd-rsp buffer address in scratch registers. This
will prevent firmware from writing to the same response
buffer again. */
- if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, 0)) {
+ if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) {
dev_err(adapter->dev,
"cmd_done: failed to clear cmd_rsp_addr_lo\n");
return -1;
}
/* Write the upper 32bits of the cmdrsp buffer physical
address */
- if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, 0)) {
+ if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) {
dev_err(adapter->dev,
"cmd_done: failed to clear cmd_rsp_addr_hi\n");
return -1;
@@ -1136,10 +1564,23 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
struct sk_buff *skb)
{
struct pcie_service_card *card = adapter->card;
+ dma_addr_t buf_pa;
+ struct sk_buff *skb_tmp;
if (skb) {
card->cmdrsp_buf = skb;
skb_push(card->cmdrsp_buf, INTF_HEADER_LEN);
+ if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_FROMDEVICE))
+ return -1;
+ }
+
+ skb_tmp = card->cmd_buf;
+ if (skb_tmp) {
+ MWIFIEX_SKB_PACB(skb_tmp, &buf_pa);
+ pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE,
+ PCI_DMA_FROMDEVICE);
+ card->cmd_buf = NULL;
}
return 0;
@@ -1151,8 +1592,14 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter,
static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
u32 wrptr, event;
+ dma_addr_t buf_pa;
+ struct mwifiex_evt_buf_desc *desc;
+
+ if (!mwifiex_pcie_ok_to_access_hw(adapter))
+ mwifiex_pm_wakeup_card(adapter);
if (adapter->event_received) {
dev_dbg(adapter->dev, "info: Event being processed, "
@@ -1166,9 +1613,9 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
}
/* Read the event ring write pointer set by firmware */
- if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) {
+ if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
dev_err(adapter->dev,
- "EventReady: failed to read REG_EVTBD_WRPTR\n");
+ "EventReady: failed to read reg->evt_wrptr\n");
return -1;
}
@@ -1176,20 +1623,23 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter)
card->evtbd_rdptr, wrptr);
if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr
& MWIFIEX_EVTBD_MASK)) ||
- ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) ==
- (card->evtbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) {
+ ((wrptr & reg->evt_rollover_ind) ==
+ (card->evtbd_rdptr & reg->evt_rollover_ind))) {
struct sk_buff *skb_cmd;
__le16 data_len = 0;
u16 evt_len;
dev_dbg(adapter->dev, "info: Read Index: %d\n", rdptr);
skb_cmd = card->evt_buf_list[rdptr];
+ MWIFIEX_SKB_PACB(skb_cmd, &buf_pa);
+ pci_unmap_single(card->dev, buf_pa, MAX_EVENT_SIZE,
+ PCI_DMA_FROMDEVICE);
+
/* Take the pointer and set it to event pointer in adapter
and will return back after event handling callback */
card->evt_buf_list[rdptr] = NULL;
- card->evtbd_ring[rdptr]->paddr = 0;
- card->evtbd_ring[rdptr]->len = 0;
- card->evtbd_ring[rdptr]->flags = 0;
+ desc = card->evtbd_ring[rdptr];
+ memset(desc, 0, sizeof(*desc));
event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN];
adapter->event_cause = event;
@@ -1225,10 +1675,12 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
struct sk_buff *skb)
{
struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
int ret = 0;
u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK;
u32 wrptr;
- phys_addr_t *buf_pa;
+ dma_addr_t buf_pa;
+ struct mwifiex_evt_buf_desc *desc;
if (!skb)
return 0;
@@ -1240,19 +1692,25 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
}
/* Read the event ring write pointer set by firmware */
- if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) {
+ if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) {
dev_err(adapter->dev,
- "event_complete: failed to read REG_EVTBD_WRPTR\n");
+ "event_complete: failed to read reg->evt_wrptr\n");
return -1;
}
if (!card->evt_buf_list[rdptr]) {
skb_push(skb, INTF_HEADER_LEN);
+ if (mwifiex_map_pci_memory(adapter, skb,
+ MAX_EVENT_SIZE,
+ PCI_DMA_FROMDEVICE))
+ return -1;
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
card->evt_buf_list[rdptr] = skb;
- buf_pa = MWIFIEX_SKB_PACB(skb);
- card->evtbd_ring[rdptr]->paddr = *buf_pa;
- card->evtbd_ring[rdptr]->len = (u16)skb->len;
- card->evtbd_ring[rdptr]->flags = 0;
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+ desc = card->evtbd_ring[rdptr];
+ desc->paddr = buf_pa;
+ desc->len = (u16)skb->len;
+ desc->flags = 0;
skb = NULL;
} else {
dev_dbg(adapter->dev,
@@ -1262,17 +1720,18 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter,
if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) {
card->evtbd_rdptr = ((card->evtbd_rdptr &
- MWIFIEX_BD_FLAG_ROLLOVER_IND) ^
- MWIFIEX_BD_FLAG_ROLLOVER_IND);
+ reg->evt_rollover_ind) ^
+ reg->evt_rollover_ind);
}
dev_dbg(adapter->dev, "info: Updated <Rd: 0x%x, Wr: 0x%x>",
card->evtbd_rdptr, wrptr);
- /* Write the event ring read pointer in to REG_EVTBD_RDPTR */
- if (mwifiex_write_reg(adapter, REG_EVTBD_RDPTR, card->evtbd_rdptr)) {
+ /* Write the event ring read pointer in to reg->evt_rdptr */
+ if (mwifiex_write_reg(adapter, reg->evt_rdptr,
+ card->evtbd_rdptr)) {
dev_err(adapter->dev,
- "event_complete: failed to read REG_EVTBD_RDPTR\n");
+ "event_complete: failed to read reg->evt_rdptr\n");
return -1;
}
@@ -1299,11 +1758,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
struct sk_buff *skb;
u32 txlen, tx_blocks = 0, tries, len;
u32 block_retry_cnt = 0;
-
- if (!adapter) {
- pr_err("adapter structure is not valid\n");
- return -1;
- }
+ dma_addr_t buf_pa;
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
if (!firmware || !firmware_len) {
dev_err(adapter->dev,
@@ -1325,7 +1782,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
ret = -ENOMEM;
goto done;
}
- mwifiex_update_sk_buff_pa(skb);
/* Perform firmware data transfer */
do {
@@ -1336,7 +1792,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
break;
for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
- ret = mwifiex_read_reg(adapter, PCIE_SCRATCH_2_REG,
+ ret = mwifiex_read_reg(adapter, reg->cmd_size,
&len);
if (ret) {
dev_warn(adapter->dev,
@@ -1382,16 +1838,15 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
dev_dbg(adapter->dev, ".");
- tx_blocks = (txlen +
- MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD - 1) /
- MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD;
+ tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) /
+ card->pcie.blksz_fw_dl;
/* Copy payload to buffer */
memmove(skb->data, &firmware[offset], txlen);
}
skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
- skb_trim(skb, tx_blocks * MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD);
+ skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl);
/* Send the boot command to device */
if (mwifiex_pcie_send_boot_cmd(adapter, skb)) {
@@ -1400,6 +1855,9 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
ret = -1;
goto done;
}
+
+ MWIFIEX_SKB_PACB(skb, &buf_pa);
+
/* Wait for the command done interrupt */
do {
if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS,
@@ -1407,11 +1865,17 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter,
dev_err(adapter->dev, "%s: Failed to read "
"interrupt status during fw dnld.\n",
__func__);
+ pci_unmap_single(card->dev, buf_pa, skb->len,
+ PCI_DMA_TODEVICE);
ret = -1;
goto done;
}
} while ((ireg_intr & CPU_INTR_DOOR_BELL) ==
CPU_INTR_DOOR_BELL);
+
+ pci_unmap_single(card->dev, buf_pa, skb->len,
+ PCI_DMA_TODEVICE);
+
offset += txlen;
} while (true);
@@ -1435,6 +1899,8 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
{
int ret = 0;
u32 firmware_stat, winner_status;
+ struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
u32 tries;
/* Mask spurios interrupts */
@@ -1445,7 +1911,8 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
}
dev_dbg(adapter->dev, "Setting driver ready signature\n");
- if (mwifiex_write_reg(adapter, REG_DRV_READY, FIRMWARE_READY_PCIE)) {
+ if (mwifiex_write_reg(adapter, reg->drv_rdy,
+ FIRMWARE_READY_PCIE)) {
dev_err(adapter->dev,
"Failed to write driver ready signature\n");
return -1;
@@ -1453,7 +1920,7 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
/* Wait for firmware initialization event */
for (tries = 0; tries < poll_num; tries++) {
- if (mwifiex_read_reg(adapter, PCIE_SCRATCH_3_REG,
+ if (mwifiex_read_reg(adapter, reg->fw_status,
&firmware_stat))
ret = -1;
else
@@ -1470,7 +1937,7 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num)
}
if (ret) {
- if (mwifiex_read_reg(adapter, PCIE_SCRATCH_3_REG,
+ if (mwifiex_read_reg(adapter, reg->fw_status,
&winner_status))
ret = -1;
else if (!winner_status) {
@@ -1594,39 +2061,40 @@ exit:
static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
{
int ret;
- u32 pcie_ireg = 0;
+ u32 pcie_ireg;
unsigned long flags;
spin_lock_irqsave(&adapter->int_lock, flags);
/* Clear out unused interrupts */
- adapter->int_status &= HOST_INTR_MASK;
+ pcie_ireg = adapter->int_status;
+ adapter->int_status = 0;
spin_unlock_irqrestore(&adapter->int_lock, flags);
- while (adapter->int_status & HOST_INTR_MASK) {
- if (adapter->int_status & HOST_INTR_DNLD_DONE) {
- adapter->int_status &= ~HOST_INTR_DNLD_DONE;
- if (adapter->data_sent) {
- dev_dbg(adapter->dev, "info: DATA sent intr\n");
- adapter->data_sent = false;
- }
+ while (pcie_ireg & HOST_INTR_MASK) {
+ if (pcie_ireg & HOST_INTR_DNLD_DONE) {
+ pcie_ireg &= ~HOST_INTR_DNLD_DONE;
+ dev_dbg(adapter->dev, "info: TX DNLD Done\n");
+ ret = mwifiex_pcie_send_data_complete(adapter);
+ if (ret)
+ return ret;
}
- if (adapter->int_status & HOST_INTR_UPLD_RDY) {
- adapter->int_status &= ~HOST_INTR_UPLD_RDY;
+ if (pcie_ireg & HOST_INTR_UPLD_RDY) {
+ pcie_ireg &= ~HOST_INTR_UPLD_RDY;
dev_dbg(adapter->dev, "info: Rx DATA\n");
ret = mwifiex_pcie_process_recv_data(adapter);
if (ret)
return ret;
}
- if (adapter->int_status & HOST_INTR_EVENT_RDY) {
- adapter->int_status &= ~HOST_INTR_EVENT_RDY;
+ if (pcie_ireg & HOST_INTR_EVENT_RDY) {
+ pcie_ireg &= ~HOST_INTR_EVENT_RDY;
dev_dbg(adapter->dev, "info: Rx EVENT\n");
ret = mwifiex_pcie_process_event_ready(adapter);
if (ret)
return ret;
}
- if (adapter->int_status & HOST_INTR_CMD_DONE) {
- adapter->int_status &= ~HOST_INTR_CMD_DONE;
+ if (pcie_ireg & HOST_INTR_CMD_DONE) {
+ pcie_ireg &= ~HOST_INTR_CMD_DONE;
if (adapter->cmd_sent) {
dev_dbg(adapter->dev,
"info: CMD sent Interrupt\n");
@@ -1654,8 +2122,6 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
"Write register failed\n");
return -1;
}
- adapter->int_status |= pcie_ireg;
- adapter->int_status &= HOST_INTR_MASK;
}
}
@@ -1687,7 +2153,7 @@ static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type,
}
if (type == MWIFIEX_TYPE_DATA)
- return mwifiex_pcie_send_data(adapter, skb);
+ return mwifiex_pcie_send_data(adapter, skb, tx_param);
else if (type == MWIFIEX_TYPE_CMD)
return mwifiex_pcie_send_cmd(adapter, skb);
@@ -1709,6 +2175,7 @@ static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
struct pcie_service_card *card = adapter->card;
int ret;
struct pci_dev *pdev = card->dev;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
pci_set_drvdata(pdev, card);
@@ -1739,6 +2206,7 @@ static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
card->pci_mmap = pci_iomap(pdev, 0, 0);
if (!card->pci_mmap) {
dev_err(adapter->dev, "iomap(0) error\n");
+ ret = -EIO;
goto err_iomap0;
}
ret = pci_request_region(pdev, 2, DRV_NAME);
@@ -1749,6 +2217,7 @@ static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
card->pci_mmap1 = pci_iomap(pdev, 2, 0);
if (!card->pci_mmap1) {
dev_err(adapter->dev, "iomap(2) error\n");
+ ret = -EIO;
goto err_iomap2;
}
@@ -1769,10 +2238,13 @@ static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter);
if (ret)
goto err_alloc_cmdbuf;
- ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
- if (ret)
- goto err_alloc_cookie;
-
+ if (reg->sleep_cookie) {
+ ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter);
+ if (ret)
+ goto err_alloc_cookie;
+ } else {
+ card->sleep_cookie_vbase = NULL;
+ }
return ret;
err_alloc_cookie:
@@ -1813,17 +2285,11 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
struct pci_dev *pdev = card->dev;
+ const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
- mwifiex_pcie_delete_sleep_cookie_buf(adapter);
- mwifiex_pcie_delete_cmdrsp_buf(adapter);
- mwifiex_pcie_delete_evtbd_ring(adapter);
- mwifiex_pcie_delete_rxbd_ring(adapter);
- mwifiex_pcie_delete_txbd_ring(adapter);
- card->cmdrsp_buf = NULL;
-
- dev_dbg(adapter->dev, "Clearing driver ready signature\n");
if (user_rmmod) {
- if (mwifiex_write_reg(adapter, REG_DRV_READY, 0x00000000))
+ dev_dbg(adapter->dev, "Clearing driver ready signature\n");
+ if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000))
dev_err(adapter->dev,
"Failed to write driver not-ready signature\n");
}
@@ -1861,7 +2327,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
}
adapter->dev = &pdev->dev;
- strcpy(adapter->fw_name, PCIE8766_DEFAULT_FW_NAME);
+ strcpy(adapter->fw_name, card->pcie.firmware);
return 0;
}
@@ -1875,10 +2341,21 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
{
struct pcie_service_card *card = adapter->card;
+ const struct mwifiex_pcie_card_reg *reg;
if (card) {
dev_dbg(adapter->dev, "%s(): calling free_irq()\n", __func__);
free_irq(card->dev->irq, card->dev);
+
+ reg = card->pcie.reg;
+ if (reg->sleep_cookie)
+ mwifiex_pcie_delete_sleep_cookie_buf(adapter);
+
+ mwifiex_pcie_delete_cmdrsp_buf(adapter);
+ mwifiex_pcie_delete_evtbd_ring(adapter);
+ mwifiex_pcie_delete_rxbd_ring(adapter);
+ mwifiex_pcie_delete_txbd_ring(adapter);
+ card->cmdrsp_buf = NULL;
}
}
@@ -1900,6 +2377,8 @@ static struct mwifiex_if_ops pcie_ops = {
.event_complete = mwifiex_pcie_event_complete,
.update_mp_end_port = NULL,
.cleanup_mpa_buf = NULL,
+ .init_fw_port = mwifiex_pcie_init_fw_port,
+ .clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
};
/*
@@ -1912,7 +2391,7 @@ static int mwifiex_pcie_init_module(void)
{
int ret;
- pr_debug("Marvell 8766 PCIe Driver\n");
+ pr_debug("Marvell PCIe Driver\n");
sema_init(&add_remove_card_sem, 1);
@@ -1955,4 +2434,5 @@ MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION);
MODULE_VERSION(PCIE_VERSION);
MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE("mrvl/pcie8766_uapsta.bin");
+MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME);
+MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME);
OpenPOWER on IntegriCloud