diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/common/nvgpu_common.c | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | 350 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h | 11 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 5 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/vgpu.c | 2 |
5 files changed, 363 insertions, 7 deletions
diff --git a/drivers/gpu/nvgpu/common/nvgpu_common.c b/drivers/gpu/nvgpu/common/nvgpu_common.c index f1109684..d7ff4841 100644 --- a/drivers/gpu/nvgpu/common/nvgpu_common.c +++ b/drivers/gpu/nvgpu/common/nvgpu_common.c | |||
@@ -52,6 +52,8 @@ static void nvgpu_init_vars(struct gk20a *g) | |||
52 | 52 | ||
53 | INIT_LIST_HEAD(&g->pending_sema_waits); | 53 | INIT_LIST_HEAD(&g->pending_sema_waits); |
54 | nvgpu_raw_spinlock_init(&g->pending_sema_waits_lock); | 54 | nvgpu_raw_spinlock_init(&g->pending_sema_waits_lock); |
55 | |||
56 | INIT_LIST_HEAD(&g->profiler_objects); | ||
55 | } | 57 | } |
56 | 58 | ||
57 | static void nvgpu_init_timeout(struct gk20a *g) | 59 | static void nvgpu_init_timeout(struct gk20a *g) |
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c index 7eb742ed..12d81343 100644 --- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | |||
@@ -62,11 +62,11 @@ nvgpu_dbg_gpu_get_session_channel(struct dbg_session_gk20a *dbg_s) | |||
62 | return ch; | 62 | return ch; |
63 | } | 63 | } |
64 | 64 | ||
65 | /* silly allocator - just increment session id */ | 65 | /* silly allocator - just increment id */ |
66 | static atomic_t session_id = ATOMIC_INIT(0); | 66 | static atomic_t unique_id = ATOMIC_INIT(0); |
67 | static int generate_session_id(void) | 67 | static int generate_unique_id(void) |
68 | { | 68 | { |
69 | return atomic_add_return(1, &session_id); | 69 | return atomic_add_return(1, &unique_id); |
70 | } | 70 | } |
71 | 71 | ||
72 | static int alloc_session(struct dbg_session_gk20a **_dbg_s) | 72 | static int alloc_session(struct dbg_session_gk20a **_dbg_s) |
@@ -80,11 +80,27 @@ static int alloc_session(struct dbg_session_gk20a **_dbg_s) | |||
80 | if (!dbg_s) | 80 | if (!dbg_s) |
81 | return -ENOMEM; | 81 | return -ENOMEM; |
82 | 82 | ||
83 | dbg_s->id = generate_session_id(); | 83 | dbg_s->id = generate_unique_id(); |
84 | *_dbg_s = dbg_s; | 84 | *_dbg_s = dbg_s; |
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
87 | 87 | ||
88 | static int alloc_profiler(struct dbg_profiler_object_data **_prof) | ||
89 | { | ||
90 | struct dbg_profiler_object_data *prof; | ||
91 | *_prof = NULL; | ||
92 | |||
93 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, ""); | ||
94 | |||
95 | prof = kzalloc(sizeof(*prof), GFP_KERNEL); | ||
96 | if (!prof) | ||
97 | return -ENOMEM; | ||
98 | |||
99 | prof->prof_handle = generate_unique_id(); | ||
100 | *_prof = prof; | ||
101 | return 0; | ||
102 | } | ||
103 | |||
88 | static int gk20a_dbg_gpu_do_dev_open(struct inode *inode, | 104 | static int gk20a_dbg_gpu_do_dev_open(struct inode *inode, |
89 | struct file *filp, bool is_profiler) | 105 | struct file *filp, bool is_profiler) |
90 | { | 106 | { |
@@ -400,13 +416,28 @@ int dbg_unbind_single_channel_gk20a(struct dbg_session_gk20a *dbg_s, | |||
400 | { | 416 | { |
401 | struct gk20a *g = dbg_s->g; | 417 | struct gk20a *g = dbg_s->g; |
402 | int chid; | 418 | int chid; |
403 | struct channel_gk20a *ch; | ||
404 | struct dbg_session_data *session_data; | 419 | struct dbg_session_data *session_data; |
420 | struct dbg_profiler_object_data *prof_obj, *tmp_obj; | ||
405 | 421 | ||
406 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, ""); | 422 | gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, ""); |
407 | 423 | ||
408 | chid = ch_data->chid; | 424 | chid = ch_data->chid; |
409 | ch = g->fifo.channel + chid; | 425 | |
426 | /* If there's a profiler ctx reservation record associated with this | ||
427 | * session/channel pair, release it. | ||
428 | */ | ||
429 | list_for_each_entry_safe(prof_obj, tmp_obj, &g->profiler_objects, | ||
430 | prof_obj_entry) { | ||
431 | if ((prof_obj->session_id == dbg_s->id) && | ||
432 | (prof_obj->ch->hw_chid == chid)) { | ||
433 | if (prof_obj->has_reservation) { | ||
434 | g->profiler_reservation_count--; | ||
435 | dbg_s->has_profiler_reservation = false; | ||
436 | } | ||
437 | list_del(&prof_obj->prof_obj_entry); | ||
438 | kfree(prof_obj); | ||
439 | } | ||
440 | } | ||
410 | 441 | ||
411 | list_del_init(&ch_data->ch_entry); | 442 | list_del_init(&ch_data->ch_entry); |
412 | 443 | ||
@@ -480,6 +511,7 @@ int gk20a_dbg_gpu_dev_release(struct inode *inode, struct file *filp) | |||
480 | { | 511 | { |
481 | struct dbg_session_gk20a *dbg_s = filp->private_data; | 512 | struct dbg_session_gk20a *dbg_s = filp->private_data; |
482 | struct gk20a *g = dbg_s->g; | 513 | struct gk20a *g = dbg_s->g; |
514 | struct dbg_profiler_object_data *prof_obj, *tmp_obj; | ||
483 | 515 | ||
484 | gk20a_dbg(gpu_dbg_gpu_dbg | gpu_dbg_fn, "%s", dev_name(dbg_s->dev)); | 516 | gk20a_dbg(gpu_dbg_gpu_dbg | gpu_dbg_fn, "%s", dev_name(dbg_s->dev)); |
485 | 517 | ||
@@ -494,6 +526,21 @@ int gk20a_dbg_gpu_dev_release(struct inode *inode, struct file *filp) | |||
494 | g->ops.dbg_session_ops.dbg_set_powergate(dbg_s, | 526 | g->ops.dbg_session_ops.dbg_set_powergate(dbg_s, |
495 | NVGPU_DBG_GPU_POWERGATE_MODE_ENABLE); | 527 | NVGPU_DBG_GPU_POWERGATE_MODE_ENABLE); |
496 | nvgpu_dbg_timeout_enable(dbg_s, NVGPU_DBG_GPU_IOCTL_TIMEOUT_ENABLE); | 528 | nvgpu_dbg_timeout_enable(dbg_s, NVGPU_DBG_GPU_IOCTL_TIMEOUT_ENABLE); |
529 | |||
530 | /* Per-context profiler objects were released when we called | ||
531 | * dbg_unbind_all_channels. We could still have global ones. | ||
532 | */ | ||
533 | list_for_each_entry_safe(prof_obj, tmp_obj, &g->profiler_objects, | ||
534 | prof_obj_entry) { | ||
535 | if (prof_obj->session_id == dbg_s->id) { | ||
536 | if (prof_obj->has_reservation) { | ||
537 | g->global_profiler_reservation_held = false; | ||
538 | g->profiler_reservation_count--; | ||
539 | } | ||
540 | list_del(&prof_obj->prof_obj_entry); | ||
541 | kfree(prof_obj); | ||
542 | } | ||
543 | } | ||
497 | nvgpu_mutex_release(&g->dbg_sessions_lock); | 544 | nvgpu_mutex_release(&g->dbg_sessions_lock); |
498 | 545 | ||
499 | nvgpu_mutex_destroy(&dbg_s->ch_list_lock); | 546 | nvgpu_mutex_destroy(&dbg_s->ch_list_lock); |
@@ -584,6 +631,15 @@ static int nvgpu_dbg_gpu_ioctl_suspend_resume_sm( | |||
584 | struct dbg_session_gk20a *dbg_s, | 631 | struct dbg_session_gk20a *dbg_s, |
585 | struct nvgpu_dbg_gpu_suspend_resume_all_sms_args *args); | 632 | struct nvgpu_dbg_gpu_suspend_resume_all_sms_args *args); |
586 | 633 | ||
634 | static int nvgpu_ioctl_allocate_profiler_object(struct dbg_session_gk20a *dbg_s, | ||
635 | struct nvgpu_dbg_gpu_profiler_obj_mgt_args *args); | ||
636 | |||
637 | static int nvgpu_ioctl_free_profiler_object(struct dbg_session_gk20a *dbg_s, | ||
638 | struct nvgpu_dbg_gpu_profiler_obj_mgt_args *args); | ||
639 | |||
640 | static int nvgpu_ioctl_profiler_reserve(struct dbg_session_gk20a *dbg_s, | ||
641 | struct nvgpu_dbg_gpu_profiler_reserve_args *args); | ||
642 | |||
587 | static int gk20a_perfbuf_map(struct dbg_session_gk20a *dbg_s, | 643 | static int gk20a_perfbuf_map(struct dbg_session_gk20a *dbg_s, |
588 | struct nvgpu_dbg_gpu_perfbuf_map_args *args); | 644 | struct nvgpu_dbg_gpu_perfbuf_map_args *args); |
589 | 645 | ||
@@ -1022,6 +1078,21 @@ long gk20a_dbg_gpu_dev_ioctl(struct file *filp, unsigned int cmd, | |||
1022 | (struct nvgpu_dbg_gpu_access_fb_memory_args *)buf); | 1078 | (struct nvgpu_dbg_gpu_access_fb_memory_args *)buf); |
1023 | break; | 1079 | break; |
1024 | 1080 | ||
1081 | case NVGPU_DBG_GPU_IOCTL_PROFILER_ALLOCATE: | ||
1082 | err = nvgpu_ioctl_allocate_profiler_object(dbg_s, | ||
1083 | (struct nvgpu_dbg_gpu_profiler_obj_mgt_args *)buf); | ||
1084 | break; | ||
1085 | |||
1086 | case NVGPU_DBG_GPU_IOCTL_PROFILER_FREE: | ||
1087 | err = nvgpu_ioctl_free_profiler_object(dbg_s, | ||
1088 | (struct nvgpu_dbg_gpu_profiler_obj_mgt_args *)buf); | ||
1089 | break; | ||
1090 | |||
1091 | case NVGPU_DBG_GPU_IOCTL_PROFILER_RESERVE: | ||
1092 | err = nvgpu_ioctl_profiler_reserve(dbg_s, | ||
1093 | (struct nvgpu_dbg_gpu_profiler_reserve_args *)buf); | ||
1094 | break; | ||
1095 | |||
1025 | default: | 1096 | default: |
1026 | gk20a_err(dev_from_gk20a(g), | 1097 | gk20a_err(dev_from_gk20a(g), |
1027 | "unrecognized dbg gpu ioctl cmd: 0x%x", | 1098 | "unrecognized dbg gpu ioctl cmd: 0x%x", |
@@ -1357,6 +1428,16 @@ static int nvgpu_dbg_gpu_ioctl_hwpm_ctxsw_mode(struct dbg_session_gk20a *dbg_s, | |||
1357 | gk20a_dbg_fn("%s pm ctxsw mode = %d", | 1428 | gk20a_dbg_fn("%s pm ctxsw mode = %d", |
1358 | dev_name(dbg_s->dev), args->mode); | 1429 | dev_name(dbg_s->dev), args->mode); |
1359 | 1430 | ||
1431 | /* Must have a valid reservation to enable/disable hwpm cxtsw. | ||
1432 | * Just print an error message for now, but eventually this should | ||
1433 | * return an error, at the point where all client sw has been | ||
1434 | * cleaned up. | ||
1435 | */ | ||
1436 | if (!dbg_s->has_profiler_reservation) { | ||
1437 | gk20a_err(dev_from_gk20a(g), | ||
1438 | "session doesn't have a valid reservation"); | ||
1439 | } | ||
1440 | |||
1360 | err = gk20a_busy(g->dev); | 1441 | err = gk20a_busy(g->dev); |
1361 | if (err) { | 1442 | if (err) { |
1362 | gk20a_err(dev_from_gk20a(g), "failed to poweron"); | 1443 | gk20a_err(dev_from_gk20a(g), "failed to poweron"); |
@@ -1440,6 +1521,261 @@ clean_up: | |||
1440 | return err; | 1521 | return err; |
1441 | } | 1522 | } |
1442 | 1523 | ||
1524 | static int nvgpu_ioctl_allocate_profiler_object( | ||
1525 | struct dbg_session_gk20a *dbg_s, | ||
1526 | struct nvgpu_dbg_gpu_profiler_obj_mgt_args *args) | ||
1527 | { | ||
1528 | int err = 0; | ||
1529 | struct gk20a *g = get_gk20a(dbg_s->dev); | ||
1530 | struct dbg_profiler_object_data *prof_obj; | ||
1531 | |||
1532 | gk20a_dbg_fn("%s", dev_name(dbg_s->dev)); | ||
1533 | |||
1534 | nvgpu_mutex_acquire(&g->dbg_sessions_lock); | ||
1535 | |||
1536 | err = alloc_profiler(&prof_obj); | ||
1537 | if (err) | ||
1538 | goto clean_up; | ||
1539 | |||
1540 | prof_obj->session_id = dbg_s->id; | ||
1541 | |||
1542 | if (dbg_s->is_profiler) | ||
1543 | prof_obj->ch = NULL; | ||
1544 | else { | ||
1545 | prof_obj->ch = nvgpu_dbg_gpu_get_session_channel(dbg_s); | ||
1546 | if (prof_obj->ch == NULL) { | ||
1547 | gk20a_err(dev_from_gk20a(g), | ||
1548 | "bind a channel for dbg session"); | ||
1549 | kfree(prof_obj); | ||
1550 | err = -EINVAL; | ||
1551 | goto clean_up; | ||
1552 | } | ||
1553 | } | ||
1554 | |||
1555 | /* Return handle to client */ | ||
1556 | args->profiler_handle = prof_obj->prof_handle; | ||
1557 | |||
1558 | INIT_LIST_HEAD(&prof_obj->prof_obj_entry); | ||
1559 | |||
1560 | list_add(&prof_obj->prof_obj_entry, &g->profiler_objects); | ||
1561 | clean_up: | ||
1562 | nvgpu_mutex_release(&g->dbg_sessions_lock); | ||
1563 | return err; | ||
1564 | } | ||
1565 | |||
1566 | static int nvgpu_ioctl_free_profiler_object( | ||
1567 | struct dbg_session_gk20a *dbg_s, | ||
1568 | struct nvgpu_dbg_gpu_profiler_obj_mgt_args *args) | ||
1569 | { | ||
1570 | int err = 0; | ||
1571 | struct gk20a *g = get_gk20a(dbg_s->dev); | ||
1572 | struct dbg_profiler_object_data *prof_obj, *tmp_obj; | ||
1573 | bool obj_found = false; | ||
1574 | |||
1575 | gk20a_dbg_fn("%s session_id = %d profiler_handle = %x", | ||
1576 | dev_name(dbg_s->dev), dbg_s->id, args->profiler_handle); | ||
1577 | |||
1578 | nvgpu_mutex_acquire(&g->dbg_sessions_lock); | ||
1579 | |||
1580 | /* Remove profiler object from the list, if a match is found */ | ||
1581 | list_for_each_entry_safe(prof_obj, tmp_obj, &g->profiler_objects, | ||
1582 | prof_obj_entry) { | ||
1583 | if (prof_obj->prof_handle == args->profiler_handle) { | ||
1584 | if (prof_obj->session_id != dbg_s->id) { | ||
1585 | gk20a_err(dev_from_gk20a(g), | ||
1586 | "invalid handle %x", | ||
1587 | args->profiler_handle); | ||
1588 | err = -EINVAL; | ||
1589 | break; | ||
1590 | } | ||
1591 | if (prof_obj->has_reservation) { | ||
1592 | if (prof_obj->ch == NULL) | ||
1593 | g->global_profiler_reservation_held = false; | ||
1594 | g->profiler_reservation_count--; | ||
1595 | dbg_s->has_profiler_reservation = false; | ||
1596 | } | ||
1597 | list_del(&prof_obj->prof_obj_entry); | ||
1598 | kfree(prof_obj); | ||
1599 | obj_found = true; | ||
1600 | break; | ||
1601 | } | ||
1602 | } | ||
1603 | if (!obj_found) { | ||
1604 | gk20a_err(dev_from_gk20a(g), "profiler %x not found", | ||
1605 | args->profiler_handle); | ||
1606 | err = -EINVAL; | ||
1607 | } | ||
1608 | |||
1609 | nvgpu_mutex_release(&g->dbg_sessions_lock); | ||
1610 | return err; | ||
1611 | } | ||
1612 | |||
1613 | static struct dbg_profiler_object_data *find_matching_prof_obj( | ||
1614 | struct dbg_session_gk20a *dbg_s, | ||
1615 | u32 profiler_handle) | ||
1616 | { | ||
1617 | struct gk20a *g = dbg_s->g; | ||
1618 | struct dbg_profiler_object_data *prof_obj; | ||
1619 | |||
1620 | list_for_each_entry(prof_obj, &g->profiler_objects, prof_obj_entry) { | ||
1621 | if (prof_obj->prof_handle == profiler_handle) { | ||
1622 | if (prof_obj->session_id != dbg_s->id) { | ||
1623 | gk20a_err(dev_from_gk20a(g), | ||
1624 | "invalid handle %x", | ||
1625 | profiler_handle); | ||
1626 | return NULL; | ||
1627 | } | ||
1628 | return prof_obj; | ||
1629 | } | ||
1630 | } | ||
1631 | return NULL; | ||
1632 | } | ||
1633 | |||
1634 | static int nvgpu_profiler_reserve_acquire(struct dbg_session_gk20a *dbg_s, | ||
1635 | u32 profiler_handle) | ||
1636 | { | ||
1637 | struct gk20a *g = dbg_s->g; | ||
1638 | struct dbg_profiler_object_data *prof_obj, *my_prof_obj; | ||
1639 | int err = 0; | ||
1640 | |||
1641 | gk20a_dbg_fn("%s profiler_handle = %x", dev_name(dbg_s->dev), profiler_handle); | ||
1642 | |||
1643 | if (g->profiler_reservation_count < 0) { | ||
1644 | gk20a_err(dev_from_gk20a(g), "Negative reservation count!"); | ||
1645 | return -EINVAL; | ||
1646 | } | ||
1647 | |||
1648 | nvgpu_mutex_acquire(&g->dbg_sessions_lock); | ||
1649 | |||
1650 | /* Find matching object. */ | ||
1651 | my_prof_obj = find_matching_prof_obj(dbg_s, profiler_handle); | ||
1652 | |||
1653 | if (!my_prof_obj) { | ||
1654 | gk20a_err(dev_from_gk20a(g), "object not found"); | ||
1655 | err = -EINVAL; | ||
1656 | goto exit; | ||
1657 | } | ||
1658 | |||
1659 | /* If we already have the reservation, we're done */ | ||
1660 | if (my_prof_obj->has_reservation) { | ||
1661 | err = 0; | ||
1662 | goto exit; | ||
1663 | } | ||
1664 | |||
1665 | if (my_prof_obj->ch == NULL) { | ||
1666 | /* Global reservations are only allowed if there are no other | ||
1667 | * global or per-context reservations currently held | ||
1668 | */ | ||
1669 | if (g->profiler_reservation_count > 0) { | ||
1670 | gk20a_err(dev_from_gk20a(g), | ||
1671 | "global reserve: have existing reservation"); | ||
1672 | err = -EBUSY; | ||
1673 | goto exit; | ||
1674 | } | ||
1675 | |||
1676 | my_prof_obj->has_reservation = true; | ||
1677 | g->global_profiler_reservation_held = true; | ||
1678 | g->profiler_reservation_count = 1; | ||
1679 | dbg_s->has_profiler_reservation = true; | ||
1680 | } else if (g->global_profiler_reservation_held) { | ||
1681 | /* If there's a global reservation, | ||
1682 | * we can't take a per-context one. | ||
1683 | */ | ||
1684 | gk20a_err(dev_from_gk20a(g), | ||
1685 | "per-ctxt reserve: global reservation in effect"); | ||
1686 | err = -EBUSY; | ||
1687 | goto exit; | ||
1688 | } else if (gk20a_is_channel_marked_as_tsg(my_prof_obj->ch)) { | ||
1689 | /* TSG: check that another channel in the TSG | ||
1690 | * doesn't already have the reservation | ||
1691 | */ | ||
1692 | int my_tsgid = my_prof_obj->ch->tsgid; | ||
1693 | |||
1694 | list_for_each_entry(prof_obj, &g->profiler_objects, | ||
1695 | prof_obj_entry) { | ||
1696 | if (prof_obj->has_reservation && | ||
1697 | (prof_obj->ch->tsgid == my_tsgid)) { | ||
1698 | gk20a_err(dev_from_gk20a(g), | ||
1699 | "per-ctxt reserve (tsg): already reserved"); | ||
1700 | err = -EBUSY; | ||
1701 | goto exit; | ||
1702 | } | ||
1703 | } | ||
1704 | |||
1705 | my_prof_obj->has_reservation = true; | ||
1706 | g->profiler_reservation_count++; | ||
1707 | dbg_s->has_profiler_reservation = true; | ||
1708 | } else { | ||
1709 | /* channel: check that some other profiler object doesn't | ||
1710 | * already have the reservation. | ||
1711 | */ | ||
1712 | struct channel_gk20a *my_ch = my_prof_obj->ch; | ||
1713 | |||
1714 | list_for_each_entry(prof_obj, &g->profiler_objects, | ||
1715 | prof_obj_entry) { | ||
1716 | if (prof_obj->has_reservation && | ||
1717 | (prof_obj->ch == my_ch)) { | ||
1718 | gk20a_err(dev_from_gk20a(g), | ||
1719 | "per-ctxt reserve (ch): already reserved"); | ||
1720 | err = -EBUSY; | ||
1721 | goto exit; | ||
1722 | } | ||
1723 | } | ||
1724 | |||
1725 | my_prof_obj->has_reservation = true; | ||
1726 | g->profiler_reservation_count++; | ||
1727 | dbg_s->has_profiler_reservation = true; | ||
1728 | } | ||
1729 | exit: | ||
1730 | nvgpu_mutex_release(&g->dbg_sessions_lock); | ||
1731 | return err; | ||
1732 | } | ||
1733 | |||
1734 | static int nvgpu_profiler_reserve_release(struct dbg_session_gk20a *dbg_s, | ||
1735 | u32 profiler_handle) | ||
1736 | { | ||
1737 | struct gk20a *g = dbg_s->g; | ||
1738 | struct dbg_profiler_object_data *prof_obj; | ||
1739 | int err = 0; | ||
1740 | |||
1741 | gk20a_dbg_fn("%s profiler_handle = %x", dev_name(dbg_s->dev), profiler_handle); | ||
1742 | |||
1743 | nvgpu_mutex_acquire(&g->dbg_sessions_lock); | ||
1744 | |||
1745 | /* Find matching object. */ | ||
1746 | prof_obj = find_matching_prof_obj(dbg_s, profiler_handle); | ||
1747 | |||
1748 | if (!prof_obj) { | ||
1749 | gk20a_err(dev_from_gk20a(g), "object not found"); | ||
1750 | err = -EINVAL; | ||
1751 | goto exit; | ||
1752 | } | ||
1753 | |||
1754 | if (prof_obj->has_reservation) { | ||
1755 | prof_obj->has_reservation = false; | ||
1756 | if (prof_obj->ch == NULL) | ||
1757 | g->global_profiler_reservation_held = false; | ||
1758 | g->profiler_reservation_count--; | ||
1759 | dbg_s->has_profiler_reservation = false; | ||
1760 | } else { | ||
1761 | gk20a_err(dev_from_gk20a(g), "No reservation found"); | ||
1762 | err = -EINVAL; | ||
1763 | goto exit; | ||
1764 | } | ||
1765 | exit: | ||
1766 | nvgpu_mutex_release(&g->dbg_sessions_lock); | ||
1767 | return err; | ||
1768 | } | ||
1769 | |||
1770 | static int nvgpu_ioctl_profiler_reserve(struct dbg_session_gk20a *dbg_s, | ||
1771 | struct nvgpu_dbg_gpu_profiler_reserve_args *args) | ||
1772 | { | ||
1773 | if (args->acquire) | ||
1774 | return nvgpu_profiler_reserve_acquire(dbg_s, args->profiler_handle); | ||
1775 | |||
1776 | return nvgpu_profiler_reserve_release(dbg_s, args->profiler_handle); | ||
1777 | } | ||
1778 | |||
1443 | static int gk20a_perfbuf_map(struct dbg_session_gk20a *dbg_s, | 1779 | static int gk20a_perfbuf_map(struct dbg_session_gk20a *dbg_s, |
1444 | struct nvgpu_dbg_gpu_perfbuf_map_args *args) | 1780 | struct nvgpu_dbg_gpu_perfbuf_map_args *args) |
1445 | { | 1781 | { |
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h index caa9395b..e8d2dbe5 100644 --- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h | |||
@@ -47,6 +47,9 @@ struct dbg_session_gk20a { | |||
47 | /* profiler session, if any */ | 47 | /* profiler session, if any */ |
48 | bool is_profiler; | 48 | bool is_profiler; |
49 | 49 | ||
50 | /* has a valid profiler reservation */ | ||
51 | bool has_profiler_reservation; | ||
52 | |||
50 | /* power enabled or disabled */ | 53 | /* power enabled or disabled */ |
51 | bool is_pg_disabled; | 54 | bool is_pg_disabled; |
52 | 55 | ||
@@ -90,6 +93,14 @@ struct dbg_session_channel_data { | |||
90 | struct dbg_session_data *session_data; | 93 | struct dbg_session_data *session_data; |
91 | }; | 94 | }; |
92 | 95 | ||
96 | struct dbg_profiler_object_data { | ||
97 | int session_id; | ||
98 | u32 prof_handle; | ||
99 | struct channel_gk20a *ch; | ||
100 | bool has_reservation; | ||
101 | struct list_head prof_obj_entry; | ||
102 | }; | ||
103 | |||
93 | int dbg_unbind_single_channel_gk20a(struct dbg_session_gk20a *dbg_s, | 104 | int dbg_unbind_single_channel_gk20a(struct dbg_session_gk20a *dbg_s, |
94 | struct dbg_session_channel_data *ch_data); | 105 | struct dbg_session_channel_data *ch_data); |
95 | 106 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 5bf1e02d..7c836b3c 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -966,6 +966,11 @@ struct gk20a { | |||
966 | struct nvgpu_dbg_gpu_reg_op *dbg_regops_tmp_buf; | 966 | struct nvgpu_dbg_gpu_reg_op *dbg_regops_tmp_buf; |
967 | u32 dbg_regops_tmp_buf_ops; | 967 | u32 dbg_regops_tmp_buf_ops; |
968 | 968 | ||
969 | /* For profiler reservations */ | ||
970 | struct list_head profiler_objects; | ||
971 | bool global_profiler_reservation_held; | ||
972 | int profiler_reservation_count; | ||
973 | |||
969 | void (*remove_support)(struct device *); | 974 | void (*remove_support)(struct device *); |
970 | 975 | ||
971 | u64 pg_ingating_time_us; | 976 | u64 pg_ingating_time_us; |
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c index a97c179f..2d7417f0 100644 --- a/drivers/gpu/nvgpu/vgpu/vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/vgpu.c | |||
@@ -251,6 +251,8 @@ static int vgpu_init_support(struct platform_device *pdev) | |||
251 | nvgpu_mutex_init(&g->dbg_sessions_lock); | 251 | nvgpu_mutex_init(&g->dbg_sessions_lock); |
252 | nvgpu_mutex_init(&g->client_lock); | 252 | nvgpu_mutex_init(&g->client_lock); |
253 | 253 | ||
254 | INIT_LIST_HEAD(&g->profiler_objects); | ||
255 | |||
254 | g->dbg_regops_tmp_buf = kzalloc(SZ_4K, GFP_KERNEL); | 256 | g->dbg_regops_tmp_buf = kzalloc(SZ_4K, GFP_KERNEL); |
255 | if (!g->dbg_regops_tmp_buf) { | 257 | if (!g->dbg_regops_tmp_buf) { |
256 | dev_err(g->dev, "couldn't allocate regops tmp buf"); | 258 | dev_err(g->dev, "couldn't allocate regops tmp buf"); |