.. | .. |
---|
36 | 36 | #include "mpp_common.h" |
---|
37 | 37 | #include "mpp_iommu.h" |
---|
38 | 38 | |
---|
39 | | -#define MPP_WAIT_TIMEOUT_DELAY (2000) |
---|
40 | | - |
---|
41 | | -/* Use 'v' as magic number */ |
---|
42 | | -#define MPP_IOC_MAGIC 'v' |
---|
43 | | - |
---|
44 | | -#define MPP_IOC_CFG_V1 _IOW(MPP_IOC_MAGIC, 1, unsigned int) |
---|
45 | | -#define MPP_IOC_CFG_V2 _IOW(MPP_IOC_MAGIC, 2, unsigned int) |
---|
46 | | - |
---|
47 | 39 | /* input parmater structure for version 1 */ |
---|
48 | 40 | struct mpp_msg_v1 { |
---|
49 | 41 | __u32 cmd; |
---|
.. | .. |
---|
59 | 51 | [MPP_DEVICE_VDPU2] = "VDPU2", |
---|
60 | 52 | [MPP_DEVICE_VDPU1_PP] = "VDPU1_PP", |
---|
61 | 53 | [MPP_DEVICE_VDPU2_PP] = "VDPU2_PP", |
---|
| 54 | + [MPP_DEVICE_AV1DEC] = "AV1DEC", |
---|
62 | 55 | [MPP_DEVICE_HEVC_DEC] = "HEVC_DEC", |
---|
63 | 56 | [MPP_DEVICE_RKVDEC] = "RKVDEC", |
---|
64 | 57 | [MPP_DEVICE_AVSPLUS_DEC] = "AVSPLUS_DEC", |
---|
| 58 | + [MPP_DEVICE_RKJPEGD] = "RKJPEGD", |
---|
65 | 59 | [MPP_DEVICE_RKVENC] = "RKVENC", |
---|
66 | 60 | [MPP_DEVICE_VEPU1] = "VEPU1", |
---|
67 | 61 | [MPP_DEVICE_VEPU2] = "VEPU2", |
---|
| 62 | + [MPP_DEVICE_VEPU2_JPEG] = "VEPU2", |
---|
68 | 63 | [MPP_DEVICE_VEPU22] = "VEPU22", |
---|
69 | 64 | [MPP_DEVICE_IEP2] = "IEP2", |
---|
70 | 65 | [MPP_DEVICE_VDPP] = "VDPP", |
---|
.. | .. |
---|
86 | 81 | |
---|
87 | 82 | #endif |
---|
88 | 83 | |
---|
89 | | -static void mpp_free_task(struct kref *ref); |
---|
90 | 84 | static void mpp_attach_workqueue(struct mpp_dev *mpp, |
---|
91 | 85 | struct mpp_taskqueue *queue); |
---|
92 | | - |
---|
93 | | -/* task queue schedule */ |
---|
94 | | -static int |
---|
95 | | -mpp_taskqueue_push_pending(struct mpp_taskqueue *queue, |
---|
96 | | - struct mpp_task *task) |
---|
97 | | -{ |
---|
98 | | - if (!task->session || !task->session->mpp) |
---|
99 | | - return -EINVAL; |
---|
100 | | - |
---|
101 | | - kref_get(&task->ref); |
---|
102 | | - mutex_lock(&queue->pending_lock); |
---|
103 | | - list_add_tail(&task->queue_link, &queue->pending_list); |
---|
104 | | - mutex_unlock(&queue->pending_lock); |
---|
105 | | - |
---|
106 | | - return 0; |
---|
107 | | -} |
---|
108 | 86 | |
---|
109 | 87 | static int |
---|
110 | 88 | mpp_taskqueue_pop_pending(struct mpp_taskqueue *queue, |
---|
.. | .. |
---|
148 | 126 | return flag; |
---|
149 | 127 | } |
---|
150 | 128 | |
---|
151 | | -static int |
---|
152 | | -mpp_taskqueue_pending_to_run(struct mpp_taskqueue *queue, |
---|
153 | | - struct mpp_task *task) |
---|
| 129 | +int mpp_taskqueue_pending_to_run(struct mpp_taskqueue *queue, struct mpp_task *task) |
---|
154 | 130 | { |
---|
155 | 131 | unsigned long flags; |
---|
156 | 132 | |
---|
.. | .. |
---|
230 | 206 | return 0; |
---|
231 | 207 | } |
---|
232 | 208 | |
---|
233 | | -static int mpp_session_clear_pending(struct mpp_session *session) |
---|
| 209 | +static void task_msgs_reset(struct mpp_task_msgs *msgs) |
---|
| 210 | +{ |
---|
| 211 | + list_del_init(&msgs->list); |
---|
| 212 | + |
---|
| 213 | + msgs->flags = 0; |
---|
| 214 | + msgs->req_cnt = 0; |
---|
| 215 | + msgs->set_cnt = 0; |
---|
| 216 | + msgs->poll_cnt = 0; |
---|
| 217 | +} |
---|
| 218 | + |
---|
| 219 | +static void task_msgs_init(struct mpp_task_msgs *msgs, struct mpp_session *session) |
---|
| 220 | +{ |
---|
| 221 | + INIT_LIST_HEAD(&msgs->list); |
---|
| 222 | + |
---|
| 223 | + msgs->session = session; |
---|
| 224 | + msgs->queue = NULL; |
---|
| 225 | + msgs->task = NULL; |
---|
| 226 | + msgs->mpp = NULL; |
---|
| 227 | + |
---|
| 228 | + msgs->ext_fd = -1; |
---|
| 229 | + |
---|
| 230 | + task_msgs_reset(msgs); |
---|
| 231 | +} |
---|
| 232 | + |
---|
| 233 | +static struct mpp_task_msgs *get_task_msgs(struct mpp_session *session) |
---|
| 234 | +{ |
---|
| 235 | + unsigned long flags; |
---|
| 236 | + struct mpp_task_msgs *msgs; |
---|
| 237 | + |
---|
| 238 | + spin_lock_irqsave(&session->lock_msgs, flags); |
---|
| 239 | + msgs = list_first_entry_or_null(&session->list_msgs_idle, |
---|
| 240 | + struct mpp_task_msgs, list_session); |
---|
| 241 | + if (msgs) { |
---|
| 242 | + list_move_tail(&msgs->list_session, &session->list_msgs); |
---|
| 243 | + spin_unlock_irqrestore(&session->lock_msgs, flags); |
---|
| 244 | + |
---|
| 245 | + return msgs; |
---|
| 246 | + } |
---|
| 247 | + spin_unlock_irqrestore(&session->lock_msgs, flags); |
---|
| 248 | + |
---|
| 249 | + msgs = kzalloc(sizeof(*msgs), GFP_KERNEL); |
---|
| 250 | + task_msgs_init(msgs, session); |
---|
| 251 | + INIT_LIST_HEAD(&msgs->list_session); |
---|
| 252 | + |
---|
| 253 | + spin_lock_irqsave(&session->lock_msgs, flags); |
---|
| 254 | + list_move_tail(&msgs->list_session, &session->list_msgs); |
---|
| 255 | + session->msgs_cnt++; |
---|
| 256 | + spin_unlock_irqrestore(&session->lock_msgs, flags); |
---|
| 257 | + |
---|
| 258 | + mpp_debug_func(DEBUG_TASK_INFO, "session %d:%d msgs cnt %d\n", |
---|
| 259 | + session->pid, session->index, session->msgs_cnt); |
---|
| 260 | + |
---|
| 261 | + return msgs; |
---|
| 262 | +} |
---|
| 263 | + |
---|
| 264 | +static void put_task_msgs(struct mpp_task_msgs *msgs) |
---|
| 265 | +{ |
---|
| 266 | + struct mpp_session *session = msgs->session; |
---|
| 267 | + unsigned long flags; |
---|
| 268 | + |
---|
| 269 | + if (!session) { |
---|
| 270 | + pr_err("invalid msgs without session\n"); |
---|
| 271 | + return; |
---|
| 272 | + } |
---|
| 273 | + |
---|
| 274 | + if (msgs->ext_fd >= 0) { |
---|
| 275 | + fdput(msgs->f); |
---|
| 276 | + msgs->ext_fd = -1; |
---|
| 277 | + } |
---|
| 278 | + |
---|
| 279 | + task_msgs_reset(msgs); |
---|
| 280 | + |
---|
| 281 | + spin_lock_irqsave(&session->lock_msgs, flags); |
---|
| 282 | + list_move_tail(&msgs->list_session, &session->list_msgs_idle); |
---|
| 283 | + spin_unlock_irqrestore(&session->lock_msgs, flags); |
---|
| 284 | +} |
---|
| 285 | + |
---|
| 286 | +static void clear_task_msgs(struct mpp_session *session) |
---|
| 287 | +{ |
---|
| 288 | + struct mpp_task_msgs *msgs, *n; |
---|
| 289 | + LIST_HEAD(list_to_free); |
---|
| 290 | + unsigned long flags; |
---|
| 291 | + |
---|
| 292 | + spin_lock_irqsave(&session->lock_msgs, flags); |
---|
| 293 | + |
---|
| 294 | + list_for_each_entry_safe(msgs, n, &session->list_msgs, list_session) |
---|
| 295 | + list_move_tail(&msgs->list_session, &list_to_free); |
---|
| 296 | + |
---|
| 297 | + list_for_each_entry_safe(msgs, n, &session->list_msgs_idle, list_session) |
---|
| 298 | + list_move_tail(&msgs->list_session, &list_to_free); |
---|
| 299 | + |
---|
| 300 | + spin_unlock_irqrestore(&session->lock_msgs, flags); |
---|
| 301 | + |
---|
| 302 | + list_for_each_entry_safe(msgs, n, &list_to_free, list_session) |
---|
| 303 | + kfree(msgs); |
---|
| 304 | +} |
---|
| 305 | + |
---|
| 306 | +static void mpp_session_clear_pending(struct mpp_session *session) |
---|
234 | 307 | { |
---|
235 | 308 | struct mpp_task *task = NULL, *n; |
---|
236 | 309 | |
---|
.. | .. |
---|
245 | 318 | kref_put(&task->ref, mpp_free_task); |
---|
246 | 319 | } |
---|
247 | 320 | mutex_unlock(&session->pending_lock); |
---|
248 | | - |
---|
249 | | - return 0; |
---|
250 | 321 | } |
---|
251 | 322 | |
---|
252 | 323 | void mpp_session_cleanup_detach(struct mpp_taskqueue *queue, struct kthread_work *work) |
---|
.. | .. |
---|
268 | 339 | mutex_unlock(&queue->session_lock); |
---|
269 | 340 | |
---|
270 | 341 | if (task_count) { |
---|
271 | | - mpp_dbg_session("session %d:%d task not finished %d\n", |
---|
272 | | - session->pid, session->index, |
---|
273 | | - atomic_read(&queue->detach_count)); |
---|
| 342 | + mpp_dbg_session("session %d:%d not finished %d task cnt %d\n", |
---|
| 343 | + session->device_type, session->index, |
---|
| 344 | + atomic_read(&queue->detach_count), task_count); |
---|
274 | 345 | |
---|
275 | 346 | mpp_session_clear_pending(session); |
---|
276 | 347 | } else { |
---|
.. | .. |
---|
308 | 379 | |
---|
309 | 380 | atomic_set(&session->task_count, 0); |
---|
310 | 381 | atomic_set(&session->release_request, 0); |
---|
| 382 | + |
---|
| 383 | + INIT_LIST_HEAD(&session->list_msgs); |
---|
| 384 | + INIT_LIST_HEAD(&session->list_msgs_idle); |
---|
| 385 | + spin_lock_init(&session->lock_msgs); |
---|
311 | 386 | |
---|
312 | 387 | mpp_dbg_session("session %p init\n", session); |
---|
313 | 388 | return session; |
---|
.. | .. |
---|
352 | 427 | else |
---|
353 | 428 | pr_err("invalid NULL session deinit function\n"); |
---|
354 | 429 | |
---|
355 | | - mpp_dbg_session("session %p:%d deinit\n", session, session->index); |
---|
| 430 | + clear_task_msgs(session); |
---|
356 | 431 | |
---|
357 | 432 | kfree(session); |
---|
358 | 433 | } |
---|
.. | .. |
---|
429 | 504 | return task; |
---|
430 | 505 | } |
---|
431 | 506 | |
---|
432 | | -static void mpp_free_task(struct kref *ref) |
---|
| 507 | +void mpp_free_task(struct kref *ref) |
---|
433 | 508 | { |
---|
434 | 509 | struct mpp_dev *mpp; |
---|
435 | 510 | struct mpp_session *session; |
---|
.. | .. |
---|
441 | 516 | } |
---|
442 | 517 | session = task->session; |
---|
443 | 518 | |
---|
444 | | - mpp_debug_func(DEBUG_TASK_INFO, |
---|
445 | | - "session %d:%d task %d state 0x%lx abort_request %d\n", |
---|
446 | | - session->device_type, session->index, task->task_index, |
---|
447 | | - task->state, atomic_read(&task->abort_request)); |
---|
448 | | - if (!session->mpp) { |
---|
449 | | - mpp_err("session %p, session->mpp is null.\n", session); |
---|
450 | | - return; |
---|
451 | | - } |
---|
452 | | - mpp = session->mpp; |
---|
| 519 | + mpp_debug_func(DEBUG_TASK_INFO, "task %d:%d free state 0x%lx abort %d\n", |
---|
| 520 | + session->index, task->task_id, task->state, |
---|
| 521 | + atomic_read(&task->abort_request)); |
---|
453 | 522 | |
---|
| 523 | + mpp = mpp_get_task_used_device(task, session); |
---|
454 | 524 | if (mpp->dev_ops->free_task) |
---|
455 | 525 | mpp->dev_ops->free_task(session, task); |
---|
| 526 | + |
---|
456 | 527 | /* Decrease reference count */ |
---|
457 | 528 | atomic_dec(&session->task_count); |
---|
458 | 529 | atomic_dec(&mpp->task_count); |
---|
.. | .. |
---|
466 | 537 | struct mpp_task, |
---|
467 | 538 | timeout_work); |
---|
468 | 539 | |
---|
469 | | - if (!test_bit(TASK_STATE_START, &task->state)) { |
---|
470 | | - mpp_err("task has not start\n"); |
---|
471 | | - schedule_delayed_work(&task->timeout_work, |
---|
472 | | - msecs_to_jiffies(MPP_WORK_TIMEOUT_DELAY)); |
---|
| 540 | + if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { |
---|
| 541 | + mpp_err("task has been handled\n"); |
---|
473 | 542 | return; |
---|
474 | 543 | } |
---|
475 | 544 | |
---|
.. | .. |
---|
479 | 548 | } |
---|
480 | 549 | |
---|
481 | 550 | session = task->session; |
---|
| 551 | + mpp_err("task %d:%d:%d processing time out!\n", session->pid, |
---|
| 552 | + session->index, task->task_id); |
---|
482 | 553 | |
---|
483 | 554 | if (!session->mpp) { |
---|
484 | 555 | mpp_err("session %d:%d, session mpp is null.\n", session->pid, |
---|
485 | 556 | session->index); |
---|
486 | 557 | return; |
---|
487 | 558 | } |
---|
488 | | - mpp = session->mpp; |
---|
489 | | - dev_err(mpp->dev, "session %d:%d task %d state %lx processing time out!\n", |
---|
490 | | - session->device_type, session->index, task->task_index, task->state); |
---|
491 | | - synchronize_hardirq(mpp->irq); |
---|
492 | | - |
---|
493 | | - if (test_and_set_bit(TASK_STATE_HANDLE, &task->state)) { |
---|
494 | | - mpp_err("task has been handled\n"); |
---|
495 | | - return; |
---|
496 | | - } |
---|
497 | 559 | |
---|
498 | 560 | mpp_task_dump_timing(task, ktime_us_delta(ktime_get(), task->on_create)); |
---|
| 561 | + |
---|
| 562 | + mpp = mpp_get_task_used_device(task, session); |
---|
499 | 563 | |
---|
500 | 564 | /* disable core irq */ |
---|
501 | 565 | disable_irq(mpp->irq); |
---|
502 | 566 | /* disable mmu irq */ |
---|
503 | | - mpp_iommu_disable_irq(mpp->iommu_info); |
---|
| 567 | + if (mpp->iommu_info && mpp->iommu_info->got_irq) |
---|
| 568 | + disable_irq(mpp->iommu_info->irq); |
---|
504 | 569 | |
---|
505 | 570 | /* hardware maybe dead, reset it */ |
---|
506 | 571 | mpp_reset_up_read(mpp->reset_group); |
---|
507 | 572 | mpp_dev_reset(mpp); |
---|
508 | 573 | mpp_power_off(mpp); |
---|
509 | 574 | |
---|
| 575 | + mpp_iommu_dev_deactivate(mpp->iommu_info, mpp); |
---|
510 | 576 | set_bit(TASK_STATE_TIMEOUT, &task->state); |
---|
511 | 577 | set_bit(TASK_STATE_DONE, &task->state); |
---|
512 | 578 | /* Wake up the GET thread */ |
---|
.. | .. |
---|
518 | 584 | /* enable core irq */ |
---|
519 | 585 | enable_irq(mpp->irq); |
---|
520 | 586 | /* enable mmu irq */ |
---|
521 | | - mpp_iommu_enable_irq(mpp->iommu_info); |
---|
| 587 | + if (mpp->iommu_info && mpp->iommu_info->got_irq) |
---|
| 588 | + enable_irq(mpp->iommu_info->irq); |
---|
522 | 589 | |
---|
523 | 590 | mpp_taskqueue_trigger_work(mpp); |
---|
524 | 591 | } |
---|
525 | 592 | |
---|
526 | 593 | static int mpp_process_task_default(struct mpp_session *session, |
---|
527 | | - struct mpp_task_msgs *msgs) |
---|
| 594 | + struct mpp_task_msgs *msgs) |
---|
528 | 595 | { |
---|
529 | 596 | struct mpp_task *task = NULL; |
---|
530 | 597 | struct mpp_dev *mpp = session->mpp; |
---|
.. | .. |
---|
532 | 599 | ktime_t on_create; |
---|
533 | 600 | |
---|
534 | 601 | if (unlikely(!mpp)) { |
---|
535 | | - mpp_err("pid %d clinet %d found invalid process function\n", |
---|
| 602 | + mpp_err("pid %d client %d found invalid process function\n", |
---|
536 | 603 | session->pid, session->device_type); |
---|
537 | 604 | return -EINVAL; |
---|
538 | 605 | } |
---|
.. | .. |
---|
555 | 622 | set_bit(TASK_TIMING_CREATE, &task->state); |
---|
556 | 623 | } |
---|
557 | 624 | |
---|
| 625 | + /* ensure current device */ |
---|
| 626 | + mpp = mpp_get_task_used_device(task, session); |
---|
| 627 | + |
---|
558 | 628 | kref_init(&task->ref); |
---|
559 | 629 | init_waitqueue_head(&task->wait); |
---|
560 | 630 | atomic_set(&task->abort_request, 0); |
---|
561 | 631 | task->task_index = atomic_fetch_inc(&mpp->task_index); |
---|
| 632 | + task->task_id = atomic_fetch_inc(&mpp->queue->task_id); |
---|
562 | 633 | INIT_DELAYED_WORK(&task->timeout_work, mpp_task_timeout_work); |
---|
563 | 634 | |
---|
564 | 635 | if (mpp->auto_freq_en && mpp->hw_ops->get_freq) |
---|
565 | 636 | mpp->hw_ops->get_freq(mpp, task); |
---|
| 637 | + |
---|
| 638 | + msgs->queue = mpp->queue; |
---|
| 639 | + msgs->task = task; |
---|
| 640 | + msgs->mpp = mpp; |
---|
566 | 641 | |
---|
567 | 642 | /* |
---|
568 | 643 | * Push task to session should be in front of push task to queue. |
---|
.. | .. |
---|
572 | 647 | */ |
---|
573 | 648 | atomic_inc(&session->task_count); |
---|
574 | 649 | mpp_session_push_pending(session, task); |
---|
575 | | - /* push current task to queue */ |
---|
576 | | - atomic_inc(&mpp->task_count); |
---|
577 | | - mpp_taskqueue_push_pending(mpp->queue, task); |
---|
578 | | - set_bit(TASK_STATE_PENDING, &task->state); |
---|
579 | | - /* trigger current queue to run task */ |
---|
580 | | - mpp_taskqueue_trigger_work(mpp); |
---|
581 | | - kref_put(&task->ref, mpp_free_task); |
---|
582 | | - mpp_debug_func(DEBUG_TASK_INFO, |
---|
583 | | - "session %d:%d task %d state 0x%lx\n", |
---|
584 | | - session->device_type, session->index, |
---|
585 | | - task->task_index, task->state); |
---|
| 650 | + |
---|
586 | 651 | return 0; |
---|
587 | 652 | } |
---|
588 | 653 | |
---|
.. | .. |
---|
662 | 727 | mpp_iommu_down_write(mpp->iommu_info); |
---|
663 | 728 | mpp_reset_down_write(mpp->reset_group); |
---|
664 | 729 | atomic_set(&mpp->reset_request, 0); |
---|
665 | | - rockchip_save_qos(mpp->dev); |
---|
| 730 | + |
---|
666 | 731 | if (mpp->hw_ops->reset) |
---|
667 | 732 | mpp->hw_ops->reset(mpp); |
---|
668 | | - rockchip_restore_qos(mpp->dev); |
---|
669 | 733 | |
---|
670 | 734 | /* Note: if the domain does not change, iommu attach will be return |
---|
671 | 735 | * as an empty operation. Therefore, force to close and then open, |
---|
.. | .. |
---|
714 | 778 | struct mpp_task *task) |
---|
715 | 779 | { |
---|
716 | 780 | int ret; |
---|
717 | | - struct mpp_session *session = task->session; |
---|
718 | 781 | u32 timing_en; |
---|
719 | 782 | |
---|
720 | 783 | mpp_debug_enter(); |
---|
.. | .. |
---|
739 | 802 | mpp_set_grf(mpp->grf_info); |
---|
740 | 803 | } |
---|
741 | 804 | /* |
---|
| 805 | + * Lock the reader locker of the device resource lock here, |
---|
| 806 | + * release at the finish operation |
---|
| 807 | + */ |
---|
| 808 | + mpp_reset_down_read(mpp->reset_group); |
---|
| 809 | + |
---|
| 810 | + /* |
---|
742 | 811 | * for iommu share hardware, should attach to ensure |
---|
743 | 812 | * working in current device |
---|
744 | 813 | */ |
---|
745 | 814 | ret = mpp_iommu_attach(mpp->iommu_info); |
---|
746 | 815 | if (ret) { |
---|
747 | 816 | dev_err(mpp->dev, "mpp_iommu_attach failed\n"); |
---|
| 817 | + mpp_reset_up_read(mpp->reset_group); |
---|
748 | 818 | return -ENODATA; |
---|
749 | 819 | } |
---|
750 | 820 | |
---|
751 | 821 | mpp_power_on(mpp); |
---|
752 | | - mpp_time_record(task); |
---|
753 | | - mpp_debug_func(DEBUG_TASK_INFO, |
---|
754 | | - "%s session %d:%d task=%d state=0x%lx\n", |
---|
755 | | - dev_name(mpp->dev), session->device_type, |
---|
756 | | - session->index, task->task_index, task->state); |
---|
| 822 | + mpp_debug_func(DEBUG_TASK_INFO, "pid %d run %s\n", |
---|
| 823 | + task->session->pid, dev_name(mpp->dev)); |
---|
757 | 824 | |
---|
758 | 825 | if (mpp->auto_freq_en && mpp->hw_ops->set_freq) |
---|
759 | 826 | mpp->hw_ops->set_freq(mpp, task); |
---|
760 | | - /* |
---|
761 | | - * TODO: Lock the reader locker of the device resource lock here, |
---|
762 | | - * release at the finish operation |
---|
763 | | - */ |
---|
764 | | - mpp_reset_down_read(mpp->reset_group); |
---|
765 | 827 | |
---|
| 828 | + mpp_iommu_dev_activate(mpp->iommu_info, mpp); |
---|
766 | 829 | if (mpp->dev_ops->run) |
---|
767 | 830 | mpp->dev_ops->run(mpp, task); |
---|
768 | | - set_bit(TASK_STATE_START, &task->state); |
---|
769 | 831 | |
---|
770 | 832 | mpp_debug_leave(); |
---|
771 | 833 | |
---|
.. | .. |
---|
780 | 842 | |
---|
781 | 843 | mpp_debug_enter(); |
---|
782 | 844 | |
---|
783 | | -get_task: |
---|
| 845 | +again: |
---|
784 | 846 | task = mpp_taskqueue_get_pending_task(queue); |
---|
785 | 847 | if (!task) |
---|
786 | 848 | goto done; |
---|
.. | .. |
---|
788 | 850 | /* if task timeout and aborted, remove it */ |
---|
789 | 851 | if (atomic_read(&task->abort_request) > 0) { |
---|
790 | 852 | mpp_taskqueue_pop_pending(queue, task); |
---|
791 | | - goto get_task; |
---|
| 853 | + goto again; |
---|
792 | 854 | } |
---|
793 | 855 | |
---|
794 | 856 | /* get device for current task */ |
---|
.. | .. |
---|
813 | 875 | */ |
---|
814 | 876 | /* Push a pending task to running queue */ |
---|
815 | 877 | if (task) { |
---|
| 878 | + struct mpp_dev *task_mpp = mpp_get_task_used_device(task, task->session); |
---|
| 879 | + |
---|
| 880 | + atomic_inc(&task_mpp->task_count); |
---|
816 | 881 | mpp_taskqueue_pending_to_run(queue, task); |
---|
817 | 882 | set_bit(TASK_STATE_RUNNING, &task->state); |
---|
818 | | - if (mpp_task_run(mpp, task)) |
---|
819 | | - mpp_taskqueue_pop_running(mpp->queue, task); |
---|
| 883 | + if (mpp_task_run(task_mpp, task)) |
---|
| 884 | + mpp_taskqueue_pop_running(queue, task); |
---|
| 885 | + else |
---|
| 886 | + goto again; |
---|
820 | 887 | } |
---|
821 | 888 | |
---|
822 | 889 | done: |
---|
.. | .. |
---|
824 | 891 | } |
---|
825 | 892 | |
---|
826 | 893 | static int mpp_wait_result_default(struct mpp_session *session, |
---|
827 | | - struct mpp_task_msgs *msgs) |
---|
| 894 | + struct mpp_task_msgs *msgs) |
---|
828 | 895 | { |
---|
829 | 896 | int ret; |
---|
830 | 897 | struct mpp_task *task; |
---|
831 | | - struct mpp_dev *mpp = session->mpp; |
---|
832 | | - |
---|
833 | | - if (unlikely(!mpp)) { |
---|
834 | | - mpp_err("pid %d clinet %d found invalid wait result function\n", |
---|
835 | | - session->pid, session->device_type); |
---|
836 | | - return -EINVAL; |
---|
837 | | - } |
---|
| 898 | + struct mpp_dev *mpp; |
---|
838 | 899 | |
---|
839 | 900 | task = mpp_session_get_pending_task(session); |
---|
840 | 901 | if (!task) { |
---|
.. | .. |
---|
842 | 903 | session->pid, session->index); |
---|
843 | 904 | return -EIO; |
---|
844 | 905 | } |
---|
| 906 | + mpp = mpp_get_task_used_device(task, session); |
---|
845 | 907 | |
---|
846 | | - ret = wait_event_timeout(task->wait, |
---|
847 | | - test_bit(TASK_STATE_DONE, &task->state), |
---|
848 | | - msecs_to_jiffies(MPP_WAIT_TIMEOUT_DELAY)); |
---|
849 | | - if (ret > 0) { |
---|
850 | | - if (mpp->dev_ops->result) |
---|
851 | | - ret = mpp->dev_ops->result(mpp, task, msgs); |
---|
852 | | - } else { |
---|
853 | | - atomic_inc(&task->abort_request); |
---|
854 | | - set_bit(TASK_STATE_ABORT, &task->state); |
---|
855 | | - mpp_err("timeout, pid %d session %d:%d count %d cur_task %d state %lx\n", |
---|
856 | | - session->pid, session->device_type, session->index, |
---|
857 | | - atomic_read(&session->task_count), task->task_index, task->state); |
---|
858 | | - } |
---|
| 908 | + ret = wait_event_interruptible(task->wait, test_bit(TASK_STATE_DONE, &task->state)); |
---|
| 909 | + if (ret == -ERESTARTSYS) |
---|
| 910 | + mpp_err("wait task break by signal\n"); |
---|
859 | 911 | |
---|
860 | | - mpp_debug_func(DEBUG_TASK_INFO, |
---|
861 | | - "session %d:%d task %d state 0x%lx kref_read %d ret %d\n", |
---|
862 | | - session->device_type, |
---|
863 | | - session->index, task->task_index, task->state, |
---|
864 | | - kref_read(&task->ref), ret); |
---|
| 912 | + if (mpp->dev_ops->result) |
---|
| 913 | + ret = mpp->dev_ops->result(mpp, task, msgs); |
---|
| 914 | + mpp_debug_func(DEBUG_TASK_INFO, "wait done session %d:%d count %d task %d state %lx\n", |
---|
| 915 | + session->device_type, session->index, atomic_read(&session->task_count), |
---|
| 916 | + task->task_index, task->state); |
---|
| 917 | + |
---|
865 | 918 | mpp_session_pop_pending(session, task); |
---|
866 | 919 | |
---|
867 | 920 | return ret; |
---|
.. | .. |
---|
896 | 949 | of_node_put(np); |
---|
897 | 950 | if (!pdev) { |
---|
898 | 951 | dev_err(dev, "failed to get mpp service from node\n"); |
---|
899 | | - ret = -ENODEV; |
---|
900 | | - goto err_put_pdev; |
---|
| 952 | + return -ENODEV; |
---|
901 | 953 | } |
---|
902 | 954 | |
---|
903 | | - mpp->pdev_srv = pdev; |
---|
904 | 955 | mpp->srv = platform_get_drvdata(pdev); |
---|
| 956 | + platform_device_put(pdev); |
---|
905 | 957 | if (!mpp->srv) { |
---|
906 | | - dev_err(&pdev->dev, "failed attach service\n"); |
---|
907 | | - ret = -EINVAL; |
---|
908 | | - goto err_put_pdev; |
---|
| 958 | + dev_err(dev, "failed attach service\n"); |
---|
| 959 | + return -EINVAL; |
---|
909 | 960 | } |
---|
910 | 961 | |
---|
911 | 962 | ret = of_property_read_u32(dev->of_node, |
---|
912 | 963 | "rockchip,taskqueue-node", &taskqueue_node); |
---|
913 | 964 | if (ret) { |
---|
914 | 965 | dev_err(dev, "failed to get taskqueue-node\n"); |
---|
915 | | - goto err_put_pdev; |
---|
| 966 | + return ret; |
---|
916 | 967 | } else if (taskqueue_node >= mpp->srv->taskqueue_cnt) { |
---|
917 | 968 | dev_err(dev, "taskqueue-node %d must less than %d\n", |
---|
918 | 969 | taskqueue_node, mpp->srv->taskqueue_cnt); |
---|
919 | | - ret = -ENODEV; |
---|
920 | | - goto err_put_pdev; |
---|
| 970 | + return -ENODEV; |
---|
921 | 971 | } |
---|
922 | 972 | /* set taskqueue according dtsi */ |
---|
923 | 973 | queue = mpp->srv->task_queues[taskqueue_node]; |
---|
924 | 974 | if (!queue) { |
---|
925 | 975 | dev_err(dev, "taskqueue attach to invalid node %d\n", |
---|
926 | 976 | taskqueue_node); |
---|
927 | | - ret = -ENODEV; |
---|
928 | | - goto err_put_pdev; |
---|
| 977 | + return -ENODEV; |
---|
929 | 978 | } |
---|
930 | 979 | mpp_attach_workqueue(mpp, queue); |
---|
931 | 980 | |
---|
.. | .. |
---|
936 | 985 | if (reset_group_node >= mpp->srv->reset_group_cnt) { |
---|
937 | 986 | dev_err(dev, "resetgroup-node %d must less than %d\n", |
---|
938 | 987 | reset_group_node, mpp->srv->reset_group_cnt); |
---|
939 | | - ret = -ENODEV; |
---|
940 | | - goto err_put_pdev; |
---|
| 988 | + return -ENODEV; |
---|
941 | 989 | } else { |
---|
942 | 990 | mpp->reset_group = mpp->srv->reset_groups[reset_group_node]; |
---|
943 | 991 | if (!mpp->reset_group->queue) |
---|
.. | .. |
---|
948 | 996 | } |
---|
949 | 997 | |
---|
950 | 998 | return 0; |
---|
951 | | - |
---|
952 | | -err_put_pdev: |
---|
953 | | - platform_device_put(pdev); |
---|
954 | | - |
---|
955 | | - return ret; |
---|
956 | 999 | } |
---|
957 | 1000 | |
---|
958 | 1001 | struct mpp_taskqueue *mpp_taskqueue_init(struct device *dev) |
---|
.. | .. |
---|
976 | 1019 | |
---|
977 | 1020 | /* default taskqueue has max 16 task capacity */ |
---|
978 | 1021 | queue->task_capacity = MPP_MAX_TASK_CAPACITY; |
---|
979 | | - |
---|
980 | | - mutex_init(&queue->ref_lock); |
---|
981 | | - atomic_set(&queue->runtime_cnt, 0); |
---|
| 1022 | + atomic_set(&queue->reset_request, 0); |
---|
982 | 1023 | atomic_set(&queue->detach_count, 0); |
---|
| 1024 | + atomic_set(&queue->task_id, 0); |
---|
| 1025 | + queue->dev_active_flags = 0; |
---|
983 | 1026 | |
---|
984 | 1027 | return queue; |
---|
985 | 1028 | } |
---|
.. | .. |
---|
987 | 1030 | static void mpp_attach_workqueue(struct mpp_dev *mpp, |
---|
988 | 1031 | struct mpp_taskqueue *queue) |
---|
989 | 1032 | { |
---|
990 | | - mpp->queue = queue; |
---|
| 1033 | + s32 core_id; |
---|
| 1034 | + |
---|
991 | 1035 | INIT_LIST_HEAD(&mpp->queue_link); |
---|
| 1036 | + |
---|
992 | 1037 | mutex_lock(&queue->dev_lock); |
---|
| 1038 | + |
---|
| 1039 | + if (mpp->core_id >= 0) |
---|
| 1040 | + core_id = mpp->core_id; |
---|
| 1041 | + else |
---|
| 1042 | + core_id = queue->core_count; |
---|
| 1043 | + |
---|
| 1044 | + if (core_id < 0 || core_id >= MPP_MAX_CORE_NUM) { |
---|
| 1045 | + dev_err(mpp->dev, "invalid core id %d\n", core_id); |
---|
| 1046 | + goto done; |
---|
| 1047 | + } |
---|
| 1048 | + |
---|
| 1049 | + /* |
---|
| 1050 | + * multi devices with no multicores share one queue, |
---|
| 1051 | + * the core_id is default value 0. |
---|
| 1052 | + */ |
---|
| 1053 | + if (queue->cores[core_id]) { |
---|
| 1054 | + if (queue->cores[core_id] == mpp) |
---|
| 1055 | + goto done; |
---|
| 1056 | + |
---|
| 1057 | + core_id = queue->core_count; |
---|
| 1058 | + } |
---|
| 1059 | + |
---|
| 1060 | + queue->cores[core_id] = mpp; |
---|
| 1061 | + queue->core_count++; |
---|
| 1062 | + |
---|
| 1063 | + set_bit(core_id, &queue->core_idle); |
---|
993 | 1064 | list_add_tail(&mpp->queue_link, &queue->dev_list); |
---|
| 1065 | + if (queue->core_id_max < (u32)core_id) |
---|
| 1066 | + queue->core_id_max = (u32)core_id; |
---|
| 1067 | + |
---|
| 1068 | + mpp->core_id = core_id; |
---|
| 1069 | + mpp->queue = queue; |
---|
| 1070 | + |
---|
| 1071 | + mpp_dbg_core("%s attach queue as core %d\n", |
---|
| 1072 | + dev_name(mpp->dev), mpp->core_id); |
---|
| 1073 | + |
---|
994 | 1074 | if (queue->task_capacity > mpp->task_capacity) |
---|
995 | 1075 | queue->task_capacity = mpp->task_capacity; |
---|
| 1076 | + |
---|
| 1077 | +done: |
---|
996 | 1078 | mutex_unlock(&queue->dev_lock); |
---|
997 | 1079 | } |
---|
998 | 1080 | |
---|
.. | .. |
---|
1002 | 1084 | |
---|
1003 | 1085 | if (queue) { |
---|
1004 | 1086 | mutex_lock(&queue->dev_lock); |
---|
| 1087 | + |
---|
| 1088 | + queue->cores[mpp->core_id] = NULL; |
---|
| 1089 | + queue->core_count--; |
---|
| 1090 | + |
---|
| 1091 | + clear_bit(mpp->core_id, &queue->core_idle); |
---|
1005 | 1092 | list_del_init(&mpp->queue_link); |
---|
| 1093 | + |
---|
| 1094 | + mpp->queue = NULL; |
---|
| 1095 | + |
---|
1006 | 1096 | mutex_unlock(&queue->dev_lock); |
---|
1007 | 1097 | } |
---|
1008 | 1098 | } |
---|
.. | .. |
---|
1018 | 1108 | found = (cmd >= MPP_CMD_CONTROL_BASE && cmd < MPP_CMD_CONTROL_BUTT) ? true : found; |
---|
1019 | 1109 | |
---|
1020 | 1110 | return found ? 0 : -EINVAL; |
---|
1021 | | -} |
---|
1022 | | - |
---|
1023 | | -static int mpp_parse_msg_v1(struct mpp_msg_v1 *msg, |
---|
1024 | | - struct mpp_request *req) |
---|
1025 | | -{ |
---|
1026 | | - int ret = 0; |
---|
1027 | | - |
---|
1028 | | - req->cmd = msg->cmd; |
---|
1029 | | - req->flags = msg->flags; |
---|
1030 | | - req->size = msg->size; |
---|
1031 | | - req->offset = msg->offset; |
---|
1032 | | - req->data = (void __user *)(unsigned long)msg->data_ptr; |
---|
1033 | | - |
---|
1034 | | - mpp_debug(DEBUG_IOCTL, "cmd %x, flags %08x, size %d, offset %x\n", |
---|
1035 | | - req->cmd, req->flags, req->size, req->offset); |
---|
1036 | | - |
---|
1037 | | - ret = mpp_check_cmd_v1(req->cmd); |
---|
1038 | | - if (ret) |
---|
1039 | | - mpp_err("mpp cmd %x is not supproted.\n", req->cmd); |
---|
1040 | | - |
---|
1041 | | - return ret; |
---|
1042 | 1111 | } |
---|
1043 | 1112 | |
---|
1044 | 1113 | static inline int mpp_msg_is_last(struct mpp_request *req) |
---|
.. | .. |
---|
1090 | 1159 | int ret; |
---|
1091 | 1160 | struct mpp_dev *mpp; |
---|
1092 | 1161 | |
---|
1093 | | - mpp_debug(DEBUG_IOCTL, "req->cmd %x\n", req->cmd); |
---|
| 1162 | + mpp_debug(DEBUG_IOCTL, "cmd %x process\n", req->cmd); |
---|
| 1163 | + |
---|
1094 | 1164 | switch (req->cmd) { |
---|
1095 | 1165 | case MPP_CMD_QUERY_HW_SUPPORT: { |
---|
1096 | 1166 | u32 hw_support = srv->hw_support; |
---|
.. | .. |
---|
1116 | 1186 | if (test_bit(client_type, &srv->hw_support)) |
---|
1117 | 1187 | mpp = srv->sub_devices[client_type]; |
---|
1118 | 1188 | } |
---|
| 1189 | + |
---|
1119 | 1190 | if (!mpp) |
---|
1120 | 1191 | return -EINVAL; |
---|
| 1192 | + |
---|
1121 | 1193 | hw_info = mpp->var->hw_info; |
---|
1122 | 1194 | mpp_debug(DEBUG_IOCTL, "hw_id %08x\n", hw_info->hw_id); |
---|
1123 | 1195 | if (put_user(hw_info->hw_id, (u32 __user *)req->data)) |
---|
.. | .. |
---|
1148 | 1220 | mpp = srv->sub_devices[client_type]; |
---|
1149 | 1221 | if (!mpp) |
---|
1150 | 1222 | return -EINVAL; |
---|
| 1223 | + |
---|
1151 | 1224 | session->device_type = (enum MPP_DEVICE_TYPE)client_type; |
---|
1152 | 1225 | session->dma = mpp_dma_session_create(mpp->dev, mpp->session_max_buffers); |
---|
1153 | 1226 | session->mpp = mpp; |
---|
.. | .. |
---|
1169 | 1242 | if (ret) |
---|
1170 | 1243 | return ret; |
---|
1171 | 1244 | } |
---|
| 1245 | + |
---|
1172 | 1246 | mpp_session_attach_workqueue(session, mpp->queue); |
---|
1173 | 1247 | } break; |
---|
1174 | 1248 | case MPP_CMD_INIT_DRIVER_DATA: { |
---|
.. | .. |
---|
1211 | 1285 | case MPP_CMD_POLL_HW_FINISH: { |
---|
1212 | 1286 | msgs->flags |= req->flags; |
---|
1213 | 1287 | msgs->poll_cnt++; |
---|
| 1288 | + msgs->poll_req = NULL; |
---|
| 1289 | + } break; |
---|
| 1290 | + case MPP_CMD_POLL_HW_IRQ: { |
---|
| 1291 | + if (msgs->poll_cnt || msgs->poll_req) |
---|
| 1292 | + mpp_err("Do NOT poll hw irq when previous call not return\n"); |
---|
| 1293 | + |
---|
| 1294 | + msgs->flags |= req->flags; |
---|
| 1295 | + msgs->poll_cnt++; |
---|
| 1296 | + |
---|
| 1297 | + if (req->size && req->data) { |
---|
| 1298 | + if (!msgs->poll_req) |
---|
| 1299 | + msgs->poll_req = req; |
---|
| 1300 | + } else { |
---|
| 1301 | + msgs->poll_req = NULL; |
---|
| 1302 | + } |
---|
1214 | 1303 | } break; |
---|
1215 | 1304 | case MPP_CMD_RESET_SESSION: { |
---|
1216 | 1305 | int ret; |
---|
.. | .. |
---|
1300 | 1389 | default: { |
---|
1301 | 1390 | mpp = session->mpp; |
---|
1302 | 1391 | if (!mpp) { |
---|
1303 | | - mpp_err("pid %d not find clinet %d\n", |
---|
| 1392 | + mpp_err("pid %d not find client %d\n", |
---|
1304 | 1393 | session->pid, session->device_type); |
---|
1305 | 1394 | return -EINVAL; |
---|
1306 | 1395 | } |
---|
.. | .. |
---|
1314 | 1403 | return 0; |
---|
1315 | 1404 | } |
---|
1316 | 1405 | |
---|
1317 | | -static long mpp_dev_ioctl(struct file *filp, |
---|
1318 | | - unsigned int cmd, |
---|
1319 | | - unsigned long arg) |
---|
| 1406 | +static void task_msgs_add(struct mpp_task_msgs *msgs, struct list_head *head) |
---|
1320 | 1407 | { |
---|
| 1408 | + struct mpp_session *session = msgs->session; |
---|
1321 | 1409 | int ret = 0; |
---|
1322 | | - struct mpp_service *srv; |
---|
1323 | | - void __user *msg; |
---|
| 1410 | + |
---|
| 1411 | + /* process each task */ |
---|
| 1412 | + if (msgs->set_cnt) { |
---|
| 1413 | + /* NOTE: update msg_flags for fd over 1024 */ |
---|
| 1414 | + session->msg_flags = msgs->flags; |
---|
| 1415 | + ret = mpp_process_task(session, msgs); |
---|
| 1416 | + } |
---|
| 1417 | + |
---|
| 1418 | + if (!ret) { |
---|
| 1419 | + INIT_LIST_HEAD(&msgs->list); |
---|
| 1420 | + list_add_tail(&msgs->list, head); |
---|
| 1421 | + } else { |
---|
| 1422 | + put_task_msgs(msgs); |
---|
| 1423 | + } |
---|
| 1424 | +} |
---|
| 1425 | + |
---|
| 1426 | +static int mpp_collect_msgs(struct list_head *head, struct mpp_session *session, |
---|
| 1427 | + unsigned int cmd, void __user *msg) |
---|
| 1428 | +{ |
---|
| 1429 | + struct mpp_msg_v1 msg_v1; |
---|
1324 | 1430 | struct mpp_request *req; |
---|
1325 | | - struct mpp_task_msgs task_msgs; |
---|
1326 | | - struct mpp_session *session = |
---|
1327 | | - (struct mpp_session *)filp->private_data; |
---|
| 1431 | + struct mpp_task_msgs *msgs = NULL; |
---|
| 1432 | + int last = 1; |
---|
| 1433 | + int ret; |
---|
| 1434 | + |
---|
| 1435 | + if (cmd != MPP_IOC_CFG_V1) { |
---|
| 1436 | + mpp_err("unknown ioctl cmd %x\n", cmd); |
---|
| 1437 | + return -EINVAL; |
---|
| 1438 | + } |
---|
| 1439 | + |
---|
| 1440 | +next: |
---|
| 1441 | + /* first, parse to fixed struct */ |
---|
| 1442 | + if (copy_from_user(&msg_v1, msg, sizeof(msg_v1))) |
---|
| 1443 | + return -EFAULT; |
---|
| 1444 | + |
---|
| 1445 | + msg += sizeof(msg_v1); |
---|
| 1446 | + |
---|
| 1447 | + mpp_debug(DEBUG_IOCTL, "cmd %x collect flags %08x, size %d, offset %x\n", |
---|
| 1448 | + msg_v1.cmd, msg_v1.flags, msg_v1.size, msg_v1.offset); |
---|
| 1449 | + |
---|
| 1450 | + if (mpp_check_cmd_v1(msg_v1.cmd)) { |
---|
| 1451 | + mpp_err("mpp cmd %x is not supported.\n", msg_v1.cmd); |
---|
| 1452 | + return -EFAULT; |
---|
| 1453 | + } |
---|
| 1454 | + |
---|
| 1455 | + if (msg_v1.flags & MPP_FLAGS_MULTI_MSG) |
---|
| 1456 | + last = (msg_v1.flags & MPP_FLAGS_LAST_MSG) ? 1 : 0; |
---|
| 1457 | + else |
---|
| 1458 | + last = 1; |
---|
| 1459 | + |
---|
| 1460 | + /* check cmd for change msgs session */ |
---|
| 1461 | + if (msg_v1.cmd == MPP_CMD_SET_SESSION_FD) { |
---|
| 1462 | + struct mpp_bat_msg bat_msg; |
---|
| 1463 | + struct mpp_bat_msg __user *usr_cmd; |
---|
| 1464 | + struct fd f; |
---|
| 1465 | + |
---|
| 1466 | + /* try session switch here */ |
---|
| 1467 | + usr_cmd = (struct mpp_bat_msg __user *)(unsigned long)msg_v1.data_ptr; |
---|
| 1468 | + |
---|
| 1469 | + if (copy_from_user(&bat_msg, usr_cmd, sizeof(bat_msg))) |
---|
| 1470 | + return -EFAULT; |
---|
| 1471 | + |
---|
| 1472 | + /* skip finished message */ |
---|
| 1473 | + if (bat_msg.flag & MPP_BAT_MSG_DONE) |
---|
| 1474 | + goto session_switch_done; |
---|
| 1475 | + |
---|
| 1476 | + f = fdget(bat_msg.fd); |
---|
| 1477 | + if (!f.file) { |
---|
| 1478 | + int ret = -EBADF; |
---|
| 1479 | + |
---|
| 1480 | + mpp_err("fd %d get session failed\n", bat_msg.fd); |
---|
| 1481 | + |
---|
| 1482 | + if (copy_to_user(&usr_cmd->ret, &ret, sizeof(usr_cmd->ret))) |
---|
| 1483 | + mpp_err("copy_to_user failed.\n"); |
---|
| 1484 | + goto session_switch_done; |
---|
| 1485 | + } |
---|
| 1486 | + |
---|
| 1487 | + /* NOTE: add previous ready task to queue and drop empty task */ |
---|
| 1488 | + if (msgs) { |
---|
| 1489 | + if (msgs->req_cnt) |
---|
| 1490 | + task_msgs_add(msgs, head); |
---|
| 1491 | + else |
---|
| 1492 | + put_task_msgs(msgs); |
---|
| 1493 | + |
---|
| 1494 | + msgs = NULL; |
---|
| 1495 | + } |
---|
| 1496 | + |
---|
| 1497 | + /* switch session */ |
---|
| 1498 | + session = f.file->private_data; |
---|
| 1499 | + msgs = get_task_msgs(session); |
---|
| 1500 | + |
---|
| 1501 | + if (f.file->private_data == session) |
---|
| 1502 | + msgs->ext_fd = bat_msg.fd; |
---|
| 1503 | + |
---|
| 1504 | + msgs->f = f; |
---|
| 1505 | + |
---|
| 1506 | + mpp_debug(DEBUG_IOCTL, "fd %d, session %d msg_cnt %d\n", |
---|
| 1507 | + bat_msg.fd, session->index, session->msgs_cnt); |
---|
| 1508 | + |
---|
| 1509 | +session_switch_done: |
---|
| 1510 | + /* session id should NOT be the last message */ |
---|
| 1511 | + if (last) |
---|
| 1512 | + return 0; |
---|
| 1513 | + |
---|
| 1514 | + goto next; |
---|
| 1515 | + } |
---|
| 1516 | + |
---|
| 1517 | + if (!msgs) |
---|
| 1518 | + msgs = get_task_msgs(session); |
---|
| 1519 | + |
---|
| 1520 | + if (!msgs) { |
---|
| 1521 | + pr_err("session %d:%d failed to get task msgs", |
---|
| 1522 | + session->pid, session->index); |
---|
| 1523 | + return -EINVAL; |
---|
| 1524 | + } |
---|
| 1525 | + |
---|
| 1526 | + if (msgs->req_cnt >= MPP_MAX_MSG_NUM) { |
---|
| 1527 | + mpp_err("session %d message count %d more than %d.\n", |
---|
| 1528 | + session->index, msgs->req_cnt, MPP_MAX_MSG_NUM); |
---|
| 1529 | + return -EINVAL; |
---|
| 1530 | + } |
---|
| 1531 | + |
---|
| 1532 | + req = &msgs->reqs[msgs->req_cnt++]; |
---|
| 1533 | + req->cmd = msg_v1.cmd; |
---|
| 1534 | + req->flags = msg_v1.flags; |
---|
| 1535 | + req->size = msg_v1.size; |
---|
| 1536 | + req->offset = msg_v1.offset; |
---|
| 1537 | + req->data = (void __user *)(unsigned long)msg_v1.data_ptr; |
---|
| 1538 | + |
---|
| 1539 | + ret = mpp_process_request(session, session->srv, req, msgs); |
---|
| 1540 | + if (ret) { |
---|
| 1541 | + mpp_err("session %d process cmd %x ret %d\n", |
---|
| 1542 | + session->index, req->cmd, ret); |
---|
| 1543 | + return ret; |
---|
| 1544 | + } |
---|
| 1545 | + |
---|
| 1546 | + if (!last) |
---|
| 1547 | + goto next; |
---|
| 1548 | + |
---|
| 1549 | + task_msgs_add(msgs, head); |
---|
| 1550 | + msgs = NULL; |
---|
| 1551 | + |
---|
| 1552 | + return 0; |
---|
| 1553 | +} |
---|
| 1554 | + |
---|
| 1555 | +static void mpp_msgs_trigger(struct list_head *msgs_list) |
---|
| 1556 | +{ |
---|
| 1557 | + struct mpp_task_msgs *msgs, *n; |
---|
| 1558 | + struct mpp_dev *mpp_prev = NULL; |
---|
| 1559 | + struct mpp_taskqueue *queue_prev = NULL; |
---|
| 1560 | + |
---|
| 1561 | + /* push task to queue */ |
---|
| 1562 | + list_for_each_entry_safe(msgs, n, msgs_list, list) { |
---|
| 1563 | + struct mpp_dev *mpp; |
---|
| 1564 | + struct mpp_task *task; |
---|
| 1565 | + struct mpp_taskqueue *queue; |
---|
| 1566 | + |
---|
| 1567 | + if (!msgs->set_cnt || !msgs->queue) |
---|
| 1568 | + continue; |
---|
| 1569 | + |
---|
| 1570 | + mpp = msgs->mpp; |
---|
| 1571 | + task = msgs->task; |
---|
| 1572 | + queue = msgs->queue; |
---|
| 1573 | + |
---|
| 1574 | + if (queue_prev != queue) { |
---|
| 1575 | + if (queue_prev && mpp_prev) { |
---|
| 1576 | + mutex_unlock(&queue_prev->pending_lock); |
---|
| 1577 | + mpp_taskqueue_trigger_work(mpp_prev); |
---|
| 1578 | + } |
---|
| 1579 | + |
---|
| 1580 | + if (queue) |
---|
| 1581 | + mutex_lock(&queue->pending_lock); |
---|
| 1582 | + |
---|
| 1583 | + mpp_prev = mpp; |
---|
| 1584 | + queue_prev = queue; |
---|
| 1585 | + } |
---|
| 1586 | + |
---|
| 1587 | + if (test_bit(TASK_STATE_ABORT, &task->state)) |
---|
| 1588 | + pr_info("try to trigger abort task %d\n", task->task_id); |
---|
| 1589 | + |
---|
| 1590 | + set_bit(TASK_STATE_PENDING, &task->state); |
---|
| 1591 | + list_add_tail(&task->queue_link, &queue->pending_list); |
---|
| 1592 | + } |
---|
| 1593 | + |
---|
| 1594 | + if (mpp_prev && queue_prev) { |
---|
| 1595 | + mutex_unlock(&queue_prev->pending_lock); |
---|
| 1596 | + mpp_taskqueue_trigger_work(mpp_prev); |
---|
| 1597 | + } |
---|
| 1598 | +} |
---|
| 1599 | + |
---|
| 1600 | +static void mpp_msgs_wait(struct list_head *msgs_list) |
---|
| 1601 | +{ |
---|
| 1602 | + struct mpp_task_msgs *msgs, *n; |
---|
| 1603 | + |
---|
| 1604 | + /* poll and release each task */ |
---|
| 1605 | + list_for_each_entry_safe(msgs, n, msgs_list, list) { |
---|
| 1606 | + struct mpp_session *session = msgs->session; |
---|
| 1607 | + |
---|
| 1608 | + if (msgs->poll_cnt) { |
---|
| 1609 | + int ret = mpp_wait_result(session, msgs); |
---|
| 1610 | + |
---|
| 1611 | + if (ret) { |
---|
| 1612 | + mpp_err("session %d wait result ret %d\n", |
---|
| 1613 | + session->index, ret); |
---|
| 1614 | + } |
---|
| 1615 | + } |
---|
| 1616 | + |
---|
| 1617 | + put_task_msgs(msgs); |
---|
| 1618 | + |
---|
| 1619 | + } |
---|
| 1620 | +} |
---|
| 1621 | + |
---|
| 1622 | +static long mpp_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
---|
| 1623 | +{ |
---|
| 1624 | + struct mpp_service *srv; |
---|
| 1625 | + struct mpp_session *session = (struct mpp_session *)filp->private_data; |
---|
| 1626 | + struct list_head msgs_list; |
---|
| 1627 | + int ret = 0; |
---|
1328 | 1628 | |
---|
1329 | 1629 | mpp_debug_enter(); |
---|
1330 | 1630 | |
---|
.. | .. |
---|
1332 | 1632 | mpp_err("session %p\n", session); |
---|
1333 | 1633 | return -EINVAL; |
---|
1334 | 1634 | } |
---|
| 1635 | + |
---|
1335 | 1636 | srv = session->srv; |
---|
| 1637 | + |
---|
1336 | 1638 | if (atomic_read(&session->release_request) > 0) { |
---|
1337 | 1639 | mpp_debug(DEBUG_IOCTL, "release session had request\n"); |
---|
1338 | 1640 | return -EBUSY; |
---|
.. | .. |
---|
1342 | 1644 | return -EBUSY; |
---|
1343 | 1645 | } |
---|
1344 | 1646 | |
---|
1345 | | - msg = (void __user *)arg; |
---|
1346 | | - memset(&task_msgs, 0, sizeof(task_msgs)); |
---|
1347 | | - do { |
---|
1348 | | - req = &task_msgs.reqs[task_msgs.req_cnt]; |
---|
1349 | | - /* first, parse to fixed struct */ |
---|
1350 | | - switch (cmd) { |
---|
1351 | | - case MPP_IOC_CFG_V1: { |
---|
1352 | | - struct mpp_msg_v1 msg_v1; |
---|
| 1647 | + INIT_LIST_HEAD(&msgs_list); |
---|
1353 | 1648 | |
---|
1354 | | - memset(&msg_v1, 0, sizeof(msg_v1)); |
---|
1355 | | - if (copy_from_user(&msg_v1, msg, sizeof(msg_v1))) |
---|
1356 | | - return -EFAULT; |
---|
1357 | | - ret = mpp_parse_msg_v1(&msg_v1, req); |
---|
1358 | | - if (ret) |
---|
1359 | | - return -EFAULT; |
---|
| 1649 | + ret = mpp_collect_msgs(&msgs_list, session, cmd, (void __user *)arg); |
---|
| 1650 | + if (ret) |
---|
| 1651 | + mpp_err("collect msgs failed %d\n", ret); |
---|
1360 | 1652 | |
---|
1361 | | - msg += sizeof(msg_v1); |
---|
1362 | | - } break; |
---|
1363 | | - default: |
---|
1364 | | - mpp_err("unknown ioctl cmd %x\n", cmd); |
---|
1365 | | - return -EINVAL; |
---|
1366 | | - } |
---|
1367 | | - task_msgs.req_cnt++; |
---|
1368 | | - /* check loop times */ |
---|
1369 | | - if (task_msgs.req_cnt > MPP_MAX_MSG_NUM) { |
---|
1370 | | - mpp_err("fail, message count %d more than %d.\n", |
---|
1371 | | - task_msgs.req_cnt, MPP_MAX_MSG_NUM); |
---|
1372 | | - return -EINVAL; |
---|
1373 | | - } |
---|
1374 | | - /* second, process request */ |
---|
1375 | | - ret = mpp_process_request(session, srv, req, &task_msgs); |
---|
1376 | | - if (ret) |
---|
1377 | | - return -EFAULT; |
---|
1378 | | - /* last, process task message */ |
---|
1379 | | - if (mpp_msg_is_last(req)) { |
---|
1380 | | - session->msg_flags = task_msgs.flags; |
---|
1381 | | - if (task_msgs.set_cnt > 0) { |
---|
1382 | | - ret = mpp_process_task(session, &task_msgs); |
---|
1383 | | - if (ret) |
---|
1384 | | - return ret; |
---|
1385 | | - } |
---|
1386 | | - if (task_msgs.poll_cnt > 0) { |
---|
1387 | | - ret = mpp_wait_result(session, &task_msgs); |
---|
1388 | | - if (ret) |
---|
1389 | | - return ret; |
---|
1390 | | - } |
---|
1391 | | - } |
---|
1392 | | - } while (!mpp_msg_is_last(req)); |
---|
| 1653 | + mpp_msgs_trigger(&msgs_list); |
---|
| 1654 | + |
---|
| 1655 | + mpp_msgs_wait(&msgs_list); |
---|
1393 | 1656 | |
---|
1394 | 1657 | mpp_debug_leave(); |
---|
1395 | 1658 | |
---|
.. | .. |
---|
1493 | 1756 | mpp_iommu_down_read(mpp->iommu_info); |
---|
1494 | 1757 | buffer = mpp_dma_import_fd(mpp->iommu_info, dma, fd); |
---|
1495 | 1758 | mpp_iommu_up_read(mpp->iommu_info); |
---|
1496 | | - if (IS_ERR_OR_NULL(buffer)) { |
---|
| 1759 | + if (IS_ERR(buffer)) { |
---|
1497 | 1760 | mpp_err("can't import dma-buf %d\n", fd); |
---|
1498 | | - return ERR_PTR(-ENOMEM); |
---|
| 1761 | + return ERR_CAST(buffer); |
---|
1499 | 1762 | } |
---|
1500 | 1763 | |
---|
1501 | 1764 | mem_region->hdl = buffer; |
---|
.. | .. |
---|
1525 | 1788 | cnt = session->trans_count; |
---|
1526 | 1789 | tbl = session->trans_table; |
---|
1527 | 1790 | } else { |
---|
1528 | | - struct mpp_dev *mpp = session->mpp; |
---|
| 1791 | + struct mpp_dev *mpp = mpp_get_task_used_device(task, session); |
---|
1529 | 1792 | struct mpp_trans_info *trans_info = mpp->var->trans_info; |
---|
1530 | 1793 | |
---|
1531 | 1794 | cnt = trans_info[fmt].count; |
---|
.. | .. |
---|
1661 | 1924 | return 0; |
---|
1662 | 1925 | } |
---|
1663 | 1926 | |
---|
1664 | | -int mpp_task_init(struct mpp_session *session, |
---|
1665 | | - struct mpp_task *task) |
---|
| 1927 | +int mpp_task_init(struct mpp_session *session, struct mpp_task *task) |
---|
1666 | 1928 | { |
---|
1667 | 1929 | INIT_LIST_HEAD(&task->pending_link); |
---|
1668 | 1930 | INIT_LIST_HEAD(&task->queue_link); |
---|
.. | .. |
---|
1677 | 1939 | int mpp_task_finish(struct mpp_session *session, |
---|
1678 | 1940 | struct mpp_task *task) |
---|
1679 | 1941 | { |
---|
1680 | | - struct mpp_dev *mpp = session->mpp; |
---|
| 1942 | + struct mpp_dev *mpp = mpp_get_task_used_device(task, session); |
---|
1681 | 1943 | |
---|
1682 | 1944 | if (mpp->dev_ops->finish) |
---|
1683 | 1945 | mpp->dev_ops->finish(mpp, task); |
---|
.. | .. |
---|
1713 | 1975 | struct mpp_task *task) |
---|
1714 | 1976 | { |
---|
1715 | 1977 | struct mpp_mem_region *mem_region = NULL, *n; |
---|
1716 | | - struct mpp_dev *mpp = session->mpp; |
---|
| 1978 | + struct mpp_dev *mpp = mpp_get_task_used_device(task, session); |
---|
1717 | 1979 | |
---|
1718 | 1980 | /* release memory region attach to this registers table. */ |
---|
1719 | 1981 | list_for_each_entry_safe(mem_region, n, |
---|
.. | .. |
---|
1738 | 2000 | if (!task) |
---|
1739 | 2001 | return -EIO; |
---|
1740 | 2002 | |
---|
1741 | | - mpp_err("--- dump mem region ---\n"); |
---|
| 2003 | + mpp_err("--- dump task %d mem region ---\n", task->task_index); |
---|
1742 | 2004 | if (!list_empty(&task->mem_region_list)) { |
---|
1743 | 2005 | list_for_each_entry_safe(mem, n, |
---|
1744 | 2006 | &task->mem_region_list, |
---|
.. | .. |
---|
1778 | 2040 | return 0; |
---|
1779 | 2041 | } |
---|
1780 | 2042 | |
---|
1781 | | -int mpp_task_dump_hw_reg(struct mpp_dev *mpp, struct mpp_task *task) |
---|
| 2043 | +int mpp_task_dump_hw_reg(struct mpp_dev *mpp) |
---|
1782 | 2044 | { |
---|
1783 | | - if (!task) |
---|
1784 | | - return -EIO; |
---|
| 2045 | + u32 i; |
---|
| 2046 | + u32 s = mpp->var->hw_info->reg_start; |
---|
| 2047 | + u32 e = mpp->var->hw_info->reg_end; |
---|
1785 | 2048 | |
---|
1786 | | - if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) { |
---|
1787 | | - u32 i; |
---|
1788 | | - u32 s = task->hw_info->reg_start; |
---|
1789 | | - u32 e = task->hw_info->reg_end; |
---|
| 2049 | + mpp_err("--- dump hardware register ---\n"); |
---|
| 2050 | + for (i = s; i <= e; i++) { |
---|
| 2051 | + u32 reg = i * sizeof(u32); |
---|
1790 | 2052 | |
---|
1791 | | - mpp_err("--- dump hardware register ---\n"); |
---|
1792 | | - for (i = s; i <= e; i++) { |
---|
1793 | | - u32 reg = i * sizeof(u32); |
---|
1794 | | - |
---|
1795 | | - mpp_err("reg[%03d]: %04x: 0x%08x\n", |
---|
| 2053 | + mpp_err("reg[%03d]: %04x: 0x%08x\n", |
---|
1796 | 2054 | i, reg, readl_relaxed(mpp->reg_base + reg)); |
---|
1797 | | - } |
---|
1798 | 2055 | } |
---|
1799 | 2056 | |
---|
1800 | 2057 | return 0; |
---|
1801 | 2058 | } |
---|
1802 | 2059 | |
---|
1803 | | -static int mpp_iommu_handle(struct iommu_domain *iommu, |
---|
1804 | | - struct device *iommu_dev, |
---|
1805 | | - unsigned long iova, |
---|
1806 | | - int status, void *arg) |
---|
| 2060 | +void mpp_reg_show(struct mpp_dev *mpp, u32 offset) |
---|
1807 | 2061 | { |
---|
1808 | | - struct mpp_dev *mpp = (struct mpp_dev *)arg; |
---|
1809 | | - struct mpp_taskqueue *queue = mpp->queue; |
---|
1810 | | - struct mpp_task *task = mpp_taskqueue_get_running_task(queue); |
---|
| 2062 | + if (!mpp) |
---|
| 2063 | + return; |
---|
1811 | 2064 | |
---|
1812 | | - /* |
---|
1813 | | - * NOTE: In link mode, this task may not be the task of the current |
---|
1814 | | - * hardware processing error |
---|
1815 | | - */ |
---|
1816 | | - if (!task || !task->session) |
---|
1817 | | - return -EIO; |
---|
1818 | | - /* get mpp from cur task */ |
---|
1819 | | - mpp = task->session->mpp; |
---|
1820 | | - dev_err(mpp->dev, "fault addr 0x%08lx status %x\n", iova, status); |
---|
| 2065 | + dev_err(mpp->dev, "reg[%03d]: %04x: 0x%08x\n", |
---|
| 2066 | + offset >> 2, offset, mpp_read_relaxed(mpp, offset)); |
---|
| 2067 | +} |
---|
1821 | 2068 | |
---|
1822 | | - mpp_task_dump_mem_region(mpp, task); |
---|
1823 | | - mpp_task_dump_hw_reg(mpp, task); |
---|
| 2069 | +void mpp_reg_show_range(struct mpp_dev *mpp, u32 start, u32 end) |
---|
| 2070 | +{ |
---|
| 2071 | + u32 offset; |
---|
1824 | 2072 | |
---|
1825 | | - if (mpp->iommu_info->hdl) |
---|
1826 | | - mpp->iommu_info->hdl(iommu, iommu_dev, iova, status, mpp); |
---|
| 2073 | + if (!mpp) |
---|
| 2074 | + return; |
---|
1827 | 2075 | |
---|
1828 | | - return 0; |
---|
| 2076 | + for (offset = start; offset < end; offset += sizeof(u32)) |
---|
| 2077 | + mpp_reg_show(mpp, offset); |
---|
1829 | 2078 | } |
---|
1830 | 2079 | |
---|
1831 | 2080 | /* The device will do more probing work after this */ |
---|
.. | .. |
---|
1843 | 2092 | /* read flag for pum idle request */ |
---|
1844 | 2093 | mpp->skip_idle = device_property_read_bool(dev, "rockchip,skip-pmu-idle-request"); |
---|
1845 | 2094 | |
---|
| 2095 | + /* read link table capacity */ |
---|
| 2096 | + ret = of_property_read_u32(np, "rockchip,task-capacity", |
---|
| 2097 | + &mpp->task_capacity); |
---|
| 2098 | + if (ret) |
---|
| 2099 | + mpp->task_capacity = 1; |
---|
| 2100 | + |
---|
| 2101 | + mpp->dev = dev; |
---|
| 2102 | + mpp->hw_ops = mpp->var->hw_ops; |
---|
| 2103 | + mpp->dev_ops = mpp->var->dev_ops; |
---|
| 2104 | + |
---|
1846 | 2105 | /* Get and attach to service */ |
---|
1847 | 2106 | ret = mpp_attach_service(mpp, dev); |
---|
1848 | 2107 | if (ret) { |
---|
.. | .. |
---|
1850 | 2109 | return -ENODEV; |
---|
1851 | 2110 | } |
---|
1852 | 2111 | |
---|
1853 | | - mpp->dev = dev; |
---|
1854 | | - mpp->hw_ops = mpp->var->hw_ops; |
---|
1855 | | - mpp->dev_ops = mpp->var->dev_ops; |
---|
1856 | | - |
---|
1857 | | - /* read link table capacity */ |
---|
1858 | | - ret = of_property_read_u32(np, "rockchip,task-capacity", |
---|
1859 | | - &mpp->task_capacity); |
---|
1860 | | - if (ret) { |
---|
1861 | | - mpp->task_capacity = 1; |
---|
1862 | | - |
---|
1863 | | - /* power domain autosuspend delay 2s */ |
---|
1864 | | - pm_runtime_set_autosuspend_delay(dev, 2000); |
---|
1865 | | - pm_runtime_use_autosuspend(dev); |
---|
1866 | | - } else { |
---|
1867 | | - dev_info(dev, "%d task capacity link mode detected\n", |
---|
1868 | | - mpp->task_capacity); |
---|
1869 | | - /* do not setup autosuspend on multi task device */ |
---|
1870 | | - } |
---|
| 2112 | + /* power domain autosuspend delay 2s */ |
---|
| 2113 | + pm_runtime_set_autosuspend_delay(dev, 2000); |
---|
| 2114 | + pm_runtime_use_autosuspend(dev); |
---|
1871 | 2115 | |
---|
1872 | 2116 | kthread_init_work(&mpp->work, mpp_task_worker_default); |
---|
1873 | 2117 | |
---|
.. | .. |
---|
1878 | 2122 | |
---|
1879 | 2123 | device_init_wakeup(dev, true); |
---|
1880 | 2124 | pm_runtime_enable(dev); |
---|
1881 | | - |
---|
1882 | 2125 | mpp->irq = platform_get_irq(pdev, 0); |
---|
1883 | 2126 | if (mpp->irq < 0) { |
---|
1884 | 2127 | dev_err(dev, "No interrupt resource found\n"); |
---|
.. | .. |
---|
1905 | 2148 | ret = -ENOMEM; |
---|
1906 | 2149 | goto failed; |
---|
1907 | 2150 | } |
---|
| 2151 | + mpp->io_base = res->start; |
---|
1908 | 2152 | |
---|
1909 | | - pm_runtime_get_sync(dev); |
---|
1910 | 2153 | /* |
---|
1911 | 2154 | * TODO: here or at the device itself, some device does not |
---|
1912 | 2155 | * have the iommu, maybe in the device is better. |
---|
1913 | 2156 | */ |
---|
1914 | 2157 | mpp->iommu_info = mpp_iommu_probe(dev); |
---|
1915 | 2158 | if (IS_ERR(mpp->iommu_info)) { |
---|
1916 | | - dev_err(dev, "failed to attach iommu: %ld\n", |
---|
1917 | | - PTR_ERR(mpp->iommu_info)); |
---|
| 2159 | + dev_err(dev, "failed to attach iommu\n"); |
---|
| 2160 | + mpp->iommu_info = NULL; |
---|
1918 | 2161 | } |
---|
1919 | 2162 | if (mpp->hw_ops->init) { |
---|
1920 | 2163 | ret = mpp->hw_ops->init(mpp); |
---|
1921 | 2164 | if (ret) |
---|
1922 | | - goto failed_init; |
---|
| 2165 | + goto failed; |
---|
1923 | 2166 | } |
---|
1924 | | - /* set iommu fault handler */ |
---|
1925 | | - if (!IS_ERR(mpp->iommu_info)) |
---|
1926 | | - iommu_set_fault_handler(mpp->iommu_info->domain, |
---|
1927 | | - mpp_iommu_handle, mpp); |
---|
1928 | 2167 | |
---|
1929 | 2168 | /* read hardware id */ |
---|
1930 | 2169 | if (hw_info->reg_id >= 0) { |
---|
| 2170 | + pm_runtime_get_sync(dev); |
---|
1931 | 2171 | if (mpp->hw_ops->clk_on) |
---|
1932 | 2172 | mpp->hw_ops->clk_on(mpp); |
---|
1933 | 2173 | |
---|
1934 | 2174 | hw_info->hw_id = mpp_read(mpp, hw_info->reg_id * sizeof(u32)); |
---|
1935 | 2175 | if (mpp->hw_ops->clk_off) |
---|
1936 | 2176 | mpp->hw_ops->clk_off(mpp); |
---|
| 2177 | + pm_runtime_put_sync(dev); |
---|
1937 | 2178 | } |
---|
1938 | 2179 | |
---|
1939 | | - pm_runtime_put_sync(dev); |
---|
1940 | | - |
---|
1941 | 2180 | return ret; |
---|
1942 | | -failed_init: |
---|
1943 | | - pm_runtime_put_sync(dev); |
---|
1944 | 2181 | failed: |
---|
1945 | 2182 | mpp_detach_workqueue(mpp); |
---|
1946 | 2183 | device_init_wakeup(dev, false); |
---|
.. | .. |
---|
1955 | 2192 | mpp->hw_ops->exit(mpp); |
---|
1956 | 2193 | |
---|
1957 | 2194 | mpp_iommu_remove(mpp->iommu_info); |
---|
1958 | | - platform_device_put(mpp->pdev_srv); |
---|
1959 | 2195 | mpp_detach_workqueue(mpp); |
---|
1960 | 2196 | device_init_wakeup(mpp->dev, false); |
---|
1961 | 2197 | pm_runtime_disable(mpp->dev); |
---|
1962 | 2198 | |
---|
1963 | 2199 | return 0; |
---|
| 2200 | +} |
---|
| 2201 | + |
---|
| 2202 | +void mpp_dev_shutdown(struct platform_device *pdev) |
---|
| 2203 | +{ |
---|
| 2204 | + int ret; |
---|
| 2205 | + int val; |
---|
| 2206 | + struct device *dev = &pdev->dev; |
---|
| 2207 | + struct mpp_dev *mpp = dev_get_drvdata(dev); |
---|
| 2208 | + |
---|
| 2209 | + dev_info(dev, "shutdown device\n"); |
---|
| 2210 | + |
---|
| 2211 | + atomic_inc(&mpp->srv->shutdown_request); |
---|
| 2212 | + ret = readx_poll_timeout(atomic_read, |
---|
| 2213 | + &mpp->task_count, |
---|
| 2214 | + val, val == 0, 20000, 200000); |
---|
| 2215 | + if (ret == -ETIMEDOUT) |
---|
| 2216 | + dev_err(dev, "wait total %d running time out\n", |
---|
| 2217 | + atomic_read(&mpp->task_count)); |
---|
| 2218 | + else |
---|
| 2219 | + dev_info(dev, "shutdown success\n"); |
---|
1964 | 2220 | } |
---|
1965 | 2221 | |
---|
1966 | 2222 | int mpp_dev_register_srv(struct mpp_dev *mpp, struct mpp_service *srv) |
---|
.. | .. |
---|
1989 | 2245 | irq_ret = mpp->dev_ops->irq(mpp); |
---|
1990 | 2246 | |
---|
1991 | 2247 | if (task) { |
---|
1992 | | - if (irq_ret != IRQ_NONE) { |
---|
| 2248 | + if (irq_ret == IRQ_WAKE_THREAD) { |
---|
1993 | 2249 | /* if wait or delayed work timeout, abort request will turn on, |
---|
1994 | 2250 | * isr should not to response, and handle it in delayed work |
---|
1995 | 2251 | */ |
---|
.. | .. |
---|
2007 | 2263 | /* normal condition, set state and wake up isr thread */ |
---|
2008 | 2264 | set_bit(TASK_STATE_IRQ, &task->state); |
---|
2009 | 2265 | } |
---|
| 2266 | + |
---|
| 2267 | + if (irq_ret == IRQ_WAKE_THREAD) |
---|
| 2268 | + mpp_iommu_dev_deactivate(mpp->iommu_info, mpp); |
---|
2010 | 2269 | } else { |
---|
2011 | 2270 | mpp_debug(DEBUG_IRQ_CHECK, "error, task is null\n"); |
---|
2012 | 2271 | } |
---|
.. | .. |
---|
2083 | 2342 | |
---|
2084 | 2343 | int mpp_time_part_diff(struct mpp_task *task) |
---|
2085 | 2344 | { |
---|
2086 | | - ktime_t end; |
---|
2087 | | - struct mpp_dev *mpp = task->session->mpp; |
---|
| 2345 | + if (mpp_debug_unlikely(DEBUG_TIMING)) { |
---|
| 2346 | + ktime_t end; |
---|
| 2347 | + struct mpp_dev *mpp = mpp_get_task_used_device(task, task->session); |
---|
2088 | 2348 | |
---|
2089 | | - end = ktime_get(); |
---|
2090 | | - mpp_debug(DEBUG_PART_TIMING, "%s: session %d:%d part time: %lld us\n", |
---|
2091 | | - dev_name(mpp->dev), task->session->pid, task->session->index, |
---|
2092 | | - ktime_us_delta(end, task->part)); |
---|
2093 | | - task->part = end; |
---|
| 2349 | + end = ktime_get(); |
---|
| 2350 | + mpp_debug(DEBUG_PART_TIMING, "%s:%d session %d:%d part time: %lld us\n", |
---|
| 2351 | + dev_name(mpp->dev), task->core_id, task->session->pid, |
---|
| 2352 | + task->session->index, ktime_us_delta(end, task->part)); |
---|
| 2353 | + task->part = end; |
---|
| 2354 | + } |
---|
2094 | 2355 | |
---|
2095 | 2356 | return 0; |
---|
2096 | 2357 | } |
---|
2097 | 2358 | |
---|
2098 | 2359 | int mpp_time_diff(struct mpp_task *task) |
---|
2099 | 2360 | { |
---|
2100 | | - ktime_t end; |
---|
2101 | | - struct mpp_dev *mpp = task->session->mpp; |
---|
| 2361 | + if (mpp_debug_unlikely(DEBUG_TIMING)) { |
---|
| 2362 | + ktime_t end; |
---|
| 2363 | + struct mpp_dev *mpp = mpp_get_task_used_device(task, task->session); |
---|
2102 | 2364 | |
---|
2103 | | - end = ktime_get(); |
---|
2104 | | - mpp_debug(DEBUG_TIMING, "%s: session %d:%d task time: %lld us\n", |
---|
2105 | | - dev_name(mpp->dev), task->session->pid, task->session->index, |
---|
2106 | | - ktime_us_delta(end, task->start)); |
---|
| 2365 | + end = ktime_get(); |
---|
| 2366 | + mpp_debug(DEBUG_TIMING, "%s:%d session %d:%d time: %lld us\n", |
---|
| 2367 | + dev_name(mpp->dev), task->core_id, task->session->pid, |
---|
| 2368 | + task->session->index, ktime_us_delta(end, task->start)); |
---|
| 2369 | + } |
---|
2107 | 2370 | |
---|
2108 | 2371 | return 0; |
---|
2109 | 2372 | } |
---|
.. | .. |
---|
2112 | 2375 | { |
---|
2113 | 2376 | if (mpp_debug_unlikely(DEBUG_TIMING)) { |
---|
2114 | 2377 | ktime_t end; |
---|
2115 | | - struct mpp_dev *mpp = task->session->mpp; |
---|
| 2378 | + struct mpp_dev *mpp = mpp_get_task_used_device(task, task->session); |
---|
2116 | 2379 | |
---|
2117 | 2380 | end = ktime_get(); |
---|
2118 | 2381 | |
---|
2119 | 2382 | if (clk_hz) |
---|
2120 | | - mpp_debug(DEBUG_TIMING, "%s: session %d time: %lld us hw %d us\n", |
---|
2121 | | - dev_name(mpp->dev), task->session->index, |
---|
2122 | | - ktime_us_delta(end, task->start), |
---|
| 2383 | + mpp_debug(DEBUG_TIMING, "%s:%d session %d:%d time: %lld us hw %d us\n", |
---|
| 2384 | + dev_name(mpp->dev), task->core_id, task->session->pid, |
---|
| 2385 | + task->session->index, ktime_us_delta(end, task->start), |
---|
2123 | 2386 | task->hw_cycles / (clk_hz / 1000000)); |
---|
2124 | 2387 | else |
---|
2125 | | - mpp_debug(DEBUG_TIMING, "%s: session %d time: %lld us\n", |
---|
2126 | | - dev_name(mpp->dev), task->session->index, |
---|
2127 | | - ktime_us_delta(end, task->start)); |
---|
| 2388 | + mpp_debug(DEBUG_TIMING, "%s:%d session %d:%d time: %lld us\n", |
---|
| 2389 | + dev_name(mpp->dev), task->core_id, task->session->pid, |
---|
| 2390 | + task->session->index, ktime_us_delta(end, task->start)); |
---|
2128 | 2391 | } |
---|
2129 | 2392 | |
---|
2130 | 2393 | return 0; |
---|
.. | .. |
---|
2143 | 2406 | ktime_t s = task->on_create; |
---|
2144 | 2407 | unsigned long state = task->state; |
---|
2145 | 2408 | |
---|
2146 | | - pr_info("task %d dump timing at %lld us:", task->task_index, time_diff); |
---|
| 2409 | + pr_info("task %d dump timing at %lld us:", task->task_id, time_diff); |
---|
2147 | 2410 | |
---|
2148 | 2411 | pr_info("timing: %-14s : %lld us\n", "create", ktime_to_us(s)); |
---|
2149 | 2412 | LOG_TIMING(state, TASK_TIMING_CREATE_END, "create end", task->on_create_end, s); |
---|
.. | .. |
---|
2325 | 2588 | return count; |
---|
2326 | 2589 | } |
---|
2327 | 2590 | |
---|
2328 | | -static const struct file_operations procfs_fops_u32 = { |
---|
2329 | | - .open = fops_open_u32, |
---|
2330 | | - .read = seq_read, |
---|
2331 | | - .release = single_release, |
---|
2332 | | - .write = fops_write_u32, |
---|
| 2591 | +static const struct proc_ops procfs_fops_u32 = { |
---|
| 2592 | + .proc_open = fops_open_u32, |
---|
| 2593 | + .proc_read = seq_read, |
---|
| 2594 | + .proc_release = single_release, |
---|
| 2595 | + .proc_write = fops_write_u32, |
---|
2333 | 2596 | }; |
---|
2334 | 2597 | |
---|
2335 | 2598 | struct proc_dir_entry * |
---|
.. | .. |
---|
2341 | 2604 | |
---|
2342 | 2605 | void mpp_procfs_create_common(struct proc_dir_entry *parent, struct mpp_dev *mpp) |
---|
2343 | 2606 | { |
---|
| 2607 | + mpp_procfs_create_u32("disable_work", 0644, parent, &mpp->disable); |
---|
2344 | 2608 | mpp_procfs_create_u32("timing_check", 0644, parent, &mpp->timing_check); |
---|
2345 | 2609 | } |
---|
2346 | 2610 | #endif |
---|