[PATCH v4 04/17] ASoC: Intel: avs: Inter process communication
Pierre-Louis Bossart
pierre-louis.bossart at linux.intel.com
Wed Mar 9 23:10:33 CET 2022
> +/*
> + * struct avs_dsp_ops - Platform-specific DSP operations
> + *
> + * @power: Power on or off DSP cores
> + * @reset: Enter or exit reset state on DSP cores
> + * @stall: Stall or run DSP cores
nit-pick: the description sounds like boolean states. add "callback to"
> + * @irq_handler: Top half of IPC servicing
> + * @irq_thread: Bottom half of IPC servicing
> + * @int_control: Enable or disable IPC interrupts
callback to ...
> + */
> struct avs_dsp_ops {
> int (* const power)(struct avs_dev *, u32, bool);
> int (* const reset)(struct avs_dev *, u32, bool);
> int (* const stall)(struct avs_dev *, u32, bool);
> + irqreturn_t (* const irq_handler)(int, void *);
> + irqreturn_t (* const irq_thread)(int, void *);
> + void (* const int_control)(struct avs_dev *, bool);
> };
> +/*
> + * struct avs_ipc - DSP IPC context
> + *
> + * @dev: PCI device
> + * @rx: Reply message cache
cache? I find this confusing, what are you trying to say here?
> + * @default_timeout_ms: default message timeout in MS
> + * @ready: whether firmware is ready and communication is open
> + * @rx_completed: whether RX for previously sent TX has been received
> + * @rx_lock: for serializating manipulation of rx_* fields
typo: serializing
> + * @msg_lock: for synchronizing request handling
> + * @done_completion: DONE-part of IPC i.e. ROM and ACKs from FW
> + * @busy_completion: BUSY-part of IPC i.e. receiving responses from FW
> + */
> +struct avs_ipc {
> + struct device *dev;
> +
> + struct avs_ipc_msg rx;
> + u32 default_timeout_ms;
> + bool ready;
> +
> + bool rx_completed;
> + spinlock_t rx_lock;
> + struct mutex msg_mutex;
> + struct completion done_completion;
> + struct completion busy_completion;
> +};
> +
> +#define AVS_EIPC EREMOTEIO
I don't recall if I already mentioned this but I don't see the need for
an intermediate redefinition of a Linux error code.
> +/*
> + * IPC handlers may return positive value (firmware error code) what denotes
> + * successful HOST <-> DSP communication yet failure to process specific request.
> + *
> + * Below macro converts returned value to linux kernel error code.
> + * All IPC callers MUST use it as soon as firmware error code is consumed.
> + */
> +#define AVS_IPC_RET(ret) \
> + (((ret) <= 0) ? (ret) : -AVS_EIPC)
> +
> +static inline void avs_ipc_err(struct avs_dev *adev, struct avs_ipc_msg *tx,
> + const char *name, int error)
> +{
> + /*
> + * If IPC channel is blocked e.g.: due to ongoing recovery,
> + * -EPERM error code is expected and thus it's not an actual error.
> + */
> + if (error == -EPERM)
> + dev_dbg(adev->dev, "%s 0x%08x 0x%08x failed: %d\n", name,
%# adds the 0x for you.
> + tx->glb.primary, tx->glb.ext.val, error);
> + else
> + dev_err(adev->dev, "%s 0x%08x 0x%08x failed: %d\n", name,
> + tx->glb.primary, tx->glb.ext.val, error);
> +}
> +static void avs_dsp_process_notification(struct avs_dev *adev, u64 header)
> +{
> + struct avs_notify_mod_data mod_data;
> + union avs_notify_msg msg = AVS_MSG(header);
> + size_t data_size = 0;
> + void *data = NULL;
> +
> + /* Ignore spurious notifications until handshake is established. */
there's no handshake here, just an initial notification after which the
IPC protocol can start?
> + if (!adev->ipc->ready && msg.notify_msg_type != AVS_NOTIFY_FW_READY) {
> + dev_dbg(adev->dev, "FW not ready, skip notification: 0x%08x\n",
> + msg.primary);
> + return;
> + }
> +
> + /* Calculate notification payload size. */
> + switch (msg.notify_msg_type) {
> + case AVS_NOTIFY_FW_READY:
> + break;
> +
> + case AVS_NOTIFY_PHRASE_DETECTED:
> + data_size = sizeof(struct avs_notify_voice_data);
> + break;
> +
> + case AVS_NOTIFY_RESOURCE_EVENT:
> + data_size = sizeof(struct avs_notify_res_data);
> + break;
> +
> + case AVS_NOTIFY_MODULE_EVENT:
> + /* To know the total payload size, header needs to be read first. */
> + memcpy_fromio(&mod_data, avs_uplink_addr(adev), sizeof(mod_data));
> + data_size = sizeof(mod_data) + mod_data.data_size;
> + break;
> +
> + default:
> + dev_info(adev->dev, "unknown notification: 0x%08x\n",
> + msg.primary);
> + break;
> + }
> +
> + if (data_size) {
> + data = kmalloc(data_size, GFP_KERNEL);
> + if (!data)
> + return;
> +
> + memcpy_fromio(data, avs_uplink_addr(adev), data_size);
> + }
> +
> + /* Perform notification-specific operations. */
> + switch (msg.notify_msg_type) {
> + case AVS_NOTIFY_FW_READY:
> + dev_dbg(adev->dev, "FW READY 0x%08x\n", msg.primary);
> + adev->ipc->ready = true;
> + complete(&adev->fw_ready);
> + break;
> +
> + default:
> + break;
> + }
> +
> + kfree(data);
> +}
More information about the Alsa-devel
mailing list