void ath10k_print_driver_info(struct ath10k *ar)
{
char fw_features[128] = {};
+ char boardinfo[100];
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
- ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
+ if (ar->id.bmi_ids_valid)
+ scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d",
+ ar->id.bmi_chip_id, ar->id.bmi_board_id);
+ else
+ scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x",
+ ar->id.subsystem_vendor, ar->id.subsystem_device);
+
+ ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
ar->hw_params.name,
ar->target_version,
ar->chip_id,
- (strlen(ar->spec_board_id) > 0 ? ", " : ""),
- ar->spec_board_id,
- (strlen(ar->spec_board_id) > 0 && !ar->spec_board_loaded
- ? " fallback" : ""),
+ boardinfo,
ar->hw->wiphy->fw_version,
ar->fw_api,
+ ar->bd_api,
ar->htt.target_version_major,
ar->htt.target_version_minor,
ar->wmi.op_version,
spin_unlock_bh(&ar->data_lock);
}
-static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
-{
- struct ath10k_fw_stats_peer *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
-static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head)
-{
- struct ath10k_fw_stats_vdev *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_fw_stats stats = {};
goto free;
}
- num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
- num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
+ num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers);
+ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs);
is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
!list_empty(&stats.pdevs));
is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
return 0;
}
-/* FIXME: How to calculate the buffer size sanely? */
-#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
-
-static void ath10k_fw_stats_fill(struct ath10k *ar,
- struct ath10k_fw_stats *fw_stats,
- char *buf)
-{
- unsigned int len = 0;
- unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
- const struct ath10k_fw_stats_pdev *pdev;
- const struct ath10k_fw_stats_vdev *vdev;
- const struct ath10k_fw_stats_peer *peer;
- size_t num_peers;
- size_t num_vdevs;
- int i;
-
- spin_lock_bh(&ar->data_lock);
-
- pdev = list_first_entry_or_null(&fw_stats->pdevs,
- struct ath10k_fw_stats_pdev, list);
- if (!pdev) {
- ath10k_warn(ar, "failed to get pdev stats\n");
- goto unlock;
- }
-
- num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
- num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s\n",
- "ath10k PDEV stats");
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Channel noise floor", pdev->ch_noise_floor);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "Channel TX power", pdev->chan_tx_power);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "TX frame count", pdev->tx_frame_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RX frame count", pdev->rx_frame_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RX clear count", pdev->rx_clear_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "Cycle count", pdev->cycle_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "PHY error count", pdev->phy_err_count);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RTS bad count", pdev->rts_bad);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RTS good count", pdev->rts_good);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "FCS bad count", pdev->fcs_bad);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "No beacon count", pdev->no_beacons);
- len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "MIB int count", pdev->mib_int_count);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s\n",
- "ath10k PDEV TX stats");
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HTT cookies queued", pdev->comp_queued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HTT cookies disp.", pdev->comp_delivered);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDU queued", pdev->msdu_enqued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU queued", pdev->mpdu_enqued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs dropped", pdev->wmm_drop);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Local enqued", pdev->local_enqued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Local freed", pdev->local_freed);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HW queued", pdev->hw_queued);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PPDUs reaped", pdev->hw_reaped);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Num underruns", pdev->underrun);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PPDUs cleaned", pdev->tx_abort);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs requed", pdev->mpdus_requed);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Excessive retries", pdev->tx_ko);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HW rate", pdev->data_rc);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Sched self tiggers", pdev->self_triggers);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Dropped due to SW retries",
- pdev->sw_retry_failure);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Illegal rate phy errors",
- pdev->illgl_rate_phy_err);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Pdev continous xretry", pdev->pdev_cont_xretry);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "TX timeout", pdev->pdev_tx_timeout);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PDEV resets", pdev->pdev_resets);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY underrun", pdev->phy_underrun);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU is more than txop limit", pdev->txop_ovf);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s\n",
- "ath10k PDEV RX stats");
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Mid PPDU route change",
- pdev->mid_ppdu_route_change);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Tot. number of statuses", pdev->status_rcvd);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 0", pdev->r0_frags);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 1", pdev->r1_frags);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 2", pdev->r2_frags);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 3", pdev->r3_frags);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs delivered to HTT", pdev->htt_msdus);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs delivered to HTT", pdev->htt_mpdus);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs delivered to stack", pdev->loc_msdus);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs delivered to stack", pdev->loc_mpdus);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Oversized AMSUs", pdev->oversize_amsdu);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY errors", pdev->phy_errs);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY errors drops", pdev->phy_err_drop);
- len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
- "ath10k VDEV stats", num_vdevs);
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- list_for_each_entry(vdev, &fw_stats->vdevs, list) {
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "vdev id", vdev->vdev_id);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "beacon snr", vdev->beacon_snr);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "data snr", vdev->data_snr);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rx frames", vdev->num_rx_frames);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rts fail", vdev->num_rts_fail);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rts success", vdev->num_rts_success);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rx err", vdev->num_rx_err);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num rx discard", vdev->num_rx_discard);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "num tx not acked", vdev->num_tx_not_acked);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] %u\n",
- "num tx frames", i,
- vdev->num_tx_frames[i]);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] %u\n",
- "num tx frames retries", i,
- vdev->num_tx_frames_retries[i]);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] %u\n",
- "num tx frames failures", i,
- vdev->num_tx_frames_failures[i]);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] 0x%08x\n",
- "tx rate history", i,
- vdev->tx_rate_history[i]);
-
- for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++)
- len += scnprintf(buf + len, buf_len - len,
- "%25s [%02d] %u\n",
- "beacon rssi history", i,
- vdev->beacon_rssi_history[i]);
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- }
-
- len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
- "ath10k PEER stats", num_peers);
- len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- "=================");
-
- list_for_each_entry(peer, &fw_stats->peers, list) {
- len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
- "Peer MAC address", peer->peer_macaddr);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "Peer RSSI", peer->peer_rssi);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "Peer TX rate", peer->peer_tx_rate);
- len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "Peer RX rate", peer->peer_rx_rate);
- len += scnprintf(buf + len, buf_len - len, "\n");
- }
-
-unlock:
- spin_unlock_bh(&ar->data_lock);
-
- if (len >= buf_len)
- buf[len - 1] = 0;
- else
- buf[len] = 0;
-}
-
static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
{
struct ath10k *ar = inode->i_private;
goto err_free;
}
- ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
+ ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
+ if (ret) {
+ ath10k_warn(ar, "failed to fill fw stats: %d\n", ret);
+ goto err_free;
+ }
+
file->private_data = buf;
mutex_unlock(&ar->conf_mutex);
.open = simple_open
};
+static ssize_t ath10k_write_btcoex(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ char buf[32];
+ size_t buf_size;
+ bool val;
+
+ buf_size = min(count, (sizeof(buf) - 1));
+ if (copy_from_user(buf, ubuf, buf_size))
+ return -EFAULT;
+
+ buf[buf_size] = '\0';
+
+ if (strtobool(buf, &val) != 0)
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
+ goto exit;
+
+ if (val)
+ set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
+ else
+ clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
+
+ if (ar->state != ATH10K_STATE_ON)
+ goto exit;
+
+ ath10k_info(ar, "restarting firmware due to btcoex change");
+
+ queue_work(ar->workqueue, &ar->restart_work);
+
+exit:
+ mutex_unlock(&ar->conf_mutex);
+
+ return count;
+}
+
+static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[32];
+ struct ath10k *ar = file->private_data;
+ int len = 0;
+
+ mutex_lock(&ar->conf_mutex);
+ len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+ test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
+ mutex_unlock(&ar->conf_mutex);
+
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_btcoex = {
+ .read = ath10k_read_btcoex,
+ .write = ath10k_write_btcoex,
+ .open = simple_open
+};
+
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
debugfs_create_file("tpc_stats", S_IRUSR,
ar->debug.debugfs_phy, ar, &fops_tpc_stats);
+ if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
+ debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
+ ar->debug.debugfs_phy, ar, &fops_btcoex);
+
return 0;
}