|
31 | 31 | #define FASTRPC_PHYS(p) ((p) & 0xffffffff) |
32 | 32 | #define FASTRPC_CTX_MAX (256) |
33 | 33 | #define FASTRPC_INIT_HANDLE 1 |
| 34 | +#define FASTRPC_DSP_UTILITIES_HANDLE 2 |
34 | 35 | #define FASTRPC_CTXID_MASK (0xFF0) |
35 | 36 | #define INIT_FILELEN_MAX (2 * 1024 * 1024) |
36 | 37 | #define FASTRPC_DEVICE_NAME "fastrpc" |
37 | 38 | #define ADSP_MMAP_ADD_PAGES 0x1000 |
| 39 | +#define DSP_UNSUPPORTED_API (0x80000414) |
| 40 | +/* MAX NUMBER of DSP ATTRIBUTES SUPPORTED */ |
| 41 | +#define FASTRPC_MAX_DSP_ATTRIBUTES (256) |
| 42 | +#define FASTRPC_MAX_DSP_ATTRIBUTES_LEN (sizeof(u32) * FASTRPC_MAX_DSP_ATTRIBUTES) |
38 | 43 |
|
39 | 44 | /* Retrives number of input buffers from the scalars parameter */ |
40 | 45 | #define REMOTE_SCALARS_INBUFS(sc) (((sc) >> 16) & 0x0ff) |
@@ -233,6 +238,9 @@ struct fastrpc_channel_ctx { |
233 | 238 | struct idr ctx_idr; |
234 | 239 | struct list_head users; |
235 | 240 | struct kref refcount; |
| 241 | + /* Flag if dsp attributes are cached */ |
| 242 | + bool valid_attributes; |
| 243 | + u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; |
236 | 244 | struct fastrpc_device *fdevice; |
237 | 245 | }; |
238 | 246 |
|
@@ -1378,6 +1386,107 @@ static int fastrpc_invoke(struct fastrpc_user *fl, char __user *argp) |
1378 | 1386 | return err; |
1379 | 1387 | } |
1380 | 1388 |
|
| 1389 | +static int fastrpc_get_info_from_dsp(struct fastrpc_user *fl, uint32_t *dsp_attr_buf, |
| 1390 | + uint32_t dsp_attr_buf_len) |
| 1391 | +{ |
| 1392 | + struct fastrpc_invoke_args args[2] = { 0 }; |
| 1393 | + |
| 1394 | + /* Capability filled in userspace */ |
| 1395 | + dsp_attr_buf[0] = 0; |
| 1396 | + |
| 1397 | + args[0].ptr = (u64)(uintptr_t)&dsp_attr_buf_len; |
| 1398 | + args[0].length = sizeof(dsp_attr_buf_len); |
| 1399 | + args[0].fd = -1; |
| 1400 | + args[1].ptr = (u64)(uintptr_t)&dsp_attr_buf[1]; |
| 1401 | + args[1].length = dsp_attr_buf_len; |
| 1402 | + args[1].fd = -1; |
| 1403 | + fl->pd = 1; |
| 1404 | + |
| 1405 | + return fastrpc_internal_invoke(fl, true, FASTRPC_DSP_UTILITIES_HANDLE, |
| 1406 | + FASTRPC_SCALARS(0, 1, 1), args); |
| 1407 | +} |
| 1408 | + |
| 1409 | +static int fastrpc_get_info_from_kernel(struct fastrpc_ioctl_capability *cap, |
| 1410 | + struct fastrpc_user *fl) |
| 1411 | +{ |
| 1412 | + struct fastrpc_channel_ctx *cctx = fl->cctx; |
| 1413 | + uint32_t attribute_id = cap->attribute_id; |
| 1414 | + uint32_t *dsp_attributes; |
| 1415 | + unsigned long flags; |
| 1416 | + uint32_t domain = cap->domain; |
| 1417 | + int err; |
| 1418 | + |
| 1419 | + spin_lock_irqsave(&cctx->lock, flags); |
| 1420 | + /* check if we already have queried dsp for attributes */ |
| 1421 | + if (cctx->valid_attributes) { |
| 1422 | + spin_unlock_irqrestore(&cctx->lock, flags); |
| 1423 | + goto done; |
| 1424 | + } |
| 1425 | + spin_unlock_irqrestore(&cctx->lock, flags); |
| 1426 | + |
| 1427 | + dsp_attributes = kzalloc(FASTRPC_MAX_DSP_ATTRIBUTES_LEN, GFP_KERNEL); |
| 1428 | + if (!dsp_attributes) |
| 1429 | + return -ENOMEM; |
| 1430 | + |
| 1431 | + err = fastrpc_get_info_from_dsp(fl, dsp_attributes, FASTRPC_MAX_DSP_ATTRIBUTES_LEN); |
| 1432 | + if (err == DSP_UNSUPPORTED_API) { |
| 1433 | + dev_info(&cctx->rpdev->dev, |
| 1434 | + "Warning: DSP capabilities not supported on domain: %d\n", domain); |
| 1435 | + kfree(dsp_attributes); |
| 1436 | + return -EOPNOTSUPP; |
| 1437 | + } else if (err) { |
| 1438 | + dev_err(&cctx->rpdev->dev, "Error: dsp information is incorrect err: %d\n", err); |
| 1439 | + kfree(dsp_attributes); |
| 1440 | + return err; |
| 1441 | + } |
| 1442 | + |
| 1443 | + spin_lock_irqsave(&cctx->lock, flags); |
| 1444 | + memcpy(cctx->dsp_attributes, dsp_attributes, FASTRPC_MAX_DSP_ATTRIBUTES_LEN); |
| 1445 | + cctx->valid_attributes = true; |
| 1446 | + spin_unlock_irqrestore(&cctx->lock, flags); |
| 1447 | + kfree(dsp_attributes); |
| 1448 | +done: |
| 1449 | + cap->capability = cctx->dsp_attributes[attribute_id]; |
| 1450 | + return 0; |
| 1451 | +} |
| 1452 | + |
| 1453 | +static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp) |
| 1454 | +{ |
| 1455 | + struct fastrpc_ioctl_capability cap = {0}; |
| 1456 | + int err = 0; |
| 1457 | + |
| 1458 | + if (copy_from_user(&cap, argp, sizeof(cap))) |
| 1459 | + return -EFAULT; |
| 1460 | + |
| 1461 | + cap.capability = 0; |
| 1462 | + if (cap.domain >= FASTRPC_DEV_MAX) { |
| 1463 | + dev_err(&fl->cctx->rpdev->dev, "Error: Invalid domain id:%d, err:%d\n", |
| 1464 | + cap.domain, err); |
| 1465 | + return -ECHRNG; |
| 1466 | + } |
| 1467 | + |
| 1468 | + /* Fastrpc Capablities does not support modem domain */ |
| 1469 | + if (cap.domain == MDSP_DOMAIN_ID) { |
| 1470 | + dev_err(&fl->cctx->rpdev->dev, "Error: modem not supported %d\n", err); |
| 1471 | + return -ECHRNG; |
| 1472 | + } |
| 1473 | + |
| 1474 | + if (cap.attribute_id >= FASTRPC_MAX_DSP_ATTRIBUTES) { |
| 1475 | + dev_err(&fl->cctx->rpdev->dev, "Error: invalid attribute: %d, err: %d\n", |
| 1476 | + cap.attribute_id, err); |
| 1477 | + return -EOVERFLOW; |
| 1478 | + } |
| 1479 | + |
| 1480 | + err = fastrpc_get_info_from_kernel(&cap, fl); |
| 1481 | + if (err) |
| 1482 | + return err; |
| 1483 | + |
| 1484 | + if (copy_to_user(argp, &cap.capability, sizeof(cap.capability))) |
| 1485 | + return -EFAULT; |
| 1486 | + |
| 1487 | + return 0; |
| 1488 | +} |
| 1489 | + |
1381 | 1490 | static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, |
1382 | 1491 | struct fastrpc_req_munmap *req) |
1383 | 1492 | { |
@@ -1683,6 +1792,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd, |
1683 | 1792 | case FASTRPC_IOCTL_MEM_UNMAP: |
1684 | 1793 | err = fastrpc_req_mem_unmap(fl, argp); |
1685 | 1794 | break; |
| 1795 | + case FASTRPC_IOCTL_GET_DSP_INFO: |
| 1796 | + err = fastrpc_get_dsp_info(fl, argp); |
| 1797 | + break; |
1686 | 1798 | default: |
1687 | 1799 | err = -ENOTTY; |
1688 | 1800 | break; |
|
0 commit comments