Lines Matching +full:resume +full:- +full:offset
3 * Copyright (c) 2010-2012 Broadcom. All rights reserved.
14 * 3. The names of the above-listed copyright holders may not be used
48 /* Some per-instance constants */
64 #define VC_SUSPEND_NUM_OFFSET 3 /* number of values before idle which are -ve */
74 #define VC_RESUME_NUM_OFFSET 1 /* number of values before idle which are -ve */
84 ** correctly - we don't want to prevent ARM suspend indefinitely in this case.
150 loff_t offset; member
213 insert = instance->completion_insert; in add_completion()
214 while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { in add_completion()
215 /* Out of space - wait for the client */ in add_completion()
218 "add_completion - completion queue full"); in add_completion()
221 if (down_interruptible(&instance->remove_event) != 0) { in add_completion()
227 if (instance->closing) { in add_completion()
235 completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; in add_completion()
237 completion->header = header; in add_completion()
238 completion->reason = reason; in add_completion()
240 completion->service_userdata = user_service->service; in add_completion()
241 completion->bulk_userdata = bulk_userdata; in add_completion()
246 lock_service(user_service->service); in add_completion()
247 if (instance->use_close_delivered) in add_completion()
248 user_service->close_pending = 1; in add_completion()
256 user_service->message_available_pos = insert; in add_completion()
258 instance->completion_insert = ++insert; in add_completion()
260 up(&instance->insert_event); in add_completion()
290 user_service = (USER_SERVICE_T *)service->base.userdata; in service_callback()
291 instance = user_service->instance; in service_callback()
293 if (!instance || instance->closing) in service_callback()
297 "service_callback - service %lx(%d,%p), reason %d, header %lx, " in service_callback()
300 service->localport, user_service->userdata, in service_callback()
304 if (header && user_service->is_vchi) { in service_callback()
306 while (user_service->msg_insert == in service_callback()
307 (user_service->msg_remove + MSG_QUEUE_SIZE)) { in service_callback()
312 "service_callback - msg queue full"); in service_callback()
316 if ((user_service->message_available_pos - in service_callback()
317 instance->completion_remove) < 0) { in service_callback()
331 if (down_interruptible(&user_service->remove_event) in service_callback()
337 } else if (instance->closing) { in service_callback()
347 user_service->msg_queue[user_service->msg_insert & in service_callback()
348 (MSG_QUEUE_SIZE - 1)] = header; in service_callback()
349 user_service->msg_insert++; in service_callback()
355 if (((user_service->message_available_pos - in service_callback()
356 instance->completion_remove) >= 0) || in service_callback()
357 user_service->dequeue_pending) { in service_callback()
358 user_service->dequeue_pending = 0; in service_callback()
364 up(&user_service->insert_event); in service_callback()
390 _sema_destroy(&user_service->insert_event); in user_service_free()
391 _sema_destroy(&user_service->remove_event); in user_service_free()
405 user_service->service->handle); in close_delivered()
407 if (user_service->close_pending) { in close_delivered()
409 unlock_service(user_service->service); in close_delivered()
411 /* Wake the user-thread blocked in close_ or remove_service */ in close_delivered()
412 up(&user_service->close_event); in close_delivered()
414 user_service->close_pending = 0; in close_delivered()
445 "vchiq_ioctl - instance %x, cmd %s, arg %p", in vchiq_ioctl()
453 if (!instance->connected) in vchiq_ioctl()
458 while ((service = next_service_by_instance(instance->state, in vchiq_ioctl()
460 status = vchiq_remove_service(service->handle); in vchiq_ioctl()
469 instance->closing = 1; in vchiq_ioctl()
470 up(&instance->insert_event); in vchiq_ioctl()
476 if (instance->connected) { in vchiq_ioctl()
477 ret = -EINVAL; in vchiq_ioctl()
480 rc = lmutex_lock_interruptible(&instance->state->mutex); in vchiq_ioctl()
485 instance->state->id, rc); in vchiq_ioctl()
486 ret = -EINTR; in vchiq_ioctl()
489 status = vchiq_connect_internal(instance->state, instance); in vchiq_ioctl()
490 lmutex_unlock(&instance->state->mutex); in vchiq_ioctl()
493 instance->connected = 1; in vchiq_ioctl()
509 ret = -ENOMEM; in vchiq_ioctl()
514 if (!instance->connected) { in vchiq_ioctl()
515 ret = -ENOTCONN; in vchiq_ioctl()
522 instance->connected ? in vchiq_ioctl()
531 instance->state, in vchiq_ioctl()
536 user_service->service = service; in vchiq_ioctl()
537 user_service->userdata = userdata; in vchiq_ioctl()
538 user_service->instance = instance; in vchiq_ioctl()
539 user_service->is_vchi = (args.is_vchi != 0); in vchiq_ioctl()
540 user_service->dequeue_pending = 0; in vchiq_ioctl()
541 user_service->close_pending = 0; in vchiq_ioctl()
542 user_service->message_available_pos = in vchiq_ioctl()
543 instance->completion_remove - 1; in vchiq_ioctl()
544 user_service->msg_insert = 0; in vchiq_ioctl()
545 user_service->msg_remove = 0; in vchiq_ioctl()
546 _sema_init(&user_service->insert_event, 0); in vchiq_ioctl()
547 _sema_init(&user_service->remove_event, 0); in vchiq_ioctl()
548 _sema_init(&user_service->close_event, 0); in vchiq_ioctl()
552 (service, instance->pid); in vchiq_ioctl()
554 vchiq_remove_service(service->handle); in vchiq_ioctl()
557 -EINTR : -EIO; in vchiq_ioctl()
563 printf("%s: [CREATE SERVICE] handle = %08x\n", __func__, service->handle); in vchiq_ioctl()
567 arg)->handle), in vchiq_ioctl()
568 (const void *)&service->handle, in vchiq_ioctl()
569 sizeof(service->handle)); in vchiq_ioctl()
573 ret = -EEXIST; in vchiq_ioctl()
590 (USER_SERVICE_T *)service->base.userdata; in vchiq_ioctl()
593 if (!user_service->close_pending) { in vchiq_ioctl()
594 status = vchiq_close_service(service->handle); in vchiq_ioctl()
602 if (user_service->close_pending && in vchiq_ioctl()
603 down_interruptible(&user_service->close_event)) in vchiq_ioctl()
607 ret = -EINVAL; in vchiq_ioctl()
622 (USER_SERVICE_T *)service->base.userdata; in vchiq_ioctl()
625 if (!user_service->close_pending) { in vchiq_ioctl()
626 status = vchiq_remove_service(service->handle); in vchiq_ioctl()
634 if (user_service->close_pending && in vchiq_ioctl()
635 down_interruptible(&user_service->close_event)) in vchiq_ioctl()
639 ret = -EINVAL; in vchiq_ioctl()
668 service->base.fourcc), in vchiq_ioctl()
669 service->client_id); in vchiq_ioctl()
670 ret = -EINVAL; in vchiq_ioctl()
673 ret = -EINVAL; in vchiq_ioctl()
695 ret = -EFAULT; in vchiq_ioctl()
697 ret = -EINVAL; in vchiq_ioctl()
713 ret = -EINVAL; in vchiq_ioctl()
721 ret = -ENOMEM; in vchiq_ioctl()
724 args.userdata = &waiter->bulk_waiter; in vchiq_ioctl()
727 lmutex_lock(&instance->bulk_waiter_list_mutex); in vchiq_ioctl()
728 list_for_each(pos, &instance->bulk_waiter_list) { in vchiq_ioctl()
730 list)->pid == current->p_pid) { in vchiq_ioctl()
739 lmutex_unlock(&instance->bulk_waiter_list_mutex); in vchiq_ioctl()
743 current->p_pid); in vchiq_ioctl()
744 ret = -ESRCH; in vchiq_ioctl()
749 (unsigned int)waiter, current->p_pid); in vchiq_ioctl()
750 args.userdata = &waiter->bulk_waiter; in vchiq_ioctl()
761 !waiter->bulk_waiter.bulk) { in vchiq_ioctl()
762 if (waiter->bulk_waiter.bulk) { in vchiq_ioctl()
766 waiter->bulk_waiter.bulk->userdata = NULL; in vchiq_ioctl()
769 _sema_destroy(&waiter->bulk_waiter.event); in vchiq_ioctl()
774 waiter->pid = current->p_pid; in vchiq_ioctl()
775 lmutex_lock(&instance->bulk_waiter_list_mutex); in vchiq_ioctl()
776 list_add(&waiter->list, &instance->bulk_waiter_list); in vchiq_ioctl()
777 lmutex_unlock(&instance->bulk_waiter_list_mutex); in vchiq_ioctl()
780 (unsigned int)waiter, current->p_pid); in vchiq_ioctl()
784 arg)->mode), in vchiq_ioctl()
795 if (!instance->connected) { in vchiq_ioctl()
796 ret = -ENOTCONN; in vchiq_ioctl()
802 lmutex_lock(&instance->completion_mutex); in vchiq_ioctl()
805 while ((instance->completion_remove == in vchiq_ioctl()
806 instance->completion_insert) in vchiq_ioctl()
807 && !instance->closing) { in vchiq_ioctl()
810 lmutex_unlock(&instance->completion_mutex); in vchiq_ioctl()
811 rc = down_interruptible(&instance->insert_event); in vchiq_ioctl()
812 lmutex_lock(&instance->completion_mutex); in vchiq_ioctl()
817 ret = -EINTR; in vchiq_ioctl()
827 remove = instance->completion_remove; in vchiq_ioctl()
835 if (remove == instance->completion_insert) in vchiq_ioctl()
838 completion = &instance->completions[ in vchiq_ioctl()
839 remove & (MAX_COMPLETIONS - 1)]; in vchiq_ioctl()
847 service1 = completion->service_userdata; in vchiq_ioctl()
848 user_service = service1->base.userdata; in vchiq_ioctl()
849 completion->service_userdata = in vchiq_ioctl()
850 user_service->userdata; in vchiq_ioctl()
852 header = completion->header; in vchiq_ioctl()
857 msglen = header->size + in vchiq_ioctl()
859 /* This must be a VCHIQ-style service */ in vchiq_ioctl()
871 ret = -EMSGSIZE; in vchiq_ioctl()
879 msgbufcount--; in vchiq_ioctl()
885 ret = -EFAULT; in vchiq_ioctl()
893 ret = -EFAULT; in vchiq_ioctl()
899 vchiq_release_message(service1->handle, in vchiq_ioctl()
904 completion->header = msgbuf; in vchiq_ioctl()
907 if ((completion->reason == in vchiq_ioctl()
909 !instance->use_close_delivered) in vchiq_ioctl()
918 ret = -EFAULT; in vchiq_ioctl()
926 instance->completion_remove = ++remove; in vchiq_ioctl()
931 &((VCHIQ_AWAIT_COMPLETION_T *)arg)-> in vchiq_ioctl()
940 &((VCHIQ_AWAIT_COMPLETION_T *)arg)->count, in vchiq_ioctl()
946 up(&instance->remove_event); in vchiq_ioctl()
948 if ((ret == 0) && instance->closing) in vchiq_ioctl()
949 ret = -ENOTCONN; in vchiq_ioctl()
958 lmutex_unlock(&instance->completion_mutex); in vchiq_ioctl()
971 ret = -EINVAL; in vchiq_ioctl()
974 user_service = (USER_SERVICE_T *)service->base.userdata; in vchiq_ioctl()
975 if (user_service->is_vchi == 0) { in vchiq_ioctl()
976 ret = -EINVAL; in vchiq_ioctl()
981 if (user_service->msg_remove == user_service->msg_insert) { in vchiq_ioctl()
985 ret = -EWOULDBLOCK; in vchiq_ioctl()
988 user_service->dequeue_pending = 1; in vchiq_ioctl()
993 &user_service->insert_event) != 0) { in vchiq_ioctl()
996 ret = -EINTR; in vchiq_ioctl()
1000 } while (user_service->msg_remove == in vchiq_ioctl()
1001 user_service->msg_insert); in vchiq_ioctl()
1007 BUG_ON((int)(user_service->msg_insert - in vchiq_ioctl()
1008 user_service->msg_remove) < 0); in vchiq_ioctl()
1010 header = user_service->msg_queue[user_service->msg_remove & in vchiq_ioctl()
1011 (MSG_QUEUE_SIZE - 1)]; in vchiq_ioctl()
1012 user_service->msg_remove++; in vchiq_ioctl()
1015 up(&user_service->remove_event); in vchiq_ioctl()
1017 ret = -ENOTCONN; in vchiq_ioctl()
1018 else if (header->size <= args.bufsize) { in vchiq_ioctl()
1022 header->data, in vchiq_ioctl()
1023 header->size) == 0)) { in vchiq_ioctl()
1024 args.bufsize = header->size; in vchiq_ioctl()
1028 service->handle, in vchiq_ioctl()
1031 ret = -EFAULT; in vchiq_ioctl()
1036 header->size); in vchiq_ioctl()
1038 ret = -EMSGSIZE; in vchiq_ioctl()
1057 ret = -EINVAL; in vchiq_ioctl()
1064 ret = -EFAULT; in vchiq_ioctl()
1077 ret = -EINVAL; in vchiq_ioctl()
1099 ret = -EINVAL; in vchiq_ioctl()
1101 instance->use_close_delivered = 1; in vchiq_ioctl()
1111 (USER_SERVICE_T *)service->base.userdata; in vchiq_ioctl()
1115 ret = -EINVAL; in vchiq_ioctl()
1119 ret = -ENOTTY; in vchiq_ioctl()
1128 ret = -EIO; in vchiq_ioctl()
1130 ret = -EINTR; in vchiq_ioctl()
1133 if ((status == VCHIQ_SUCCESS) && (ret < 0) && (ret != -EINTR) && in vchiq_ioctl()
1134 (ret != -EWOULDBLOCK)) in vchiq_ioctl()
1136 " ioctl instance %lx, cmd %s -> status %d, %d", in vchiq_ioctl()
1144 " ioctl instance %lx, cmd %s -> status %d, %d", in vchiq_ioctl()
1151 /* XXXBSD: report BSD-style error to userland */ in vchiq_ioctl()
1153 ret = -ret; in vchiq_ioctl()
1183 return -ENOTCONN; in vchiq_open()
1188 return -ENOMEM; in vchiq_open()
1190 instance->state = state; in vchiq_open()
1192 instance->pid = td->td_proc->p_pid; in vchiq_open()
1202 _sema_init(&instance->insert_event, 0); in vchiq_open()
1203 _sema_init(&instance->remove_event, 0); in vchiq_open()
1204 lmutex_init(&instance->completion_mutex); in vchiq_open()
1205 lmutex_init(&instance->bulk_waiter_list_mutex); in vchiq_open()
1206 INIT_LIST_HEAD(&instance->bulk_waiter_list); in vchiq_open()
1213 return -ENXIO; in vchiq_open()
1246 ret = -EPERM; in vchiq_close()
1251 vchiq_use_internal(instance->state, NULL, in vchiq_close()
1254 lmutex_lock(&instance->completion_mutex); in vchiq_close()
1257 instance->closing = 1; in vchiq_close()
1258 up(&instance->insert_event); in vchiq_close()
1260 lmutex_unlock(&instance->completion_mutex); in vchiq_close()
1263 up(&instance->remove_event); in vchiq_close()
1269 USER_SERVICE_T *user_service = service->base.userdata; in vchiq_close()
1272 up(&user_service->remove_event); in vchiq_close()
1282 USER_SERVICE_T *user_service = service->base.userdata; in vchiq_close()
1284 down(&service->remove_event); in vchiq_close()
1286 BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); in vchiq_close()
1290 while (user_service->msg_remove != in vchiq_close()
1291 user_service->msg_insert) { in vchiq_close()
1292 VCHIQ_HEADER_T *header = user_service-> in vchiq_close()
1293 msg_queue[user_service->msg_remove & in vchiq_close()
1294 (MSG_QUEUE_SIZE - 1)]; in vchiq_close()
1295 user_service->msg_remove++; in vchiq_close()
1300 service->handle, in vchiq_close()
1311 while (instance->completion_remove != in vchiq_close()
1312 instance->completion_insert) { in vchiq_close()
1315 completion = &instance->completions[ in vchiq_close()
1316 instance->completion_remove & in vchiq_close()
1317 (MAX_COMPLETIONS - 1)]; in vchiq_close()
1318 service1 = completion->service_userdata; in vchiq_close()
1319 if (completion->reason == VCHIQ_SERVICE_CLOSED) in vchiq_close()
1322 service->base.userdata; in vchiq_close()
1324 /* Wake any blocked user-thread */ in vchiq_close()
1325 if (instance->use_close_delivered) in vchiq_close()
1326 up(&user_service->close_event); in vchiq_close()
1329 instance->completion_remove++; in vchiq_close()
1333 vchiq_release_internal(instance->state, NULL); in vchiq_close()
1338 &instance->bulk_waiter_list) { in vchiq_close()
1345 "bulk_waiter - cleaned up %x " in vchiq_close()
1347 (unsigned int)waiter, waiter->pid); in vchiq_close()
1348 _sema_destroy(&waiter->bulk_waiter.event); in vchiq_close()
1357 ret = -ENXIO; in vchiq_close()
1375 if (context->actual < context->space) { in vchiq_dump()
1377 if (context->offset > 0) { in vchiq_dump()
1378 int skip_bytes = min(len, (int)context->offset); in vchiq_dump()
1380 len -= skip_bytes; in vchiq_dump()
1381 context->offset -= skip_bytes; in vchiq_dump()
1382 if (context->offset > 0) in vchiq_dump()
1385 copy_bytes = min(len, (int)(context->space - context->actual)); in vchiq_dump()
1388 memcpy(context->buf + context->actual, str, copy_bytes); in vchiq_dump()
1389 context->actual += copy_bytes; in vchiq_dump()
1390 len -= copy_bytes; in vchiq_dump()
1395 if ((len == 0) && (str[copy_bytes - 1] == '\0')) { in vchiq_dump()
1397 memcpy(context->buf + context->actual - 1, &cr, 1); in vchiq_dump()
1419 for (i = 0; i < state->unused_service; i++) { in vchiq_dump_platform_instances()
1420 VCHIQ_SERVICE_T *service = state->services[i]; in vchiq_dump_platform_instances()
1423 if (service && (service->base.callback == service_callback)) { in vchiq_dump_platform_instances()
1424 instance = service->instance; in vchiq_dump_platform_instances()
1426 instance->mark = 0; in vchiq_dump_platform_instances()
1430 for (i = 0; i < state->unused_service; i++) { in vchiq_dump_platform_instances()
1431 VCHIQ_SERVICE_T *service = state->services[i]; in vchiq_dump_platform_instances()
1434 if (service && (service->base.callback == service_callback)) { in vchiq_dump_platform_instances()
1435 instance = service->instance; in vchiq_dump_platform_instances()
1436 if (instance && !instance->mark) { in vchiq_dump_platform_instances()
1440 (unsigned int)instance, instance->pid, in vchiq_dump_platform_instances()
1441 instance->connected ? " connected, " : in vchiq_dump_platform_instances()
1443 instance->completion_insert - in vchiq_dump_platform_instances()
1444 instance->completion_remove, in vchiq_dump_platform_instances()
1449 instance->mark = 1; in vchiq_dump_platform_instances()
1464 USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata; in vchiq_dump_platform_service_state()
1469 (unsigned int)service->instance); in vchiq_dump_platform_service_state()
1471 if ((service->base.callback == service_callback) && in vchiq_dump_platform_service_state()
1472 user_service->is_vchi) { in vchiq_dump_platform_service_state()
1473 len += snprintf(buf + len, sizeof(buf) - len, in vchiq_dump_platform_service_state()
1475 user_service->msg_insert - user_service->msg_remove, in vchiq_dump_platform_service_state()
1478 if (user_service->dequeue_pending) in vchiq_dump_platform_service_state()
1479 len += snprintf(buf + len, sizeof(buf) - len, in vchiq_dump_platform_service_state()
1499 int offset; in dump_phys_mem() local
1513 offset = (int)(long)virt_addr & (PAGE_SIZE - 1); in dump_phys_mem()
1514 end_offset = (int)(long)end_virt_addr & (PAGE_SIZE - 1); in dump_phys_mem()
1516 num_pages = (offset + num_bytes + PAGE_SIZE - 1) / PAGE_SIZE; in dump_phys_mem()
1526 down_read(¤t->mm->mmap_sem); in dump_phys_mem()
1528 current->mm, /* mm */ in dump_phys_mem()
1535 up_read(¤t->mm->mmap_sem); in dump_phys_mem()
1537 prev_idx = -1; in dump_phys_mem()
1540 while (offset < end_offset) { in dump_phys_mem()
1542 int page_offset = offset % PAGE_SIZE; in dump_phys_mem()
1543 page_idx = offset / PAGE_SIZE; in dump_phys_mem()
1561 offset += 16; in dump_phys_mem()
1586 context.offset = *ppos; in vchiq_read()
1602 else if (g_state.remote->initialised != 1) in vchiq_get_state()
1603 printk(KERN_NOTICE "%s: g_state.remote->initialised != 1 (%d)\n", in vchiq_get_state()
1604 __func__, g_state.remote->initialised); in vchiq_get_state()
1607 (g_state.remote->initialised == 1)) ? &g_state : NULL; in vchiq_get_state()
1619 /* autosuspend not supported - always return wanted */ in vchiq_videocore_wanted()
1621 else if (arm_state->blocked_count) in vchiq_videocore_wanted()
1623 else if (!arm_state->videocore_use_count) in vchiq_videocore_wanted()
1624 /* usage count zero - check for override unless we're forcing */ in vchiq_videocore_wanted()
1625 if (arm_state->resume_blocked) in vchiq_videocore_wanted()
1630 /* non-zero usage count - videocore still required */ in vchiq_videocore_wanted()
1685 if (wait_for_completion_interruptible(&arm_state->ka_evt) in vchiq_keepalive_thread_func()
1695 rc = atomic_xchg(&arm_state->ka_release_count, 0); in vchiq_keepalive_thread_func()
1696 uc = atomic_xchg(&arm_state->ka_use_count, 0); in vchiq_keepalive_thread_func()
1700 while (uc--) { in vchiq_keepalive_thread_func()
1701 atomic_inc(&arm_state->ka_use_ack_count); in vchiq_keepalive_thread_func()
1709 while (rc--) { in vchiq_keepalive_thread_func()
1731 rwlock_init(&arm_state->susp_res_lock); in vchiq_arm_init_state()
1733 init_completion(&arm_state->ka_evt); in vchiq_arm_init_state()
1734 atomic_set(&arm_state->ka_use_count, 0); in vchiq_arm_init_state()
1735 atomic_set(&arm_state->ka_use_ack_count, 0); in vchiq_arm_init_state()
1736 atomic_set(&arm_state->ka_release_count, 0); in vchiq_arm_init_state()
1738 init_completion(&arm_state->vc_suspend_complete); in vchiq_arm_init_state()
1740 init_completion(&arm_state->vc_resume_complete); in vchiq_arm_init_state()
1741 /* Initialise to 'done' state. We only want to block on resume in vchiq_arm_init_state()
1745 init_completion(&arm_state->resume_blocker); in vchiq_arm_init_state()
1747 * completion while resume is blocked */ in vchiq_arm_init_state()
1748 complete_all(&arm_state->resume_blocker); in vchiq_arm_init_state()
1750 init_completion(&arm_state->blocked_blocker); in vchiq_arm_init_state()
1752 * completion while things are waiting on the resume blocker */ in vchiq_arm_init_state()
1753 complete_all(&arm_state->blocked_blocker); in vchiq_arm_init_state()
1755 arm_state->suspend_timer_timeout = SUSPEND_TIMER_TIMEOUT_MS; in vchiq_arm_init_state()
1756 arm_state->suspend_timer_running = 0; in vchiq_arm_init_state()
1757 vchiq_init_timer(&arm_state->suspend_timer); in vchiq_arm_init_state()
1758 arm_state->suspend_timer.data = (unsigned long)(state); in vchiq_arm_init_state()
1759 arm_state->suspend_timer.function = suspend_timer_callback; in vchiq_arm_init_state()
1761 arm_state->first_connect = 0; in vchiq_arm_init_state()
1773 ** step. Suspend and resume state are maintained separately, since most of
1777 ** need to occur on state machine reset and end-state(s), so these are also
1783 ** VC_SUSPEND_IDLE - Initialise the suspend completion at the same time.
1790 ** VC_SUSPEND_IN_PROGRESS - This state is considered the point of no return for
1791 ** suspend - ie from this point on we must try to suspend
1793 ** resume state machine to VC_RESUME_IDLE in this state.
1795 ** VC_SUSPEND_SUSPENDED - Suspend has completed successfully. Also call
1799 ** VC_SUSPEND_REJECTED - Videocore rejected suspend. Videocore will also
1800 ** initiate resume, so no need to alter resume state.
1804 ** VC_SUSPEND_FAILED - We failed to initiate videocore suspend. We notify the
1805 ** suspend completion and reset the resume state machine.
1807 ** VC_RESUME_IDLE - Initialise the resume completion at the same time. The
1808 ** resume completion is in its 'done' state whenever
1812 ** running can wait on this completion - it will only block
1815 ** VC_RESUME_RESUMED - Resume has completed successfully. Videocore is running.
1816 ** Call complete_all on the resume completion to unblock
1817 ** any threads waiting for resume. Also reset the suspend
1820 ** VC_RESUME_FAILED - Currently unused - no mechanism to fail resume exists.
1828 arm_state->vc_suspend_state = new_state; in set_suspend_state()
1833 complete_all(&arm_state->vc_suspend_complete); in set_suspend_state()
1836 complete_all(&arm_state->vc_suspend_complete); in set_suspend_state()
1839 complete_all(&arm_state->vc_suspend_complete); in set_suspend_state()
1840 arm_state->vc_resume_state = VC_RESUME_RESUMED; in set_suspend_state()
1841 complete_all(&arm_state->vc_resume_complete); in set_suspend_state()
1845 INIT_COMPLETION(arm_state->vc_suspend_complete); in set_suspend_state()
1853 complete_all(&arm_state->vc_suspend_complete); in set_suspend_state()
1866 arm_state->vc_resume_state = new_state; in set_resume_state()
1874 INIT_COMPLETION(arm_state->vc_resume_complete); in set_resume_state()
1881 complete_all(&arm_state->vc_resume_complete); in set_resume_state()
1895 vchiq_del_timer(&arm_state->suspend_timer); in start_suspend_timer()
1896 arm_state->suspend_timer.expires = jiffies + in start_suspend_timer()
1897 msecs_to_jiffies(arm_state-> in start_suspend_timer()
1899 vchiq_add_timer(&arm_state->suspend_timer); in start_suspend_timer()
1900 arm_state->suspend_timer_running = 1; in start_suspend_timer()
1907 if (arm_state->suspend_timer_running) { in stop_suspend_timer()
1908 vchiq_del_timer(&arm_state->suspend_timer); in stop_suspend_timer()
1909 arm_state->suspend_timer_running = 0; in stop_suspend_timer()
1917 return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) && in need_resume()
1918 (arm_state->vc_resume_state < VC_RESUME_REQUESTED) && in need_resume()
1935 if (arm_state->blocked_count) { in block_resume()
1937 INIT_COMPLETION(arm_state->blocked_blocker); in block_resume()
1938 write_unlock_bh(&arm_state->susp_res_lock); in block_resume()
1942 &arm_state->blocked_blocker, timeout_val) in block_resume()
1947 write_lock_bh(&arm_state->susp_res_lock); in block_resume()
1952 write_lock_bh(&arm_state->susp_res_lock); in block_resume()
1955 /* We need to wait for resume to complete if it's in process */ in block_resume()
1956 while (arm_state->vc_resume_state != VC_RESUME_RESUMED && in block_resume()
1957 arm_state->vc_resume_state > VC_RESUME_IDLE) { in block_resume()
1961 "many times for resume" , __func__); in block_resume()
1964 write_unlock_bh(&arm_state->susp_res_lock); in block_resume()
1965 vchiq_log_info(vchiq_susp_log_level, "%s wait for resume", in block_resume()
1968 &arm_state->vc_resume_complete, timeout_val) in block_resume()
1971 "resume failed (%s)", __func__, in block_resume()
1972 resume_state_names[arm_state->vc_resume_state + in block_resume()
1975 write_lock_bh(&arm_state->susp_res_lock); in block_resume()
1979 write_lock_bh(&arm_state->susp_res_lock); in block_resume()
1983 INIT_COMPLETION(arm_state->resume_blocker); in block_resume()
1984 arm_state->resume_blocked = 1; in block_resume()
1993 complete_all(&arm_state->resume_blocker); in unblock_resume()
1994 arm_state->resume_blocked = 0; in unblock_resume()
2012 switch (arm_state->vc_suspend_state) { in vchiq_arm_vcsuspend()
2027 suspend_state_names[arm_state->vc_suspend_state + in vchiq_arm_vcsuspend()
2060 write_lock_bh(&arm_state->susp_res_lock); in vchiq_platform_check_suspend()
2061 if (arm_state->vc_suspend_state == VC_SUSPEND_REQUESTED && in vchiq_platform_check_suspend()
2062 arm_state->vc_resume_state == VC_RESUME_RESUMED) { in vchiq_platform_check_suspend()
2066 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_platform_check_suspend()
2082 int vc_use_count = arm_state->videocore_use_count; in output_timeout_error()
2083 int active_services = state->unused_service; in output_timeout_error()
2086 if (!arm_state->videocore_use_count) { in output_timeout_error()
2091 VCHIQ_SERVICE_T *service_ptr = state->services[i]; in output_timeout_error()
2092 if (service_ptr && service_ptr->service_use_count && in output_timeout_error()
2093 (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE)) { in output_timeout_error()
2096 service_ptr->base.fourcc), in output_timeout_error()
2097 service_ptr->client_id, in output_timeout_error()
2098 service_ptr->service_use_count, in output_timeout_error()
2099 service_ptr->service_use_count == in output_timeout_error()
2108 arm_state->autosuspend_override, service_err); in output_timeout_error()
2127 int repeat = -1; in vchiq_arm_force_suspend()
2134 write_lock_bh(&arm_state->susp_res_lock); in vchiq_arm_force_suspend()
2139 if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { in vchiq_arm_force_suspend()
2140 /* Already suspended - just block resume and exit */ in vchiq_arm_force_suspend()
2145 } else if (arm_state->vc_suspend_state <= VC_SUSPEND_IDLE) { in vchiq_arm_force_suspend()
2153 } else if (arm_state->autosuspend_override < in vchiq_arm_force_suspend()
2160 "many times - attempting suspend", __func__); in vchiq_arm_force_suspend()
2165 "in progress - wait for completion", __func__); in vchiq_arm_force_suspend()
2174 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_arm_force_suspend()
2177 &arm_state->vc_suspend_complete, in vchiq_arm_force_suspend()
2180 write_lock_bh(&arm_state->susp_res_lock); in vchiq_arm_force_suspend()
2187 if (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) { in vchiq_arm_force_suspend()
2194 arm_state->autosuspend_override++; in vchiq_arm_force_suspend()
2200 } while (0 < (repeat--)); in vchiq_arm_force_suspend()
2203 if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED) { in vchiq_arm_force_suspend()
2207 suspend_state_names[arm_state->vc_suspend_state + in vchiq_arm_force_suspend()
2211 if (arm_state->vc_suspend_state < VC_SUSPEND_IDLE) in vchiq_arm_force_suspend()
2217 /* successfully suspended - unlock and exit */ in vchiq_arm_force_suspend()
2221 /* all error states need to unblock resume before exit */ in vchiq_arm_force_suspend()
2225 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_arm_force_suspend()
2242 write_lock_bh(&arm_state->susp_res_lock); in vchiq_check_suspend()
2243 if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED && in vchiq_check_suspend()
2244 arm_state->first_connect && in vchiq_check_suspend()
2248 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_check_suspend()
2260 int resume = 0; in vchiq_arm_allow_resume() local
2261 int ret = -1; in vchiq_arm_allow_resume()
2268 write_lock_bh(&arm_state->susp_res_lock); in vchiq_arm_allow_resume()
2270 resume = vchiq_check_resume(state); in vchiq_arm_allow_resume()
2271 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_arm_allow_resume()
2273 if (resume) { in vchiq_arm_allow_resume()
2275 &arm_state->vc_resume_complete) < 0) { in vchiq_arm_allow_resume()
2284 read_lock_bh(&arm_state->susp_res_lock); in vchiq_arm_allow_resume()
2285 if (arm_state->vc_suspend_state == VC_SUSPEND_SUSPENDED) { in vchiq_arm_allow_resume()
2293 read_unlock_bh(&arm_state->susp_res_lock); in vchiq_arm_allow_resume()
2304 int resume = 0; in vchiq_check_resume() local
2314 resume = 1; in vchiq_check_resume()
2319 return resume; in vchiq_check_resume()
2334 write_lock_bh(&arm_state->susp_res_lock); in vchiq_platform_check_resume()
2335 if (arm_state->wake_address == 0) { in vchiq_platform_check_resume()
2340 if (arm_state->vc_resume_state == VC_RESUME_IN_PROGRESS) { in vchiq_platform_check_resume()
2346 if (arm_state->vc_resume_state == VC_RESUME_REQUESTED) { in vchiq_platform_check_resume()
2351 "%s: not resuming (resume state %s)", __func__, in vchiq_platform_check_resume()
2352 resume_state_names[arm_state->vc_resume_state + in vchiq_platform_check_resume()
2356 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_platform_check_resume()
2387 entity_uc = &arm_state->peer_use_count; in vchiq_use_internal()
2390 VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), in vchiq_use_internal()
2391 service->client_id); in vchiq_use_internal()
2392 entity_uc = &service->service_use_count; in vchiq_use_internal()
2400 write_lock_bh(&arm_state->susp_res_lock); in vchiq_use_internal()
2401 while (arm_state->resume_blocked) { in vchiq_use_internal()
2407 if (arm_state->resume_blocked && arm_state->vc_suspend_state == in vchiq_use_internal()
2413 if (!try_wait_for_completion(&arm_state->resume_blocker)) { in vchiq_use_internal()
2414 /* Indicate that there are threads waiting on the resume in vchiq_use_internal()
2419 arm_state->blocked_count++; in vchiq_use_internal()
2420 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_use_internal()
2421 vchiq_log_info(vchiq_susp_log_level, "%s %s resume " in vchiq_use_internal()
2422 "blocked - waiting...", __func__, entity); in vchiq_use_internal()
2424 &arm_state->resume_blocker) != 0) { in vchiq_use_internal()
2426 "wait for resume blocker interrupted", in vchiq_use_internal()
2429 write_lock_bh(&arm_state->susp_res_lock); in vchiq_use_internal()
2430 arm_state->blocked_count--; in vchiq_use_internal()
2431 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_use_internal()
2434 vchiq_log_info(vchiq_susp_log_level, "%s %s resume " in vchiq_use_internal()
2436 write_lock_bh(&arm_state->susp_res_lock); in vchiq_use_internal()
2437 if (--arm_state->blocked_count == 0) in vchiq_use_internal()
2438 complete_all(&arm_state->blocked_blocker); in vchiq_use_internal()
2444 local_uc = ++arm_state->videocore_use_count; in vchiq_use_internal()
2449 * vc_resume_complete will block until we either resume or fail to in vchiq_use_internal()
2451 if (arm_state->vc_suspend_state <= VC_SUSPEND_REQUESTED) in vchiq_use_internal()
2466 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_use_internal()
2469 * block for the non-suspended case. */ in vchiq_use_internal()
2470 if (!try_wait_for_completion(&arm_state->vc_resume_complete)) { in vchiq_use_internal()
2471 vchiq_log_info(vchiq_susp_log_level, "%s %s wait for resume", in vchiq_use_internal()
2474 &arm_state->vc_resume_complete) != 0) { in vchiq_use_internal()
2476 "resume interrupted", __func__, entity); in vchiq_use_internal()
2486 long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); in vchiq_use_internal()
2491 ack_cnt--; in vchiq_use_internal()
2494 &arm_state->ka_use_ack_count); in vchiq_use_internal()
2518 VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), in vchiq_release_internal()
2519 service->client_id); in vchiq_release_internal()
2520 entity_uc = &service->service_use_count; in vchiq_release_internal()
2523 entity_uc = &arm_state->peer_use_count; in vchiq_release_internal()
2526 write_lock_bh(&arm_state->susp_res_lock); in vchiq_release_internal()
2527 if (!arm_state->videocore_use_count || !(*entity_uc)) { in vchiq_release_internal()
2528 /* Don't use BUG_ON - don't allow user thread to crash kernel */ in vchiq_release_internal()
2529 WARN_ON(!arm_state->videocore_use_count); in vchiq_release_internal()
2534 --arm_state->videocore_use_count; in vchiq_release_internal()
2535 --(*entity_uc); in vchiq_release_internal()
2539 !arm_state->resume_blocked) { in vchiq_release_internal()
2545 "%s %s count %d, state count %d - suspending", in vchiq_release_internal()
2547 arm_state->videocore_use_count); in vchiq_release_internal()
2554 arm_state->videocore_use_count); in vchiq_release_internal()
2557 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_release_internal()
2569 atomic_inc(&arm_state->ka_use_count); in vchiq_on_remote_use()
2570 complete(&arm_state->ka_evt); in vchiq_on_remote_use()
2578 atomic_inc(&arm_state->ka_release_count); in vchiq_on_remote_release()
2579 complete(&arm_state->ka_evt); in vchiq_on_remote_release()
2585 return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); in vchiq_use_service_internal()
2591 return vchiq_release_internal(service->state, service); in vchiq_release_service_internal()
2601 "%s - suspend timer expired - check suspend", __func__); in suspend_timer_callback()
2613 ret = vchiq_use_internal(service->state, service, in vchiq_use_service_no_resume()
2626 ret = vchiq_use_internal(service->state, service, in vchiq_use_service()
2639 ret = vchiq_release_internal(service->state, service); in vchiq_release_service()
2653 * non-zero counts */ in vchiq_dump_service_use_state()
2655 static const char *nz = "<-- preventing suspend"; in vchiq_dump_service_use_state()
2671 read_lock_bh(&arm_state->susp_res_lock); in vchiq_dump_service_use_state()
2672 vc_suspend_state = arm_state->vc_suspend_state; in vchiq_dump_service_use_state()
2673 vc_resume_state = arm_state->vc_resume_state; in vchiq_dump_service_use_state()
2674 peer_count = arm_state->peer_use_count; in vchiq_dump_service_use_state()
2675 vc_use_count = arm_state->videocore_use_count; in vchiq_dump_service_use_state()
2676 active_services = state->unused_service; in vchiq_dump_service_use_state()
2681 VCHIQ_SERVICE_T *service_ptr = state->services[i]; in vchiq_dump_service_use_state()
2685 if (only_nonzero && !service_ptr->service_use_count) in vchiq_dump_service_use_state()
2688 if (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE) { in vchiq_dump_service_use_state()
2689 service_data[j].fourcc = service_ptr->base.fourcc; in vchiq_dump_service_use_state()
2690 service_data[j].clientid = service_ptr->client_id; in vchiq_dump_service_use_state()
2691 service_data[j++].use_count = service_ptr-> in vchiq_dump_service_use_state()
2696 read_unlock_bh(&arm_state->susp_res_lock); in vchiq_dump_service_use_state()
2699 "-- Videcore suspend state: %s --", in vchiq_dump_service_use_state()
2702 "-- Videcore resume state: %s --", in vchiq_dump_service_use_state()
2708 "with non-zero use-count", active_services, in vchiq_dump_service_use_state()
2713 "----- %c%c%c%c:%d service count %d %s", in vchiq_dump_service_use_state()
2720 "----- VCHIQ use count count %d", peer_count); in vchiq_dump_service_use_state()
2722 "--- Overall vchiq instance use count %d", vc_use_count); in vchiq_dump_service_use_state()
2733 if (!service || !service->state) in vchiq_check_service()
2738 arm_state = vchiq_platform_get_arm_state(service->state); in vchiq_check_service()
2740 read_lock_bh(&arm_state->susp_res_lock); in vchiq_check_service()
2741 if (service->service_use_count) in vchiq_check_service()
2743 read_unlock_bh(&arm_state->susp_res_lock); in vchiq_check_service()
2747 "%s ERROR - %c%c%c%c:%8x service count %d, " in vchiq_check_service()
2749 VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), in vchiq_check_service()
2750 service->client_id, service->service_use_count, in vchiq_check_service()
2751 arm_state->videocore_use_count, in vchiq_check_service()
2752 suspend_state_names[arm_state->vc_suspend_state + in vchiq_check_service()
2754 vchiq_dump_service_use_state(service->state); in vchiq_check_service()
2770 vchiq_log_info(vchiq_susp_log_level, "%d: %s->%s", state->id, in vchiq_platform_conn_state_changed()
2772 if (state->conn_state == VCHIQ_CONNSTATE_CONNECTED) { in vchiq_platform_conn_state_changed()
2773 write_lock_bh(&arm_state->susp_res_lock); in vchiq_platform_conn_state_changed()
2774 if (!arm_state->first_connect) { in vchiq_platform_conn_state_changed()
2776 arm_state->first_connect = 1; in vchiq_platform_conn_state_changed()
2777 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_platform_conn_state_changed()
2778 snprintf(threadname, sizeof(threadname), "VCHIQka-%d", in vchiq_platform_conn_state_changed()
2779 state->id); in vchiq_platform_conn_state_changed()
2780 arm_state->ka_thread = vchiq_thread_create( in vchiq_platform_conn_state_changed()
2784 if (arm_state->ka_thread == NULL) { in vchiq_platform_conn_state_changed()
2789 wake_up_process(arm_state->ka_thread); in vchiq_platform_conn_state_changed()
2792 write_unlock_bh(&arm_state->susp_res_lock); in vchiq_platform_conn_state_changed()
2798 * vchiq_init - called when the module is loaded.
2819 return (-ENXIO); in vchiq_init()
2829 "vchiq: initialised - version %d (min %d)", in vchiq_init()
2849 while ((service = next_service_by_instance(instance->state, in vchiq_instance_get_use_count()
2851 use_count += service->service_use_count; in vchiq_instance_get_use_count()
2857 /* read the per-process use-count */
2877 int pid = instance->pid; in vchiq_proc_add_instance()
2891 instance->proc_entry = top; in vchiq_proc_add_instance()
2896 remove_proc_entry(top->name, clients); in vchiq_proc_add_instance()
2898 return -ENOMEM; in vchiq_proc_add_instance()
2904 remove_proc_entry("use_count", instance->proc_entry); in vchiq_proc_remove_instance()
2905 remove_proc_entry(instance->proc_entry->name, clients); in vchiq_proc_remove_instance()
2912 * vchiq_exit - called when the module is unloaded.