Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /******************************************************************************
0003  * rtl871x_io.c
0004  *
0005  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
0006  * Linux device driver for RTL8192SU
0007  *
0008  * Modifications for inclusion into the Linux staging tree are
0009  * Copyright(c) 2010 Larry Finger. All rights reserved.
0010  *
0011  * Contact information:
0012  * WLAN FAE <wlanfae@realtek.com>
0013  * Larry Finger <Larry.Finger@lwfinger.net>
0014  *
0015  ******************************************************************************/
0016 /*
0017  *
0018  * The purpose of rtl871x_io.c
0019  *
0020  * a. provides the API
0021  * b. provides the protocol engine
0022  * c. provides the software interface between caller and the hardware interface
0023  *
0024  * For r8712u, both sync/async operations are provided.
0025  *
0026  * Only sync read/write_mem operations are provided.
0027  *
0028  */
0029 
0030 #define _RTL871X_IO_C_
0031 
0032 #include "osdep_service.h"
0033 #include "drv_types.h"
0034 #include "rtl871x_io.h"
0035 #include "osdep_intf.h"
0036 #include "usb_ops.h"
0037 
0038 static uint _init_intf_hdl(struct _adapter *padapter,
0039                struct intf_hdl *pintf_hdl)
0040 {
0041     struct  intf_priv   *pintf_priv;
0042     void (*set_intf_option)(u32 *poption) = NULL;
0043     void (*set_intf_funs)(struct intf_hdl *pintf_hdl);
0044     void (*set_intf_ops)(struct _io_ops *pops);
0045     uint (*init_intf_priv)(struct intf_priv *pintfpriv);
0046 
0047     set_intf_option = &(r8712_usb_set_intf_option);
0048     set_intf_funs = &(r8712_usb_set_intf_funs);
0049     set_intf_ops = &r8712_usb_set_intf_ops;
0050     init_intf_priv = &r8712_usb_init_intf_priv;
0051     pintf_priv = pintf_hdl->pintfpriv = kmalloc(sizeof(struct intf_priv),
0052                             GFP_ATOMIC);
0053     if (!pintf_priv)
0054         goto _init_intf_hdl_fail;
0055     pintf_hdl->adapter = (u8 *)padapter;
0056     set_intf_option(&pintf_hdl->intf_option);
0057     set_intf_funs(pintf_hdl);
0058     set_intf_ops(&pintf_hdl->io_ops);
0059     pintf_priv->intf_dev = (u8 *)&padapter->dvobjpriv;
0060     if (init_intf_priv(pintf_priv) == _FAIL)
0061         goto _init_intf_hdl_fail;
0062     return _SUCCESS;
0063 _init_intf_hdl_fail:
0064     kfree(pintf_priv);
0065     return _FAIL;
0066 }
0067 
0068 static void _unload_intf_hdl(struct intf_priv *pintfpriv)
0069 {
0070     void (*unload_intf_priv)(struct intf_priv *pintfpriv);
0071 
0072     unload_intf_priv = &r8712_usb_unload_intf_priv;
0073     unload_intf_priv(pintfpriv);
0074     kfree(pintfpriv);
0075 }
0076 
0077 static uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl)
0078 {
0079     struct _adapter *adapter = (struct _adapter *)dev;
0080 
0081     pintfhdl->intf_option = 0;
0082     pintfhdl->adapter = dev;
0083     pintfhdl->intf_dev = (u8 *)&adapter->dvobjpriv;
0084     if (!_init_intf_hdl(adapter, pintfhdl))
0085         goto register_intf_hdl_fail;
0086     return _SUCCESS;
0087 register_intf_hdl_fail:
0088     return false;
0089 }
0090 
0091 static  void unregister_intf_hdl(struct intf_hdl *pintfhdl)
0092 {
0093     _unload_intf_hdl(pintfhdl->pintfpriv);
0094     memset((u8 *)pintfhdl, 0, sizeof(struct intf_hdl));
0095 }
0096 
0097 uint r8712_alloc_io_queue(struct _adapter *adapter)
0098 {
0099     u32 i;
0100     struct io_queue *pio_queue;
0101     struct io_req *pio_req;
0102 
0103     pio_queue = kmalloc(sizeof(*pio_queue), GFP_ATOMIC);
0104     if (!pio_queue)
0105         goto alloc_io_queue_fail;
0106     INIT_LIST_HEAD(&pio_queue->free_ioreqs);
0107     INIT_LIST_HEAD(&pio_queue->processing);
0108     INIT_LIST_HEAD(&pio_queue->pending);
0109     spin_lock_init(&pio_queue->lock);
0110     pio_queue->pallocated_free_ioreqs_buf = kzalloc(NUM_IOREQ *
0111                         (sizeof(struct io_req)) + 4,
0112                         GFP_ATOMIC);
0113     if ((pio_queue->pallocated_free_ioreqs_buf) == NULL)
0114         goto alloc_io_queue_fail;
0115     pio_queue->free_ioreqs_buf = pio_queue->pallocated_free_ioreqs_buf + 4
0116             - ((addr_t)(pio_queue->pallocated_free_ioreqs_buf)
0117             & 3);
0118     pio_req = (struct io_req *)(pio_queue->free_ioreqs_buf);
0119     for (i = 0; i < NUM_IOREQ; i++) {
0120         INIT_LIST_HEAD(&pio_req->list);
0121         list_add_tail(&pio_req->list, &pio_queue->free_ioreqs);
0122         pio_req++;
0123     }
0124     if ((register_intf_hdl((u8 *)adapter, &pio_queue->intf)) == _FAIL)
0125         goto alloc_io_queue_fail;
0126     adapter->pio_queue = pio_queue;
0127     return _SUCCESS;
0128 alloc_io_queue_fail:
0129     if (pio_queue) {
0130         kfree(pio_queue->pallocated_free_ioreqs_buf);
0131         kfree(pio_queue);
0132     }
0133     adapter->pio_queue = NULL;
0134     return _FAIL;
0135 }
0136 
0137 void r8712_free_io_queue(struct _adapter *adapter)
0138 {
0139     struct io_queue *pio_queue = adapter->pio_queue;
0140 
0141     if (pio_queue) {
0142         kfree(pio_queue->pallocated_free_ioreqs_buf);
0143         adapter->pio_queue = NULL;
0144         unregister_intf_hdl(&pio_queue->intf);
0145         kfree(pio_queue);
0146     }
0147 }