.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. |
---|
3 | 4 | * Copyright (C) 2013 Red Hat |
---|
4 | 5 | * Author: Rob Clark <robdclark@gmail.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms of the GNU General Public License version 2 as published by |
---|
8 | | - * the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | | - * more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License along with |
---|
16 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
---|
17 | 6 | */ |
---|
18 | 7 | |
---|
19 | 8 | #ifndef __MSM_DRV_H__ |
---|
.. | .. |
---|
33 | 22 | #include <linux/types.h> |
---|
34 | 23 | #include <linux/of_graph.h> |
---|
35 | 24 | #include <linux/of_device.h> |
---|
36 | | -#include <asm/sizes.h> |
---|
| 25 | +#include <linux/sizes.h> |
---|
37 | 26 | #include <linux/kthread.h> |
---|
38 | 27 | |
---|
39 | | -#include <drm/drmP.h> |
---|
40 | 28 | #include <drm/drm_atomic.h> |
---|
41 | 29 | #include <drm/drm_atomic_helper.h> |
---|
42 | | -#include <drm/drm_crtc_helper.h> |
---|
43 | 30 | #include <drm/drm_plane_helper.h> |
---|
| 31 | +#include <drm/drm_probe_helper.h> |
---|
44 | 32 | #include <drm/drm_fb_helper.h> |
---|
45 | 33 | #include <drm/msm_drm.h> |
---|
46 | 34 | #include <drm/drm_gem.h> |
---|
.. | .. |
---|
68 | 56 | rwlock_t queuelock; |
---|
69 | 57 | struct list_head submitqueues; |
---|
70 | 58 | int queueid; |
---|
| 59 | + struct msm_gem_address_space *aspace; |
---|
| 60 | + struct kref ref; |
---|
| 61 | + int seqno; |
---|
71 | 62 | }; |
---|
72 | 63 | |
---|
73 | 64 | enum msm_mdp_plane_property { |
---|
.. | .. |
---|
75 | 66 | PLANE_PROP_ALPHA, |
---|
76 | 67 | PLANE_PROP_PREMULTIPLIED, |
---|
77 | 68 | PLANE_PROP_MAX_NUM |
---|
78 | | -}; |
---|
79 | | - |
---|
80 | | -struct msm_vblank_ctrl { |
---|
81 | | - struct kthread_work work; |
---|
82 | | - struct list_head event_list; |
---|
83 | | - spinlock_t lock; |
---|
84 | 69 | }; |
---|
85 | 70 | |
---|
86 | 71 | #define MSM_GPU_MAX_RINGS 4 |
---|
.. | .. |
---|
122 | 107 | u32 num_lm; |
---|
123 | 108 | u32 num_enc; |
---|
124 | 109 | u32 num_intf; |
---|
| 110 | + u32 num_dspp; |
---|
125 | 111 | }; |
---|
126 | 112 | |
---|
127 | 113 | /** |
---|
128 | 114 | * struct msm_display_info - defines display properties |
---|
129 | | - * @intf_type: DRM_MODE_CONNECTOR_ display type |
---|
| 115 | + * @intf_type: DRM_MODE_ENCODER_ type |
---|
130 | 116 | * @capabilities: Bitmask of display flags |
---|
131 | 117 | * @num_of_h_tiles: Number of horizontal tiles in case of split interface |
---|
132 | 118 | * @h_tile_instance: Controller instance used per tile. Number of elements is |
---|
.. | .. |
---|
145 | 131 | /* Commit/Event thread specific structure */ |
---|
146 | 132 | struct msm_drm_thread { |
---|
147 | 133 | struct drm_device *dev; |
---|
148 | | - struct task_struct *thread; |
---|
149 | 134 | unsigned int crtc_id; |
---|
150 | | - struct kthread_worker worker; |
---|
| 135 | + struct kthread_worker *worker; |
---|
151 | 136 | }; |
---|
152 | 137 | |
---|
153 | 138 | struct msm_drm_private { |
---|
.. | .. |
---|
176 | 161 | /* DSI is shared by mdp4 and mdp5 */ |
---|
177 | 162 | struct msm_dsi *dsi[2]; |
---|
178 | 163 | |
---|
| 164 | + struct msm_dp *dp; |
---|
| 165 | + |
---|
179 | 166 | /* when we have more than one 'msm_gpu' these need to be an array: */ |
---|
180 | 167 | struct msm_gpu *gpu; |
---|
181 | 168 | struct msm_file_private *lastctx; |
---|
| 169 | + /* gpu is only set on open(), but we need this info earlier */ |
---|
| 170 | + bool is_a2xx; |
---|
182 | 171 | |
---|
183 | 172 | struct drm_fb_helper *fbdev; |
---|
184 | 173 | |
---|
.. | .. |
---|
189 | 178 | /* list of GEM objects: */ |
---|
190 | 179 | struct list_head inactive_list; |
---|
191 | 180 | |
---|
| 181 | + /* worker for delayed free of objects: */ |
---|
| 182 | + struct work_struct free_work; |
---|
| 183 | + struct llist_head free_list; |
---|
| 184 | + |
---|
192 | 185 | struct workqueue_struct *wq; |
---|
193 | 186 | |
---|
194 | 187 | unsigned int num_planes; |
---|
.. | .. |
---|
197 | 190 | unsigned int num_crtcs; |
---|
198 | 191 | struct drm_crtc *crtcs[MAX_CRTCS]; |
---|
199 | 192 | |
---|
200 | | - struct msm_drm_thread disp_thread[MAX_CRTCS]; |
---|
201 | 193 | struct msm_drm_thread event_thread[MAX_CRTCS]; |
---|
202 | 194 | |
---|
203 | 195 | unsigned int num_encoders; |
---|
.. | .. |
---|
226 | 218 | struct notifier_block vmap_notifier; |
---|
227 | 219 | struct shrinker shrinker; |
---|
228 | 220 | |
---|
229 | | - struct msm_vblank_ctrl vblank_ctrl; |
---|
230 | 221 | struct drm_atomic_state *pm_state; |
---|
231 | 222 | }; |
---|
232 | 223 | |
---|
.. | .. |
---|
234 | 225 | uint32_t pixel_format; |
---|
235 | 226 | }; |
---|
236 | 227 | |
---|
| 228 | +struct msm_pending_timer; |
---|
| 229 | + |
---|
237 | 230 | int msm_atomic_prepare_fb(struct drm_plane *plane, |
---|
238 | 231 | struct drm_plane_state *new_state); |
---|
| 232 | +void msm_atomic_init_pending_timer(struct msm_pending_timer *timer, |
---|
| 233 | + struct msm_kms *kms, int crtc_idx); |
---|
239 | 234 | void msm_atomic_commit_tail(struct drm_atomic_state *state); |
---|
240 | 235 | struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev); |
---|
241 | 236 | void msm_atomic_state_clear(struct drm_atomic_state *state); |
---|
242 | 237 | void msm_atomic_state_free(struct drm_atomic_state *state); |
---|
243 | 238 | |
---|
| 239 | +int msm_crtc_enable_vblank(struct drm_crtc *crtc); |
---|
| 240 | +void msm_crtc_disable_vblank(struct drm_crtc *crtc); |
---|
| 241 | + |
---|
| 242 | +int msm_gem_init_vma(struct msm_gem_address_space *aspace, |
---|
| 243 | + struct msm_gem_vma *vma, int npages, |
---|
| 244 | + u64 range_start, u64 range_end); |
---|
| 245 | +void msm_gem_purge_vma(struct msm_gem_address_space *aspace, |
---|
| 246 | + struct msm_gem_vma *vma); |
---|
244 | 247 | void msm_gem_unmap_vma(struct msm_gem_address_space *aspace, |
---|
245 | | - struct msm_gem_vma *vma, struct sg_table *sgt); |
---|
| 248 | + struct msm_gem_vma *vma); |
---|
246 | 249 | int msm_gem_map_vma(struct msm_gem_address_space *aspace, |
---|
247 | | - struct msm_gem_vma *vma, struct sg_table *sgt, int npages); |
---|
| 250 | + struct msm_gem_vma *vma, int prot, |
---|
| 251 | + struct sg_table *sgt, int npages); |
---|
| 252 | +void msm_gem_close_vma(struct msm_gem_address_space *aspace, |
---|
| 253 | + struct msm_gem_vma *vma); |
---|
| 254 | + |
---|
| 255 | + |
---|
| 256 | +struct msm_gem_address_space * |
---|
| 257 | +msm_gem_address_space_get(struct msm_gem_address_space *aspace); |
---|
248 | 258 | |
---|
249 | 259 | void msm_gem_address_space_put(struct msm_gem_address_space *aspace); |
---|
250 | 260 | |
---|
251 | 261 | struct msm_gem_address_space * |
---|
252 | | -msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, |
---|
253 | | - const char *name); |
---|
| 262 | +msm_gem_address_space_create(struct msm_mmu *mmu, const char *name, |
---|
| 263 | + u64 va_start, u64 size); |
---|
254 | 264 | |
---|
255 | 265 | int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); |
---|
256 | 266 | void msm_unregister_mmu(struct drm_device *dev, struct msm_mmu *mmu); |
---|
| 267 | + |
---|
| 268 | +bool msm_use_mmu(struct drm_device *dev); |
---|
257 | 269 | |
---|
258 | 270 | void msm_gem_submit_free(struct msm_gem_submit *submit); |
---|
259 | 271 | int msm_ioctl_gem_submit(struct drm_device *dev, void *data, |
---|
.. | .. |
---|
269 | 281 | uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj); |
---|
270 | 282 | int msm_gem_get_iova(struct drm_gem_object *obj, |
---|
271 | 283 | struct msm_gem_address_space *aspace, uint64_t *iova); |
---|
| 284 | +int msm_gem_get_and_pin_iova_range(struct drm_gem_object *obj, |
---|
| 285 | + struct msm_gem_address_space *aspace, uint64_t *iova, |
---|
| 286 | + u64 range_start, u64 range_end); |
---|
| 287 | +int msm_gem_get_and_pin_iova(struct drm_gem_object *obj, |
---|
| 288 | + struct msm_gem_address_space *aspace, uint64_t *iova); |
---|
272 | 289 | uint64_t msm_gem_iova(struct drm_gem_object *obj, |
---|
| 290 | + struct msm_gem_address_space *aspace); |
---|
| 291 | +void msm_gem_unpin_iova(struct drm_gem_object *obj, |
---|
273 | 292 | struct msm_gem_address_space *aspace); |
---|
274 | 293 | struct page **msm_gem_get_pages(struct drm_gem_object *obj); |
---|
275 | 294 | void msm_gem_put_pages(struct drm_gem_object *obj); |
---|
276 | | -void msm_gem_put_iova(struct drm_gem_object *obj, |
---|
277 | | - struct msm_gem_address_space *aspace); |
---|
278 | 295 | int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev, |
---|
279 | 296 | struct drm_mode_create_dumb *args); |
---|
280 | 297 | int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, |
---|
.. | .. |
---|
283 | 300 | void *msm_gem_prime_vmap(struct drm_gem_object *obj); |
---|
284 | 301 | void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); |
---|
285 | 302 | int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); |
---|
286 | | -struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj); |
---|
287 | 303 | struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, |
---|
288 | 304 | struct dma_buf_attachment *attach, struct sg_table *sg); |
---|
289 | 305 | int msm_gem_prime_pin(struct drm_gem_object *obj); |
---|
.. | .. |
---|
294 | 310 | int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv); |
---|
295 | 311 | int msm_gem_sync_object(struct drm_gem_object *obj, |
---|
296 | 312 | struct msm_fence_context *fctx, bool exclusive); |
---|
297 | | -void msm_gem_move_to_active(struct drm_gem_object *obj, |
---|
298 | | - struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence); |
---|
299 | | -void msm_gem_move_to_inactive(struct drm_gem_object *obj); |
---|
| 313 | +void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu); |
---|
| 314 | +void msm_gem_active_put(struct drm_gem_object *obj); |
---|
300 | 315 | int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout); |
---|
301 | 316 | int msm_gem_cpu_fini(struct drm_gem_object *obj); |
---|
302 | 317 | void msm_gem_free_object(struct drm_gem_object *obj); |
---|
303 | 318 | int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, |
---|
304 | | - uint32_t size, uint32_t flags, uint32_t *handle); |
---|
| 319 | + uint32_t size, uint32_t flags, uint32_t *handle, char *name); |
---|
305 | 320 | struct drm_gem_object *msm_gem_new(struct drm_device *dev, |
---|
306 | 321 | uint32_t size, uint32_t flags); |
---|
307 | 322 | struct drm_gem_object *msm_gem_new_locked(struct drm_device *dev, |
---|
.. | .. |
---|
312 | 327 | void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size, |
---|
313 | 328 | uint32_t flags, struct msm_gem_address_space *aspace, |
---|
314 | 329 | struct drm_gem_object **bo, uint64_t *iova); |
---|
| 330 | +void msm_gem_kernel_put(struct drm_gem_object *bo, |
---|
| 331 | + struct msm_gem_address_space *aspace, bool locked); |
---|
315 | 332 | struct drm_gem_object *msm_gem_import(struct drm_device *dev, |
---|
316 | 333 | struct dma_buf *dmabuf, struct sg_table *sgt); |
---|
| 334 | +void msm_gem_free_work(struct work_struct *work); |
---|
| 335 | + |
---|
| 336 | +__printf(2, 3) |
---|
| 337 | +void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...); |
---|
317 | 338 | |
---|
318 | 339 | int msm_framebuffer_prepare(struct drm_framebuffer *fb, |
---|
319 | 340 | struct msm_gem_address_space *aspace); |
---|
.. | .. |
---|
364 | 385 | } |
---|
365 | 386 | #endif |
---|
366 | 387 | |
---|
| 388 | +#ifdef CONFIG_DRM_MSM_DP |
---|
| 389 | +int __init msm_dp_register(void); |
---|
| 390 | +void __exit msm_dp_unregister(void); |
---|
| 391 | +int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, |
---|
| 392 | + struct drm_encoder *encoder); |
---|
| 393 | +int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder); |
---|
| 394 | +int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder); |
---|
| 395 | +int msm_dp_display_pre_disable(struct msm_dp *dp, struct drm_encoder *encoder); |
---|
| 396 | +void msm_dp_display_mode_set(struct msm_dp *dp, struct drm_encoder *encoder, |
---|
| 397 | + struct drm_display_mode *mode, |
---|
| 398 | + struct drm_display_mode *adjusted_mode); |
---|
| 399 | +void msm_dp_irq_postinstall(struct msm_dp *dp_display); |
---|
| 400 | + |
---|
| 401 | +void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor); |
---|
| 402 | + |
---|
| 403 | +#else |
---|
| 404 | +static inline int __init msm_dp_register(void) |
---|
| 405 | +{ |
---|
| 406 | + return -EINVAL; |
---|
| 407 | +} |
---|
| 408 | +static inline void __exit msm_dp_unregister(void) |
---|
| 409 | +{ |
---|
| 410 | +} |
---|
| 411 | +static inline int msm_dp_modeset_init(struct msm_dp *dp_display, |
---|
| 412 | + struct drm_device *dev, |
---|
| 413 | + struct drm_encoder *encoder) |
---|
| 414 | +{ |
---|
| 415 | + return -EINVAL; |
---|
| 416 | +} |
---|
| 417 | +static inline int msm_dp_display_enable(struct msm_dp *dp, |
---|
| 418 | + struct drm_encoder *encoder) |
---|
| 419 | +{ |
---|
| 420 | + return -EINVAL; |
---|
| 421 | +} |
---|
| 422 | +static inline int msm_dp_display_disable(struct msm_dp *dp, |
---|
| 423 | + struct drm_encoder *encoder) |
---|
| 424 | +{ |
---|
| 425 | + return -EINVAL; |
---|
| 426 | +} |
---|
| 427 | +static inline int msm_dp_display_pre_disable(struct msm_dp *dp, |
---|
| 428 | + struct drm_encoder *encoder) |
---|
| 429 | +{ |
---|
| 430 | + return -EINVAL; |
---|
| 431 | +} |
---|
| 432 | +static inline void msm_dp_display_mode_set(struct msm_dp *dp, |
---|
| 433 | + struct drm_encoder *encoder, |
---|
| 434 | + struct drm_display_mode *mode, |
---|
| 435 | + struct drm_display_mode *adjusted_mode) |
---|
| 436 | +{ |
---|
| 437 | +} |
---|
| 438 | + |
---|
| 439 | +static inline void msm_dp_irq_postinstall(struct msm_dp *dp_display) |
---|
| 440 | +{ |
---|
| 441 | +} |
---|
| 442 | + |
---|
| 443 | +static inline void msm_dp_debugfs_init(struct msm_dp *dp_display, |
---|
| 444 | + struct drm_minor *minor) |
---|
| 445 | +{ |
---|
| 446 | +} |
---|
| 447 | + |
---|
| 448 | +#endif |
---|
| 449 | + |
---|
367 | 450 | void __init msm_mdp_register(void); |
---|
368 | 451 | void __exit msm_mdp_unregister(void); |
---|
369 | 452 | void __init msm_dpu_register(void); |
---|
.. | .. |
---|
376 | 459 | int msm_debugfs_late_init(struct drm_device *dev); |
---|
377 | 460 | int msm_rd_debugfs_init(struct drm_minor *minor); |
---|
378 | 461 | void msm_rd_debugfs_cleanup(struct msm_drm_private *priv); |
---|
| 462 | +__printf(3, 4) |
---|
379 | 463 | void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, |
---|
380 | 464 | const char *fmt, ...); |
---|
381 | 465 | int msm_perf_debugfs_init(struct drm_minor *minor); |
---|
382 | 466 | void msm_perf_debugfs_cleanup(struct msm_drm_private *priv); |
---|
383 | 467 | #else |
---|
384 | 468 | static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } |
---|
385 | | -static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, |
---|
386 | | - const char *fmt, ...) {} |
---|
| 469 | +__printf(3, 4) |
---|
| 470 | +static inline void msm_rd_dump_submit(struct msm_rd_state *rd, |
---|
| 471 | + struct msm_gem_submit *submit, |
---|
| 472 | + const char *fmt, ...) {} |
---|
387 | 473 | static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {} |
---|
388 | 474 | static inline void msm_perf_debugfs_cleanup(struct msm_drm_private *priv) {} |
---|
389 | 475 | #endif |
---|
390 | 476 | |
---|
391 | 477 | struct clk *msm_clk_get(struct platform_device *pdev, const char *name); |
---|
392 | | -int msm_clk_bulk_get(struct device *dev, struct clk_bulk_data **bulk); |
---|
393 | 478 | |
---|
394 | 479 | struct clk *msm_clk_bulk_get_clock(struct clk_bulk_data *bulk, int count, |
---|
395 | 480 | const char *name); |
---|
396 | 481 | void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, |
---|
| 482 | + const char *dbgname); |
---|
| 483 | +void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name, |
---|
397 | 484 | const char *dbgname); |
---|
398 | 485 | void msm_writel(u32 data, void __iomem *addr); |
---|
399 | 486 | u32 msm_readl(const void __iomem *addr); |
---|
.. | .. |
---|
402 | 489 | int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx); |
---|
403 | 490 | struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, |
---|
404 | 491 | u32 id); |
---|
405 | | -int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, |
---|
| 492 | +int msm_submitqueue_create(struct drm_device *drm, |
---|
| 493 | + struct msm_file_private *ctx, |
---|
406 | 494 | u32 prio, u32 flags, u32 *id); |
---|
| 495 | +int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, |
---|
| 496 | + struct drm_msm_submitqueue_query *args); |
---|
407 | 497 | int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id); |
---|
408 | 498 | void msm_submitqueue_close(struct msm_file_private *ctx); |
---|
409 | 499 | |
---|
410 | 500 | void msm_submitqueue_destroy(struct kref *kref); |
---|
411 | 501 | |
---|
| 502 | +static inline void __msm_file_private_destroy(struct kref *kref) |
---|
| 503 | +{ |
---|
| 504 | + struct msm_file_private *ctx = container_of(kref, |
---|
| 505 | + struct msm_file_private, ref); |
---|
| 506 | + |
---|
| 507 | + msm_gem_address_space_put(ctx->aspace); |
---|
| 508 | + kfree(ctx); |
---|
| 509 | +} |
---|
| 510 | + |
---|
| 511 | +static inline void msm_file_private_put(struct msm_file_private *ctx) |
---|
| 512 | +{ |
---|
| 513 | + kref_put(&ctx->ref, __msm_file_private_destroy); |
---|
| 514 | +} |
---|
| 515 | + |
---|
| 516 | +static inline struct msm_file_private *msm_file_private_get( |
---|
| 517 | + struct msm_file_private *ctx) |
---|
| 518 | +{ |
---|
| 519 | + kref_get(&ctx->ref); |
---|
| 520 | + return ctx; |
---|
| 521 | +} |
---|
412 | 522 | |
---|
413 | 523 | #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) |
---|
414 | 524 | #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) |
---|
.. | .. |
---|
434 | 544 | static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) |
---|
435 | 545 | { |
---|
436 | 546 | ktime_t now = ktime_get(); |
---|
437 | | - unsigned long remaining_jiffies; |
---|
| 547 | + s64 remaining_jiffies; |
---|
438 | 548 | |
---|
439 | 549 | if (ktime_compare(*timeout, now) < 0) { |
---|
440 | 550 | remaining_jiffies = 0; |
---|
441 | 551 | } else { |
---|
442 | 552 | ktime_t rem = ktime_sub(*timeout, now); |
---|
443 | | - struct timespec ts = ktime_to_timespec(rem); |
---|
444 | | - remaining_jiffies = timespec_to_jiffies(&ts); |
---|
| 553 | + remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); |
---|
445 | 554 | } |
---|
446 | 555 | |
---|
447 | | - return remaining_jiffies; |
---|
| 556 | + return clamp(remaining_jiffies, 0LL, (s64)INT_MAX); |
---|
448 | 557 | } |
---|
449 | 558 | |
---|
450 | 559 | #endif /* __MSM_DRV_H__ */ |
---|