提交 a72e25f7 编写于 作者: J John W. Linville

Merge branch 'for-linville' of git://github.com/kvalo/ath

...@@ -283,7 +283,7 @@ static int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -283,7 +283,7 @@ static int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
if (unlikely(CE_RING_DELTA(nentries_mask, if (unlikely(CE_RING_DELTA(nentries_mask,
write_index, sw_index - 1) <= 0)) { write_index, sw_index - 1) <= 0)) {
ret = -EIO; ret = -ENOSR;
goto exit; goto exit;
} }
...@@ -338,38 +338,19 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, ...@@ -338,38 +338,19 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
return ret; return ret;
} }
int ath10k_ce_sendlist_send(struct ath10k_ce_pipe *ce_state, int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe)
void *per_transfer_context,
unsigned int transfer_id,
u32 paddr, unsigned int nbytes,
u32 flags)
{ {
struct ath10k_ce_ring *src_ring = ce_state->src_ring; struct ath10k *ar = pipe->ar;
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
unsigned int nentries_mask = src_ring->nentries_mask; int delta;
unsigned int sw_index;
unsigned int write_index;
int delta, ret = -ENOMEM;
spin_lock_bh(&ar_pci->ce_lock); spin_lock_bh(&ar_pci->ce_lock);
delta = CE_RING_DELTA(pipe->src_ring->nentries_mask,
sw_index = src_ring->sw_index; pipe->src_ring->write_index,
write_index = src_ring->write_index; pipe->src_ring->sw_index - 1);
delta = CE_RING_DELTA(nentries_mask, write_index, sw_index - 1);
if (delta >= 1) {
ret = ath10k_ce_send_nolock(ce_state, per_transfer_context,
paddr, nbytes,
transfer_id, flags);
if (ret)
ath10k_warn("CE send failed: %d\n", ret);
}
spin_unlock_bh(&ar_pci->ce_lock); spin_unlock_bh(&ar_pci->ce_lock);
return ret; return delta;
} }
int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state, int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state,
......
...@@ -156,21 +156,7 @@ void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, ...@@ -156,21 +156,7 @@ void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
void (*send_cb)(struct ath10k_ce_pipe *), void (*send_cb)(struct ath10k_ce_pipe *),
int disable_interrupts); int disable_interrupts);
/* int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe);
* Queue a "sendlist" of buffers to be sent using gather to a single
* anonymous destination buffer
* ce - which copy engine to use
* sendlist - list of simple buffers to send using gather
* transfer_id - arbitrary ID; reflected to destination
* Returns 0 on success; otherwise an error status.
*
* Implemenation note: Pushes multiple buffers with Gather to Source ring.
*/
int ath10k_ce_sendlist_send(struct ath10k_ce_pipe *ce_state,
void *per_transfer_context,
unsigned int transfer_id,
u32 paddr, unsigned int nbytes,
u32 flags);
/*==================Recv=======================*/ /*==================Recv=======================*/
......
...@@ -59,27 +59,6 @@ static void ath10k_send_suspend_complete(struct ath10k *ar) ...@@ -59,27 +59,6 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
wake_up(&ar->event_queue); wake_up(&ar->event_queue);
} }
static int ath10k_check_fw_version(struct ath10k *ar)
{
char version[32];
if (ar->fw_version_major >= SUPPORTED_FW_MAJOR &&
ar->fw_version_minor >= SUPPORTED_FW_MINOR &&
ar->fw_version_release >= SUPPORTED_FW_RELEASE &&
ar->fw_version_build >= SUPPORTED_FW_BUILD)
return 0;
snprintf(version, sizeof(version), "%u.%u.%u.%u",
SUPPORTED_FW_MAJOR, SUPPORTED_FW_MINOR,
SUPPORTED_FW_RELEASE, SUPPORTED_FW_BUILD);
ath10k_warn("WARNING: Firmware version %s is not officially supported.\n",
ar->hw->wiphy->fw_version);
ath10k_warn("Please upgrade to version %s (or newer)\n", version);
return 0;
}
static int ath10k_init_connect_htc(struct ath10k *ar) static int ath10k_init_connect_htc(struct ath10k *ar)
{ {
int status; int status;
...@@ -189,8 +168,7 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, ...@@ -189,8 +168,7 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
return fw; return fw;
} }
static int ath10k_push_board_ext_data(struct ath10k *ar, static int ath10k_push_board_ext_data(struct ath10k *ar)
const struct firmware *fw)
{ {
u32 board_data_size = QCA988X_BOARD_DATA_SZ; u32 board_data_size = QCA988X_BOARD_DATA_SZ;
u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ;
...@@ -210,14 +188,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, ...@@ -210,14 +188,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar,
if (board_ext_data_addr == 0) if (board_ext_data_addr == 0)
return 0; return 0;
if (fw->size != (board_data_size + board_ext_data_size)) { if (ar->board_len != (board_data_size + board_ext_data_size)) {
ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n", ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n",
fw->size, board_data_size, board_ext_data_size); ar->board_len, board_data_size, board_ext_data_size);
return -EINVAL; return -EINVAL;
} }
ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, ret = ath10k_bmi_write_memory(ar, board_ext_data_addr,
fw->data + board_data_size, ar->board_data + board_data_size,
board_ext_data_size); board_ext_data_size);
if (ret) { if (ret) {
ath10k_err("could not write board ext data (%d)\n", ret); ath10k_err("could not write board ext data (%d)\n", ret);
...@@ -236,12 +214,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, ...@@ -236,12 +214,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar,
static int ath10k_download_board_data(struct ath10k *ar) static int ath10k_download_board_data(struct ath10k *ar)
{ {
const struct firmware *fw = ar->board_data;
u32 board_data_size = QCA988X_BOARD_DATA_SZ; u32 board_data_size = QCA988X_BOARD_DATA_SZ;
u32 address; u32 address;
int ret; int ret;
ret = ath10k_push_board_ext_data(ar, fw); ret = ath10k_push_board_ext_data(ar);
if (ret) { if (ret) {
ath10k_err("could not push board ext data (%d)\n", ret); ath10k_err("could not push board ext data (%d)\n", ret);
goto exit; goto exit;
...@@ -253,8 +230,9 @@ static int ath10k_download_board_data(struct ath10k *ar) ...@@ -253,8 +230,9 @@ static int ath10k_download_board_data(struct ath10k *ar)
goto exit; goto exit;
} }
ret = ath10k_bmi_write_memory(ar, address, fw->data, ret = ath10k_bmi_write_memory(ar, address, ar->board_data,
min_t(u32, board_data_size, fw->size)); min_t(u32, board_data_size,
ar->board_len));
if (ret) { if (ret) {
ath10k_err("could not write board data (%d)\n", ret); ath10k_err("could not write board data (%d)\n", ret);
goto exit; goto exit;
...@@ -272,17 +250,16 @@ static int ath10k_download_board_data(struct ath10k *ar) ...@@ -272,17 +250,16 @@ static int ath10k_download_board_data(struct ath10k *ar)
static int ath10k_download_and_run_otp(struct ath10k *ar) static int ath10k_download_and_run_otp(struct ath10k *ar)
{ {
const struct firmware *fw = ar->otp;
u32 address = ar->hw_params.patch_load_addr; u32 address = ar->hw_params.patch_load_addr;
u32 exec_param; u32 exec_param;
int ret; int ret;
/* OTP is optional */ /* OTP is optional */
if (!ar->otp) if (!ar->otp_data || !ar->otp_len)
return 0; return 0;
ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size); ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
if (ret) { if (ret) {
ath10k_err("could not write otp (%d)\n", ret); ath10k_err("could not write otp (%d)\n", ret);
goto exit; goto exit;
...@@ -301,13 +278,13 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) ...@@ -301,13 +278,13 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
static int ath10k_download_fw(struct ath10k *ar) static int ath10k_download_fw(struct ath10k *ar)
{ {
const struct firmware *fw = ar->firmware;
u32 address; u32 address;
int ret; int ret;
address = ar->hw_params.patch_load_addr; address = ar->hw_params.patch_load_addr;
ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size); ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data,
ar->firmware_len);
if (ret) { if (ret) {
ath10k_err("could not write fw (%d)\n", ret); ath10k_err("could not write fw (%d)\n", ret);
goto exit; goto exit;
...@@ -319,8 +296,8 @@ static int ath10k_download_fw(struct ath10k *ar) ...@@ -319,8 +296,8 @@ static int ath10k_download_fw(struct ath10k *ar)
static void ath10k_core_free_firmware_files(struct ath10k *ar) static void ath10k_core_free_firmware_files(struct ath10k *ar)
{ {
if (ar->board_data && !IS_ERR(ar->board_data)) if (ar->board && !IS_ERR(ar->board))
release_firmware(ar->board_data); release_firmware(ar->board);
if (ar->otp && !IS_ERR(ar->otp)) if (ar->otp && !IS_ERR(ar->otp))
release_firmware(ar->otp); release_firmware(ar->otp);
...@@ -328,12 +305,20 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ...@@ -328,12 +305,20 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
if (ar->firmware && !IS_ERR(ar->firmware)) if (ar->firmware && !IS_ERR(ar->firmware))
release_firmware(ar->firmware); release_firmware(ar->firmware);
ar->board = NULL;
ar->board_data = NULL; ar->board_data = NULL;
ar->board_len = 0;
ar->otp = NULL; ar->otp = NULL;
ar->otp_data = NULL;
ar->otp_len = 0;
ar->firmware = NULL; ar->firmware = NULL;
ar->firmware_data = NULL;
ar->firmware_len = 0;
} }
static int ath10k_core_fetch_firmware_files(struct ath10k *ar) static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
{ {
int ret = 0; int ret = 0;
...@@ -347,15 +332,18 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ...@@ -347,15 +332,18 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
return -EINVAL; return -EINVAL;
} }
ar->board_data = ath10k_fetch_fw_file(ar, ar->board = ath10k_fetch_fw_file(ar,
ar->hw_params.fw.dir, ar->hw_params.fw.dir,
ar->hw_params.fw.board); ar->hw_params.fw.board);
if (IS_ERR(ar->board_data)) { if (IS_ERR(ar->board)) {
ret = PTR_ERR(ar->board_data); ret = PTR_ERR(ar->board);
ath10k_err("could not fetch board data (%d)\n", ret); ath10k_err("could not fetch board data (%d)\n", ret);
goto err; goto err;
} }
ar->board_data = ar->board->data;
ar->board_len = ar->board->size;
ar->firmware = ath10k_fetch_fw_file(ar, ar->firmware = ath10k_fetch_fw_file(ar,
ar->hw_params.fw.dir, ar->hw_params.fw.dir,
ar->hw_params.fw.fw); ar->hw_params.fw.fw);
...@@ -365,6 +353,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ...@@ -365,6 +353,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
goto err; goto err;
} }
ar->firmware_data = ar->firmware->data;
ar->firmware_len = ar->firmware->size;
/* OTP may be undefined. If so, don't fetch it at all */ /* OTP may be undefined. If so, don't fetch it at all */
if (ar->hw_params.fw.otp == NULL) if (ar->hw_params.fw.otp == NULL)
return 0; return 0;
...@@ -378,6 +369,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ...@@ -378,6 +369,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
goto err; goto err;
} }
ar->otp_data = ar->otp->data;
ar->otp_len = ar->otp->size;
return 0; return 0;
err: err:
...@@ -385,6 +379,191 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ...@@ -385,6 +379,191 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
return ret; return ret;
} }
static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
{
size_t magic_len, len, ie_len;
int ie_id, i, index, bit, ret;
struct ath10k_fw_ie *hdr;
const u8 *data;
__le32 *timestamp;
/* first fetch the firmware file (firmware-*.bin) */
ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
if (IS_ERR(ar->firmware)) {
ath10k_err("Could not fetch firmware file '%s': %ld\n",
name, PTR_ERR(ar->firmware));
return PTR_ERR(ar->firmware);
}
data = ar->firmware->data;
len = ar->firmware->size;
/* magic also includes the null byte, check that as well */
magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
if (len < magic_len) {
ath10k_err("firmware image too small to contain magic: %zu\n",
len);
ret = -EINVAL;
goto err;
}
if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
ath10k_err("Invalid firmware magic\n");
ret = -EINVAL;
goto err;
}
/* jump over the padding */
magic_len = ALIGN(magic_len, 4);
len -= magic_len;
data += magic_len;
/* loop elements */
while (len > sizeof(struct ath10k_fw_ie)) {
hdr = (struct ath10k_fw_ie *)data;
ie_id = le32_to_cpu(hdr->id);
ie_len = le32_to_cpu(hdr->len);
len -= sizeof(*hdr);
data += sizeof(*hdr);
if (len < ie_len) {
ath10k_err("Invalid length for FW IE %d (%zu < %zu)\n",
ie_id, len, ie_len);
ret = -EINVAL;
goto err;
}
switch (ie_id) {
case ATH10K_FW_IE_FW_VERSION:
if (ie_len > sizeof(ar->hw->wiphy->fw_version) - 1)
break;
memcpy(ar->hw->wiphy->fw_version, data, ie_len);
ar->hw->wiphy->fw_version[ie_len] = '\0';
ath10k_dbg(ATH10K_DBG_BOOT,
"found fw version %s\n",
ar->hw->wiphy->fw_version);
break;
case ATH10K_FW_IE_TIMESTAMP:
if (ie_len != sizeof(u32))
break;
timestamp = (__le32 *)data;
ath10k_dbg(ATH10K_DBG_BOOT, "found fw timestamp %d\n",
le32_to_cpup(timestamp));
break;
case ATH10K_FW_IE_FEATURES:
ath10k_dbg(ATH10K_DBG_BOOT,
"found firmware features ie (%zd B)\n",
ie_len);
for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {
index = i / 8;
bit = i % 8;
if (index == ie_len)
break;
if (data[index] & (1 << bit))
__set_bit(i, ar->fw_features);
}
ath10k_dbg_dump(ATH10K_DBG_BOOT, "features", "",
ar->fw_features,
sizeof(ar->fw_features));
break;
case ATH10K_FW_IE_FW_IMAGE:
ath10k_dbg(ATH10K_DBG_BOOT,
"found fw image ie (%zd B)\n",
ie_len);
ar->firmware_data = data;
ar->firmware_len = ie_len;
break;
case ATH10K_FW_IE_OTP_IMAGE:
ath10k_dbg(ATH10K_DBG_BOOT,
"found otp image ie (%zd B)\n",
ie_len);
ar->otp_data = data;
ar->otp_len = ie_len;
break;
default:
ath10k_warn("Unknown FW IE: %u\n",
le32_to_cpu(hdr->id));
break;
}
/* jump over the padding */
ie_len = ALIGN(ie_len, 4);
len -= ie_len;
data += ie_len;
}
if (!ar->firmware_data || !ar->firmware_len) {
ath10k_warn("No ATH10K_FW_IE_FW_IMAGE found from %s, skipping\n",
name);
ret = -ENOMEDIUM;
goto err;
}
/* now fetch the board file */
if (ar->hw_params.fw.board == NULL) {
ath10k_err("board data file not defined");
ret = -EINVAL;
goto err;
}
ar->board = ath10k_fetch_fw_file(ar,
ar->hw_params.fw.dir,
ar->hw_params.fw.board);
if (IS_ERR(ar->board)) {
ret = PTR_ERR(ar->board);
ath10k_err("could not fetch board data (%d)\n", ret);
goto err;
}
ar->board_data = ar->board->data;
ar->board_len = ar->board->size;
return 0;
err:
ath10k_core_free_firmware_files(ar);
return ret;
}
static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
{
int ret;
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE);
if (ret == 0) {
ar->fw_api = 2;
goto out;
}
ret = ath10k_core_fetch_firmware_api_1(ar);
if (ret)
return ret;
ar->fw_api = 1;
out:
ath10k_dbg(ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
return 0;
}
static int ath10k_init_download_firmware(struct ath10k *ar) static int ath10k_init_download_firmware(struct ath10k *ar)
{ {
int ret; int ret;
...@@ -541,6 +720,9 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, ...@@ -541,6 +720,9 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
skb_queue_head_init(&ar->offchan_tx_queue); skb_queue_head_init(&ar->offchan_tx_queue);
INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work);
skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
init_waitqueue_head(&ar->event_queue); init_waitqueue_head(&ar->event_queue);
INIT_WORK(&ar->restart_work, ath10k_core_restart); INIT_WORK(&ar->restart_work, ath10k_core_restart);
...@@ -555,6 +737,8 @@ EXPORT_SYMBOL(ath10k_core_create); ...@@ -555,6 +737,8 @@ EXPORT_SYMBOL(ath10k_core_create);
void ath10k_core_destroy(struct ath10k *ar) void ath10k_core_destroy(struct ath10k *ar)
{ {
ath10k_debug_destroy(ar);
flush_workqueue(ar->workqueue); flush_workqueue(ar->workqueue);
destroy_workqueue(ar->workqueue); destroy_workqueue(ar->workqueue);
...@@ -566,6 +750,8 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -566,6 +750,8 @@ int ath10k_core_start(struct ath10k *ar)
{ {
int status; int status;
lockdep_assert_held(&ar->conf_mutex);
ath10k_bmi_start(ar); ath10k_bmi_start(ar);
if (ath10k_init_configure_target(ar)) { if (ath10k_init_configure_target(ar)) {
...@@ -616,10 +802,6 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -616,10 +802,6 @@ int ath10k_core_start(struct ath10k *ar)
ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version); ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version);
status = ath10k_check_fw_version(ar);
if (status)
goto err_disconnect_htc;
status = ath10k_wmi_cmd_init(ar); status = ath10k_wmi_cmd_init(ar);
if (status) { if (status) {
ath10k_err("could not send WMI init command (%d)\n", status); ath10k_err("could not send WMI init command (%d)\n", status);
...@@ -642,6 +824,7 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -642,6 +824,7 @@ int ath10k_core_start(struct ath10k *ar)
goto err_disconnect_htc; goto err_disconnect_htc;
ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
INIT_LIST_HEAD(&ar->arvifs);
return 0; return 0;
...@@ -658,6 +841,8 @@ EXPORT_SYMBOL(ath10k_core_start); ...@@ -658,6 +841,8 @@ EXPORT_SYMBOL(ath10k_core_start);
void ath10k_core_stop(struct ath10k *ar) void ath10k_core_stop(struct ath10k *ar)
{ {
lockdep_assert_held(&ar->conf_mutex);
ath10k_debug_stop(ar); ath10k_debug_stop(ar);
ath10k_htc_stop(&ar->htc); ath10k_htc_stop(&ar->htc);
ath10k_htt_detach(&ar->htt); ath10k_htt_detach(&ar->htt);
...@@ -705,15 +890,21 @@ static int ath10k_core_probe_fw(struct ath10k *ar) ...@@ -705,15 +890,21 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
return ret; return ret;
} }
mutex_lock(&ar->conf_mutex);
ret = ath10k_core_start(ar); ret = ath10k_core_start(ar);
if (ret) { if (ret) {
ath10k_err("could not init core (%d)\n", ret); ath10k_err("could not init core (%d)\n", ret);
ath10k_core_free_firmware_files(ar); ath10k_core_free_firmware_files(ar);
ath10k_hif_power_down(ar); ath10k_hif_power_down(ar);
mutex_unlock(&ar->conf_mutex);
return ret; return ret;
} }
ath10k_core_stop(ar); ath10k_core_stop(ar);
mutex_unlock(&ar->conf_mutex);
ath10k_hif_power_down(ar); ath10k_hif_power_down(ar);
return 0; return 0;
} }
......
...@@ -43,15 +43,17 @@ ...@@ -43,15 +43,17 @@
/* Antenna noise floor */ /* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95 #define ATH10K_DEFAULT_NOISE_FLOOR -95
#define ATH10K_MAX_NUM_MGMT_PENDING 16
struct ath10k; struct ath10k;
struct ath10k_skb_cb { struct ath10k_skb_cb {
dma_addr_t paddr; dma_addr_t paddr;
bool is_mapped; bool is_mapped;
bool is_aborted; bool is_aborted;
u8 vdev_id;
struct { struct {
u8 vdev_id;
u8 tid; u8 tid;
bool is_offchan; bool is_offchan;
...@@ -102,11 +104,26 @@ struct ath10k_bmi { ...@@ -102,11 +104,26 @@ struct ath10k_bmi {
bool done_sent; bool done_sent;
}; };
#define ATH10K_MAX_MEM_REQS 16
struct ath10k_mem_chunk {
void *vaddr;
dma_addr_t paddr;
u32 len;
u32 req_id;
};
struct ath10k_wmi { struct ath10k_wmi {
enum ath10k_htc_ep_id eid; enum ath10k_htc_ep_id eid;
struct completion service_ready; struct completion service_ready;
struct completion unified_ready; struct completion unified_ready;
wait_queue_head_t tx_credits_wq; wait_queue_head_t tx_credits_wq;
struct wmi_cmd_map *cmd;
struct wmi_vdev_param_map *vdev_param;
struct wmi_pdev_param_map *pdev_param;
u32 num_mem_chunks;
struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS];
}; };
struct ath10k_peer_stat { struct ath10k_peer_stat {
...@@ -188,6 +205,8 @@ struct ath10k_peer { ...@@ -188,6 +205,8 @@ struct ath10k_peer {
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
struct ath10k_vif { struct ath10k_vif {
struct list_head list;
u32 vdev_id; u32 vdev_id;
enum wmi_vdev_type vdev_type; enum wmi_vdev_type vdev_type;
enum wmi_vdev_subtype vdev_subtype; enum wmi_vdev_subtype vdev_subtype;
...@@ -198,8 +217,10 @@ struct ath10k_vif { ...@@ -198,8 +217,10 @@ struct ath10k_vif {
struct ath10k *ar; struct ath10k *ar;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
struct work_struct wep_key_work;
struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1];
u8 def_wep_key_index; u8 def_wep_key_idx;
u8 def_wep_key_newidx;
u16 tx_seq_no; u16 tx_seq_no;
...@@ -268,6 +289,12 @@ enum ath10k_fw_features { ...@@ -268,6 +289,12 @@ enum ath10k_fw_features {
/* wmi_mgmt_rx_hdr contains extra RSSI information */ /* wmi_mgmt_rx_hdr contains extra RSSI information */
ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0, ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0,
/* firmware from 10X branch */
ATH10K_FW_FEATURE_WMI_10X = 1,
/* firmware support tx frame management over WMI, otherwise it's HTT */
ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX = 2,
/* keep last */ /* keep last */
ATH10K_FW_FEATURE_COUNT, ATH10K_FW_FEATURE_COUNT,
}; };
...@@ -324,9 +351,19 @@ struct ath10k { ...@@ -324,9 +351,19 @@ struct ath10k {
} fw; } fw;
} hw_params; } hw_params;
const struct firmware *board_data; const struct firmware *board;
const void *board_data;
size_t board_len;
const struct firmware *otp; const struct firmware *otp;
const void *otp_data;
size_t otp_len;
const struct firmware *firmware; const struct firmware *firmware;
const void *firmware_data;
size_t firmware_len;
int fw_api;
struct { struct {
struct completion started; struct completion started;
...@@ -369,6 +406,7 @@ struct ath10k { ...@@ -369,6 +406,7 @@ struct ath10k {
/* protects shared structure data */ /* protects shared structure data */
spinlock_t data_lock; spinlock_t data_lock;
struct list_head arvifs;
struct list_head peers; struct list_head peers;
wait_queue_head_t peer_mapping_wq; wait_queue_head_t peer_mapping_wq;
...@@ -377,6 +415,9 @@ struct ath10k { ...@@ -377,6 +415,9 @@ struct ath10k {
struct completion offchan_tx_completed; struct completion offchan_tx_completed;
struct sk_buff *offchan_tx_skb; struct sk_buff *offchan_tx_skb;
struct work_struct wmi_mgmt_tx_work;
struct sk_buff_head wmi_mgmt_tx_queue;
enum ath10k_state state; enum ath10k_state state;
struct work_struct restart_work; struct work_struct restart_work;
......
...@@ -618,6 +618,8 @@ int ath10k_debug_start(struct ath10k *ar) ...@@ -618,6 +618,8 @@ int ath10k_debug_start(struct ath10k *ar)
{ {
int ret; int ret;
lockdep_assert_held(&ar->conf_mutex);
ret = ath10k_debug_htt_stats_req(ar); ret = ath10k_debug_htt_stats_req(ar);
if (ret) if (ret)
/* continue normally anyway, this isn't serious */ /* continue normally anyway, this isn't serious */
...@@ -628,7 +630,13 @@ int ath10k_debug_start(struct ath10k *ar) ...@@ -628,7 +630,13 @@ int ath10k_debug_start(struct ath10k *ar)
void ath10k_debug_stop(struct ath10k *ar) void ath10k_debug_stop(struct ath10k *ar)
{ {
cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); lockdep_assert_held(&ar->conf_mutex);
/* Must not use _sync to avoid deadlock, we do that in
* ath10k_debug_destroy(). The check for htt_stats_mask is to avoid
* warning from del_timer(). */
if (ar->debug.htt_stats_mask != 0)
cancel_delayed_work(&ar->debug.htt_stats_dwork);
} }
int ath10k_debug_create(struct ath10k *ar) int ath10k_debug_create(struct ath10k *ar)
...@@ -662,6 +670,11 @@ int ath10k_debug_create(struct ath10k *ar) ...@@ -662,6 +670,11 @@ int ath10k_debug_create(struct ath10k *ar)
return 0; return 0;
} }
void ath10k_debug_destroy(struct ath10k *ar)
{
cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
}
#endif /* CONFIG_ATH10K_DEBUGFS */ #endif /* CONFIG_ATH10K_DEBUGFS */
#ifdef CONFIG_ATH10K_DEBUG #ifdef CONFIG_ATH10K_DEBUG
......
...@@ -46,6 +46,7 @@ extern __printf(1, 2) int ath10k_warn(const char *fmt, ...); ...@@ -46,6 +46,7 @@ extern __printf(1, 2) int ath10k_warn(const char *fmt, ...);
int ath10k_debug_start(struct ath10k *ar); int ath10k_debug_start(struct ath10k *ar);
void ath10k_debug_stop(struct ath10k *ar); void ath10k_debug_stop(struct ath10k *ar);
int ath10k_debug_create(struct ath10k *ar); int ath10k_debug_create(struct ath10k *ar);
void ath10k_debug_destroy(struct ath10k *ar);
void ath10k_debug_read_service_map(struct ath10k *ar, void ath10k_debug_read_service_map(struct ath10k *ar,
void *service_map, void *service_map,
size_t map_size); size_t map_size);
...@@ -67,6 +68,10 @@ static inline int ath10k_debug_create(struct ath10k *ar) ...@@ -67,6 +68,10 @@ static inline int ath10k_debug_create(struct ath10k *ar)
return 0; return 0;
} }
static inline void ath10k_debug_destroy(struct ath10k *ar)
{
}
static inline void ath10k_debug_read_service_map(struct ath10k *ar, static inline void ath10k_debug_read_service_map(struct ath10k *ar,
void *service_map, void *service_map,
size_t map_size) size_t map_size)
......
...@@ -308,7 +308,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -308,7 +308,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
struct sk_buff *txdesc = NULL; struct sk_buff *txdesc = NULL;
struct htt_cmd *cmd; struct htt_cmd *cmd;
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
u8 vdev_id = skb_cb->htt.vdev_id; u8 vdev_id = skb_cb->vdev_id;
int len = 0; int len = 0;
int msdu_id = -1; int msdu_id = -1;
int res; int res;
...@@ -384,7 +384,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -384,7 +384,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
struct sk_buff *txdesc = NULL; struct sk_buff *txdesc = NULL;
bool use_frags; bool use_frags;
u8 vdev_id = ATH10K_SKB_CB(msdu)->htt.vdev_id; u8 vdev_id = ATH10K_SKB_CB(msdu)->vdev_id;
u8 tid; u8 tid;
int prefetch_len, desc_len; int prefetch_len, desc_len;
int msdu_id = -1; int msdu_id = -1;
......
...@@ -20,12 +20,6 @@ ...@@ -20,12 +20,6 @@
#include "targaddrs.h" #include "targaddrs.h"
/* Supported FW version */
#define SUPPORTED_FW_MAJOR 1
#define SUPPORTED_FW_MINOR 0
#define SUPPORTED_FW_RELEASE 0
#define SUPPORTED_FW_BUILD 636
/* QCA988X 1.0 definitions (unsupported) */ /* QCA988X 1.0 definitions (unsupported) */
#define QCA988X_HW_1_0_CHIP_ID_REV 0x0 #define QCA988X_HW_1_0_CHIP_ID_REV 0x0
...@@ -38,6 +32,25 @@ ...@@ -38,6 +32,25 @@
#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin"
#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234
#define ATH10K_FW_API2_FILE "firmware-2.bin"
/* includes also the null byte */
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
struct ath10k_fw_ie {
__le32 id;
__le32 len;
u8 data[0];
};
enum ath10k_fw_ie_type {
ATH10K_FW_IE_FW_VERSION = 0,
ATH10K_FW_IE_TIMESTAMP = 1,
ATH10K_FW_IE_FEATURES = 2,
ATH10K_FW_IE_FW_IMAGE = 3,
ATH10K_FW_IE_OTP_IMAGE = 4,
};
/* Known pecularities: /* Known pecularities:
* - current FW doesn't support raw rx mode (last tested v599) * - current FW doesn't support raw rx mode (last tested v599)
* - current FW dumps upon raw tx mode (last tested v599) * - current FW dumps upon raw tx mode (last tested v599)
...@@ -59,6 +72,7 @@ enum ath10k_mcast2ucast_mode { ...@@ -59,6 +72,7 @@ enum ath10k_mcast2ucast_mode {
ATH10K_MCAST2UCAST_ENABLED = 1, ATH10K_MCAST2UCAST_ENABLED = 1,
}; };
/* Target specific defines for MAIN firmware */
#define TARGET_NUM_VDEVS 8 #define TARGET_NUM_VDEVS 8
#define TARGET_NUM_PEER_AST 2 #define TARGET_NUM_PEER_AST 2
#define TARGET_NUM_WDS_ENTRIES 32 #define TARGET_NUM_WDS_ENTRIES 32
...@@ -93,6 +107,36 @@ enum ath10k_mcast2ucast_mode { ...@@ -93,6 +107,36 @@ enum ath10k_mcast2ucast_mode {
#define TARGET_NUM_MSDU_DESC (1024 + 400) #define TARGET_NUM_MSDU_DESC (1024 + 400)
#define TARGET_MAX_FRAG_ENTRIES 0 #define TARGET_MAX_FRAG_ENTRIES 0
/* Target specific defines for 10.X firmware */
#define TARGET_10X_NUM_VDEVS 16
#define TARGET_10X_NUM_PEER_AST 2
#define TARGET_10X_NUM_WDS_ENTRIES 32
#define TARGET_10X_DMA_BURST_SIZE 0
#define TARGET_10X_MAC_AGGR_DELIM 0
#define TARGET_10X_AST_SKID_LIMIT 16
#define TARGET_10X_NUM_PEERS (128 + (TARGET_10X_NUM_VDEVS))
#define TARGET_10X_NUM_OFFLOAD_PEERS 0
#define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0
#define TARGET_10X_NUM_PEER_KEYS 2
#define TARGET_10X_NUM_TIDS 256
#define TARGET_10X_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
#define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
#define TARGET_10X_RX_TIMEOUT_LO_PRI 100
#define TARGET_10X_RX_TIMEOUT_HI_PRI 40
#define TARGET_10X_RX_DECAP_MODE ATH10K_HW_TXRX_NATIVE_WIFI
#define TARGET_10X_SCAN_MAX_PENDING_REQS 4
#define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV 2
#define TARGET_10X_ROAM_OFFLOAD_MAX_VDEV 2
#define TARGET_10X_ROAM_OFFLOAD_MAX_AP_PROFILES 8
#define TARGET_10X_GTK_OFFLOAD_MAX_VDEV 3
#define TARGET_10X_NUM_MCAST_GROUPS 0
#define TARGET_10X_NUM_MCAST_TABLE_ELEMS 0
#define TARGET_10X_MCAST2UCAST_MODE ATH10K_MCAST2UCAST_DISABLED
#define TARGET_10X_TX_DBG_LOG_SIZE 1024
#define TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
#define TARGET_10X_VOW_CONFIG 0
#define TARGET_10X_NUM_MSDU_DESC (1024 + 400)
#define TARGET_10X_MAX_FRAG_ENTRIES 0
/* Number of Copy Engines supported */ /* Number of Copy Engines supported */
#define CE_COUNT 8 #define CE_COUNT 8
......
...@@ -34,6 +34,8 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id); ...@@ -34,6 +34,8 @@ struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id);
void ath10k_reset_scan(unsigned long ptr); void ath10k_reset_scan(unsigned long ptr);
void ath10k_offchan_tx_purge(struct ath10k *ar); void ath10k_offchan_tx_purge(struct ath10k *ar);
void ath10k_offchan_tx_work(struct work_struct *work); void ath10k_offchan_tx_work(struct work_struct *work);
void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar);
void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work);
void ath10k_halt(struct ath10k *ar); void ath10k_halt(struct ath10k *ar);
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
......
...@@ -720,18 +720,8 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, ...@@ -720,18 +720,8 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id,
"ath10k tx: data: ", "ath10k tx: data: ",
nbuf->data, nbuf->len); nbuf->data, nbuf->len);
/* Make sure we have resources to handle this request */ ret = ath10k_ce_send(ce_hdl, nbuf, skb_cb->paddr, len, transfer_id,
spin_lock_bh(&pipe_info->pipe_lock); flags);
if (!pipe_info->num_sends_allowed) {
ath10k_warn("Pipe: %d is full\n", pipe_id);
spin_unlock_bh(&pipe_info->pipe_lock);
return -ENOSR;
}
pipe_info->num_sends_allowed--;
spin_unlock_bh(&pipe_info->pipe_lock);
ret = ath10k_ce_sendlist_send(ce_hdl, nbuf, transfer_id,
skb_cb->paddr, len, flags);
if (ret) if (ret)
ath10k_warn("CE send failed: %p\n", nbuf); ath10k_warn("CE send failed: %p\n", nbuf);
...@@ -741,14 +731,7 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id, ...@@ -741,14 +731,7 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id,
static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_pci_pipe *pipe_info = &(ar_pci->pipe_info[pipe]); return ath10k_ce_num_free_src_entries(ar_pci->pipe_info[pipe].ce_hdl);
int ret;
spin_lock_bh(&pipe_info->pipe_lock);
ret = pipe_info->num_sends_allowed;
spin_unlock_bh(&pipe_info->pipe_lock);
return ret;
} }
static void ath10k_pci_hif_dump_area(struct ath10k *ar) static void ath10k_pci_hif_dump_area(struct ath10k *ar)
...@@ -863,7 +846,6 @@ static int ath10k_pci_start_ce(struct ath10k *ar) ...@@ -863,7 +846,6 @@ static int ath10k_pci_start_ce(struct ath10k *ar)
ath10k_pci_ce_send_done, ath10k_pci_ce_send_done,
disable_interrupts); disable_interrupts);
completions += attr->src_nentries; completions += attr->src_nentries;
pipe_info->num_sends_allowed = attr->src_nentries - 1;
} }
if (attr->dest_nentries) { if (attr->dest_nentries) {
...@@ -1033,7 +1015,6 @@ static void ath10k_pci_process_ce(struct ath10k *ar) ...@@ -1033,7 +1015,6 @@ static void ath10k_pci_process_ce(struct ath10k *ar)
*/ */
spin_lock_bh(&compl->pipe_info->pipe_lock); spin_lock_bh(&compl->pipe_info->pipe_lock);
list_add_tail(&compl->list, &compl->pipe_info->compl_free); list_add_tail(&compl->list, &compl->pipe_info->compl_free);
compl->pipe_info->num_sends_allowed += send_done;
spin_unlock_bh(&compl->pipe_info->pipe_lock); spin_unlock_bh(&compl->pipe_info->pipe_lock);
} }
......
...@@ -178,9 +178,6 @@ struct ath10k_pci_pipe { ...@@ -178,9 +178,6 @@ struct ath10k_pci_pipe {
/* List of free CE completion slots */ /* List of free CE completion slots */
struct list_head compl_free; struct list_head compl_free;
/* Limit the number of outstanding send requests. */
int num_sends_allowed;
struct ath10k_pci *ar_pci; struct ath10k_pci *ar_pci;
struct tasklet_struct intr; struct tasklet_struct intr;
}; };
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
/* disable credit flow control on a specific service */ /* disable credit flow control on a specific service */
#define HTC_CONN_FLGS_DISABLE_CRED_FLOW_CTRL (1 << 3) #define HTC_CONN_FLGS_DISABLE_CRED_FLOW_CTRL (1 << 3)
#define HTC_CONN_FLGS_SET_RECV_ALLOC_SHIFT 8 #define HTC_CONN_FLGS_SET_RECV_ALLOC_SHIFT 8
#define HTC_CONN_FLGS_SET_RECV_ALLOC_MASK 0xFF00 #define HTC_CONN_FLGS_SET_RECV_ALLOC_MASK 0xFF00U
/* connect response status codes */ /* connect response status codes */
#define HTC_SERVICE_SUCCESS 0 #define HTC_SERVICE_SUCCESS 0
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册