staticint wfx_hif_generic_confirm(struct wfx_dev *wdev, conststruct wfx_hif_msg *hif, constvoid *buf)
{ /* All confirm messages start with status */ int status = le32_to_cpup((__le32 *)buf); int cmd = hif->id; int len = le16_to_cpu(hif->len) - 4; /* drop header */
if (cmd != wdev->hif_cmd.buf_send->id) {
dev_warn(wdev->dev, "chip response mismatch request: 0x%.2x vs 0x%.2x\n",
cmd, wdev->hif_cmd.buf_send->id); return -EINVAL;
}
if (wdev->hif_cmd.buf_recv) { if (wdev->hif_cmd.len_recv >= len && len > 0)
memcpy(wdev->hif_cmd.buf_recv, buf, len); else
status = -EIO;
}
wdev->hif_cmd.ret = status;
if (body->bc_mc_only) {
wvif = wdev_to_wvif(wdev, hif->interface); if (!wvif) {
dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__); return -EIO;
} if (body->resume)
wfx_suspend_resume_mc(wvif, STA_NOTIFY_AWAKE); else
wfx_suspend_resume_mc(wvif, STA_NOTIFY_SLEEP);
} else {
WARN(body->peer_sta_set, "misunderstood indication");
WARN(hif->interface != 2, "misunderstood indication"); if (body->resume)
wfx_suspend_hot_dev(wdev, STA_NOTIFY_AWAKE); else
wfx_suspend_hot_dev(wdev, STA_NOTIFY_SLEEP);
}
return 0;
}
staticint wfx_hif_generic_indication(struct wfx_dev *wdev, conststruct wfx_hif_msg *hif, constvoid *buf)
{ conststruct wfx_hif_ind_generic *body = buf; int type = le32_to_cpu(body->type);
switch (type) { case HIF_GENERIC_INDICATION_TYPE_RAW: return 0; case HIF_GENERIC_INDICATION_TYPE_STRING:
dev_info(wdev->dev, "firmware says: %s\n", (char *)&body->data); return 0; case HIF_GENERIC_INDICATION_TYPE_RX_STATS:
mutex_lock(&wdev->rx_stats_lock); /* Older firmware send a generic indication beside RxStats */ if (!wfx_api_older_than(wdev, 1, 4))
dev_info(wdev->dev, "Rx test ongoing. Temperature: %d degrees C\n",
body->data.rx_stats.current_temp);
memcpy(&wdev->rx_stats, &body->data.rx_stats, sizeof(wdev->rx_stats));
mutex_unlock(&wdev->rx_stats_lock); return 0; case HIF_GENERIC_INDICATION_TYPE_TX_POWER_LOOP_INFO:
mutex_lock(&wdev->tx_power_loop_info_lock);
memcpy(&wdev->tx_power_loop_info, &body->data.tx_power_loop_info, sizeof(wdev->tx_power_loop_info));
mutex_unlock(&wdev->tx_power_loop_info_lock); return 0; default:
dev_err(wdev->dev, "generic_indication: unknown indication type: %#.8x\n", type); return -EIO;
}
}
staticconststruct { int val; constchar *str; bool has_param;
} hif_errors[] = {
{ HIF_ERROR_FIRMWARE_ROLLBACK, "rollback status" },
{ HIF_ERROR_FIRMWARE_DEBUG_ENABLED, "debug feature enabled" },
{ HIF_ERROR_PDS_PAYLOAD, "PDS version is not supported" },
{ HIF_ERROR_PDS_TESTFEATURE, "PDS ask for an unknown test mode" },
{ HIF_ERROR_OOR_VOLTAGE, "out-of-range power supply voltage", true },
{ HIF_ERROR_OOR_TEMPERATURE, "out-of-range temperature", true },
{ HIF_ERROR_SLK_REQ_DURING_KEY_EXCHANGE, "secure link does not expect request during key exchange" },
{ HIF_ERROR_SLK_SESSION_KEY, "secure link session key is invalid" },
{ HIF_ERROR_SLK_OVERFLOW, "secure link overflow" },
{ HIF_ERROR_SLK_WRONG_ENCRYPTION_STATE, "secure link messages list does not match message encryption" },
{ HIF_ERROR_SLK_UNCONFIGURED, "secure link not yet configured" },
{ HIF_ERROR_HIF_BUS_FREQUENCY_TOO_LOW, "bus clock is too slow (<1kHz)" },
{ HIF_ERROR_HIF_RX_DATA_TOO_LARGE, "HIF message too large" }, /* Following errors only exists in old firmware versions: */
{ HIF_ERROR_HIF_TX_QUEUE_FULL, "HIF messages queue is full" },
{ HIF_ERROR_HIF_BUS, "HIF bus" },
{ HIF_ERROR_SLK_MULTI_TX_UNSUPPORTED, "secure link does not support multi-tx confirmations" },
{ HIF_ERROR_SLK_OUTDATED_SESSION_KEY, "secure link session key is outdated" },
{ HIF_ERROR_SLK_DECRYPTION, "secure link params (nonce or tag) mismatch" },
};
staticint wfx_hif_error_indication(struct wfx_dev *wdev, conststruct wfx_hif_msg *hif, constvoid *buf)
{ conststruct wfx_hif_ind_error *body = buf; int type = le32_to_cpu(body->type); int param = (s8)body->data[0]; int i;
for (i = 0; i < ARRAY_SIZE(hif_errors); i++) if (type == hif_errors[i].val) break; if (i < ARRAY_SIZE(hif_errors)) if (hif_errors[i].has_param)
dev_err(wdev->dev, "asynchronous error: %s: %d\n",
hif_errors[i].str, param); else
dev_err(wdev->dev, "asynchronous error: %s\n", hif_errors[i].str); else
dev_err(wdev->dev, "asynchronous error: unknown: %08x\n", type);
print_hex_dump(KERN_INFO, "hif: ", DUMP_PREFIX_OFFSET,
16, 1, hif, le16_to_cpu(hif->len), false);
wdev->chip_frozen = true;
return 0;
};
staticint wfx_hif_exception_indication(struct wfx_dev *wdev, conststruct wfx_hif_msg *hif, constvoid *buf)
{ conststruct wfx_hif_ind_exception *body = buf; int type = le32_to_cpu(body->type);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.