} __packed;
enum hif_error {
- HIF_ERROR_FIRMWARE_ROLLBACK = 0x0,
- HIF_ERROR_FIRMWARE_DEBUG_ENABLED = 0x1,
- HIF_ERROR_OUTDATED_SESSION_KEY = 0x2,
- HIF_ERROR_INVALID_SESSION_KEY = 0x3,
- HIF_ERROR_OOR_VOLTAGE = 0x4,
- HIF_ERROR_PDS_VERSION = 0x5,
- HIF_ERROR_OOR_TEMPERATURE = 0x6,
- HIF_ERROR_REQ_DURING_KEY_EXCHANGE = 0x7,
- HIF_ERROR_MULTI_TX_CNF_SECURELINK = 0x8,
- HIF_ERROR_SECURELINK_OVERFLOW = 0x9,
- HIF_ERROR_SECURELINK_DECRYPTION = 0xa
+ HIF_ERROR_FIRMWARE_ROLLBACK = 0x00,
+ HIF_ERROR_FIRMWARE_DEBUG_ENABLED = 0x01,
+ HIF_ERROR_SLK_OUTDATED_SESSION_KEY = 0x02,
+ HIF_ERROR_SLK_SESSION_KEY = 0x03,
+ HIF_ERROR_OOR_VOLTAGE = 0x04,
+ HIF_ERROR_PDS_PAYLOAD = 0x05,
+ HIF_ERROR_OOR_TEMPERATURE = 0x06,
+ HIF_ERROR_SLK_REQ_DURING_KEY_EXCHANGE = 0x07,
+ HIF_ERROR_SLK_MULTI_TX_UNSUPPORTED = 0x08,
+ HIF_ERROR_SLK_OVERFLOW = 0x09,
+ HIF_ERROR_SLK_DECRYPTION = 0x0a,
+ HIF_ERROR_SLK_WRONG_ENCRYPTION_STATE = 0x0b,
+ HIF_ERROR_HIF_BUS_FREQUENCY_TOO_LOW = 0x0c,
+ HIF_ERROR_HIF_RX_DATA_TOO_LARGE = 0x0e,
+ HIF_ERROR_HIF_TX_QUEUE_FULL = 0x0d,
+ HIF_ERROR_HIF_BUS = 0x0f,
+ HIF_ERROR_PDS_TESTFEATURE = 0x10,
};
struct hif_ind_error {
return 0;
}
-static int hif_error_indication(struct wfx_dev *wdev,
- const struct hif_msg *hif, const void *buf)
-{
- const struct hif_ind_error *body = buf;
- u8 *pRollback = (u8 *) body->data;
- u32 *pStatus = (u32 *) body->data;
-
- switch (body->type) {
- case HIF_ERROR_FIRMWARE_ROLLBACK:
- dev_err(wdev->dev,
- "asynchronous error: firmware rollback error %d\n",
- *pRollback);
- break;
- case HIF_ERROR_FIRMWARE_DEBUG_ENABLED:
- dev_err(wdev->dev, "asynchronous error: firmware debug feature enabled\n");
- break;
- case HIF_ERROR_OUTDATED_SESSION_KEY:
- dev_err(wdev->dev, "asynchronous error: secure link outdated key: %#.8x\n",
- *pStatus);
- break;
- case HIF_ERROR_INVALID_SESSION_KEY:
- dev_err(wdev->dev, "asynchronous error: invalid session key\n");
- break;
- case HIF_ERROR_OOR_VOLTAGE:
- dev_err(wdev->dev, "asynchronous error: out-of-range overvoltage: %#.8x\n",
- *pStatus);
- break;
- case HIF_ERROR_OOR_TEMPERATURE:
- dev_err(wdev->dev, "asynchronous error: out-of-range temperature: %#.8x\n",
- *pStatus);
- break;
- case HIF_ERROR_PDS_VERSION:
- dev_err(wdev->dev,
- "asynchronous error: wrong PDS payload or version: %#.8x\n",
- *pStatus);
- break;
- default:
- dev_err(wdev->dev, "asynchronous error: unknown (%d)\n",
- body->type);
- break;
- }
- wdev->chip_frozen = true;
- return 0;
-}
-
static int hif_generic_indication(struct wfx_dev *wdev,
const struct hif_msg *hif, const void *buf)
{
}
}
+static const struct {
+ int val;
+ const char *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_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" },
+};
+
+static int hif_error_indication(struct wfx_dev *wdev,
+ const struct hif_msg *hif, const void *buf)
+{
+ const struct 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, hif->len, false);
+ wdev->chip_frozen = true;
+
+ return 0;
+};
+
static int hif_exception_indication(struct wfx_dev *wdev,
const struct hif_msg *hif, const void *buf)
{