qcacmn: Introduce APIs needed by WIN
Added new APIs ce_batch_send and ce_send_single
only used by WIN.
Acked-by: Varsha Mishra <varsham@codeaurora.org>
Change-Id: I55d86d692455be118734f6e0a13e0e58c227b1a0
CRs-Fixed: 1009050
diff --git a/hif/src/ce/ce_api.h b/hif/src/ce/ce_api.h
index fd757b2..7a15365 100644
--- a/hif/src/ce/ce_api.h
+++ b/hif/src/ce/ce_api.h
@@ -114,6 +114,7 @@
#define CE_WM_FLAG_SEND_LOW 2
#define CE_WM_FLAG_RECV_HIGH 4
#define CE_WM_FLAG_RECV_LOW 8
+#define CE_HTT_TX_CE 4
/* A list of buffers to be gathered and sent */
struct ce_sendlist;
@@ -155,6 +156,17 @@
#endif
void ce_pkt_dl_len_set(void *hif_sc, unsigned int pkt_download_len);
+void ce_update_tx_ring(struct CE_handle *ce_tx_hdl, uint32_t num_htt_cmpls);
+extern qdf_nbuf_t ce_batch_send(struct CE_handle *ce_tx_hdl,
+ qdf_nbuf_t msdu,
+ uint32_t transfer_id,
+ uint32_t len,
+ uint32_t sendhead);
+
+extern int ce_send_single(struct CE_handle *ce_tx_hdl,
+ qdf_nbuf_t msdu,
+ uint32_t transfer_id,
+ uint32_t len);
/*
* Register a Send Callback function.
* This function is called as soon as the contents of a Send
diff --git a/hif/src/ce/ce_internal.h b/hif/src/ce/ce_internal.h
index 1d95984..4df0ec0 100644
--- a/hif/src/ce/ce_internal.h
+++ b/hif/src/ce/ce_internal.h
@@ -250,31 +250,39 @@
struct CE_src_desc {
uint32_t buffer_addr;
#if _BYTE_ORDER == _BIG_ENDIAN
- uint32_t meta_data:14,
- byte_swap:1,
- gather:1,
- nbytes:16;
+ uint32_t meta_data:12,
+ target_int_disable:1,
+ host_int_disable:1,
+ byte_swap:1,
+ gather:1,
+ nbytes:16;
#else
- uint32_t nbytes:16,
- gather:1,
- byte_swap:1,
- meta_data:14;
+ uint32_t nbytes:16,
+ gather:1,
+ byte_swap:1,
+ host_int_disable:1,
+ target_int_disable:1,
+ meta_data:12;
#endif
};
struct CE_dest_desc {
uint32_t buffer_addr;
#if _BYTE_ORDER == _BIG_ENDIAN
- uint32_t meta_data:14,
- byte_swap:1,
- gather:1,
- nbytes:16;
+ uint32_t meta_data:12,
+ target_int_disable:1,
+ host_int_disable:1,
+ byte_swap:1,
+ gather:1,
+ nbytes:16;
#else
uint32_t nbytes:16,
- gather:1,
- byte_swap:1,
- meta_data:14;
+ gather:1,
+ byte_swap:1,
+ host_int_disable:1,
+ target_int_disable:1,
+ meta_data:12;
#endif
};
#endif /* QCA_WIFI_3_0 */
diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c
index 6b1570e..88ef77b 100644
--- a/hif/src/ce/ce_main.c
+++ b/hif/src/ce/ce_main.c
@@ -47,7 +47,9 @@
#include "ce_assignment.h"
#include "ce_tasklet.h"
#include "platform_icnss.h"
+#ifndef CONFIG_WIN
#include "qwlan_version.h"
+#endif
#define CE_POLL_TIMEOUT 10 /* ms */
@@ -1119,7 +1121,7 @@
return;
}
}
-#ifdef ATH_11AC_TXCOMPACT
+#if ATH_11AC_TXCOMPACT
ce_per_engine_servicereap(scn, pipe);
#else
ce_per_engine_service(scn, pipe);
diff --git a/hif/src/ce/ce_service.c b/hif/src/ce/ce_service.c
index c3fc02f..ae4d643 100644
--- a/hif/src/ce/ce_service.c
+++ b/hif/src/ce/ce_service.c
@@ -309,6 +309,9 @@
memcpy(&(((uint32_t *)shadow_src_desc)[1]), &user_flags,
sizeof(uint32_t));
#endif
+ shadow_src_desc->target_int_disable = 0;
+ shadow_src_desc->host_int_disable = 0;
+
shadow_src_desc->meta_data = transfer_id;
/*
@@ -703,6 +706,201 @@
}
#endif /* WLAN_FEATURE_FASTPATH */
+#ifndef AH_NEED_TX_DATA_SWAP
+#define AH_NEED_TX_DATA_SWAP 0
+#endif
+
+/**
+ * ce_batch_send() - sends bunch of msdus at once
+ * @ce_tx_hdl : pointer to CE handle
+ * @msdu : list of msdus to be sent
+ * @transfer_id : transfer id
+ * @len : Downloaded length
+ * @sendhead : sendhead
+ *
+ * Assumption : Called with an array of MSDU's
+ * Function:
+ * For each msdu in the array
+ * 1. Send each msdu
+ * 2. Increment write index accordinlgy.
+ *
+ * Return: list of msds not sent
+ */
+qdf_nbuf_t ce_batch_send(struct CE_handle *ce_tx_hdl, qdf_nbuf_t msdu,
+ uint32_t transfer_id, u_int32_t len, uint32_t sendhead)
+{
+ struct CE_state *ce_state = (struct CE_state *)ce_tx_hdl;
+ struct hif_softc *scn = ce_state->scn;
+ struct CE_ring_state *src_ring = ce_state->src_ring;
+ u_int32_t ctrl_addr = ce_state->ctrl_addr;
+ /* A_target_id_t targid = TARGID(scn);*/
+
+ uint32_t nentries_mask = src_ring->nentries_mask;
+ uint32_t sw_index, write_index;
+
+ struct CE_src_desc *src_desc_base =
+ (struct CE_src_desc *)src_ring->base_addr_owner_space;
+ uint32_t *src_desc;
+
+ struct CE_src_desc lsrc_desc = {0};
+ int deltacount = 0;
+ qdf_nbuf_t freelist = NULL, hfreelist = NULL, tempnext;
+
+ sw_index = src_ring->sw_index;
+ write_index = src_ring->write_index;
+
+ deltacount = CE_RING_DELTA(nentries_mask, write_index, sw_index-1);
+
+ while (msdu) {
+ tempnext = qdf_nbuf_next(msdu);
+
+ if (deltacount < 2) {
+ if (sendhead)
+ return msdu;
+ qdf_print("Out of descriptor\n");
+ src_ring->write_index = write_index;
+ war_ce_src_ring_write_idx_set(scn, ctrl_addr,
+ write_index);
+
+ sw_index = src_ring->sw_index;
+ write_index = src_ring->write_index;
+
+ deltacount = CE_RING_DELTA(nentries_mask, write_index,
+ sw_index-1);
+ if (freelist == NULL) {
+ freelist = msdu;
+ hfreelist = msdu;
+ } else {
+ qdf_nbuf_set_next(freelist, msdu);
+ freelist = msdu;
+ }
+ qdf_nbuf_set_next(msdu, NULL);
+ msdu = tempnext;
+ continue;
+ }
+
+ src_desc = (uint32_t *)CE_SRC_RING_TO_DESC(src_desc_base,
+ write_index);
+
+ src_desc[0] = qdf_nbuf_get_frag_paddr(msdu, 0);
+
+ lsrc_desc.meta_data = transfer_id;
+ if (len > msdu->len)
+ len = msdu->len;
+ lsrc_desc.nbytes = len;
+ /* Data packet is a byte stream, so disable byte swap */
+ lsrc_desc.byte_swap = AH_NEED_TX_DATA_SWAP;
+ lsrc_desc.gather = 0; /*For the last one, gather is not set*/
+
+ src_desc[1] = ((uint32_t *)&lsrc_desc)[1];
+
+
+ src_ring->per_transfer_context[write_index] = msdu;
+ write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
+
+ if (sendhead)
+ break;
+ qdf_nbuf_set_next(msdu, NULL);
+ msdu = tempnext;
+
+ }
+
+
+ src_ring->write_index = write_index;
+ war_ce_src_ring_write_idx_set(scn, ctrl_addr, write_index);
+
+ return hfreelist;
+}
+
+/**
+ * ce_update_tx_ring() - Advance sw index.
+ * @ce_tx_hdl : pointer to CE handle
+ * @num_htt_cmpls : htt completions received.
+ *
+ * Function:
+ * Increment the value of sw index of src ring
+ * according to number of htt completions
+ * received.
+ *
+ * Return: void
+ */
+void ce_update_tx_ring(struct CE_handle *ce_tx_hdl, uint32_t num_htt_cmpls)
+{
+ struct CE_state *ce_state = (struct CE_state *)ce_tx_hdl;
+ struct CE_ring_state *src_ring = ce_state->src_ring;
+ uint32_t nentries_mask = src_ring->nentries_mask;
+ /*
+ * Advance the s/w index:
+ * This effectively simulates completing the CE ring descriptors
+ */
+ src_ring->sw_index =
+ CE_RING_IDX_ADD(nentries_mask, src_ring->sw_index,
+ num_htt_cmpls);
+}
+
+/**
+ * ce_send_single() - sends
+ * @ce_tx_hdl : pointer to CE handle
+ * @msdu : msdu to be sent
+ * @transfer_id : transfer id
+ * @len : Downloaded length
+ *
+ * Function:
+ * 1. Send one msdu
+ * 2. Increment write index of src ring accordinlgy.
+ *
+ * Return: int: CE sent status
+ */
+int ce_send_single(struct CE_handle *ce_tx_hdl, qdf_nbuf_t msdu,
+ uint32_t transfer_id, u_int32_t len)
+{
+ struct CE_state *ce_state = (struct CE_state *)ce_tx_hdl;
+ struct hif_softc *scn = ce_state->scn;
+ struct CE_ring_state *src_ring = ce_state->src_ring;
+ uint32_t ctrl_addr = ce_state->ctrl_addr;
+ /*A_target_id_t targid = TARGID(scn);*/
+
+ uint32_t nentries_mask = src_ring->nentries_mask;
+ uint32_t sw_index, write_index;
+
+ struct CE_src_desc *src_desc_base =
+ (struct CE_src_desc *)src_ring->base_addr_owner_space;
+ uint32_t *src_desc;
+
+ struct CE_src_desc lsrc_desc = {0};
+
+ sw_index = src_ring->sw_index;
+ write_index = src_ring->write_index;
+
+ if (qdf_unlikely(CE_RING_DELTA(nentries_mask, write_index,
+ sw_index-1) < 1)) {
+ /* ol_tx_stats_inc_ring_error(sc->scn->pdev_txrx_handle, 1); */
+ qdf_print("ce send fail %d %d %d\n", nentries_mask,
+ write_index, sw_index);
+ return 1;
+ }
+
+ src_desc = (uint32_t *)CE_SRC_RING_TO_DESC(src_desc_base, write_index);
+
+ src_desc[0] = qdf_nbuf_get_frag_paddr(msdu, 0);
+
+ lsrc_desc.meta_data = transfer_id;
+ lsrc_desc.nbytes = len;
+ /* Data packet is a byte stream, so disable byte swap */
+ lsrc_desc.byte_swap = AH_NEED_TX_DATA_SWAP;
+ lsrc_desc.gather = 0; /* For the last one, gather is not set */
+
+ src_desc[1] = ((uint32_t *)&lsrc_desc)[1];
+
+
+ src_ring->per_transfer_context[write_index] = msdu;
+ write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
+
+ src_ring->write_index = write_index;
+ war_ce_src_ring_write_idx_set(scn, ctrl_addr, write_index);
+
+ return QDF_STATUS_SUCCESS;
+}
/**
* ce_recv_buf_enqueue() - enqueue a recv buffer into a copy engine
* @coyeng: copy engine handle
@@ -1373,7 +1571,7 @@
dest_ring->write_index = write_index;
}
-#define MSG_FLUSH_NUM 6
+#define MSG_FLUSH_NUM 32
/**
* ce_per_engine_service_fast() - CE handler routine to service fastpath messages
* @scn: hif_context
diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c
index 14a9b12..03c9f76 100644
--- a/hif/src/hif_main.c
+++ b/hif/src/hif_main.c
@@ -983,3 +983,117 @@
return false;
}
+
+/**
+ * hif_batch_send() - API to access hif specific function
+ * ce_batch_send.
+ * @osc: HIF Context
+ * @msdu : list of msdus to be sent
+ * @transfer_id : transfer id
+ * @len : donwloaded length
+ *
+ * Return: list of msds not sent
+ */
+qdf_nbuf_t hif_batch_send(struct hif_opaque_softc *osc, qdf_nbuf_t msdu,
+ uint32_t transfer_id, u_int32_t len, uint32_t sendhead)
+{
+ void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
+ return ce_batch_send((struct CE_handle *)ce_tx_hdl, msdu, transfer_id,
+ len, sendhead);
+}
+
+/**
+ * hif_update_tx_ring() - API to access hif specific function
+ * ce_update_tx_ring.
+ * @osc: HIF Context
+ * @num_htt_cmpls : number of htt compl received.
+ *
+ * Return: void
+ */
+void hif_update_tx_ring(struct hif_opaque_softc *osc, u_int32_t num_htt_cmpls)
+{
+ void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
+ ce_update_tx_ring(ce_tx_hdl, num_htt_cmpls);
+}
+
+
+/**
+ * hif_send_single() - API to access hif specific function
+ * ce_send_single.
+ * @osc: HIF Context
+ * @msdu : msdu to be sent
+ * @transfer_id: transfer id
+ * @len : downloaded length
+ *
+ * Return: msdu sent status
+ */
+int hif_send_single(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, uint32_t
+ transfer_id, u_int32_t len)
+{
+ void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
+ return ce_send_single((struct CE_handle *)ce_tx_hdl, msdu, transfer_id,
+ len);
+}
+
+/**
+ * hif_send_fast() - API to access hif specific function
+ * ce_send_fast.
+ * @osc: HIF Context
+ * @msdu : array of msdus to be sent
+ * @num_msdus : number of msdus in an array
+ * @transfer_id: transfer id
+ *
+ * Return: No. of packets that could be sent
+ */
+int hif_send_fast(struct hif_opaque_softc *osc, qdf_nbuf_t *nbuf_arr,
+ uint32_t num_msdus, uint32_t transfer_id)
+{
+ void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
+ return ce_send_fast((struct CE_handle *)ce_tx_hdl, nbuf_arr, num_msdus,
+ transfer_id);
+}
+
+/**
+ * hif_pkt_dl_len_set() - API to access hif specific function
+ * ce_pkt_dl_len_set.
+ * @osc: HIF Context
+ * @pkt_download_len: download length
+ *
+ * Return: None
+ */
+void hif_pkt_dl_len_set(void *hif_sc, unsigned int pkt_download_len)
+{
+ ce_pkt_dl_len_set(hif_sc, pkt_download_len);
+}
+
+/**
+ * hif_reg_write() - API to access hif specific function
+ * hif_write32_mb.
+ * @hif_ctx : HIF Context
+ * @offset : offset on which value has to be written
+ * @value : value to be written
+ *
+ * Return: None
+ */
+void hif_reg_write(struct hif_opaque_softc *hif_ctx, uint32_t offset,
+ uint32_t value)
+{
+ struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
+ hif_write32_mb(scn->mem + offset, value);
+
+}
+
+/**
+ * hif_reg_read() - API to access hif specific function
+ * hif_read32_mb.
+ * @hif_ctx : HIF Context
+ * @offset : offset from which value has to be read
+ *
+ * Return: Read value
+ */
+uint32_t hif_reg_read(struct hif_opaque_softc *hif_ctx, uint32_t offset)
+{
+
+ struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
+ return hif_read32_mb(scn->mem + offset);
+}
diff --git a/hif/src/pcie/if_pci.c b/hif/src/pcie/if_pci.c
index 47e513c..ec8d72f 100644
--- a/hif/src/pcie/if_pci.c
+++ b/hif/src/pcie/if_pci.c
@@ -3026,7 +3026,7 @@
void *addr;
addr = scn->mem + offset;
- value = A_PCI_READ32(addr);
+ value = hif_read32_mb(addr);
{
unsigned long irq_flags;