1e24c1f86SMichael Straube // SPDX-License-Identifier: GPL-2.0
22865d42cSLarry Finger /******************************************************************************
32865d42cSLarry Finger  * rtl871x_io.c
42865d42cSLarry Finger  *
52865d42cSLarry Finger  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
62865d42cSLarry Finger  * Linux device driver for RTL8192SU
72865d42cSLarry Finger  *
82865d42cSLarry Finger  * Modifications for inclusion into the Linux staging tree are
92865d42cSLarry Finger  * Copyright(c) 2010 Larry Finger. All rights reserved.
102865d42cSLarry Finger  *
112865d42cSLarry Finger  * Contact information:
122865d42cSLarry Finger  * WLAN FAE <wlanfae@realtek.com>
132865d42cSLarry Finger  * Larry Finger <Larry.Finger@lwfinger.net>
142865d42cSLarry Finger  *
152865d42cSLarry Finger  ******************************************************************************/
162865d42cSLarry Finger /*
172865d42cSLarry Finger  *
182865d42cSLarry Finger  * The purpose of rtl871x_io.c
192865d42cSLarry Finger  *
202865d42cSLarry Finger  * a. provides the API
212865d42cSLarry Finger  * b. provides the protocol engine
222865d42cSLarry Finger  * c. provides the software interface between caller and the hardware interface
232865d42cSLarry Finger  *
242865d42cSLarry Finger  * For r8712u, both sync/async operations are provided.
252865d42cSLarry Finger  *
262865d42cSLarry Finger  * Only sync read/write_mem operations are provided.
272865d42cSLarry Finger  *
282865d42cSLarry Finger  */
292865d42cSLarry Finger 
302865d42cSLarry Finger #define _RTL871X_IO_C_
312865d42cSLarry Finger 
322865d42cSLarry Finger #include "osdep_service.h"
332865d42cSLarry Finger #include "drv_types.h"
342865d42cSLarry Finger #include "rtl871x_io.h"
352865d42cSLarry Finger #include "osdep_intf.h"
362865d42cSLarry Finger #include "usb_ops.h"
372865d42cSLarry Finger 
_init_intf_hdl(struct _adapter * padapter,struct intf_hdl * pintf_hdl)382865d42cSLarry Finger static uint _init_intf_hdl(struct _adapter *padapter,
392865d42cSLarry Finger 			   struct intf_hdl *pintf_hdl)
402865d42cSLarry Finger {
412865d42cSLarry Finger 	struct	intf_priv	*pintf_priv;
422865d42cSLarry Finger 	void (*set_intf_option)(u32 *poption) = NULL;
432865d42cSLarry Finger 	void (*set_intf_funs)(struct intf_hdl *pintf_hdl);
442865d42cSLarry Finger 	void (*set_intf_ops)(struct _io_ops	*pops);
452865d42cSLarry Finger 	uint (*init_intf_priv)(struct intf_priv *pintfpriv);
462865d42cSLarry Finger 
472865d42cSLarry Finger 	set_intf_option = &(r8712_usb_set_intf_option);
482865d42cSLarry Finger 	set_intf_funs = &(r8712_usb_set_intf_funs);
492865d42cSLarry Finger 	set_intf_ops = &r8712_usb_set_intf_ops;
502865d42cSLarry Finger 	init_intf_priv = &r8712_usb_init_intf_priv;
5191d435feSVitaly Osipov 	pintf_priv = pintf_hdl->pintfpriv = kmalloc(sizeof(struct intf_priv),
5291d435feSVitaly Osipov 						    GFP_ATOMIC);
530e934ce2SMichael Straube 	if (!pintf_priv)
542865d42cSLarry Finger 		goto _init_intf_hdl_fail;
552865d42cSLarry Finger 	pintf_hdl->adapter = (u8 *)padapter;
562865d42cSLarry Finger 	set_intf_option(&pintf_hdl->intf_option);
572865d42cSLarry Finger 	set_intf_funs(pintf_hdl);
582865d42cSLarry Finger 	set_intf_ops(&pintf_hdl->io_ops);
59cbe5d64fSDafna Hirschfeld 	pintf_priv->intf_dev = (u8 *)&padapter->dvobjpriv;
602865d42cSLarry Finger 	if (init_intf_priv(pintf_priv) == _FAIL)
612865d42cSLarry Finger 		goto _init_intf_hdl_fail;
622865d42cSLarry Finger 	return _SUCCESS;
632865d42cSLarry Finger _init_intf_hdl_fail:
6440083865SAlexander Beregalov 	kfree(pintf_priv);
652865d42cSLarry Finger 	return _FAIL;
662865d42cSLarry Finger }
672865d42cSLarry Finger 
_unload_intf_hdl(struct intf_priv * pintfpriv)682865d42cSLarry Finger static void _unload_intf_hdl(struct intf_priv *pintfpriv)
692865d42cSLarry Finger {
702865d42cSLarry Finger 	void (*unload_intf_priv)(struct intf_priv *pintfpriv);
712865d42cSLarry Finger 
722865d42cSLarry Finger 	unload_intf_priv = &r8712_usb_unload_intf_priv;
732865d42cSLarry Finger 	unload_intf_priv(pintfpriv);
7440083865SAlexander Beregalov 	kfree(pintfpriv);
752865d42cSLarry Finger }
762865d42cSLarry Finger 
register_intf_hdl(u8 * dev,struct intf_hdl * pintfhdl)772865d42cSLarry Finger static uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl)
782865d42cSLarry Finger {
792865d42cSLarry Finger 	struct _adapter *adapter = (struct _adapter *)dev;
802865d42cSLarry Finger 
812865d42cSLarry Finger 	pintfhdl->intf_option = 0;
822865d42cSLarry Finger 	pintfhdl->adapter = dev;
83cbe5d64fSDafna Hirschfeld 	pintfhdl->intf_dev = (u8 *)&adapter->dvobjpriv;
84366ba427STapasweni Pathak 	if (!_init_intf_hdl(adapter, pintfhdl))
852865d42cSLarry Finger 		goto register_intf_hdl_fail;
862865d42cSLarry Finger 	return _SUCCESS;
872865d42cSLarry Finger register_intf_hdl_fail:
882865d42cSLarry Finger 	return false;
892865d42cSLarry Finger }
902865d42cSLarry Finger 
unregister_intf_hdl(struct intf_hdl * pintfhdl)912865d42cSLarry Finger static  void unregister_intf_hdl(struct intf_hdl *pintfhdl)
922865d42cSLarry Finger {
932865d42cSLarry Finger 	_unload_intf_hdl(pintfhdl->pintfpriv);
942865d42cSLarry Finger 	memset((u8 *)pintfhdl, 0, sizeof(struct intf_hdl));
952865d42cSLarry Finger }
962865d42cSLarry Finger 
r8712_alloc_io_queue(struct _adapter * adapter)972865d42cSLarry Finger uint r8712_alloc_io_queue(struct _adapter *adapter)
982865d42cSLarry Finger {
992865d42cSLarry Finger 	u32 i;
1002865d42cSLarry Finger 	struct io_queue *pio_queue;
1012865d42cSLarry Finger 	struct io_req *pio_req;
1022865d42cSLarry Finger 
103bd9dc62cSVitaly Osipov 	pio_queue = kmalloc(sizeof(*pio_queue), GFP_ATOMIC);
1049155c924SBhumika Goyal 	if (!pio_queue)
1052865d42cSLarry Finger 		goto alloc_io_queue_fail;
106534c4acdSJames A Shackleford 	INIT_LIST_HEAD(&pio_queue->free_ioreqs);
107534c4acdSJames A Shackleford 	INIT_LIST_HEAD(&pio_queue->processing);
108534c4acdSJames A Shackleford 	INIT_LIST_HEAD(&pio_queue->pending);
1092865d42cSLarry Finger 	spin_lock_init(&pio_queue->lock);
1100234961dSHariprasad Kelam 	pio_queue->pallocated_free_ioreqs_buf = kzalloc(NUM_IOREQ *
11191d435feSVitaly Osipov 						(sizeof(struct io_req)) + 4,
11291d435feSVitaly Osipov 						GFP_ATOMIC);
1132865d42cSLarry Finger 	if ((pio_queue->pallocated_free_ioreqs_buf) == NULL)
1142865d42cSLarry Finger 		goto alloc_io_queue_fail;
1152865d42cSLarry Finger 	pio_queue->free_ioreqs_buf = pio_queue->pallocated_free_ioreqs_buf + 4
1162865d42cSLarry Finger 			- ((addr_t)(pio_queue->pallocated_free_ioreqs_buf)
1172865d42cSLarry Finger 			& 3);
1182865d42cSLarry Finger 	pio_req = (struct io_req *)(pio_queue->free_ioreqs_buf);
1192865d42cSLarry Finger 	for (i = 0; i < NUM_IOREQ; i++) {
120534c4acdSJames A Shackleford 		INIT_LIST_HEAD(&pio_req->list);
121fdfbf789SJames A Shackleford 		list_add_tail(&pio_req->list, &pio_queue->free_ioreqs);
1222865d42cSLarry Finger 		pio_req++;
1232865d42cSLarry Finger 	}
124cbe5d64fSDafna Hirschfeld 	if ((register_intf_hdl((u8 *)adapter, &pio_queue->intf)) == _FAIL)
1252865d42cSLarry Finger 		goto alloc_io_queue_fail;
1262865d42cSLarry Finger 	adapter->pio_queue = pio_queue;
1272865d42cSLarry Finger 	return _SUCCESS;
1282865d42cSLarry Finger alloc_io_queue_fail:
1292865d42cSLarry Finger 	if (pio_queue) {
1302865d42cSLarry Finger 		kfree(pio_queue->pallocated_free_ioreqs_buf);
131646da830STapasweni Pathak 		kfree(pio_queue);
1322865d42cSLarry Finger 	}
1332865d42cSLarry Finger 	adapter->pio_queue = NULL;
1342865d42cSLarry Finger 	return _FAIL;
1352865d42cSLarry Finger }
1362865d42cSLarry Finger 
r8712_free_io_queue(struct _adapter * adapter)1372865d42cSLarry Finger void r8712_free_io_queue(struct _adapter *adapter)
1382865d42cSLarry Finger {
1390b2ea2c7SShivani Bhardwaj 	struct io_queue *pio_queue = adapter->pio_queue;
1402865d42cSLarry Finger 
1412865d42cSLarry Finger 	if (pio_queue) {
1422865d42cSLarry Finger 		kfree(pio_queue->pallocated_free_ioreqs_buf);
1432865d42cSLarry Finger 		adapter->pio_queue = NULL;
1442865d42cSLarry Finger 		unregister_intf_hdl(&pio_queue->intf);
145646da830STapasweni Pathak 		kfree(pio_queue);
1462865d42cSLarry Finger 	}
1472865d42cSLarry Finger }
148