mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
ath.git patch for v6.11
We have a single patch for the next 6.11-rc which introduces a workaround to ath12k which addresses a WCN7850 hardware issue that prevents proper operation with unaligned transmit buffers. -----BEGIN PGP SIGNATURE----- iIoEABYKADIWIQQ/mtSHzPUi16IfDEksFbugiYzLewUCZroXzBQcampvaG5zb25A a2VybmVsLm9yZwAKCRAsFbugiYzLe5oCAQC9wYFSc9ZTtNFNQ8dWd8+d1raE4sQz 3kb7k2JxJr1bOQD/Y1ytd68C1XUw8KZpo1PcYCcAjNNHYYCBKMG7u0Oiygo= =eueu -----END PGP SIGNATURE----- Merge tag 'ath-current-20240812' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath ath.git patch for v6.11 We have a single patch for the next 6.11-rc which introduces a workaround to ath12k which addresses a WCN7850 hardware issue that prevents proper operation with unaligned transmit buffers.
This commit is contained in:
commit
e37a9184f2
@ -162,6 +162,60 @@ static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath12k_dp_tx_move_payload(struct sk_buff *skb,
|
||||
unsigned long delta,
|
||||
bool head)
|
||||
{
|
||||
unsigned long len = skb->len;
|
||||
|
||||
if (head) {
|
||||
skb_push(skb, delta);
|
||||
memmove(skb->data, skb->data + delta, len);
|
||||
skb_trim(skb, len);
|
||||
} else {
|
||||
skb_put(skb, delta);
|
||||
memmove(skb->data + delta, skb->data, len);
|
||||
skb_pull(skb, delta);
|
||||
}
|
||||
}
|
||||
|
||||
static int ath12k_dp_tx_align_payload(struct ath12k_base *ab,
|
||||
struct sk_buff **pskb)
|
||||
{
|
||||
u32 iova_mask = ab->hw_params->iova_mask;
|
||||
unsigned long offset, delta1, delta2;
|
||||
struct sk_buff *skb2, *skb = *pskb;
|
||||
unsigned int headroom = skb_headroom(skb);
|
||||
int tailroom = skb_tailroom(skb);
|
||||
int ret = 0;
|
||||
|
||||
offset = (unsigned long)skb->data & iova_mask;
|
||||
delta1 = offset;
|
||||
delta2 = iova_mask - offset + 1;
|
||||
|
||||
if (headroom >= delta1) {
|
||||
ath12k_dp_tx_move_payload(skb, delta1, true);
|
||||
} else if (tailroom >= delta2) {
|
||||
ath12k_dp_tx_move_payload(skb, delta2, false);
|
||||
} else {
|
||||
skb2 = skb_realloc_headroom(skb, iova_mask);
|
||||
if (!skb2) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
offset = (unsigned long)skb2->data & iova_mask;
|
||||
if (offset)
|
||||
ath12k_dp_tx_move_payload(skb2, offset, true);
|
||||
*pskb = skb2;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -184,6 +238,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,
|
||||
bool tcl_ring_retry;
|
||||
bool msdu_ext_desc = false;
|
||||
bool add_htt_metadata = false;
|
||||
u32 iova_mask = ab->hw_params->iova_mask;
|
||||
|
||||
if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
|
||||
return -ESHUTDOWN;
|
||||
@ -279,6 +334,23 @@ tcl_ring_sel:
|
||||
goto fail_remove_tx_buf;
|
||||
}
|
||||
|
||||
if (iova_mask &&
|
||||
(unsigned long)skb->data & iova_mask) {
|
||||
ret = ath12k_dp_tx_align_payload(ab, &skb);
|
||||
if (ret) {
|
||||
ath12k_warn(ab, "failed to align TX buffer %d\n", ret);
|
||||
/* don't bail out, give original buffer
|
||||
* a chance even unaligned.
|
||||
*/
|
||||
goto map;
|
||||
}
|
||||
|
||||
/* hdr is pointing to a wrong place after alignment,
|
||||
* so refresh it for later use.
|
||||
*/
|
||||
hdr = (void *)skb->data;
|
||||
}
|
||||
map:
|
||||
ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(ab->dev, ti.paddr)) {
|
||||
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
|
||||
|
@ -924,6 +924,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
|
||||
.acpi_guid = NULL,
|
||||
.supports_dynamic_smps_6ghz = true,
|
||||
|
||||
.iova_mask = 0,
|
||||
},
|
||||
{
|
||||
.name = "wcn7850 hw2.0",
|
||||
@ -1000,6 +1002,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
|
||||
.acpi_guid = &wcn7850_uuid,
|
||||
.supports_dynamic_smps_6ghz = false,
|
||||
|
||||
.iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1,
|
||||
},
|
||||
{
|
||||
.name = "qcn9274 hw2.0",
|
||||
@ -1072,6 +1076,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
|
||||
|
||||
.acpi_guid = NULL,
|
||||
.supports_dynamic_smps_6ghz = true,
|
||||
|
||||
.iova_mask = 0,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -96,6 +96,8 @@
|
||||
#define ATH12K_M3_FILE "m3.bin"
|
||||
#define ATH12K_REGDB_FILE_NAME "regdb.bin"
|
||||
|
||||
#define ATH12K_PCIE_MAX_PAYLOAD_SIZE 128
|
||||
|
||||
enum ath12k_hw_rate_cck {
|
||||
ATH12K_HW_RATE_CCK_LP_11M = 0,
|
||||
ATH12K_HW_RATE_CCK_LP_5_5M,
|
||||
@ -215,6 +217,8 @@ struct ath12k_hw_params {
|
||||
|
||||
const guid_t *acpi_guid;
|
||||
bool supports_dynamic_smps_6ghz;
|
||||
|
||||
u32 iova_mask;
|
||||
};
|
||||
|
||||
struct ath12k_hw_ops {
|
||||
|
@ -9193,6 +9193,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
|
||||
|
||||
hw->vif_data_size = sizeof(struct ath12k_vif);
|
||||
hw->sta_data_size = sizeof(struct ath12k_sta);
|
||||
hw->extra_tx_headroom = ab->hw_params->iova_mask;
|
||||
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
|
||||
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_STA_TX_PWR);
|
||||
|
Loading…
Reference in New Issue
Block a user