2 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <linux/kernel.h>
22 void mt76x02_tx(struct ieee80211_hw
*hw
, struct ieee80211_tx_control
*control
,
25 struct ieee80211_tx_info
*info
= IEEE80211_SKB_CB(skb
);
26 struct mt76x02_dev
*dev
= hw
->priv
;
27 struct ieee80211_vif
*vif
= info
->control
.vif
;
28 struct mt76_wcid
*wcid
= &dev
->mt76
.global_wcid
;
31 struct mt76x02_sta
*msta
;
33 msta
= (struct mt76x02_sta
*)control
->sta
->drv_priv
;
36 struct mt76x02_vif
*mvif
;
38 mvif
= (struct mt76x02_vif
*)vif
->drv_priv
;
39 wcid
= &mvif
->group_wcid
;
42 mt76_tx(&dev
->mt76
, control
->sta
, wcid
, skb
);
44 EXPORT_SYMBOL_GPL(mt76x02_tx
);
46 void mt76x02_queue_rx_skb(struct mt76_dev
*mdev
, enum mt76_rxq_id q
,
49 struct mt76x02_dev
*dev
= container_of(mdev
, struct mt76x02_dev
, mt76
);
50 void *rxwi
= skb
->data
;
52 if (q
== MT_RXQ_MCU
) {
53 /* this is used just by mmio code */
54 mt76_mcu_rx_event(&dev
->mt76
, skb
);
58 skb_pull(skb
, sizeof(struct mt76x02_rxwi
));
59 if (mt76x02_mac_process_rx(dev
, skb
, rxwi
)) {
64 mt76_rx(mdev
, q
, skb
);
66 EXPORT_SYMBOL_GPL(mt76x02_queue_rx_skb
);
68 s8
mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev
*dev
,
69 const struct ieee80211_tx_rate
*rate
)
73 if (rate
->flags
& IEEE80211_TX_RC_VHT_MCS
) {
74 u8 mcs
= ieee80211_rate_get_vht_mcs(rate
);
76 if (mcs
== 8 || mcs
== 9) {
77 max_txpwr
= dev
->mt76
.rate_power
.vht
[8];
81 nss
= ieee80211_rate_get_vht_nss(rate
);
82 idx
= ((nss
- 1) << 3) + mcs
;
83 max_txpwr
= dev
->mt76
.rate_power
.ht
[idx
& 0xf];
85 } else if (rate
->flags
& IEEE80211_TX_RC_MCS
) {
86 max_txpwr
= dev
->mt76
.rate_power
.ht
[rate
->idx
& 0xf];
88 enum nl80211_band band
= dev
->mt76
.chandef
.chan
->band
;
90 if (band
== NL80211_BAND_2GHZ
) {
91 const struct ieee80211_rate
*r
;
92 struct wiphy
*wiphy
= dev
->mt76
.hw
->wiphy
;
93 struct mt76_rate_power
*rp
= &dev
->mt76
.rate_power
;
95 r
= &wiphy
->bands
[band
]->bitrates
[rate
->idx
];
96 if (r
->flags
& IEEE80211_RATE_SHORT_PREAMBLE
)
97 max_txpwr
= rp
->cck
[r
->hw_value
& 0x3];
99 max_txpwr
= rp
->ofdm
[r
->hw_value
& 0x7];
101 max_txpwr
= dev
->mt76
.rate_power
.ofdm
[rate
->idx
& 0x7];
108 s8
mt76x02_tx_get_txpwr_adj(struct mt76x02_dev
*dev
, s8 txpwr
, s8 max_txpwr_adj
)
110 txpwr
= min_t(s8
, txpwr
, dev
->mt76
.txpower_conf
);
111 txpwr
-= (dev
->target_power
+ dev
->target_power_delta
[0]);
112 txpwr
= min_t(s8
, txpwr
, max_txpwr_adj
);
114 if (!dev
->enable_tpc
)
117 return min_t(s8
, txpwr
, 7);
119 return (txpwr
< -16) ? 8 : (txpwr
+ 32) / 2;
122 void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev
*dev
, s8 txpwr
)
126 txpwr_adj
= mt76x02_tx_get_txpwr_adj(dev
, txpwr
,
127 dev
->mt76
.rate_power
.ofdm
[4]);
128 mt76_rmw_field(dev
, MT_PROT_AUTO_TX_CFG
,
129 MT_PROT_AUTO_TX_CFG_PROT_PADJ
, txpwr_adj
);
130 mt76_rmw_field(dev
, MT_PROT_AUTO_TX_CFG
,
131 MT_PROT_AUTO_TX_CFG_AUTO_PADJ
, txpwr_adj
);
133 EXPORT_SYMBOL_GPL(mt76x02_tx_set_txpwr_auto
);
135 bool mt76x02_tx_status_data(struct mt76_dev
*mdev
, u8
*update
)
137 struct mt76x02_dev
*dev
= container_of(mdev
, struct mt76x02_dev
, mt76
);
138 struct mt76x02_tx_status stat
;
140 if (!mt76x02_mac_load_tx_status(dev
, &stat
))
143 mt76x02_send_tx_status(dev
, &stat
, update
);
147 EXPORT_SYMBOL_GPL(mt76x02_tx_status_data
);
149 int mt76x02_tx_prepare_skb(struct mt76_dev
*mdev
, void *txwi_ptr
,
150 enum mt76_txq_id qid
, struct mt76_wcid
*wcid
,
151 struct ieee80211_sta
*sta
,
152 struct mt76_tx_info
*tx_info
)
154 struct mt76x02_dev
*dev
= container_of(mdev
, struct mt76x02_dev
, mt76
);
155 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*)tx_info
->skb
->data
;
156 struct mt76x02_txwi
*txwi
= txwi_ptr
;
157 int hdrlen
, len
, pid
, qsel
= MT_QSEL_EDCA
;
159 if (qid
== MT_TXQ_PSD
&& wcid
&& wcid
->idx
< 128)
160 mt76x02_mac_wcid_set_drop(dev
, wcid
->idx
, false);
162 hdrlen
= ieee80211_hdrlen(hdr
->frame_control
);
163 len
= tx_info
->skb
->len
- (hdrlen
& 2);
164 mt76x02_mac_write_txwi(dev
, txwi
, tx_info
->skb
, wcid
, sta
, len
);
166 pid
= mt76_tx_status_skb_add(mdev
, wcid
, tx_info
->skb
);
169 if (pid
>= MT_PACKET_ID_FIRST
)
172 tx_info
->info
= FIELD_PREP(MT_TXD_INFO_QSEL
, qsel
) |
175 if (!wcid
|| wcid
->hw_key_idx
== 0xff || wcid
->sw_iv
)
176 tx_info
->info
|= MT_TXD_INFO_WIV
;
180 EXPORT_SYMBOL_GPL(mt76x02_tx_prepare_skb
);