mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
Support WDI 3.0 over GSI. Change-Id: I952ea2bb864f179ed3238305520051f884e3a1af Signed-off-by: Bojun Pan <bojunp@codeaurora.org>
1171 lines
34 KiB
C
1171 lines
34 KiB
C
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include "ipa_ut_framework.h"
|
|
#include <linux/ipa_wdi3.h>
|
|
#include <linux/ipa.h>
|
|
#include <linux/delay.h>
|
|
#include "../ipa_v3/ipa_i.h"
|
|
|
|
#define NUM_TX_BUFS 10
|
|
#define NUM_RX_BUFS 10
|
|
#define NUM_REDUNDANT_TX_ELE 1
|
|
#define NUM_RX_TR_ELE NUM_RX_BUFS
|
|
#define NUM_RX_ER_ELE NUM_RX_BUFS
|
|
#define NUM_TX_TR_ELE (NUM_TX_BUFS + NUM_REDUNDANT_TX_ELE)
|
|
#define NUM_TX_ER_ELE (NUM_TX_BUFS + NUM_REDUNDANT_TX_ELE)
|
|
|
|
#define RX_METADATA_SIZE 4
|
|
#define PACKET_HEADER_SIZE 220
|
|
#define ETH_PACKET_SIZE 4
|
|
#define PACKET_CONTENT 0x12345678
|
|
|
|
#define PKT_SIZE 4096
|
|
|
|
#define DB_REGISTER_SIZE 4
|
|
|
|
#define NUM_MULTI_PKT 8
|
|
|
|
int multi_pkt_array[] = {0x12345678, 0x87654321,
|
|
0x00112233, 0x01234567, 0x45454545, 0x80808080,
|
|
0x13245678, 0x12345767, 0x43213456};
|
|
|
|
int rx_uc_db_local;
|
|
int tx_uc_db_local;
|
|
u8 tx_bf_idx;
|
|
u8 rx_bf_idx;
|
|
|
|
struct ipa_test_wdi3_context {
|
|
struct ipa_mem_buffer tx_transfer_ring_addr;
|
|
struct ipa_mem_buffer tx_event_ring_addr;
|
|
struct ipa_mem_buffer rx_transfer_ring_addr;
|
|
struct ipa_mem_buffer rx_event_ring_addr;
|
|
struct ipa_mem_buffer tx_bufs[NUM_TX_BUFS];
|
|
struct ipa_mem_buffer rx_bufs[NUM_RX_BUFS];
|
|
struct ipa_mem_buffer tx_transfer_ring_db;
|
|
struct ipa_mem_buffer tx_event_ring_db;
|
|
struct ipa_mem_buffer rx_transfer_ring_db;
|
|
struct ipa_mem_buffer rx_event_ring_db;
|
|
dma_addr_t tx_uc_db_pa;
|
|
dma_addr_t rx_uc_db_pa;
|
|
};
|
|
|
|
static struct ipa_test_wdi3_context *test_wdi3_ctx;
|
|
|
|
struct buffer_addr_info {
|
|
u32 buffer_addr_low;
|
|
u32 buffer_addr_high : 8;
|
|
u32 return_buffer_manager : 3;
|
|
u32 sw_buffer_cookie : 21;
|
|
} __packed;
|
|
|
|
struct tx_transfer_ring_ele {
|
|
struct buffer_addr_info buf_or_link_desc_addr_info;
|
|
u32 resv[6];
|
|
} __packed;
|
|
|
|
struct tx_event_ring_ele {
|
|
u32 reserved_5;
|
|
struct buffer_addr_info buf_or_link_desc_addr_info;
|
|
u32 buf_or_ext_desc_type : 1;
|
|
u32 epd : 1;
|
|
u32 encap_type : 2;
|
|
u32 encrypt_type : 4;
|
|
u32 src_buffer_swap : 1;
|
|
u32 link_meta_swap : 1;
|
|
u32 hlos_tid : 4;
|
|
u32 addrX_en : 1;
|
|
u32 addrY_en : 1;
|
|
u32 tcl_cmd_number : 16;
|
|
u32 data_length : 16;
|
|
u32 ipv4_checksum_en : 1;
|
|
u32 udp_over_ipv4_checksum_en : 1;
|
|
u32 udp_over_ipv6_checksum_en : 1;
|
|
u32 tcp_over_ipv4_checksum_en : 1;
|
|
u32 tcp_over_ipv6_checksum_en : 1;
|
|
u32 to_fw : 1;
|
|
u32 dscp_to_tid_priority_table_id : 1;
|
|
u32 packet_offset : 9;
|
|
u32 buffer_timestamp : 19;
|
|
u32 buffer_timestamp_valid : 1;
|
|
u32 reserved_4 : 12;
|
|
u32 reserved_6;
|
|
u32 reserved_7a : 20;
|
|
u32 ring_id : 8;
|
|
u32 looping_count : 4;
|
|
} __packed;
|
|
|
|
struct rx_mpdu_desc_info {
|
|
u32 msdu_count : 8;
|
|
u32 mpdu_sequence_number : 12;
|
|
u32 fragment_flag : 1;
|
|
u32 mpdu_retry_bit : 1;
|
|
u32 ampdu_flag : 1;
|
|
u32 bar_frame : 1;
|
|
u32 pn_fields_contain_valid_info : 1;
|
|
u32 sa_is_valid : 1;
|
|
u32 sa_idx_timeout : 1;
|
|
u32 da_is_valid : 1;
|
|
u32 da_is_mcbc : 1;
|
|
u32 da_idx_timeout : 1;
|
|
u32 raw_mpdu : 1;
|
|
u32 reserved : 1;
|
|
u32 peer_meta_data;
|
|
} __packed;
|
|
|
|
struct rx_msdu_desc_info {
|
|
u32 first_msdu_in_mpdu_flag : 1;
|
|
u32 last_msdu_in_mpdu_flag : 1;
|
|
u32 msdu_continuation : 1;
|
|
u32 msdu_length : 14;
|
|
u32 reo_destination_indication : 5;
|
|
u32 msdu_drop : 1;
|
|
u32 sa_is_valid : 1;
|
|
u32 sa_idx_timeout : 1;
|
|
u32 da_is_valid : 1;
|
|
u32 da_is_mcbc : 1;
|
|
u32 da_idx_timeout : 1;
|
|
u32 reserved_0a : 4;
|
|
u32 reserved_1a;
|
|
} __packed;
|
|
|
|
struct rx_transfer_ring_ele {
|
|
struct buffer_addr_info buf_or_link_desc_addr_info;
|
|
struct rx_mpdu_desc_info rx_mpdu_desc_info_details;
|
|
struct rx_msdu_desc_info rx_msdu_desc_info_details;
|
|
u32 rx_reo_queue_desc_addr_31_0;
|
|
u32 rx_reo_queue_desc_addr_39_32 : 8;
|
|
u32 reo_dest_buffer_type : 1;
|
|
u32 reo_push_reason : 2;
|
|
u32 reo_error_code : 5;
|
|
u32 receive_queue_number : 16;
|
|
u32 soft_reorder_info_valid : 1;
|
|
u32 reorder_opcode : 4;
|
|
u32 reorder_slot_index : 8;
|
|
u32 reserved_8a : 19;
|
|
u32 reserved_9a;
|
|
u32 reserved_10a;
|
|
u32 reserved_11a;
|
|
u32 reserved_12a;
|
|
u32 reserved_13a;
|
|
u32 reserved_14a;
|
|
u32 reserved_15a : 20;
|
|
u32 ring_id : 8;
|
|
u32 looping_count : 4;
|
|
} __packed;
|
|
|
|
struct rx_event_ring_ele {
|
|
struct buffer_addr_info buf_or_link_desc_addr_info;
|
|
} __packed;
|
|
|
|
static void ipa_test_wdi3_free_dma_buff(struct ipa_mem_buffer *mem)
|
|
{
|
|
if (!mem) {
|
|
IPA_UT_ERR("empty pointer\n");
|
|
return;
|
|
}
|
|
|
|
dma_free_coherent(ipa3_ctx->pdev, mem->size, mem->base,
|
|
mem->phys_base);
|
|
}
|
|
|
|
static void ipa_test_wdi3_advance_uc_db(u32 *db, int steps,
|
|
int num_words, int ring_size)
|
|
{
|
|
*db = (*db + steps * num_words) % (ring_size / 4);
|
|
IPA_UT_DBG("new db value: %u\n", *db);
|
|
}
|
|
|
|
static int ipa_test_wdi3_alloc_mmio(void)
|
|
{
|
|
int ret = 0, i, j;
|
|
int num_tx_alloc_bufs, num_rx_alloc_bufs;
|
|
u32 size;
|
|
|
|
if (!test_wdi3_ctx) {
|
|
IPA_UT_ERR("test_wdi3_ctx is not initialized.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* allocate tx transfer ring memory */
|
|
size = NUM_TX_TR_ELE * sizeof(struct tx_transfer_ring_ele);
|
|
test_wdi3_ctx->tx_transfer_ring_addr.size = size;
|
|
test_wdi3_ctx->tx_transfer_ring_addr.base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, size,
|
|
&test_wdi3_ctx->tx_transfer_ring_addr.phys_base,
|
|
GFP_KERNEL);
|
|
if (!test_wdi3_ctx->tx_transfer_ring_addr.phys_base) {
|
|
IPA_UT_ERR("fail to alloc memory.\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* allocate tx event ring memory */
|
|
size = NUM_TX_ER_ELE * sizeof(struct tx_event_ring_ele);
|
|
test_wdi3_ctx->tx_event_ring_addr.size = size;
|
|
test_wdi3_ctx->tx_event_ring_addr.base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, size,
|
|
&test_wdi3_ctx->tx_event_ring_addr.phys_base,
|
|
GFP_KERNEL);
|
|
if (!test_wdi3_ctx->tx_event_ring_addr.phys_base) {
|
|
IPA_UT_ERR("fail to alloc memory.\n");
|
|
ret = -ENOMEM;
|
|
goto fail_tx_event_ring;
|
|
}
|
|
|
|
/* allocate rx transfer ring memory */
|
|
size = NUM_RX_TR_ELE * sizeof(struct rx_transfer_ring_ele);
|
|
test_wdi3_ctx->rx_transfer_ring_addr.size = size;
|
|
test_wdi3_ctx->rx_transfer_ring_addr.base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, size,
|
|
&test_wdi3_ctx->rx_transfer_ring_addr.phys_base,
|
|
GFP_KERNEL);
|
|
if (!test_wdi3_ctx->rx_transfer_ring_addr.phys_base) {
|
|
IPA_UT_ERR("fail to alloc memory.\n");
|
|
ret = -ENOMEM;
|
|
goto fail_rx_transfer_ring;
|
|
}
|
|
|
|
/* allocate rx event ring memory */
|
|
size = NUM_RX_ER_ELE * sizeof(struct rx_event_ring_ele);
|
|
test_wdi3_ctx->rx_event_ring_addr.size = size;
|
|
test_wdi3_ctx->rx_event_ring_addr.base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, size,
|
|
&test_wdi3_ctx->rx_event_ring_addr.phys_base,
|
|
GFP_KERNEL);
|
|
if (!test_wdi3_ctx->rx_event_ring_addr.phys_base) {
|
|
IPA_UT_ERR("fail to alloc memory.\n");
|
|
ret = -ENOMEM;
|
|
goto fail_rx_event_ring;
|
|
}
|
|
|
|
/* allocate tx buffers */
|
|
num_tx_alloc_bufs = NUM_TX_BUFS;
|
|
for (i = 0; i < NUM_TX_BUFS; i++) {
|
|
size = ETH_PACKET_SIZE; //2kB buffer size;
|
|
test_wdi3_ctx->tx_bufs[i].size = size;
|
|
test_wdi3_ctx->tx_bufs[i].base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, size,
|
|
&test_wdi3_ctx->tx_bufs[i].phys_base,
|
|
GFP_KERNEL);
|
|
if (!test_wdi3_ctx->tx_bufs[i].phys_base) {
|
|
IPA_UT_ERR("fail to alloc memory.\n");
|
|
num_tx_alloc_bufs = i-1;
|
|
ret = -ENOMEM;
|
|
goto fail_tx_bufs;
|
|
}
|
|
}
|
|
|
|
/* allocate rx buffers */
|
|
num_rx_alloc_bufs = NUM_RX_BUFS;
|
|
for (i = 0; i < NUM_RX_BUFS; i++) {
|
|
size = ETH_PACKET_SIZE + PACKET_HEADER_SIZE; //2kB buffer size;
|
|
test_wdi3_ctx->rx_bufs[i].size = size;
|
|
test_wdi3_ctx->rx_bufs[i].base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, size,
|
|
&test_wdi3_ctx->rx_bufs[i].phys_base,
|
|
GFP_KERNEL);
|
|
if (!test_wdi3_ctx->rx_bufs[i].phys_base) {
|
|
IPA_UT_ERR("fail to alloc memory.\n");
|
|
num_rx_alloc_bufs = i-1;
|
|
ret = -ENOMEM;
|
|
goto fail_rx_bufs;
|
|
}
|
|
}
|
|
|
|
/* allocate tx transfer ring db */
|
|
test_wdi3_ctx->tx_transfer_ring_db.size = DB_REGISTER_SIZE;
|
|
test_wdi3_ctx->tx_transfer_ring_db.base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, DB_REGISTER_SIZE,
|
|
&test_wdi3_ctx->tx_transfer_ring_db.phys_base, GFP_KERNEL);
|
|
if (!test_wdi3_ctx->tx_transfer_ring_db.base) {
|
|
IPA_UT_ERR("fail to alloc memory\n");
|
|
ret = -ENOMEM;
|
|
goto fail_tx_transfer_ring_db;
|
|
}
|
|
|
|
/* allocate tx event ring db */
|
|
test_wdi3_ctx->tx_event_ring_db.size = DB_REGISTER_SIZE;
|
|
test_wdi3_ctx->tx_event_ring_db.base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, DB_REGISTER_SIZE,
|
|
&test_wdi3_ctx->tx_event_ring_db.phys_base, GFP_KERNEL);
|
|
if (!test_wdi3_ctx->tx_event_ring_db.base) {
|
|
IPA_UT_ERR("fail to alloc memory\n");
|
|
ret = -ENOMEM;
|
|
goto fail_tx_event_ring_db;
|
|
}
|
|
|
|
/* allocate rx transfer ring db */
|
|
test_wdi3_ctx->rx_transfer_ring_db.size = DB_REGISTER_SIZE;
|
|
test_wdi3_ctx->rx_transfer_ring_db.base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, DB_REGISTER_SIZE,
|
|
&test_wdi3_ctx->rx_transfer_ring_db.phys_base, GFP_KERNEL);
|
|
if (!test_wdi3_ctx->rx_transfer_ring_db.base) {
|
|
IPA_UT_ERR("fail to alloc memory\n");
|
|
ret = -ENOMEM;
|
|
goto fail_rx_transfer_ring_db;
|
|
}
|
|
|
|
/* allocate rx event ring db */
|
|
test_wdi3_ctx->rx_event_ring_db.size = DB_REGISTER_SIZE;
|
|
test_wdi3_ctx->rx_event_ring_db.base =
|
|
dma_alloc_coherent(ipa3_ctx->pdev, DB_REGISTER_SIZE,
|
|
&test_wdi3_ctx->rx_event_ring_db.phys_base, GFP_KERNEL);
|
|
if (!test_wdi3_ctx->rx_event_ring_db.base) {
|
|
IPA_UT_ERR("fail to alloc memory\n");
|
|
ret = -ENOMEM;
|
|
goto fail_rx_event_ring_db;
|
|
}
|
|
|
|
return ret;
|
|
|
|
fail_rx_event_ring_db:
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_transfer_ring_db);
|
|
|
|
fail_rx_transfer_ring_db:
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_event_ring_db);
|
|
|
|
fail_tx_event_ring_db:
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_transfer_ring_db);
|
|
|
|
fail_tx_transfer_ring_db:
|
|
fail_rx_bufs:
|
|
for (j = 0; j <= num_rx_alloc_bufs; j++)
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_bufs[j]);
|
|
|
|
fail_tx_bufs:
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_event_ring_addr);
|
|
|
|
for (j = 0; j <= num_tx_alloc_bufs; j++)
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_bufs[j]);
|
|
|
|
fail_rx_event_ring:
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_transfer_ring_addr);
|
|
|
|
fail_rx_transfer_ring:
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_event_ring_addr);
|
|
|
|
fail_tx_event_ring:
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_transfer_ring_addr);
|
|
return ret;
|
|
}
|
|
|
|
static int ipa_test_wdi3_free_mmio(void)
|
|
{
|
|
int i;
|
|
|
|
if (!test_wdi3_ctx) {
|
|
IPA_UT_ERR("test_wdi3_ctx is not initialized.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_event_ring_db);
|
|
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_transfer_ring_db);
|
|
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_event_ring_db);
|
|
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_transfer_ring_db);
|
|
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_event_ring_addr);
|
|
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_transfer_ring_addr);
|
|
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_event_ring_addr);
|
|
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_transfer_ring_addr);
|
|
|
|
for (i = 0; i < NUM_RX_BUFS; i++)
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->rx_bufs[i]);
|
|
|
|
for (i = 0; i < NUM_TX_BUFS; i++)
|
|
ipa_test_wdi3_free_dma_buff(&test_wdi3_ctx->tx_bufs[i]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_test_wdi3_suite_setup(void **priv)
|
|
{
|
|
int ret = 0;
|
|
struct ipa_wdi_init_in_params in;
|
|
struct ipa_wdi_init_out_params out;
|
|
|
|
IPA_UT_DBG("Start WDI3 Setup\n");
|
|
|
|
/* init ipa wdi ctx */
|
|
in.wdi_notify = NULL;
|
|
in.notify = NULL;
|
|
in.priv = NULL;
|
|
in.wdi_version = IPA_WDI_3;
|
|
ipa_wdi_init(&in, &out);
|
|
|
|
|
|
if (!ipa3_ctx) {
|
|
IPA_UT_ERR("No IPA ctx\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
test_wdi3_ctx = kzalloc(sizeof(struct ipa_test_wdi3_context),
|
|
GFP_KERNEL);
|
|
if (!test_wdi3_ctx) {
|
|
IPA_UT_ERR("failed to allocate ctx\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = ipa_test_wdi3_alloc_mmio();
|
|
if (ret) {
|
|
IPA_UT_ERR("failed to alloc mmio\n");
|
|
goto fail_alloc_mmio;
|
|
}
|
|
|
|
*priv = test_wdi3_ctx;
|
|
return 0;
|
|
|
|
fail_alloc_mmio:
|
|
kfree(test_wdi3_ctx);
|
|
test_wdi3_ctx = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static int ipa_test_wdi3_suite_teardown(void *priv)
|
|
{
|
|
if (!test_wdi3_ctx)
|
|
return 0;
|
|
|
|
ipa_test_wdi3_free_mmio();
|
|
kfree(test_wdi3_ctx);
|
|
test_wdi3_ctx = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_wdi3_setup_pipes(void)
|
|
{
|
|
struct ipa_wdi_conn_in_params *in_param;
|
|
struct ipa_wdi_conn_out_params *out_param;
|
|
struct tx_transfer_ring_ele *tx_transfer, *tx_transfer_base;
|
|
struct rx_transfer_ring_ele *rx_transfer;
|
|
void __iomem *rx_uc_db;
|
|
void __iomem *tx_uc_db;
|
|
int i, index;
|
|
|
|
if (!test_wdi3_ctx) {
|
|
IPA_UT_ERR("context is empty.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
in_param = kzalloc(sizeof(struct ipa_wdi_conn_in_params),
|
|
GFP_KERNEL);
|
|
if (!in_param) {
|
|
IPA_UT_ERR("failed to allocate in_param\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
out_param = kzalloc(sizeof(struct ipa_wdi_conn_out_params),
|
|
GFP_KERNEL);
|
|
if (!out_param) {
|
|
IPA_UT_ERR("failed to allocate out_param\n");
|
|
kfree(in_param);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
memset(in_param, 0, sizeof(struct ipa_wdi_conn_in_params));
|
|
memset(out_param, 0, sizeof(struct ipa_wdi_conn_out_params));
|
|
|
|
/* setup tx parameters */
|
|
in_param->is_smmu_enabled = false;
|
|
in_param->u_tx.tx.client = IPA_CLIENT_WLAN2_CONS;
|
|
in_param->u_tx.tx.transfer_ring_base_pa =
|
|
test_wdi3_ctx->tx_transfer_ring_addr.phys_base;
|
|
in_param->u_tx.tx.transfer_ring_size =
|
|
test_wdi3_ctx->tx_transfer_ring_addr.size;
|
|
in_param->u_tx.tx.transfer_ring_doorbell_pa =
|
|
test_wdi3_ctx->tx_transfer_ring_db.phys_base;
|
|
|
|
in_param->notify = NULL;
|
|
in_param->u_tx.tx.event_ring_base_pa =
|
|
test_wdi3_ctx->tx_event_ring_addr.phys_base;
|
|
in_param->u_tx.tx.event_ring_size =
|
|
test_wdi3_ctx->tx_event_ring_addr.size;
|
|
in_param->u_tx.tx.event_ring_doorbell_pa =
|
|
test_wdi3_ctx->tx_event_ring_db.phys_base;
|
|
IPA_UT_DBG("tx_event_ring_db.phys_base %llu\n",
|
|
test_wdi3_ctx->tx_event_ring_db.phys_base);
|
|
IPA_UT_DBG("tx_event_ring_db.base %pK\n",
|
|
test_wdi3_ctx->tx_event_ring_db.base);
|
|
IPA_UT_DBG("tx_event_ring.phys_base %llu\n",
|
|
test_wdi3_ctx->tx_event_ring_addr.phys_base);
|
|
IPA_UT_DBG("tx_event_ring.base %pK\n",
|
|
test_wdi3_ctx->tx_event_ring_addr.base);
|
|
|
|
in_param->u_tx.tx.num_pkt_buffers = NUM_TX_BUFS;
|
|
|
|
/* setup rx parameters */
|
|
in_param->u_rx.rx.client = IPA_CLIENT_WLAN2_PROD;
|
|
in_param->u_rx.rx.transfer_ring_base_pa =
|
|
test_wdi3_ctx->rx_transfer_ring_addr.phys_base;
|
|
in_param->u_rx.rx.transfer_ring_size =
|
|
test_wdi3_ctx->rx_transfer_ring_addr.size;
|
|
in_param->u_rx.rx.transfer_ring_doorbell_pa =
|
|
test_wdi3_ctx->rx_transfer_ring_db.phys_base;
|
|
in_param->u_rx.rx.pkt_offset = PACKET_HEADER_SIZE;
|
|
|
|
|
|
in_param->u_rx.rx.event_ring_base_pa =
|
|
test_wdi3_ctx->rx_event_ring_addr.phys_base;
|
|
in_param->u_rx.rx.event_ring_size =
|
|
test_wdi3_ctx->rx_event_ring_addr.size;
|
|
in_param->u_rx.rx.event_ring_doorbell_pa =
|
|
test_wdi3_ctx->rx_event_ring_db.phys_base;
|
|
|
|
IPA_UT_DBG("rx_event_ring_db.phys_base %llu\n",
|
|
in_param->u_rx.rx.event_ring_doorbell_pa);
|
|
IPA_UT_DBG("rx_event_ring_db.base %pK\n",
|
|
test_wdi3_ctx->rx_event_ring_addr.base);
|
|
|
|
in_param->u_rx.rx.num_pkt_buffers = NUM_RX_BUFS;
|
|
if (ipa_wdi_conn_pipes(in_param, out_param)) {
|
|
IPA_UT_ERR("fail to conn wdi3 pipes.\n");
|
|
kfree(in_param);
|
|
kfree(out_param);
|
|
return -EFAULT;
|
|
}
|
|
if (ipa_wdi_enable_pipes()) {
|
|
IPA_UT_ERR("fail to enable wdi3 pipes.\n");
|
|
ipa_wdi_disconn_pipes();
|
|
kfree(in_param);
|
|
kfree(out_param);
|
|
return -EFAULT;
|
|
}
|
|
test_wdi3_ctx->tx_uc_db_pa = out_param->tx_uc_db_pa;
|
|
test_wdi3_ctx->rx_uc_db_pa = out_param->rx_uc_db_pa;
|
|
IPA_UT_DBG("tx_uc_db_pa %llu, rx_uc_db_pa %llu.\n",
|
|
test_wdi3_ctx->tx_uc_db_pa, test_wdi3_ctx->rx_uc_db_pa);
|
|
|
|
rx_uc_db = ioremap(test_wdi3_ctx->rx_uc_db_pa, DB_REGISTER_SIZE);
|
|
tx_uc_db = ioremap(test_wdi3_ctx->tx_uc_db_pa, DB_REGISTER_SIZE);
|
|
|
|
/* setup db registers */
|
|
*(u32 *)test_wdi3_ctx->rx_transfer_ring_db.base = rx_uc_db_local;
|
|
*(u32 *)test_wdi3_ctx->rx_event_ring_db.base = 0;
|
|
|
|
*(u32 *)test_wdi3_ctx->tx_transfer_ring_db.base = tx_uc_db_local;
|
|
*(u32 *)test_wdi3_ctx->tx_event_ring_db.base = 0;
|
|
|
|
rx_transfer = (struct rx_transfer_ring_ele *)
|
|
test_wdi3_ctx->rx_transfer_ring_addr.base;
|
|
for (i = 0; i < NUM_TX_BUFS; i++) {
|
|
rx_transfer->buf_or_link_desc_addr_info.buffer_addr_low =
|
|
(u64)test_wdi3_ctx->rx_bufs[i].phys_base & 0xFFFFFFFF;
|
|
rx_transfer->buf_or_link_desc_addr_info.buffer_addr_high =
|
|
((u64)test_wdi3_ctx->rx_bufs[i].phys_base >> 32)
|
|
& 0xFFFFFFFF;
|
|
rx_transfer++;
|
|
}
|
|
|
|
tx_transfer_base = (struct tx_transfer_ring_ele *)
|
|
test_wdi3_ctx->tx_transfer_ring_addr.base;
|
|
index = tx_uc_db_local;
|
|
for (i = 0; i < NUM_TX_BUFS; i++) {
|
|
tx_transfer = tx_transfer_base + index;
|
|
tx_transfer->buf_or_link_desc_addr_info.buffer_addr_low =
|
|
(u64)test_wdi3_ctx->tx_bufs[i].phys_base & 0xFFFFFFFF;
|
|
tx_transfer->buf_or_link_desc_addr_info.buffer_addr_high =
|
|
((u64)test_wdi3_ctx->tx_bufs[i].phys_base >> 32)
|
|
& 0xFFFFFFFF;
|
|
index = (index + 1) % NUM_TX_TR_ELE;
|
|
}
|
|
ipa_test_wdi3_advance_uc_db(&tx_uc_db_local, NUM_TX_BUFS,
|
|
sizeof(struct tx_transfer_ring_ele)/4,
|
|
test_wdi3_ctx->tx_transfer_ring_addr.size);
|
|
iowrite32(tx_uc_db_local, tx_uc_db);
|
|
kfree(in_param);
|
|
kfree(out_param);
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_wdi3_teardown_pipes(void)
|
|
{
|
|
ipa_wdi_disable_pipes();
|
|
ipa_wdi_disconn_pipes();
|
|
rx_bf_idx = 0;
|
|
tx_bf_idx = 0;
|
|
rx_uc_db_local = 0;
|
|
tx_uc_db_local = 0;
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_wdi3_send_one_packet(void)
|
|
{
|
|
void __iomem *rx_uc_db;
|
|
void __iomem *tx_uc_db;
|
|
u32 *tx_event_ring_db, *rx_transfer_ring_db, *rx_event_ring_db;
|
|
u32 orig_tx_event_ring_db;
|
|
u32 orig_rx_event_ring_db;
|
|
u32 orig_tx_trans_ring_db;
|
|
u32 *packet;
|
|
u32 *packet_recv = NULL;
|
|
struct rx_transfer_ring_ele *rx_transfer;
|
|
struct rx_event_ring_ele *rx_event;
|
|
struct tx_event_ring_ele *tx_event;
|
|
struct tx_transfer_ring_ele *tx_transfer;
|
|
struct buffer_addr_info rx_buf;
|
|
dma_addr_t recv_packet_addr;
|
|
int loop_cnt, i, num_words;
|
|
int idx;
|
|
|
|
/* populate packet content */
|
|
rx_uc_db = ioremap(test_wdi3_ctx->rx_uc_db_pa, DB_REGISTER_SIZE);
|
|
num_words = sizeof(struct rx_transfer_ring_ele) / 4;
|
|
idx = rx_uc_db_local / num_words;
|
|
packet = (u32 *)test_wdi3_ctx->rx_bufs[rx_bf_idx].base +
|
|
PACKET_HEADER_SIZE/4;
|
|
*packet = PACKET_CONTENT;
|
|
IPA_UT_DBG("local rx uc db: %u, rx buffer index %d\n",
|
|
rx_uc_db_local, rx_bf_idx);
|
|
rx_bf_idx = (rx_bf_idx + 1) % NUM_RX_BUFS;
|
|
/* update rx_transfer_ring_ele */
|
|
rx_transfer = (struct rx_transfer_ring_ele *)
|
|
(test_wdi3_ctx->rx_transfer_ring_addr.base) +
|
|
idx;
|
|
|
|
ipa_test_wdi3_advance_uc_db(&rx_uc_db_local, 1,
|
|
sizeof(struct rx_transfer_ring_ele)/4,
|
|
test_wdi3_ctx->rx_transfer_ring_addr.size);
|
|
rx_transfer->rx_msdu_desc_info_details.msdu_length =
|
|
ETH_PACKET_SIZE + PACKET_HEADER_SIZE;
|
|
|
|
rx_buf.buffer_addr_low =
|
|
rx_transfer->buf_or_link_desc_addr_info.buffer_addr_low;
|
|
rx_buf.buffer_addr_high =
|
|
rx_transfer->buf_or_link_desc_addr_info.buffer_addr_high;
|
|
|
|
tx_event_ring_db = (u32 *)test_wdi3_ctx->tx_event_ring_db.base;
|
|
orig_tx_event_ring_db = *tx_event_ring_db;
|
|
IPA_UT_DBG("original tx event ring db: %u\n",
|
|
orig_tx_event_ring_db);
|
|
|
|
rx_event_ring_db = (u32 *)test_wdi3_ctx->rx_event_ring_db.base;
|
|
orig_rx_event_ring_db = *rx_event_ring_db;
|
|
IPA_UT_DBG("original rx event ring db: %u\n",
|
|
orig_rx_event_ring_db);
|
|
|
|
rx_transfer_ring_db
|
|
= (u32 *)test_wdi3_ctx->rx_transfer_ring_db.base;
|
|
orig_tx_trans_ring_db = *rx_transfer_ring_db;
|
|
IPA_UT_DBG("original rx transfer ring db: %u\n",
|
|
*rx_transfer_ring_db);
|
|
|
|
/* ring uc db */
|
|
iowrite32(rx_uc_db_local, rx_uc_db);
|
|
IPA_UT_DBG("rx db local: %u\n", rx_uc_db_local);
|
|
|
|
loop_cnt = 0;
|
|
while (orig_tx_event_ring_db == *tx_event_ring_db ||
|
|
*rx_event_ring_db == orig_rx_event_ring_db) {
|
|
loop_cnt++;
|
|
IPA_UT_DBG("loop count: %d tx\n", loop_cnt);
|
|
IPA_UT_DBG("orig_tx_event_ring_db: %u tx_event_ring_db: %u\n",
|
|
orig_tx_event_ring_db, *tx_event_ring_db);
|
|
IPA_UT_DBG("rx_transfer_ring_db: %u rx db local: %u\n",
|
|
*rx_transfer_ring_db, rx_uc_db_local);
|
|
IPA_UT_DBG("orig_rx_event_ring_db: %u rx_event_ring_db %u\n",
|
|
orig_rx_event_ring_db, *rx_event_ring_db);
|
|
if (loop_cnt == 1000) {
|
|
IPA_UT_ERR("transfer timeout!\n");
|
|
gsi_wdi3_dump_register(1);
|
|
gsi_wdi3_dump_register(9);
|
|
BUG();
|
|
return -EFAULT;
|
|
}
|
|
usleep_range(1000, 1001);
|
|
}
|
|
IPA_UT_DBG("rx_transfer_ring_db: %u\n", *rx_transfer_ring_db);
|
|
IPA_UT_DBG("tx_event_ring_db: %u\n", *tx_event_ring_db);
|
|
num_words = sizeof(struct rx_event_ring_ele)/4;
|
|
rx_event = (struct rx_event_ring_ele *)
|
|
(test_wdi3_ctx->rx_event_ring_addr.base) +
|
|
(*rx_event_ring_db/num_words - 1 + NUM_RX_ER_ELE) %
|
|
NUM_RX_ER_ELE;
|
|
IPA_UT_DBG("rx_event offset: %u\n",
|
|
(*rx_event_ring_db/num_words - 1 + NUM_RX_ER_ELE) %
|
|
NUM_RX_ER_ELE);
|
|
IPA_UT_DBG("rx_event va: %pK\n", rx_event);
|
|
IPA_UT_DBG("rx event low: %u rx event high: %u\n",
|
|
rx_event->buf_or_link_desc_addr_info.buffer_addr_low,
|
|
rx_event->buf_or_link_desc_addr_info.buffer_addr_high);
|
|
IPA_UT_DBG("rx buf low: %u rx buf high: %u\n",
|
|
rx_buf.buffer_addr_low, rx_buf.buffer_addr_high);
|
|
if (rx_event->buf_or_link_desc_addr_info.buffer_addr_low !=
|
|
rx_buf.buffer_addr_low ||
|
|
rx_event->buf_or_link_desc_addr_info.buffer_addr_high !=
|
|
rx_buf.buffer_addr_high) {
|
|
IPA_UT_ERR("rx event ring buf addr doesn't match.\n");
|
|
BUG();
|
|
return -EFAULT;
|
|
}
|
|
|
|
num_words = sizeof(struct tx_event_ring_ele)/4;
|
|
tx_event = (struct tx_event_ring_ele *)
|
|
test_wdi3_ctx->tx_event_ring_addr.base +
|
|
(*tx_event_ring_db/num_words - 1 + NUM_TX_ER_ELE) %
|
|
NUM_TX_ER_ELE;
|
|
IPA_UT_DBG("tx_event va: %pK\n", tx_event);
|
|
IPA_UT_DBG("tx event offset: %u\n",
|
|
(*tx_event_ring_db/num_words - 1 + NUM_TX_ER_ELE) %
|
|
NUM_TX_ER_ELE);
|
|
IPA_UT_DBG("recv addr low: %u recv_addr high: %u\n",
|
|
tx_event->buf_or_link_desc_addr_info.buffer_addr_low,
|
|
tx_event->buf_or_link_desc_addr_info.buffer_addr_high);
|
|
recv_packet_addr =
|
|
((u64)tx_event->buf_or_link_desc_addr_info.buffer_addr_high
|
|
<< 32) |
|
|
(u64)tx_event->buf_or_link_desc_addr_info.buffer_addr_low;
|
|
IPA_UT_DBG("high: %llu low: %llu all: %llu\n",
|
|
(u64)tx_event->buf_or_link_desc_addr_info.buffer_addr_high
|
|
<< 32,
|
|
(u64)tx_event->buf_or_link_desc_addr_info.buffer_addr_low,
|
|
recv_packet_addr);
|
|
for (i = 0; i < NUM_TX_BUFS; i++)
|
|
if (recv_packet_addr == test_wdi3_ctx->tx_bufs[i].phys_base) {
|
|
IPA_UT_DBG("found buf at position %d\n", i);
|
|
packet_recv = (u32 *)test_wdi3_ctx->tx_bufs[i].base;
|
|
}
|
|
IPA_UT_DBG("packet_recv addr: %pK\n", packet_recv);
|
|
if (*packet_recv != PACKET_CONTENT) {
|
|
IPA_UT_ERR("recv packet doesn't match.\n");
|
|
IPA_UT_ERR("packet: %d packet_recv: %d\n", PACKET_CONTENT,
|
|
*packet_recv);
|
|
return -EFAULT;
|
|
}
|
|
IPA_UT_INFO("recv packet matches!! Recycling the buffer ...\n");
|
|
/* recycle buffer */
|
|
tx_uc_db = ioremap(test_wdi3_ctx->tx_uc_db_pa, DB_REGISTER_SIZE);
|
|
num_words = sizeof(struct tx_transfer_ring_ele) / 4;
|
|
idx = tx_uc_db_local / num_words;
|
|
IPA_UT_DBG("tx_db_local: %u idx %d\n", tx_uc_db_local, idx);
|
|
tx_transfer = (struct tx_transfer_ring_ele *)
|
|
test_wdi3_ctx->tx_transfer_ring_addr.base + idx;
|
|
tx_transfer->buf_or_link_desc_addr_info.buffer_addr_low =
|
|
tx_event->buf_or_link_desc_addr_info.buffer_addr_low;
|
|
tx_transfer->buf_or_link_desc_addr_info.buffer_addr_high =
|
|
tx_event->buf_or_link_desc_addr_info.buffer_addr_high;
|
|
ipa_test_wdi3_advance_uc_db(&tx_uc_db_local, 1,
|
|
sizeof(struct tx_transfer_ring_ele)/4,
|
|
test_wdi3_ctx->tx_transfer_ring_addr.size);
|
|
iowrite32(tx_uc_db_local, tx_uc_db);
|
|
tx_bf_idx = (tx_bf_idx + 1) % NUM_TX_BUFS;
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_wdi3_test_reg_intf(void)
|
|
{
|
|
struct ipa_wdi_reg_intf_in_params in;
|
|
char netdev_name[IPA_RESOURCE_NAME_MAX] = {0};
|
|
u8 hdr_content = 1;
|
|
|
|
memset(&in, 0, sizeof(in));
|
|
snprintf(netdev_name, sizeof(netdev_name), "wdi3_test");
|
|
in.netdev_name = netdev_name;
|
|
in.is_meta_data_valid = 0;
|
|
in.hdr_info[0].hdr = &hdr_content;
|
|
in.hdr_info[0].hdr_len = 1;
|
|
in.hdr_info[0].dst_mac_addr_offset = 0;
|
|
in.hdr_info[0].hdr_type = IPA_HDR_L2_ETHERNET_II;
|
|
in.hdr_info[1].hdr = &hdr_content;
|
|
in.hdr_info[1].hdr_len = 1;
|
|
in.hdr_info[1].dst_mac_addr_offset = 0;
|
|
in.hdr_info[1].hdr_type = IPA_HDR_L2_ETHERNET_II;
|
|
|
|
return ipa_wdi_reg_intf(&in);
|
|
}
|
|
|
|
static int ipa_wdi3_test_dereg_intf(void)
|
|
{
|
|
char netdev_name[IPA_RESOURCE_NAME_MAX] = {0};
|
|
|
|
snprintf(netdev_name, sizeof(netdev_name), "wdi3_test");
|
|
IPA_UT_INFO("netdev name: %s strlen: %lu\n", netdev_name,
|
|
strlen(netdev_name));
|
|
|
|
return ipa_wdi_dereg_intf(netdev_name);
|
|
}
|
|
|
|
static int ipa_wdi3_test_single_transfer(void *priv)
|
|
{
|
|
struct ipa_ep_cfg ep_cfg = { {0} };
|
|
|
|
if (ipa_wdi3_test_reg_intf()) {
|
|
IPA_UT_ERR("fail to register intf.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ipa_wdi3_setup_pipes()) {
|
|
IPA_UT_ERR("fail to setup wdi3 pipes.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* configure WLAN RX EP in DMA mode */
|
|
ep_cfg.mode.mode = IPA_DMA;
|
|
ep_cfg.mode.dst = IPA_CLIENT_WLAN2_CONS;
|
|
|
|
ep_cfg.seq.set_dynamic = true;
|
|
|
|
ipa_cfg_ep(ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD), &ep_cfg);
|
|
|
|
if (ipa_wdi3_send_one_packet()) {
|
|
IPA_UT_ERR("fail to transfer packet.\n");
|
|
ipa_wdi3_teardown_pipes();
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ipa_wdi3_teardown_pipes()) {
|
|
IPA_UT_ERR("fail to tear down pipes.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
IPA_UT_INFO("pipes were torn down!\n");
|
|
|
|
if (ipa_wdi3_test_dereg_intf()) {
|
|
IPA_UT_ERR("fail to deregister interface.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_wdi3_send_multi_packet(void)
|
|
{
|
|
void __iomem *rx_uc_db;
|
|
void __iomem *tx_uc_db;
|
|
u32 *tx_event_ring_db, *rx_transfer_ring_db, *rx_event_ring_db;
|
|
u32 orig_tx_event_ring_db;
|
|
u32 orig_rx_event_ring_db;
|
|
u32 *packet;
|
|
u32 *packet_recv = NULL;
|
|
struct rx_transfer_ring_ele *rx_transfer;
|
|
struct rx_event_ring_ele *rx_event;
|
|
struct tx_event_ring_ele *tx_event;
|
|
struct tx_transfer_ring_ele *tx_transfer;
|
|
struct buffer_addr_info rx_buf;
|
|
dma_addr_t recv_packet_addr;
|
|
int loop_cnt, i, num_words;
|
|
int idx;
|
|
|
|
/* populate packet content */
|
|
num_words = sizeof(struct rx_transfer_ring_ele) / 4;
|
|
rx_uc_db = ioremap(test_wdi3_ctx->rx_uc_db_pa, DB_REGISTER_SIZE);
|
|
for (i = 0; i < NUM_MULTI_PKT; i++) {
|
|
idx = rx_uc_db_local / num_words;
|
|
packet = (u32 *)test_wdi3_ctx->rx_bufs[rx_bf_idx].base
|
|
+ PACKET_HEADER_SIZE / 4;
|
|
*packet = multi_pkt_array[i];
|
|
IPA_UT_DBG("rx_db_local: %u rx_bf_idx: %d\n",
|
|
rx_uc_db_local, rx_bf_idx);
|
|
rx_bf_idx = (rx_bf_idx + 1) % NUM_RX_BUFS;
|
|
/* update rx_transfer_ring_ele */
|
|
rx_transfer = (struct rx_transfer_ring_ele *)
|
|
test_wdi3_ctx->rx_transfer_ring_addr.base + idx;
|
|
ipa_test_wdi3_advance_uc_db(&rx_uc_db_local, 1,
|
|
sizeof(struct rx_transfer_ring_ele)/4,
|
|
test_wdi3_ctx->rx_transfer_ring_addr.size);
|
|
rx_transfer->rx_msdu_desc_info_details.msdu_length =
|
|
ETH_PACKET_SIZE + PACKET_HEADER_SIZE;
|
|
rx_buf.buffer_addr_low =
|
|
rx_transfer->buf_or_link_desc_addr_info.buffer_addr_low;
|
|
rx_buf.buffer_addr_high =
|
|
rx_transfer->buf_or_link_desc_addr_info.buffer_addr_high;
|
|
}
|
|
|
|
tx_event_ring_db = (u32 *)test_wdi3_ctx->tx_event_ring_db.base;
|
|
orig_tx_event_ring_db = *tx_event_ring_db;
|
|
IPA_UT_DBG("original tx event ring db: %u\n", orig_tx_event_ring_db);
|
|
|
|
rx_event_ring_db = (u32 *)test_wdi3_ctx->rx_event_ring_db.base;
|
|
orig_rx_event_ring_db = *rx_event_ring_db;
|
|
IPA_UT_DBG("original rx event ring db: %u\n", orig_rx_event_ring_db);
|
|
|
|
rx_transfer_ring_db = (u32 *)test_wdi3_ctx->rx_transfer_ring_db.base;
|
|
IPA_UT_DBG("original rx transfer ring db: %u\n", *rx_transfer_ring_db);
|
|
|
|
/* ring uc db */
|
|
iowrite32(rx_uc_db_local, rx_uc_db);
|
|
IPA_UT_DBG("rx db local: %u\n", rx_uc_db_local);
|
|
|
|
loop_cnt = 0;
|
|
while (orig_tx_event_ring_db == *tx_event_ring_db ||
|
|
*rx_transfer_ring_db != rx_uc_db_local ||
|
|
orig_rx_event_ring_db == *rx_event_ring_db) {
|
|
loop_cnt++;
|
|
IPA_UT_DBG("loop count: %d tx\n", loop_cnt);
|
|
IPA_UT_DBG("orig_tx_event_ring_db: %u tx_event_ring_db: %u\n",
|
|
orig_tx_event_ring_db, *tx_event_ring_db);
|
|
IPA_UT_DBG("rx_transfer_ring_db: %u rx db local: %u\n",
|
|
*rx_transfer_ring_db, rx_uc_db_local);
|
|
IPA_UT_DBG("orig_rx_event_ring_db: %u rx_event_ring_db %u\n",
|
|
orig_rx_event_ring_db, *rx_event_ring_db);
|
|
if (loop_cnt == 1000) {
|
|
IPA_UT_ERR("transfer timeout!\n");
|
|
BUG();
|
|
return -EFAULT;
|
|
}
|
|
usleep_range(1000, 1001);
|
|
}
|
|
|
|
IPA_UT_DBG("rx_transfer_ring_db: %u\n", *rx_transfer_ring_db);
|
|
IPA_UT_DBG("tx_event_ring_db: %u\n", *tx_event_ring_db);
|
|
num_words = sizeof(struct rx_event_ring_ele)/4;
|
|
rx_event = (struct rx_event_ring_ele *)
|
|
test_wdi3_ctx->rx_event_ring_addr.base +
|
|
(*rx_event_ring_db/num_words - 1 + NUM_RX_ER_ELE) %
|
|
NUM_RX_ER_ELE;
|
|
IPA_UT_DBG("rx_event va: %pK\n", rx_event);
|
|
|
|
IPA_UT_DBG("rx event low: %u rx event high: %u\n",
|
|
rx_event->buf_or_link_desc_addr_info.buffer_addr_low,
|
|
rx_event->buf_or_link_desc_addr_info.buffer_addr_high);
|
|
IPA_UT_DBG("rx buf low: %u rx buf high: %u\n",
|
|
rx_buf.buffer_addr_low, rx_buf.buffer_addr_high);
|
|
|
|
if (rx_event->buf_or_link_desc_addr_info.buffer_addr_low !=
|
|
rx_buf.buffer_addr_low ||
|
|
rx_event->buf_or_link_desc_addr_info.buffer_addr_high !=
|
|
rx_buf.buffer_addr_high) {
|
|
IPA_UT_ERR("rx event ring buf addr doesn't match.\n");
|
|
return -EFAULT;
|
|
}
|
|
num_words = sizeof(struct tx_event_ring_ele)/4;
|
|
tx_event = (struct tx_event_ring_ele *)
|
|
test_wdi3_ctx->tx_event_ring_addr.base +
|
|
(*tx_event_ring_db/num_words - NUM_MULTI_PKT + NUM_TX_ER_ELE) %
|
|
NUM_TX_ER_ELE;
|
|
IPA_UT_DBG("tx_event va: %pK\n", tx_event);
|
|
IPA_UT_DBG("recv addr low: %u recv_addr high: %u\n",
|
|
tx_event->buf_or_link_desc_addr_info.buffer_addr_low,
|
|
tx_event->buf_or_link_desc_addr_info.buffer_addr_high);
|
|
recv_packet_addr =
|
|
((u64)tx_event->buf_or_link_desc_addr_info.buffer_addr_high
|
|
<< 32) |
|
|
(u64)tx_event->buf_or_link_desc_addr_info.buffer_addr_low;
|
|
IPA_UT_DBG("high: %llu low: %llu all: %llu\n",
|
|
(u64)tx_event->buf_or_link_desc_addr_info.buffer_addr_high
|
|
<< 32,
|
|
(u64)tx_event->buf_or_link_desc_addr_info.buffer_addr_low,
|
|
recv_packet_addr);
|
|
for (i = 0; i < NUM_TX_BUFS; i++)
|
|
if (recv_packet_addr == test_wdi3_ctx->tx_bufs[i].phys_base) {
|
|
IPA_UT_INFO("found buf at position %d\n", i);
|
|
packet_recv = (u32 *)test_wdi3_ctx->tx_bufs[i].base;
|
|
}
|
|
|
|
if (*packet_recv != multi_pkt_array[0]) {
|
|
IPA_UT_ERR("recv packet doesn't match.\n");
|
|
IPA_UT_ERR("packet: %d packet_recv: %d\n",
|
|
multi_pkt_array[0], *packet_recv);
|
|
return -EFAULT;
|
|
}
|
|
|
|
IPA_UT_INFO("recv packet matches.\n");
|
|
|
|
/* recycle buffer */
|
|
tx_uc_db = ioremap(test_wdi3_ctx->tx_uc_db_pa, DB_REGISTER_SIZE);
|
|
num_words = sizeof(struct tx_transfer_ring_ele) / 4;
|
|
|
|
for (i = 0; i < NUM_MULTI_PKT; i++) {
|
|
idx = tx_uc_db_local / num_words;
|
|
IPA_UT_DBG("tx_db_local: %u idx %d\n", tx_uc_db_local, idx);
|
|
tx_event = (struct tx_event_ring_ele *)
|
|
test_wdi3_ctx->tx_event_ring_addr.base +
|
|
(*tx_event_ring_db/num_words - NUM_MULTI_PKT
|
|
+ i + NUM_TX_ER_ELE) % NUM_TX_ER_ELE;
|
|
tx_transfer = (struct tx_transfer_ring_ele *)
|
|
test_wdi3_ctx->tx_transfer_ring_addr.base + idx;
|
|
tx_transfer->buf_or_link_desc_addr_info.buffer_addr_low =
|
|
tx_event->buf_or_link_desc_addr_info.buffer_addr_low;
|
|
tx_transfer->buf_or_link_desc_addr_info.buffer_addr_high =
|
|
tx_event->buf_or_link_desc_addr_info.buffer_addr_high;
|
|
ipa_test_wdi3_advance_uc_db(&tx_uc_db_local, 1,
|
|
sizeof(struct tx_transfer_ring_ele)/4,
|
|
test_wdi3_ctx->tx_transfer_ring_addr.size);
|
|
}
|
|
iowrite32(tx_uc_db_local, tx_uc_db);
|
|
tx_bf_idx = (tx_bf_idx + NUM_MULTI_PKT) % NUM_TX_BUFS;
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_wdi3_test_multi_transfer(void *priv)
|
|
{
|
|
struct ipa_ep_cfg ep_cfg = { {0} };
|
|
|
|
if (ipa_wdi3_test_reg_intf()) {
|
|
IPA_UT_ERR("fail to register intf.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ipa_wdi3_setup_pipes()) {
|
|
IPA_UT_ERR("fail to setup wdi3 pipes.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* configure WLAN RX EP in DMA mode */
|
|
ep_cfg.mode.mode = IPA_DMA;
|
|
ep_cfg.mode.dst = IPA_CLIENT_WLAN2_CONS;
|
|
|
|
ep_cfg.seq.set_dynamic = true;
|
|
|
|
ipa_cfg_ep(ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD), &ep_cfg);
|
|
|
|
if (ipa_wdi3_send_multi_packet()) {
|
|
IPA_UT_ERR("fail to transfer packet.\n");
|
|
ipa_wdi3_teardown_pipes();
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ipa_wdi3_teardown_pipes()) {
|
|
IPA_UT_ERR("fail to tear down pipes.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
IPA_UT_INFO("pipes were torn down!\n");
|
|
|
|
if (ipa_wdi3_test_dereg_intf()) {
|
|
IPA_UT_ERR("fail to deregister interface.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_wdi3_test_multi_transfer2(void *priv)
|
|
{
|
|
struct ipa_ep_cfg ep_cfg = { {0} };
|
|
int i;
|
|
|
|
if (ipa_wdi3_test_reg_intf()) {
|
|
IPA_UT_ERR("fail to register intf.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ipa_wdi3_setup_pipes()) {
|
|
IPA_UT_ERR("fail to setup wdi3 pipes.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* configure WLAN RX EP in DMA mode */
|
|
ep_cfg.mode.mode = IPA_DMA;
|
|
ep_cfg.mode.dst = IPA_CLIENT_WLAN2_CONS;
|
|
|
|
ep_cfg.seq.set_dynamic = true;
|
|
|
|
ipa_cfg_ep(ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD), &ep_cfg);
|
|
|
|
IPA_UT_DBG("-----start transfer 32 pkt----\n");
|
|
for (i = 0; i < 32; i++) {
|
|
IPA_UT_DBG("--transferring num #%d pkt--\n", i + 1);
|
|
if (ipa_wdi3_send_one_packet()) {
|
|
IPA_UT_ERR("fail to transfer packet.\n");
|
|
ipa_wdi3_teardown_pipes();
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
if (ipa_wdi3_teardown_pipes()) {
|
|
IPA_UT_ERR("fail to tear down pipes.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
IPA_UT_ERR("pipes were torn down!\n");
|
|
|
|
if (ipa_wdi3_test_dereg_intf()) {
|
|
IPA_UT_ERR("fail to deregister interface.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ipa_wdi3_test_multi_transfer3(void *priv)
|
|
{
|
|
struct ipa_ep_cfg ep_cfg = { {0} };
|
|
int i;
|
|
|
|
if (ipa_wdi3_test_reg_intf()) {
|
|
IPA_UT_ERR("fail to register intf.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (ipa_wdi3_setup_pipes()) {
|
|
IPA_UT_ERR("fail to setup wdi3 pipes.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* configure WLAN RX EP in DMA mode */
|
|
ep_cfg.mode.mode = IPA_DMA;
|
|
ep_cfg.mode.dst = IPA_CLIENT_WLAN2_CONS;
|
|
|
|
ep_cfg.seq.set_dynamic = true;
|
|
|
|
ipa_cfg_ep(ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD), &ep_cfg);
|
|
|
|
IPA_UT_DBG("-----start transfer 256 pkt----\n");
|
|
for (i = 0; i < 32; i++) {
|
|
IPA_UT_DBG("--transferring num # %d to num # %d pkt--\n",
|
|
(i + 1) * 8, (i + 2) * 8 - 1);
|
|
if (ipa_wdi3_send_multi_packet()) {
|
|
IPA_UT_ERR("fail to transfer packet.\n");
|
|
ipa_wdi3_teardown_pipes();
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
|
|
if (ipa_wdi3_teardown_pipes()) {
|
|
IPA_UT_ERR("fail to tear down pipes.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
IPA_UT_ERR("pipes were torn down!\n");
|
|
|
|
if (ipa_wdi3_test_dereg_intf()) {
|
|
IPA_UT_ERR("fail to deregister interface.\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Suite definition block */
|
|
IPA_UT_DEFINE_SUITE_START(wdi3, "WDI3 tests",
|
|
ipa_test_wdi3_suite_setup, ipa_test_wdi3_suite_teardown)
|
|
{
|
|
IPA_UT_ADD_TEST(single_transfer,
|
|
"single data transfer",
|
|
ipa_wdi3_test_single_transfer,
|
|
true, IPA_HW_v3_0, IPA_HW_MAX),
|
|
|
|
IPA_UT_ADD_TEST(multi_transfer,
|
|
"multiple data transfer",
|
|
ipa_wdi3_test_multi_transfer,
|
|
true, IPA_HW_v3_0, IPA_HW_MAX),
|
|
|
|
IPA_UT_ADD_TEST(multi_transfer2,
|
|
"multiple data transfer with data wrap around",
|
|
ipa_wdi3_test_multi_transfer2,
|
|
true, IPA_HW_v3_0, IPA_HW_MAX),
|
|
|
|
IPA_UT_ADD_TEST(multi_transfer3,
|
|
"multiple data transfer with data wrap around2",
|
|
ipa_wdi3_test_multi_transfer3,
|
|
true, IPA_HW_v3_0, IPA_HW_MAX)
|
|
} IPA_UT_DEFINE_SUITE_END(wdi3);
|
|
|
|
|