/******************************************************************************
|
*
|
* 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 "twt.h"
|
|
u32 mac_twt_info_upd_h2c(struct mac_ax_adapter *adapter,
|
struct mac_ax_twt_para *info)
|
{
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_twtinfo_upd *hdr;
|
u32 ret = MACSUCCESS;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
hdr = (struct fwcmd_twtinfo_upd *)
|
h2cb_put(h2cb, sizeof(struct fwcmd_twtinfo_upd));
|
if (!hdr) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
/* port 4 not support */
|
if (info->port >= MAC_AX_PORT_4) {
|
PLTFM_MSG_ERR("[ERR] twt info upd h2c port %d\n", info->port);
|
return MACFUNCINPUT;
|
}
|
|
hdr->dword0 =
|
cpu_to_le32(SET_WORD(info->nego_tp,
|
FWCMD_H2C_TWTINFO_UPD_NEGOTYPE) |
|
SET_WORD(info->act, FWCMD_H2C_TWTINFO_UPD_ACT) |
|
(info->trig ? FWCMD_H2C_TWTINFO_UPD_TRIGGER : 0) |
|
(info->flow_tp ?
|
FWCMD_H2C_TWTINFO_UPD_FLOWTYPE : 0) |
|
(info->impt ? FWCMD_H2C_TWTINFO_UPD_IMPT : 0) |
|
(info->wake_unit ?
|
FWCMD_H2C_TWTINFO_UPD_WAKEDURUNIT : 0) |
|
(info->rsp_pm ? FWCMD_H2C_TWTINFO_UPD_RSPPM : 0) |
|
(info->proct ? FWCMD_H2C_TWTINFO_UPD_PROT : 0) |
|
SET_WORD(info->flow_id,
|
FWCMD_H2C_TWTINFO_UPD_FLOWID) |
|
SET_WORD(info->id, FWCMD_H2C_TWTINFO_UPD_ID) |
|
(info->band ? FWCMD_H2C_TWTINFO_UPD_BAND : 0) |
|
SET_WORD(info->port, FWCMD_H2C_TWTINFO_UPD_PORT));
|
|
hdr->dword1 =
|
cpu_to_le32(SET_WORD(info->wake_exp,
|
FWCMD_H2C_TWTINFO_UPD_WAKE_EXP) |
|
SET_WORD(info->wake_man,
|
FWCMD_H2C_TWTINFO_UPD_WAKE_MAN) |
|
SET_WORD(info->twtulfixmode,
|
FWCMD_H2C_TWTINFO_UPD_ULFIXMODE) |
|
SET_WORD(info->dur,
|
FWCMD_H2C_TWTINFO_UPD_DUR));
|
|
hdr->dword2 =
|
cpu_to_le32(SET_WORD(info->trgt_l,
|
FWCMD_H2C_TWTINFO_UPD_TGT_L));
|
|
hdr->dword3 =
|
cpu_to_le32(SET_WORD(info->trgt_h,
|
FWCMD_H2C_TWTINFO_UPD_TGT_H));
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C,
|
FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_TWT,
|
FWCMD_H2C_FUNC_TWTINFO_UPD,
|
0,
|
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)
|
goto fail;
|
|
h2cb_free(adapter, h2cb);
|
|
h2c_end_flow(adapter);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
u32 mac_twt_act_h2c(struct mac_ax_adapter *adapter,
|
struct mac_ax_twtact_para *info)
|
{
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_twt_stansp_upd *hdr;
|
u32 ret = MACSUCCESS;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
hdr = (struct fwcmd_twt_stansp_upd *)
|
h2cb_put(h2cb, sizeof(struct fwcmd_twt_stansp_upd));
|
if (!hdr) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
hdr->dword0 =
|
cpu_to_le32(SET_WORD(info->macid,
|
FWCMD_H2C_TWT_STANSP_UPD_MACID) |
|
SET_WORD(info->id,
|
FWCMD_H2C_TWT_STANSP_UPD_ID) |
|
SET_WORD(info->act,
|
FWCMD_H2C_TWT_STANSP_UPD_ACT));
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C,
|
FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_TWT,
|
FWCMD_H2C_FUNC_TWT_STANSP_UPD,
|
0,
|
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)
|
goto fail;
|
|
h2cb_free(adapter, h2cb);
|
|
h2c_end_flow(adapter);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
u32 mac_twt_staanno_h2c(struct mac_ax_adapter *adapter,
|
struct mac_ax_twtanno_para *info)
|
{
|
#if MAC_AX_PHL_H2C
|
struct rtw_h2c_pkt *h2cb;
|
#else
|
struct h2c_buf *h2cb;
|
#endif
|
struct fwcmd_twt_announce_upd *hdr;
|
u32 ret = MACSUCCESS;
|
|
h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD);
|
if (!h2cb)
|
return MACNPTR;
|
|
hdr = (struct fwcmd_twt_announce_upd *)h2cb_put(h2cb,
|
sizeof(struct fwcmd_twt_announce_upd));
|
if (!hdr) {
|
ret = MACNOBUF;
|
goto fail;
|
}
|
|
hdr->dword0 =
|
cpu_to_le32(SET_WORD(info->macid, FWCMD_H2C_TWT_ANNOUNCE_UPD_MACID));
|
|
ret = h2c_pkt_set_hdr(adapter, h2cb,
|
FWCMD_TYPE_H2C,
|
FWCMD_H2C_CAT_MAC,
|
FWCMD_H2C_CL_TWT,
|
FWCMD_H2C_FUNC_TWT_ANNOUNCE_UPD,
|
1,
|
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)
|
goto fail;
|
|
h2cb_free(adapter, h2cb);
|
|
h2c_end_flow(adapter);
|
|
return MACSUCCESS;
|
fail:
|
h2cb_free(adapter, h2cb);
|
|
return ret;
|
}
|
|
void mac_twt_wait_anno(struct mac_ax_adapter *adapter,
|
u8 *c2h_content, u8 *upd_addr)
|
{
|
u32 plat_c2h_content = *(u32 *)(c2h_content);
|
struct mac_ax_twtanno_c2hpara *para =
|
(struct mac_ax_twtanno_c2hpara *)upd_addr;
|
|
para->wait_case = GET_FIELD(plat_c2h_content,
|
FWCMD_C2H_WAIT_ANNOUNCE_WAIT_CASE);
|
para->macid0 = GET_FIELD(plat_c2h_content,
|
FWCMD_C2H_WAIT_ANNOUNCE_MACID0);
|
para->macid1 = GET_FIELD(plat_c2h_content,
|
FWCMD_C2H_WAIT_ANNOUNCE_MACID1);
|
para->macid2 = GET_FIELD(plat_c2h_content,
|
FWCMD_C2H_WAIT_ANNOUNCE_MACID2);
|
}
|
|
void mac_get_tsf(struct mac_ax_adapter *adapter,
|
struct mac_ax_port_tsf *tsf)
|
{
|
struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter);
|
u32 reg_l = 0;
|
u32 reg_h = 0;
|
|
switch (tsf->port) {
|
case 0:
|
reg_h = R_AX_TSFTR_HIGH_P0;
|
reg_l = R_AX_TSFTR_LOW_P0;
|
break;
|
case 1:
|
reg_h = R_AX_TSFTR_HIGH_P1;
|
reg_l = R_AX_TSFTR_LOW_P1;
|
break;
|
case 2:
|
reg_h = R_AX_TSFTR_HIGH_P2;
|
reg_l = R_AX_TSFTR_LOW_P2;
|
break;
|
case 3:
|
reg_h = R_AX_TSFTR_HIGH_P3;
|
reg_l = R_AX_TSFTR_LOW_P3;
|
break;
|
default:
|
reg_h = R_AX_TSFTR_HIGH_P0;
|
reg_l = R_AX_TSFTR_LOW_P0;
|
break;
|
}
|
|
tsf->tsf_h = MAC_REG_R32(reg_h);
|
tsf->tsf_l = MAC_REG_R32(reg_l);
|
}
|