xref: /openwifi/driver/sdr.c (revision b60e485eb584f5f026a594a5f59c9fb2ef2cb5ee)
1 // Author: Xianjun Jiao, Michael Mehari, Wei Liu
2 // SPDX-FileCopyrightText: 2019 UGent
3 // SPDX-License-Identifier: AGPL-3.0-or-later
4 
5 #include <linux/bitops.h>
6 #include <linux/dmapool.h>
7 #include <linux/io.h>
8 #include <linux/iopoll.h>
9 #include <linux/of_address.h>
10 #include <linux/of_platform.h>
11 #include <linux/of_irq.h>
12 #include <linux/slab.h>
13 #include <linux/clk.h>
14 #include <linux/io-64-nonatomic-lo-hi.h>
15 
16 #include <linux/delay.h>
17 #include <linux/interrupt.h>
18 
19 #include <linux/dmaengine.h>
20 #include <linux/slab.h>
21 #include <linux/delay.h>
22 #include <linux/etherdevice.h>
23 
24 #include <linux/init.h>
25 #include <linux/kthread.h>
26 #include <linux/module.h>
27 #include <linux/of_dma.h>
28 #include <linux/platform_device.h>
29 #include <linux/random.h>
30 #include <linux/slab.h>
31 #include <linux/wait.h>
32 #include <linux/sched/task.h>
33 #include <linux/dma/xilinx_dma.h>
34 #include <linux/spi/spi.h>
35 #include <net/mac80211.h>
36 
37 #include <linux/clk.h>
38 #include <linux/clkdev.h>
39 #include <linux/clk-provider.h>
40 
41 #include <linux/iio/iio.h>
42 #include <linux/iio/sysfs.h>
43 
44 #include <linux/gpio.h>
45 #include <linux/leds.h>
46 
47 #define IIO_AD9361_USE_PRIVATE_H_
48 #include <../../drivers/iio/adc/ad9361_regs.h>
49 #include <../../drivers/iio/adc/ad9361.h>
50 #include <../../drivers/iio/adc/ad9361_private.h>
51 
52 #include <../../drivers/iio/frequency/cf_axi_dds.h>
53 extern int ad9361_get_tx_atten(struct ad9361_rf_phy *phy, u32 tx_num);
54 extern int ad9361_set_tx_atten(struct ad9361_rf_phy *phy, u32 atten_mdb,
55 			       bool tx1, bool tx2, bool immed);
56 extern int ad9361_ctrl_outs_setup(struct ad9361_rf_phy *phy,
57 				  struct ctrl_outs_control *ctrl);
58 
59 #include "../user_space/sdrctl_src/nl80211_testmode_def.h"
60 #include "hw_def.h"
61 #include "sdr.h"
62 #include "git_rev.h"
63 
64 // driver API of component driver
65 extern struct tx_intf_driver_api *tx_intf_api;
66 extern struct rx_intf_driver_api *rx_intf_api;
67 extern struct openofdm_tx_driver_api *openofdm_tx_api;
68 extern struct openofdm_rx_driver_api *openofdm_rx_api;
69 extern struct xpu_driver_api *xpu_api;
70 
71 static int test_mode = 0; // 0 normal; 1 rx test
72 
73 MODULE_AUTHOR("Xianjun Jiao");
74 MODULE_DESCRIPTION("SDR driver");
75 MODULE_LICENSE("GPL v2");
76 
77 module_param(test_mode, int, 0);
78 MODULE_PARM_DESC(myint, "test_mode. 0 normal; 1 rx test");
79 
80 // ---------------rfkill---------------------------------------
81 static bool openwifi_is_radio_enabled(struct openwifi_priv *priv)
82 {
83 	int reg;
84 
85 	if (priv->tx_intf_cfg == TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT1)
86 		reg = ad9361_get_tx_atten(priv->ad9361_phy, 2);
87 	else
88 		reg = ad9361_get_tx_atten(priv->ad9361_phy, 1);
89 
90 	if (reg == AD9361_RADIO_ON_TX_ATT)
91 		return true;// 0 off, 1 on
92 	return false;
93 }
94 
95 void openwifi_rfkill_init(struct ieee80211_hw *hw)
96 {
97 	struct openwifi_priv *priv = hw->priv;
98 
99 	priv->rfkill_off = openwifi_is_radio_enabled(priv);
100 	printk("%s openwifi_rfkill_init: wireless switch is %s\n", sdr_compatible_str, priv->rfkill_off ? "on" : "off");
101 	wiphy_rfkill_set_hw_state(hw->wiphy, !priv->rfkill_off);
102 	wiphy_rfkill_start_polling(hw->wiphy);
103 }
104 
105 void openwifi_rfkill_poll(struct ieee80211_hw *hw)
106 {
107 	bool enabled;
108 	struct openwifi_priv *priv = hw->priv;
109 
110 	enabled = openwifi_is_radio_enabled(priv);
111 	// printk("%s openwifi_rfkill_poll: wireless radio switch turned %s\n", sdr_compatible_str, enabled ? "on" : "off");
112 	if (unlikely(enabled != priv->rfkill_off)) {
113 		priv->rfkill_off = enabled;
114 		printk("%s openwifi_rfkill_poll: WARNING wireless radio switch turned %s\n", sdr_compatible_str, enabled ? "on" : "off");
115 		wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
116 	}
117 }
118 
119 void openwifi_rfkill_exit(struct ieee80211_hw *hw)
120 {
121 	printk("%s openwifi_rfkill_exit\n", sdr_compatible_str);
122 	wiphy_rfkill_stop_polling(hw->wiphy);
123 }
124 //----------------rfkill end-----------------------------------
125 
126 //static void ad9361_rf_init(void);
127 //static void ad9361_rf_stop(void);
128 //static void ad9361_rf_calc_rssi(void);
129 static void ad9361_rf_set_channel(struct ieee80211_hw *dev,
130 				  struct ieee80211_conf *conf)
131 {
132 	struct openwifi_priv *priv = dev->priv;
133 	u32 actual_rx_lo = conf->chandef.chan->center_freq - priv->rx_freq_offset_to_lo_MHz + priv->drv_rx_reg_val[DRV_RX_REG_IDX_EXTRA_FO];
134 	u32 actual_tx_lo;
135 	bool change_flag = (actual_rx_lo != priv->actual_rx_lo);
136 	int static_lbt_th, auto_lbt_th, fpga_lbt_th;
137 
138 	if (change_flag) {
139 		priv->actual_rx_lo = actual_rx_lo;
140 
141 		actual_tx_lo = conf->chandef.chan->center_freq - priv->tx_freq_offset_to_lo_MHz;
142 
143 		clk_set_rate(priv->ad9361_phy->clks[RX_RFPLL], ( ((u64)1000000ull)*((u64)actual_rx_lo )>>1) );
144 		clk_set_rate(priv->ad9361_phy->clks[TX_RFPLL], ( ((u64)1000000ull)*((u64)actual_tx_lo )>>1) );
145 
146 		if (actual_rx_lo<2412) {
147 			priv->rssi_correction = 153;
148 		} else if (actual_rx_lo<=2484) {
149 			priv->rssi_correction = 153;
150 		} else if (actual_rx_lo<5160) {
151 			priv->rssi_correction = 153;
152 		} else if (actual_rx_lo<=5240) {
153 			priv->rssi_correction = 145;
154 		} else if (actual_rx_lo<=5320) {
155 			priv->rssi_correction = 148;
156 		} else {
157 			priv->rssi_correction = 148;
158 		}
159 
160 		// xpu_api->XPU_REG_LBT_TH_write((priv->rssi_correction-62)<<1); // -62dBm
161 		// xpu_api->XPU_REG_LBT_TH_write((priv->rssi_correction-62-16)<<1); // wei's magic value is 135, here is 134 @ ch 44
162 		auto_lbt_th = ((priv->rssi_correction-62-16)<<1);
163 		static_lbt_th = priv->drv_xpu_reg_val[DRV_XPU_REG_IDX_LBT_TH];
164 		fpga_lbt_th = (static_lbt_th==0?auto_lbt_th:static_lbt_th);
165 		xpu_api->XPU_REG_LBT_TH_write(fpga_lbt_th);
166 
167 		priv->last_auto_fpga_lbt_th = auto_lbt_th;
168 
169 		if (actual_rx_lo < 2500) {
170 			//priv->slot_time = 20; //20 is default slot time in ERP(OFDM)/11g 2.4G; short one is 9.
171 			//xpu_api->XPU_REG_BAND_CHANNEL_write(BAND_2_4GHZ<<16);
172 			if (priv->band != BAND_2_4GHZ) {
173 				priv->band = BAND_2_4GHZ;
174 				xpu_api->XPU_REG_BAND_CHANNEL_write( (priv->use_short_slot<<24)|(priv->band<<16) );
175 			}
176 			// //xpu_api->XPU_REG_RECV_ACK_COUNT_TOP_write( (((45+2)*10)<<16) | 10 ); // high 16 bits to cover sig valid of ACK packet, low 16 bits is adjustment of fcs valid waiting time.  let's add 2us for those device that is really "slow"!
177 			// xpu_api->XPU_REG_RECV_ACK_COUNT_TOP_write( (((45+2+2)*10)<<16) | 10 );//add 2us for longer fir. BUT corrding to FPGA probing test, we do not need this
178 			// xpu_api->XPU_REG_SEND_ACK_WAIT_TOP_write( 0 );
179 			// tx_intf_api->TX_INTF_REG_CTS_TOSELF_WAIT_SIFS_TOP_write(((10)*10)<<16);
180 		}
181 		else {
182 			//priv->slot_time = 9; //default slot time of OFDM PHY (OFDM by default means 5GHz)
183 			// xpu_api->XPU_REG_BAND_CHANNEL_write(BAND_5_8GHZ<<16);
184 			if (priv->band != BAND_5_8GHZ) {
185 				priv->band = BAND_5_8GHZ;
186 				xpu_api->XPU_REG_BAND_CHANNEL_write( (priv->use_short_slot<<24)|(priv->band<<16) );
187 			}
188 			// //xpu_api->XPU_REG_RECV_ACK_COUNT_TOP_write( (((51+2)*10)<<16) | 10 ); // because 5GHz needs longer SIFS (16 instead of 10), we need 58 instead of 48 for XPU low mac setting.  let's add 2us for those device that is really "slow"!
189 			// xpu_api->XPU_REG_RECV_ACK_COUNT_TOP_write( (((51+2+2)*10)<<16) | 10 );//add 2us for longer fir.  BUT corrding to FPGA probing test, we do not need this
190 			// //xpu_api->XPU_REG_SEND_ACK_WAIT_TOP_write( 60*10 );
191 			// xpu_api->XPU_REG_SEND_ACK_WAIT_TOP_write( 50*10 );// for longer fir we need this delay 1us shorter
192 			// tx_intf_api->TX_INTF_REG_CTS_TOSELF_WAIT_SIFS_TOP_write(((16)*10)<<16);
193 		}
194 		//printk("%s ad9361_rf_set_channel %dM rssi_correction %d\n", sdr_compatible_str,conf->chandef.chan->center_freq,priv->rssi_correction);
195 		// //-- use less
196 		//clk_prepare_enable(priv->ad9361_phy->clks[RX_RFPLL]);
197 		//printk("%s ad9361_rf_set_channel tune to %d read back %llu\n", sdr_compatible_str,conf->chandef.chan->center_freq,2*priv->ad9361_phy->state->current_rx_lo_freq);
198 		//ad9361_set_trx_clock_chain_default(priv->ad9361_phy);
199 		//printk("%s ad9361_rf_set_channel tune to %d read back %llu\n", sdr_compatible_str,conf->chandef.chan->center_freq,2*priv->ad9361_phy->state->current_rx_lo_freq);
200 		printk("%s ad9361_rf_set_channel %dM rssi_correction %d (change flag %d) fpga_lbt_th %d (auto %d static %d)\n", sdr_compatible_str,conf->chandef.chan->center_freq,priv->rssi_correction,change_flag,fpga_lbt_th,auto_lbt_th,static_lbt_th);
201 	}
202 }
203 
204 const struct openwifi_rf_ops ad9361_rf_ops = {
205 	.name		= "ad9361",
206 //	.init		= ad9361_rf_init,
207 //	.stop		= ad9361_rf_stop,
208 	.set_chan	= ad9361_rf_set_channel,
209 //	.calc_rssi	= ad9361_rf_calc_rssi,
210 };
211 
212 u16 reverse16(u16 d) {
213 	union u16_byte2 tmp0, tmp1;
214 	tmp0.a = d;
215 	tmp1.c[0] = tmp0.c[1];
216 	tmp1.c[1] = tmp0.c[0];
217 	return(tmp1.a);
218 }
219 
220 u32 reverse32(u32 d) {
221 	union u32_byte4 tmp0, tmp1;
222 	tmp0.a = d;
223 	tmp1.c[0] = tmp0.c[3];
224 	tmp1.c[1] = tmp0.c[2];
225 	tmp1.c[2] = tmp0.c[1];
226 	tmp1.c[3] = tmp0.c[0];
227 	return(tmp1.a);
228 }
229 
230 static int openwifi_init_tx_ring(struct openwifi_priv *priv, int ring_idx)
231 {
232 	struct openwifi_ring *ring = &(priv->tx_ring[ring_idx]);
233 	int i;
234 
235 	ring->stop_flag = 0;
236 	ring->bd_wr_idx = 0;
237 	ring->bd_rd_idx = 0;
238 	ring->bds = kmalloc(sizeof(struct openwifi_buffer_descriptor)*NUM_TX_BD,GFP_KERNEL);
239 	if (ring->bds==NULL) {
240 		printk("%s openwifi_init_tx_ring: WARNING Cannot allocate TX ring\n",sdr_compatible_str);
241 		return -ENOMEM;
242 	}
243 
244 	for (i = 0; i < NUM_TX_BD; i++) {
245 		ring->bds[i].skb_linked=0; // for tx, skb is from upper layer
246 		//at first right after skb allocated, head, data, tail are the same.
247 		ring->bds[i].dma_mapping_addr = 0; // for tx, mapping is done after skb is received from upper layer in tx routine
248 	}
249 
250 	return 0;
251 }
252 
253 static void openwifi_free_tx_ring(struct openwifi_priv *priv, int ring_idx)
254 {
255 	struct openwifi_ring *ring = &(priv->tx_ring[ring_idx]);
256 	int i;
257 
258 	ring->stop_flag = 0;
259 	ring->bd_wr_idx = 0;
260 	ring->bd_rd_idx = 0;
261 	for (i = 0; i < NUM_TX_BD; i++) {
262 		if (ring->bds[i].skb_linked == 0 && ring->bds[i].dma_mapping_addr == 0)
263 			continue;
264 		if (ring->bds[i].dma_mapping_addr != 0)
265 			dma_unmap_single(priv->tx_chan->device->dev, ring->bds[i].dma_mapping_addr,ring->bds[i].skb_linked->len, DMA_MEM_TO_DEV);
266 //		if (ring->bds[i].skb_linked!=NULL)
267 //			dev_kfree_skb(ring->bds[i].skb_linked); // only use dev_kfree_skb when there is exception
268 		if ( (ring->bds[i].dma_mapping_addr != 0 && ring->bds[i].skb_linked == 0) ||
269 		     (ring->bds[i].dma_mapping_addr == 0 && ring->bds[i].skb_linked != 0))
270 			printk("%s openwifi_free_tx_ring: WARNING ring %d i %d skb_linked %p dma_mapping_addr %08x\n", sdr_compatible_str,
271 			ring_idx, i, (void*)(ring->bds[i].skb_linked), (unsigned int)(ring->bds[i].dma_mapping_addr));
272 
273 		ring->bds[i].skb_linked=0;
274 		ring->bds[i].dma_mapping_addr = 0;
275 	}
276 	if (ring->bds)
277 		kfree(ring->bds);
278 	ring->bds = NULL;
279 }
280 
281 static int openwifi_init_rx_ring(struct openwifi_priv *priv)
282 {
283 	int i;
284 	u8 *pdata_tmp;
285 
286 	priv->rx_cyclic_buf = dma_alloc_coherent(priv->rx_chan->device->dev,RX_BD_BUF_SIZE*NUM_RX_BD,&priv->rx_cyclic_buf_dma_mapping_addr,GFP_KERNEL);
287 	if (!priv->rx_cyclic_buf) {
288 		printk("%s openwifi_init_rx_ring: WARNING dma_alloc_coherent failed!\n", sdr_compatible_str);
289 		dma_free_coherent(priv->rx_chan->device->dev,RX_BD_BUF_SIZE*NUM_RX_BD,priv->rx_cyclic_buf,priv->rx_cyclic_buf_dma_mapping_addr);
290 		return(-1);
291 	}
292 
293 	// Set tsft_low and tsft_high to 0. If they are not zero, it means there is a packet in the buffer by DMA
294 	for (i=0; i<NUM_RX_BD; i++) {
295 		pdata_tmp = priv->rx_cyclic_buf + i*RX_BD_BUF_SIZE; // our header insertion is at the beginning
296 		(*((u32*)(pdata_tmp+0 ))) = 0;
297 		(*((u32*)(pdata_tmp+4 ))) = 0;
298 	}
299 	printk("%s openwifi_init_rx_ring: tsft_low and tsft_high are cleared!\n", sdr_compatible_str);
300 
301 	return 0;
302 }
303 
304 static void openwifi_free_rx_ring(struct openwifi_priv *priv)
305 {
306 	if (priv->rx_cyclic_buf)
307 		dma_free_coherent(priv->rx_chan->device->dev,RX_BD_BUF_SIZE*NUM_RX_BD,priv->rx_cyclic_buf,priv->rx_cyclic_buf_dma_mapping_addr);
308 
309 	priv->rx_cyclic_buf_dma_mapping_addr = 0;
310 	priv->rx_cyclic_buf = 0;
311 }
312 
313 static int rx_dma_setup(struct ieee80211_hw *dev){
314 	struct openwifi_priv *priv = dev->priv;
315 	struct dma_device *rx_dev = priv->rx_chan->device;
316 
317 	priv->rxd = rx_dev->device_prep_dma_cyclic(priv->rx_chan,priv->rx_cyclic_buf_dma_mapping_addr,RX_BD_BUF_SIZE*NUM_RX_BD,RX_BD_BUF_SIZE,DMA_DEV_TO_MEM,DMA_CTRL_ACK|DMA_PREP_INTERRUPT);
318 	if (!(priv->rxd)) {
319 		openwifi_free_rx_ring(priv);
320 		printk("%s rx_dma_setup: WARNING rx_dev->device_prep_dma_cyclic %p\n", sdr_compatible_str, (void*)(priv->rxd));
321 		return(-1);
322 	}
323 	priv->rxd->callback = 0;
324 	priv->rxd->callback_param = 0;
325 
326 	priv->rx_cookie = priv->rxd->tx_submit(priv->rxd);
327 
328 	if (dma_submit_error(priv->rx_cookie)) {
329 		printk("%s rx_dma_setup: WARNING dma_submit_error(rx_cookie) %d\n", sdr_compatible_str, (u32)(priv->rx_cookie));
330 		return(-1);
331 	}
332 
333 	dma_async_issue_pending(priv->rx_chan);
334 	return(0);
335 }
336 
337 static irqreturn_t openwifi_rx_interrupt(int irq, void *dev_id)
338 {
339 	struct ieee80211_hw *dev = dev_id;
340 	struct openwifi_priv *priv = dev->priv;
341 	struct ieee80211_rx_status rx_status = {0};
342 	struct sk_buff *skb;
343 	struct ieee80211_hdr *hdr;
344 	u32 addr1_low32=0, addr2_low32=0, addr3_low32=0, len, rate_idx, tsft_low, tsft_high, loop_count=0, ht_flag, short_gi;//, fc_di;
345 	// u32 dma_driver_buf_idx_mod;
346 	u8 *pdata_tmp, fcs_ok;//, target_buf_idx;//, phy_rx_sn_hw;
347 	s8 signal;
348 	u16 rssi_val, addr1_high16=0, addr2_high16=0, addr3_high16=0, sc=0;
349 	bool content_ok = false, len_overflow = false;
350 	static u8 target_buf_idx_old = 0;
351 
352 	spin_lock(&priv->lock);
353 
354 	while(1) { // loop all rx buffers that have new rx packets
355 		pdata_tmp = priv->rx_cyclic_buf + target_buf_idx_old*RX_BD_BUF_SIZE; // our header insertion is at the beginning
356 		tsft_low =     (*((u32*)(pdata_tmp+0 )));
357 		tsft_high =    (*((u32*)(pdata_tmp+4 )));
358 		if ( tsft_low==0 && tsft_high==0 ) // no packet in the buffer
359 			break;
360 
361 		rssi_val =     (*((u16*)(pdata_tmp+8 )));
362 		len =          (*((u16*)(pdata_tmp+12)));
363 
364 		len_overflow = (len>(RX_BD_BUF_SIZE-16)?true:false);
365 
366 		rate_idx =     (*((u16*)(pdata_tmp+14)));
367 		short_gi =     ((rate_idx&0x20)!=0);
368 		rate_idx =     (rate_idx&0xDF);
369 
370 		fcs_ok = ( len_overflow?0:(*(( u8*)(pdata_tmp+16+len-1))) );
371 
372 		//phy_rx_sn_hw = (fcs_ok&(NUM_RX_BD-1));
373 		// phy_rx_sn_hw = (fcs_ok&0x7f);//0x7f is FPGA limitation
374 		// dma_driver_buf_idx_mod = (state.residue&0x7f);
375 		fcs_ok = ((fcs_ok&0x80)!=0);
376 		ht_flag = ((rate_idx&0x10)!=0);
377 
378 		if ( (len>=14 && (!len_overflow)) && (rate_idx>=8 && rate_idx<=23)) {
379 			// if ( phy_rx_sn_hw!=dma_driver_buf_idx_mod) {
380 			// 	printk("%s openwifi_rx_interrupt: WARNING sn %d next buf_idx %d!\n", sdr_compatible_str,phy_rx_sn_hw,dma_driver_buf_idx_mod);
381 			// }
382 			content_ok = true;
383 		} else {
384 			printk("%s openwifi_rx_interrupt: WARNING content!\n", sdr_compatible_str);
385 			content_ok = false;
386 		}
387 
388 		rssi_val = (rssi_val>>1);
389 		if ( (rssi_val+128)<priv->rssi_correction )
390 			signal = -128;
391 		else
392 			signal = rssi_val - priv->rssi_correction;
393 
394 		// fc_di =        (*((u32*)(pdata_tmp+16)));
395 		// addr1_high16 = (*((u16*)(pdata_tmp+16+4)));
396 		// addr1_low32  = (*((u32*)(pdata_tmp+16+4+2)));
397 		// addr2_high16 = (*((u16*)(pdata_tmp+16+6+4)));
398 		// addr2_low32  = (*((u32*)(pdata_tmp+16+6+4+2)));
399 		// addr3_high16 = (*((u16*)(pdata_tmp+16+12+4)));
400 		// addr3_low32  = (*((u32*)(pdata_tmp+16+12+4+2)));
401 		if ( (priv->drv_rx_reg_val[DRV_RX_REG_IDX_PRINT_CFG]&2) || ( (priv->drv_rx_reg_val[DRV_RX_REG_IDX_PRINT_CFG]&1) && fcs_ok==0 ) ) {
402 			hdr = (struct ieee80211_hdr *)(pdata_tmp+16);
403 			addr1_low32  = *((u32*)(hdr->addr1+2));
404 			addr1_high16 = *((u16*)(hdr->addr1));
405 			if (len>=20) {
406 				addr2_low32  = *((u32*)(hdr->addr2+2));
407 				addr2_high16 = *((u16*)(hdr->addr2));
408 			}
409 			if (len>=26) {
410 				addr3_low32  = *((u32*)(hdr->addr3+2));
411 				addr3_high16 = *((u16*)(hdr->addr3));
412 			}
413 			if (len>=28)
414 				sc = hdr->seq_ctrl;
415 
416 			if ( (addr1_low32!=0xffffffff || addr1_high16!=0xffff) || (priv->drv_rx_reg_val[DRV_RX_REG_IDX_PRINT_CFG]&4) )
417 				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,
418 					len, ht_flag, wifi_rate_table[rate_idx], hdr->frame_control, hdr->duration_id,
419 					reverse16(addr1_high16), reverse32(addr1_low32), reverse16(addr2_high16), reverse32(addr2_low32), reverse16(addr3_high16), reverse32(addr3_low32),
420 					sc, fcs_ok, target_buf_idx_old, signal);
421 		}
422 
423 		// priv->phy_rx_sn_hw_old = phy_rx_sn_hw;
424 		if (content_ok) {
425 			skb = dev_alloc_skb(len);
426 			if (skb) {
427 				skb_put_data(skb,pdata_tmp+16,len);
428 
429 				rx_status.antenna = 0;
430 				// def in ieee80211_rate openwifi_rates 0~11. 0~3 11b(1M~11M), 4~11 11a/g(6M~54M)
431 				rx_status.rate_idx = wifi_rate_table_mapping[rate_idx];
432 				rx_status.signal = signal;
433 				rx_status.freq = dev->conf.chandef.chan->center_freq;
434 				rx_status.band = dev->conf.chandef.chan->band;
435 				rx_status.mactime = ( ( (u64)tsft_low ) | ( ((u64)tsft_high)<<32 ) );
436 				rx_status.flag |= RX_FLAG_MACTIME_START;
437 				if (!fcs_ok)
438 					rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
439 				if (rate_idx <= 15)
440 					rx_status.encoding = RX_ENC_LEGACY;
441 				else
442 					rx_status.encoding = RX_ENC_HT;
443 				rx_status.bw = RATE_INFO_BW_20;
444 				if (short_gi)
445 					rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI;
446 
447 				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); // put rx_status into skb->cb, from now on skb->cb is not dma_dsts any more.
448 				ieee80211_rx_irqsafe(dev, skb); // call mac80211 function
449 			} else
450 				printk("%s openwifi_rx_interrupt: WARNING dev_alloc_skb failed!\n", sdr_compatible_str);
451 		}
452 		(*((u32*)(pdata_tmp+0 ))) = 0;
453 		(*((u32*)(pdata_tmp+4 ))) = 0; // clear the tsft_low and tsft_high to indicate the packet has been processed
454 		loop_count++;
455 		target_buf_idx_old=((target_buf_idx_old+1)&(NUM_RX_BD-1));
456 	}
457 
458 	if ( loop_count!=1 && (priv->drv_rx_reg_val[DRV_RX_REG_IDX_PRINT_CFG]&1) )
459 		printk("%s openwifi_rx_interrupt: WARNING loop_count %d\n", sdr_compatible_str,loop_count);
460 
461 // openwifi_rx_interrupt_out:
462 	spin_unlock(&priv->lock);
463 	return IRQ_HANDLED;
464 }
465 
466 static irqreturn_t openwifi_tx_interrupt(int irq, void *dev_id)
467 {
468 	struct ieee80211_hw *dev = dev_id;
469 	struct openwifi_priv *priv = dev->priv;
470 	struct openwifi_ring *ring;
471 	struct sk_buff *skb;
472 	struct ieee80211_tx_info *info;
473 	u32 reg_val, hw_queue_len, prio, queue_idx, dma_fifo_no_room_flag, num_slot_random, cw, loop_count=0;//, i;
474 	u8 tx_result_report;
475 	// u16 prio_rd_idx_store[64]={0};
476 
477 	spin_lock(&priv->lock);
478 
479 	while(1) { // loop all packets that have been sent by FPGA
480 		reg_val = tx_intf_api->TX_INTF_REG_PKT_INFO_read();
481 		if (reg_val!=0xFFFFFFFF) {
482 			prio = ((0x7FFFF & reg_val)>>(5+NUM_BIT_MAX_PHY_TX_SN+NUM_BIT_MAX_NUM_HW_QUEUE));
483 			cw = ((0xF0000000 & reg_val) >> 28);
484 			num_slot_random = ((0xFF80000 &reg_val)>>(2+5+NUM_BIT_MAX_PHY_TX_SN+NUM_BIT_MAX_NUM_HW_QUEUE));
485 			if(cw > 10) {
486 				cw = 10 ;
487 				num_slot_random += 512 ;
488 			}
489 
490 			ring = &(priv->tx_ring[prio]);
491 			ring->bd_rd_idx = ((reg_val>>5)&MAX_PHY_TX_SN);
492 			skb = ring->bds[ring->bd_rd_idx].skb_linked;
493 
494 			dma_unmap_single(priv->tx_chan->device->dev,ring->bds[ring->bd_rd_idx].dma_mapping_addr,
495 					skb->len, DMA_MEM_TO_DEV);
496 
497 			if ( ring->stop_flag == 1) {
498 				// Wake up Linux queue if FPGA and driver ring have room
499 				queue_idx = ((reg_val>>(5+NUM_BIT_MAX_PHY_TX_SN))&(MAX_NUM_HW_QUEUE-1));
500 				dma_fifo_no_room_flag = tx_intf_api->TX_INTF_REG_S_AXIS_FIFO_NO_ROOM_read();
501 				hw_queue_len = tx_intf_api->TX_INTF_REG_QUEUE_FIFO_DATA_COUNT_read();
502 
503 				// printk("%s openwifi_tx_interrupt: WARNING loop %d prio %d queue %d no room flag %x hw queue len %08x wr %d rd %d call %d\n", sdr_compatible_str,
504 				// loop_count, prio, queue_idx, dma_fifo_no_room_flag, hw_queue_len, ring->bd_wr_idx, ring->bd_rd_idx, priv->call_counter);
505 
506 				if ( ((dma_fifo_no_room_flag>>queue_idx)&1)==0 && (NUM_TX_BD-((hw_queue_len>>(queue_idx*8))&0xFF))>=RING_ROOM_THRESHOLD ) {
507 					// printk("%s openwifi_tx_interrupt: WARNING ieee80211_wake_queue loop %d call %d\n", sdr_compatible_str, loop_count, priv->call_counter);
508 					printk("%s openwifi_tx_interrupt: WARNING ieee80211_wake_queue prio %d queue %d no room flag %x hw queue len %08x wr %d rd %d\n", sdr_compatible_str,
509 					prio, queue_idx, dma_fifo_no_room_flag, hw_queue_len, ring->bd_wr_idx, ring->bd_rd_idx);
510 					ieee80211_wake_queue(dev, prio);
511 					ring->stop_flag = 0;
512 				}
513 			}
514 
515 			if ( (*(u32*)(&(skb->data[4]))) || ((*(u32*)(&(skb->data[12])))&0xFFFF0000) ) {
516 				printk("%s openwifi_tx_interrupt: WARNING %08x %08x %08x %08x\n", sdr_compatible_str, *(u32*)(&(skb->data[12])), *(u32*)(&(skb->data[8])), *(u32*)(&(skb->data[4])), *(u32*)(&(skb->data[0])));
517 				continue;
518 			}
519 
520 			skb_pull(skb, LEN_PHY_HEADER);
521 			//skb_trim(skb, num_byte_pad_skb);
522 			info = IEEE80211_SKB_CB(skb);
523 			ieee80211_tx_info_clear_status(info);
524 
525 			tx_result_report = (reg_val&0x1F);
526 			if ( !(info->flags & IEEE80211_TX_CTL_NO_ACK) ) {
527 				if ((tx_result_report&0x10)==0)
528 					info->flags |= IEEE80211_TX_STAT_ACK;
529 
530 				// printk("%s openwifi_tx_interrupt: rate&try: %d %d %03x; %d %d %03x; %d %d %03x; %d %d %03x\n", sdr_compatible_str,
531 				// 	info->status.rates[0].idx,info->status.rates[0].count,info->status.rates[0].flags,
532 				// 	info->status.rates[1].idx,info->status.rates[1].count,info->status.rates[1].flags,
533 				// 	info->status.rates[2].idx,info->status.rates[2].count,info->status.rates[2].flags,
534 				// 	info->status.rates[3].idx,info->status.rates[3].count,info->status.rates[3].flags);
535 			}
536 
537 			info->status.rates[0].count = (tx_result_report&0xF) + 1; //according to our test, the 1st rate is the most important. we only do retry on the 1st rate
538 			info->status.rates[1].idx = -1;
539 			info->status.rates[2].idx = -1;
540 			info->status.rates[3].idx = -1;//in mac80211.h: #define IEEE80211_TX_MAX_RATES	4
541 
542 			if ( (tx_result_report&0x10) && ((priv->drv_tx_reg_val[DRV_TX_REG_IDX_PRINT_CFG])&1) )
543 				printk("%s openwifi_tx_interrupt: WARNING tx_result %02x prio%d wr%d rd%d\n", sdr_compatible_str, tx_result_report, prio, ring->bd_wr_idx, ring->bd_rd_idx);
544 			if ( ( (!(info->flags & IEEE80211_TX_CTL_NO_ACK))||(priv->drv_tx_reg_val[DRV_TX_REG_IDX_PRINT_CFG]&4) ) && ((priv->drv_tx_reg_val[DRV_TX_REG_IDX_PRINT_CFG])&2) )
545 				printk("%s openwifi_tx_interrupt: tx_result %02x prio%d wr%d rd%d num_rand_slot %d cw %d \n", sdr_compatible_str, tx_result_report, prio, ring->bd_wr_idx, ring->bd_rd_idx, num_slot_random,cw);
546 
547 			ieee80211_tx_status_irqsafe(dev, skb);
548 
549 			loop_count++;
550 
551 			// printk("%s openwifi_tx_interrupt: loop %d prio %d rd %d\n", sdr_compatible_str, loop_count, prio, ring->bd_rd_idx);
552 
553 		} else
554 			break;
555 	}
556 	if ( loop_count!=1 && ((priv->drv_tx_reg_val[DRV_TX_REG_IDX_PRINT_CFG])&1) )
557 		printk("%s openwifi_tx_interrupt: WARNING loop_count %d\n", sdr_compatible_str, loop_count);
558 
559 	spin_unlock(&priv->lock);
560 	return IRQ_HANDLED;
561 }
562 
563 u32 gen_parity(u32 v){
564 	v ^= v >> 1;
565 	v ^= v >> 2;
566 	v = (v & 0x11111111U) * 0x11111111U;
567 	return (v >> 28) & 1;
568 }
569 
570 u8 gen_ht_sig_crc(u64 m)
571 {
572 	u8 i, temp, c[8] = {1, 1, 1, 1, 1, 1, 1, 1}, ht_sig_crc;
573 
574 	for (i = 0; i < 34; i++)
575 	{
576 		temp = c[7] ^ ((m >> i) & 0x01);
577 
578 		c[7] = c[6];
579 		c[6] = c[5];
580 		c[5] = c[4];
581 		c[4] = c[3];
582 		c[3] = c[2];
583 		c[2] = c[1] ^ temp;
584 		c[1] = c[0] ^ temp;
585 		c[0] = temp;
586 	}
587 	ht_sig_crc = ((~c[7] & 0x01) << 0) | ((~c[6] & 0x01) << 1) | ((~c[5] & 0x01) << 2) | ((~c[4] & 0x01) << 3) | ((~c[3] & 0x01) << 4) | ((~c[2] & 0x01) << 5) | ((~c[1] & 0x01) << 6) | ((~c[0] & 0x01) << 7);
588 
589 	return ht_sig_crc;
590 }
591 
592 u32 calc_phy_header(u8 rate_hw_value, bool use_ht_rate, bool use_short_gi, u32 len, u8 *bytes){
593 	//u32 signal_word = 0 ;
594 	u8  SIG_RATE = 0, HT_SIG_RATE;
595 	u8	len_2to0, len_10to3, len_msb,b0,b1,b2, header_parity ;
596 	u32 l_len, ht_len, ht_sig1, ht_sig2;
597 
598 	// printk("rate_hw_value=%u\tuse_ht_rate=%u\tuse_short_gi=%u\tlen=%u\n", rate_hw_value, use_ht_rate, use_short_gi, len);
599 
600 	// HT-mixed mode ht signal
601 
602 	if(use_ht_rate)
603 	{
604 		SIG_RATE = wifi_mcs_table_11b_force_up[4];
605 		HT_SIG_RATE = rate_hw_value;
606 		l_len  = 24 * len / wifi_n_dbps_ht_table[rate_hw_value];
607 		ht_len = len;
608 	}
609 	else
610 	{
611 		// rate_hw_value = (rate_hw_value<=4?0:(rate_hw_value-4));
612 		// SIG_RATE = wifi_mcs_table_phy_tx[rate_hw_value];
613 		SIG_RATE = wifi_mcs_table_11b_force_up[rate_hw_value];
614 		l_len = len;
615 	}
616 
617 	len_2to0 = l_len & 0x07 ;
618 	len_10to3 = (l_len >> 3 ) & 0xFF ;
619 	len_msb = (l_len >> 11) & 0x01 ;
620 
621 	b0=SIG_RATE | (len_2to0 << 5) ;
622 	b1 = len_10to3 ;
623 	header_parity = gen_parity((len_msb << 16)| (b1<<8) | b0) ;
624 	b2 = ( len_msb | (header_parity << 1) ) ;
625 
626 	memset(bytes,0,16);
627 	bytes[0] = b0 ;
628 	bytes[1] = b1 ;
629     bytes[2] = b2;
630 
631 	// HT-mixed mode signal
632 	if(use_ht_rate)
633 	{
634 		ht_sig1 = (HT_SIG_RATE & 0x7F) | ((ht_len << 8) & 0xFFFF00);
635 		ht_sig2 = 0x04 | (use_short_gi << 7);
636 		ht_sig2 = ht_sig2 | (gen_ht_sig_crc(ht_sig1 | ht_sig2 << 24) << 10);
637 
638 	    bytes[3]  = 1;
639 	    bytes[8]  = (ht_sig1 & 0xFF);
640 	    bytes[9]  = (ht_sig1 >> 8)  & 0xFF;
641 	    bytes[10] = (ht_sig1 >> 16) & 0xFF;
642 	    bytes[11] = (ht_sig2 & 0xFF);
643 	    bytes[12] = (ht_sig2 >> 8)  & 0xFF;
644 	    bytes[13] = (ht_sig2 >> 16) & 0xFF;
645 
646 		return(HT_SIG_RATE);
647 	}
648 	else
649 	{
650 		//signal_word = b0+(b1<<8)+(b2<<16) ;
651 		//return signal_word;
652 		return(SIG_RATE);
653 	}
654 }
655 
656 static inline struct gpio_led_data * //please align with the implementation in leds-gpio.c
657 			cdev_to_gpio_led_data(struct led_classdev *led_cdev)
658 {
659 	return container_of(led_cdev, struct gpio_led_data, cdev);
660 }
661 
662 static void openwifi_tx(struct ieee80211_hw *dev,
663 		       struct ieee80211_tx_control *control,
664 		       struct sk_buff *skb)
665 {
666 	struct openwifi_priv *priv = dev->priv;
667 	unsigned long flags;
668 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
669 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
670 	struct openwifi_ring *ring;
671 	dma_addr_t dma_mapping_addr;
672 	unsigned int prio, i;
673 	u32 num_dma_symbol, len_mac_pdu, num_dma_byte, len_phy_packet, num_byte_pad;
674 	u32 rate_signal_value,rate_hw_value,ack_flag;
675 	u32 pkt_need_ack, addr1_low32=0, addr2_low32=0, addr3_low32=0, queue_idx=2, dma_reg, cts_reg;//, openofdm_state_history;
676 	u16 addr1_high16=0, addr2_high16=0, addr3_high16=0, sc=0, cts_duration=0, cts_rate_hw_value = 0, cts_rate_signal_value=0, sifs, ack_duration=0, traffic_pkt_duration;
677 	u8 fc_flag,fc_type,fc_subtype,retry_limit_raw,*dma_buf,retry_limit_hw_value,rc_flags;
678 	bool use_rts_cts, use_cts_protect, use_ht_rate=false, use_short_gi, addr_flag, cts_use_traffic_rate=false, force_use_cts_protect=false;
679 	__le16 frame_control,duration_id;
680 	u32 dma_fifo_no_room_flag, hw_queue_len;
681 	enum dma_status status;
682 	// static bool led_status=0;
683 	// struct gpio_led_data *led_dat = cdev_to_gpio_led_data(priv->led[3]);
684 
685 	// if ( (priv->phy_tx_sn&7) ==0 ) {
686 	// 	openofdm_state_history = openofdm_rx_api->OPENOFDM_RX_REG_STATE_HISTORY_read();
687 	// 	if (openofdm_state_history!=openofdm_state_history_old){
688 	// 		led_status = (~led_status);
689 	// 		openofdm_state_history_old = openofdm_state_history;
690 	// 		gpiod_set_value(led_dat->gpiod, led_status);
691 	// 	}
692 	// }
693 
694 	if (test_mode==1){
695 		printk("%s openwifi_tx: WARNING test_mode==1\n", sdr_compatible_str);
696 		goto openwifi_tx_early_out;
697 	}
698 
699 	if (skb->data_len>0) {// more data are not in linear data area skb->data
700 		printk("%s openwifi_tx: WARNING skb->data_len>0\n", sdr_compatible_str);
701 		goto openwifi_tx_early_out;
702 	}
703 
704 	len_mac_pdu = skb->len;
705 	len_phy_packet = len_mac_pdu + LEN_PHY_HEADER;
706 	num_dma_symbol = (len_phy_packet>>TX_INTF_NUM_BYTE_PER_DMA_SYMBOL_IN_BITS) + ((len_phy_packet&(TX_INTF_NUM_BYTE_PER_DMA_SYMBOL-1))!=0);
707 
708 	// get Linux priority/queue setting info and target mac address
709 	prio = skb_get_queue_mapping(skb);
710 	addr1_low32  = *((u32*)(hdr->addr1+2));
711 	ring = &(priv->tx_ring[prio]);
712 
713 	// -------------- DO your idea here! Map Linux/SW "prio" to hardware "queue_idx" -----------
714 	if (priv->slice_idx == 0xFFFFFFFF) {// use Linux default prio setting, if there isn't any slice config
715 		queue_idx = prio;
716 	} else {// customized prio to queue_idx mapping
717 		//if (fc_type==2 && fc_subtype==0 && (!addr_flag)) { // for unicast data packet only
718 		// check current packet belonging to which slice/hw-queue
719 			for (i=0; i<MAX_NUM_HW_QUEUE; i++) {
720 				if ( priv->dest_mac_addr_queue_map[i] == addr1_low32 ) {
721 					break;
722 				}
723 			}
724 		//}
725 		queue_idx = (i>=MAX_NUM_HW_QUEUE?2:i); // if no address is hit, use FPGA queue 2. because the queue 2 is the longest.
726 	}
727 	// -------------------- end of Map Linux/SW "prio" to hardware "queue_idx" ------------------
728 
729 	// check whether the packet is bigger than DMA buffer size
730 	num_dma_byte = (num_dma_symbol<<TX_INTF_NUM_BYTE_PER_DMA_SYMBOL_IN_BITS);
731 	if (num_dma_byte > TX_BD_BUF_SIZE) {
732 		// dev_err(priv->tx_chan->device->dev, "sdr,sdr openwifi_tx: WARNING num_dma_byte > TX_BD_BUF_SIZE\n");
733 		printk("%s openwifi_tx: WARNING sn %d num_dma_byte > TX_BD_BUF_SIZE\n", sdr_compatible_str, ring->bd_wr_idx);
734 		goto openwifi_tx_early_out;
735 	}
736 	num_byte_pad = num_dma_byte-len_phy_packet;
737 
738 	// get other info from packet header
739 	addr1_high16 = *((u16*)(hdr->addr1));
740 	if (len_mac_pdu>=20) {
741 		addr2_low32  = *((u32*)(hdr->addr2+2));
742 		addr2_high16 = *((u16*)(hdr->addr2));
743 	}
744 	if (len_mac_pdu>=26) {
745 		addr3_low32  = *((u32*)(hdr->addr3+2));
746 		addr3_high16 = *((u16*)(hdr->addr3));
747 	}
748 
749 	duration_id = hdr->duration_id;
750 	frame_control=hdr->frame_control;
751 	ack_flag = (info->flags&IEEE80211_TX_CTL_NO_ACK);
752 	fc_type = ((frame_control)>>2)&3;
753 	fc_subtype = ((frame_control)>>4)&0xf;
754 	fc_flag = ( fc_type==2 || fc_type==0 || (fc_type==1 && (fc_subtype==8 || fc_subtype==9 || fc_subtype==10) ) );
755 	//if it is broadcasting or multicasting addr
756 	addr_flag = ( (addr1_low32==0 && addr1_high16==0) ||
757 	              (addr1_low32==0xFFFFFFFF && addr1_high16==0xFFFF) ||
758 				  (addr1_high16==0x3333) ||
759 				  (addr1_high16==0x0001 && hdr->addr1[2]==0x5E)  );
760 	if ( fc_flag && ( !addr_flag ) && (!ack_flag) ) { // unicast data frame
761 		pkt_need_ack = 1; //FPGA need to wait ACK after this pkt sent
762 	} else {
763 		pkt_need_ack = 0;
764 	}
765 
766 	// get Linux rate (MCS) setting
767 	rate_hw_value = ieee80211_get_tx_rate(dev, info)->hw_value;
768 	//rate_hw_value = 10; //4:6M, 5:9M, 6:12M, 7:18M, 8:24M, 9:36M, 10:48M, 11:54M
769 	if (priv->drv_tx_reg_val[DRV_TX_REG_IDX_RATE]>0 && fc_type==2 && (!addr_flag)) //rate override command
770 		rate_hw_value = priv->drv_tx_reg_val[DRV_TX_REG_IDX_RATE];
771 
772 	retry_limit_raw = info->control.rates[0].count;
773 
774 	rc_flags = info->control.rates[0].flags;
775 	use_rts_cts = ((rc_flags&IEEE80211_TX_RC_USE_RTS_CTS)!=0);
776 	use_cts_protect = ((rc_flags&IEEE80211_TX_RC_USE_CTS_PROTECT)!=0);
777 	use_ht_rate = ((rc_flags&IEEE80211_TX_RC_MCS)!=0);
778 	use_short_gi = ((rc_flags&IEEE80211_TX_RC_SHORT_GI)!=0);
779 
780 	if (use_rts_cts)
781 		printk("%s openwifi_tx: WARNING sn %d use_rts_cts is not supported!\n", sdr_compatible_str, ring->bd_wr_idx);
782 
783 	if (use_cts_protect) {
784 		cts_rate_hw_value = ieee80211_get_rts_cts_rate(dev, info)->hw_value;
785 		cts_duration = le16_to_cpu(ieee80211_ctstoself_duration(dev,info->control.vif,len_mac_pdu,info));
786 	} else if (force_use_cts_protect) { // could override mac80211 setting here.
787 		cts_rate_hw_value = 4; //wifi_mcs_table_11b_force_up[] translate it to 1011(6M)
788 		sifs = (priv->actual_rx_lo<2500?10:16);
789 		if (pkt_need_ack)
790 			ack_duration = 44;//assume the ack we wait use 6Mbps: 4*ceil((22+14*8)/24) + 20(preamble+SIGNAL)
791 		traffic_pkt_duration = 20 + 4*(((22+len_mac_pdu*8)/wifi_n_dbps_table[rate_hw_value])+1);
792 		cts_duration = traffic_pkt_duration + sifs + pkt_need_ack*(sifs+ack_duration);
793 	}
794 
795 // this is 11b stuff
796 //	if (info->flags&IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
797 //		printk("%s openwifi_tx: WARNING IEEE80211_TX_RC_USE_SHORT_PREAMBLE\n", sdr_compatible_str);
798 
799 	if (len_mac_pdu>=28) {
800 		if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
801 			if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
802 				priv->seqno += 0x10;
803 			hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
804 			hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
805 		}
806 		sc = hdr->seq_ctrl;
807 	}
808 
809 	if ( ( (!addr_flag)||(priv->drv_tx_reg_val[DRV_TX_REG_IDX_PRINT_CFG]&4) ) && (priv->drv_tx_reg_val[DRV_TX_REG_IDX_PRINT_CFG]&2) )
810 		printk("%s openwifi_tx: %4dbytes ht%d %3dM FC%04x DI%04x addr1/2/3:%04x%08x/%04x%08x/%04x%08x SC%04x flag%08x retr%d ack%d prio%d q%d wr%d rd%d\n", sdr_compatible_str,
811 			len_mac_pdu, (use_ht_rate == false ? 0 : 1), (use_ht_rate == false ? wifi_rate_all[rate_hw_value] : wifi_rate_all[rate_hw_value + 12]),frame_control,duration_id,
812 			reverse16(addr1_high16), reverse32(addr1_low32), reverse16(addr2_high16), reverse32(addr2_low32), reverse16(addr3_high16), reverse32(addr3_low32),
813 			sc, info->flags, retry_limit_raw, pkt_need_ack, prio, queue_idx,
814 			// use_rts_cts,use_cts_protect|force_use_cts_protect,wifi_rate_all[cts_rate_hw_value],cts_duration,
815 			ring->bd_wr_idx,ring->bd_rd_idx);
816 
817 		// printk("%s openwifi_tx: rate&try: %d %d %03x; %d %d %03x; %d %d %03x; %d %d %03x\n", sdr_compatible_str,
818 		// 	info->status.rates[0].idx,info->status.rates[0].count,info->status.rates[0].flags,
819 		// 	info->status.rates[1].idx,info->status.rates[1].count,info->status.rates[1].flags,
820 		// 	info->status.rates[2].idx,info->status.rates[2].count,info->status.rates[2].flags,
821 		// 	info->status.rates[3].idx,info->status.rates[3].count,info->status.rates[3].flags);
822 
823 	// -----------end of preprocess some info from header and skb----------------
824 
825 	// /* HW will perform RTS-CTS when only RTS flags is set.
826 	//  * HW will perform CTS-to-self when both RTS and CTS flags are set.
827 	//  * RTS rate and RTS duration will be used also for CTS-to-self.
828 	//  */
829 	// if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
830 	// 	tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
831 	// 	rts_duration = ieee80211_rts_duration(dev, priv->vif[0], // assume all vif have the same config
832 	// 					len_mac_pdu, info);
833 	// 	printk("%s openwifi_tx: rc_flags & IEEE80211_TX_RC_USE_RTS_CTS\n", sdr_compatible_str);
834 	// } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
835 	// 	tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
836 	// 	rts_duration = ieee80211_ctstoself_duration(dev, priv->vif[0], // assume all vif have the same config
837 	// 					len_mac_pdu, info);
838 	// 	printk("%s openwifi_tx: rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT\n", sdr_compatible_str);
839 	// }
840 
841 	// when skb does not have enough headroom, skb_push will cause kernel panic. headroom needs to be extended if necessary
842 	if (skb_headroom(skb)<LEN_PHY_HEADER) {
843 		struct sk_buff *skb_new; // in case original skb headroom is not enough to host phy header needed by FPGA IP core
844 		printk("%s openwifi_tx: WARNING sn %d skb_headroom(skb)<LEN_PHY_HEADER\n", sdr_compatible_str, ring->bd_wr_idx);
845 		if ((skb_new = skb_realloc_headroom(skb, LEN_PHY_HEADER)) == NULL) {
846 			printk("%s openwifi_tx: WARNING sn %d skb_realloc_headroom failed!\n", sdr_compatible_str, ring->bd_wr_idx);
847 			goto openwifi_tx_early_out;
848 		}
849 		if (skb->sk != NULL)
850 			skb_set_owner_w(skb_new, skb->sk);
851 		dev_kfree_skb(skb);
852 		skb = skb_new;
853 	}
854 
855 	skb_push( skb, LEN_PHY_HEADER );
856 	rate_signal_value = calc_phy_header(rate_hw_value, use_ht_rate, use_short_gi, len_mac_pdu+LEN_PHY_CRC, skb->data); //fill the phy header
857 
858 	//make sure dma length is integer times of DDC_NUM_BYTE_PER_DMA_SYMBOL
859 	if (skb_tailroom(skb)<num_byte_pad) {
860 		printk("%s openwifi_tx: WARNING sn %d skb_tailroom(skb)<num_byte_pad!\n", sdr_compatible_str, ring->bd_wr_idx);
861 		// skb_pull(skb, LEN_PHY_HEADER);
862 		goto openwifi_tx_early_out;
863 	}
864 	skb_put( skb, num_byte_pad );
865 
866 	retry_limit_hw_value = ( retry_limit_raw==0?0:((retry_limit_raw - 1)&0xF) );
867 	dma_buf = skb->data;
868 
869 	cts_rate_signal_value = wifi_mcs_table_11b_force_up[cts_rate_hw_value];
870 	cts_reg = (((use_cts_protect|force_use_cts_protect)<<31)|(cts_use_traffic_rate<<30)|(cts_duration<<8)|(cts_rate_signal_value<<4)|rate_signal_value);
871 	dma_reg = ( (( ((prio<<(NUM_BIT_MAX_NUM_HW_QUEUE+NUM_BIT_MAX_PHY_TX_SN))|(ring->bd_wr_idx<<NUM_BIT_MAX_NUM_HW_QUEUE)|queue_idx) )<<18)|(retry_limit_hw_value<<14)|(pkt_need_ack<<13)|num_dma_symbol );
872 
873 	/* We must be sure that tx_flags is written last because the HW
874 	 * looks at it to check if the rest of data is valid or not
875 	 */
876 	//wmb();
877 	// entry->flags = cpu_to_le32(tx_flags);
878 	/* We must be sure this has been written before following HW
879 	 * register write, because this write will make the HW attempts
880 	 * to DMA the just-written data
881 	 */
882 	//wmb();
883 
884 	spin_lock_irqsave(&priv->lock, flags); // from now on, we'd better avoid interrupt because ring->stop_flag is shared with interrupt
885 
886 	// -------------check whether FPGA dma fifo and queue (queue_idx) has enough room-------------
887 	dma_fifo_no_room_flag = tx_intf_api->TX_INTF_REG_S_AXIS_FIFO_NO_ROOM_read();
888 	hw_queue_len = tx_intf_api->TX_INTF_REG_QUEUE_FIFO_DATA_COUNT_read();
889 	if ( ((dma_fifo_no_room_flag>>queue_idx)&1) || ((NUM_TX_BD-((hw_queue_len>>(queue_idx*8))&0xFF))<RING_ROOM_THRESHOLD)  || ring->stop_flag==1 ) {
890 		ieee80211_stop_queue(dev, prio); // here we should stop those prio related to the queue idx flag set in TX_INTF_REG_S_AXIS_FIFO_NO_ROOM_read
891 		printk("%s openwifi_tx: WARNING ieee80211_stop_queue prio %d queue %d no room flag %x hw queue len %08x request %d wr %d rd %d\n", sdr_compatible_str,
892 		prio, queue_idx, dma_fifo_no_room_flag, hw_queue_len, num_dma_symbol, ring->bd_wr_idx, ring->bd_rd_idx);
893 		ring->stop_flag = 1;
894 		goto openwifi_tx_early_out_after_lock;
895 	}
896 	// --------end of check whether FPGA fifo (queue_idx) has enough room------------
897 
898 	status = dma_async_is_tx_complete(priv->tx_chan, priv->tx_cookie, NULL, NULL);
899 	if (status!=DMA_COMPLETE) {
900 		printk("%s openwifi_tx: WARNING status!=DMA_COMPLETE\n", sdr_compatible_str);
901 		goto openwifi_tx_early_out_after_lock;
902 	}
903 
904 	if ( (*(u32*)(&(skb->data[4]))) || ((*(u32*)(&(skb->data[12])))&0xFFFF0000) ) {
905 		printk("%s openwifi_tx: WARNING 1 %d %08x %08x %08x %08x\n", sdr_compatible_str, num_byte_pad, *(u32*)(&(skb->data[12])), *(u32*)(&(skb->data[8])), *(u32*)(&(skb->data[4])), *(u32*)(&(skb->data[0])));
906 		goto openwifi_tx_early_out_after_lock;
907 	}
908 
909 //-------------------------fire skb DMA to hardware----------------------------------
910 	dma_mapping_addr = dma_map_single(priv->tx_chan->device->dev, dma_buf,
911 				 num_dma_byte, DMA_MEM_TO_DEV);
912 
913 	if (dma_mapping_error(priv->tx_chan->device->dev,dma_mapping_addr)) {
914 		// dev_err(priv->tx_chan->device->dev, "sdr,sdr openwifi_tx: WARNING TX DMA mapping error\n");
915 		printk("%s openwifi_tx: WARNING sn %d TX DMA mapping error\n", sdr_compatible_str, ring->bd_wr_idx);
916 		goto openwifi_tx_early_out_after_lock;
917 	}
918 
919 	sg_init_table(&(priv->tx_sg), 1); // only need to be initialized once in openwifi_start
920 	sg_dma_address( &(priv->tx_sg) ) = dma_mapping_addr;
921 	sg_dma_len( &(priv->tx_sg) ) = num_dma_byte;
922 
923 	tx_intf_api->TX_INTF_REG_CTS_TOSELF_CONFIG_write(cts_reg);
924 	tx_intf_api->TX_INTF_REG_NUM_DMA_SYMBOL_TO_PL_write(dma_reg);
925 	priv->txd = priv->tx_chan->device->device_prep_slave_sg(priv->tx_chan, &(priv->tx_sg),1,DMA_MEM_TO_DEV, DMA_CTRL_ACK | DMA_PREP_INTERRUPT, NULL);
926 	if (!(priv->txd)) {
927 		printk("%s openwifi_tx: WARNING sn %d device_prep_slave_sg %p\n", sdr_compatible_str, ring->bd_wr_idx, (void*)(priv->txd));
928 		goto openwifi_tx_after_dma_mapping;
929 	}
930 
931 	priv->tx_cookie = priv->txd->tx_submit(priv->txd);
932 
933 	if (dma_submit_error(priv->tx_cookie)) {
934 		printk("%s openwifi_tx: WARNING sn %d dma_submit_error(tx_cookie) %d\n", sdr_compatible_str, ring->bd_wr_idx, (u32)(priv->tx_cookie));
935 		goto openwifi_tx_after_dma_mapping;
936 	}
937 
938 	// seems everything is ok. let's mark this pkt in bd descriptor ring
939 	ring->bds[ring->bd_wr_idx].skb_linked = skb;
940 	ring->bds[ring->bd_wr_idx].dma_mapping_addr = dma_mapping_addr;
941 
942 	ring->bd_wr_idx = ((ring->bd_wr_idx+1)&(NUM_TX_BD-1));
943 
944 	dma_async_issue_pending(priv->tx_chan);
945 
946 	if ( (*(u32*)(&(skb->data[4]))) || ((*(u32*)(&(skb->data[12])))&0xFFFF0000) )
947 		printk("%s openwifi_tx: WARNING 2 %08x %08x %08x %08x\n", sdr_compatible_str, *(u32*)(&(skb->data[12])), *(u32*)(&(skb->data[8])), *(u32*)(&(skb->data[4])), *(u32*)(&(skb->data[0])));
948 
949 	spin_unlock_irqrestore(&priv->lock, flags);
950 
951 	return;
952 
953 openwifi_tx_after_dma_mapping:
954 	dma_unmap_single(priv->tx_chan->device->dev, dma_mapping_addr, num_dma_byte, DMA_MEM_TO_DEV);
955 
956 openwifi_tx_early_out_after_lock:
957 	// skb_pull(skb, LEN_PHY_HEADER);
958 	dev_kfree_skb(skb);
959 	spin_unlock_irqrestore(&priv->lock, flags);
960 	// printk("%s openwifi_tx: WARNING openwifi_tx_after_dma_mapping phy_tx_sn %d queue %d\n", sdr_compatible_str,priv->phy_tx_sn,queue_idx);
961 	return;
962 
963 openwifi_tx_early_out:
964 	dev_kfree_skb(skb);
965 	// printk("%s openwifi_tx: WARNING openwifi_tx_early_out phy_tx_sn %d queue %d\n", sdr_compatible_str,priv->phy_tx_sn,queue_idx);
966 }
967 
968 static int openwifi_start(struct ieee80211_hw *dev)
969 {
970 	struct openwifi_priv *priv = dev->priv;
971 	int ret, i, rssi_half_db_offset, agc_gain_delay;//rssi_half_db_th,
972 	u32 reg;
973 
974 	for (i=0; i<MAX_NUM_VIF; i++) {
975 		priv->vif[i] = NULL;
976 	}
977 
978 	memset(priv->drv_tx_reg_val, 0, sizeof(priv->drv_tx_reg_val));
979 	memset(priv->drv_rx_reg_val, 0, sizeof(priv->drv_rx_reg_val));
980 	memset(priv->drv_xpu_reg_val, 0, sizeof(priv->drv_xpu_reg_val));
981 	priv->drv_xpu_reg_val[DRV_XPU_REG_IDX_GIT_REV] = GIT_REV;
982 
983 	//turn on radio
984 	if (priv->tx_intf_cfg == TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT1) {
985 		ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT, false, true, true); // AD9361_RADIO_ON_TX_ATT 3000 means 3dB, 0 means 0dB
986 		reg = ad9361_get_tx_atten(priv->ad9361_phy, 2);
987 	} else {
988 		ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT, true, false, true); // AD9361_RADIO_ON_TX_ATT 3000 means 3dB, 0 means 0dB
989 		reg = ad9361_get_tx_atten(priv->ad9361_phy, 1);
990 	}
991 	if (reg == AD9361_RADIO_ON_TX_ATT) {
992 		priv->rfkill_off = 1;// 0 off, 1 on
993 		printk("%s openwifi_start: rfkill radio on\n",sdr_compatible_str);
994 	}
995 	else
996 		printk("%s openwifi_start: WARNING rfkill radio on failed. tx att read %d require %d\n",sdr_compatible_str, reg, AD9361_RADIO_ON_TX_ATT);
997 
998 	if (priv->rx_intf_cfg == RX_INTF_BW_20MHZ_AT_0MHZ_ANT0)
999 		priv->ctrl_out.index=0x16;
1000 	else
1001 		priv->ctrl_out.index=0x17;
1002 
1003 	ret = ad9361_ctrl_outs_setup(priv->ad9361_phy, &(priv->ctrl_out));
1004 	if (ret < 0) {
1005 		printk("%s openwifi_start: WARNING ad9361_ctrl_outs_setup %d\n",sdr_compatible_str, ret);
1006 	} else {
1007 		printk("%s openwifi_start: ad9361_ctrl_outs_setup en_mask 0x%02x index 0x%02x\n",sdr_compatible_str, priv->ctrl_out.en_mask, priv->ctrl_out.index);
1008 	}
1009 
1010 	priv->rx_freq_offset_to_lo_MHz = rx_intf_fo_mapping[priv->rx_intf_cfg];
1011 	priv->tx_freq_offset_to_lo_MHz = tx_intf_fo_mapping[priv->tx_intf_cfg];
1012 
1013 	rx_intf_api->hw_init(priv->rx_intf_cfg,8,8);
1014 	tx_intf_api->hw_init(priv->tx_intf_cfg,8,8,priv->fpga_type);
1015 	openofdm_tx_api->hw_init(priv->openofdm_tx_cfg);
1016 	openofdm_rx_api->hw_init(priv->openofdm_rx_cfg);
1017 	xpu_api->hw_init(priv->xpu_cfg);
1018 
1019 	agc_gain_delay = 50; //samples
1020 	rssi_half_db_offset = 150; // to be consistent
1021 	xpu_api->XPU_REG_RSSI_DB_CFG_write(0x80000000|((rssi_half_db_offset<<16)|agc_gain_delay) );
1022 	xpu_api->XPU_REG_RSSI_DB_CFG_write((~0x80000000)&((rssi_half_db_offset<<16)|agc_gain_delay) );
1023 
1024 	openofdm_rx_api->OPENOFDM_RX_REG_POWER_THRES_write(0);
1025 	// rssi_half_db_th = 87<<1; // -62dBm // will setup in runtime in _rf_set_channel
1026 	// xpu_api->XPU_REG_LBT_TH_write(rssi_half_db_th); // set IQ rssi th step .5dB to xxx and enable it
1027 	xpu_api->XPU_REG_FORCE_IDLE_MISC_write(75); //control the duration to force ch_idle after decoding a packet due to imperfection of agc and signals
1028 
1029 	//xpu_api->XPU_REG_SEND_ACK_WAIT_TOP_write( ((40)<<16)|0 );//high 16bit 5GHz; low 16 bit 2.4GHz (Attention, current tx core has around 1.19us starting delay that makes the ack fall behind 10us SIFS in 2.4GHz! Need to improve TX in 2.4GHz!)
1030 	//xpu_api->XPU_REG_SEND_ACK_WAIT_TOP_write( ((51)<<16)|0 );//now our tx send out I/Q immediately
1031 	xpu_api->XPU_REG_SEND_ACK_WAIT_TOP_write( ((51+23)<<16)|(0+23) );//we have more time when we use FIR in AD9361
1032 
1033 	xpu_api->XPU_REG_RECV_ACK_COUNT_TOP0_write( (1<<31) | (((45+2+2)*10 + 15)<<16) | 10 );//2.4GHz. extra 300 clocks are needed when rx core fall into fake ht detection phase (rx mcs 6M)
1034 	xpu_api->XPU_REG_RECV_ACK_COUNT_TOP1_write( (1<<31) | (((51+2+2)*10 + 15)<<16) | 10 );//5GHz. extra 300 clocks are needed when rx core fall into fake ht detection phase (rx mcs 6M)
1035 
1036 	tx_intf_api->TX_INTF_REG_CTS_TOSELF_WAIT_SIFS_TOP_write( ((16*10)<<16)|(10*10) );//high 16bit 5GHz; low 16 bit 2.4GHz. counter speed 10MHz is assumed
1037 
1038 	// //xpu_api->XPU_REG_BB_RF_DELAY_write(51); // fine tuned value at 0.005us. old: dac-->ant port: 0.6us, 57 taps fir at 40MHz: 1.425us; round trip: 2*(0.6+1.425)=4.05us; 4.05*10=41
1039 	// xpu_api->XPU_REG_BB_RF_DELAY_write(47);//add .5us for slightly longer fir -- already in xpu.c
1040 	xpu_api->XPU_REG_MAC_ADDR_write(priv->mac_addr);
1041 
1042 	// setup time schedule of 4 slices
1043 	// slice 0
1044 	xpu_api->XPU_REG_SLICE_COUNT_TOTAL_write(50000-1); // total 50ms
1045 	xpu_api->XPU_REG_SLICE_COUNT_START_write(0); //start 0ms
1046 	xpu_api->XPU_REG_SLICE_COUNT_END_write(50000-1); //end 50ms
1047 
1048 	// slice 1
1049 	xpu_api->XPU_REG_SLICE_COUNT_TOTAL_write((1<<20)|(50000-1)); // total 50ms
1050 	xpu_api->XPU_REG_SLICE_COUNT_START_write((1<<20)|(0)); //start 0ms
1051 	//xpu_api->XPU_REG_SLICE_COUNT_END_write((1<<20)|(20000-1)); //end 20ms
1052 	xpu_api->XPU_REG_SLICE_COUNT_END_write((1<<20)|(50000-1)); //end 20ms
1053 
1054 	// slice 2
1055 	xpu_api->XPU_REG_SLICE_COUNT_TOTAL_write((2<<20)|(50000-1)); // total 50ms
1056 	//xpu_api->XPU_REG_SLICE_COUNT_START_write((2<<20)|(20000)); //start 20ms
1057 	xpu_api->XPU_REG_SLICE_COUNT_START_write((2<<20)|(0)); //start 20ms
1058 	//xpu_api->XPU_REG_SLICE_COUNT_END_write((2<<20)|(40000-1)); //end 20ms
1059 	xpu_api->XPU_REG_SLICE_COUNT_END_write((2<<20)|(50000-1)); //end 20ms
1060 
1061 	// slice 3
1062 	xpu_api->XPU_REG_SLICE_COUNT_TOTAL_write((3<<20)|(50000-1)); // total 50ms
1063 	//xpu_api->XPU_REG_SLICE_COUNT_START_write((3<<20)|(40000)); //start 40ms
1064 	xpu_api->XPU_REG_SLICE_COUNT_START_write((3<<20)|(0)); //start 40ms
1065 	//xpu_api->XPU_REG_SLICE_COUNT_END_write((3<<20)|(50000-1)); //end 20ms
1066 	xpu_api->XPU_REG_SLICE_COUNT_END_write((3<<20)|(50000-1)); //end 20ms
1067 
1068 	// all slice sync rest
1069 	xpu_api->XPU_REG_MULTI_RST_write(1<<7); //bit7 reset the counter for all queues at the same time
1070 	xpu_api->XPU_REG_MULTI_RST_write(0<<7);
1071 
1072 	//xpu_api->XPU_REG_MAC_ADDR_HIGH_write( (*( (u16*)(priv->mac_addr + 4) )) );
1073 	printk("%s openwifi_start: rx_intf_cfg %d openofdm_rx_cfg %d tx_intf_cfg %d openofdm_tx_cfg %d\n",sdr_compatible_str, priv->rx_intf_cfg, priv->openofdm_rx_cfg, priv->tx_intf_cfg, priv->openofdm_tx_cfg);
1074 	printk("%s openwifi_start: rx_freq_offset_to_lo_MHz %d tx_freq_offset_to_lo_MHz %d\n",sdr_compatible_str, priv->rx_freq_offset_to_lo_MHz, priv->tx_freq_offset_to_lo_MHz);
1075 
1076 	tx_intf_api->TX_INTF_REG_INTERRUPT_SEL_write(0x30004); //disable tx interrupt
1077 	rx_intf_api->RX_INTF_REG_INTERRUPT_TEST_write(0x100); // disable rx interrupt by interrupt test mode
1078 	rx_intf_api->RX_INTF_REG_M_AXIS_RST_write(1); // hold M AXIS in reset status
1079 
1080 	if (test_mode==1) {
1081 		printk("%s openwifi_start: test_mode==1\n",sdr_compatible_str);
1082 		goto normal_out;
1083 	}
1084 
1085 	priv->rx_chan = dma_request_slave_channel(&(priv->pdev->dev), "rx_dma_s2mm");
1086 	if (IS_ERR(priv->rx_chan) || priv->rx_chan==NULL) {
1087 		ret = PTR_ERR(priv->rx_chan);
1088 		pr_err("%s openwifi_start: No Rx channel ret %d priv->rx_chan 0x%p\n",sdr_compatible_str, ret, priv->rx_chan);
1089 		goto err_dma;
1090 	}
1091 
1092 	priv->tx_chan = dma_request_slave_channel(&(priv->pdev->dev), "tx_dma_mm2s");
1093 	if (IS_ERR(priv->tx_chan) || priv->tx_chan==NULL) {
1094 		ret = PTR_ERR(priv->tx_chan);
1095 		pr_err("%s openwifi_start: No Tx channel ret %d priv->tx_chan 0x%p\n",sdr_compatible_str, ret, priv->tx_chan);
1096 		goto err_dma;
1097 	}
1098 	printk("%s openwifi_start: DMA channel setup successfully. priv->rx_chan 0x%p priv->tx_chan 0x%p\n",sdr_compatible_str, priv->rx_chan, priv->tx_chan);
1099 
1100 	ret = openwifi_init_rx_ring(priv);
1101 	if (ret) {
1102 		printk("%s openwifi_start: openwifi_init_rx_ring ret %d\n", sdr_compatible_str,ret);
1103 		goto err_free_rings;
1104 	}
1105 
1106 	priv->seqno=0;
1107 	for (i=0; i<MAX_NUM_SW_QUEUE; i++) {
1108 		if ((ret = openwifi_init_tx_ring(priv, i))) {
1109 			printk("%s openwifi_start: openwifi_init_tx_ring %d ret %d\n", sdr_compatible_str, i, ret);
1110 			goto err_free_rings;
1111 		}
1112 	}
1113 
1114 	if ( (ret = rx_dma_setup(dev)) ) {
1115 		printk("%s openwifi_start: rx_dma_setup ret %d\n", sdr_compatible_str,ret);
1116 		goto err_free_rings;
1117 	}
1118 
1119 	priv->irq_rx = irq_of_parse_and_map(priv->pdev->dev.of_node, 1);
1120 	ret = request_irq(priv->irq_rx, openwifi_rx_interrupt,
1121 			IRQF_SHARED, "sdr,rx_pkt_intr", dev);
1122 	if (ret) {
1123 		wiphy_err(dev->wiphy, "openwifi_start:failed to register IRQ handler openwifi_rx_interrupt\n");
1124 		goto err_free_rings;
1125 	} else {
1126 		printk("%s openwifi_start: irq_rx %d\n", sdr_compatible_str, priv->irq_rx);
1127 	}
1128 
1129 	priv->irq_tx = irq_of_parse_and_map(priv->pdev->dev.of_node, 3);
1130 	ret = request_irq(priv->irq_tx, openwifi_tx_interrupt,
1131 			IRQF_SHARED, "sdr,tx_itrpt", dev);
1132 	if (ret) {
1133 		wiphy_err(dev->wiphy, "openwifi_start: failed to register IRQ handler openwifi_tx_interrupt\n");
1134 		goto err_free_rings;
1135 	} else {
1136 		printk("%s openwifi_start: irq_tx %d\n", sdr_compatible_str, priv->irq_tx);
1137 	}
1138 
1139 	rx_intf_api->RX_INTF_REG_INTERRUPT_TEST_write(0x000); // enable rx interrupt get normal fcs valid pass through ddc to ARM
1140 	tx_intf_api->TX_INTF_REG_INTERRUPT_SEL_write(0x4); //enable tx interrupt
1141 	rx_intf_api->RX_INTF_REG_M_AXIS_RST_write(0); // release M AXIS
1142 	xpu_api->XPU_REG_TSF_LOAD_VAL_write(0,0); // reset tsf timer
1143 
1144 	//ieee80211_wake_queue(dev, 0);
1145 
1146 normal_out:
1147 	printk("%s openwifi_start: normal end\n", sdr_compatible_str);
1148 	return 0;
1149 
1150 err_free_rings:
1151 	openwifi_free_rx_ring(priv);
1152 	for (i=0; i<MAX_NUM_SW_QUEUE; i++)
1153 		openwifi_free_tx_ring(priv, i);
1154 
1155 err_dma:
1156 	ret = -1;
1157 	printk("%s openwifi_start: abnormal end ret %d\n", sdr_compatible_str, ret);
1158 	return ret;
1159 }
1160 
1161 static void openwifi_stop(struct ieee80211_hw *dev)
1162 {
1163 	struct openwifi_priv *priv = dev->priv;
1164 	u32 reg, reg1;
1165 	int i;
1166 
1167 	if (test_mode==1){
1168 		pr_info("%s openwifi_stop: test_mode==1\n", sdr_compatible_str);
1169 		goto normal_out;
1170 	}
1171 
1172 	//turn off radio
1173 	#if 1
1174 	ad9361_tx_mute(priv->ad9361_phy, 1);
1175 	reg = ad9361_get_tx_atten(priv->ad9361_phy, 2);
1176 	reg1 = ad9361_get_tx_atten(priv->ad9361_phy, 1);
1177 	if (reg == AD9361_RADIO_OFF_TX_ATT && reg1 == AD9361_RADIO_OFF_TX_ATT ) {
1178 		priv->rfkill_off = 0;// 0 off, 1 on
1179 		printk("%s openwifi_stop: rfkill radio off\n",sdr_compatible_str);
1180 	}
1181 	else
1182 		printk("%s openwifi_stop: WARNING rfkill radio off failed. tx att read %d %d require %d\n",sdr_compatible_str, reg, reg1, AD9361_RADIO_OFF_TX_ATT);
1183 	#endif
1184 
1185 	//ieee80211_stop_queue(dev, 0);
1186 
1187 	tx_intf_api->TX_INTF_REG_INTERRUPT_SEL_write(0x30004); //disable tx interrupt
1188 	rx_intf_api->RX_INTF_REG_INTERRUPT_TEST_write(0x100); // disable fcs_valid by interrupt test mode
1189 	rx_intf_api->RX_INTF_REG_M_AXIS_RST_write(1); // hold M AXIS in reset status
1190 
1191 	for (i=0; i<MAX_NUM_VIF; i++) {
1192 		priv->vif[i] = NULL;
1193 	}
1194 
1195 	openwifi_free_rx_ring(priv);
1196 	for (i=0; i<MAX_NUM_SW_QUEUE; i++)
1197 		openwifi_free_tx_ring(priv, i);
1198 
1199 	pr_info("%s openwifi_stop: dropped channel %s\n", sdr_compatible_str, dma_chan_name(priv->rx_chan));
1200 	dmaengine_terminate_all(priv->rx_chan);
1201 	dma_release_channel(priv->rx_chan);
1202 	pr_info("%s openwifi_stop: dropped channel %s\n", sdr_compatible_str, dma_chan_name(priv->tx_chan));
1203 	dmaengine_terminate_all(priv->tx_chan);
1204 	dma_release_channel(priv->tx_chan);
1205 
1206 	//priv->rf->stop(dev);
1207 
1208 	free_irq(priv->irq_rx, dev);
1209 	free_irq(priv->irq_tx, dev);
1210 
1211 normal_out:
1212 	printk("%s openwifi_stop\n", sdr_compatible_str);
1213 }
1214 
1215 static u64 openwifi_get_tsf(struct ieee80211_hw *dev,
1216 			   struct ieee80211_vif *vif)
1217 {
1218 	u32 tsft_low, tsft_high;
1219 
1220 	tsft_low = xpu_api->XPU_REG_TSF_RUNTIME_VAL_LOW_read();
1221 	tsft_high = xpu_api->XPU_REG_TSF_RUNTIME_VAL_HIGH_read();
1222 	//printk("%s openwifi_get_tsf: %08x%08x\n", sdr_compatible_str,tsft_high,tsft_low);
1223 	return( ( (u64)tsft_low ) | ( ((u64)tsft_high)<<32 ) );
1224 }
1225 
1226 static void openwifi_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf)
1227 {
1228 	u32 tsft_high = ((tsf >> 32)&0xffffffff);
1229 	u32 tsft_low  = (tsf&0xffffffff);
1230 	xpu_api->XPU_REG_TSF_LOAD_VAL_write(tsft_high,tsft_low);
1231 	printk("%s openwifi_set_tsf: %08x%08x\n", sdr_compatible_str,tsft_high,tsft_low);
1232 }
1233 
1234 static void openwifi_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1235 {
1236 	xpu_api->XPU_REG_TSF_LOAD_VAL_write(0,0);
1237 	printk("%s openwifi_reset_tsf\n", sdr_compatible_str);
1238 }
1239 
1240 static int openwifi_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
1241 {
1242 	printk("%s openwifi_set_rts_threshold WARNING value %d\n", sdr_compatible_str,value);
1243 	return(0);
1244 }
1245 
1246 static void openwifi_beacon_work(struct work_struct *work)
1247 {
1248 	struct openwifi_vif *vif_priv =
1249 		container_of(work, struct openwifi_vif, beacon_work.work);
1250 	struct ieee80211_vif *vif =
1251 		container_of((void *)vif_priv, struct ieee80211_vif, drv_priv);
1252 	struct ieee80211_hw *dev = vif_priv->dev;
1253 	struct ieee80211_mgmt *mgmt;
1254 	struct sk_buff *skb;
1255 
1256 	/* don't overflow the tx ring */
1257 	if (ieee80211_queue_stopped(dev, 0))
1258 		goto resched;
1259 
1260 	/* grab a fresh beacon */
1261 	skb = ieee80211_beacon_get(dev, vif);
1262 	if (!skb)
1263 		goto resched;
1264 
1265 	/*
1266 	 * update beacon timestamp w/ TSF value
1267 	 * TODO: make hardware update beacon timestamp
1268 	 */
1269 	mgmt = (struct ieee80211_mgmt *)skb->data;
1270 	mgmt->u.beacon.timestamp = cpu_to_le64(openwifi_get_tsf(dev, vif));
1271 
1272 	/* TODO: use actual beacon queue */
1273 	skb_set_queue_mapping(skb, 0);
1274 	openwifi_tx(dev, NULL, skb);
1275 
1276 resched:
1277 	/*
1278 	 * schedule next beacon
1279 	 * TODO: use hardware support for beacon timing
1280 	 */
1281 	schedule_delayed_work(&vif_priv->beacon_work,
1282 			usecs_to_jiffies(1024 * vif->bss_conf.beacon_int));
1283 }
1284 
1285 static int openwifi_add_interface(struct ieee80211_hw *dev,
1286 				 struct ieee80211_vif *vif)
1287 {
1288 	int i;
1289 	struct openwifi_priv *priv = dev->priv;
1290 	struct openwifi_vif *vif_priv;
1291 
1292 	switch (vif->type) {
1293 	case NL80211_IFTYPE_AP:
1294 	case NL80211_IFTYPE_STATION:
1295 	case NL80211_IFTYPE_ADHOC:
1296 	case NL80211_IFTYPE_MONITOR:
1297 	case NL80211_IFTYPE_MESH_POINT:
1298 		break;
1299 	default:
1300 		return -EOPNOTSUPP;
1301 	}
1302 	// let's support more than 1 interface
1303 	for (i=0; i<MAX_NUM_VIF; i++) {
1304 		if (priv->vif[i] == NULL)
1305 			break;
1306 	}
1307 
1308 	printk("%s openwifi_add_interface start. vif for loop result %d\n", sdr_compatible_str, i);
1309 
1310 	if (i==MAX_NUM_VIF)
1311 		return -EBUSY;
1312 
1313 	priv->vif[i] = vif;
1314 
1315 	/* Initialize driver private area */
1316 	vif_priv = (struct openwifi_vif *)&vif->drv_priv;
1317 	vif_priv->idx = i;
1318 
1319 	vif_priv->dev = dev;
1320 	INIT_DELAYED_WORK(&vif_priv->beacon_work, openwifi_beacon_work);
1321 	vif_priv->enable_beacon = false;
1322 
1323 	printk("%s openwifi_add_interface end with vif idx %d\n", sdr_compatible_str,vif_priv->idx);
1324 
1325 	return 0;
1326 }
1327 
1328 static void openwifi_remove_interface(struct ieee80211_hw *dev,
1329 				     struct ieee80211_vif *vif)
1330 {
1331 	struct openwifi_vif *vif_priv;
1332 	struct openwifi_priv *priv = dev->priv;
1333 
1334 	vif_priv = (struct openwifi_vif *)&vif->drv_priv;
1335 	priv->vif[vif_priv->idx] = NULL;
1336 	printk("%s openwifi_remove_interface vif idx %d\n", sdr_compatible_str, vif_priv->idx);
1337 }
1338 
1339 static int openwifi_config(struct ieee80211_hw *dev, u32 changed)
1340 {
1341 	struct openwifi_priv *priv = dev->priv;
1342 	struct ieee80211_conf *conf = &dev->conf;
1343 
1344 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
1345 		priv->rf->set_chan(dev, conf);
1346 	else
1347 		printk("%s openwifi_config changed flag %08x\n", sdr_compatible_str, changed);
1348 
1349 	return 0;
1350 }
1351 
1352 static void openwifi_bss_info_changed(struct ieee80211_hw *dev,
1353 				     struct ieee80211_vif *vif,
1354 				     struct ieee80211_bss_conf *info,
1355 				     u32 changed)
1356 {
1357 	struct openwifi_priv *priv = dev->priv;
1358 	struct openwifi_vif *vif_priv;
1359 	u32 bssid_low, bssid_high;
1360 
1361 	vif_priv = (struct openwifi_vif *)&vif->drv_priv;
1362 
1363 	//be careful: we don have valid chip, so registers addresses in priv->map->BSSID[0] are not valid! should not print it!
1364 	//printk("%s openwifi_bss_info_changed map bssid %02x%02x%02x%02x%02x%02x\n",sdr_compatible_str,priv->map->BSSID[0],priv->map->BSSID[1],priv->map->BSSID[2],priv->map->BSSID[3],priv->map->BSSID[4],priv->map->BSSID[5]);
1365 	if (changed & BSS_CHANGED_BSSID) {
1366 		printk("%s openwifi_bss_info_changed BSS_CHANGED_BSSID %02x%02x%02x%02x%02x%02x\n",sdr_compatible_str,info->bssid[0],info->bssid[1],info->bssid[2],info->bssid[3],info->bssid[4],info->bssid[5]);
1367 		// write new bssid to our HW, and do not change bssid filter
1368 		//u32 bssid_filter_high = xpu_api->XPU_REG_BSSID_FILTER_HIGH_read();
1369 		bssid_low = ( *( (u32*)(info->bssid) ) );
1370 		bssid_high = ( *( (u16*)(info->bssid+4) ) );
1371 
1372 		//bssid_filter_high = (bssid_filter_high&0x80000000);
1373 		//bssid_high = (bssid_high|bssid_filter_high);
1374 		xpu_api->XPU_REG_BSSID_FILTER_LOW_write(bssid_low);
1375 		xpu_api->XPU_REG_BSSID_FILTER_HIGH_write(bssid_high);
1376 	}
1377 
1378 	if (changed & BSS_CHANGED_BEACON_INT) {
1379 		printk("%s openwifi_bss_info_changed WARNING BSS_CHANGED_BEACON_INT %x\n",sdr_compatible_str,info->beacon_int);
1380 	}
1381 
1382 	if (changed & BSS_CHANGED_TXPOWER)
1383 		printk("%s openwifi_bss_info_changed WARNING BSS_CHANGED_TXPOWER %x\n",sdr_compatible_str,info->txpower);
1384 
1385 	if (changed & BSS_CHANGED_ERP_CTS_PROT)
1386 		printk("%s openwifi_bss_info_changed WARNING BSS_CHANGED_ERP_CTS_PROT %x\n",sdr_compatible_str,info->use_cts_prot);
1387 
1388 	if (changed & BSS_CHANGED_BASIC_RATES)
1389 		printk("%s openwifi_bss_info_changed WARNING BSS_CHANGED_BASIC_RATES %x\n",sdr_compatible_str,info->basic_rates);
1390 
1391 	if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) {
1392 		printk("%s openwifi_bss_info_changed WARNING BSS_CHANGED_ERP_SLOT %d BSS_CHANGED_ERP_PREAMBLE %d short slot %d\n",sdr_compatible_str,
1393 		changed&BSS_CHANGED_ERP_SLOT,changed&BSS_CHANGED_ERP_PREAMBLE,info->use_short_slot);
1394 		if (info->use_short_slot && priv->use_short_slot==false) {
1395 			priv->use_short_slot=true;
1396 			xpu_api->XPU_REG_BAND_CHANNEL_write( (priv->use_short_slot<<24)|(priv->band<<16) );
1397 		} else if ((!info->use_short_slot) && priv->use_short_slot==true) {
1398 			priv->use_short_slot=false;
1399 			xpu_api->XPU_REG_BAND_CHANNEL_write( (priv->use_short_slot<<24)|(priv->band<<16) );
1400 		}
1401 	}
1402 
1403 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
1404 		printk("%s openwifi_bss_info_changed WARNING BSS_CHANGED_BEACON_ENABLED\n",sdr_compatible_str);
1405 		vif_priv->enable_beacon = info->enable_beacon;
1406 	}
1407 
1408 	if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) {
1409 		cancel_delayed_work_sync(&vif_priv->beacon_work);
1410 		if (vif_priv->enable_beacon)
1411 			schedule_work(&vif_priv->beacon_work.work);
1412 		printk("%s openwifi_bss_info_changed WARNING BSS_CHANGED_BEACON_ENABLED %d BSS_CHANGED_BEACON %d\n",sdr_compatible_str,
1413 		changed&BSS_CHANGED_BEACON_ENABLED,changed&BSS_CHANGED_BEACON);
1414 	}
1415 }
1416 // helper function
1417 u32 log2val(u32 val){
1418 	u32 ret_val = 0 ;
1419 	while(val>1){
1420 		val = val >> 1 ;
1421 		ret_val ++ ;
1422 	}
1423 	return ret_val ;
1424 }
1425 
1426 static int openwifi_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
1427 	      const struct ieee80211_tx_queue_params *params)
1428 {
1429 	u32 reg_val, cw_min_exp, cw_max_exp;
1430 
1431 	printk("%s openwifi_conf_tx: [queue %d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d, aifs and txop ignored\n",
1432 		  sdr_compatible_str,queue,params->aifs,params->cw_min,params->cw_max,params->txop);
1433 
1434 	reg_val=xpu_api->XPU_REG_CSMA_CFG_read();
1435 	cw_min_exp = (log2val(params->cw_min + 1) & 0x0F);
1436 	cw_max_exp = (log2val(params->cw_max + 1) & 0x0F);
1437 	switch(queue){
1438 		case 0: reg_val = ( (reg_val & 0xFFFFFF00) | ((cw_min_exp | (cw_max_exp << 4)) << 0) );  break;
1439 		case 1: reg_val = ( (reg_val & 0xFFFF00FF) | ((cw_min_exp | (cw_max_exp << 4)) << 8) );  break;
1440 		case 2: reg_val = ( (reg_val & 0xFF00FFFF) | ((cw_min_exp | (cw_max_exp << 4)) << 16) ); break;
1441 		case 3: reg_val = ( (reg_val & 0x00FFFFFF) | ((cw_min_exp | (cw_max_exp << 4)) << 24) ); break;
1442 		default: printk("%s openwifi_conf_tx: WARNING queue %d does not exist",sdr_compatible_str, queue); return(0);
1443 	}
1444 	xpu_api->XPU_REG_CSMA_CFG_write(reg_val);
1445 	return(0);
1446 }
1447 
1448 static u64 openwifi_prepare_multicast(struct ieee80211_hw *dev,
1449 				     struct netdev_hw_addr_list *mc_list)
1450 {
1451 	printk("%s openwifi_prepare_multicast\n", sdr_compatible_str);
1452 	return netdev_hw_addr_list_count(mc_list);
1453 }
1454 
1455 static void openwifi_configure_filter(struct ieee80211_hw *dev,
1456 				     unsigned int changed_flags,
1457 				     unsigned int *total_flags,
1458 				     u64 multicast)
1459 {
1460 	u32 filter_flag;
1461 
1462 	(*total_flags) &= SDR_SUPPORTED_FILTERS;
1463 	(*total_flags) |= FIF_ALLMULTI; //because we need to pass all multicast (no matter it is for us or not) to upper layer
1464 
1465 	filter_flag = (*total_flags);
1466 
1467 	filter_flag = (filter_flag|UNICAST_FOR_US|BROADCAST_ALL_ONE|BROADCAST_ALL_ZERO);
1468 	//filter_flag = (filter_flag|UNICAST_FOR_US|BROADCAST_ALL_ONE|BROADCAST_ALL_ZERO|MONITOR_ALL); // all pkt will be delivered to arm
1469 
1470 	//if (priv->vif[0]->type == NL80211_IFTYPE_MONITOR)
1471 	if ((filter_flag&0xf0) == 0xf0) //FIF_BCN_PRBRESP_PROMISC/FIF_CONTROL/FIF_OTHER_BSS/FIF_PSPOLL are set means monitor mode
1472 		filter_flag = (filter_flag|MONITOR_ALL);
1473 	else
1474 		filter_flag = (filter_flag&(~MONITOR_ALL));
1475 
1476 	if ( !(filter_flag&FIF_BCN_PRBRESP_PROMISC) )
1477 		filter_flag = (filter_flag|MY_BEACON);
1478 
1479 	filter_flag = (filter_flag|FIF_PSPOLL);
1480 
1481 	xpu_api->XPU_REG_FILTER_FLAG_write(filter_flag|HIGH_PRIORITY_DISCARD_FLAG);
1482 	//xpu_api->XPU_REG_FILTER_FLAG_write(filter_flag); //do not discard any pkt
1483 
1484 	printk("%s openwifi_configure_filter MON %d M_BCN %d BST0 %d BST1 %d UST %d PB_RQ %d PS_PL %d O_BSS %d CTL %d BCN_PRP %d PCP_FL %d FCS_FL %d ALL_MUT %d\n", sdr_compatible_str,
1485 	(filter_flag>>13)&1,(filter_flag>>12)&1,(filter_flag>>11)&1,(filter_flag>>10)&1,(filter_flag>>9)&1,(filter_flag>>8)&1,(filter_flag>>7)&1,(filter_flag>>6)&1,(filter_flag>>5)&1,(filter_flag>>4)&1,(filter_flag>>3)&1,(filter_flag>>2)&1,(filter_flag>>1)&1);
1486 }
1487 
1488 static int openwifi_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len)
1489 {
1490 	struct openwifi_priv *priv = hw->priv;
1491 	struct nlattr *tb[OPENWIFI_ATTR_MAX + 1];
1492 	struct sk_buff *skb;
1493 	int err;
1494 	u32 tmp=-1, reg_cat, reg_addr, reg_val, reg_addr_idx, tsft_high, tsft_low;
1495 
1496 	err = nla_parse(tb, OPENWIFI_ATTR_MAX, data, len, openwifi_testmode_policy, NULL);
1497 	if (err)
1498 		return err;
1499 
1500 	if (!tb[OPENWIFI_ATTR_CMD])
1501 		return -EINVAL;
1502 
1503 	switch (nla_get_u32(tb[OPENWIFI_ATTR_CMD])) {
1504 	case OPENWIFI_CMD_SET_GAP:
1505 		if (!tb[OPENWIFI_ATTR_GAP])
1506 			return -EINVAL;
1507 		tmp = nla_get_u32(tb[OPENWIFI_ATTR_GAP]);
1508 		printk("%s openwifi radio inter frame gap set to %d usec\n", sdr_compatible_str, tmp);
1509 		xpu_api->XPU_REG_CSMA_CFG_write(tmp); // unit us
1510 		return 0;
1511 	case OPENWIFI_CMD_GET_GAP:
1512 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1513 		if (!skb)
1514 			return -ENOMEM;
1515 		tmp = xpu_api->XPU_REG_CSMA_CFG_read();
1516 		if (nla_put_u32(skb, OPENWIFI_ATTR_GAP, tmp))
1517 			goto nla_put_failure;
1518 		return cfg80211_testmode_reply(skb);
1519 	case OPENWIFI_CMD_SET_SLICE_IDX:
1520 		if (!tb[OPENWIFI_ATTR_SLICE_IDX])
1521 			return -EINVAL;
1522 		tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_IDX]);
1523 		printk("%s set openwifi slice_idx in hex: %08x\n", sdr_compatible_str, tmp);
1524 		if (tmp == MAX_NUM_HW_QUEUE) {
1525 			printk("%s set openwifi slice_idx reset all queue counter.\n", sdr_compatible_str);
1526 			xpu_api->XPU_REG_MULTI_RST_write(1<<7); //bit7 reset the counter for all queues at the same time
1527 			xpu_api->XPU_REG_MULTI_RST_write(0<<7);
1528 		} else {
1529 			priv->slice_idx = tmp;
1530 		}
1531 		return 0;
1532 	case OPENWIFI_CMD_GET_SLICE_IDX:
1533 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1534 		if (!skb)
1535 			return -ENOMEM;
1536 		tmp = priv->slice_idx;
1537 		if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_IDX, tmp))
1538 			goto nla_put_failure;
1539 		printk("%s get openwifi slice_idx in hex: %08x\n", sdr_compatible_str, tmp);
1540 		return cfg80211_testmode_reply(skb);
1541 	case OPENWIFI_CMD_SET_ADDR:
1542 		if (!tb[OPENWIFI_ATTR_ADDR])
1543 			return -EINVAL;
1544 		tmp = nla_get_u32(tb[OPENWIFI_ATTR_ADDR]);
1545 		if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
1546 			printk("%s set openwifi slice_target_mac_addr(low32) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx);
1547 		} else {
1548 			printk("%s set openwifi slice_target_mac_addr(low32) in hex: %08x to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
1549 			priv->dest_mac_addr_queue_map[priv->slice_idx] = reverse32(tmp);
1550 		}
1551 		return 0;
1552 	case OPENWIFI_CMD_GET_ADDR:
1553 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1554 		if (!skb)
1555 			return -ENOMEM;
1556 		if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
1557 			tmp = -1;
1558 		} else {
1559 			tmp = reverse32(priv->dest_mac_addr_queue_map[priv->slice_idx]);
1560 		}
1561 		if (nla_put_u32(skb, OPENWIFI_ATTR_ADDR, tmp))
1562 			goto nla_put_failure;
1563 		printk("%s get openwifi slice_target_mac_addr(low32) in hex: %08x of slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
1564 		return cfg80211_testmode_reply(skb);
1565 
1566 	case OPENWIFI_CMD_SET_SLICE_TOTAL:
1567 		if (!tb[OPENWIFI_ATTR_SLICE_TOTAL])
1568 			return -EINVAL;
1569 		tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_TOTAL]);
1570 		if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
1571 			printk("%s set SLICE_TOTAL(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx);
1572 		} else {
1573 			printk("%s set SLICE_TOTAL(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
1574 			xpu_api->XPU_REG_SLICE_COUNT_TOTAL_write((priv->slice_idx<<20)|tmp);
1575 		}
1576 		return 0;
1577 	case OPENWIFI_CMD_GET_SLICE_TOTAL:
1578 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1579 		if (!skb)
1580 			return -ENOMEM;
1581 		tmp = (xpu_api->XPU_REG_SLICE_COUNT_TOTAL_read());
1582 		printk("%s get SLICE_TOTAL(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20);
1583 		if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_TOTAL, tmp))
1584 			goto nla_put_failure;
1585 		return cfg80211_testmode_reply(skb);
1586 
1587 	case OPENWIFI_CMD_SET_SLICE_START:
1588 		if (!tb[OPENWIFI_ATTR_SLICE_START])
1589 			return -EINVAL;
1590 		tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_START]);
1591 		if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
1592 			printk("%s set SLICE_START(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx);
1593 		} else {
1594 			printk("%s set SLICE_START(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
1595 			xpu_api->XPU_REG_SLICE_COUNT_START_write((priv->slice_idx<<20)|tmp);
1596 		}
1597 		return 0;
1598 	case OPENWIFI_CMD_GET_SLICE_START:
1599 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1600 		if (!skb)
1601 			return -ENOMEM;
1602 		tmp = (xpu_api->XPU_REG_SLICE_COUNT_START_read());
1603 		printk("%s get SLICE_START(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20);
1604 		if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_START, tmp))
1605 			goto nla_put_failure;
1606 		return cfg80211_testmode_reply(skb);
1607 
1608 	case OPENWIFI_CMD_SET_SLICE_END:
1609 		if (!tb[OPENWIFI_ATTR_SLICE_END])
1610 			return -EINVAL;
1611 		tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_END]);
1612 		if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
1613 			printk("%s set SLICE_END(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx);
1614 		} else {
1615 			printk("%s set SLICE_END(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
1616 			xpu_api->XPU_REG_SLICE_COUNT_END_write((priv->slice_idx<<20)|tmp);
1617 		}
1618 		return 0;
1619 	case OPENWIFI_CMD_GET_SLICE_END:
1620 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1621 		if (!skb)
1622 			return -ENOMEM;
1623 		tmp = (xpu_api->XPU_REG_SLICE_COUNT_END_read());
1624 		printk("%s get SLICE_END(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20);
1625 		if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_END, tmp))
1626 			goto nla_put_failure;
1627 		return cfg80211_testmode_reply(skb);
1628 
1629 	// case OPENWIFI_CMD_SET_SLICE_TOTAL1:
1630 	// 	if (!tb[OPENWIFI_ATTR_SLICE_TOTAL1])
1631 	// 		return -EINVAL;
1632 	// 	tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_TOTAL1]);
1633 	// 	printk("%s set SLICE_TOTAL1(duration) to %d usec\n", sdr_compatible_str, tmp);
1634 	// 	// xpu_api->XPU_REG_SLICE_COUNT_TOTAL1_write(tmp);
1635 	// 	return 0;
1636 	// case OPENWIFI_CMD_GET_SLICE_TOTAL1:
1637 	// 	skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1638 	// 	if (!skb)
1639 	// 		return -ENOMEM;
1640 	// 	// tmp = (xpu_api->XPU_REG_SLICE_COUNT_TOTAL1_read());
1641 	// 	if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_TOTAL1, tmp))
1642 	// 		goto nla_put_failure;
1643 	// 	return cfg80211_testmode_reply(skb);
1644 
1645 	// case OPENWIFI_CMD_SET_SLICE_START1:
1646 	// 	if (!tb[OPENWIFI_ATTR_SLICE_START1])
1647 	// 		return -EINVAL;
1648 	// 	tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_START1]);
1649 	// 	printk("%s set SLICE_START1(duration) to %d usec\n", sdr_compatible_str, tmp);
1650 	// 	// xpu_api->XPU_REG_SLICE_COUNT_START1_write(tmp);
1651 	// 	return 0;
1652 	// case OPENWIFI_CMD_GET_SLICE_START1:
1653 	// 	skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1654 	// 	if (!skb)
1655 	// 		return -ENOMEM;
1656 	// 	// tmp = (xpu_api->XPU_REG_SLICE_COUNT_START1_read());
1657 	// 	if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_START1, tmp))
1658 	// 		goto nla_put_failure;
1659 	// 	return cfg80211_testmode_reply(skb);
1660 
1661 	// case OPENWIFI_CMD_SET_SLICE_END1:
1662 	// 	if (!tb[OPENWIFI_ATTR_SLICE_END1])
1663 	// 		return -EINVAL;
1664 	// 	tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_END1]);
1665 	// 	printk("%s set SLICE_END1(duration) to %d usec\n", sdr_compatible_str, tmp);
1666 	// 	// xpu_api->XPU_REG_SLICE_COUNT_END1_write(tmp);
1667 	// 	return 0;
1668 	// case OPENWIFI_CMD_GET_SLICE_END1:
1669 	// 	skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1670 	// 	if (!skb)
1671 	// 		return -ENOMEM;
1672 	// 	// tmp = (xpu_api->XPU_REG_SLICE_COUNT_END1_read());
1673 	// 	if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_END1, tmp))
1674 	// 		goto nla_put_failure;
1675 	// 	return cfg80211_testmode_reply(skb);
1676 
1677 	case OPENWIFI_CMD_SET_RSSI_TH:
1678 		if (!tb[OPENWIFI_ATTR_RSSI_TH])
1679 			return -EINVAL;
1680 		tmp = nla_get_u32(tb[OPENWIFI_ATTR_RSSI_TH]);
1681 		// printk("%s set RSSI_TH to %d\n", sdr_compatible_str, tmp);
1682 		// xpu_api->XPU_REG_LBT_TH_write(tmp);
1683 		// return 0;
1684 		printk("%s WARNING Please use command: sdrctl dev sdr0 set reg drv_xpu 0 reg_value! (1~2047, 0 means AUTO)!\n", sdr_compatible_str);
1685 		return -EOPNOTSUPP;
1686 	case OPENWIFI_CMD_GET_RSSI_TH:
1687 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1688 		if (!skb)
1689 			return -ENOMEM;
1690 		tmp = xpu_api->XPU_REG_LBT_TH_read();
1691 		if (nla_put_u32(skb, OPENWIFI_ATTR_RSSI_TH, tmp))
1692 			goto nla_put_failure;
1693 		return cfg80211_testmode_reply(skb);
1694 
1695 	case OPENWIFI_CMD_SET_TSF:
1696 		printk("openwifi_set_tsf_1");
1697 		if ( (!tb[OPENWIFI_ATTR_HIGH_TSF]) || (!tb[OPENWIFI_ATTR_LOW_TSF]) )
1698 				return -EINVAL;
1699 		printk("openwifi_set_tsf_2");
1700 		tsft_high = nla_get_u32(tb[OPENWIFI_ATTR_HIGH_TSF]);
1701 		tsft_low  = nla_get_u32(tb[OPENWIFI_ATTR_LOW_TSF]);
1702 		xpu_api->XPU_REG_TSF_LOAD_VAL_write(tsft_high,tsft_low);
1703 		printk("%s openwifi_set_tsf: %08x%08x\n", sdr_compatible_str,tsft_high,tsft_low);
1704 		return 0;
1705 
1706 	case REG_CMD_SET:
1707 		if ( (!tb[REG_ATTR_ADDR]) || (!tb[REG_ATTR_VAL]) )
1708 			return -EINVAL;
1709 		reg_addr = nla_get_u32(tb[REG_ATTR_ADDR]);
1710 		reg_val  = nla_get_u32(tb[REG_ATTR_VAL]);
1711 		reg_cat = ((reg_addr>>16)&0xFFFF);
1712 		reg_addr = (reg_addr&0xFFFF);
1713 		reg_addr_idx = (reg_addr>>2);
1714 		printk("%s recv set cmd reg cat %d addr %08x val %08x idx %d\n", sdr_compatible_str, reg_cat, reg_addr, reg_val, reg_addr_idx);
1715 		if (reg_cat==1)
1716 			printk("%s WARNING reg cat 1 (rf) is not supported yet!\n", sdr_compatible_str);
1717 		else if (reg_cat==2)
1718 			rx_intf_api->reg_write(reg_addr,reg_val);
1719 		else if (reg_cat==3)
1720 			tx_intf_api->reg_write(reg_addr,reg_val);
1721 		else if (reg_cat==4)
1722 			openofdm_rx_api->reg_write(reg_addr,reg_val);
1723 		else if (reg_cat==5)
1724 			openofdm_tx_api->reg_write(reg_addr,reg_val);
1725 		else if (reg_cat==6)
1726 			xpu_api->reg_write(reg_addr,reg_val);
1727 		else if (reg_cat==7) {
1728 			if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
1729 				priv->drv_rx_reg_val[reg_addr_idx]=reg_val;
1730 				if (reg_addr_idx==DRV_RX_REG_IDX_FREQ_BW_CFG) {
1731 					if (reg_val==0)
1732 						priv->rx_intf_cfg = RX_INTF_BW_20MHZ_AT_0MHZ_ANT0;
1733 					else
1734 						priv->rx_intf_cfg = RX_INTF_BW_20MHZ_AT_0MHZ_ANT1;
1735 
1736 					priv->rx_freq_offset_to_lo_MHz = rx_intf_fo_mapping[priv->rx_intf_cfg];
1737 					//priv->tx_freq_offset_to_lo_MHz = tx_intf_fo_mapping[priv->tx_intf_cfg];
1738 				}
1739 			} else
1740 				printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
1741 		}
1742 		else if (reg_cat==8) {
1743 			if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
1744 				priv->drv_tx_reg_val[reg_addr_idx]=reg_val;
1745 				if (reg_addr_idx==DRV_TX_REG_IDX_FREQ_BW_CFG) {
1746 					if (reg_val==0) {
1747 						priv->tx_intf_cfg = TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT0;
1748 						ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT, true, false, true);
1749 					} else {
1750 						priv->tx_intf_cfg = TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT1;
1751 						ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT, false, true, true);
1752 					}
1753 
1754 					//priv->rx_freq_offset_to_lo_MHz = rx_intf_fo_mapping[priv->rx_intf_cfg];
1755 					priv->tx_freq_offset_to_lo_MHz = tx_intf_fo_mapping[priv->tx_intf_cfg];
1756 				}
1757 			} else
1758 				printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
1759 		}
1760 		else if (reg_cat==9) {
1761 			if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
1762 				priv->drv_xpu_reg_val[reg_addr_idx]=reg_val;
1763 				if (reg_addr_idx==DRV_XPU_REG_IDX_LBT_TH) {
1764 					if (reg_val) {
1765 						xpu_api->XPU_REG_LBT_TH_write(reg_val);
1766 						printk("%s override FPGA LBT threshold to %d. The last_auto_fpga_lbt_th %d\n", sdr_compatible_str, reg_val, priv->last_auto_fpga_lbt_th);
1767 					} else {
1768 						xpu_api->XPU_REG_LBT_TH_write(priv->last_auto_fpga_lbt_th);
1769 						printk("%s Restore last_auto_fpga_lbt_th %d to FPGA. ad9361_rf_set_channel will take control\n", sdr_compatible_str, priv->last_auto_fpga_lbt_th);
1770 					}
1771 				}
1772 			} else
1773 				printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
1774 		}
1775 		else
1776 			printk("%s WARNING reg cat %d is not supported yet!\n", sdr_compatible_str, reg_cat);
1777 
1778 		return 0;
1779 	case REG_CMD_GET:
1780 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
1781 		if (!skb)
1782 			return -ENOMEM;
1783 		reg_addr = nla_get_u32(tb[REG_ATTR_ADDR]);
1784 		reg_cat = ((reg_addr>>16)&0xFFFF);
1785 		reg_addr = (reg_addr&0xFFFF);
1786 		reg_addr_idx = (reg_addr>>2);
1787 		printk("%s recv get cmd reg cat %d addr %08x idx %d\n", sdr_compatible_str, reg_cat, reg_addr, reg_addr_idx);
1788 		if (reg_cat==1) {
1789 			printk("%s WARNING reg cat 1 (rf) is not supported yet!\n", sdr_compatible_str);
1790 			tmp = 0xFFFFFFFF;
1791 		}
1792 		else if (reg_cat==2)
1793 			tmp = rx_intf_api->reg_read(reg_addr);
1794 		else if (reg_cat==3)
1795 			tmp = tx_intf_api->reg_read(reg_addr);
1796 		else if (reg_cat==4)
1797 			tmp = openofdm_rx_api->reg_read(reg_addr);
1798 		else if (reg_cat==5)
1799 			tmp = openofdm_tx_api->reg_read(reg_addr);
1800 		else if (reg_cat==6)
1801 			tmp = xpu_api->reg_read(reg_addr);
1802 		else if (reg_cat==7) {
1803 			if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
1804 				if (reg_addr_idx==DRV_RX_REG_IDX_FREQ_BW_CFG) {
1805 					priv->rx_freq_offset_to_lo_MHz = rx_intf_fo_mapping[priv->rx_intf_cfg];
1806 					//priv->tx_freq_offset_to_lo_MHz = tx_intf_fo_mapping[priv->tx_intf_cfg];
1807 
1808 					if (priv->rx_intf_cfg == RX_INTF_BW_20MHZ_AT_0MHZ_ANT0)
1809 						priv->drv_rx_reg_val[reg_addr_idx]=0;
1810 					else if	(priv->rx_intf_cfg == RX_INTF_BW_20MHZ_AT_0MHZ_ANT1)
1811 						priv->drv_rx_reg_val[reg_addr_idx]=1;
1812 				}
1813 				tmp = priv->drv_rx_reg_val[reg_addr_idx];
1814 			} else
1815 				printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
1816 		}
1817 		else if (reg_cat==8) {
1818 			if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
1819 				if (reg_addr_idx==DRV_TX_REG_IDX_FREQ_BW_CFG) {
1820 					//priv->rx_freq_offset_to_lo_MHz = rx_intf_fo_mapping[priv->rx_intf_cfg];
1821 					priv->tx_freq_offset_to_lo_MHz = tx_intf_fo_mapping[priv->tx_intf_cfg];
1822 					if (priv->tx_intf_cfg == TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT0)
1823 						priv->drv_tx_reg_val[reg_addr_idx]=0;
1824 					else if	(priv->tx_intf_cfg == TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT1)
1825 						priv->drv_tx_reg_val[reg_addr_idx]=1;
1826 				}
1827 				tmp = priv->drv_tx_reg_val[reg_addr_idx];
1828 			} else
1829 				printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
1830 		}
1831 		else if (reg_cat==9) {
1832 			if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG)
1833 				tmp = priv->drv_xpu_reg_val[reg_addr_idx];
1834 			else
1835 				printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
1836 		}
1837 		else
1838 			printk("%s WARNING reg cat %d is not supported yet!\n", sdr_compatible_str, reg_cat);
1839 
1840 		if (nla_put_u32(skb, REG_ATTR_VAL, tmp))
1841 			goto nla_put_failure;
1842 		return cfg80211_testmode_reply(skb);
1843 
1844 	default:
1845 		return -EOPNOTSUPP;
1846 	}
1847 
1848  nla_put_failure:
1849 	dev_kfree_skb(skb);
1850 	return -ENOBUFS;
1851 }
1852 
1853 static const struct ieee80211_ops openwifi_ops = {
1854 	.tx			       = openwifi_tx,
1855 	.start			   = openwifi_start,
1856 	.stop			   = openwifi_stop,
1857 	.add_interface	   = openwifi_add_interface,
1858 	.remove_interface  = openwifi_remove_interface,
1859 	.config			   = openwifi_config,
1860 	.bss_info_changed  = openwifi_bss_info_changed,
1861 	.conf_tx		   = openwifi_conf_tx,
1862 	.prepare_multicast = openwifi_prepare_multicast,
1863 	.configure_filter  = openwifi_configure_filter,
1864 	.rfkill_poll	   = openwifi_rfkill_poll,
1865 	.get_tsf		   = openwifi_get_tsf,
1866 	.set_tsf		   = openwifi_set_tsf,
1867 	.reset_tsf		   = openwifi_reset_tsf,
1868 	.set_rts_threshold = openwifi_set_rts_threshold,
1869 	.testmode_cmd	   = openwifi_testmode_cmd,
1870 };
1871 
1872 static const struct of_device_id openwifi_dev_of_ids[] = {
1873 	{ .compatible = "sdr,sdr", },
1874 	{}
1875 };
1876 MODULE_DEVICE_TABLE(of, openwifi_dev_of_ids);
1877 
1878 static int custom_match_spi_dev(struct device *dev, void *data)
1879 {
1880     const char *name = data;
1881 
1882 	bool ret = sysfs_streq(name, dev->of_node->name);
1883 	printk("%s custom_match_spi_dev %s %s %d\n", sdr_compatible_str,name, dev->of_node->name, ret);
1884 	return ret;
1885 }
1886 
1887 static int custom_match_platform_dev(struct device *dev, void *data)
1888 {
1889 	struct platform_device *plat_dev = to_platform_device(dev);
1890 	const char *name = data;
1891 	char *name_in_sys_bus_platform_devices = strstr(plat_dev->name, name);
1892 	bool match_flag = (name_in_sys_bus_platform_devices != NULL);
1893 
1894 	if (match_flag) {
1895 		printk("%s custom_match_platform_dev %s\n", sdr_compatible_str,plat_dev->name);
1896 	}
1897 	return(match_flag);
1898 }
1899 
1900 static int openwifi_dev_probe(struct platform_device *pdev)
1901 {
1902 	struct ieee80211_hw *dev;
1903 	struct openwifi_priv *priv;
1904 	int err=1, rand_val;
1905 	const char *chip_name, *fpga_model;
1906 	u32 reg;//, reg1;
1907 
1908 	struct device_node *np = pdev->dev.of_node;
1909 
1910 	struct device *tmp_dev;
1911 	struct platform_device *tmp_pdev;
1912 	struct iio_dev *tmp_indio_dev;
1913 	// struct gpio_leds_priv *tmp_led_priv;
1914 
1915 	printk("\n");
1916 
1917 	if (np) {
1918 		const struct of_device_id *match;
1919 
1920 		match = of_match_node(openwifi_dev_of_ids, np);
1921 		if (match) {
1922 			printk("%s openwifi_dev_probe: match!\n", sdr_compatible_str);
1923 			err = 0;
1924 		}
1925 	}
1926 
1927 	if (err)
1928 		return err;
1929 
1930 	dev = ieee80211_alloc_hw(sizeof(*priv), &openwifi_ops);
1931 	if (!dev) {
1932 		printk(KERN_ERR "%s openwifi_dev_probe: ieee80211 alloc failed\n",sdr_compatible_str);
1933 		err = -ENOMEM;
1934 		goto err_free_dev;
1935 	}
1936 
1937 	priv = dev->priv;
1938 	priv->pdev = pdev;
1939 
1940 	err = of_property_read_string(of_find_node_by_path("/"), "model", &fpga_model);
1941 	if(err < 0) {
1942 		printk("%s openwifi_dev_probe: WARNING unknown openwifi FPGA model %d\n",sdr_compatible_str, err);
1943 		priv->fpga_type = SMALL_FPGA;
1944 	} else {
1945 		// LARGE FPGAs (i.e. ZCU102, Z7035, ZC706)
1946 		if(strstr(fpga_model, "ZCU102") != NULL || strstr(fpga_model, "Z7035") != NULL || strstr(fpga_model, "ZC706") != NULL)
1947 			priv->fpga_type = LARGE_FPGA;
1948 		// SMALL FPGA: (i.e. ZED, ZC702, Z7020)
1949 		else if(strstr(fpga_model, "ZED") != NULL || strstr(fpga_model, "ZC702") != NULL || strstr(fpga_model, "Z7020") != NULL)
1950 			priv->fpga_type = SMALL_FPGA;
1951 	}
1952 
1953 	// //-------------find ad9361-phy driver for lo/channel control---------------
1954 	priv->actual_rx_lo = 0;
1955 	tmp_dev = bus_find_device( &spi_bus_type, NULL, "ad9361-phy", custom_match_spi_dev );
1956 	if (tmp_dev == NULL) {
1957 		printk(KERN_ERR "%s find_dev ad9361-phy failed\n",sdr_compatible_str);
1958 		err = -ENOMEM;
1959 		goto err_free_dev;
1960 	}
1961 	printk("%s bus_find_device ad9361-phy: %s. driver_data pointer %p\n", sdr_compatible_str, ((struct spi_device*)tmp_dev)->modalias, (void*)(((struct spi_device*)tmp_dev)->dev.driver_data));
1962 	if (((struct spi_device*)tmp_dev)->dev.driver_data == NULL) {
1963 		printk(KERN_ERR "%s find_dev ad9361-phy failed. dev.driver_data == NULL\n",sdr_compatible_str);
1964 		err = -ENOMEM;
1965 		goto err_free_dev;
1966 	}
1967 
1968 	priv->ad9361_phy = ad9361_spi_to_phy((struct spi_device*)tmp_dev);
1969 	if (!(priv->ad9361_phy)) {
1970 		printk(KERN_ERR "%s ad9361_spi_to_phy failed\n",sdr_compatible_str);
1971 		err = -ENOMEM;
1972 		goto err_free_dev;
1973 	}
1974 	printk("%s ad9361_spi_to_phy ad9361-phy: %s\n", sdr_compatible_str, priv->ad9361_phy->spi->modalias);
1975 
1976 	priv->ctrl_out.en_mask=0xFF;
1977 	priv->ctrl_out.index=0x16;
1978 	err = ad9361_ctrl_outs_setup(priv->ad9361_phy, &(priv->ctrl_out));
1979 	if (err < 0) {
1980 		printk("%s openwifi_dev_probe: WARNING ad9361_ctrl_outs_setup %d\n",sdr_compatible_str, err);
1981 	} else {
1982 		printk("%s openwifi_dev_probe: ad9361_ctrl_outs_setup en_mask 0x%02x index 0x%02x\n",sdr_compatible_str, priv->ctrl_out.en_mask, priv->ctrl_out.index);
1983 	}
1984 
1985 	reg = ad9361_spi_read(priv->ad9361_phy->spi, REG_CTRL_OUTPUT_POINTER);
1986 	printk("%s openwifi_dev_probe: ad9361_spi_read REG_CTRL_OUTPUT_POINTER 0x%02x\n",sdr_compatible_str, reg);
1987 	reg = ad9361_spi_read(priv->ad9361_phy->spi, REG_CTRL_OUTPUT_ENABLE);
1988 	printk("%s openwifi_dev_probe: ad9361_spi_read REG_CTRL_OUTPUT_ENABLE 0x%02x\n",sdr_compatible_str, reg);
1989 
1990 	// //-------------find driver: axi_ad9361 hdl ref design module, dac channel---------------
1991 	tmp_dev = bus_find_device( &platform_bus_type, NULL, "cf-ad9361-dds-core-lpc", custom_match_platform_dev );
1992 	if (!tmp_dev) {
1993 		printk(KERN_ERR "%s bus_find_device platform_bus_type cf-ad9361-dds-core-lpc failed\n",sdr_compatible_str);
1994 		err = -ENOMEM;
1995 		goto err_free_dev;
1996 	}
1997 
1998 	tmp_pdev = to_platform_device(tmp_dev);
1999 	if (!tmp_pdev) {
2000 		printk(KERN_ERR "%s to_platform_device failed\n",sdr_compatible_str);
2001 		err = -ENOMEM;
2002 		goto err_free_dev;
2003 	}
2004 
2005 	tmp_indio_dev = platform_get_drvdata(tmp_pdev);
2006 	if (!tmp_indio_dev) {
2007 		printk(KERN_ERR "%s platform_get_drvdata failed\n",sdr_compatible_str);
2008 		err = -ENOMEM;
2009 		goto err_free_dev;
2010 	}
2011 
2012 	priv->dds_st = iio_priv(tmp_indio_dev);
2013 	if (!(priv->dds_st)) {
2014 		printk(KERN_ERR "%s iio_priv failed\n",sdr_compatible_str);
2015 		err = -ENOMEM;
2016 		goto err_free_dev;
2017 	}
2018 	printk("%s openwifi_dev_probe: cf-ad9361-dds-core-lpc dds_st->version %08x chip_info->name %s\n",sdr_compatible_str,priv->dds_st->version,priv->dds_st->chip_info->name);
2019 	cf_axi_dds_datasel(priv->dds_st, -1, DATA_SEL_DMA);
2020 	printk("%s openwifi_dev_probe: cf_axi_dds_datasel DATA_SEL_DMA\n",sdr_compatible_str);
2021 
2022 	// //-------------find driver: axi_ad9361 hdl ref design module, adc channel---------------
2023 	// turn off radio by muting tx
2024 	// ad9361_tx_mute(priv->ad9361_phy, 1);
2025 	// reg = ad9361_get_tx_atten(priv->ad9361_phy, 2);
2026 	// reg1 = ad9361_get_tx_atten(priv->ad9361_phy, 1);
2027 	// if (reg == AD9361_RADIO_OFF_TX_ATT && reg1 == AD9361_RADIO_OFF_TX_ATT ) {
2028 	// 	priv->rfkill_off = 0;// 0 off, 1 on
2029 	// 	printk("%s openwifi_dev_probe: rfkill radio off\n",sdr_compatible_str);
2030 	// }
2031 	// else
2032 	// 	printk("%s openwifi_dev_probe: WARNING rfkill radio off failed. tx att read %d %d require %d\n",sdr_compatible_str, reg, reg1, AD9361_RADIO_OFF_TX_ATT);
2033 
2034 	priv->last_auto_fpga_lbt_th = 134;//just to avoid uninitialized
2035 	priv->rssi_correction = 43;//this will be set in real-time by _rf_set_channel()
2036 
2037 	//priv->rf_bw = 20000000; // Signal quality issue! NOT use for now. 20MHz or 40MHz. 40MHz need ddc/duc. 20MHz works in bypass mode
2038 	priv->rf_bw = 40000000; // 20MHz or 40MHz. 40MHz need ddc/duc. 20MHz works in bypass mode
2039 
2040 	priv->xpu_cfg = XPU_NORMAL;
2041 
2042 	priv->openofdm_tx_cfg = OPENOFDM_TX_NORMAL;
2043 	priv->openofdm_rx_cfg = OPENOFDM_RX_NORMAL;
2044 
2045 	printk("%s openwifi_dev_probe: priv->rf_bw == %dHz. bool for 20000000 %d, 40000000 %d\n",sdr_compatible_str, priv->rf_bw, (priv->rf_bw==20000000) , (priv->rf_bw==40000000) );
2046 	if (priv->rf_bw == 20000000) {
2047 		priv->rx_intf_cfg = RX_INTF_BYPASS;
2048 		priv->tx_intf_cfg = TX_INTF_BYPASS;
2049 		//priv->rx_freq_offset_to_lo_MHz = 0;
2050 		//priv->tx_freq_offset_to_lo_MHz = 0;
2051 	} else if (priv->rf_bw == 40000000) {
2052 		//priv->rx_intf_cfg = RX_INTF_BW_20MHZ_AT_P_10MHZ; //work
2053 		//priv->tx_intf_cfg = TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT1; //work
2054 
2055 		// // test ddc at central, duc at central+10M. It works. And also change rx BW from 40MHz to 20MHz in rf_init.sh. Rx sampling rate is still 40Msps
2056 		priv->rx_intf_cfg = RX_INTF_BW_20MHZ_AT_0MHZ_ANT0;
2057 		priv->tx_intf_cfg = TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT0; // Let's use rx0 tx0 as default mode, because it works for both 9361 and 9364
2058 		// // try another antenna option
2059 		//priv->rx_intf_cfg = RX_INTF_BW_20MHZ_AT_0MHZ_ANT1;
2060 		//priv->tx_intf_cfg = TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT0;
2061 
2062 		#if 0
2063 		if (priv->rx_intf_cfg == DDC_BW_20MHZ_AT_N_10MHZ) {
2064 			priv->rx_freq_offset_to_lo_MHz = -10;
2065 		} else if (priv->rx_intf_cfg == DDC_BW_20MHZ_AT_P_10MHZ) {
2066 			priv->rx_freq_offset_to_lo_MHz = 10;
2067 		} else if (priv->rx_intf_cfg == DDC_BW_20MHZ_AT_0MHZ) {
2068 			priv->rx_freq_offset_to_lo_MHz = 0;
2069 		} else {
2070 			printk("%s openwifi_dev_probe: Warning! priv->rx_intf_cfg == %d\n",sdr_compatible_str,priv->rx_intf_cfg);
2071 		}
2072 		#endif
2073 	} else {
2074 		printk("%s openwifi_dev_probe: Warning! priv->rf_bw == %dHz (should be 20000000 or 40000000)\n",sdr_compatible_str, priv->rf_bw);
2075 	}
2076 	priv->rx_freq_offset_to_lo_MHz = rx_intf_fo_mapping[priv->rx_intf_cfg];
2077 	priv->tx_freq_offset_to_lo_MHz = tx_intf_fo_mapping[priv->tx_intf_cfg];
2078 	printk("%s openwifi_dev_probe: test_mode %d\n", sdr_compatible_str, test_mode);
2079 
2080 	//let's by default turn radio on when probing
2081 	if (priv->tx_intf_cfg == TX_INTF_BW_20MHZ_AT_N_10MHZ_ANT1) {
2082 		ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT, false, true, true); // AD9361_RADIO_ON_TX_ATT 3000 means 3dB, 0 means 0dB
2083 		reg = ad9361_get_tx_atten(priv->ad9361_phy, 2);
2084 	} else {
2085 		ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT, true, false, true); // AD9361_RADIO_ON_TX_ATT 3000 means 3dB, 0 means 0dB
2086 		reg = ad9361_get_tx_atten(priv->ad9361_phy, 1);
2087 	}
2088 	if (reg == AD9361_RADIO_ON_TX_ATT) {
2089 		priv->rfkill_off = 1;// 0 off, 1 on
2090 		printk("%s openwifi_dev_probe: rfkill radio on\n",sdr_compatible_str);
2091 	} else
2092 		printk("%s openwifi_dev_probe: WARNING rfkill radio on failed. tx att read %d require %d\n",sdr_compatible_str, reg, AD9361_RADIO_ON_TX_ATT);
2093 
2094 	memset(priv->drv_rx_reg_val,0,sizeof(priv->drv_rx_reg_val));
2095 	memset(priv->drv_tx_reg_val,0,sizeof(priv->drv_tx_reg_val));
2096 	memset(priv->drv_xpu_reg_val,0,sizeof(priv->drv_xpu_reg_val));
2097 
2098 	// //set ad9361 in certain mode
2099 	#if 0
2100 	err = ad9361_set_trx_clock_chain_freq(priv->ad9361_phy,priv->rf_bw);
2101 	printk("%s openwifi_dev_probe: ad9361_set_trx_clock_chain_freq %dHz err %d\n",sdr_compatible_str, priv->rf_bw,err);
2102 	err = ad9361_update_rf_bandwidth(priv->ad9361_phy,priv->rf_bw,priv->rf_bw);
2103 	printk("%s openwifi_dev_probe: ad9361_update_rf_bandwidth %dHz err %d\n",sdr_compatible_str, priv->rf_bw,err);
2104 
2105 	rx_intf_api->hw_init(priv->rx_intf_cfg,8,8);
2106 	tx_intf_api->hw_init(priv->tx_intf_cfg,8,8,priv->fpga_type);
2107 	openofdm_tx_api->hw_init(priv->openofdm_tx_cfg);
2108 	openofdm_rx_api->hw_init(priv->openofdm_rx_cfg);
2109 	printk("%s openwifi_dev_probe: rx_intf_cfg %d openofdm_rx_cfg %d tx_intf_cfg %d openofdm_tx_cfg %d\n",sdr_compatible_str, priv->rx_intf_cfg, priv->openofdm_rx_cfg, priv->tx_intf_cfg, priv->openofdm_tx_cfg);
2110 	printk("%s openwifi_dev_probe: rx_freq_offset_to_lo_MHz %d tx_freq_offset_to_lo_MHz %d\n",sdr_compatible_str, priv->rx_freq_offset_to_lo_MHz, priv->tx_freq_offset_to_lo_MHz);
2111 	#endif
2112 
2113 	dev->max_rates = 1; //maximum number of alternate rate retry stages the hw can handle.
2114 
2115 	SET_IEEE80211_DEV(dev, &pdev->dev);
2116 	platform_set_drvdata(pdev, dev);
2117 
2118 	BUILD_BUG_ON(sizeof(priv->rates_2GHz) != sizeof(openwifi_2GHz_rates));
2119 	BUILD_BUG_ON(sizeof(priv->rates_5GHz) != sizeof(openwifi_5GHz_rates));
2120 	BUILD_BUG_ON(sizeof(priv->channels_2GHz) != sizeof(openwifi_2GHz_channels));
2121 	BUILD_BUG_ON(sizeof(priv->channels_5GHz) != sizeof(openwifi_5GHz_channels));
2122 
2123 	memcpy(priv->rates_2GHz, openwifi_2GHz_rates, sizeof(openwifi_2GHz_rates));
2124 	memcpy(priv->rates_5GHz, openwifi_5GHz_rates, sizeof(openwifi_5GHz_rates));
2125 	memcpy(priv->channels_2GHz, openwifi_2GHz_channels, sizeof(openwifi_2GHz_channels));
2126 	memcpy(priv->channels_5GHz, openwifi_5GHz_channels, sizeof(openwifi_5GHz_channels));
2127 
2128 	priv->band = BAND_5_8GHZ; //this can be changed by band _rf_set_channel() (2.4GHz ERP(OFDM)) (5GHz OFDM)
2129 	priv->channel = 44;  //currently useless. this can be changed by band _rf_set_channel()
2130 	priv->use_short_slot = false; //this can be changed by openwifi_bss_info_changed: BSS_CHANGED_ERP_SLOT
2131 
2132 	priv->band_2GHz.band = NL80211_BAND_2GHZ;
2133 	priv->band_2GHz.channels = priv->channels_2GHz;
2134 	priv->band_2GHz.n_channels = ARRAY_SIZE(priv->channels_2GHz);
2135 	priv->band_2GHz.bitrates = priv->rates_2GHz;
2136 	priv->band_2GHz.n_bitrates = ARRAY_SIZE(priv->rates_2GHz);
2137 	priv->band_2GHz.ht_cap.ht_supported = true;
2138 	priv->band_2GHz.ht_cap.cap = IEEE80211_HT_CAP_SGI_20;
2139 	memset(&priv->band_2GHz.ht_cap.mcs, 0, sizeof(priv->band_2GHz.ht_cap.mcs));
2140 	priv->band_2GHz.ht_cap.mcs.rx_mask[0] = 0xff;
2141 	priv->band_2GHz.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
2142 	dev->wiphy->bands[NL80211_BAND_2GHZ] = &(priv->band_2GHz);
2143 
2144 	priv->band_5GHz.band = NL80211_BAND_5GHZ;
2145 	priv->band_5GHz.channels = priv->channels_5GHz;
2146 	priv->band_5GHz.n_channels = ARRAY_SIZE(priv->channels_5GHz);
2147 	priv->band_5GHz.bitrates = priv->rates_5GHz;
2148 	priv->band_5GHz.n_bitrates = ARRAY_SIZE(priv->rates_5GHz);
2149 	priv->band_5GHz.ht_cap.ht_supported = true;
2150 	priv->band_5GHz.ht_cap.cap = IEEE80211_HT_CAP_SGI_20;
2151 	memset(&priv->band_5GHz.ht_cap.mcs, 0, sizeof(priv->band_5GHz.ht_cap.mcs));
2152 	priv->band_5GHz.ht_cap.mcs.rx_mask[0] = 0xff;
2153 	priv->band_5GHz.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
2154 	dev->wiphy->bands[NL80211_BAND_5GHZ] = &(priv->band_5GHz);
2155 
2156 	printk("%s openwifi_dev_probe: band_2GHz.n_channels %d n_bitrates %d band_5GHz.n_channels %d n_bitrates %d\n",sdr_compatible_str,
2157 	priv->band_2GHz.n_channels,priv->band_2GHz.n_bitrates,priv->band_5GHz.n_channels,priv->band_5GHz.n_bitrates);
2158 
2159 	ieee80211_hw_set(dev, HOST_BROADCAST_PS_BUFFERING);
2160 	ieee80211_hw_set(dev, RX_INCLUDES_FCS);
2161 	ieee80211_hw_set(dev, BEACON_TX_STATUS);
2162 
2163 	dev->vif_data_size = sizeof(struct openwifi_vif);
2164 	dev->wiphy->interface_modes =
2165 			BIT(NL80211_IFTYPE_MONITOR)|
2166 			BIT(NL80211_IFTYPE_P2P_GO) |
2167 			BIT(NL80211_IFTYPE_P2P_CLIENT) |
2168 			BIT(NL80211_IFTYPE_AP) |
2169 			BIT(NL80211_IFTYPE_STATION) |
2170 			BIT(NL80211_IFTYPE_ADHOC) |
2171 			BIT(NL80211_IFTYPE_MESH_POINT) |
2172 			BIT(NL80211_IFTYPE_OCB);
2173 	dev->wiphy->iface_combinations = &openwifi_if_comb;
2174 	dev->wiphy->n_iface_combinations = 1;
2175 
2176 	dev->wiphy->regulatory_flags = (REGULATORY_STRICT_REG|REGULATORY_CUSTOM_REG); // use our own config within strict regulation
2177 	//dev->wiphy->regulatory_flags = REGULATORY_CUSTOM_REG; // use our own config
2178 	wiphy_apply_custom_regulatory(dev->wiphy, &sdr_regd);
2179 
2180 	chip_name = "ZYNQ";
2181 
2182 	/* we declare to MAC80211 all the queues except for beacon queue
2183 	 * that will be eventually handled by DRV.
2184 	 * TX rings are arranged in such a way that lower is the IDX,
2185 	 * higher is the priority, in order to achieve direct mapping
2186 	 * with mac80211, however the beacon queue is an exception and it
2187 	 * is mapped on the highst tx ring IDX.
2188 	 */
2189 	dev->queues = MAX_NUM_HW_QUEUE;
2190 	//dev->queues = 1;
2191 
2192 	ieee80211_hw_set(dev, SIGNAL_DBM);
2193 
2194 	wiphy_ext_feature_set(dev->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
2195 
2196 	priv->rf = &ad9361_rf_ops;
2197 
2198 	memset(priv->dest_mac_addr_queue_map,0,sizeof(priv->dest_mac_addr_queue_map));
2199 	priv->slice_idx = 0xFFFFFFFF;
2200 
2201 	sg_init_table(&(priv->tx_sg), 1);
2202 
2203 	get_random_bytes(&rand_val, sizeof(rand_val));
2204     rand_val%=250;
2205 	priv->mac_addr[0]=0x66;	priv->mac_addr[1]=0x55;	priv->mac_addr[2]=0x44;	priv->mac_addr[3]=0x33;	priv->mac_addr[4]=0x22;
2206 	priv->mac_addr[5]=rand_val+1;
2207 	//priv->mac_addr[5]=0x11;
2208 	if (!is_valid_ether_addr(priv->mac_addr)) {
2209 		printk(KERN_WARNING "%s openwifi_dev_probe: WARNING Invalid hwaddr! Using randomly generated MAC addr\n",sdr_compatible_str);
2210 		eth_random_addr(priv->mac_addr);
2211 	} else {
2212 		printk("%s openwifi_dev_probe: mac_addr %02x:%02x:%02x:%02x:%02x:%02x\n",sdr_compatible_str,priv->mac_addr[0],priv->mac_addr[1],priv->mac_addr[2],priv->mac_addr[3],priv->mac_addr[4],priv->mac_addr[5]);
2213 	}
2214 	SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr);
2215 
2216 	spin_lock_init(&priv->lock);
2217 
2218 	err = ieee80211_register_hw(dev);
2219 	if (err) {
2220 		pr_err(KERN_ERR "%s openwifi_dev_probe: WARNING Cannot register device\n",sdr_compatible_str);
2221 		goto err_free_dev;
2222 	} else {
2223 		printk("%s openwifi_dev_probe: ieee80211_register_hw %d\n",sdr_compatible_str, err);
2224 	}
2225 
2226 	// // //--------------------hook leds (not complete yet)--------------------------------
2227 	// tmp_dev = bus_find_device( &platform_bus_type, NULL, "leds", custom_match_platform_dev ); //leds is the name in devicetree, not "compatible" field
2228 	// if (!tmp_dev) {
2229 	// 	printk(KERN_ERR "%s bus_find_device platform_bus_type leds-gpio failed\n",sdr_compatible_str);
2230 	// 	err = -ENOMEM;
2231 	// 	goto err_free_dev;
2232 	// }
2233 
2234 	// tmp_pdev = to_platform_device(tmp_dev);
2235 	// if (!tmp_pdev) {
2236 	// 	printk(KERN_ERR "%s to_platform_device failed for leds-gpio\n",sdr_compatible_str);
2237 	// 	err = -ENOMEM;
2238 	// 	goto err_free_dev;
2239 	// }
2240 
2241 	// tmp_led_priv = platform_get_drvdata(tmp_pdev);
2242 	// if (!tmp_led_priv) {
2243 	// 	printk(KERN_ERR "%s platform_get_drvdata failed for leds-gpio\n",sdr_compatible_str);
2244 	// 	err = -ENOMEM;
2245 	// 	goto err_free_dev;
2246 	// }
2247 	// printk("%s openwifi_dev_probe: leds-gpio detect %d leds!\n",sdr_compatible_str, tmp_led_priv->num_leds);
2248 	// if (tmp_led_priv->num_leds!=4){
2249 	// 	printk(KERN_ERR "%s WARNING we expect 4 leds, but actual %d leds\n",sdr_compatible_str,tmp_led_priv->num_leds);
2250 	// 	err = -ENOMEM;
2251 	// 	goto err_free_dev;
2252 	// }
2253 	// gpiod_set_value(tmp_led_priv->leds[0].gpiod, 1);//light it
2254 	// gpiod_set_value(tmp_led_priv->leds[3].gpiod, 0);//black it
2255 	// priv->num_led = tmp_led_priv->num_leds;
2256 	// priv->led[0] = &(tmp_led_priv->leds[0].cdev);
2257 	// priv->led[1] = &(tmp_led_priv->leds[1].cdev);
2258 	// priv->led[2] = &(tmp_led_priv->leds[2].cdev);
2259 	// priv->led[3] = &(tmp_led_priv->leds[3].cdev);
2260 
2261 	// snprintf(priv->led_name[0], OPENWIFI_LED_MAX_NAME_LEN, "openwifi-%s::radio", wiphy_name(dev->wiphy));
2262 	// snprintf(priv->led_name[1], OPENWIFI_LED_MAX_NAME_LEN, "openwifi-%s::assoc", wiphy_name(dev->wiphy));
2263 	// snprintf(priv->led_name[2], OPENWIFI_LED_MAX_NAME_LEN, "openwifi-%s::tx", wiphy_name(dev->wiphy));
2264 	// snprintf(priv->led_name[3], OPENWIFI_LED_MAX_NAME_LEN, "openwifi-%s::rx", wiphy_name(dev->wiphy));
2265 
2266 	wiphy_info(dev->wiphy, "hwaddr %pm, %s + %s\n",
2267 		   priv->mac_addr, chip_name, priv->rf->name);
2268 
2269 	openwifi_rfkill_init(dev);
2270 	return 0;
2271 
2272  err_free_dev:
2273 	ieee80211_free_hw(dev);
2274 
2275 	return err;
2276 }
2277 
2278 static int openwifi_dev_remove(struct platform_device *pdev)
2279 {
2280 	struct ieee80211_hw *dev = platform_get_drvdata(pdev);
2281 
2282 	if (!dev) {
2283 		pr_info("%s openwifi_dev_remove: dev %p\n", sdr_compatible_str, (void*)dev);
2284 		return(-1);
2285 	}
2286 
2287 	openwifi_rfkill_exit(dev);
2288 	ieee80211_unregister_hw(dev);
2289 	ieee80211_free_hw(dev);
2290 	return(0);
2291 }
2292 
2293 static struct platform_driver openwifi_dev_driver = {
2294 	.driver = {
2295 		.name = "sdr,sdr",
2296 		.owner = THIS_MODULE,
2297 		.of_match_table = openwifi_dev_of_ids,
2298 	},
2299 	.probe = openwifi_dev_probe,
2300 	.remove = openwifi_dev_remove,
2301 };
2302 
2303 module_platform_driver(openwifi_dev_driver);
2304