On 7/26/22 8:47 PM, Dan Carpenter wrote: > 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 will fix it and provide a patch. -- Vijendar > > 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