/******************************************************************************
|
*
|
* Copyright(c) 2019 Realtek Corporation. All rights reserved.
|
*
|
* This program is free software; you can redistribute it and/or modify it
|
* under the terms of version 2 of the GNU General Public License as
|
* published by the Free Software Foundation.
|
*
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
* more details.
|
*
|
******************************************************************************/
|
|
#include "fwdl.h"
|
#include "fwofld.h"
|
|
static u32 get_io_ofld_cap(struct mac_ax_adapter *adapter, u32 *val)
|
{
|
*val |= FW_CAP_IO_OFLD;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_get_fw_cap(struct mac_ax_adapter *adapter, u32 *val)
|
{
|
*val = 0;
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACFWNONRDY;
|
|
get_io_ofld_cap(adapter, val);
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_reset_fwofld_state(struct mac_ax_adapter *adapter, u8 op)
|
{
|
switch (op) {
|
case FW_OFLD_OP_DUMP_EFUSE:
|
adapter->sm.efuse_ofld = MAC_AX_OFLD_H2C_IDLE;
|
break;
|
|
case FW_OFLD_OP_PACKET_OFLD:
|
adapter->sm.pkt_ofld = MAC_AX_OFLD_H2C_IDLE;
|
break;
|
|
case FW_OFLD_OP_READ_OFLD:
|
adapter->sm.read_request = MAC_AX_OFLD_REQ_IDLE;
|
adapter->sm.read_h2c = MAC_AX_OFLD_H2C_IDLE;
|
break;
|
|
case FW_OFLD_OP_WRITE_OFLD:
|
adapter->sm.write_request = MAC_AX_OFLD_REQ_IDLE;
|
adapter->sm.write_h2c = MAC_AX_OFLD_H2C_IDLE;
|
break;
|
|
case FW_OFLD_OP_CONF_OFLD:
|
adapter->sm.conf_request = MAC_AX_OFLD_REQ_IDLE;
|
adapter->sm.conf_h2c = MAC_AX_OFLD_H2C_IDLE;
|
break;
|
case FW_OFLD_OP_CH_SWITCH:
|
adapter->sm.ch_switch = MAC_AX_OFLD_H2C_IDLE;
|
break;
|
|
default:
|
return MACNOITEM;
|
}
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_check_fwofld_done(struct mac_ax_adapter *adapter, u8 op)
|
{
|
struct mac_ax_pkt_ofld_info *ofld_info = &adapter->pkt_ofld_info;
|
|
switch (op) {
|
case FW_OFLD_OP_DUMP_EFUSE:
|
if (adapter->sm.efuse_ofld == MAC_AX_OFLD_H2C_IDLE)
|
return MACSUCCESS;
|
break;
|
|
case FW_OFLD_OP_PACKET_OFLD:
|
if (ofld_info->last_op == PKT_OFLD_OP_READ) {
|
if (adapter->sm.pkt_ofld == MAC_AX_OFLD_H2C_DONE)
|
return MACSUCCESS;
|
} else {
|
if (adapter->sm.pkt_ofld == MAC_AX_OFLD_H2C_IDLE)
|
return MACSUCCESS;
|
}
|
break;
|
case FW_OFLD_OP_READ_OFLD:
|
if (adapter->sm.read_h2c == MAC_AX_OFLD_H2C_DONE)
|
return MACSUCCESS;
|
break;
|
case FW_OFLD_OP_WRITE_OFLD:
|
if (adapter->sm.write_h2c == MAC_AX_OFLD_H2C_IDLE)
|
return MACSUCCESS;
|
break;
|
case FW_OFLD_OP_CONF_OFLD:
|
if (adapter->sm.conf_h2c == MAC_AX_OFLD_H2C_IDLE)
|
return MACSUCCESS;
|
break;
|
case FW_OFLD_OP_CH_SWITCH:
|
if (adapter->sm.ch_switch == MAC_AX_OFLD_H2C_IDLE ||
|
adapter->sm.ch_switch == MAC_AX_CH_SWITCH_GET_RPT)
|
return MACSUCCESS;
|
break;
|
default:
|
return MACNOITEM;
|
}
|
|
return MACPROCBUSY;
|
}
|
|
static u32 cnv_write_ofld_state(struct mac_ax_adapter *adapter, u8 dest)
|
{
|
u8 state;
|
|
state = adapter->sm.write_request;
|
|
if (state > MAC_AX_OFLD_REQ_CLEANED)
|
return MACPROCERR;
|
|
if (dest == MAC_AX_OFLD_REQ_IDLE) {
|
if (state != MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_CLEANED) {
|
if (state == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_CREATED) {
|
if (state == MAC_AX_OFLD_REQ_IDLE ||
|
state == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_H2C_SENT) {
|
if (state != MAC_AX_OFLD_REQ_CREATED)
|
return MACPROCERR;
|
}
|
|
adapter->sm.write_request = dest;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_clear_write_request(struct mac_ax_adapter *adapter)
|
{
|
if (adapter->sm.write_request == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
|
if (cnv_write_ofld_state(adapter, MAC_AX_OFLD_REQ_CLEANED)
|
!= MACSUCCESS)
|
return MACPROCERR;
|
|
PLTFM_FREE(adapter->write_ofld_info.buf,
|
adapter->write_ofld_info.buf_size);
|
adapter->write_ofld_info.buf = NULL;
|
adapter->write_ofld_info.buf_wptr = NULL;
|
adapter->write_ofld_info.last_req = NULL;
|
adapter->write_ofld_info.buf_size = 0;
|
adapter->write_ofld_info.avl_buf_size = 0;
|
adapter->write_ofld_info.used_size = 0;
|
adapter->write_ofld_info.req_num = 0;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_add_write_request(struct mac_ax_adapter *adapter,
|
struct mac_ax_write_req *req, u8 *value, u8 *mask)
|
{
|
struct mac_ax_write_ofld_info *ofld_info = &adapter->write_ofld_info;
|
struct fwcmd_write_ofld_req *write_ptr;
|
u32 data_len = 0;
|
u8 state;
|
|
state = adapter->sm.write_request;
|
|
if (!(state == MAC_AX_OFLD_REQ_CREATED ||
|
state == MAC_AX_OFLD_REQ_CLEANED)) {
|
return MACPROCERR;
|
}
|
|
if (!ofld_info->buf) {
|
ofld_info->buf = (u8 *)PLTFM_MALLOC(WRITE_OFLD_MAX_LEN);
|
if (!ofld_info->buf)
|
return MACNPTR;
|
ofld_info->buf_wptr = ofld_info->buf;
|
ofld_info->buf_size = WRITE_OFLD_MAX_LEN;
|
ofld_info->avl_buf_size = WRITE_OFLD_MAX_LEN;
|
ofld_info->used_size = 0;
|
ofld_info->req_num = 0;
|
}
|
|
data_len = sizeof(struct mac_ax_write_req);
|
data_len += req->value_len;
|
if (req->mask_en == 1)
|
data_len += req->value_len;
|
|
if (ofld_info->avl_buf_size < data_len)
|
return MACNOBUF;
|
|
if (!value)
|
return MACNPTR;
|
|
if (req->mask_en == 1 && !mask)
|
return MACNPTR;
|
|
if (cnv_write_ofld_state(adapter,
|
MAC_AX_OFLD_REQ_CREATED) != MACSUCCESS)
|
return MACPROCERR;
|
|
if (ofld_info->req_num != 0)
|
ofld_info->last_req->ls = 0;
|
|
ofld_info->last_req = (struct mac_ax_write_req *)ofld_info->buf_wptr;
|
|
req->ls = 1;
|
|
write_ptr = (struct fwcmd_write_ofld_req *)ofld_info->buf_wptr;
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(req->value_len,
|
FWCMD_H2C_WRITE_OFLD_REQ_VALUE_LEN) |
|
SET_WORD(req->ofld_id,
|
FWCMD_H2C_WRITE_OFLD_REQ_OFLD_ID) |
|
SET_WORD(req->entry_num,
|
FWCMD_H2C_WRITE_OFLD_REQ_ENTRY_NUM) |
|
req->polling | req->mask_en | req->ls
|
);
|
|
write_ptr->dword1 =
|
cpu_to_le32(SET_WORD(req->offset,
|
FWCMD_H2C_WRITE_OFLD_REQ_OFFSET)
|
);
|
|
ofld_info->buf_wptr += sizeof(struct mac_ax_write_req);
|
ofld_info->avl_buf_size -= sizeof(struct mac_ax_write_req);
|
ofld_info->used_size += sizeof(struct mac_ax_write_req);
|
|
PLTFM_MEMCPY(ofld_info->buf_wptr, value, req->value_len);
|
|
ofld_info->buf_wptr += req->value_len;
|
ofld_info->avl_buf_size -= req->value_len;
|
ofld_info->used_size += req->value_len;
|
|
if (req->mask_en == 1) {
|
PLTFM_MEMCPY(ofld_info->buf_wptr, mask, req->value_len);
|
ofld_info->buf_wptr += req->value_len;
|
ofld_info->avl_buf_size -= req->value_len;
|
ofld_info->used_size += req->value_len;
|
}
|
|
ofld_info->req_num++;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_write_ofld(struct mac_ax_adapter *adapter)
|
{
|
u8 *buf;
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct mac_ax_write_ofld_info *ofld_info = &adapter->write_ofld_info;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
if (ofld_info->used_size + FWCMD_HDR_LEN > READ_OFLD_MAX_LEN)
|
return MACBUFSZ;
|
|
if (adapter->sm.write_h2c != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCERR;
|
|
if (adapter->sm.write_request != MAC_AX_OFLD_REQ_CREATED)
|
return MACPROCERR;
|
|
if (cnv_write_ofld_state(adapter,
|
MAC_AX_OFLD_REQ_H2C_SENT) != MACSUCCESS)
|
return MACPROCERR;
|
|
adapter->sm.write_h2c = MAC_AX_OFLD_H2C_SENDING;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_LONG_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, ofld_info->used_size);
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
PLTFM_MEMCPY(buf, ofld_info->buf, ofld_info->used_size);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_WRITE_OFLD,
|
1, 1);
|
|
if (ret)
|
goto fail;
|
|
// return MACSUCCESS if h2c aggregation is enabled and enqueued successfully.
|
// H2C shall be sent by mac_h2c_agg_tx.
|
ret = h2c_agg_enqueue(adapter, h2cb);
|
if (ret == MACSUCCESS)
|
return MACSUCCESS;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx: %d\n", ret);
|
adapter->sm.write_request = MAC_AX_OFLD_REQ_IDLE;
|
adapter->sm.write_h2c = MAC_AX_OFLD_H2C_IDLE;
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
|
if (cnv_write_ofld_state(adapter, MAC_AX_OFLD_REQ_IDLE) != MACSUCCESS)
|
return MACPROCERR;
|
|
h2c_end_flow(adapter);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
static u32 cnv_conf_ofld_state(struct mac_ax_adapter *adapter, u8 dest)
|
{
|
u8 state;
|
|
state = adapter->sm.conf_request;
|
|
if (state > MAC_AX_OFLD_REQ_CLEANED)
|
return MACPROCERR;
|
|
if (dest == MAC_AX_OFLD_REQ_IDLE) {
|
if (state != MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_CLEANED) {
|
if (state == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_CREATED) {
|
if (state == MAC_AX_OFLD_REQ_IDLE ||
|
state == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_H2C_SENT) {
|
if (state != MAC_AX_OFLD_REQ_CREATED)
|
return MACPROCERR;
|
}
|
|
adapter->sm.conf_request = dest;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_clear_conf_request(struct mac_ax_adapter *adapter)
|
{
|
if (adapter->sm.conf_request == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
|
if (cnv_conf_ofld_state(adapter, MAC_AX_OFLD_REQ_CLEANED) !=
|
MACSUCCESS)
|
return MACPROCERR;
|
|
PLTFM_FREE(adapter->conf_ofld_info.buf,
|
adapter->conf_ofld_info.buf_size);
|
adapter->conf_ofld_info.buf = NULL;
|
adapter->conf_ofld_info.buf_wptr = NULL;
|
adapter->conf_ofld_info.buf_size = 0;
|
adapter->conf_ofld_info.avl_buf_size = 0;
|
adapter->conf_ofld_info.used_size = 0;
|
adapter->conf_ofld_info.req_num = 0;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_add_conf_request(struct mac_ax_adapter *adapter,
|
struct mac_ax_conf_ofld_req *req)
|
{
|
struct mac_ax_conf_ofld_info *ofld_info = &adapter->conf_ofld_info;
|
struct fwcmd_conf_ofld_req_cmd *write_ptr;
|
u8 state;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
state = adapter->sm.conf_request;
|
|
if (!(state == MAC_AX_OFLD_REQ_CREATED ||
|
state == MAC_AX_OFLD_REQ_CLEANED)) {
|
return MACPROCERR;
|
}
|
|
if (!ofld_info->buf) {
|
ofld_info->buf = (u8 *)PLTFM_MALLOC(CONF_OFLD_MAX_LEN);
|
if (!ofld_info->buf)
|
return MACNPTR;
|
ofld_info->buf_wptr = ofld_info->buf;
|
ofld_info->buf_size = CONF_OFLD_MAX_LEN;
|
ofld_info->avl_buf_size = CONF_OFLD_MAX_LEN;
|
ofld_info->used_size = 0;
|
ofld_info->req_num = 0;
|
}
|
|
if (ofld_info->avl_buf_size < sizeof(struct mac_ax_conf_ofld_req))
|
return MACNOBUF;
|
|
if (cnv_conf_ofld_state(adapter, MAC_AX_OFLD_REQ_CREATED) != MACSUCCESS)
|
return MACPROCERR;
|
|
write_ptr = (struct fwcmd_conf_ofld_req_cmd *)ofld_info->buf_wptr;
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(req->device,
|
FWCMD_H2C_CONF_OFLD_REQ_CMD_DEVICE)
|
);
|
|
write_ptr->dword1 =
|
cpu_to_le32(SET_WORD(req->req.hioe.hioe_op,
|
FWCMD_H2C_CONF_OFLD_REQ_CMD_HIOE_OP) |
|
SET_WORD(req->req.hioe.inst_type,
|
FWCMD_H2C_CONF_OFLD_REQ_CMD_INST_TYPE) |
|
SET_WORD(req->req.hioe.data_mode,
|
FWCMD_H2C_CONF_OFLD_REQ_CMD_DATA_MODE)
|
);
|
|
write_ptr->dword2 = cpu_to_le32(req->req.hioe.param0.register_addr);
|
|
write_ptr->dword3 =
|
cpu_to_le32(SET_WORD(req->req.hioe.param1.byte_data_h,
|
FWCMD_H2C_CONF_OFLD_REQ_CMD_BYTE_DATA_H) |
|
SET_WORD(req->req.hioe.param2.byte_data_l,
|
FWCMD_H2C_CONF_OFLD_REQ_CMD_BYTE_DATA_L)
|
);
|
|
ofld_info->buf_wptr += sizeof(struct mac_ax_conf_ofld_req);
|
ofld_info->avl_buf_size -= sizeof(struct mac_ax_conf_ofld_req);
|
ofld_info->used_size += sizeof(struct mac_ax_conf_ofld_req);
|
|
ofld_info->req_num++;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_conf_ofld(struct mac_ax_adapter *adapter)
|
{
|
u8 *buf;
|
u32 ret;
|
struct fwcmd_conf_ofld *write_ptr;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct mac_ax_conf_ofld_info *ofld_info = &adapter->conf_ofld_info;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
if (ofld_info->used_size + FWCMD_HDR_LEN > CONF_OFLD_MAX_LEN)
|
return MACBUFSZ;
|
|
if (adapter->sm.conf_h2c != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCERR;
|
|
if (adapter->sm.conf_request != MAC_AX_OFLD_REQ_CREATED)
|
return MACPROCERR;
|
|
if (cnv_conf_ofld_state(adapter,
|
MAC_AX_OFLD_REQ_H2C_SENT) != MACSUCCESS)
|
return MACPROCERR;
|
|
adapter->sm.conf_h2c = MAC_AX_OFLD_H2C_SENDING;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_LONG_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, sizeof(struct mac_ax_conf_ofld_hdr));
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
write_ptr = (struct fwcmd_conf_ofld *)buf;
|
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(ofld_info->req_num,
|
FWCMD_H2C_CONF_OFLD_PATTERN_COUNT));
|
|
buf = h2cb_put(h2cb, ofld_info->used_size);
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
PLTFM_MEMCPY(buf, ofld_info->buf, ofld_info->used_size);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_CONF_OFLD,
|
1, 1);
|
if (ret)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx: %d\n", ret);
|
adapter->sm.conf_request = MAC_AX_OFLD_REQ_IDLE;
|
adapter->sm.conf_h2c = MAC_AX_OFLD_H2C_IDLE;
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
|
if (cnv_conf_ofld_state(adapter, MAC_AX_OFLD_REQ_IDLE) != MACSUCCESS)
|
return MACPROCERR;
|
|
h2c_end_flow(adapter);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
static inline void mac_pkt_ofld_set_bitmap(u8 *bitmap, u16 index)
|
{
|
bitmap[index >> 3] |= (1 << (index & 7));
|
}
|
|
static inline void mac_pkt_ofld_unset_bitmap(u8 *bitmap, u16 index)
|
{
|
bitmap[index >> 3] &= ~(1 << (index & 7));
|
}
|
|
static inline u8 mac_pkt_ofld_get_bitmap(u8 *bitmap, u16 index)
|
{
|
return bitmap[index / 8] & (1 << (index & 7)) ? 1 : 0;
|
}
|
|
u32 mac_read_pkt_ofld(struct mac_ax_adapter *adapter, u8 id)
|
{
|
u8 *buf;
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_packet_ofld *write_ptr;
|
struct mac_ax_pkt_ofld_info *ofld_info = &adapter->pkt_ofld_info;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
if (id == PKT_OFLD_MAX_COUNT - 1)
|
return MACNOITEM;
|
|
if (mac_pkt_ofld_get_bitmap(ofld_info->id_bitmap, id) == 0)
|
return MACNOITEM;
|
|
if (adapter->sm.pkt_ofld != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCERR;
|
|
adapter->sm.pkt_ofld = MAC_AX_OFLD_H2C_SENDING;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, sizeof(struct mac_ax_pkt_ofld_hdr));
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
write_ptr = (struct fwcmd_packet_ofld *)buf;
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(id, FWCMD_H2C_PACKET_OFLD_PKT_IDX) |
|
SET_WORD(PKT_OFLD_OP_READ, FWCMD_H2C_PACKET_OFLD_PKT_OP)
|
);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD,
|
FWCMD_H2C_FUNC_PACKET_OFLD,
|
1, 1);
|
if (ret)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx: %d\n", ret);
|
adapter->sm.pkt_ofld = MAC_AX_OFLD_H2C_IDLE;
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
|
ofld_info->last_op = PKT_OFLD_OP_READ;
|
|
h2c_end_flow(adapter);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
u32 mac_del_pkt_ofld(struct mac_ax_adapter *adapter, u8 id)
|
{
|
u8 *buf;
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_packet_ofld *write_ptr;
|
struct mac_ax_pkt_ofld_info *ofld_info = &adapter->pkt_ofld_info;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
if (id == PKT_OFLD_MAX_COUNT - 1)
|
return MACNOITEM;
|
|
if (mac_pkt_ofld_get_bitmap(ofld_info->id_bitmap, id) == 0)
|
return MACNOITEM;
|
|
if (ofld_info->used_id_count == 0)
|
return MACNOITEM;
|
|
if (adapter->sm.pkt_ofld != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCERR;
|
|
adapter->sm.pkt_ofld = MAC_AX_OFLD_H2C_SENDING;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, sizeof(struct mac_ax_pkt_ofld_hdr));
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
write_ptr = (struct fwcmd_packet_ofld *)buf;
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(id, FWCMD_H2C_PACKET_OFLD_PKT_IDX) |
|
SET_WORD(PKT_OFLD_OP_DEL, FWCMD_H2C_PACKET_OFLD_PKT_OP)
|
);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_PACKET_OFLD,
|
1, 1);
|
if (ret)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx: %d\n", ret);
|
adapter->sm.pkt_ofld = MAC_AX_OFLD_H2C_IDLE;
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
|
ofld_info->last_op = PKT_OFLD_OP_DEL;
|
|
h2c_end_flow(adapter);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
u32 mac_add_pkt_ofld(struct mac_ax_adapter *adapter, u8 *pkt, u16 len, u8 *id)
|
{
|
u8 *buf;
|
u16 alloc_id;
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_packet_ofld *write_ptr;
|
struct mac_ax_pkt_ofld_info *ofld_info = &adapter->pkt_ofld_info;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
if (ofld_info->free_id_count == 0)
|
return MACNOBUF;
|
|
if (adapter->sm.pkt_ofld != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCERR;
|
|
adapter->sm.pkt_ofld = MAC_AX_OFLD_H2C_SENDING;
|
|
for (alloc_id = 0; alloc_id < PKT_OFLD_MAX_COUNT - 1; alloc_id++) {
|
if (mac_pkt_ofld_get_bitmap(ofld_info->id_bitmap,
|
alloc_id) == 0)
|
break;
|
}
|
|
PLTFM_MSG_TRACE("pkt ofld add. alloc_id: %d, free cnt: %d, use cnt: %d\n",
|
alloc_id, ofld_info->free_id_count,
|
ofld_info->used_id_count);
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, sizeof(struct mac_ax_pkt_ofld_hdr));
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
write_ptr = (struct fwcmd_packet_ofld *)buf;
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD((u8)alloc_id, FWCMD_H2C_PACKET_OFLD_PKT_IDX) |
|
SET_WORD(PKT_OFLD_OP_ADD, FWCMD_H2C_PACKET_OFLD_PKT_OP) |
|
SET_WORD(len, FWCMD_H2C_PACKET_OFLD_PKT_LENGTH)
|
);
|
|
*id = (u8)alloc_id;
|
|
buf = h2cb_put(h2cb, len);
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
PLTFM_MEMCPY(buf, pkt, len);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_PACKET_OFLD,
|
1, 1);
|
if (ret)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx: %d\n", ret);
|
adapter->sm.pkt_ofld = MAC_AX_OFLD_H2C_IDLE;
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
|
ofld_info->last_op = PKT_OFLD_OP_ADD;
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
u32 mac_pkt_ofld_packet(struct mac_ax_adapter *adapter,
|
u8 **pkt_buf, u16 *pkt_len, u8 *pkt_id)
|
{
|
struct mac_ax_pkt_ofld_pkt *pkt_info = &adapter->pkt_ofld_pkt;
|
*pkt_buf = NULL;
|
|
if (adapter->sm.pkt_ofld != MAC_AX_OFLD_H2C_DONE)
|
return MACPROCERR;
|
|
*pkt_buf = (u8 *)PLTFM_MALLOC(pkt_info->pkt_len);
|
if (!*pkt_buf)
|
return MACBUFALLOC;
|
|
PLTFM_MEMCPY(*pkt_buf, pkt_info->pkt, pkt_info->pkt_len);
|
|
*pkt_len = pkt_info->pkt_len;
|
*pkt_id = pkt_info->pkt_id;
|
|
adapter->sm.pkt_ofld = MAC_AX_OFLD_H2C_IDLE;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_dump_efuse_ofld(struct mac_ax_adapter *adapter, u32 efuse_size,
|
bool is_hidden)
|
{
|
u32 ret, size;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct mac_ax_efuse_ofld_info *ofld_info = &adapter->efuse_ofld_info;
|
u8 *buf;
|
struct fwcmd_dump_efuse *write_ptr;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
if (adapter->sm.efuse_ofld != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCERR;
|
|
adapter->sm.efuse_ofld = MAC_AX_OFLD_H2C_SENDING;
|
|
size = efuse_size;
|
if (!ofld_info->buf) {
|
ofld_info->buf = (u8 *)PLTFM_MALLOC(size);
|
if (!ofld_info->buf)
|
return MACBUFALLOC;
|
}
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, sizeof(struct mac_ax_pkt_ofld_hdr));
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
write_ptr = (struct fwcmd_dump_efuse *)buf;
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(efuse_size, FWCMD_H2C_DUMP_EFUSE_DUMP_SIZE) |
|
(is_hidden ? FWCMD_H2C_DUMP_EFUSE_IS_HIDDEN : 0));
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_DUMP_EFUSE,
|
0, 0);
|
if (ret)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx\n");
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
u32 mac_efuse_ofld_map(struct mac_ax_adapter *adapter, u8 *efuse_map,
|
u32 efuse_size)
|
{
|
u32 size = efuse_size;
|
struct mac_ax_efuse_ofld_info *ofld_info = &adapter->efuse_ofld_info;
|
|
if (adapter->sm.efuse_ofld != MAC_AX_OFLD_H2C_DONE)
|
return MACPROCERR;
|
|
PLTFM_MEMCPY(efuse_map, ofld_info->buf, size);
|
|
adapter->sm.efuse_ofld = MAC_AX_OFLD_H2C_IDLE;
|
|
return MACSUCCESS;
|
}
|
|
static u32 cnv_read_ofld_state(struct mac_ax_adapter *adapter, u8 dest)
|
{
|
u8 state;
|
|
state = adapter->sm.read_request;
|
|
if (state > MAC_AX_OFLD_REQ_CLEANED)
|
return MACPROCERR;
|
|
if (dest == MAC_AX_OFLD_REQ_IDLE) {
|
if (state != MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_CLEANED) {
|
if (state == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_CREATED) {
|
if (state == MAC_AX_OFLD_REQ_IDLE ||
|
state == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
} else if (dest == MAC_AX_OFLD_REQ_H2C_SENT) {
|
if (state != MAC_AX_OFLD_REQ_CREATED)
|
return MACPROCERR;
|
}
|
|
adapter->sm.read_request = dest;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_clear_read_request(struct mac_ax_adapter *adapter)
|
{
|
if (adapter->sm.read_request == MAC_AX_OFLD_REQ_H2C_SENT)
|
return MACPROCERR;
|
|
if (cnv_read_ofld_state(adapter, MAC_AX_OFLD_REQ_CLEANED)
|
!= MACSUCCESS)
|
return MACPROCERR;
|
|
PLTFM_FREE(adapter->read_ofld_info.buf,
|
adapter->read_ofld_info.buf_size);
|
adapter->read_ofld_info.buf = NULL;
|
adapter->read_ofld_info.buf_wptr = NULL;
|
adapter->read_ofld_info.last_req = NULL;
|
adapter->read_ofld_info.buf_size = 0;
|
adapter->read_ofld_info.avl_buf_size = 0;
|
adapter->read_ofld_info.used_size = 0;
|
adapter->read_ofld_info.req_num = 0;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_add_read_request(struct mac_ax_adapter *adapter,
|
struct mac_ax_read_req *req)
|
{
|
struct mac_ax_read_ofld_info *ofld_info = &adapter->read_ofld_info;
|
struct fwcmd_read_ofld_req *write_ptr;
|
u8 state;
|
|
state = adapter->sm.read_request;
|
|
if (!(state == MAC_AX_OFLD_REQ_CREATED ||
|
state == MAC_AX_OFLD_REQ_CLEANED)) {
|
return MACPROCERR;
|
}
|
|
if (!ofld_info->buf) {
|
ofld_info->buf = (u8 *)PLTFM_MALLOC(READ_OFLD_MAX_LEN);
|
if (!ofld_info->buf)
|
return MACNPTR;
|
ofld_info->buf_wptr = ofld_info->buf;
|
ofld_info->buf_size = READ_OFLD_MAX_LEN;
|
ofld_info->avl_buf_size = READ_OFLD_MAX_LEN;
|
ofld_info->used_size = 0;
|
ofld_info->req_num = 0;
|
}
|
|
if (ofld_info->avl_buf_size < sizeof(struct mac_ax_read_req))
|
return MACNOBUF;
|
|
if (cnv_read_ofld_state(adapter, MAC_AX_OFLD_REQ_CREATED) != MACSUCCESS)
|
return MACPROCERR;
|
|
if (ofld_info->req_num != 0)
|
ofld_info->last_req->ls = 0;
|
|
ofld_info->last_req = (struct mac_ax_read_req *)ofld_info->buf_wptr;
|
|
req->ls = 1;
|
|
write_ptr = (struct fwcmd_read_ofld_req *)ofld_info->buf_wptr;
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(req->value_len,
|
FWCMD_H2C_READ_OFLD_REQ_VALUE_LEN) |
|
SET_WORD(req->ofld_id,
|
FWCMD_H2C_READ_OFLD_REQ_OFLD_ID) |
|
SET_WORD(req->entry_num,
|
FWCMD_H2C_READ_OFLD_REQ_ENTRY_NUM) | req->ls
|
);
|
|
write_ptr->dword1 =
|
cpu_to_le32(SET_WORD(req->offset,
|
FWCMD_H2C_READ_OFLD_REQ_OFFSET)
|
);
|
|
ofld_info->buf_wptr += sizeof(struct mac_ax_read_req);
|
ofld_info->avl_buf_size -= sizeof(struct mac_ax_read_req);
|
ofld_info->used_size += sizeof(struct mac_ax_read_req);
|
ofld_info->req_num++;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_read_ofld(struct mac_ax_adapter *adapter)
|
{
|
u8 *buf;
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct mac_ax_read_ofld_info *ofld_info = &adapter->read_ofld_info;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
if (ofld_info->used_size + FWCMD_HDR_LEN > READ_OFLD_MAX_LEN)
|
return MACBUFSZ;
|
|
if (adapter->sm.read_h2c != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCERR;
|
|
if (adapter->sm.read_request != MAC_AX_OFLD_REQ_CREATED)
|
return MACPROCERR;
|
|
if (cnv_read_ofld_state(adapter,
|
MAC_AX_OFLD_REQ_H2C_SENT) != MACSUCCESS)
|
return MACPROCERR;
|
|
adapter->sm.read_h2c = MAC_AX_OFLD_H2C_SENDING;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_LONG_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, ofld_info->used_size);
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
PLTFM_MEMCPY(buf, ofld_info->buf, ofld_info->used_size);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_READ_OFLD,
|
1, 1);
|
|
if (ret)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx: %d\n", ret);
|
adapter->sm.read_request = MAC_AX_OFLD_REQ_IDLE;
|
adapter->sm.read_h2c = MAC_AX_OFLD_H2C_IDLE;
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
|
if (cnv_read_ofld_state(adapter, MAC_AX_OFLD_REQ_IDLE) != MACSUCCESS)
|
return MACPROCERR;
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
u32 mac_read_ofld_value(struct mac_ax_adapter *adapter,
|
u8 **val_buf, u16 *val_len)
|
{
|
struct mac_ax_read_ofld_value *value_info = &adapter->read_ofld_value;
|
*val_buf = NULL;
|
|
if (adapter->sm.read_h2c != MAC_AX_OFLD_H2C_DONE)
|
return MACPROCERR;
|
|
*val_buf = (u8 *)PLTFM_MALLOC(value_info->len);
|
if (!*val_buf)
|
return MACBUFALLOC;
|
|
PLTFM_MEMCPY(*val_buf, value_info->buf, value_info->len);
|
|
*val_len = value_info->len;
|
|
adapter->sm.read_h2c = MAC_AX_OFLD_H2C_IDLE;
|
|
return MACSUCCESS;
|
}
|
|
u32 mac_general_pkt_ids(struct mac_ax_adapter *adapter,
|
struct mac_ax_general_pkt_ids *ids)
|
{
|
u8 *buf;
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_general_pkt *write_ptr;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
buf = h2cb_put(h2cb, sizeof(struct mac_ax_general_pkt_ids));
|
if (!buf) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
write_ptr = (struct fwcmd_general_pkt *)buf;
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(ids->macid, FWCMD_H2C_GENERAL_PKT_MACID) |
|
SET_WORD(ids->probersp, FWCMD_H2C_GENERAL_PKT_PROBRSP_ID) |
|
SET_WORD(ids->pspoll, FWCMD_H2C_GENERAL_PKT_PSPOLL_ID) |
|
SET_WORD(ids->nulldata, FWCMD_H2C_GENERAL_PKT_NULL_ID)
|
);
|
|
write_ptr->dword1 =
|
cpu_to_le32(SET_WORD(ids->qosnull, FWCMD_H2C_GENERAL_PKT_QOS_NULL_ID) |
|
SET_WORD(ids->cts2self, FWCMD_H2C_GENERAL_PKT_CTS2SELF_ID) |
|
SET_WORD(ids->probereq, FWCMD_H2C_GENERAL_PKT_PROBREQ_ID) |
|
SET_WORD(ids->apcsa, FWCMD_H2C_GENERAL_PKT_APCSA_ID)
|
);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_INFO,
|
FWCMD_H2C_FUNC_GENERAL_PKT,
|
1, 1);
|
if (ret)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx: %d\n", ret);
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
static u32 add_cmd(struct mac_ax_adapter *adapter, struct rtw_mac_cmd *cmd)
|
{
|
struct mac_ax_cmd_ofld_info *ofld_info = &adapter->cmd_ofld_info;
|
u16 total_len = CMD_OFLD_SIZE;
|
struct fwcmd_cmd_ofld *write_ptr;
|
|
if (!ofld_info->buf) {
|
ofld_info->buf = (u8 *)PLTFM_MALLOC(CMD_OFLD_MAX_LEN);
|
if (!ofld_info->buf)
|
return MACBUFALLOC;
|
ofld_info->buf_wptr = ofld_info->buf;
|
ofld_info->last_wptr = NULL;
|
ofld_info->buf_size = CMD_OFLD_MAX_LEN;
|
ofld_info->avl_buf_size = CMD_OFLD_MAX_LEN;
|
ofld_info->used_size = 0;
|
ofld_info->cmd_num = 0;
|
ofld_info->accu_delay = 0;
|
}
|
|
write_ptr = (struct fwcmd_cmd_ofld *)ofld_info->buf_wptr;
|
|
write_ptr->dword0 =
|
cpu_to_le32(SET_WORD(cmd->src, FWCMD_H2C_CMD_OFLD_SRC) |
|
SET_WORD(cmd->type, FWCMD_H2C_CMD_OFLD_TYPE) |
|
(cmd->lc ? FWCMD_H2C_CMD_OFLD_LC : 0) |
|
SET_WORD(cmd->rf_path, FWCMD_H2C_CMD_OFLD_PATH) |
|
SET_WORD(cmd->offset, FWCMD_H2C_CMD_OFLD_OFFSET) |
|
SET_WORD(ofld_info->cmd_num, FWCMD_H2C_CMD_OFLD_CMD_NUM)
|
);
|
write_ptr->dword1 =
|
cpu_to_le32(SET_WORD(cmd->id, FWCMD_H2C_CMD_OFLD_ID));
|
write_ptr->dword2 =
|
cpu_to_le32(SET_WORD(cmd->value, FWCMD_H2C_CMD_OFLD_VALUE));
|
write_ptr->dword3 =
|
cpu_to_le32(SET_WORD(cmd->mask, FWCMD_H2C_CMD_OFLD_MASK));
|
|
ofld_info->last_wptr = ofld_info->buf_wptr;
|
ofld_info->buf_wptr += total_len;
|
ofld_info->avl_buf_size -= total_len;
|
ofld_info->used_size += total_len;
|
ofld_info->cmd_num++;
|
if (cmd->type == RTW_MAC_DELAY_OFLD)
|
ofld_info->accu_delay += cmd->value;
|
|
return MACSUCCESS;
|
}
|
|
static u32 chk_cmd_ofld_reg(struct mac_ax_adapter *adapter)
|
{
|
#define MAC_AX_CMD_OFLD_POLL_CNT 1000
|
#define MAC_AX_CMD_OFLD_POLL_US 50
|
struct mac_ax_c2hreg_poll c2h;
|
struct fwcmd_c2hreg *c2h_content;
|
u32 ret, result, i, cmd_num;
|
struct mac_ax_cmd_ofld_info *ofld_info = &adapter->cmd_ofld_info;
|
u8 *cmd;
|
|
c2h.polling_id = FWCMD_C2HREG_FUNC_IO_OFLD_RESULT;
|
c2h.retry_cnt = MAC_AX_CMD_OFLD_POLL_CNT;
|
c2h.retry_wait_us = MAC_AX_CMD_OFLD_POLL_US;
|
ret = proc_msg_reg(adapter, NULL, &c2h);
|
if (ret) {
|
PLTFM_MSG_ERR("%s: fail to wait FW done(%d)\n", __func__, ret);
|
return ret;
|
}
|
|
c2h_content = &c2h.c2hreg_cont.c2h_content;
|
result = GET_FIELD(c2h_content->dword0,
|
FWCMD_C2HREG_IO_OFLD_RESULT_RET);
|
if (result) {
|
cmd_num = GET_FIELD(c2h_content->dword0,
|
FWCMD_C2HREG_IO_OFLD_RESULT_CMD_NUM);
|
cmd = ofld_info->buf + cmd_num * CMD_OFLD_SIZE;
|
PLTFM_MSG_ERR("%s: fail to finish IO offload\n", __func__);
|
PLTFM_MSG_ERR("fail offset = %x\n", c2h_content->dword1);
|
PLTFM_MSG_ERR("exp val = %x\n", c2h_content->dword2);
|
PLTFM_MSG_ERR("read val = %x\n", c2h_content->dword3);
|
PLTFM_MSG_ERR("fail cmd num = %d\n", cmd_num);
|
for (i = 0; i < CMD_OFLD_SIZE; i += 4)
|
PLTFM_MSG_ERR("%x\n", *((u32 *)(cmd + i)));
|
|
return MACFIOOFLD;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 chk_cmd_ofld_pkt(struct mac_ax_adapter *adapter)
|
{
|
u32 cnt = MAC_AX_CMD_OFLD_POLL_CNT;
|
struct mac_ax_state_mach *sm = &adapter->sm;
|
struct mac_ax_drv_stats *drv_stats = &adapter->drv_stats;
|
struct mac_ax_cmd_ofld_info *ofld_info = &adapter->cmd_ofld_info;
|
|
while (--cnt) {
|
if (sm->cmd_state == MAC_AX_CMD_OFLD_RCVD)
|
break;
|
if (drv_stats->drv_rm)
|
return MACDRVRM;
|
PLTFM_DELAY_US(MAC_AX_CMD_OFLD_POLL_US);
|
}
|
|
PLTFM_MSG_TRACE("%s: cnt = %d, us = %d\n",
|
__func__, cnt, MAC_AX_CMD_OFLD_POLL_US);
|
|
if (!cnt) {
|
PLTFM_MSG_ERR("%s: polling timeout\n", __func__);
|
return MACPOLLTO;
|
}
|
|
if (ofld_info->result) {
|
PLTFM_MSG_ERR("%s: ofld FAIL!!!\n", __func__);
|
return MACFIOOFLD;
|
}
|
|
return MACSUCCESS;
|
}
|
|
static u32 chk_cmd_ofld(struct mac_ax_adapter *adapter, u8 rx_ok)
|
{
|
u32 ret;
|
|
if (rx_ok)
|
ret = chk_cmd_ofld_pkt(adapter);
|
else
|
ret = chk_cmd_ofld_reg(adapter);
|
|
return ret;
|
}
|
|
static u32 cmd_ofld(struct mac_ax_adapter *adapter)
|
{
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct mac_ax_cmd_ofld_info *ofld_info = &adapter->cmd_ofld_info;
|
u8 *buffer;
|
u8 func;
|
u8 rx_ok = adapter->drv_stats.rx_ok;
|
struct mac_ax_state_mach *sm = &adapter->sm;
|
|
PLTFM_MSG_TRACE("%s===>\n", __func__);
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_LONG_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buffer = h2cb_put(h2cb, ofld_info->used_size);
|
if (!buffer) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
PLTFM_MEMCPY(buffer, ofld_info->buf, ofld_info->used_size);
|
|
func = rx_ok ? FWCMD_H2C_FUNC_CMD_OFLD_PKT :
|
FWCMD_H2C_FUNC_CMD_OFLD_REG;
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, func,
|
0, 0);
|
if (ret)
|
goto fail;
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret)
|
goto fail;
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
PLTFM_MSG_ERR("[ERR]platform tx\n");
|
goto fail;
|
}
|
|
if (ofld_info->accu_delay)
|
PLTFM_DELAY_US(ofld_info->accu_delay);
|
|
sm->cmd_state = MAC_AX_CMD_OFLD_SENDING;
|
|
ret = chk_cmd_ofld(adapter, rx_ok);
|
if (ret) {
|
PLTFM_MSG_ERR("%s: check IO offload fail\n", __func__);
|
goto fail;
|
}
|
|
h2cb_free(adapter, h2cb);
|
PLTFM_FREE(ofld_info->buf, CMD_OFLD_MAX_LEN);
|
ofld_info->buf = NULL;
|
|
PLTFM_MSG_TRACE("%s<===\n", __func__);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
PLTFM_FREE(ofld_info->buf, CMD_OFLD_MAX_LEN);
|
ofld_info->buf = NULL;
|
|
return ret;
|
}
|
|
u32 mac_add_cmd_ofld(struct mac_ax_adapter *adapter, struct rtw_mac_cmd *cmd)
|
{
|
struct mac_ax_cmd_ofld_info *ofld_info = &adapter->cmd_ofld_info;
|
struct mac_ax_state_mach *sm = &adapter->sm;
|
u32 ret = MACSUCCESS;
|
|
if (cmd->type != RTW_MAC_DELAY_OFLD &&
|
cmd->src != RTW_MAC_RF_CMD_OFLD && cmd->offset & (4 - 1))
|
return MACBADDR;
|
|
if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY)
|
return MACNOFW;
|
|
PLTFM_MUTEX_LOCK(&ofld_info->cmd_ofld_lock);
|
if (sm->cmd_state != MAC_AX_CMD_OFLD_IDLE) {
|
PLTFM_MSG_ERR("%s: IO offload is busy\n", __func__);
|
PLTFM_MUTEX_UNLOCK(&ofld_info->cmd_ofld_lock);
|
return MACPROCERR;
|
}
|
sm->cmd_state = MAC_AX_CMD_OFLD_PROC;
|
PLTFM_MUTEX_UNLOCK(&ofld_info->cmd_ofld_lock);
|
|
if (ofld_info->buf &&
|
ofld_info->avl_buf_size < CMD_OFLD_SIZE) {
|
if (!ofld_info->last_wptr) {
|
ret = MACNPTR;
|
PLTFM_MSG_ERR("%s: wrong pointer\n", __func__);
|
goto END;
|
}
|
*ofld_info->last_wptr = *ofld_info->last_wptr |
|
FWCMD_H2C_CMD_OFLD_LC;
|
ret = cmd_ofld(adapter);
|
if (ret) {
|
PLTFM_MSG_ERR("%s: send IO offload fail\n", __func__);
|
goto END;
|
}
|
}
|
|
ret = add_cmd(adapter, cmd);
|
if (ret)
|
goto END;
|
|
if (!cmd->lc)
|
goto END;
|
|
ret = cmd_ofld(adapter);
|
|
END:
|
PLTFM_MUTEX_LOCK(&ofld_info->cmd_ofld_lock);
|
sm->cmd_state = MAC_AX_CMD_OFLD_IDLE;
|
PLTFM_MUTEX_UNLOCK(&ofld_info->cmd_ofld_lock);
|
|
return ret;
|
}
|
|
u32 write_mac_reg_ofld(struct mac_ax_adapter *adapter,
|
u16 offset, u32 mask, u32 val, u8 lc)
|
{
|
struct rtw_mac_cmd cmd = {RTW_MAC_MAC_CMD_OFLD, RTW_MAC_WRITE_OFLD,
|
0, RTW_MAC_RF_PATH_A, 0, 0, 0, 0};
|
|
cmd.offset = offset;
|
cmd.mask = mask;
|
cmd.value = val;
|
cmd.lc = lc;
|
|
return mac_add_cmd_ofld(adapter, &cmd);
|
}
|
|
u32 poll_mac_reg_ofld(struct mac_ax_adapter *adapter,
|
u16 offset, u32 mask, u32 val, u8 lc)
|
{
|
struct rtw_mac_cmd cmd = {RTW_MAC_MAC_CMD_OFLD, RTW_MAC_COMPARE_OFLD,
|
0, RTW_MAC_RF_PATH_A, 0, 0, 0, 0};
|
|
cmd.offset = offset;
|
cmd.mask = mask;
|
cmd.value = val;
|
cmd.lc = lc;
|
|
return mac_add_cmd_ofld(adapter, &cmd);
|
}
|
|
u32 delay_ofld(struct mac_ax_adapter *adapter,
|
u32 val)
|
{
|
struct rtw_mac_cmd cmd = {RTW_MAC_MAC_CMD_OFLD, RTW_MAC_DELAY_OFLD,
|
0, RTW_MAC_RF_PATH_A, 0, 0, 0, 0};
|
|
cmd.value = val;
|
|
return mac_add_cmd_ofld(adapter, &cmd);
|
}
|
|
u32 mac_ccxrpt_parsing(struct mac_ax_adapter *adapter, u8 *buf, struct mac_ax_ccxrpt *info)
|
{
|
u32 val_d0;
|
u32 val_d3;
|
u32 dword0 = *((u32 *)buf);
|
u32 dword3 = *((u32 *)(buf + 12));
|
|
val_d0 = le32_to_cpu(dword0);
|
val_d3 = le32_to_cpu(dword3);
|
info->tx_state = GET_FIELD(val_d0, TXCCXRPT_TX_STATE);
|
info->sw_define = GET_FIELD(val_d0, TXCCXRPT_SW_DEFINE);
|
info->macid = GET_FIELD(val_d0, TXCCXRPT_MACID);
|
info->pkt_ok_num = GET_FIELD(val_d3, TXCCXRPT_PKT_OK_NUM);
|
info->data_txcnt = GET_FIELD(val_d3, TXCCXRPT_DATA_TX_CNT);
|
|
return MACSUCCESS;
|
}
|
|
u32 get_ccxrpt_event(struct mac_ax_adapter *adapter,
|
struct rtw_c2h_info *c2h,
|
enum phl_msg_evt_id *id, u8 *c2h_info)
|
{
|
struct mac_ax_ccxrpt *info;
|
u32 val_d0, val_d3;
|
u32 dword0 = *((u32 *)c2h->content);
|
u32 dword3 = *((u32 *)(c2h->content + 12));
|
|
info = (struct mac_ax_ccxrpt *)c2h_info;
|
val_d0 = le32_to_cpu(dword0);
|
val_d3 = le32_to_cpu(dword3);
|
info->tx_state = GET_FIELD(val_d0, TXCCXRPT_TX_STATE);
|
info->sw_define = GET_FIELD(val_d0, TXCCXRPT_SW_DEFINE);
|
info->macid = GET_FIELD(val_d0, TXCCXRPT_MACID);
|
info->pkt_ok_num = GET_FIELD(val_d3, TXCCXRPT_PKT_OK_NUM);
|
info->data_txcnt = GET_FIELD(val_d3, TXCCXRPT_DATA_TX_CNT);
|
|
if (info->tx_state)
|
*id = MSG_EVT_CCX_REPORT_TX_FAIL;
|
else
|
*id = MSG_EVT_CCX_REPORT_TX_OK;
|
|
return MACSUCCESS;
|
}
|
|
static inline u8 scanofld_ch_list_len(struct scan_chinfo_list *list)
|
{
|
return list->size;
|
}
|
|
static inline void scanofld_ch_list_init(struct scan_chinfo_list *list)
|
{
|
list->head = NULL;
|
list->tail = NULL;
|
list->size = 0;
|
}
|
|
static inline u32 scanofld_ch_list_insert_head(struct mac_ax_adapter *adapter,
|
struct scan_chinfo_list *list,
|
struct mac_ax_scanofld_chinfo *chinfo)
|
{
|
struct scanofld_chinfo_node *node;
|
|
node = (struct scanofld_chinfo_node *)PLTFM_MALLOC(sizeof(struct scanofld_chinfo_node));
|
if (!node)
|
return MACNOBUF;
|
node->next = list->head;
|
if (list->size == 0)
|
list->tail = node;
|
list->size++;
|
list->head = node;
|
node->chinfo = chinfo;
|
return MACSUCCESS;
|
}
|
|
static inline u32 scanofld_ch_list_insert_tail(struct mac_ax_adapter *adapter,
|
struct scan_chinfo_list *list,
|
struct mac_ax_scanofld_chinfo *chinfo)
|
{
|
struct scanofld_chinfo_node *node;
|
|
node = (struct scanofld_chinfo_node *)PLTFM_MALLOC(sizeof(struct scanofld_chinfo_node));
|
|
if (!node)
|
return MACNOBUF;
|
if (list->size == 0)
|
list->head = node;
|
else
|
list->tail->next = node;
|
|
list->tail = node;
|
node->chinfo = chinfo;
|
node->next = NULL;
|
list->size++;
|
return MACSUCCESS;
|
}
|
|
static inline void scanofld_ch_node_print(struct mac_ax_adapter *adapter,
|
struct scanofld_chinfo_node *curr_node, u8 i)
|
{
|
PLTFM_MSG_TRACE("[CH %d] - DWORD 0:%x\n", i, *((u32 *)(curr_node->chinfo)));
|
PLTFM_MSG_TRACE("[CH %d] -- period = %d\n", i, curr_node->chinfo->period);
|
PLTFM_MSG_TRACE("[CH %d] -- dwell_time = %d\n", i, curr_node->chinfo->dwell_time);
|
PLTFM_MSG_TRACE("[CH %d] -- central_ch = %d\n", i, curr_node->chinfo->central_ch);
|
PLTFM_MSG_TRACE("[CH %d] -- pri_ch = %d\n", i, curr_node->chinfo->pri_ch);
|
PLTFM_MSG_TRACE("[CH %d] - DWORD 1:%x\n", i, *((u32 *)(curr_node->chinfo) + 1));
|
PLTFM_MSG_TRACE("[CH %d] -- bw = %d\n", i, curr_node->chinfo->bw);
|
PLTFM_MSG_TRACE("[CH %d] -- noti_dwell = %d\n", i, curr_node->chinfo->c2h_notify_dwell);
|
PLTFM_MSG_TRACE("[CH %d] -- noti_preTX = %d\n", i, curr_node->chinfo->c2h_notify_preTX);
|
PLTFM_MSG_TRACE("[CH %d] -- noti_postTX = %d\n", i, curr_node->chinfo->c2h_notify_postTX);
|
PLTFM_MSG_TRACE("[CH %d] -- noti_leaveCh = %d\n", i, curr_node->chinfo->c2h_notify_leaveCH);
|
PLTFM_MSG_TRACE("[CH %d] -- noti_enterCh = %d\n", i, curr_node->chinfo->c2h_notify_enterCH);
|
PLTFM_MSG_TRACE("[CH %d] -- numAddtionPkt = %d\n", i, curr_node->chinfo->num_addition_pkt);
|
PLTFM_MSG_TRACE("[CH %d] -- tx_pkt = %d\n", i, curr_node->chinfo->tx_pkt);
|
PLTFM_MSG_TRACE("[CH %d] -- pause_tx_data = %d\n", i, curr_node->chinfo->pause_tx_data);
|
PLTFM_MSG_TRACE("[CH %d] -- rsvd0 = %d\n", i, curr_node->chinfo->rsvd0);
|
PLTFM_MSG_TRACE("[CH %d] -- rsvd1 = %d\n", i, curr_node->chinfo->rsvd1);
|
PLTFM_MSG_TRACE("[CH %d] - DWORD 2:%x\n", i, *((u32 *)(curr_node->chinfo) + 2));
|
PLTFM_MSG_TRACE("[CH %d] -- id 0 = %d\n", i, curr_node->chinfo->additional_pkt_id[0]);
|
PLTFM_MSG_TRACE("[CH %d] -- id 1 = %d\n", i, curr_node->chinfo->additional_pkt_id[1]);
|
PLTFM_MSG_TRACE("[CH %d] -- id 2 = %d\n", i, curr_node->chinfo->additional_pkt_id[2]);
|
PLTFM_MSG_TRACE("[CH %d] -- id 3 = %d\n", i, curr_node->chinfo->additional_pkt_id[3]);
|
PLTFM_MSG_TRACE("[CH %d] - DWORD 3:%x\n", i, *((u32 *)(curr_node->chinfo) + 3));
|
PLTFM_MSG_TRACE("[CH %d] -- id 4 = %d\n", i, curr_node->chinfo->additional_pkt_id[4]);
|
PLTFM_MSG_TRACE("[CH %d] -- id 5 = %d\n", i, curr_node->chinfo->additional_pkt_id[5]);
|
PLTFM_MSG_TRACE("[CH %d] -- id 6 = %d\n", i, curr_node->chinfo->additional_pkt_id[6]);
|
PLTFM_MSG_TRACE("[CH %d] -- id 7 = %d\n", i, curr_node->chinfo->additional_pkt_id[7]);
|
}
|
|
static inline void scanofld_ch_list_print(struct mac_ax_adapter *adapter,
|
struct scan_chinfo_list *list)
|
{
|
struct scanofld_chinfo_node *curr_node = list->head;
|
u8 i = 0;
|
|
PLTFM_MSG_TRACE("------------------------------------------\n");
|
PLTFM_MSG_TRACE("[CH List] len = %d\n", list->size);
|
while (curr_node) {
|
scanofld_ch_node_print(adapter, curr_node, i);
|
PLTFM_MSG_TRACE("\n");
|
curr_node = curr_node->next;
|
i++;
|
}
|
PLTFM_MSG_TRACE("------------------------------------------\n\n");
|
}
|
|
void mac_scanofld_ch_list_clear(struct mac_ax_adapter *adapter,
|
struct scan_chinfo_list *list)
|
{
|
struct scanofld_chinfo_node *curr_node = list->head;
|
struct scanofld_chinfo_node *tmp;
|
|
while (curr_node) {
|
tmp = curr_node;
|
curr_node = curr_node->next;
|
PLTFM_FREE(tmp->chinfo, sizeof(struct mac_ax_scanofld_chinfo));
|
PLTFM_FREE(tmp, sizeof(struct scanofld_chinfo_node));
|
list->size--;
|
}
|
list->head = NULL;
|
list->tail = NULL;
|
scanofld_ch_list_print(adapter, list);
|
}
|
|
void mac_scanofld_reset_state(struct mac_ax_adapter *adapter)
|
{
|
struct mac_ax_scanofld_info *scanofld_info;
|
|
scanofld_info = &adapter->scanofld_info;
|
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
|
scanofld_info->fw_scan_busy = 0;
|
}
|
|
u32 mac_add_scanofld_ch(struct mac_ax_adapter *adapter, struct mac_ax_scanofld_chinfo *chinfo,
|
u8 send_h2c, u8 clear_after_send)
|
{
|
struct mac_ax_scanofld_info *scanofld_info;
|
struct scan_chinfo_list *list;
|
struct scanofld_chinfo_node *curr_node;
|
struct mac_ax_scanofld_chinfo *tmp;
|
u32 ret;
|
u8 list_size;
|
u8 *buf8;
|
u32 *buf32;
|
u32 *chinfo32;
|
u8 chinfo_dword;
|
struct fwcmd_add_scanofld_ch *pkt;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cbuf;
|
#else
|
struct h2c_buf *h2cbuf;
|
#endif
|
|
scanofld_info = &adapter->scanofld_info;
|
PLTFM_MSG_TRACE("[scan] drv_chlist_busy=%d, fw_chlist_busy=%d",
|
scanofld_info->drv_chlist_busy, scanofld_info->fw_chlist_busy);
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
if (scanofld_info->drv_chlist_busy) {
|
PLTFM_MSG_ERR("[scan][add] Halmac scan list busy, abort adding.\n");
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
return MACPROCBUSY;
|
}
|
scanofld_info->drv_chlist_busy = 1;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
|
ret = MACSUCCESS;
|
|
if (!scanofld_info->list) {
|
list = (struct scan_chinfo_list *)PLTFM_MALLOC(sizeof(struct scan_chinfo_list));
|
scanofld_info->list = list;
|
scanofld_ch_list_init(adapter->scanofld_info.list);
|
}
|
list = scanofld_info->list;
|
|
tmp = (struct mac_ax_scanofld_chinfo *)PLTFM_MALLOC(sizeof(struct mac_ax_scanofld_chinfo));
|
PLTFM_MEMCPY(tmp, chinfo, sizeof(struct mac_ax_scanofld_chinfo));
|
ret = scanofld_ch_list_insert_tail(adapter, list, tmp);
|
if (ret) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
return ret;
|
}
|
scanofld_ch_list_print(adapter, list);
|
|
if (!send_h2c) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
return ret;
|
}
|
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
if (scanofld_info->fw_chlist_busy) {
|
PLTFM_MSG_ERR("[scan][add] FW scan list busy, abort sending.\n");
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
return MACPROCBUSY;
|
}
|
adapter->scanofld_info.fw_chlist_busy = 1;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
|
list_size = scanofld_ch_list_len(list);
|
if (list_size == 0) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
return MACNOITEM;
|
}
|
|
h2cbuf = h2cb_alloc(adapter, H2CB_CLASS_LONG_DATA);
|
if (!h2cbuf) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
return MACNPTR;
|
}
|
|
buf8 = h2cb_put(h2cbuf,
|
sizeof(struct fwcmd_add_scanofld_ch) +
|
list_size * sizeof(struct mac_ax_scanofld_chinfo));
|
if (!buf8) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
return MACNOBUF;
|
}
|
|
pkt = (struct fwcmd_add_scanofld_ch *)buf8;
|
pkt->dword0 = cpu_to_le32(SET_WORD(list_size, FWCMD_H2C_ADD_SCANOFLD_CH_NUM_OF_CH) |
|
SET_WORD(sizeof(struct mac_ax_scanofld_chinfo) / 4,
|
FWCMD_H2C_ADD_SCANOFLD_CH_SIZE_OF_CHINFO));
|
buf32 = (u32 *)(buf8 + sizeof(struct fwcmd_add_scanofld_ch));
|
curr_node = list->head;
|
while (curr_node) {
|
chinfo32 = (u32 *)(curr_node->chinfo);
|
for (chinfo_dword = 0;
|
chinfo_dword < (sizeof(struct mac_ax_scanofld_chinfo) / 4);
|
chinfo_dword++) {
|
*buf32 = cpu_to_le32(*chinfo32);
|
buf32++;
|
chinfo32++;
|
}
|
curr_node = curr_node->next;
|
}
|
|
ret = h2c_pkt_set_hdr(adapter, h2cbuf, FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_ADD_SCANOFLD_CH, 1, 1);
|
if (ret) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
return ret;
|
}
|
ret = h2c_pkt_build_txd(adapter, h2cbuf);
|
if (ret) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->drv_chlist_state_lock);
|
scanofld_info->drv_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->drv_chlist_state_lock);
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
return ret;
|
}
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cbuf);
|
#else
|
ret = PLTFM_TX(h2cbuf->data, h2cbuf->len);
|
#endif
|
h2cb_free(adapter, h2cbuf);
|
if (ret)
|
return ret;
|
h2c_end_flow(adapter);
|
PLTFM_MSG_TRACE("[scan] drv_chlist_busy=%d, fw_chlist_busy=%d",
|
scanofld_info->drv_chlist_busy, scanofld_info->fw_chlist_busy);
|
scanofld_info->clear_drv_ch_list = clear_after_send;
|
return ret;
|
}
|
|
u32 mac_scanofld(struct mac_ax_adapter *adapter, struct mac_ax_scanofld_param *scanParam)
|
{
|
u8 *buf;
|
u32 ret;
|
struct mac_ax_scanofld_info *scanofld_info;
|
struct fwcmd_scanofld *pkt;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cbuf;
|
#else
|
struct h2c_buf *h2cbuf;
|
#endif
|
|
scanofld_info = &adapter->scanofld_info;
|
ret = MACSUCCESS;
|
PLTFM_MSG_TRACE("[scan] op=%d (%d), fw_scan_busy=%d, fw_chlist_busy=%d",
|
scanParam->operation, !!(scanParam->operation),
|
scanofld_info->fw_scan_busy, scanofld_info->fw_chlist_busy);
|
if (!!(scanParam->operation) && scanofld_info->fw_scan_busy) {
|
PLTFM_MSG_ERR("[scan] Cant start scanning while scanning\n");
|
return MACPROCBUSY;
|
}
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
if (!!(scanParam->operation) && scanofld_info->fw_chlist_busy) {
|
PLTFM_MSG_ERR("[scan] Cant start scanning when fw chlist busy\n");
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
return MACPROCBUSY;
|
}
|
|
scanofld_info->fw_chlist_busy = (u8)!!(scanParam->operation);
|
scanofld_info->fw_scan_busy = (u8)!!(scanParam->operation);
|
PLTFM_MSG_TRACE("[scan] fw_chlist_busy = %d, fw_scan_busy=%d",
|
scanofld_info->fw_chlist_busy, scanofld_info->fw_scan_busy);
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
PLTFM_MSG_TRACE("[scan] macid=%d\n", scanParam->macid);
|
PLTFM_MSG_TRACE("[scan] port_id=%d\n", scanParam->port_id);
|
PLTFM_MSG_TRACE("[scan] band=%d\n", scanParam->band);
|
PLTFM_MSG_TRACE("[scan] operation=%d\n", scanParam->operation);
|
PLTFM_MSG_TRACE("[scan] target_ch_mode=%d\n", scanParam->target_ch_mode);
|
PLTFM_MSG_TRACE("[scan] start_mode=%d\n", scanParam->start_mode);
|
PLTFM_MSG_TRACE("[scan] scan_type=%d\n", scanParam->scan_type);
|
PLTFM_MSG_TRACE("[scan] target_ch_bw=%d\n", scanParam->target_ch_bw);
|
PLTFM_MSG_TRACE("[scan] target_pri_ch=%d\n", scanParam->target_pri_ch);
|
PLTFM_MSG_TRACE("[scan] target_central_ch=%d\n", scanParam->target_central_ch);
|
PLTFM_MSG_TRACE("[scan] probe_req_pkt_id=%d\n", scanParam->probe_req_pkt_id);
|
PLTFM_MSG_TRACE("[scan] norm_pd=%d\n", scanParam->norm_pd);
|
PLTFM_MSG_TRACE("[scan] norm_cy=%d\n", scanParam->norm_cy);
|
PLTFM_MSG_TRACE("[scan] slow_pd=%d\n", scanParam->slow_pd);
|
|
h2cbuf = h2cb_alloc(adapter, H2CB_CLASS_DATA);
|
if (!h2cbuf) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_scan_busy = 0;
|
return MACNPTR;
|
}
|
|
buf = h2cb_put(h2cbuf, sizeof(struct fwcmd_scanofld));
|
if (!buf) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = 0;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_scan_busy = 0;
|
return MACNOBUF;
|
}
|
|
pkt = (struct fwcmd_scanofld *)buf;
|
pkt->dword0 = cpu_to_le32(SET_WORD(scanParam->macid, FWCMD_H2C_SCANOFLD_MACID) |
|
SET_WORD(scanParam->norm_cy, FWCMD_H2C_SCANOFLD_NORM_CY) |
|
SET_WORD(scanParam->port_id, FWCMD_H2C_SCANOFLD_PORT_ID) |
|
(scanParam->band ? FWCMD_H2C_SCANOFLD_BAND : 0) |
|
SET_WORD(scanParam->operation, FWCMD_H2C_SCANOFLD_OPERATION));
|
pkt->dword1 = cpu_to_le32((scanParam->c2h_end ? FWCMD_H2C_SCANOFLD_C2H_NOTIFY_END : 0) |
|
(scanParam->target_ch_mode ?
|
FWCMD_H2C_SCANOFLD_TARGET_CH_MODE : 0) |
|
(scanParam->start_mode ?
|
FWCMD_H2C_SCANOFLD_START_MODE : 0) |
|
SET_WORD(scanParam->scan_type, FWCMD_H2C_SCANOFLD_SCAN_TYPE) |
|
SET_WORD(scanParam->target_ch_bw,
|
FWCMD_H2C_SCANOFLD_TARGET_CH_BW) |
|
SET_WORD(scanParam->target_pri_ch,
|
FWCMD_H2C_SCANOFLD_TARGET_PRI_CH) |
|
SET_WORD(scanParam->target_central_ch,
|
FWCMD_H2C_SCANOFLD_TARGET_CENTRAL_CH) |
|
SET_WORD(scanParam->probe_req_pkt_id,
|
FWCMD_H2C_SCANOFLD_PROBE_REQ_PKT_ID));
|
pkt->dword2 = cpu_to_le32(SET_WORD(scanParam->norm_pd, FWCMD_H2C_SCANOFLD_NORM_PD) |
|
SET_WORD(scanParam->slow_pd, FWCMD_H2C_SCANOFLD_SLOW_PD));
|
pkt->dword3 = cpu_to_le32(scanParam->tsf_high);
|
pkt->dword4 = cpu_to_le32(scanParam->tsf_low);
|
|
ret = h2c_pkt_set_hdr(adapter, h2cbuf, FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_SCANOFLD, 1, 1);
|
if (ret) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = !scanofld_info->fw_chlist_busy;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_scan_busy = !scanofld_info->fw_scan_busy;
|
return ret;
|
}
|
ret = h2c_pkt_build_txd(adapter, h2cbuf);
|
if (ret) {
|
PLTFM_MUTEX_LOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_chlist_busy = !scanofld_info->fw_chlist_busy;
|
PLTFM_MUTEX_UNLOCK(&scanofld_info->fw_chlist_state_lock);
|
scanofld_info->fw_scan_busy = !scanofld_info->fw_scan_busy;
|
return ret;
|
}
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cbuf);
|
#else
|
ret = PLTFM_TX(h2cbuf->data, h2cbuf->len);
|
#endif
|
h2cb_free(adapter, h2cbuf);
|
if (ret)
|
return ret;
|
h2c_end_flow(adapter);
|
return ret;
|
}
|
|
u32 mac_scanofld_fw_busy(struct mac_ax_adapter *adapter)
|
{
|
if (adapter->scanofld_info.fw_scan_busy)
|
return MACPROCBUSY;
|
else
|
return MACSUCCESS;
|
}
|
|
u32 mac_scanofld_chlist_busy(struct mac_ax_adapter *adapter)
|
{
|
if (adapter->scanofld_info.drv_chlist_busy || adapter->scanofld_info.fw_chlist_busy)
|
return MACPROCBUSY;
|
else
|
return MACSUCCESS;
|
}
|
|
u32 mac_ch_switch_ofld(struct mac_ax_adapter *adapter, struct mac_ax_ch_switch_parm parm)
|
{
|
u32 ret;
|
u8 *buf;
|
struct fwcmd_ch_switch *pkt;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cbuf;
|
#else
|
struct h2c_buf *h2cbuf;
|
#endif
|
if (adapter->sm.ch_switch != MAC_AX_OFLD_H2C_IDLE)
|
return MACPROCBUSY;
|
adapter->sm.ch_switch = MAC_AX_OFLD_H2C_SENDING;
|
h2cbuf = h2cb_alloc(adapter, H2CB_CLASS_DATA);
|
if (!h2cbuf) {
|
adapter->sm.ch_switch = MAC_AX_OFLD_H2C_IDLE;
|
return MACNOBUF;
|
}
|
buf = h2cb_put(h2cbuf, sizeof(struct fwcmd_ch_switch));
|
if (!buf) {
|
adapter->sm.ch_switch = MAC_AX_OFLD_H2C_IDLE;
|
return MACNOBUF;
|
}
|
pkt = (struct fwcmd_ch_switch *)buf;
|
pkt->dword0 = cpu_to_le32(SET_WORD(parm.pri_ch, FWCMD_H2C_CH_SWITCH_PRI_CH) |
|
SET_WORD(parm.central_ch, FWCMD_H2C_CH_SWITCH_CENTRAL_CH) |
|
SET_WORD(parm.bw, FWCMD_H2C_CH_SWITCH_BW) |
|
SET_WORD(parm.ch_band, FWCMD_H2C_CH_SWITCH_CH_BAND) |
|
(parm.band ? FWCMD_H2C_CH_SWITCH_BAND : 0) |
|
(parm.reload_rf ? FWCMD_H2C_CH_SWITCH_RELOAD_RF : 0));
|
ret = h2c_pkt_set_hdr(adapter, h2cbuf, FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_CH_SWITCH, 1, 0);
|
if (ret) {
|
adapter->sm.ch_switch = MAC_AX_OFLD_H2C_IDLE;
|
return ret;
|
}
|
ret = h2c_pkt_build_txd(adapter, h2cbuf);
|
if (ret) {
|
adapter->sm.ch_switch = MAC_AX_OFLD_H2C_IDLE;
|
return ret;
|
}
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cbuf);
|
#else
|
ret = PLTFM_TX(h2cbuf->data, h2cbuf->len);
|
#endif
|
h2cb_free(adapter, h2cbuf);
|
if (ret) {
|
adapter->sm.ch_switch = MAC_AX_OFLD_H2C_IDLE;
|
return ret;
|
}
|
h2c_end_flow(adapter);
|
return ret;
|
}
|
|
u32 mac_get_ch_switch_rpt(struct mac_ax_adapter *adapter, struct mac_ax_ch_switch_rpt *rpt)
|
{
|
struct mac_ax_state_mach *sm = &adapter->sm;
|
|
if (sm->ch_switch != MAC_AX_CH_SWITCH_GET_RPT)
|
return MACPROCERR;
|
PLTFM_MEMCPY(rpt, adapter->ch_switch_rpt, sizeof(struct mac_ax_ch_switch_rpt));
|
sm->ch_switch = MAC_AX_OFLD_H2C_IDLE;
|
return MACSUCCESS;
|
}
|
|
u32 mac_cfg_bcn_filter(struct mac_ax_adapter *adapter, struct mac_ax_bcn_fltr cfg)
|
{
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
u8 *buffer;
|
struct fwcmd_cfg_bcnfltr *write_ptr;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buffer = h2cb_put(h2cb, sizeof(struct fwcmd_cfg_bcnfltr));
|
if (!buffer) {
|
h2cb_free(adapter, h2cb);
|
return MACNOBUF;
|
}
|
|
write_ptr = (struct fwcmd_cfg_bcnfltr *)buffer;
|
write_ptr->dword0 = cpu_to_le32((cfg.mon_rssi ? FWCMD_H2C_CFG_BCNFLTR_MON_RSSI : 0) |
|
(cfg.mon_bcn ? FWCMD_H2C_CFG_BCNFLTR_MON_BCN : 0) |
|
(cfg.mon_tp ? FWCMD_H2C_CFG_BCNFLTR_MON_TP : 0) |
|
SET_WORD(cfg.tp_thld, FWCMD_H2C_CFG_BCNFLTR_TP_THLD) |
|
SET_WORD(cfg.bcn_loss_cnt,
|
FWCMD_H2C_CFG_BCNFLTR_BCN_LOSS_CNT) |
|
SET_WORD(cfg.rssi_hys, FWCMD_H2C_CFG_BCNFLTR_RSSI_HYS) |
|
SET_WORD(cfg.rssi_thld, FWCMD_H2C_CFG_BCNFLTR_RSSI_THLD) |
|
SET_WORD(cfg.macid, FWCMD_H2C_CFG_BCNFLTR_MACID));
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb, FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD,
|
FWCMD_H2C_FUNC_CFG_BCNFLTR,
|
0, 0);
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
h2cb_free(adapter, h2cb);
|
return MACSUCCESS;
|
}
|
|
u32 mac_bcn_filter_rssi(struct mac_ax_adapter *adapter, u8 macid, u8 size, u8 *rssi)
|
{
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
u8 *buffer;
|
u32 *buffer_32;
|
u32 *rssi_32;
|
struct fwcmd_ofld_rssi *write_ptr;
|
u8 append_size;
|
u8 sh;
|
|
if (size == 0)
|
return MACSETVALERR;
|
|
append_size = (size + 3) & (~0x3);
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buffer = h2cb_put(h2cb, sizeof(struct fwcmd_ofld_rssi) + append_size);
|
if (!buffer) {
|
h2cb_free(adapter, h2cb);
|
return MACNOBUF;
|
}
|
|
write_ptr = (struct fwcmd_ofld_rssi *)buffer;
|
write_ptr->dword0 = cpu_to_le32(SET_WORD(macid, FWCMD_H2C_OFLD_RSSI_MACID) |
|
SET_WORD(size, FWCMD_H2C_OFLD_RSSI_NUM_RSSI));
|
|
rssi_32 = (u32 *)rssi;
|
buffer_32 = ((u32 *)buffer) + 1;
|
for (sh = 0; sh < (append_size >> 2) ; sh++)
|
*(buffer_32 + sh) = cpu_to_le32(*(rssi_32 + sh));
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb, FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD,
|
FWCMD_H2C_FUNC_OFLD_RSSI,
|
0, 0);
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
h2cb_free(adapter, h2cb);
|
return MACSUCCESS;
|
}
|
|
u32 mac_bcn_filter_tp(struct mac_ax_adapter *adapter, u8 macid, u16 tx, u16 rx)
|
{
|
u32 ret;
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
u8 *buffer;
|
struct fwcmd_ofld_tp *write_ptr;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_DATA);
|
if (!h2cb)
|
return MACNPTR;
|
|
buffer = h2cb_put(h2cb, sizeof(struct fwcmd_ofld_tp));
|
if (!buffer) {
|
h2cb_free(adapter, h2cb);
|
return MACNOBUF;
|
}
|
|
write_ptr = (struct fwcmd_ofld_tp *)buffer;
|
write_ptr->dword0 = cpu_to_le32(SET_WORD(tx, FWCMD_H2C_OFLD_TP_TXTP) |
|
SET_WORD(rx, FWCMD_H2C_OFLD_TP_RXTP) |
|
SET_WORD(macid, FWCMD_H2C_OFLD_TP_MACID));
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb, FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_FW_OFLD,
|
FWCMD_H2C_FUNC_OFLD_TP,
|
0, 0);
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
ret = h2c_pkt_build_txd(adapter, h2cb);
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
#if MAC_AX_PHL_H2C
|
ret = PLTFM_TX(h2cb);
|
#else
|
ret = PLTFM_TX(h2cb->data, h2cb->len);
|
#endif
|
if (ret) {
|
h2cb_free(adapter, h2cb);
|
return ret;
|
}
|
|
h2cb_free(adapter, h2cb);
|
return MACSUCCESS;
|
}
|