xref: /openbmc/linux/sound/soc/intel/avs/dsp.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
19fe51c55SCezary Rojewski // SPDX-License-Identifier: GPL-2.0-only
29fe51c55SCezary Rojewski //
39fe51c55SCezary Rojewski // Copyright(c) 2021-2022 Intel Corporation. All rights reserved.
49fe51c55SCezary Rojewski //
59fe51c55SCezary Rojewski // Authors: Cezary Rojewski <cezary.rojewski@intel.com>
69fe51c55SCezary Rojewski //          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
79fe51c55SCezary Rojewski //
89fe51c55SCezary Rojewski 
99fe51c55SCezary Rojewski #include <sound/hdaudio_ext.h>
109fe51c55SCezary Rojewski #include "avs.h"
119fe51c55SCezary Rojewski #include "registers.h"
1269b23b39SCezary Rojewski #include "trace.h"
139fe51c55SCezary Rojewski 
149fe51c55SCezary Rojewski #define AVS_ADSPCS_INTERVAL_US		500
159fe51c55SCezary Rojewski #define AVS_ADSPCS_TIMEOUT_US		50000
168192d24cSCezary Rojewski #define AVS_ADSPCS_DELAY_US		1000
179fe51c55SCezary Rojewski 
avs_dsp_core_power(struct avs_dev * adev,u32 core_mask,bool power)189fe51c55SCezary Rojewski int avs_dsp_core_power(struct avs_dev *adev, u32 core_mask, bool power)
199fe51c55SCezary Rojewski {
209fe51c55SCezary Rojewski 	u32 value, mask, reg;
219fe51c55SCezary Rojewski 	int ret;
229fe51c55SCezary Rojewski 
2369b23b39SCezary Rojewski 	value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
2469b23b39SCezary Rojewski 	trace_avs_dsp_core_op(value, core_mask, "power", power);
2569b23b39SCezary Rojewski 
269fe51c55SCezary Rojewski 	mask = AVS_ADSPCS_SPA_MASK(core_mask);
279fe51c55SCezary Rojewski 	value = power ? mask : 0;
289fe51c55SCezary Rojewski 
299fe51c55SCezary Rojewski 	snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
308192d24cSCezary Rojewski 	/* Delay the polling to avoid false positives. */
318192d24cSCezary Rojewski 	usleep_range(AVS_ADSPCS_DELAY_US, 2 * AVS_ADSPCS_DELAY_US);
329fe51c55SCezary Rojewski 
339fe51c55SCezary Rojewski 	mask = AVS_ADSPCS_CPA_MASK(core_mask);
349fe51c55SCezary Rojewski 	value = power ? mask : 0;
359fe51c55SCezary Rojewski 
369fe51c55SCezary Rojewski 	ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
379fe51c55SCezary Rojewski 				       reg, (reg & mask) == value,
389fe51c55SCezary Rojewski 				       AVS_ADSPCS_INTERVAL_US,
399fe51c55SCezary Rojewski 				       AVS_ADSPCS_TIMEOUT_US);
409fe51c55SCezary Rojewski 	if (ret)
419fe51c55SCezary Rojewski 		dev_err(adev->dev, "core_mask %d power %s failed: %d\n",
429fe51c55SCezary Rojewski 			core_mask, power ? "on" : "off", ret);
439fe51c55SCezary Rojewski 
449fe51c55SCezary Rojewski 	return ret;
459fe51c55SCezary Rojewski }
469fe51c55SCezary Rojewski 
avs_dsp_core_reset(struct avs_dev * adev,u32 core_mask,bool reset)479fe51c55SCezary Rojewski int avs_dsp_core_reset(struct avs_dev *adev, u32 core_mask, bool reset)
489fe51c55SCezary Rojewski {
499fe51c55SCezary Rojewski 	u32 value, mask, reg;
509fe51c55SCezary Rojewski 	int ret;
519fe51c55SCezary Rojewski 
5269b23b39SCezary Rojewski 	value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
5369b23b39SCezary Rojewski 	trace_avs_dsp_core_op(value, core_mask, "reset", reset);
5469b23b39SCezary Rojewski 
559fe51c55SCezary Rojewski 	mask = AVS_ADSPCS_CRST_MASK(core_mask);
569fe51c55SCezary Rojewski 	value = reset ? mask : 0;
579fe51c55SCezary Rojewski 
589fe51c55SCezary Rojewski 	snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
599fe51c55SCezary Rojewski 
609fe51c55SCezary Rojewski 	ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
619fe51c55SCezary Rojewski 				       reg, (reg & mask) == value,
629fe51c55SCezary Rojewski 				       AVS_ADSPCS_INTERVAL_US,
639fe51c55SCezary Rojewski 				       AVS_ADSPCS_TIMEOUT_US);
649fe51c55SCezary Rojewski 	if (ret)
659fe51c55SCezary Rojewski 		dev_err(adev->dev, "core_mask %d %s reset failed: %d\n",
669fe51c55SCezary Rojewski 			core_mask, reset ? "enter" : "exit", ret);
679fe51c55SCezary Rojewski 
689fe51c55SCezary Rojewski 	return ret;
699fe51c55SCezary Rojewski }
709fe51c55SCezary Rojewski 
avs_dsp_core_stall(struct avs_dev * adev,u32 core_mask,bool stall)719fe51c55SCezary Rojewski int avs_dsp_core_stall(struct avs_dev *adev, u32 core_mask, bool stall)
729fe51c55SCezary Rojewski {
739fe51c55SCezary Rojewski 	u32 value, mask, reg;
749fe51c55SCezary Rojewski 	int ret;
759fe51c55SCezary Rojewski 
7669b23b39SCezary Rojewski 	value = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPCS);
7769b23b39SCezary Rojewski 	trace_avs_dsp_core_op(value, core_mask, "stall", stall);
7869b23b39SCezary Rojewski 
799fe51c55SCezary Rojewski 	mask = AVS_ADSPCS_CSTALL_MASK(core_mask);
809fe51c55SCezary Rojewski 	value = stall ? mask : 0;
819fe51c55SCezary Rojewski 
829fe51c55SCezary Rojewski 	snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPCS, mask, value);
839fe51c55SCezary Rojewski 
849fe51c55SCezary Rojewski 	ret = snd_hdac_adsp_readl_poll(adev, AVS_ADSP_REG_ADSPCS,
859fe51c55SCezary Rojewski 				       reg, (reg & mask) == value,
869fe51c55SCezary Rojewski 				       AVS_ADSPCS_INTERVAL_US,
879fe51c55SCezary Rojewski 				       AVS_ADSPCS_TIMEOUT_US);
888192d24cSCezary Rojewski 	if (ret) {
899fe51c55SCezary Rojewski 		dev_err(adev->dev, "core_mask %d %sstall failed: %d\n",
909fe51c55SCezary Rojewski 			core_mask, stall ? "" : "un", ret);
919fe51c55SCezary Rojewski 		return ret;
929fe51c55SCezary Rojewski 	}
939fe51c55SCezary Rojewski 
948192d24cSCezary Rojewski 	/* Give HW time to propagate the change. */
958192d24cSCezary Rojewski 	usleep_range(AVS_ADSPCS_DELAY_US, 2 * AVS_ADSPCS_DELAY_US);
968192d24cSCezary Rojewski 	return 0;
978192d24cSCezary Rojewski }
988192d24cSCezary Rojewski 
avs_dsp_core_enable(struct avs_dev * adev,u32 core_mask)999fe51c55SCezary Rojewski int avs_dsp_core_enable(struct avs_dev *adev, u32 core_mask)
1009fe51c55SCezary Rojewski {
1019fe51c55SCezary Rojewski 	int ret;
1029fe51c55SCezary Rojewski 
1039fe51c55SCezary Rojewski 	ret = avs_dsp_op(adev, power, core_mask, true);
1049fe51c55SCezary Rojewski 	if (ret)
1059fe51c55SCezary Rojewski 		return ret;
1069fe51c55SCezary Rojewski 
1079fe51c55SCezary Rojewski 	ret = avs_dsp_op(adev, reset, core_mask, false);
1089fe51c55SCezary Rojewski 	if (ret)
1099fe51c55SCezary Rojewski 		return ret;
1109fe51c55SCezary Rojewski 
1119fe51c55SCezary Rojewski 	return avs_dsp_op(adev, stall, core_mask, false);
1129fe51c55SCezary Rojewski }
1139fe51c55SCezary Rojewski 
avs_dsp_core_disable(struct avs_dev * adev,u32 core_mask)1149fe51c55SCezary Rojewski int avs_dsp_core_disable(struct avs_dev *adev, u32 core_mask)
1159fe51c55SCezary Rojewski {
1169fe51c55SCezary Rojewski 	/* No error checks to allow for complete DSP shutdown. */
1179fe51c55SCezary Rojewski 	avs_dsp_op(adev, stall, core_mask, true);
1189fe51c55SCezary Rojewski 	avs_dsp_op(adev, reset, core_mask, true);
1199fe51c55SCezary Rojewski 
1209fe51c55SCezary Rojewski 	return avs_dsp_op(adev, power, core_mask, false);
1219fe51c55SCezary Rojewski }
1229fe51c55SCezary Rojewski 
avs_dsp_enable(struct avs_dev * adev,u32 core_mask)123215e67b2SCezary Rojewski static int avs_dsp_enable(struct avs_dev *adev, u32 core_mask)
124215e67b2SCezary Rojewski {
125215e67b2SCezary Rojewski 	u32 mask;
126215e67b2SCezary Rojewski 	int ret;
127215e67b2SCezary Rojewski 
128215e67b2SCezary Rojewski 	ret = avs_dsp_core_enable(adev, core_mask);
129215e67b2SCezary Rojewski 	if (ret < 0)
130215e67b2SCezary Rojewski 		return ret;
131215e67b2SCezary Rojewski 
132215e67b2SCezary Rojewski 	mask = core_mask & ~AVS_MAIN_CORE_MASK;
133215e67b2SCezary Rojewski 	if (!mask)
134215e67b2SCezary Rojewski 		/*
135215e67b2SCezary Rojewski 		 * without main core, fw is dead anyway
136215e67b2SCezary Rojewski 		 * so setting D0 for it is futile.
137215e67b2SCezary Rojewski 		 */
138215e67b2SCezary Rojewski 		return 0;
139215e67b2SCezary Rojewski 
140215e67b2SCezary Rojewski 	ret = avs_ipc_set_dx(adev, mask, true);
141215e67b2SCezary Rojewski 	return AVS_IPC_RET(ret);
142215e67b2SCezary Rojewski }
143215e67b2SCezary Rojewski 
avs_dsp_disable(struct avs_dev * adev,u32 core_mask)144215e67b2SCezary Rojewski static int avs_dsp_disable(struct avs_dev *adev, u32 core_mask)
145215e67b2SCezary Rojewski {
146215e67b2SCezary Rojewski 	int ret;
147215e67b2SCezary Rojewski 
148215e67b2SCezary Rojewski 	ret = avs_ipc_set_dx(adev, core_mask, false);
149215e67b2SCezary Rojewski 	if (ret)
150215e67b2SCezary Rojewski 		return AVS_IPC_RET(ret);
151215e67b2SCezary Rojewski 
152215e67b2SCezary Rojewski 	return avs_dsp_core_disable(adev, core_mask);
153215e67b2SCezary Rojewski }
154215e67b2SCezary Rojewski 
avs_dsp_get_core(struct avs_dev * adev,u32 core_id)155215e67b2SCezary Rojewski static int avs_dsp_get_core(struct avs_dev *adev, u32 core_id)
156215e67b2SCezary Rojewski {
157215e67b2SCezary Rojewski 	u32 mask;
158215e67b2SCezary Rojewski 	int ret;
159215e67b2SCezary Rojewski 
160215e67b2SCezary Rojewski 	mask = BIT_MASK(core_id);
161215e67b2SCezary Rojewski 	if (mask == AVS_MAIN_CORE_MASK)
162215e67b2SCezary Rojewski 		/* nothing to do for main core */
163215e67b2SCezary Rojewski 		return 0;
164215e67b2SCezary Rojewski 	if (core_id >= adev->hw_cfg.dsp_cores) {
165215e67b2SCezary Rojewski 		ret = -EINVAL;
166215e67b2SCezary Rojewski 		goto err;
167215e67b2SCezary Rojewski 	}
168215e67b2SCezary Rojewski 
169215e67b2SCezary Rojewski 	adev->core_refs[core_id]++;
170215e67b2SCezary Rojewski 	if (adev->core_refs[core_id] == 1) {
171335c4cbdSCezary Rojewski 		/*
172335c4cbdSCezary Rojewski 		 * No cores other than main-core can be running for DSP
173335c4cbdSCezary Rojewski 		 * to achieve d0ix. Conscious SET_D0IX IPC failure is permitted,
174335c4cbdSCezary Rojewski 		 * simply d0ix power state will no longer be attempted.
175335c4cbdSCezary Rojewski 		 */
176335c4cbdSCezary Rojewski 		ret = avs_dsp_disable_d0ix(adev);
177335c4cbdSCezary Rojewski 		if (ret && ret != -AVS_EIPC)
178335c4cbdSCezary Rojewski 			goto err_disable_d0ix;
179335c4cbdSCezary Rojewski 
180215e67b2SCezary Rojewski 		ret = avs_dsp_enable(adev, mask);
181215e67b2SCezary Rojewski 		if (ret)
182215e67b2SCezary Rojewski 			goto err_enable_dsp;
183215e67b2SCezary Rojewski 	}
184215e67b2SCezary Rojewski 
185215e67b2SCezary Rojewski 	return 0;
186215e67b2SCezary Rojewski 
187215e67b2SCezary Rojewski err_enable_dsp:
188335c4cbdSCezary Rojewski 	avs_dsp_enable_d0ix(adev);
189335c4cbdSCezary Rojewski err_disable_d0ix:
190215e67b2SCezary Rojewski 	adev->core_refs[core_id]--;
191215e67b2SCezary Rojewski err:
192215e67b2SCezary Rojewski 	dev_err(adev->dev, "get core %d failed: %d\n", core_id, ret);
193215e67b2SCezary Rojewski 	return ret;
194215e67b2SCezary Rojewski }
195215e67b2SCezary Rojewski 
avs_dsp_put_core(struct avs_dev * adev,u32 core_id)196215e67b2SCezary Rojewski static int avs_dsp_put_core(struct avs_dev *adev, u32 core_id)
197215e67b2SCezary Rojewski {
198215e67b2SCezary Rojewski 	u32 mask;
199215e67b2SCezary Rojewski 	int ret;
200215e67b2SCezary Rojewski 
201215e67b2SCezary Rojewski 	mask = BIT_MASK(core_id);
202215e67b2SCezary Rojewski 	if (mask == AVS_MAIN_CORE_MASK)
203215e67b2SCezary Rojewski 		/* nothing to do for main core */
204215e67b2SCezary Rojewski 		return 0;
205215e67b2SCezary Rojewski 	if (core_id >= adev->hw_cfg.dsp_cores) {
206215e67b2SCezary Rojewski 		ret = -EINVAL;
207215e67b2SCezary Rojewski 		goto err;
208215e67b2SCezary Rojewski 	}
209215e67b2SCezary Rojewski 
210215e67b2SCezary Rojewski 	adev->core_refs[core_id]--;
211215e67b2SCezary Rojewski 	if (!adev->core_refs[core_id]) {
212215e67b2SCezary Rojewski 		ret = avs_dsp_disable(adev, mask);
213215e67b2SCezary Rojewski 		if (ret)
214215e67b2SCezary Rojewski 			goto err;
215335c4cbdSCezary Rojewski 
216335c4cbdSCezary Rojewski 		/* Match disable_d0ix in avs_dsp_get_core(). */
217335c4cbdSCezary Rojewski 		avs_dsp_enable_d0ix(adev);
218215e67b2SCezary Rojewski 	}
219215e67b2SCezary Rojewski 
220215e67b2SCezary Rojewski 	return 0;
221215e67b2SCezary Rojewski err:
222215e67b2SCezary Rojewski 	dev_err(adev->dev, "put core %d failed: %d\n", core_id, ret);
223215e67b2SCezary Rojewski 	return ret;
224215e67b2SCezary Rojewski }
225215e67b2SCezary Rojewski 
avs_dsp_init_module(struct avs_dev * adev,u16 module_id,u8 ppl_instance_id,u8 core_id,u8 domain,void * param,u32 param_size,u8 * instance_id)226215e67b2SCezary Rojewski int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
227215e67b2SCezary Rojewski 			u8 core_id, u8 domain, void *param, u32 param_size,
228*320f4d86SAmadeusz Sławiński 			u8 *instance_id)
229215e67b2SCezary Rojewski {
230215e67b2SCezary Rojewski 	struct avs_module_entry mentry;
231b27f4523SCezary Rojewski 	bool was_loaded = false;
232215e67b2SCezary Rojewski 	int ret, id;
233215e67b2SCezary Rojewski 
234215e67b2SCezary Rojewski 	id = avs_module_id_alloc(adev, module_id);
235215e67b2SCezary Rojewski 	if (id < 0)
236215e67b2SCezary Rojewski 		return id;
237215e67b2SCezary Rojewski 
238215e67b2SCezary Rojewski 	ret = avs_get_module_id_entry(adev, module_id, &mentry);
239215e67b2SCezary Rojewski 	if (ret)
240215e67b2SCezary Rojewski 		goto err_mod_entry;
241215e67b2SCezary Rojewski 
242215e67b2SCezary Rojewski 	ret = avs_dsp_get_core(adev, core_id);
243215e67b2SCezary Rojewski 	if (ret)
244215e67b2SCezary Rojewski 		goto err_mod_entry;
245215e67b2SCezary Rojewski 
246b27f4523SCezary Rojewski 	/* Load code into memory if this is the first instance. */
247b27f4523SCezary Rojewski 	if (!id && !avs_module_entry_is_loaded(&mentry)) {
248b27f4523SCezary Rojewski 		ret = avs_dsp_op(adev, transfer_mods, true, &mentry, 1);
249b27f4523SCezary Rojewski 		if (ret) {
250b27f4523SCezary Rojewski 			dev_err(adev->dev, "load modules failed: %d\n", ret);
251b27f4523SCezary Rojewski 			goto err_mod_entry;
252b27f4523SCezary Rojewski 		}
253b27f4523SCezary Rojewski 		was_loaded = true;
254b27f4523SCezary Rojewski 	}
255b27f4523SCezary Rojewski 
256215e67b2SCezary Rojewski 	ret = avs_ipc_init_instance(adev, module_id, id, ppl_instance_id,
257215e67b2SCezary Rojewski 				    core_id, domain, param, param_size);
258215e67b2SCezary Rojewski 	if (ret) {
259215e67b2SCezary Rojewski 		ret = AVS_IPC_RET(ret);
260215e67b2SCezary Rojewski 		goto err_ipc;
261215e67b2SCezary Rojewski 	}
262215e67b2SCezary Rojewski 
263215e67b2SCezary Rojewski 	*instance_id = id;
264215e67b2SCezary Rojewski 	return 0;
265215e67b2SCezary Rojewski 
266215e67b2SCezary Rojewski err_ipc:
267b27f4523SCezary Rojewski 	if (was_loaded)
268b27f4523SCezary Rojewski 		avs_dsp_op(adev, transfer_mods, false, &mentry, 1);
269215e67b2SCezary Rojewski 	avs_dsp_put_core(adev, core_id);
270215e67b2SCezary Rojewski err_mod_entry:
271215e67b2SCezary Rojewski 	avs_module_id_free(adev, module_id, id);
272215e67b2SCezary Rojewski 	return ret;
273215e67b2SCezary Rojewski }
274215e67b2SCezary Rojewski 
avs_dsp_delete_module(struct avs_dev * adev,u16 module_id,u8 instance_id,u8 ppl_instance_id,u8 core_id)275*320f4d86SAmadeusz Sławiński void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u8 instance_id,
276215e67b2SCezary Rojewski 			   u8 ppl_instance_id, u8 core_id)
277215e67b2SCezary Rojewski {
278b27f4523SCezary Rojewski 	struct avs_module_entry mentry;
279b27f4523SCezary Rojewski 	int ret;
280b27f4523SCezary Rojewski 
281215e67b2SCezary Rojewski 	/* Modules not owned by any pipeline need to be freed explicitly. */
282215e67b2SCezary Rojewski 	if (ppl_instance_id == INVALID_PIPELINE_ID)
283215e67b2SCezary Rojewski 		avs_ipc_delete_instance(adev, module_id, instance_id);
284215e67b2SCezary Rojewski 
285215e67b2SCezary Rojewski 	avs_module_id_free(adev, module_id, instance_id);
286215e67b2SCezary Rojewski 
287b27f4523SCezary Rojewski 	ret = avs_get_module_id_entry(adev, module_id, &mentry);
288b27f4523SCezary Rojewski 	/* Unload occupied memory if this was the last instance. */
289b27f4523SCezary Rojewski 	if (!ret && mentry.type.load_type == AVS_MODULE_LOAD_TYPE_LOADABLE) {
290b27f4523SCezary Rojewski 		if (avs_is_module_ida_empty(adev, module_id)) {
291b27f4523SCezary Rojewski 			ret = avs_dsp_op(adev, transfer_mods, false, &mentry, 1);
292b27f4523SCezary Rojewski 			if (ret)
293b27f4523SCezary Rojewski 				dev_err(adev->dev, "unload modules failed: %d\n", ret);
294b27f4523SCezary Rojewski 		}
295b27f4523SCezary Rojewski 	}
296b27f4523SCezary Rojewski 
297215e67b2SCezary Rojewski 	avs_dsp_put_core(adev, core_id);
298215e67b2SCezary Rojewski }
299215e67b2SCezary Rojewski 
avs_dsp_create_pipeline(struct avs_dev * adev,u16 req_size,u8 priority,bool lp,u16 attributes,u8 * instance_id)300215e67b2SCezary Rojewski int avs_dsp_create_pipeline(struct avs_dev *adev, u16 req_size, u8 priority,
301215e67b2SCezary Rojewski 			    bool lp, u16 attributes, u8 *instance_id)
302215e67b2SCezary Rojewski {
303215e67b2SCezary Rojewski 	struct avs_fw_cfg *fw_cfg = &adev->fw_cfg;
304215e67b2SCezary Rojewski 	int ret, id;
305215e67b2SCezary Rojewski 
306215e67b2SCezary Rojewski 	id = ida_alloc_max(&adev->ppl_ida, fw_cfg->max_ppl_count - 1, GFP_KERNEL);
307215e67b2SCezary Rojewski 	if (id < 0)
308215e67b2SCezary Rojewski 		return id;
309215e67b2SCezary Rojewski 
310215e67b2SCezary Rojewski 	ret = avs_ipc_create_pipeline(adev, req_size, priority, id, lp, attributes);
311215e67b2SCezary Rojewski 	if (ret) {
312215e67b2SCezary Rojewski 		ida_free(&adev->ppl_ida, id);
313215e67b2SCezary Rojewski 		return AVS_IPC_RET(ret);
314215e67b2SCezary Rojewski 	}
315215e67b2SCezary Rojewski 
316215e67b2SCezary Rojewski 	*instance_id = id;
317215e67b2SCezary Rojewski 	return 0;
318215e67b2SCezary Rojewski }
319215e67b2SCezary Rojewski 
avs_dsp_delete_pipeline(struct avs_dev * adev,u8 instance_id)320215e67b2SCezary Rojewski int avs_dsp_delete_pipeline(struct avs_dev *adev, u8 instance_id)
321215e67b2SCezary Rojewski {
322215e67b2SCezary Rojewski 	int ret;
323215e67b2SCezary Rojewski 
324215e67b2SCezary Rojewski 	ret = avs_ipc_delete_pipeline(adev, instance_id);
325215e67b2SCezary Rojewski 	if (ret)
326215e67b2SCezary Rojewski 		ret = AVS_IPC_RET(ret);
327215e67b2SCezary Rojewski 
328215e67b2SCezary Rojewski 	ida_free(&adev->ppl_ida, instance_id);
329215e67b2SCezary Rojewski 	return ret;
330215e67b2SCezary Rojewski }
331