aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2017-10-12 14:57:49 -0400
committerDave Airlie <airlied@redhat.com>2017-10-20 17:23:24 -0400
commit570e86963a511c1b404e81c72d2c42169faf9324 (patch)
tree141fe6301ce5ea32f2acdfc109bff15a5c615fc2 /drivers
parent19f470b2e47ddde4ad51744c2e140b86524b1f5a (diff)
drm: Widen vblank count to 64-bits [v3]
This modifies the datatypes used by the vblank code to provide 64 bits of vblank count. The driver interfaces have been left using 32 bits of vblank count; all of the code necessary to widen that value for the user API was already included to handle devices returning fewer than 32-bits. This will provide the necessary datatypes for the Vulkan API. v2: * Re-write wait_vblank ioctl to ABSOLUTE sequence When an application uses the WAIT_VBLANK ioctl with RELATIVE or NEXTONMISS bits set, the target vblank interval is updated within the kernel. We need to write that target back to the ioctl buffer and update the flags bits so that if the wait is interrupted by a signal, when it is re-started, it will target precisely the same vblank count as before. * Leave driver API with 32-bit vblank count v3: * Rebase on top of Arnd Bergmann's patch which had the switch to ktime_t parts. [airlied: fix conflict with Ville vblank change]. Suggested-by: Michel Dänzer <michel@daenzer.net> Suggested-by: Daniel Vetter <daniel@ffwll.ch> Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> (cherry picked from commit 2affbc16983e4fc90960bc7f70e7615f4228199b)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_vblank.c104
1 files changed, 71 insertions, 33 deletions
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 3af6c20ba03b..c7e5a274f419 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -251,7 +251,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
251 } 251 }
252 252
253 DRM_DEBUG_VBL("updating vblank count on crtc %u:" 253 DRM_DEBUG_VBL("updating vblank count on crtc %u:"
254 " current=%u, diff=%u, hw=%u hw_last=%u\n", 254 " current=%llu, diff=%u, hw=%u hw_last=%u\n",
255 pipe, vblank->count, diff, cur_vblank, vblank->last); 255 pipe, vblank->count, diff, cur_vblank, vblank->last);
256 256
257 if (diff == 0) { 257 if (diff == 0) {
@@ -740,17 +740,31 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
740 * Returns: 740 * Returns:
741 * The software vblank counter. 741 * The software vblank counter.
742 */ 742 */
743u32 drm_crtc_vblank_count(struct drm_crtc *crtc) 743u64 drm_crtc_vblank_count(struct drm_crtc *crtc)
744{ 744{
745 return drm_vblank_count(crtc->dev, drm_crtc_index(crtc)); 745 return drm_vblank_count(crtc->dev, drm_crtc_index(crtc));
746} 746}
747EXPORT_SYMBOL(drm_crtc_vblank_count); 747EXPORT_SYMBOL(drm_crtc_vblank_count);
748 748
749static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, 749/**
750 * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the
751 * system timestamp corresponding to that vblank counter value.
752 * @dev: DRM device
753 * @pipe: index of CRTC whose counter to retrieve
754 * @vblanktime: Pointer to ktime_t to receive the vblank timestamp.
755 *
756 * Fetches the "cooked" vblank count value that represents the number of
757 * vblank events since the system was booted, including lost events due to
758 * modesetting activity. Returns corresponding system timestamp of the time
759 * of the vblank interval that corresponds to the current vblank counter value.
760 *
761 * This is the legacy version of drm_crtc_vblank_count_and_time().
762 */
763static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
750 ktime_t *vblanktime) 764 ktime_t *vblanktime)
751{ 765{
752 struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; 766 struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
753 u32 vblank_count; 767 u64 vblank_count;
754 unsigned int seq; 768 unsigned int seq;
755 769
756 if (WARN_ON(pipe >= dev->num_crtcs)) { 770 if (WARN_ON(pipe >= dev->num_crtcs)) {
@@ -778,7 +792,7 @@ static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
778 * modesetting activity. Returns corresponding system timestamp of the time 792 * modesetting activity. Returns corresponding system timestamp of the time
779 * of the vblank interval that corresponds to the current vblank counter value. 793 * of the vblank interval that corresponds to the current vblank counter value.
780 */ 794 */
781u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, 795u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
782 ktime_t *vblanktime) 796 ktime_t *vblanktime)
783{ 797{
784 return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc), 798 return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc),
@@ -788,7 +802,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
788 802
789static void send_vblank_event(struct drm_device *dev, 803static void send_vblank_event(struct drm_device *dev,
790 struct drm_pending_vblank_event *e, 804 struct drm_pending_vblank_event *e,
791 unsigned long seq, ktime_t now) 805 u64 seq, ktime_t now)
792{ 806{
793 struct timespec64 tv = ktime_to_timespec64(now); 807 struct timespec64 tv = ktime_to_timespec64(now);
794 808
@@ -854,7 +868,7 @@ void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
854 assert_spin_locked(&dev->event_lock); 868 assert_spin_locked(&dev->event_lock);
855 869
856 e->pipe = pipe; 870 e->pipe = pipe;
857 e->event.sequence = drm_crtc_accurate_vblank_count(crtc) + 1; 871 e->sequence = drm_crtc_accurate_vblank_count(crtc) + 1;
858 e->event.crtc_id = crtc->base.id; 872 e->event.crtc_id = crtc->base.id;
859 list_add_tail(&e->base.link, &dev->vblank_event_list); 873 list_add_tail(&e->base.link, &dev->vblank_event_list);
860} 874}
@@ -875,7 +889,8 @@ void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
875 struct drm_pending_vblank_event *e) 889 struct drm_pending_vblank_event *e)
876{ 890{
877 struct drm_device *dev = crtc->dev; 891 struct drm_device *dev = crtc->dev;
878 unsigned int seq, pipe = drm_crtc_index(crtc); 892 u64 seq;
893 unsigned int pipe = drm_crtc_index(crtc);
879 ktime_t now; 894 ktime_t now;
880 895
881 if (dev->num_crtcs > 0) { 896 if (dev->num_crtcs > 0) {
@@ -1088,7 +1103,7 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc)
1088 1103
1089 ktime_t now; 1104 ktime_t now;
1090 unsigned long irqflags; 1105 unsigned long irqflags;
1091 unsigned int seq; 1106 u64 seq;
1092 1107
1093 if (WARN_ON(pipe >= dev->num_crtcs)) 1108 if (WARN_ON(pipe >= dev->num_crtcs))
1094 return; 1109 return;
@@ -1123,8 +1138,8 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc)
1123 if (e->pipe != pipe) 1138 if (e->pipe != pipe)
1124 continue; 1139 continue;
1125 DRM_DEBUG("Sending premature vblank event on disable: " 1140 DRM_DEBUG("Sending premature vblank event on disable: "
1126 "wanted %u, current %u\n", 1141 "wanted %llu, current %llu\n",
1127 e->event.sequence, seq); 1142 e->sequence, seq);
1128 list_del(&e->base.link); 1143 list_del(&e->base.link);
1129 drm_vblank_put(dev, pipe); 1144 drm_vblank_put(dev, pipe);
1130 send_vblank_event(dev, e, seq, now); 1145 send_vblank_event(dev, e, seq, now);
@@ -1296,12 +1311,13 @@ int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data,
1296 return 0; 1311 return 0;
1297} 1312}
1298 1313
1299static inline bool vblank_passed(u32 seq, u32 ref) 1314static inline bool vblank_passed(u64 seq, u64 ref)
1300{ 1315{
1301 return (seq - ref) <= (1 << 23); 1316 return (seq - ref) <= (1 << 23);
1302} 1317}
1303 1318
1304static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, 1319static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
1320 u64 req_seq,
1305 union drm_wait_vblank *vblwait, 1321 union drm_wait_vblank *vblwait,
1306 struct drm_file *file_priv) 1322 struct drm_file *file_priv)
1307{ 1323{
@@ -1309,7 +1325,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
1309 struct drm_pending_vblank_event *e; 1325 struct drm_pending_vblank_event *e;
1310 ktime_t now; 1326 ktime_t now;
1311 unsigned long flags; 1327 unsigned long flags;
1312 unsigned int seq; 1328 u64 seq;
1313 int ret; 1329 int ret;
1314 1330
1315 e = kzalloc(sizeof(*e), GFP_KERNEL); 1331 e = kzalloc(sizeof(*e), GFP_KERNEL);
@@ -1344,21 +1360,20 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
1344 1360
1345 seq = drm_vblank_count_and_time(dev, pipe, &now); 1361 seq = drm_vblank_count_and_time(dev, pipe, &now);
1346 1362
1347 DRM_DEBUG("event on vblank count %u, current %u, crtc %u\n", 1363 DRM_DEBUG("event on vblank count %llu, current %llu, crtc %u\n",
1348 vblwait->request.sequence, seq, pipe); 1364 req_seq, seq, pipe);
1349 1365
1350 trace_drm_vblank_event_queued(file_priv, pipe, 1366 trace_drm_vblank_event_queued(file_priv, pipe, req_seq);
1351 vblwait->request.sequence);
1352 1367
1353 e->event.sequence = vblwait->request.sequence; 1368 e->sequence = req_seq;
1354 if (vblank_passed(seq, vblwait->request.sequence)) { 1369 if (vblank_passed(seq, req_seq)) {
1355 drm_vblank_put(dev, pipe); 1370 drm_vblank_put(dev, pipe);
1356 send_vblank_event(dev, e, seq, now); 1371 send_vblank_event(dev, e, seq, now);
1357 vblwait->reply.sequence = seq; 1372 vblwait->reply.sequence = seq;
1358 } else { 1373 } else {
1359 /* drm_handle_vblank_events will call drm_vblank_put */ 1374 /* drm_handle_vblank_events will call drm_vblank_put */
1360 list_add_tail(&e->base.link, &dev->vblank_event_list); 1375 list_add_tail(&e->base.link, &dev->vblank_event_list);
1361 vblwait->reply.sequence = vblwait->request.sequence; 1376 vblwait->reply.sequence = req_seq;
1362 } 1377 }
1363 1378
1364 spin_unlock_irqrestore(&dev->event_lock, flags); 1379 spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -1384,6 +1399,22 @@ static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
1384 _DRM_VBLANK_NEXTONMISS)); 1399 _DRM_VBLANK_NEXTONMISS));
1385} 1400}
1386 1401
1402/*
1403 * Widen a 32-bit param to 64-bits.
1404 *
1405 * \param narrow 32-bit value (missing upper 32 bits)
1406 * \param near 64-bit value that should be 'close' to near
1407 *
1408 * This function returns a 64-bit value using the lower 32-bits from
1409 * 'narrow' and constructing the upper 32-bits so that the result is
1410 * as close as possible to 'near'.
1411 */
1412
1413static u64 widen_32_to_64(u32 narrow, u64 near)
1414{
1415 return near + (s32) (narrow - near);
1416}
1417
1387static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe, 1418static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe,
1388 struct drm_wait_vblank_reply *reply) 1419 struct drm_wait_vblank_reply *reply)
1389{ 1420{
@@ -1407,7 +1438,8 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
1407 struct drm_vblank_crtc *vblank; 1438 struct drm_vblank_crtc *vblank;
1408 union drm_wait_vblank *vblwait = data; 1439 union drm_wait_vblank *vblwait = data;
1409 int ret; 1440 int ret;
1410 unsigned int flags, seq, pipe, high_pipe; 1441 u64 req_seq, seq;
1442 unsigned int flags, pipe, high_pipe;
1411 1443
1412 if (!dev->irq_enabled) 1444 if (!dev->irq_enabled)
1413 return -EINVAL; 1445 return -EINVAL;
@@ -1455,9 +1487,12 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
1455 1487
1456 switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { 1488 switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
1457 case _DRM_VBLANK_RELATIVE: 1489 case _DRM_VBLANK_RELATIVE:
1458 vblwait->request.sequence += seq; 1490 req_seq = seq + vblwait->request.sequence;
1491 vblwait->request.sequence = req_seq;
1459 vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; 1492 vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
1493 break;
1460 case _DRM_VBLANK_ABSOLUTE: 1494 case _DRM_VBLANK_ABSOLUTE:
1495 req_seq = widen_32_to_64(vblwait->request.sequence, seq);
1461 break; 1496 break;
1462 default: 1497 default:
1463 ret = -EINVAL; 1498 ret = -EINVAL;
@@ -1465,22 +1500,25 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
1465 } 1500 }
1466 1501
1467 if ((flags & _DRM_VBLANK_NEXTONMISS) && 1502 if ((flags & _DRM_VBLANK_NEXTONMISS) &&
1468 vblank_passed(seq, vblwait->request.sequence)) 1503 vblank_passed(seq, req_seq)) {
1469 vblwait->request.sequence = seq + 1; 1504 req_seq = seq + 1;
1505 vblwait->request.type &= ~_DRM_VBLANK_NEXTONMISS;
1506 vblwait->request.sequence = req_seq;
1507 }
1470 1508
1471 if (flags & _DRM_VBLANK_EVENT) { 1509 if (flags & _DRM_VBLANK_EVENT) {
1472 /* must hold on to the vblank ref until the event fires 1510 /* must hold on to the vblank ref until the event fires
1473 * drm_vblank_put will be called asynchronously 1511 * drm_vblank_put will be called asynchronously
1474 */ 1512 */
1475 return drm_queue_vblank_event(dev, pipe, vblwait, file_priv); 1513 return drm_queue_vblank_event(dev, pipe, req_seq, vblwait, file_priv);
1476 } 1514 }
1477 1515
1478 if (vblwait->request.sequence != seq) { 1516 if (req_seq != seq) {
1479 DRM_DEBUG("waiting on vblank count %u, crtc %u\n", 1517 DRM_DEBUG("waiting on vblank count %llu, crtc %u\n",
1480 vblwait->request.sequence, pipe); 1518 req_seq, pipe);
1481 DRM_WAIT_ON(ret, vblank->queue, 3 * HZ, 1519 DRM_WAIT_ON(ret, vblank->queue, 3 * HZ,
1482 vblank_passed(drm_vblank_count(dev, pipe), 1520 vblank_passed(drm_vblank_count(dev, pipe),
1483 vblwait->request.sequence) || 1521 req_seq) ||
1484 !READ_ONCE(vblank->enabled)); 1522 !READ_ONCE(vblank->enabled));
1485 } 1523 }
1486 1524
@@ -1502,7 +1540,7 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
1502{ 1540{
1503 struct drm_pending_vblank_event *e, *t; 1541 struct drm_pending_vblank_event *e, *t;
1504 ktime_t now; 1542 ktime_t now;
1505 unsigned int seq; 1543 u64 seq;
1506 1544
1507 assert_spin_locked(&dev->event_lock); 1545 assert_spin_locked(&dev->event_lock);
1508 1546
@@ -1511,11 +1549,11 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
1511 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { 1549 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
1512 if (e->pipe != pipe) 1550 if (e->pipe != pipe)
1513 continue; 1551 continue;
1514 if (!vblank_passed(seq, e->event.sequence)) 1552 if (!vblank_passed(seq, e->sequence))
1515 continue; 1553 continue;
1516 1554
1517 DRM_DEBUG("vblank event on %u, current %u\n", 1555 DRM_DEBUG("vblank event on %llu, current %llu\n",
1518 e->event.sequence, seq); 1556 e->sequence, seq);
1519 1557
1520 list_del(&e->base.link); 1558 list_del(&e->base.link);
1521 drm_vblank_put(dev, pipe); 1559 drm_vblank_put(dev, pipe);