xref: /linux/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c (revision cdd38c5f1ce4398ec58fec95904b75824daab7b5)
173ffcd40SLee Jones /*
2dad0d04fSFariya Fatima  * Copyright (c) 2014 Redpine Signals Inc.
3dad0d04fSFariya Fatima  *
4dad0d04fSFariya Fatima  * Permission to use, copy, modify, and/or distribute this software for any
5dad0d04fSFariya Fatima  * purpose with or without fee is hereby granted, provided that the above
6dad0d04fSFariya Fatima  * copyright notice and this permission notice appear in all copies.
7dad0d04fSFariya Fatima  *
8dad0d04fSFariya Fatima  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9dad0d04fSFariya Fatima  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10dad0d04fSFariya Fatima  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11dad0d04fSFariya Fatima  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12dad0d04fSFariya Fatima  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13dad0d04fSFariya Fatima  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14dad0d04fSFariya Fatima  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15dad0d04fSFariya Fatima  *
16dad0d04fSFariya Fatima  */
17dad0d04fSFariya Fatima 
18dad0d04fSFariya Fatima #include <linux/firmware.h>
19716b840cSSiva Rebbagondla #include <net/rsi_91x.h>
20dad0d04fSFariya Fatima #include "rsi_sdio.h"
21dad0d04fSFariya Fatima #include "rsi_common.h"
22dad0d04fSFariya Fatima 
23dad0d04fSFariya Fatima /**
24dad0d04fSFariya Fatima  * rsi_sdio_master_access_msword() - This function sets the AHB master access
25dad0d04fSFariya Fatima  *				     MS word in the SDIO slave registers.
26dad0d04fSFariya Fatima  * @adapter: Pointer to the adapter structure.
27dad0d04fSFariya Fatima  * @ms_word: ms word need to be initialized.
28dad0d04fSFariya Fatima  *
29dad0d04fSFariya Fatima  * Return: status: 0 on success, -1 on failure.
30dad0d04fSFariya Fatima  */
31b97e9b94SPrameela Rani Garnepudi int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word)
32dad0d04fSFariya Fatima {
33dad0d04fSFariya Fatima 	u8 byte;
34dad0d04fSFariya Fatima 	u8 function = 0;
35dad0d04fSFariya Fatima 	int status = 0;
36dad0d04fSFariya Fatima 
37dad0d04fSFariya Fatima 	byte = (u8)(ms_word & 0x00FF);
38dad0d04fSFariya Fatima 
39dad0d04fSFariya Fatima 	rsi_dbg(INIT_ZONE,
40dad0d04fSFariya Fatima 		"%s: MASTER_ACCESS_MSBYTE:0x%x\n", __func__, byte);
41dad0d04fSFariya Fatima 
42dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
43dad0d04fSFariya Fatima 					 function,
44dad0d04fSFariya Fatima 					 SDIO_MASTER_ACCESS_MSBYTE,
45dad0d04fSFariya Fatima 					 &byte);
46dad0d04fSFariya Fatima 	if (status) {
47dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
48dad0d04fSFariya Fatima 			"%s: fail to access MASTER_ACCESS_MSBYTE\n",
49dad0d04fSFariya Fatima 			__func__);
50dad0d04fSFariya Fatima 		return -1;
51dad0d04fSFariya Fatima 	}
52dad0d04fSFariya Fatima 
53dad0d04fSFariya Fatima 	byte = (u8)(ms_word >> 8);
54dad0d04fSFariya Fatima 
55dad0d04fSFariya Fatima 	rsi_dbg(INIT_ZONE, "%s:MASTER_ACCESS_LSBYTE:0x%x\n", __func__, byte);
56dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
57dad0d04fSFariya Fatima 					 function,
58dad0d04fSFariya Fatima 					 SDIO_MASTER_ACCESS_LSBYTE,
59dad0d04fSFariya Fatima 					 &byte);
60dad0d04fSFariya Fatima 	return status;
61dad0d04fSFariya Fatima }
62dad0d04fSFariya Fatima 
6328743146SMarek Vasut static void rsi_rx_handler(struct rsi_hw *adapter);
6428743146SMarek Vasut 
6550117605SPrameela Rani Garnepudi void rsi_sdio_rx_thread(struct rsi_common *common)
6650117605SPrameela Rani Garnepudi {
6750117605SPrameela Rani Garnepudi 	struct rsi_hw *adapter = common->priv;
6850117605SPrameela Rani Garnepudi 	struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
6950117605SPrameela Rani Garnepudi 
7050117605SPrameela Rani Garnepudi 	do {
7150117605SPrameela Rani Garnepudi 		rsi_wait_event(&sdev->rx_thread.event, EVENT_WAIT_FOREVER);
7250117605SPrameela Rani Garnepudi 		rsi_reset_event(&sdev->rx_thread.event);
7328743146SMarek Vasut 		rsi_rx_handler(adapter);
7428743146SMarek Vasut 	} while (!atomic_read(&sdev->rx_thread.thread_done));
7550117605SPrameela Rani Garnepudi 
7650117605SPrameela Rani Garnepudi 	rsi_dbg(INFO_ZONE, "%s: Terminated SDIO RX thread\n", __func__);
7750117605SPrameela Rani Garnepudi 	atomic_inc(&sdev->rx_thread.thread_done);
7850117605SPrameela Rani Garnepudi 	complete_and_exit(&sdev->rx_thread.completion, 0);
7950117605SPrameela Rani Garnepudi }
8050117605SPrameela Rani Garnepudi 
81dad0d04fSFariya Fatima /**
82dad0d04fSFariya Fatima  * rsi_process_pkt() - This Function reads rx_blocks register and figures out
83dad0d04fSFariya Fatima  *		       the size of the rx pkt.
84dad0d04fSFariya Fatima  * @common: Pointer to the driver private structure.
85dad0d04fSFariya Fatima  *
86dad0d04fSFariya Fatima  * Return: 0 on success, -1 on failure.
87dad0d04fSFariya Fatima  */
88dad0d04fSFariya Fatima static int rsi_process_pkt(struct rsi_common *common)
89dad0d04fSFariya Fatima {
90dad0d04fSFariya Fatima 	struct rsi_hw *adapter = common->priv;
91ebf084eaSKarun Eagalapati 	struct rsi_91x_sdiodev *dev =
92ebf084eaSKarun Eagalapati 		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
93dad0d04fSFariya Fatima 	u8 num_blks = 0;
94dad0d04fSFariya Fatima 	u32 rcv_pkt_len = 0;
95dad0d04fSFariya Fatima 	int status = 0;
96ebf084eaSKarun Eagalapati 	u8 value = 0;
97dad0d04fSFariya Fatima 
98ebf084eaSKarun Eagalapati 	num_blks = ((adapter->interrupt_status & 1) |
99ebf084eaSKarun Eagalapati 			((adapter->interrupt_status >> RECV_NUM_BLOCKS) << 1));
100ebf084eaSKarun Eagalapati 
101ebf084eaSKarun Eagalapati 	if (!num_blks) {
102dad0d04fSFariya Fatima 		status = rsi_sdio_read_register(adapter,
103dad0d04fSFariya Fatima 						SDIO_RX_NUM_BLOCKS_REG,
104ebf084eaSKarun Eagalapati 						&value);
105dad0d04fSFariya Fatima 		if (status) {
106dad0d04fSFariya Fatima 			rsi_dbg(ERR_ZONE,
107dad0d04fSFariya Fatima 				"%s: Failed to read pkt length from the card:\n",
108dad0d04fSFariya Fatima 				__func__);
109dad0d04fSFariya Fatima 			return status;
110dad0d04fSFariya Fatima 		}
111ebf084eaSKarun Eagalapati 		num_blks = value & 0x1f;
112ebf084eaSKarun Eagalapati 	}
113ebf084eaSKarun Eagalapati 
114ebf084eaSKarun Eagalapati 	if (dev->write_fail == 2)
115ebf084eaSKarun Eagalapati 		rsi_sdio_ack_intr(common->priv, (1 << MSDU_PKT_PENDING));
116ebf084eaSKarun Eagalapati 
117ebf084eaSKarun Eagalapati 	if (unlikely(!num_blks)) {
118ebf084eaSKarun Eagalapati 		dev->write_fail = 2;
119ebf084eaSKarun Eagalapati 		return -1;
120ebf084eaSKarun Eagalapati 	}
121ebf084eaSKarun Eagalapati 
122dad0d04fSFariya Fatima 	rcv_pkt_len = (num_blks * 256);
123dad0d04fSFariya Fatima 
12428743146SMarek Vasut 	status = rsi_sdio_host_intf_read_pkt(adapter, dev->pktbuffer,
12528743146SMarek Vasut 					     rcv_pkt_len);
126dad0d04fSFariya Fatima 	if (status) {
127dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",
128dad0d04fSFariya Fatima 			__func__);
129d50c761aSFariya Fatima 		return status;
130dad0d04fSFariya Fatima 	}
13150117605SPrameela Rani Garnepudi 
13228743146SMarek Vasut 	status = rsi_read_pkt(common, dev->pktbuffer, rcv_pkt_len);
13328743146SMarek Vasut 	if (status) {
13428743146SMarek Vasut 		rsi_dbg(ERR_ZONE, "Failed to read the packet\n");
13528743146SMarek Vasut 		return status;
13628743146SMarek Vasut 	}
13750117605SPrameela Rani Garnepudi 
13850117605SPrameela Rani Garnepudi 	return 0;
13950117605SPrameela Rani Garnepudi }
140dad0d04fSFariya Fatima 
141dad0d04fSFariya Fatima /**
142dad0d04fSFariya Fatima  * rsi_init_sdio_slave_regs() - This function does the actual initialization
143dad0d04fSFariya Fatima  *				of SDBUS slave registers.
144dad0d04fSFariya Fatima  * @adapter: Pointer to the adapter structure.
145dad0d04fSFariya Fatima  *
146dad0d04fSFariya Fatima  * Return: status: 0 on success, -1 on failure.
147dad0d04fSFariya Fatima  */
148dad0d04fSFariya Fatima int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
149dad0d04fSFariya Fatima {
150dad0d04fSFariya Fatima 	struct rsi_91x_sdiodev *dev =
151dad0d04fSFariya Fatima 		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
152dad0d04fSFariya Fatima 	u8 function = 0;
153dad0d04fSFariya Fatima 	u8 byte;
154dad0d04fSFariya Fatima 	int status = 0;
155dad0d04fSFariya Fatima 
156dad0d04fSFariya Fatima 	if (dev->next_read_delay) {
157dad0d04fSFariya Fatima 		byte = dev->next_read_delay;
158dad0d04fSFariya Fatima 		status = rsi_sdio_write_register(adapter,
159dad0d04fSFariya Fatima 						 function,
160dad0d04fSFariya Fatima 						 SDIO_NXT_RD_DELAY2,
161dad0d04fSFariya Fatima 						 &byte);
162dad0d04fSFariya Fatima 		if (status) {
163dad0d04fSFariya Fatima 			rsi_dbg(ERR_ZONE,
164dad0d04fSFariya Fatima 				"%s: Failed to write SDIO_NXT_RD_DELAY2\n",
165dad0d04fSFariya Fatima 				__func__);
166dad0d04fSFariya Fatima 			return -1;
167dad0d04fSFariya Fatima 		}
168dad0d04fSFariya Fatima 	}
169dad0d04fSFariya Fatima 
170dad0d04fSFariya Fatima 	if (dev->sdio_high_speed_enable) {
171dad0d04fSFariya Fatima 		rsi_dbg(INIT_ZONE, "%s: Enabling SDIO High speed\n", __func__);
172dad0d04fSFariya Fatima 		byte = 0x3;
173dad0d04fSFariya Fatima 
174dad0d04fSFariya Fatima 		status = rsi_sdio_write_register(adapter,
175dad0d04fSFariya Fatima 						 function,
176dad0d04fSFariya Fatima 						 SDIO_REG_HIGH_SPEED,
177dad0d04fSFariya Fatima 						 &byte);
178dad0d04fSFariya Fatima 		if (status) {
179dad0d04fSFariya Fatima 			rsi_dbg(ERR_ZONE,
180dad0d04fSFariya Fatima 				"%s: Failed to enable SDIO high speed\n",
181dad0d04fSFariya Fatima 				__func__);
182dad0d04fSFariya Fatima 			return -1;
183dad0d04fSFariya Fatima 		}
184dad0d04fSFariya Fatima 	}
185dad0d04fSFariya Fatima 
186dad0d04fSFariya Fatima 	/* This tells SDIO FIFO when to start read to host */
18755930d2bSColin Ian King 	rsi_dbg(INIT_ZONE, "%s: Initializing SDIO read start level\n", __func__);
188dad0d04fSFariya Fatima 	byte = 0x24;
189dad0d04fSFariya Fatima 
190dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
191dad0d04fSFariya Fatima 					 function,
192dad0d04fSFariya Fatima 					 SDIO_READ_START_LVL,
193dad0d04fSFariya Fatima 					 &byte);
194dad0d04fSFariya Fatima 	if (status) {
195dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
196dad0d04fSFariya Fatima 			"%s: Failed to write SDIO_READ_START_LVL\n", __func__);
197dad0d04fSFariya Fatima 		return -1;
198dad0d04fSFariya Fatima 	}
199dad0d04fSFariya Fatima 
20055930d2bSColin Ian King 	rsi_dbg(INIT_ZONE, "%s: Initializing FIFO ctrl registers\n", __func__);
201dad0d04fSFariya Fatima 	byte = (128 - 32);
202dad0d04fSFariya Fatima 
203dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
204dad0d04fSFariya Fatima 					 function,
205dad0d04fSFariya Fatima 					 SDIO_READ_FIFO_CTL,
206dad0d04fSFariya Fatima 					 &byte);
207dad0d04fSFariya Fatima 	if (status) {
208dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
209dad0d04fSFariya Fatima 			"%s: Failed to write SDIO_READ_FIFO_CTL\n", __func__);
210dad0d04fSFariya Fatima 		return -1;
211dad0d04fSFariya Fatima 	}
212dad0d04fSFariya Fatima 
213dad0d04fSFariya Fatima 	byte = 32;
214dad0d04fSFariya Fatima 	status = rsi_sdio_write_register(adapter,
215dad0d04fSFariya Fatima 					 function,
216dad0d04fSFariya Fatima 					 SDIO_WRITE_FIFO_CTL,
217dad0d04fSFariya Fatima 					 &byte);
218dad0d04fSFariya Fatima 	if (status) {
219dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
220dad0d04fSFariya Fatima 			"%s: Failed to write SDIO_WRITE_FIFO_CTL\n", __func__);
221dad0d04fSFariya Fatima 		return -1;
222dad0d04fSFariya Fatima 	}
223dad0d04fSFariya Fatima 
224dad0d04fSFariya Fatima 	return 0;
225dad0d04fSFariya Fatima }
226dad0d04fSFariya Fatima 
227dad0d04fSFariya Fatima /**
22828743146SMarek Vasut  * rsi_rx_handler() - Read and process SDIO interrupts.
229dad0d04fSFariya Fatima  * @adapter: Pointer to the adapter structure.
230dad0d04fSFariya Fatima  *
231dad0d04fSFariya Fatima  * Return: None.
232dad0d04fSFariya Fatima  */
23328743146SMarek Vasut static void rsi_rx_handler(struct rsi_hw *adapter)
234dad0d04fSFariya Fatima {
235dad0d04fSFariya Fatima 	struct rsi_common *common = adapter->priv;
236dad0d04fSFariya Fatima 	struct rsi_91x_sdiodev *dev =
237dad0d04fSFariya Fatima 		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
238dad0d04fSFariya Fatima 	int status;
239dad0d04fSFariya Fatima 	u8 isr_status = 0;
240dad0d04fSFariya Fatima 	u8 fw_status = 0;
241dad0d04fSFariya Fatima 
242dad0d04fSFariya Fatima 	dev->rx_info.sdio_int_counter++;
243dad0d04fSFariya Fatima 
244dad0d04fSFariya Fatima 	do {
2456c409cadSKarun Eagalapati 		mutex_lock(&common->rx_lock);
246dad0d04fSFariya Fatima 		status = rsi_sdio_read_register(common->priv,
247dad0d04fSFariya Fatima 						RSI_FN1_INT_REGISTER,
248dad0d04fSFariya Fatima 						&isr_status);
249dad0d04fSFariya Fatima 		if (status) {
250dad0d04fSFariya Fatima 			rsi_dbg(ERR_ZONE,
251dad0d04fSFariya Fatima 				"%s: Failed to Read Intr Status Register\n",
252dad0d04fSFariya Fatima 				__func__);
2536c409cadSKarun Eagalapati 			mutex_unlock(&common->rx_lock);
254dad0d04fSFariya Fatima 			return;
255dad0d04fSFariya Fatima 		}
256ebf084eaSKarun Eagalapati 		adapter->interrupt_status = isr_status;
257dad0d04fSFariya Fatima 
258dad0d04fSFariya Fatima 		if (isr_status == 0) {
259dad0d04fSFariya Fatima 			rsi_set_event(&common->tx_thread.event);
260dad0d04fSFariya Fatima 			dev->rx_info.sdio_intr_status_zero++;
2616c409cadSKarun Eagalapati 			mutex_unlock(&common->rx_lock);
262dad0d04fSFariya Fatima 			return;
263dad0d04fSFariya Fatima 		}
264dad0d04fSFariya Fatima 
265dad0d04fSFariya Fatima 		rsi_dbg(ISR_ZONE, "%s: Intr_status = %x %d %d\n",
266dad0d04fSFariya Fatima 			__func__, isr_status, (1 << MSDU_PKT_PENDING),
267dad0d04fSFariya Fatima 			(1 << FW_ASSERT_IND));
268dad0d04fSFariya Fatima 
269*abd131a1SMarek Vasut 		if (isr_status & BIT(PKT_BUFF_AVAILABLE)) {
270*abd131a1SMarek Vasut 			status = rsi_sdio_check_buffer_status(adapter, 0);
27167c52a4dSKarun Eagalapati 			if (status < 0)
27267c52a4dSKarun Eagalapati 				rsi_dbg(ERR_ZONE,
27367c52a4dSKarun Eagalapati 					"%s: Failed to check buffer status\n",
27467c52a4dSKarun Eagalapati 					__func__);
275dad0d04fSFariya Fatima 			rsi_sdio_ack_intr(common->priv,
276*abd131a1SMarek Vasut 					  BIT(PKT_BUFF_AVAILABLE));
277f75d3419SJahnavi Meher 			rsi_set_event(&common->tx_thread.event);
278f75d3419SJahnavi Meher 
279*abd131a1SMarek Vasut 			rsi_dbg(ISR_ZONE, "%s: ==> BUFFER_AVAILABLE <==\n",
280dad0d04fSFariya Fatima 				__func__);
281d64dd2a1SKarun Eagalapati 			dev->buff_status_updated = true;
282dad0d04fSFariya Fatima 
283*abd131a1SMarek Vasut 			isr_status &= ~BIT(PKT_BUFF_AVAILABLE);
284*abd131a1SMarek Vasut 		}
285*abd131a1SMarek Vasut 
286*abd131a1SMarek Vasut 		if (isr_status & BIT(FW_ASSERT_IND)) {
287*abd131a1SMarek Vasut 			rsi_dbg(ERR_ZONE, "%s: ==> FIRMWARE Assert <==\n",
288dad0d04fSFariya Fatima 				__func__);
289dad0d04fSFariya Fatima 			status = rsi_sdio_read_register(common->priv,
290dad0d04fSFariya Fatima 							SDIO_FW_STATUS_REG,
291dad0d04fSFariya Fatima 							&fw_status);
292dad0d04fSFariya Fatima 			if (status) {
293dad0d04fSFariya Fatima 				rsi_dbg(ERR_ZONE,
294dad0d04fSFariya Fatima 					"%s: Failed to read f/w reg\n",
295dad0d04fSFariya Fatima 					__func__);
296dad0d04fSFariya Fatima 			} else {
297dad0d04fSFariya Fatima 				rsi_dbg(ERR_ZONE,
298dad0d04fSFariya Fatima 					"%s: Firmware Status is 0x%x\n",
299dad0d04fSFariya Fatima 					__func__, fw_status);
300dad0d04fSFariya Fatima 				rsi_sdio_ack_intr(common->priv,
301*abd131a1SMarek Vasut 						  BIT(FW_ASSERT_IND));
302dad0d04fSFariya Fatima 			}
303dad0d04fSFariya Fatima 
304dad0d04fSFariya Fatima 			common->fsm_state = FSM_CARD_NOT_READY;
305dad0d04fSFariya Fatima 
306*abd131a1SMarek Vasut 			isr_status &= ~BIT(FW_ASSERT_IND);
307*abd131a1SMarek Vasut 		}
308*abd131a1SMarek Vasut 
309*abd131a1SMarek Vasut 		if (isr_status & BIT(MSDU_PKT_PENDING)) {
310dad0d04fSFariya Fatima 			rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");
311dad0d04fSFariya Fatima 			dev->rx_info.total_sdio_msdu_pending_intr++;
312dad0d04fSFariya Fatima 
313dad0d04fSFariya Fatima 			status = rsi_process_pkt(common);
314dad0d04fSFariya Fatima 			if (status) {
315*abd131a1SMarek Vasut 				rsi_dbg(ERR_ZONE, "%s: Failed to read pkt\n",
316dad0d04fSFariya Fatima 					__func__);
3176c409cadSKarun Eagalapati 				mutex_unlock(&common->rx_lock);
318dad0d04fSFariya Fatima 				return;
319dad0d04fSFariya Fatima 			}
320*abd131a1SMarek Vasut 
321*abd131a1SMarek Vasut 			isr_status &= ~BIT(MSDU_PKT_PENDING);
322*abd131a1SMarek Vasut 		}
323*abd131a1SMarek Vasut 
324*abd131a1SMarek Vasut 		if (isr_status) {
325dad0d04fSFariya Fatima 			rsi_sdio_ack_intr(common->priv, isr_status);
326dad0d04fSFariya Fatima 			dev->rx_info.total_sdio_unknown_intr++;
327dad0d04fSFariya Fatima 			isr_status = 0;
328*abd131a1SMarek Vasut 			rsi_dbg(ISR_ZONE, "Unknown Interrupt %x\n",
329dad0d04fSFariya Fatima 				isr_status);
330dad0d04fSFariya Fatima 		}
331*abd131a1SMarek Vasut 
3326c409cadSKarun Eagalapati 		mutex_unlock(&common->rx_lock);
333dad0d04fSFariya Fatima 	} while (1);
334dad0d04fSFariya Fatima }
335dad0d04fSFariya Fatima 
33623e414ccSKarun Eagalapati /* This function is used to read buffer status register and
33723e414ccSKarun Eagalapati  * set relevant fields in rsi_91x_sdiodev struct.
338dad0d04fSFariya Fatima  */
33923e414ccSKarun Eagalapati int rsi_sdio_check_buffer_status(struct rsi_hw *adapter, u8 q_num)
340dad0d04fSFariya Fatima {
341dad0d04fSFariya Fatima 	struct rsi_common *common = adapter->priv;
342dad0d04fSFariya Fatima 	struct rsi_91x_sdiodev *dev =
343dad0d04fSFariya Fatima 		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
344dad0d04fSFariya Fatima 	u8 buf_status = 0;
345dad0d04fSFariya Fatima 	int status = 0;
346d64dd2a1SKarun Eagalapati 	static int counter = 4;
347dad0d04fSFariya Fatima 
348d64dd2a1SKarun Eagalapati 	if (!dev->buff_status_updated && counter) {
349d64dd2a1SKarun Eagalapati 		counter--;
350d64dd2a1SKarun Eagalapati 		goto out;
351d64dd2a1SKarun Eagalapati 	}
352d64dd2a1SKarun Eagalapati 
353d64dd2a1SKarun Eagalapati 	dev->buff_status_updated = false;
354dad0d04fSFariya Fatima 	status = rsi_sdio_read_register(common->priv,
355dad0d04fSFariya Fatima 					RSI_DEVICE_BUFFER_STATUS_REGISTER,
356dad0d04fSFariya Fatima 					&buf_status);
357dad0d04fSFariya Fatima 
358dad0d04fSFariya Fatima 	if (status) {
359dad0d04fSFariya Fatima 		rsi_dbg(ERR_ZONE,
360dad0d04fSFariya Fatima 			"%s: Failed to read status register\n", __func__);
361dad0d04fSFariya Fatima 		return -1;
362dad0d04fSFariya Fatima 	}
363dad0d04fSFariya Fatima 
364dad0d04fSFariya Fatima 	if (buf_status & (BIT(PKT_MGMT_BUFF_FULL))) {
365dad0d04fSFariya Fatima 		if (!dev->rx_info.mgmt_buffer_full)
366dad0d04fSFariya Fatima 			dev->rx_info.mgmt_buf_full_counter++;
367dad0d04fSFariya Fatima 		dev->rx_info.mgmt_buffer_full = true;
368dad0d04fSFariya Fatima 	} else {
369dad0d04fSFariya Fatima 		dev->rx_info.mgmt_buffer_full = false;
370dad0d04fSFariya Fatima 	}
371dad0d04fSFariya Fatima 
372dad0d04fSFariya Fatima 	if (buf_status & (BIT(PKT_BUFF_FULL))) {
373dad0d04fSFariya Fatima 		if (!dev->rx_info.buffer_full)
374dad0d04fSFariya Fatima 			dev->rx_info.buf_full_counter++;
375dad0d04fSFariya Fatima 		dev->rx_info.buffer_full = true;
376dad0d04fSFariya Fatima 	} else {
377dad0d04fSFariya Fatima 		dev->rx_info.buffer_full = false;
378dad0d04fSFariya Fatima 	}
379dad0d04fSFariya Fatima 
380dad0d04fSFariya Fatima 	if (buf_status & (BIT(PKT_BUFF_SEMI_FULL))) {
381dad0d04fSFariya Fatima 		if (!dev->rx_info.semi_buffer_full)
382dad0d04fSFariya Fatima 			dev->rx_info.buf_semi_full_counter++;
383dad0d04fSFariya Fatima 		dev->rx_info.semi_buffer_full = true;
384dad0d04fSFariya Fatima 	} else {
385dad0d04fSFariya Fatima 		dev->rx_info.semi_buffer_full = false;
386dad0d04fSFariya Fatima 	}
387dad0d04fSFariya Fatima 
388d64dd2a1SKarun Eagalapati 	if (dev->rx_info.mgmt_buffer_full || dev->rx_info.buf_full_counter)
389d64dd2a1SKarun Eagalapati 		counter = 1;
390d64dd2a1SKarun Eagalapati 	else
391d64dd2a1SKarun Eagalapati 		counter = 4;
392d64dd2a1SKarun Eagalapati 
393d64dd2a1SKarun Eagalapati out:
394dad0d04fSFariya Fatima 	if ((q_num == MGMT_SOFT_Q) && (dev->rx_info.mgmt_buffer_full))
395dad0d04fSFariya Fatima 		return QUEUE_FULL;
396dad0d04fSFariya Fatima 
397d64dd2a1SKarun Eagalapati 	if ((q_num < MGMT_SOFT_Q) && (dev->rx_info.buffer_full))
398dad0d04fSFariya Fatima 		return QUEUE_FULL;
399dad0d04fSFariya Fatima 
400dad0d04fSFariya Fatima 	return QUEUE_NOT_FULL;
401dad0d04fSFariya Fatima }
402dad0d04fSFariya Fatima 
403dad0d04fSFariya Fatima /**
404dad0d04fSFariya Fatima  * rsi_sdio_determine_event_timeout() - This Function determines the event
405dad0d04fSFariya Fatima  *					timeout duration.
406dad0d04fSFariya Fatima  * @adapter: Pointer to the adapter structure.
407dad0d04fSFariya Fatima  *
408dad0d04fSFariya Fatima  * Return: timeout duration is returned.
409dad0d04fSFariya Fatima  */
410dad0d04fSFariya Fatima int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter)
411dad0d04fSFariya Fatima {
412dad0d04fSFariya Fatima 	struct rsi_91x_sdiodev *dev =
413dad0d04fSFariya Fatima 		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
414dad0d04fSFariya Fatima 
415dad0d04fSFariya Fatima 	/* Once buffer full is seen, event timeout to occur every 2 msecs */
416dad0d04fSFariya Fatima 	if (dev->rx_info.buffer_full)
417dad0d04fSFariya Fatima 		return 2;
418dad0d04fSFariya Fatima 
419dad0d04fSFariya Fatima 	return EVENT_WAIT_FOREVER;
420dad0d04fSFariya Fatima }
421