Commit a0ec0169 authored by Golan Ben Ami's avatar Golan Ben Ami Committed by Luca Coelho

iwlwifi: support new tx api

22560 devices use a new tx cmd api. Update the code to use
the new api.
Signed-off-by: default avatarGolan Ben Ami <golan.ben.ami@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 7b3e42ea
...@@ -193,7 +193,8 @@ enum iwl_legacy_cmds { ...@@ -193,7 +193,8 @@ enum iwl_legacy_cmds {
FW_GET_ITEM_CMD = 0x1a, FW_GET_ITEM_CMD = 0x1a,
/** /**
* @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2, * @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or
* &struct iwl_tx_cmd_gen3,
* response in &struct iwl_mvm_tx_resp or * response in &struct iwl_mvm_tx_resp or
* &struct iwl_mvm_tx_resp_v3 * &struct iwl_mvm_tx_resp_v3
*/ */
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -320,6 +322,29 @@ struct iwl_tx_cmd_gen2 { ...@@ -320,6 +322,29 @@ struct iwl_tx_cmd_gen2 {
struct ieee80211_hdr hdr[0]; struct ieee80211_hdr hdr[0];
} __packed; /* TX_CMD_API_S_VER_7 */ } __packed; /* TX_CMD_API_S_VER_7 */
/**
* struct iwl_tx_cmd_gen3 - TX command struct to FW for 22560 devices
* ( TX_CMD = 0x1c )
* @len: in bytes of the payload, see below for details
* @flags: combination of &enum iwl_tx_cmd_flags
* @offload_assist: TX offload configuration
* @dram_info: FW internal DRAM storage
* @rate_n_flags: rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is
* cleared. Combination of RATE_MCS_*
* @ttl: time to live - packet lifetime limit. The FW should drop if
* passed.
* @hdr: 802.11 header
*/
struct iwl_tx_cmd_gen3 {
__le16 len;
__le16 flags;
__le32 offload_assist;
struct iwl_dram_sec_info dram_info;
__le32 rate_n_flags;
__le64 ttl;
struct ieee80211_hdr hdr[0];
} __packed; /* TX_CMD_API_S_VER_8 */
/* /*
* TX response related data * TX response related data
*/ */
......
...@@ -484,13 +484,15 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -484,13 +484,15 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
/* Make sure we zero enough of dev_cmd */ /* Make sure we zero enough of dev_cmd */
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) > sizeof(*tx_cmd)); BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) > sizeof(*tx_cmd));
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) > sizeof(*tx_cmd));
memset(dev_cmd, 0, sizeof(dev_cmd->hdr) + sizeof(*tx_cmd)); memset(dev_cmd, 0, sizeof(dev_cmd->hdr) + sizeof(*tx_cmd));
dev_cmd->hdr.cmd = TX_CMD; dev_cmd->hdr.cmd = TX_CMD;
if (iwl_mvm_has_new_tx_api(mvm)) { if (iwl_mvm_has_new_tx_api(mvm)) {
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
u16 offload_assist = 0; u16 offload_assist = 0;
u32 rate_n_flags = 0;
u16 flags = 0;
if (ieee80211_is_data_qos(hdr->frame_control)) { if (ieee80211_is_data_qos(hdr->frame_control)) {
u8 *qc = ieee80211_get_qos_ctl(hdr); u8 *qc = ieee80211_get_qos_ctl(hdr);
...@@ -507,7 +509,20 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -507,7 +509,20 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
!(offload_assist & BIT(TX_CMD_OFFLD_AMSDU))) !(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
offload_assist |= BIT(TX_CMD_OFFLD_PAD); offload_assist |= BIT(TX_CMD_OFFLD_PAD);
cmd->offload_assist |= cpu_to_le16(offload_assist); if (!info->control.hw_key)
flags |= IWL_TX_FLAGS_ENCRYPT_DIS;
/* For data packets rate info comes from the fw */
if (!(ieee80211_is_data(hdr->frame_control) && sta)) {
flags |= IWL_TX_FLAGS_CMD_RATE;
rate_n_flags = iwl_mvm_get_tx_rate(mvm, info, sta);
}
if (mvm->trans->cfg->device_family >=
IWL_DEVICE_FAMILY_22560) {
struct iwl_tx_cmd_gen3 *cmd = (void *)dev_cmd->payload;
cmd->offload_assist |= cpu_to_le32(offload_assist);
/* Total # bytes to be transmitted */ /* Total # bytes to be transmitted */
cmd->len = cpu_to_le16((u16)skb->len); cmd->len = cpu_to_le16((u16)skb->len);
...@@ -515,17 +530,22 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -515,17 +530,22 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
/* Copy MAC header from skb into command buffer */ /* Copy MAC header from skb into command buffer */
memcpy(cmd->hdr, hdr, hdrlen); memcpy(cmd->hdr, hdr, hdrlen);
if (!info->control.hw_key) cmd->flags = cpu_to_le16(flags);
cmd->flags |= cpu_to_le32(IWL_TX_FLAGS_ENCRYPT_DIS); cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
} else {
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
/* For data packets rate info comes from the fw */ cmd->offload_assist |= cpu_to_le16(offload_assist);
if (ieee80211_is_data(hdr->frame_control) && sta)
goto out; /* Total # bytes to be transmitted */
cmd->len = cpu_to_le16((u16)skb->len);
cmd->flags |= cpu_to_le32(IWL_TX_FLAGS_CMD_RATE); /* Copy MAC header from skb into command buffer */
cmd->rate_n_flags = memcpy(cmd->hdr, hdr, hdrlen);
cpu_to_le32(iwl_mvm_get_tx_rate(mvm, info, sta));
cmd->flags = cpu_to_le32(flags);
cmd->rate_n_flags = cpu_to_le32(rate_n_flags);
}
goto out; goto out;
} }
......
...@@ -402,8 +402,14 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans, ...@@ -402,8 +402,14 @@ struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
* (This calculation modifies the TX command, so do it before the * (This calculation modifies the TX command, so do it before the
* setup of the first TB) * setup of the first TB)
*/ */
len = sizeof(struct iwl_tx_cmd_gen2) + sizeof(struct iwl_cmd_header) + if (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560)
ieee80211_hdrlen(hdr->frame_control) - IWL_FIRST_TB_SIZE; len = sizeof(struct iwl_tx_cmd_gen2);
else
len = sizeof(struct iwl_tx_cmd_gen3);
len += sizeof(struct iwl_cmd_header) +
ieee80211_hdrlen(hdr->frame_control) -
IWL_FIRST_TB_SIZE;
/* do not align A-MSDU to dword as the subframe header aligns it */ /* do not align A-MSDU to dword as the subframe header aligns it */
if (amsdu) if (amsdu)
...@@ -480,9 +486,9 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, ...@@ -480,9 +486,9 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
struct iwl_device_cmd *dev_cmd, int txq_id) struct iwl_device_cmd *dev_cmd, int txq_id)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload;
struct iwl_cmd_meta *out_meta; struct iwl_cmd_meta *out_meta;
struct iwl_txq *txq = trans_pcie->txq[txq_id]; struct iwl_txq *txq = trans_pcie->txq[txq_id];
u16 cmd_len;
int idx; int idx;
void *tfd; void *tfd;
...@@ -497,6 +503,18 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, ...@@ -497,6 +503,18 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
spin_lock(&txq->lock); spin_lock(&txq->lock);
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
struct iwl_tx_cmd_gen3 *tx_cmd_gen3 =
(void *)dev_cmd->payload;
cmd_len = le16_to_cpu(tx_cmd_gen3->len);
} else {
struct iwl_tx_cmd_gen2 *tx_cmd_gen2 =
(void *)dev_cmd->payload;
cmd_len = le16_to_cpu(tx_cmd_gen2->len);
}
if (iwl_queue_space(trans, txq) < txq->high_mark) { if (iwl_queue_space(trans, txq) < txq->high_mark) {
iwl_stop_queue(trans, txq); iwl_stop_queue(trans, txq);
...@@ -535,7 +553,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb, ...@@ -535,7 +553,7 @@ int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
} }
/* Set up entry for this TFD in Tx byte-count array */ /* Set up entry for this TFD in Tx byte-count array */
iwl_pcie_gen2_update_byte_tbl(trans_pcie, txq, le16_to_cpu(tx_cmd->len), iwl_pcie_gen2_update_byte_tbl(trans_pcie, txq, cmd_len,
iwl_pcie_gen2_get_num_tbs(trans, tfd)); iwl_pcie_gen2_get_num_tbs(trans, tfd));
/* start timer if queue currently empty */ /* start timer if queue currently empty */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment