Fix the issue of iGent env related big ping delay:

1. The issue only happens at zcu102 side, when it is tested as AP together with zedboard
2. The issue does not happen when zcu102 is client and zedboard is AP
3. The issue (most likely) does not happen in places other than iGent (like Pablo home)
4. Sometimes it does happen at my home when I test zcu102 as AP together with COTS WiFi
5. Indeed seems like the environment related. Guess some quick small packets in the environment quickly flush/round-up/mess-up the rx dma cyclic buffer, and the rx interrupt internal static variable target_buf_idx_old loses track of the background automatic rx dma cyclic buffer
6. The fix is for all board types (zcu102, zedboard, 7035, etc)
7. The driver compiling make_all.sh script generates USE_NEW_RX_INTERRUPT macro to pre_def.h to enable the new code (while keeping the old code). You can use the script as before.
8. The logic of the fix is that exhaustive search all the rx dma cyclic buffer in rx interrupt to get packet to Linux in the first place.
This commit is contained in:
Xianjun Jiao 2021-09-29 16:52:45 +02:00
parent f286042926
commit 109b1cfd3a
3 changed files with 33 additions and 8 deletions

View File

@ -39,10 +39,12 @@ if [ "$ARCH_OPTION" == "64" ]; then
LINUX_KERNEL_SRC_DIR=$OPENWIFI_DIR/adi-linux-64/
ARCH="arm64"
CROSS_COMPILE="aarch64-linux-gnu-"
echo "#define USE_NEW_RX_INTERRUPT 1" > pre_def.h
else
LINUX_KERNEL_SRC_DIR=$OPENWIFI_DIR/adi-linux/
ARCH="arm"
CROSS_COMPILE="arm-linux-gnueabihf-"
echo "#define USE_NEW_RX_INTERRUPT 1" > pre_def.h
fi
# check if user entered the right path to analog device linux

View File

@ -338,19 +338,29 @@ static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id)
// u32 dma_driver_buf_idx_mod;
u8 *pdata_tmp, fcs_ok;//, target_buf_idx;//, phy_rx_sn_hw;
s8 signal;
u16 rssi_val, addr1_high16=0, addr2_high16=0, addr3_high16=0, sc=0;
u16 agc_status_and_pkt_exist_flag, rssi_val, addr1_high16=0, addr2_high16=0, addr3_high16=0, sc=0;
bool content_ok = false, len_overflow = false;
static u8 target_buf_idx_old = 0;
#ifdef USE_NEW_RX_INTERRUPT
int i;
spin_lock(&priv->lock);
for (i=0; i<NUM_RX_BD; i++) {
pdata_tmp = priv->rx_cyclic_buf + i*RX_BD_BUF_SIZE;
agc_status_and_pkt_exist_flag = (*((u16*)(pdata_tmp+10))); //check rx_intf_pl_to_m_axis.v. FPGA TODO: add pkt exist 1bit flag next to gpio_status_lock_by_sig_valid
if ( agc_status_and_pkt_exist_flag==0 ) // no packet in the buffer
continue;
#else
static u8 target_buf_idx_old = 0;
spin_lock(&priv->lock);
while(1) { // loop all rx buffers that have new rx packets
pdata_tmp = priv->rx_cyclic_buf + target_buf_idx_old*RX_BD_BUF_SIZE; // our header insertion is at the beginning
agc_status_and_pkt_exist_flag = (*((u16*)(pdata_tmp+10)));
if ( agc_status_and_pkt_exist_flag==0 ) // no packet in the buffer
break;
#endif
tsft_low = (*((u32*)(pdata_tmp+0 )));
tsft_high = (*((u32*)(pdata_tmp+4 )));
if ( tsft_low==0 && tsft_high==0 ) // no packet in the buffer
break;
rssi_val = (*((u16*)(pdata_tmp+8 )));
len = (*((u16*)(pdata_tmp+12)));
@ -410,7 +420,11 @@ static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id)
printk("%s openwifi_rx_interrupt:%4dbytes ht%d %3dM FC%04x DI%04x addr1/2/3:%04x%08x/%04x%08x/%04x%08x SC%04x fcs%d buf_idx%d %ddBm\n", sdr_compatible_str,
len, ht_flag, wifi_rate_table[rate_idx], hdr->frame_control, hdr->duration_id,
reverse16(addr1_high16), reverse32(addr1_low32), reverse16(addr2_high16), reverse32(addr2_low32), reverse16(addr3_high16), reverse32(addr3_low32),
#ifdef USE_NEW_RX_INTERRUPT
sc, fcs_ok, i, signal);
#else
sc, fcs_ok, target_buf_idx_old, signal);
#endif
}
// priv->phy_rx_sn_hw_old = phy_rx_sn_hw;
@ -442,10 +456,11 @@ static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id)
} else
printk("%s openwifi_rx_interrupt: WARNING dev_alloc_skb failed!\n", sdr_compatible_str);
}
(*((u32*)(pdata_tmp+0 ))) = 0;
(*((u32*)(pdata_tmp+4 ))) = 0; // clear the tsft_low and tsft_high to indicate the packet has been processed
(*((u16*)(pdata_tmp+10))) = 0; // clear the field (set by rx_intf_pl_to_m_axis.v) to indicate the packet has been processed
loop_count++;
#ifndef USE_NEW_RX_INTERRUPT
target_buf_idx_old=((target_buf_idx_old+1)&(NUM_RX_BD-1));
#endif
}
if ( loop_count!=1 && (priv->drv_rx_reg_val[DRV_RX_REG_IDX_PRINT_CFG]&1) )

View File

@ -5,6 +5,8 @@
#ifndef OPENWIFI_SDR
#define OPENWIFI_SDR
#include "pre_def.h"
// -------------------for leds--------------------------------
struct gpio_led_data { //please always align with the leds-gpio.c in linux kernel
struct led_classdev cdev;
@ -90,7 +92,13 @@ union u16_byte2 {
#define RING_ROOM_THRESHOLD 4
#define NUM_TX_BD 64 // !!! should align to the fifo size in tx_bit_intf.v
#ifdef USE_NEW_RX_INTERRUPT
#define NUM_RX_BD 8
#else
#define NUM_RX_BD 16
#endif
#define TX_BD_BUF_SIZE (8192)
#define RX_BD_BUF_SIZE (8192)