From: Dan Carpenter <dan.carpenter@oracle.com>
To: Vijendar.Mukunda@amd.com
Cc: amd-gfx@lists.freedesktop.org
Subject: [bug report] drm/amdgpu: create I2S platform devices for Jadeite platform
Date: Tue, 26 Jul 2022 18:17:22 +0300 [thread overview]
Message-ID: <YuAFgoepMHvkw3CB@kili> (raw)
Hello Vijendar Mukunda,
The patch 4c33e5179ff1: "drm/amdgpu: create I2S platform devices for
Jadeite platform" from Jun 30, 2022, leads to the following Smatch
static checker warning:
drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:393 acp_hw_init()
error: buffer overflow 'i2s_pdata' 3 <= 3
drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:396 acp_hw_init()
error: buffer overflow 'i2s_pdata' 3 <= 3
drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
225 static int acp_hw_init(void *handle)
226 {
227 int r;
228 u64 acp_base;
229 u32 val = 0;
230 u32 count = 0;
231 struct i2s_platform_data *i2s_pdata = NULL;
232
233 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
234
235 const struct amdgpu_ip_block *ip_block =
236 amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ACP);
237
238 if (!ip_block)
239 return -EINVAL;
240
241 r = amd_acp_hw_init(adev->acp.cgs_device,
242 ip_block->version->major, ip_block->version->minor);
243 /* -ENODEV means board uses AZ rather than ACP */
244 if (r == -ENODEV) {
245 amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
246 return 0;
247 } else if (r) {
248 return r;
249 }
250
251 if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
252 return -EINVAL;
253
254 acp_base = adev->rmmio_base;
255 adev->acp.acp_genpd = kzalloc(sizeof(struct acp_pm_domain), GFP_KERNEL);
256 if (!adev->acp.acp_genpd)
257 return -ENOMEM;
258
259 adev->acp.acp_genpd->gpd.name = "ACP_AUDIO";
260 adev->acp.acp_genpd->gpd.power_off = acp_poweroff;
261 adev->acp.acp_genpd->gpd.power_on = acp_poweron;
262 adev->acp.acp_genpd->adev = adev;
263
264 pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false);
265 dmi_check_system(acp_quirk_table);
266 switch (acp_machine_id) {
267 case ST_JADEITE:
268 {
269 adev->acp.acp_cell = kcalloc(2, sizeof(struct mfd_cell),
270 GFP_KERNEL);
271 if (!adev->acp.acp_cell) {
272 r = -ENOMEM;
273 goto failure;
274 }
275
276 adev->acp.acp_res = kcalloc(3, sizeof(struct resource), GFP_KERNEL);
277 if (!adev->acp.acp_res) {
278 r = -ENOMEM;
279 goto failure;
280 }
281
282 i2s_pdata = kcalloc(1, sizeof(struct i2s_platform_data), GFP_KERNEL);
283 if (!i2s_pdata) {
284 r = -ENOMEM;
285 goto failure;
286 }
287
288 i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
289 DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
290 i2s_pdata[0].cap = DWC_I2S_PLAY | DWC_I2S_RECORD;
291 i2s_pdata[0].snd_rates = SNDRV_PCM_RATE_8000_96000;
292 i2s_pdata[0].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET;
293 i2s_pdata[0].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET;
294
295 adev->acp.acp_res[0].name = "acp2x_dma";
296 adev->acp.acp_res[0].flags = IORESOURCE_MEM;
297 adev->acp.acp_res[0].start = acp_base;
298 adev->acp.acp_res[0].end = acp_base + ACP_DMA_REGS_END;
299
300 adev->acp.acp_res[1].name = "acp2x_dw_i2s_play_cap";
301 adev->acp.acp_res[1].flags = IORESOURCE_MEM;
302 adev->acp.acp_res[1].start = acp_base + ACP_I2S_CAP_REGS_START;
303 adev->acp.acp_res[1].end = acp_base + ACP_I2S_CAP_REGS_END;
304
305 adev->acp.acp_res[2].name = "acp2x_dma_irq";
306 adev->acp.acp_res[2].flags = IORESOURCE_IRQ;
307 adev->acp.acp_res[2].start = amdgpu_irq_create_mapping(adev, 162);
308 adev->acp.acp_res[2].end = adev->acp.acp_res[2].start;
309
310 adev->acp.acp_cell[0].name = "acp_audio_dma";
311 adev->acp.acp_cell[0].num_resources = 3;
312 adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0];
313 adev->acp.acp_cell[0].platform_data = &adev->asic_type;
314 adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type);
315
316 adev->acp.acp_cell[1].name = "designware-i2s";
317 adev->acp.acp_cell[1].num_resources = 1;
318 adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1];
319 adev->acp.acp_cell[1].platform_data = &i2s_pdata[0];
320 adev->acp.acp_cell[1].pdata_size = sizeof(struct i2s_platform_data);
321 r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, 2);
322 if (r)
323 goto failure;
324 r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
325 acp_genpd_add_device);
326 if (r)
327 goto failure;
328 break;
329 }
330 default:
331 adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell),
332 GFP_KERNEL);
333
334 if (!adev->acp.acp_cell) {
335 r = -ENOMEM;
336 goto failure;
337 }
338
339 adev->acp.acp_res = kcalloc(5, sizeof(struct resource), GFP_KERNEL);
340 if (!adev->acp.acp_res) {
341 r = -ENOMEM;
342 goto failure;
343 }
344
345 i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), GFP_KERNEL);
^
3 elements
346 if (!i2s_pdata) {
347 r = -ENOMEM;
348 goto failure;
349 }
350
351 switch (adev->asic_type) {
352 case CHIP_STONEY:
353 i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
354 DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
355 break;
356 default:
357 i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
358 }
359 i2s_pdata[0].cap = DWC_I2S_PLAY;
360 i2s_pdata[0].snd_rates = SNDRV_PCM_RATE_8000_96000;
361 i2s_pdata[0].i2s_reg_comp1 = ACP_I2S_COMP1_PLAY_REG_OFFSET;
362 i2s_pdata[0].i2s_reg_comp2 = ACP_I2S_COMP2_PLAY_REG_OFFSET;
363 switch (adev->asic_type) {
364 case CHIP_STONEY:
365 i2s_pdata[1].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
366 DW_I2S_QUIRK_COMP_PARAM1 |
367 DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
368 break;
369 default:
370 i2s_pdata[1].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
371 DW_I2S_QUIRK_COMP_PARAM1;
372 }
373
374 i2s_pdata[1].cap = DWC_I2S_RECORD;
375 i2s_pdata[1].snd_rates = SNDRV_PCM_RATE_8000_96000;
376 i2s_pdata[1].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET;
377 i2s_pdata[1].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET;
378
379 i2s_pdata[2].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
380 switch (adev->asic_type) {
381 case CHIP_STONEY:
382 i2s_pdata[2].quirks |= DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
383 break;
384 default:
385 break;
386 }
387
388 i2s_pdata[2].cap = DWC_I2S_PLAY | DWC_I2S_RECORD;
389 i2s_pdata[2].snd_rates = SNDRV_PCM_RATE_8000_96000;
390 i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET;
391 i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET;
392
--> 393 i2s_pdata[3].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
^^^^^^^^^^^^
394 switch (adev->asic_type) {
395 case CHIP_STONEY:
396 i2s_pdata[3].quirks |= DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
^^^^^^^^^^^^
Out of boundses.
397 break;
398 default:
399 break;
400 }
401 adev->acp.acp_res[0].name = "acp2x_dma";
402 adev->acp.acp_res[0].flags = IORESOURCE_MEM;
403 adev->acp.acp_res[0].start = acp_base;
404 adev->acp.acp_res[0].end = acp_base + ACP_DMA_REGS_END;
405
406 adev->acp.acp_res[1].name = "acp2x_dw_i2s_play";
407 adev->acp.acp_res[1].flags = IORESOURCE_MEM;
408 adev->acp.acp_res[1].start = acp_base + ACP_I2S_PLAY_REGS_START;
409 adev->acp.acp_res[1].end = acp_base + ACP_I2S_PLAY_REGS_END;
410
411 adev->acp.acp_res[2].name = "acp2x_dw_i2s_cap";
412 adev->acp.acp_res[2].flags = IORESOURCE_MEM;
413 adev->acp.acp_res[2].start = acp_base + ACP_I2S_CAP_REGS_START;
414 adev->acp.acp_res[2].end = acp_base + ACP_I2S_CAP_REGS_END;
415
416 adev->acp.acp_res[3].name = "acp2x_dw_bt_i2s_play_cap";
417 adev->acp.acp_res[3].flags = IORESOURCE_MEM;
418 adev->acp.acp_res[3].start = acp_base + ACP_BT_PLAY_REGS_START;
419 adev->acp.acp_res[3].end = acp_base + ACP_BT_PLAY_REGS_END;
420
421 adev->acp.acp_res[4].name = "acp2x_dma_irq";
422 adev->acp.acp_res[4].flags = IORESOURCE_IRQ;
423 adev->acp.acp_res[4].start = amdgpu_irq_create_mapping(adev, 162);
424 adev->acp.acp_res[4].end = adev->acp.acp_res[4].start;
425
426 adev->acp.acp_cell[0].name = "acp_audio_dma";
427 adev->acp.acp_cell[0].num_resources = 5;
428 adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0];
429 adev->acp.acp_cell[0].platform_data = &adev->asic_type;
430 adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type);
431
432 adev->acp.acp_cell[1].name = "designware-i2s";
433 adev->acp.acp_cell[1].num_resources = 1;
434 adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1];
435 adev->acp.acp_cell[1].platform_data = &i2s_pdata[0];
436 adev->acp.acp_cell[1].pdata_size = sizeof(struct i2s_platform_data);
437
438 adev->acp.acp_cell[2].name = "designware-i2s";
439 adev->acp.acp_cell[2].num_resources = 1;
440 adev->acp.acp_cell[2].resources = &adev->acp.acp_res[2];
441 adev->acp.acp_cell[2].platform_data = &i2s_pdata[1];
442 adev->acp.acp_cell[2].pdata_size = sizeof(struct i2s_platform_data);
443
444 adev->acp.acp_cell[3].name = "designware-i2s";
445 adev->acp.acp_cell[3].num_resources = 1;
446 adev->acp.acp_cell[3].resources = &adev->acp.acp_res[3];
447 adev->acp.acp_cell[3].platform_data = &i2s_pdata[2];
448 adev->acp.acp_cell[3].pdata_size = sizeof(struct i2s_platform_data);
449
450 r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, ACP_DEVS);
451 if (r)
452 goto failure;
453
454 r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
455 acp_genpd_add_device);
456 if (r)
457 goto failure;
458 }
459
460 /* Assert Soft reset of ACP */
461 val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
462
463 val |= ACP_SOFT_RESET__SoftResetAud_MASK;
464 cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
465
466 count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE;
467 while (true) {
468 val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
469 if (ACP_SOFT_RESET__SoftResetAudDone_MASK ==
470 (val & ACP_SOFT_RESET__SoftResetAudDone_MASK))
471 break;
472 if (--count == 0) {
473 dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
474 r = -ETIMEDOUT;
475 goto failure;
476 }
477 udelay(100);
478 }
479 /* Enable clock to ACP and wait until the clock is enabled */
480 val = cgs_read_register(adev->acp.cgs_device, mmACP_CONTROL);
481 val = val | ACP_CONTROL__ClkEn_MASK;
482 cgs_write_register(adev->acp.cgs_device, mmACP_CONTROL, val);
483
484 count = ACP_CLOCK_EN_TIME_OUT_VALUE;
485
486 while (true) {
487 val = cgs_read_register(adev->acp.cgs_device, mmACP_STATUS);
488 if (val & (u32) 0x1)
489 break;
490 if (--count == 0) {
491 dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
492 r = -ETIMEDOUT;
493 goto failure;
494 }
495 udelay(100);
496 }
497 /* Deassert the SOFT RESET flags */
498 val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
499 val &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
500 cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
501 return 0;
502
503 failure:
504 kfree(i2s_pdata);
505 kfree(adev->acp.acp_res);
506 kfree(adev->acp.acp_cell);
507 kfree(adev->acp.acp_genpd);
508 return r;
509 }
regards,
dan carpenter
next reply other threads:[~2022-07-26 15:17 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-26 15:17 Dan Carpenter [this message]
2022-07-27 6:36 ` [bug report] drm/amdgpu: create I2S platform devices for Jadeite platform Mukunda,Vijendar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YuAFgoepMHvkw3CB@kili \
--to=dan.carpenter@oracle.com \
--cc=Vijendar.Mukunda@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.