// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
* rtl871x_cmd.c
*
* Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
* Linux device driver for RTL8192SU
*
* Modifications for inclusion into the Linux staging tree are
* Copyright(c) 2010 Larry Finger. All rights reserved.
*
* Contact information:
* WLAN FAE <wlanfae@realtek.com>
* Larry Finger <Larry.Finger@lwfinger.net>
*
******************************************************************************/
#define _RTL871X_CMD_C_
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kref.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/circ_buf.h>
#include <linux/uaccess.h>
#include <asm/byteorder.h>
#include <linux/atomic.h>
#include <linux/semaphore.h>
#include <linux/rtnetlink.h>
#include "osdep_service.h"
#include "drv_types.h"
#include "recv_osdep.h"
#include "mlme_osdep.h"
/*
* Caller and the r8712_cmd_thread can protect cmd_q by spin_lock.
* No irqsave is necessary.
*/
static sint _init_cmd_priv(struct cmd_priv *pcmdpriv)
{
init_completion(&pcmdpriv->cmd_queue_comp);
init_completion(&pcmdpriv->terminate_cmdthread_comp);
_init_queue(&(pcmdpriv->cmd_queue));
/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
pcmdpriv->cmd_seq = 1;
pcmdpriv->cmd_allocated_buf = kmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
GFP_ATOMIC);
if (!pcmdpriv->cmd_allocated_buf)
return _FAIL;
pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ -
((addr_t)(pcmdpriv->cmd_allocated_buf) &
(CMDBUFF_ALIGN_SZ - 1));
pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC);
if (!pcmdpriv->rsp_allocated_buf) {
kfree(pcmdpriv->cmd_allocated_buf);
pcmdpriv->cmd_allocated_buf = NULL;
return _FAIL;
}
pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 -
((addr_t)(pcmdpriv->rsp_allocated_buf) & 3);
pcmdpriv->cmd_issued_cnt = 0;
pcmdpriv->cmd_done_cnt = 0;
pcmdpriv->rsp_cnt = 0;
return _SUCCESS;
}
static sint _init_evt_priv(struct evt_priv *pevtpriv)
{
/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
pevtpriv->event_seq = 0;
pevtpriv->evt_allocated_buf = kmalloc(MAX_EVTSZ + 4, GFP_ATOMIC);
if (!pevtpriv->evt_allocated_buf)
return _FAIL;
pevtpriv->evt_buf = pevtpriv->evt_allocated_buf + 4 -
((addr_t)(pevtpriv->evt_allocated_buf) & 3);
pevtpriv->evt_done_cnt = 0;
return _SUCCESS;
}
static void _free_evt_priv(struct evt_priv *pevtpriv)
{
kfree(pevtpriv->evt_allocated_buf);
}
static void _free_cmd_priv(struct cmd_priv *pcmdpriv)
{
if (pcmdpriv) {
kfree(pcmdpriv->cmd_allocated_buf);
kfree(pcmdpriv->rsp_allocated_buf);
}
}
/*
* Calling Context:
*
* _enqueue_cmd can only be called between kernel thread,
* since only spin_lock is used.
*
* ISR/Call-Back functions can't call this sub-function.
*
*/
static sint _enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
{
unsigned long irqL;
if (!obj)
return _SUCCESS;
spin_lock_irqsave(&queue->lock, irqL);
list_add_tail(&obj->list, &queue->queue);
spin_unlock_irqrestore(&queue->lock, irqL);
return _SUCCESS;
}
static struct cmd_obj *_dequeue_cmd(struct __queue *queue)
{
unsigned long irqL;
struct cmd_obj *obj;
spin_lock_irqsave(&queue->lock, irqL);
obj = list_first_entry_or_null(&queue->queue,
struct cmd_obj, list);
if (obj)
list_del_init(&obj->list);
spin_unlock_irqrestore(&queue->lock, irqL);
return obj;
}
u32 r8712_init_cmd_priv(struct cmd_priv *pcmdpriv)
{
return _init_cmd_priv(pcmdpriv);
}
u32 r8712_init_evt_priv(struct evt_priv *pevtpriv)
{
return _init_evt_priv(pevtpriv);
}
void r8712_free_evt_priv(struct evt_priv *pevtpriv)
{
_free_evt_priv(pevtpriv);
}
void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv)
{
_free_cmd_priv(pcmdpriv);
}
u32 r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
{
int res;
if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
return _FAIL;
res = _enqueue_cmd(&pcmdpriv->cmd_queue, obj);
complete(&pcmdpriv->cmd_queue_comp);
return res;
}
u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, <