예제 #1
0
static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
{
	__le32 regdump_val[REGISTER_DUMP_LEN_MAX];
	u32 i, address, regdump_addr = 0;
	int ret;

	if (ar->target_type != TARGET_TYPE_AR6003)
		return;

	/* the reg dump pointer is copied to the host interest area */
	address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
	address = TARG_VTOP(ar->target_type, address);

	/* read RAM location through diagnostic window */
	ret = ath6kl_diag_read32(ar, address, &regdump_addr);

	if (ret || !regdump_addr) {
		ath6kl_warn("failed to get ptr to register dump area: %d\n",
			    ret);
		return;
	}

	ath6kl_dbg(ATH6KL_DBG_IRQ, "register dump data address 0x%x\n",
		regdump_addr);
	regdump_addr = TARG_VTOP(ar->target_type, regdump_addr);

	/* fetch register dump data */
	ret = ath6kl_diag_read(ar, regdump_addr, (u8 *)&regdump_val[0],
				  REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
	if (ret) {
		ath6kl_warn("failed to get register dump: %d\n", ret);
		return;
	}

	ath6kl_info("crash dump:\n");
	ath6kl_info("hw 0x%x fw %s\n", ar->wiphy->hw_version,
		    ar->wiphy->fw_version);

	BUILD_BUG_ON(REG_DUMP_COUNT_AR6003 % 4);

	for (i = 0; i < REG_DUMP_COUNT_AR6003 / 4; i++) {
		ath6kl_info("%d: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
			    4 * i,
			    le32_to_cpu(regdump_val[i]),
			    le32_to_cpu(regdump_val[i + 1]),
			    le32_to_cpu(regdump_val[i + 2]),
			    le32_to_cpu(regdump_val[i + 3]));
	}

}
예제 #2
0
static int ath6kl_dt_parse_vreg_info(struct device *dev,
	struct ath6kl_power_vreg_data **vreg_data, const char *vreg_name)
{
	int len, ret = 0;
	const __be32 *prop;
	char prop_name[MAX_PROP_SIZE];
	struct ath6kl_power_vreg_data *vreg;
	struct device_node *np = dev->of_node;

	ath6kl_dbg(ATH6KL_DBG_BOOT, "vreg dev tree parse for %s\n", vreg_name);

	snprintf(prop_name, MAX_PROP_SIZE, "%s-supply", vreg_name);
	if (of_parse_phandle(np, prop_name, 0)) {
		vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
		if (!vreg) {
			ath6kl_err("No memory for vreg: %s\n", vreg_name);
			ret = -ENOMEM;
			goto err;
		}

		vreg->name = vreg_name;

		snprintf(prop_name, MAX_PROP_SIZE,
				"%s-voltage-level", vreg_name);
		prop = of_get_property(np, prop_name, &len);
		if (!prop || (len != (2 * sizeof(__be32)))) {
			ath6kl_dbg(ATH6KL_DBG_BOOT, "%s %s property\n",
				prop ? "invalid format" : "no", prop_name);
		} else {
			vreg->low_vol_level = be32_to_cpup(&prop[0]);
			vreg->high_vol_level = be32_to_cpup(&prop[1]);
		}

		*vreg_data = vreg;
		ath6kl_dbg(ATH6KL_DBG_BOOT, "%s: vol=[%d %d]uV\n",
			vreg->name, vreg->low_vol_level,
			vreg->high_vol_level);
	}  else
		ath6kl_info("%s: is not provided in device tree\n", vreg_name);

err:
	return ret;
}
예제 #3
0
static int ap_keepalive_update_check_txrx_time(struct ath6kl_vif *vif)
{
	struct ath6kl *ar = vif->ar;
	struct wmi_ap_mode_stat *ap_stats = &vif->ap_stats;
	struct wmi_per_sta_stat *per_sta_stat;
	struct ath6kl_sta *conn;
	int i, action;

	if (test_bit(STATS_UPDATE_PEND, &vif->flags)) {
		ath6kl_info("somebody still query now and ignore it this time.\n");
		return -EBUSY;
	}

	/* Now, tranfer to host time and update to vif->sta_list[]. */
	for (i = 0; i < AP_MAX_NUM_STA; i++) {
		per_sta_stat = &ap_stats->sta[i];
		if (per_sta_stat->aid) {
			conn = ath6kl_find_sta_by_aid(vif, per_sta_stat->aid);
			if (conn) {
				action = _ap_keepalive_update_check_txrx_time(vif, 
									      conn, 
									      per_sta_stat->last_txrx_time);

				if (action == AP_KA_ACTION_POLL) {
					ath6kl_wmi_ap_poll_sta(ar->wmi, 
							       vif->fw_vif_idx, 
							       conn->aid);
				} else if (action == AP_KA_ACTION_REMOVE) {
					ath6kl_wmi_ap_set_mlme(ar->wmi, 
							       vif->fw_vif_idx, 
							       WMI_AP_DEAUTH,
							       conn->mac, 
							       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
				}
			} else {
				ath6kl_err("can't find this AID %d in STA list\n", per_sta_stat->aid);
			}
		}
	}

	return 0;
}
예제 #4
0
static void ath6kl_hif_dump(struct ath6kl *ar, u32 fw_dump_addr, u32 len)
{
	__le32 regdump_val[MAX_DUMP_BYTE_NUM_ONE_ITERATION / 4];
	u32 read_len = 0;
	u32 i = 0,count;
	int ret;
	u32 phy_addr = TARG_VTOP(ar->target_type, fw_dump_addr);

	len = (len + 3) & (~0x3);
	fw_dump_addr = (fw_dump_addr + 3) & (~0x3);

	while(len) {
		read_len = len;
		if(read_len > MAX_DUMP_BYTE_NUM_ONE_ITERATION)
			read_len = MAX_DUMP_BYTE_NUM_ONE_ITERATION;

		phy_addr = TARG_VTOP(ar->target_type, fw_dump_addr);
		ret = ath6kl_diag_read(ar, phy_addr, (u8 *) &regdump_val[0], read_len);
		if (ret) {
			ath6kl_warn("failed to get register dump: %d\n", ret);
			return;
		}

		count = read_len / 4;
		for (i = 0; i < count; i += 4) {
			ath6kl_info("0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
				    le32_to_cpu(fw_dump_addr + 4 * i),
				    le32_to_cpu(regdump_val[i]),
				    le32_to_cpu(regdump_val[i + 1]),
				    le32_to_cpu(regdump_val[i + 2]),
				    le32_to_cpu(regdump_val[i + 3]));
		}

		len -= read_len;
		fw_dump_addr += read_len;
	}
}