示例#1
0
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
	uint32_t alarm_type_mask = 1U << alarm_type;

	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
		return -EINVAL;

	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		mutex_lock(&alarm_mutex);
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		alarm_try_to_cancel(&alarms[alarm_type]);
		if (alarm_pending) {
			alarm_pending &= ~alarm_type_mask;
			if (!alarm_pending && !wait_pending)
				wake_unlock(&alarm_wake_lock);
		}
		alarm_enabled &= ~alarm_type_mask;
		spin_unlock_irqrestore(&alarm_slock, flags);
		
		if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP)
		{
			set_power_on_alarm(0,0);
			printk("PM_DEBUG_MXP: RTC alarm has been cleared.\n");
		}
		
		mutex_unlock(&alarm_mutex);
		break;

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
		mutex_lock(&alarm_mutex);
		spin_lock_irqsave(&alarm_slock, flags);

		/*printk("PM_DEBUG_MXP: alarm %d set %ld.%09ld\n", alarm_type,
*/	
		alarm_enabled |= alarm_type_mask;
		alarm_start_range(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time),
			timespec_to_ktime(new_alarm_time));
		spin_unlock_irqrestore(&alarm_slock, flags);
		//[ECID:0000]ZTE_BSP maxiaoping 20140415 modify MSM8X10 alarm driver for power of charge,start.
		if ((alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP) &&
				(ANDROID_ALARM_BASE_CMD(cmd) ==
				 ANDROID_ALARM_SET(0)))
		{
			set_power_on_alarm(new_alarm_time.tv_sec, 1);
			/*printk("PM_DEBUG_MXP: RTC alarm type %d is set to %ld.%09ld\n", alarm_type,
*/	
		}
		//[ECID:0000]ZTE_BSP maxiaoping 20140415 modify MSM8X10 alarm driver for power of charge,end.
		mutex_unlock(&alarm_mutex);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rv = alarm_set_rtc(new_rtc_time);
		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv < 0)
			goto err1;
		break;
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
		case ANDROID_ALARM_RTC_POWEROFF_WAKEUP:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			tmp_time =
				ktime_to_timespec(alarm_get_elapsed_realtime());
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}
示例#2
0
int ip_options_compile(struct net *net,
		       struct ip_options * opt, struct sk_buff * skb)
{
	int l;
	unsigned char * iph;
	unsigned char * optptr;
	int optlen;
	unsigned char * pp_ptr = NULL;
	struct rtable *rt = NULL;

	if (skb != NULL) {
		rt = skb_rtable(skb);
		optptr = (unsigned char *)&(ip_hdr(skb)[1]);
	} else
		optptr = opt->__data;
	iph = optptr - sizeof(struct iphdr);

	for (l = opt->optlen; l > 0; ) {
		switch (*optptr) {
		      case IPOPT_END:
			for (optptr++, l--; l>0; optptr++, l--) {
				if (*optptr != IPOPT_END) {
					*optptr = IPOPT_END;
					opt->is_changed = 1;
				}
			}
			goto eol;
		      case IPOPT_NOOP:
			l--;
			optptr++;
			continue;
		}
		optlen = optptr[1];
		if (optlen<2 || optlen>l) {
			pp_ptr = optptr;
			goto error;
		}
		switch (*optptr) {
		      case IPOPT_SSRR:
		      case IPOPT_LSRR:
			if (optlen < 3) {
				pp_ptr = optptr + 1;
				goto error;
			}
			if (optptr[2] < 4) {
				pp_ptr = optptr + 2;
				goto error;
			}
			/* NB: cf RFC-1812 5.2.4.1 */
			if (opt->srr) {
				pp_ptr = optptr;
				goto error;
			}
			if (!skb) {
				if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) {
					pp_ptr = optptr + 1;
					goto error;
				}
				memcpy(&opt->faddr, &optptr[3], 4);
				if (optlen > 7)
					memmove(&optptr[3], &optptr[7], optlen-7);
			}
			opt->is_strictroute = (optptr[0] == IPOPT_SSRR);
			opt->srr = optptr - iph;
			break;
		      case IPOPT_RR:
			if (opt->rr) {
				pp_ptr = optptr;
				goto error;
			}
			if (optlen < 3) {
				pp_ptr = optptr + 1;
				goto error;
			}
			if (optptr[2] < 4) {
				pp_ptr = optptr + 2;
				goto error;
			}
			if (optptr[2] <= optlen) {
				if (optptr[2]+3 > optlen) {
					pp_ptr = optptr + 2;
					goto error;
				}
				if (skb) {
					memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
					opt->is_changed = 1;
				}
				optptr[2] += 4;
				opt->rr_needaddr = 1;
			}
			opt->rr = optptr - iph;
			break;
		      case IPOPT_TIMESTAMP:
			if (opt->ts) {
				pp_ptr = optptr;
				goto error;
			}
			if (optlen < 4) {
				pp_ptr = optptr + 1;
				goto error;
			}
			if (optptr[2] < 5) {
				pp_ptr = optptr + 2;
				goto error;
			}
			if (optptr[2] <= optlen) {
				__be32 *timeptr = NULL;
				if (optptr[2]+3 > optptr[1]) {
					pp_ptr = optptr + 2;
					goto error;
				}
				switch (optptr[3]&0xF) {
				      case IPOPT_TS_TSONLY:
					opt->ts = optptr - iph;
					if (skb)
						timeptr = (__be32*)&optptr[optptr[2]-1];
					opt->ts_needtime = 1;
					optptr[2] += 4;
					break;
				      case IPOPT_TS_TSANDADDR:
					if (optptr[2]+7 > optptr[1]) {
						pp_ptr = optptr + 2;
						goto error;
					}
					opt->ts = optptr - iph;
					if (skb) {
						memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
						timeptr = (__be32*)&optptr[optptr[2]+3];
					}
					opt->ts_needaddr = 1;
					opt->ts_needtime = 1;
					optptr[2] += 8;
					break;
				      case IPOPT_TS_PRESPEC:
					if (optptr[2]+7 > optptr[1]) {
						pp_ptr = optptr + 2;
						goto error;
					}
					opt->ts = optptr - iph;
					{
						__be32 addr;
						memcpy(&addr, &optptr[optptr[2]-1], 4);
						if (inet_addr_type(net, addr) == RTN_UNICAST)
							break;
						if (skb)
							timeptr = (__be32*)&optptr[optptr[2]+3];
					}
					opt->ts_needtime = 1;
					optptr[2] += 8;
					break;
				      default:
					if (!skb && !capable(CAP_NET_RAW)) {
						pp_ptr = optptr + 3;
						goto error;
					}
					break;
				}
				if (timeptr) {
					struct timespec tv;
					__be32  midtime;
					getnstimeofday(&tv);
					midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC);
					memcpy(timeptr, &midtime, sizeof(__be32));
					opt->is_changed = 1;
				}
			} else {
				unsigned overflow = optptr[3]>>4;
				if (overflow == 15) {
					pp_ptr = optptr + 3;
					goto error;
				}
				opt->ts = optptr - iph;
				if (skb) {
					optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
					opt->is_changed = 1;
				}
			}
			break;
		      case IPOPT_RA:
			if (optlen < 4) {
				pp_ptr = optptr + 1;
				goto error;
			}
			if (optptr[2] == 0 && optptr[3] == 0)
				opt->router_alert = optptr - iph;
			break;
		      case IPOPT_CIPSO:
			if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) {
				pp_ptr = optptr;
				goto error;
			}
			opt->cipso = optptr - iph;
			if (cipso_v4_validate(skb, &optptr)) {
				pp_ptr = optptr;
				goto error;
			}
			break;
		      case IPOPT_SEC:
		      case IPOPT_SID:
		      default:
			if (!skb && !capable(CAP_NET_RAW)) {
				pp_ptr = optptr;
				goto error;
			}
			break;
		}
		l -= optlen;
		optptr += optlen;
	}

eol:
	if (!pp_ptr)
		return 0;

error:
	if (skb) {
		icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
	}
	return -EINVAL;
}
示例#3
0
void fbtft_update_display(struct fbtft_par *par, unsigned start_line, unsigned end_line)
{
	size_t offset, len;
	struct timespec ts_start, ts_end, test_of_time;
	long ms, us, ns;
	bool timeit = false;
	int ret = 0;

	if (unlikely(par->debug & (DEBUG_TIME_FIRST_UPDATE | DEBUG_TIME_EACH_UPDATE))) {
		if ((par->debug & DEBUG_TIME_EACH_UPDATE) || \
				((par->debug & DEBUG_TIME_FIRST_UPDATE) && !par->first_update_done)) {
			getnstimeofday(&ts_start);
			timeit = true;
		}
	}

	/* Sanity checks */
	if (start_line > end_line) {
		dev_warn(par->info->device,
			"%s: start_line=%u is larger than end_line=%u. Shouldn't happen, will do full display update\n",
			__func__, start_line, end_line);
		start_line = 0;
		end_line = par->info->var.yres - 1;
	}
	if (start_line > par->info->var.yres - 1 || end_line > par->info->var.yres - 1) {
		dev_warn(par->info->device,
			"%s: start_line=%u or end_line=%u is larger than max=%d. Shouldn't happen, will do full display update\n",
			__func__, start_line, end_line, par->info->var.yres - 1);
		start_line = 0;
		end_line = par->info->var.yres - 1;
	}

	fbtft_par_dbg(DEBUG_UPDATE_DISPLAY, par, "%s(start_line=%u, end_line=%u)\n",
		__func__, start_line, end_line);

	if (par->fbtftops.set_addr_win)
		par->fbtftops.set_addr_win(par, 0, start_line,
				par->info->var.xres-1, end_line);

	offset = start_line * par->info->fix.line_length;
	len = (end_line - start_line + 1) * par->info->fix.line_length;
	ret = par->fbtftops.write_vmem(par, offset, len);
	if (ret < 0)
		dev_err(par->info->device,
			"%s: write_vmem failed to update display buffer\n",
			__func__);

	if (unlikely(timeit)) {
		getnstimeofday(&ts_end);
		test_of_time = timespec_sub(ts_end, ts_start);
		us = (test_of_time.tv_nsec / 1000) % 1000;
		ms = (test_of_time.tv_sec * 1000) + ((test_of_time.tv_nsec / 1000000) % 1000);
		ns = test_of_time.tv_nsec % 1000;
		dev_info(par->info->device,
			"Elapsed time for display update: %4lu.%.3lu%.3lu ms (fps: %2lu, lines=%u)\n",
			ms, us, ns,
			test_of_time.tv_nsec ? 1000000000 / test_of_time.tv_nsec : 0,
			end_line - start_line + 1);
		par->first_update_done = true;
	}
}
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	struct rtc_time new_rtc_tm;
	struct rtc_device *rtc_dev;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
	uint32_t alarm_type_mask = 1U << alarm_type;


	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
		return -EINVAL;

	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		switch (alarm_type) {
		case ANDROID_ALARM_POWER_UP:
			/* disable power up alarm interrupt */
			rv = alarm_irq_enable(0);
			break;
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
		case ANDROID_ALARM_SYSTEMTIME:
			spin_lock_irqsave(&alarm_slock, flags);
			pr_alarm(IO, "alarm %d clear\n", alarm_type);
			devalarm_try_to_cancel(&alarms[alarm_type]);
			if (alarm_pending) {
				alarm_pending &= ~alarm_type_mask;
				if (!alarm_pending && !wait_pending)
					wake_unlock(&alarm_wake_lock);
			}
			alarm_enabled &= ~alarm_type_mask;
			spin_unlock_irqrestore(&alarm_slock, flags);
			break;
		default:
			break;
		}

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

#if defined(CONFIG_RTC_CHN_ALARM_BOOT)
	case ANDROID_ALARM_SET_ALARM:
	{
		char bootalarm_data[14];

		if (copy_from_user(bootalarm_data, (void __user *)arg, 14)) {
			rv = -EFAULT;
			goto err1;
		}

		alarm_set_bootalarm(bootalarm_data);	

		break;
	}
#endif
	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
		alarm_enabled |= alarm_type_mask;
		devalarm_start(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time));
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (alarm_type == ANDROID_ALARM_POWER_UP)
			alarm_set_rtc_ring(new_alarm_time);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
		rtc_dev = alarmtimer_get_rtcdev();
		rv = do_settimeofday(&new_rtc_time);
		if (rv < 0)
			goto err1;
		if (rtc_dev)
			rv = rtc_set_time(rtc_dev, &new_rtc_tm);

		if (pwr_rtc_dev)
			rv = rtc_set_time(pwr_rtc_dev, &new_rtc_tm);

		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv < 0)
			goto err1;
		break;
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_POWER_UP:
		case ANDROID_ALARM_RTC:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			get_monotonic_boottime(&tmp_time);
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
	uint32_t alarm_type_mask = 1U << alarm_type;

	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
		return -EINVAL;

	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		alarm_try_to_cancel(&alarms[alarm_type]);
		if (alarm_pending) {
			alarm_pending &= ~alarm_type_mask;
			if (!alarm_pending && !wait_pending)
				wake_unlock(&alarm_wake_lock);
		}
		alarm_enabled &= ~alarm_type_mask;
		if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP)
			set_power_on_alarm(0);
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
		// ASUS_BSP+++ Shawn_Huang "Add debug log for setting alarm "
		ktime_get_ts(&tmp_time);
		printk("asus_alarm %d now %ld.%09ld, set %ld.%09ld\n", 
			alarm_type,
			tmp_time.tv_sec, tmp_time.tv_nsec,
			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
		// ASUS_BSP--- Shawn_Huang "Add debug log for setting alarm "
		alarm_enabled |= alarm_type_mask;
		alarm_start_range(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time),
			timespec_to_ktime(new_alarm_time));
		if ((alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP) &&
				(ANDROID_ALARM_BASE_CMD(cmd) ==
				 ANDROID_ALARM_SET(0)))
			set_power_on_alarm(new_alarm_time.tv_sec);
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rv = alarm_set_rtc(new_rtc_time);
		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
		spin_unlock_irqrestore(&alarm_slock, flags);
        { // jack added to get correct time for last shutdown log +++++++++++
            if(!asus_rtc_set)
            {  
                asus_rtc_set = 1;
            }
        }// jack added to get correct time for last shutdown log ------------		
		if (rv < 0)
			goto err1;
		break;
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
		case ANDROID_ALARM_RTC_POWEROFF_WAKEUP:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			tmp_time =
				ktime_to_timespec(alarm_get_elapsed_realtime());
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}
示例#6
0
// [email protected] 20110110 MUIC mode change in case of trap [START]
static void CP_CRASH_wq_func(struct work_struct *cp_crash_wq)
{
	volatile unsigned long *make_panic = 0;
	extern void set_muic_mode(u32 mode);
	int ret;
	
// CRASH TIME INFORMATION ADD. 2011-04-23 eunae.kim
	struct timespec ts;
	struct rtc_time tm;
	getnstimeofday(&ts);
	rtc_time_to_tm(ts.tv_sec, &tm);
	
	printk(KERN_INFO "[CP CRASH IRQ] CP_CRASH_wq_func()");	
	printk(KERN_INFO "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);	
// CHEOLGWAK  2011-5-14 delayed work queue
#ifdef CONFIG_MACH_LGE_COSMO_DOMASTIC
	if(!gpio_get_value(CP_CRASH_INT_N)){
#else
	if(gpio_get_value(CP_CRASH_INT_N)){
#endif
#if 0   // [email protected] prevent to make panic
		*make_panic = 0xDEAD;	
#endif
		//LGE_ChangeS [email protected] 20110131 CIQ [START]
		lge_store_ciq_reset(0, LGE_NVDATA_IQ_RESET_EXCEPTION);
		//LGE_ChangeS [email protected] 20110131 CIQ [END]

	// CHEOLGWAK  2011-2-26 CP_CRASH_COUNT
		{
			unsigned char data;
			lge_dynamic_nvdata_read(LGE_NVDATA_DYNAMIC_CP_CRASH_COUNT_OFFSET,&data,1);
			data++;
			lge_dynamic_nvdata_write(LGE_NVDATA_DYNAMIC_CP_CRASH_COUNT_OFFSET,&data,1);
		}
	// CHEOLGWAK  2011-2-26 CP_CRASH_COUNT

	// CHEOLGWAK  2011-2-28 

		// [email protected] 20110111 
		if (lge_is_crash_dump_enabled() != 1)
		{	
#ifndef ENABLE_CP_CRASH_RESET	//20110301 LGE_RIL_RECOVERY
			printk(" CP CRASH! immediate RIL/CP reset");
			input_report_key(in_dev, EVENT_KEY, 1);
			input_report_key(in_dev, EVENT_KEY, 0);
			input_sync(in_dev);
			printk("[CPW] input_report_key(): %d\n", EVENT_KEY);
#endif
			return;
		}

	// [email protected] 20110130 CP Crash Core Dump Season2 [START]
	//	set_muic_mode(7 /* MUIC_CP_UART */);
		printk(KERN_INFO "[CP CRASH IRQ] launch ifx_coredump process\n");	

	{
		char* argv[] = {"/system/bin/ifx_coredump", "CP_CRASH_IRQ", NULL};
		char *envp[] = { "HOME=/",	"PATH=/sbin:/bin:/system/bin",	NULL };	
		//@@ret = call_usermodehelper(argv[0], argv, envp, UMH_NO_WAIT);
		ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
		printk(KERN_INFO "[CP CRASH IRQ] launch ifx_coredump process ret:%d\n",ret);	
	}

		gpio_set_value(82, 1);

#if 0
		// LED toggle
		int toggle = 0;
		for(;;)
		{
			if(toggle == 0)
			{
				gpio_set_value(82, 1);
				toggle = 1;
			}
			else                                 
			{
				gpio_set_value(82, 0);
				toggle = 0;
			}
			msleep(100);
		}
#endif	
	// [email protected] 20110130 CP Crash Core Dump Season2 [END]
	}
	else
	{
		return;		
	}
// CHEOLGWAK  2011-5-14 delayed work queue
}

static irqreturn_t CP_CRASH_interrupt_handler(s32 irq, void *data)
{
	/* Make the interrupt on CP CRASH INT wake up OMAP which is in suspend mode */
// CHEOLGWAK  2011-5-14 delayed work queue
	//schedule_work(&CP_CRASH_INT_wq);
	schedule_delayed_work( &cp_crash_int_delayed_wq, msecs_to_jiffies(500));
// CHEOLGWAK  2011-5-14 delayed work queue
	return IRQ_HANDLED;
}
示例#7
0
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	struct rtc_time new_rtc_tm;
	struct rtc_device *rtc_dev;
	struct rtc_wkalrm pwron_alm;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
	uint32_t alarm_type_mask = 1U << alarm_type;

 	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT &&
	    alarm_type != ANDROID_ALARM_POWER_ON &&
	    alarm_type != ANDROID_ALARM_POWER_ON_LOGO) {
		return -EINVAL;
	}
	
	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		if (alarm_type == ANDROID_ALARM_POWER_ON ||
			alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
			new_alarm_time.tv_sec = 0;
			alarm_set_power_on(new_alarm_time, false);
			break;
		}
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		devalarm_try_to_cancel(&alarms[alarm_type]);
		if (alarm_pending) {
			alarm_pending &= ~alarm_type_mask;
			if (!alarm_pending && !wait_pending)
				wake_unlock(&alarm_wake_lock);
		}
		alarm_enabled &= ~alarm_type_mask;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
	//	pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
	//		new_alarm_time.tv_sec, new_alarm_time.tv_nsec);

		if (alarm_type == ANDROID_ALARM_POWER_ON) {
			alarm_set_power_on(new_alarm_time, false);
			break;
		}
		if (alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
			alarm_set_power_on(new_alarm_time, true);
			break;
		}
		spin_lock_irqsave(&alarm_slock, flags);
	
		alarm_enabled |= alarm_type_mask;
		devalarm_start(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time));
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
	//	pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
		
		pr_alarm(IO, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
		new_rtc_time.tv_sec, new_rtc_time.tv_nsec,
		new_rtc_tm.tm_hour, new_rtc_tm.tm_min,
		new_rtc_tm.tm_sec, new_rtc_tm.tm_mon + 1,
		new_rtc_tm.tm_mday,
		new_rtc_tm.tm_year + 1900);

		rtc_dev = alarmtimer_get_rtcdev();
		rv = do_settimeofday(&new_rtc_time);
		if (rv < 0)
		{	
			goto err1;
		}
		if (rtc_dev)
		{
			rv = rtc_set_time(rtc_dev, &new_rtc_tm);
		}
		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv < 0)
			goto err1;
		break;
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			get_monotonic_boottime(&tmp_time);
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		case ANDROID_ALARM_POWER_ON:
		case ANDROID_ALARM_POWER_ON_LOGO:
			break;		
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;
	case ANDROID_ALARM_GET_POWER_ON:
		alarm_get_power_on(&pwron_alm);
		if (copy_to_user((void __user *)arg, &pwron_alm,
		    sizeof(struct rtc_wkalrm))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}
示例#8
0
static inline void start_profile() {
	getnstimeofday(&start_ts);
}
示例#9
0
static inline void stop_profile() {
	getnstimeofday(&end_ts);
}
示例#10
0
DWORD BAHW_MyGetMSecs(void)
{
	struct timespec now;
	getnstimeofday(&now);
	return now.tv_sec * 1000 + now.tv_nsec / 1000000;
}
示例#11
0
u64 get_time_ns(void)
{
	struct timespec tsval;
	getnstimeofday(&tsval);
	return (u64)timespec_to_ns(&tsval);
}
示例#12
0
static void ramdump_get_time(void){
	getnstimeofday(&ts);
	rtc_time_to_tm(ts.tv_sec, &tm);
	sprintf(rd_kernel_time, "%d-%02d-%02d-%02d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
}
示例#13
0
文件: pm_cpuidle.c 项目: mozyg/kernel
static int omap3_enter_idle(struct cpuidle_device *dev,
			struct cpuidle_state *state)
{
	struct omap3_processor_cx *cx;
	struct timespec ts_preidle;
	struct timespec ts_postidle;
	struct timespec ts_idle;

	/* Used for LPR mode DSS context save/restore. */
	u32 pm_wken_dss      = 0;
	u32 pm_pwstctrl_dss  = 0;
	u32 cm_clkstctrl_dss = 0;
	u32 cm_fclken_dss    = 0;
	u32 cm_iclken_dss    = 0;
	u32 cm_autoidle_dss  = 0;

	u32 fclken_core;
	u32 iclken_core;
	u32 fclken_per;
	u32 iclken_per;

	int wakeup_latency;

	struct system_power_state target_state;
	struct system_power_state cur_state;

#ifdef CONFIG_HW_SUP_TRANS
	u32 sleepdep_per;
	u32 wakedep_per;
#endif /* #ifdef CONFIG_HW_SUP_TRANS */

	u32 sdrc_power_register = 0;
	int core_sleep_flg = 0;
	int got_console_lock = 0;

	/* Disable interrupts.
	 */
	local_irq_disable();
	local_fiq_disable();

	/* If need resched - return immediately
	 */ 
	if( need_resched()) {
		local_fiq_enable();
		local_irq_enable();
		return 0;
	}

	/* Reset previous power state registers.
	 */
	clear_prepwstst();

	omap3_idle_setup_wkup_sources ();
	
	/* Set up target state from state context provided by cpuidle.
	 */
	cx = cpuidle_get_statedata(state);
	target_state.mpu_state  = cx->mpu_state;
	target_state.core_state = cx->core_state;
	target_state.neon_state = 0; /* Avoid gcc warning. Will be set in
					adjust_target_states(). */

	/* take a time marker for residency.
	 */
	getnstimeofday(&ts_preidle);

	/* If the requested state is C0, we bail here...
	 */
	if (cx->type == OMAP3_STATE_C1) {
		omap_sram_idle(target_state.mpu_state);
		goto return_sleep_time;
	}

	if (cx->type > OMAP3_STATE_C2)
		sched_clock_idle_sleep_event(); /* about to enter deep idle */

	/* Adjust PER and NEON domain target states as well as CORE domain
	 * target state depending on MPU/CORE setting, enable_off sysfs entry
	 * and PER timer status.
	 */
	adjust_target_states(&target_state);

	wakeup_latency = cx->wakeup_latency;
	/* NOTE:
	 *   We will never get the condition below as we are not supporting
	 *   CORE OFF right now. Keeping this code around for future reference.
	 */
	if (target_state.core_state != cx->core_state) {
		/* Currently, this can happen only for core_off. Adjust wakeup
		 * latency to that of core_cswr state. Hard coded now and needs
		 * to be made more generic omap3_power_states[4] is CSWR for
		 * core */
		wakeup_latency = omap3_power_states[4].wakeup_latency;
	}

	/* Reprogram next wake up tick to adjust for wake latency */
	if (wakeup_latency > 1000) {
		struct tick_device *d = tick_get_device(smp_processor_id());
		ktime_t now = ktime_get();

		if (ktime_to_ns(ktime_sub(d->evtdev->next_event, now)) >
					(wakeup_latency * 1000 + NSEC_PER_MSEC)) {
			ktime_t adjust = ktime_set(0, (wakeup_latency * 1000));
			ktime_t next   = ktime_sub(d->evtdev->next_event, adjust);
			clockevents_program_event(d->evtdev, next, now);
		}
	}

	/* Check for pending interrupts. If there is an interrupt, return */
	if (INTCPS_PENDING_IRQ0 | INTCPS_PENDING_IRQ1 | INTCPS_PENDING_IRQ2)
		goto return_sleep_time;


	/* Remember the current power states and clock settings.
	 */
	prcm_get_power_domain_state(DOM_PER,  &cur_state.per_state);
	prcm_get_power_domain_state(DOM_CAM,  &cur_state.cam_state);
	prcm_get_power_domain_state(DOM_SGX,  &cur_state.sgx_state);
	prcm_get_power_domain_state(DOM_NEON, &cur_state.neon_state);

	fclken_core = CM_FCLKEN1_CORE;
	iclken_core = CM_ICLKEN1_CORE;
	fclken_per  = CM_FCLKEN_PER;
	iclken_per  = CM_ICLKEN_PER;

#ifdef CONFIG_HW_SUP_TRANS
	/* Facilitating SWSUP RET, from HWSUP mode */
	sleepdep_per = CM_SLEEPDEP_PER;
	wakedep_per  = PM_WKDEP_PER;
#endif /* #ifdef CONFIG_HW_SUP_TRANS */

	/* If target state if core_off, save registers before changing
	 * anything.
	 */
	if (target_state.core_state >= PRCM_CORE_OSWR_MEMRET) {
		prcm_save_registers();
	}

	/* Check for pending interrupts. If there is an interrupt, return */
	if (INTCPS_PENDING_IRQ0 | INTCPS_PENDING_IRQ1 | INTCPS_PENDING_IRQ2)
		goto return_sleep_time;


	/* Program MPU and NEON to target state */
	if (target_state.mpu_state > PRCM_MPU_ACTIVE) {
		if ((cur_state.neon_state == PRCM_ON) &&
		    (target_state.neon_state != PRCM_ON)) {

			if (target_state.neon_state == PRCM_OFF)
				omap3_save_neon_context();

			prcm_transition_domain_to(DOM_NEON, target_state.neon_state);
		}
#ifdef _disabled_CONFIG_MPU_OFF
		/* Populate scratchpad restore address */
		scratchpad_set_restore_addr();
#endif
		/* TODO No support for OFF Mode yet
		if(target_state.core_state > PRCM_CORE_CSWR_MEMRET)
			omap3_save_secure_ram_context(target_state.core_state);
		*/
		prcm_set_mpu_domain_state(target_state.mpu_state);
	}

	/* Check for pending interrupts. If there is an interrupt, return */
	if (INTCPS_PENDING_IRQ0 | INTCPS_PENDING_IRQ1 | INTCPS_PENDING_IRQ2)
		goto restore;


	/* Program CORE and PER to target state */
	if (target_state.core_state > PRCM_CORE_ACTIVE) {
		/* Log core sleep attempt */
		core_sleep_flg = 1;

		/* Lock the console to prevent potential access to UARTs.
		 */
		if (0 == try_acquire_console_sem()) {
			got_console_lock = 1;
		}

		/* Handle PER, CAM and SGX domains. */
		if ((cur_state.per_state == PRCM_ON) &&
		    (target_state.per_state != PRCM_ON)) {

			if (target_state.per_state == PRCM_OFF) {
				omap3_save_per_context();
			}

			prcm_transition_domain_to(DOM_PER, target_state.per_state);
		}
		if (PRCM_ON == cur_state.cam_state)
			prcm_transition_domain_to(DOM_CAM, PRCM_RET);
		if (PRCM_ON == cur_state.sgx_state)
			prcm_transition_domain_to(DOM_SGX, PRCM_RET);

		disable_smartreflex(SR1_ID);
		disable_smartreflex(SR2_ID);

		prcm_set_core_domain_state(target_state.core_state);

		/* Enable Autoidle for GPT1 explicitly - Errata 1.4 */
		CM_AUTOIDLE_WKUP |= 0x1;

		/* Disable HSUSB OTG ICLK explicitly*/
		CM_ICLKEN1_CORE &= ~0x10;

		/* Enabling GPT1 wake-up capabilities */
		PM_WKEN_WKUP |= 0x1;

		/* Errata 2.15
		 * Configure UARTs to ForceIdle. Otherwise they can prevent
		 * CORE RET.
		 */
		omap24xx_uart_set_force_idle();

		CM_ICLKEN1_CORE &= ~(1<<7); /* MAILBOXES */
		CM_ICLKEN1_CORE &= ~(1<<6); /* OMAPCTRL */

		/* If we are in LPR mode we need to set up DSS accordingly.
		 */
		if (omap2_disp_lpr_is_enabled()) {
			pm_wken_dss      = PM_WKEN_DSS;
			pm_pwstctrl_dss  = PM_PWSTCTRL_DSS;
			cm_clkstctrl_dss = CM_CLKSTCTRL_DSS;
			cm_fclken_dss    = CM_FCLKEN_DSS;
			cm_iclken_dss    = CM_ICLKEN_DSS;
			cm_autoidle_dss  = CM_AUTOIDLE_DSS;
			PM_WKEN_DSS      = 0x00000001;
			PM_PWSTCTRL_DSS  = 0x00030107;
			CM_CLKSTCTRL_DSS = 0x00000003;
			CM_FCLKEN_DSS    = 0x00000001;
			CM_ICLKEN_DSS    = 0x00000001;
			CM_AUTOIDLE_DSS  = 0x00000001;
		}
	}

	/* Check for pending interrupts. If there is an interrupt, return */
	if (INTCPS_PENDING_IRQ0 | INTCPS_PENDING_IRQ1 | INTCPS_PENDING_IRQ2)
		goto restore;

#ifdef CONFIG_DISABLE_HFCLK
	PRM_CLKSRC_CTRL |= 0x18; /* set sysclk to stop */
#endif /* #ifdef CONFIG_DISABLE_HFCLK */


	DEBUG_STATE_CAPTURE();


	/* Errata 1.142:
	 * SDRC not sending auto-refresh when OMAP wakes-up from OFF mode
	 */
	if (!is_device_type_gp() && is_sil_rev_equal_to(OMAP3430_REV_ES3_0)) {
		sdrc_power_register = SDRC_POWER_REG;
		SDRC_POWER_REG &= ~(SDRC_PWR_AUTOCOUNT_MASK | SDRC_PWR_CLKCTRL_MASK);
		SDRC_POWER_REG |= 0x120;
		if (target_state.core_state == PRCM_CORE_OFF)
			save_scratchpad_contents();
	}

	omap_sram_idle(target_state.mpu_state);

	/* Errata 1.142:
	 * SDRC not sending auto-refresh when OMAP wakes-up from OFF mode
	 */
	if (!is_device_type_gp() && is_sil_rev_equal_to(OMAP3430_REV_ES3_0))
		SDRC_POWER_REG = sdrc_power_register;

restore:
#ifdef CONFIG_DISABLE_HFCLK
	PRM_CLKSRC_CTRL &= ~0x18;
#endif /* #ifdef CONFIG_DISABLE_HFCLK */
	/* Disabling IO_PAD capabilities */
	PM_WKEN_WKUP &= ~(0x100);

	CM_FCLKEN1_CORE = fclken_core;
	CM_ICLKEN1_CORE = iclken_core;

	if (target_state.mpu_state > PRCM_MPU_ACTIVE) {
#ifdef _disabled_CONFIG_MPU_OFF
		/* On ES 2.0, if scratchpad is populated with valid pointer,
		 * warm reset does not work So populate scratchpad restore
		 * address only in cpuidle and suspend calls
		*/
		scratchpad_clr_restore_addr();
#endif
		prcm_set_mpu_domain_state(PRCM_MPU_ACTIVE);

		if ((cur_state.neon_state == PRCM_ON) &&
		    (target_state.mpu_state > PRCM_MPU_INACTIVE)) {
			u8 pre_state;

			prcm_force_power_domain_state(DOM_NEON, cur_state.neon_state);
			prcm_get_pre_power_domain_state(DOM_NEON, &pre_state);

			if (pre_state == PRCM_OFF) {
				omap3_restore_neon_context();
			}

#ifdef CONFIG_HW_SUP_TRANS
			prcm_set_power_domain_state(DOM_NEON, POWER_DOMAIN_ON,
								PRCM_AUTO);
#endif
		}
	}

	/* Continue core restoration part, only if Core-Sleep is attempted */
	if ((target_state.core_state > PRCM_CORE_ACTIVE) && core_sleep_flg) {
		u8 pre_per_state;

		prcm_set_core_domain_state(PRCM_CORE_ACTIVE);

		omap24xx_uart_clr_force_idle();

		enable_smartreflex(SR1_ID);
		enable_smartreflex(SR2_ID);

		/* Turn PER back ON if it was ON before idle.
		 */
		if (cur_state.per_state == PRCM_ON) {
			prcm_force_power_domain_state(DOM_PER, cur_state.per_state);

			CM_ICLKEN_PER = iclken_per;
			CM_FCLKEN_PER = fclken_per;

			prcm_get_pre_power_domain_state(DOM_PER, &pre_per_state);
			if (pre_per_state == PRCM_OFF) {
				omap3_restore_per_context();
#ifdef CONFIG_OMAP34XX_OFFMODE
				context_restore_update(DOM_PER);
#endif
			}

#ifdef CONFIG_HW_SUP_TRANS
			/* Facilitating SWSUP RET, from HWSUP mode */
			CM_SLEEPDEP_PER = sleepdep_per;
			PM_WKDEP_PER    = wakedep_per;
			prcm_set_power_domain_state(DOM_PER, PRCM_ON, PRCM_AUTO);
#endif
		}

		/* Restore CAM and SGX. */
		if (PRCM_ON == cur_state.cam_state)
			prcm_transition_domain_to(DOM_CAM, PRCM_ON);
		if (PRCM_ON == cur_state.sgx_state)
			prcm_transition_domain_to(DOM_SGX, PRCM_ON);

		/* If we lost CORE context, restore it.
		 */
		if (target_state.core_state >= PRCM_CORE_OSWR_MEMRET) {
#ifdef CONFIG_OMAP34XX_OFFMODE
			context_restore_update(DOM_CORE1);
#endif
			prcm_restore_registers();
			prcm_restore_core_context(target_state.core_state);
#ifdef CONFIG_CORE_OFF
			omap3_restore_core_settings();
#endif
		}

		/* Restore DSS settings */
		if (omap2_disp_lpr_is_enabled()) {
			PM_WKEN_DSS      = pm_wken_dss;
			PM_PWSTCTRL_DSS  = pm_pwstctrl_dss;
			CM_CLKSTCTRL_DSS = cm_clkstctrl_dss;
			CM_FCLKEN_DSS    = cm_fclken_dss;
			CM_ICLKEN_DSS    = cm_iclken_dss;
			CM_AUTOIDLE_DSS  = cm_autoidle_dss;
		}

		/* At this point CORE and PER domain are back. We can release
		 * the console if we have it.
		 */
		if (got_console_lock) {
			release_console_sem();
		}

#ifdef CONFIG_OMAP_32K_TIMER
		/* Errata 1.4
		 * If a General Purpose Timer (GPTimer) is in posted mode
		 * (TSIRC.POSTED=1), due to internal resynchronizations, values
		 * read in TCRR, TCAR1 and TCAR2 registers right after the
		 * timer interface clock (L4) goes from stopped to active may
		 * not return the expected values. The most common event
		 * leading to this situation occurs upon wake up from idle.
		 *
		 * Software has to wait at least (2 timer interface clock
		 * cycles + 1 timer functional clock cycle) after L4 clock
		 * wakeup before reading TCRR, TCAR1 or TCAR2 registers for
		 * GPTimers in POSTED internal synchro- nization mode, and
		 * before reading WCRR register of the Watchdog timers . The
		 * same workaround must be applied before reading CR and
		 * 32KSYNCNT_REV registers of the synctimer module.
		 *
		 * Wait Period = 2 timer interface clock cycles +
		 *               1 timer functional clock cycle
		 * Interface clock  = L4 clock (50MHz worst case).
		 * Functional clock = 32KHz
		 * Wait Period = 2*10^-6/50 + 1/32768 = 0.000030557 = 30.557us
		 * Rounding off the delay value to a safer 50us.
		 */
		udelay(GPTIMER_WAIT_DELAY);
#endif

		/* Disable autoidling of GPT1.
		 */
		CM_AUTOIDLE_WKUP &= ~(0x1);
	}

	DPRINTK("MPU state:%x, CORE state:%x\n",
			PM_PREPWSTST_MPU, PM_PREPWSTST_CORE);

	/* Do wakeup event check s*/
	post_uart_activity();

	/* Update stats for sysfs entries.
	 */
	store_prepwst();

return_sleep_time:
	getnstimeofday(&ts_postidle);
#if defined(CONFIG_SYSFS) && defined(DEBUG_BAIL_STATS)
	ts_last_wake_up = ts_postidle;
#endif
	ts_idle = timespec_sub(ts_postidle, ts_preidle);

	if (cx->type > OMAP3_STATE_C2)
		sched_clock_idle_wakeup_event(timespec_to_ns(&ts_idle));


	DEBUG_STATE_PRINT(core_sleep_flg);


	local_irq_enable();
	local_fiq_enable();

	return (u32)timespec_to_ns(&ts_idle)/1000;
}
示例#14
0
static int msm_voice_put(struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
{
	int rc = 0;
	uint32_t rx_dev_id;
	uint32_t tx_dev_id;
	struct msm_snddev_info *rx_dev_info;
	struct msm_snddev_info *tx_dev_info;
	int set = ucontrol->value.integer.value[2];
	u32 session_mask;

	int i = 0, j = 0;
	struct snddev_icodec_state *icodec;
	struct adie_codec_hwsetting_entry *rx_entry;
	struct adie_codec_hwsetting_entry *tx_entry;
	struct timespec ts;
	struct rtc_time tm;

	/* if (!set)
		return -EPERM; */

	pr_aud_info("[ALSA] msm_route_voice: "
		"tx %d, rx %d, set %d\n",
		(int) ucontrol->value.integer.value[1],
		(int) ucontrol->value.integer.value[0],
		set);

	if (set) {
		getnstimeofday(&ts);
		rtc_time_to_tm(ts.tv_sec, &tm);
		pr_aud_info1("[ATS][phonecall_start][successful] at %lld (%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
		ktime_to_ns(ktime_get()),
		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
		tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
	} else {
		getnstimeofday(&ts);
		rtc_time_to_tm(ts.tv_sec, &tm);
		pr_aud_info1("[ATS][phonecall_end][successful] at %lld (%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
		ktime_to_ns(ktime_get()),
		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
		tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
	}

	/* Rx Device Routing */
	rx_dev_id = ucontrol->value.integer.value[0];
	rx_dev_info = audio_dev_ctrl_find_dev(rx_dev_id);

	if (IS_ERR(rx_dev_info)) {
		MM_AUD_ERR("pass invalid dev_id\n");
		rc = PTR_ERR(rx_dev_info);
		return rc;
	}

	if (!(rx_dev_info->capability & SNDDEV_CAP_RX)) {
		MM_AUD_ERR("First Dev is supposed to be RX\n");
		return -EFAULT;
	}

	MM_DBG("route cfg %d STREAM_VOICE_RX type\n",
		rx_dev_id);

	/* replace with Rx voice/media setting for adie */
	if (rx_dev_info->acdb_id != 10 &&
	    (rx_dev_info->acdb_id < 1000)) {
	    icodec = (struct snddev_icodec_state *)rx_dev_info->private_data;
	    rx_entry = icodec->data->profile->settings;
	    j = icodec->data->profile->setting_sz;
	    if (set) {
		for (i = 0; i < j; i++)
		    if (rx_entry[i].voc_action != NULL) {
			rx_entry[i].actions = rx_entry[i].voc_action;
			rx_entry[i].action_sz = rx_entry[i].voc_action_sz;
		    }
	    } else {
		for (i = 0; i < j; i++)
		    if (rx_entry[i].midi_action != NULL) {
			rx_entry[i].actions = rx_entry[i].midi_action;
			rx_entry[i].action_sz = rx_entry[i].midi_action_sz;
		    }
	    }
	}

	msm_set_voc_route(rx_dev_info, AUDIO_ROUTE_STREAM_VOICE_RX,
				rx_dev_id);

	session_mask =	0x1 << (8 * ((int)AUDDEV_CLNT_VOC-1));

	/* Tx Device Routing */
	tx_dev_id = ucontrol->value.integer.value[1];
	tx_dev_info = audio_dev_ctrl_find_dev(tx_dev_id);

	if (IS_ERR(tx_dev_info)) {
		MM_AUD_ERR("pass invalid dev_id\n");
		rc = PTR_ERR(tx_dev_info);
		return rc;
	}

	if (!(tx_dev_info->capability & SNDDEV_CAP_TX)) {
		MM_AUD_ERR("Second Dev is supposed to be Tx\n");
		return -EFAULT;
	}

	MM_DBG("route cfg %d %d type\n",
		tx_dev_id, AUDIO_ROUTE_STREAM_VOICE_TX);
	/* replace with Tx voice/media setting for adie */
	if (tx_dev_info->acdb_id != 9 &&
	    (tx_dev_info->acdb_id < 1000)) {
	    icodec = (struct snddev_icodec_state *)tx_dev_info->private_data;
	    tx_entry = icodec->data->profile->settings;
	    j = icodec->data->profile->setting_sz;
	    if (set) {
		for (i = 0; i < j; i++)
		    if (tx_entry[i].voc_action != NULL) {
			tx_entry[i].actions = tx_entry[i].voc_action;
			tx_entry[i].action_sz = tx_entry[i].voc_action_sz;
		    }
	    } else {
		for (i = 0; i < j; i++)
		    if (tx_entry[i].midi_action != NULL) {
			tx_entry[i].actions = tx_entry[i].midi_action;
			tx_entry[i].action_sz = tx_entry[i].midi_action_sz;
		    }
	    }
	}
	msm_set_voc_route(tx_dev_info, AUDIO_ROUTE_STREAM_VOICE_TX,
				tx_dev_id);

	broadcast_event(AUDDEV_EVT_DEV_CHG_VOICE, tx_dev_id, session_mask);

	if (set) {
	if (rx_dev_info->opened)
		broadcast_event(AUDDEV_EVT_DEV_RDY, rx_dev_id,	session_mask);

	if (tx_dev_info->opened)
		broadcast_event(AUDDEV_EVT_DEV_RDY, tx_dev_id, session_mask);
	}

	return rc;
}
示例#15
0
static int __init rtc_hctosys(void)
{
	int err = -ENODEV;
	struct rtc_time tm;
	struct timespec tv = {
		.tv_nsec = NSEC_PER_SEC >> 1,
	};
	struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);

	if (rtc == NULL) {
		pr_err("%s: unable to open rtc device (%s)\n",
			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
		goto err_open;
	}

	err = rtc_read_time(rtc, &tm);
	if (err) {
		dev_err(rtc->dev.parent,
			"hctosys: unable to read the hardware clock\n");
		goto err_read;

	}

	err = rtc_valid_tm(&tm);
	if (err) {
		dev_err(rtc->dev.parent,
			"hctosys: invalid date/time\n");
		goto err_invalid;
	}

	rtc_tm_to_time(&tm, &tv.tv_sec);

	do_settimeofday(&tv);

	//                                                              
	#if 1
	{
		struct timespec ts;
		getnstimeofday(&ts);
		printk(KERN_UTC_BOOT "%d-%02d-%02d %02d:%02d:%02d.%06lu\n",
			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec/1000);
	}
	#else
	//                                                            
	dev_info(rtc->dev.parent,
		"setting system clock to "
		"%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n",
		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
		tm.tm_hour, tm.tm_min, tm.tm_sec,
		(unsigned int) tv.tv_sec);
	#endif

err_invalid:
err_read:
	rtc_class_close(rtc);

err_open:
	rtc_hctosys_ret = err;

	return err;
}

late_initcall(rtc_hctosys);
/*
 * This function executes in interrupt context.
 */
static int msm_isp_notify_vfe(struct v4l2_subdev *sd,
                              unsigned int notification,  void *arg)
{
    int rc = 0;
    struct v4l2_event v4l2_evt;
    struct msm_isp_event_ctrl *isp_event;
    struct msm_cam_media_controller *pmctl =
        (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
    struct msm_free_buf buf;

    if (!pmctl) {
        pr_err("%s: no context in dsp callback.\n", __func__);
        rc = -EINVAL;
        return rc;
    }

    if (notification == NOTIFY_VFE_BUF_EVT)
        return msm_isp_notify_VFE_BUF_EVT(sd, arg);

    if (notification == NOTIFY_VFE_BUF_FREE_EVT)
        return msm_isp_notify_VFE_BUF_FREE_EVT(sd, arg);

    isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC);
    if (!isp_event) {
        pr_err("%s Insufficient memory. return", __func__);
        return -ENOMEM;
    }

    v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
                    MSM_CAM_RESP_STAT_EVT_MSG;
    v4l2_evt.id = 0;

    *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;

    isp_event->resptype = MSM_CAM_RESP_STAT_EVT_MSG;
    isp_event->isp_data.isp_msg.type = MSM_CAMERA_MSG;
    isp_event->isp_data.isp_msg.len = 0;

    switch (notification) {
    case NOTIFY_ISP_MSG_EVT: {
        struct isp_msg_event *isp_msg = (struct isp_msg_event *)arg;

        isp_event->isp_data.isp_msg.msg_id = isp_msg->msg_id;
        isp_event->isp_data.isp_msg.frame_id = isp_msg->sof_count;
        getnstimeofday(&(isp_event->isp_data.isp_msg.timestamp));
        break;
    }
    case NOTIFY_VFE_MSG_OUT: {
        uint8_t msgid;
        struct isp_msg_output *isp_output =
            (struct isp_msg_output *)arg;
        switch (isp_output->output_id) {
        case MSG_ID_OUTPUT_P:
            msgid = VFE_MSG_OUTPUT_P;
            break;
        case MSG_ID_OUTPUT_V:
            msgid = VFE_MSG_OUTPUT_V;
            break;
        case MSG_ID_OUTPUT_T:
            msgid = VFE_MSG_OUTPUT_T;
            break;
        case MSG_ID_OUTPUT_S:
            msgid = VFE_MSG_OUTPUT_S;
            break;
        case MSG_ID_OUTPUT_PRIMARY:
            msgid = VFE_MSG_OUTPUT_PRIMARY;
            break;
        case MSG_ID_OUTPUT_SECONDARY:
            msgid = VFE_MSG_OUTPUT_SECONDARY;
            break;
        case MSG_ID_OUTPUT_TERTIARY1:
            msgid = VFE_MSG_OUTPUT_TERTIARY1;
            break;
        case MSG_ID_OUTPUT_TERTIARY2:
            msgid = VFE_MSG_OUTPUT_TERTIARY2;
            break;
        default:
            pr_err("%s: Invalid VFE output id: %d\n",
                   __func__, isp_output->output_id);
            rc = -EINVAL;
            break;
        }

        if (!rc) {
            isp_event->isp_data.isp_msg.msg_id =
                isp_output->output_id;
            isp_event->isp_data.isp_msg.frame_id =
                isp_output->frameCounter;
            buf = isp_output->buf;
            msgid = msm_isp_vfe_msg_to_img_mode(pmctl, msgid);
            BUG_ON(msgid < 0);
            msm_mctl_buf_done(pmctl, msgid,
                              &buf, isp_output->frameCounter);
        }
    }
    break;
    case NOTIFY_VFE_MSG_COMP_STATS: {
        struct msm_stats_buf *stats = (struct msm_stats_buf *)arg;
        struct msm_stats_buf *stats_buf = NULL;

        isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE;
        stats->aec.buff = msm_pmem_stats_ptov_lookup(pmctl,
                          stats->aec.buff, &(stats->aec.fd));
        stats->awb.buff = msm_pmem_stats_ptov_lookup(pmctl,
                          stats->awb.buff, &(stats->awb.fd));
        stats->af.buff = msm_pmem_stats_ptov_lookup(pmctl,
                         stats->af.buff, &(stats->af.fd));
        stats->ihist.buff = msm_pmem_stats_ptov_lookup(pmctl,
                            stats->ihist.buff, &(stats->ihist.fd));
        stats->rs.buff = msm_pmem_stats_ptov_lookup(pmctl,
                         stats->rs.buff, &(stats->rs.fd));
        stats->cs.buff = msm_pmem_stats_ptov_lookup(pmctl,
                         stats->cs.buff, &(stats->cs.fd));

        stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC);
        if (!stats_buf) {
            pr_err("%s: out of memory.\n", __func__);
            rc = -ENOMEM;
        } else {
            *stats_buf = *stats;
            isp_event->isp_data.isp_msg.len	=
                sizeof(struct msm_stats_buf);
            isp_event->isp_data.isp_msg.data = stats_buf;
        }
    }
    break;
    case NOTIFY_VFE_MSG_STATS: {
        struct msm_stats_buf stats;
        struct isp_msg_stats *isp_stats = (struct isp_msg_stats *)arg;

        isp_event->isp_data.isp_msg.msg_id = isp_stats->id;
        isp_event->isp_data.isp_msg.frame_id =
            isp_stats->frameCounter;
        stats.buffer = msm_pmem_stats_ptov_lookup(pmctl,
                       isp_stats->buffer,
                       &(stats.fd));
        switch (isp_stats->id) {
        case MSG_ID_STATS_AEC:
            stats.aec.buff = stats.buffer;
            stats.aec.fd = stats.fd;
            break;
        case MSG_ID_STATS_AF:
            stats.af.buff = stats.buffer;
            stats.af.fd = stats.fd;
            break;
        case MSG_ID_STATS_AWB:
            stats.awb.buff = stats.buffer;
            stats.awb.fd = stats.fd;
            break;
        case MSG_ID_STATS_IHIST:
            stats.ihist.buff = stats.buffer;
            stats.ihist.fd = stats.fd;
            break;
        case MSG_ID_STATS_RS:
            stats.rs.buff = stats.buffer;
            stats.rs.fd = stats.fd;
            break;
        case MSG_ID_STATS_CS:
            stats.cs.buff = stats.buffer;
            stats.cs.fd = stats.fd;
            break;
        case MSG_ID_STATS_AWB_AEC:
            break;
        default:
            pr_err("%s: Invalid msg type", __func__);
            break;
        }
        if (!stats.buffer) {
            pr_err("%s: msm_pmem_stats_ptov_lookup error\n",
                   __func__);
            isp_event->isp_data.isp_msg.len = 0;
            rc = -EFAULT;
        } else {
            struct msm_stats_buf *stats_buf =
                kmalloc(sizeof(struct msm_stats_buf),
                        GFP_ATOMIC);
            if (!stats_buf) {
                pr_err("%s: out of memory.\n",
                       __func__);
                rc = -ENOMEM;
            } else {
                *stats_buf = stats;
                isp_event->isp_data.isp_msg.len	=
                    sizeof(struct msm_stats_buf);
                isp_event->isp_data.isp_msg.data = stats_buf;
            }
        }
    }
    break;
    default:
        pr_err("%s: Unsupport isp notification %d\n",
               __func__, notification);
        rc = -EINVAL;
        break;
    }

    v4l2_event_queue(pmctl->config_device->config_stat_event_queue.pvdev,
                     &v4l2_evt);

    return rc;
}
示例#17
0
int enter_lowpm(struct cpuidle_device *dev,
			struct cpuidle_state *state)
{
	int icanidle = 0;
	int idle_time;
	int cpu_id = 0;
	int cpu_idle_flag = IDLE_DISABLE;
	struct cpuidle_state *new_state = state;
	struct timeval before, after;
    int enter_state;
    struct timespec t;
	unsigned int timer_id = 0;
	unsigned int schedule_time = 0xffffffff;
    unsigned int expected_us;

    local_irq_disable();
    cpu_id = get_cpu();
    put_cpu();
    if(get_enter_state(state, &enter_state) != 0)
    {
        local_irq_enable();
        return 0;
    }

    /* Used to keep track of the total time in idle */
	getnstimeofday(&before);

    #if 1
    /*启动过程中不允许ACPU下电*/
    /*if((CPU_IDLE_C1 <= enter_state)&&(CPU_IDLE_C3 >= enter_state)&&(before.tv_sec < IDLE_ACTIVE_DELAY_S))*/
    if((CPU_IDLE_C1 <= enter_state)&&(CPU_IDLE_C3 >= enter_state)&&(0 == g_pwc_init_flag))
    {
        PRINT_PWC_DBG(PWC_SWITCH_CPUIDLE,"before.tv_sec:0x%x\n",before.tv_sec);

        local_irq_enable();
        return 0;
    }
    #endif

    if((RET_OK == pwrctrl_is_func_on(PWC_SWITCH_CPUIDLE))&&((CPU_IDLE_C0 < enter_state)&&(CPU_IDLE_C4 > enter_state))&&(0 == cpu_id))
    {
        cpu_idle_flag = IDLE_ENABLE;
    }
    else
    {
        cpu_idle_flag = IDLE_DISABLE;
    }


    /*C3起定时器来唤醒 后续可优化*/
    if((enter_state >= CPU_IDLE_C3)&&(IDLE_ENABLE == cpu_idle_flag))
    {
        pwrctrl_sleep_mgr_get_next_schedule_time(0, &timer_id, &schedule_time);

        if(schedule_time > (0xFFFFFFFF / 1000))
        {
            schedule_time = 0xFFFFFFFF;
        }
        else
        {
            schedule_time *= USEC_PER_MSEC;
        }
        /*C3停止所有TCXO定时器,待优化*/

    	/* determine the expected residency time, round up */
    	t = ktime_to_timespec(tick_nohz_get_sleep_length());
    	expected_us = t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC;

        if(schedule_time < expected_us)
        {
            PRINT_PWC_DBG(PWC_SWITCH_CPUIDLE,"enter_lowpm,system time:%d private time:%d\n",expected_us, schedule_time);
            expected_us = schedule_time;
        }

        expected_us -= state->exit_latency;
        DRV_TIMER_STOP(CPU_IDLE_TIMER);
        DRV_TIMER_START((unsigned int)CPU_IDLE_TIMER, cpu_idle_timer_isr, (int)0, (expected_us / MSEC_PER_SEC), TIMER_ONCE_COUNT, TIMER_UNIT_MS);
    }


    if(IDLE_ENABLE == cpu_idle_flag)
    {
        *gp_cpuidle_state = (enter_state << CPUIDLE_STATE_START_BIT) | (CPU_IDLE_STAT_VALID << CPUIDLE_STATE_MAGIC_START_BIT);
        /*pwrctrl_wdt_disable();*/
    }

    if(0 == cpu_id)
    {
        PRINT_PWC_DBG(PWC_SWITCH_CPUIDLE,"system will enter cpuidle state(%d)\n",enter_state);
    }

    if(CPU_IDLE_C0 == enter_state)
    {
        cpu_do_idle();
    }
    else if(IDLE_ENABLE == cpu_idle_flag)
    {
        pwrctrl_deep_sleep();
    }

    if(enter_state >= SPECIAL_HANDLE_STATE)
    {
        /*清除timer中断*/
        /*C3恢复之前停止所有TCXO定时器,待优化*/
    }

    if(IDLE_ENABLE == cpu_idle_flag)
    {
        *gp_cpuidle_state = (CPU_IDLE_C4 << CPUIDLE_STATE_START_BIT) | (CPU_IDLE_STAT_VALID << CPUIDLE_STATE_MAGIC_START_BIT);
        /*pwrctrl_wdt_enable();*/
    }

    getnstimeofday(&after);

    idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
		    (after.tv_usec - before.tv_usec);
    local_irq_enable();

	return idle_time;
}
示例#18
0
/**
 * ecryptfs_readdir
 * @file: The eCryptfs directory file
 * @ctx: The actor to feed the entries to
 */
static int ecryptfs_readdir(struct file *file, struct dir_context *ctx)
{
	int rc;
	struct file *lower_file;
	struct inode *inode = file_inode(file);
	struct ecryptfs_getdents_callback buf = {
		.ctx.actor = ecryptfs_filldir,
		.caller = ctx,
		.sb = inode->i_sb,
	};
	lower_file = ecryptfs_file_to_lower(file);
	lower_file->f_pos = ctx->pos;
	rc = iterate_dir(lower_file, &buf.ctx);
	ctx->pos = buf.ctx.pos;
	if (rc < 0)
		goto out;
	if (buf.filldir_called && !buf.entries_written)
		goto out;
	if (rc >= 0)
		fsstack_copy_attr_atime(inode,
					file_inode(lower_file));
out:
	return rc;
}

struct kmem_cache *ecryptfs_file_info_cache;

static int read_or_initialize_metadata(struct dentry *dentry)
{
	struct inode *inode = dentry->d_inode;
	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
	struct ecryptfs_crypt_stat *crypt_stat;
	int rc;

	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
	mount_crypt_stat = &ecryptfs_superblock_to_private(
						inode->i_sb)->mount_crypt_stat;

#ifdef CONFIG_WTL_ENCRYPTION_FILTER
	if (crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED
		&& crypt_stat->flags & ECRYPTFS_POLICY_APPLIED
		&& crypt_stat->flags & ECRYPTFS_ENCRYPTED
		&& !(crypt_stat->flags & ECRYPTFS_KEY_VALID)
		&& !(crypt_stat->flags & ECRYPTFS_KEY_SET)
		&& crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED) {
		crypt_stat->flags |= ECRYPTFS_ENCRYPTED_OTHER_DEVICE;
	}
	mutex_lock(&crypt_stat->cs_mutex);
	if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_NEW_PASSTHROUGH)
			&& (crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
		if (ecryptfs_read_metadata(dentry)) {
			crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
					| ECRYPTFS_ENCRYPTED);
			rc = 0;
			goto out;
		}
	} else if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_FILTERING)
			&& (crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
		struct dentry *fp_dentry =
			ecryptfs_inode_to_private(inode)->lower_file->f_dentry;
		char filename[NAME_MAX+1] = {0};
		if (fp_dentry->d_name.len <= NAME_MAX)
			memcpy(filename, fp_dentry->d_name.name,
					fp_dentry->d_name.len + 1);

		if (is_file_name_match(mount_crypt_stat, fp_dentry)
			|| is_file_ext_match(mount_crypt_stat, filename)) {
			if (ecryptfs_read_metadata(dentry))
				crypt_stat->flags &=
				~(ECRYPTFS_I_SIZE_INITIALIZED
				| ECRYPTFS_ENCRYPTED);
			rc = 0;
			goto out;
		}
	}
	mutex_unlock(&crypt_stat->cs_mutex);
#endif

	mutex_lock(&crypt_stat->cs_mutex);

	if (crypt_stat->flags & ECRYPTFS_POLICY_APPLIED &&
	    crypt_stat->flags & ECRYPTFS_KEY_VALID) {
		rc = 0;
		goto out;
	}

	rc = ecryptfs_read_metadata(dentry);
	if (!rc)
		goto out;

#ifdef CONFIG_SDP
	/*
	 * no passthrough/xattr for sensitive files
	 */
	if ((rc) && crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)
		goto out;
#endif

	if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) {
		crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
				       | ECRYPTFS_ENCRYPTED);
		rc = 0;
		goto out;
	}

	if (!(mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) &&
	    !i_size_read(ecryptfs_inode_to_lower(inode))) {
		rc = ecryptfs_initialize_file(dentry, inode);
		if (!rc)
			goto out;
	}

	rc = -EIO;
out:
	mutex_unlock(&crypt_stat->cs_mutex);
#ifdef CONFIG_SDP
	if(!rc)
	{
		/*
		 * SDP v2.0 : sensitive directory (SDP vault)
		 * Files under sensitive directory automatically becomes sensitive
		 */
		struct dentry *p = dentry->d_parent;
		struct inode *parent_inode = p->d_inode;
		struct ecryptfs_crypt_stat *parent_crypt_stat =
				&ecryptfs_inode_to_private(parent_inode)->crypt_stat;

		if (!(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) &&
				((S_ISDIR(parent_inode->i_mode)) &&
						(parent_crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE))) {
			rc = ecryptfs_sdp_set_sensitive(parent_crypt_stat->engine_id, dentry);
		}
	}
#endif
	return rc;
}

#if defined(CONFIG_MMC_DW_FMP_ECRYPT_FS) || defined(CONFIG_UFS_FMP_ECRYPT_FS)
static void ecryptfs_set_rapages(struct file *file, unsigned int flag)
{
	if (!flag)
		file->f_ra.ra_pages = 0;
	else
		file->f_ra.ra_pages = (unsigned int)file->f_mapping->backing_dev_info->ra_pages;
}

static int ecryptfs_set_fmpinfo(struct file *file, struct inode *inode, unsigned int set_flag)
{
	struct address_space *mapping = file->f_mapping;

	if (set_flag) {
		struct ecryptfs_crypt_stat *crypt_stat =
			&ecryptfs_inode_to_private(inode)->crypt_stat;
		struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
			&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;

		if (strncmp(crypt_stat->cipher, "aesxts", sizeof("aesxts"))
			&& strncmp(crypt_stat->cipher, "aes", sizeof("aes"))) {
			if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
				mapping->plain_text = 1;
				return 0;
			} else {
				ecryptfs_printk(KERN_ERR,
						"%s: Error invalid file encryption algorithm, inode %lu, filename %s alg %s\n"
						, __func__, inode->i_ino,  file->f_dentry->d_name.name, crypt_stat->cipher);
				return -EINVAL;
			}
		}
		mapping->iv = crypt_stat->root_iv;
		mapping->key = crypt_stat->key;
		mapping->sensitive_data_index = crypt_stat->metadata_size/4096;
		if (mount_crypt_stat->cipher_code == RFC2440_CIPHER_AES_XTS_256) {
			mapping->key_length = crypt_stat->key_size * 2;
			mapping->alg = "aesxts";
		} else {
			mapping->key_length = crypt_stat->key_size;
			mapping->alg = crypt_stat->cipher;
		}
		mapping->hash_tfm = crypt_stat->hash_tfm;
#ifdef CONFIG_CRYPTO_FIPS
		mapping->cc_enable =
			(mount_crypt_stat->flags & ECRYPTFS_ENABLE_CC)?1:0;
#endif
	} else {
		mapping->iv = NULL;
		mapping->key = NULL;
		mapping->key_length = 0;
		mapping->sensitive_data_index = 0;
		mapping->alg = NULL;
		mapping->hash_tfm = NULL;
#ifdef CONFIG_CRYPTO_FIPS
		mapping->cc_enable = 0;
#endif
		mapping->plain_text = 0;
	}

	return 0;
}

void ecryptfs_propagate_rapages(struct file *file, unsigned int flag)
{
	struct file *f = file;

	do {
		if (!f)
			return;
		ecryptfs_set_rapages(f, flag);
	} while(f->f_op->get_lower_file && (f = f->f_op->get_lower_file(f)));

}

int ecryptfs_propagate_fmpinfo(struct inode *inode, unsigned int flag)
{
	struct file *f = ecryptfs_inode_to_private(inode)->lower_file;

	do {
		if (!f)
			return 0;
		if (ecryptfs_set_fmpinfo(f, inode, flag))
			return -EINVAL;
	} while(f->f_op->get_lower_file && (f = f->f_op->get_lower_file(f)));

	return 0;
}
#endif

/**
 * ecryptfs_open
 * @inode: inode speciying file to open
 * @file: Structure to return filled in
 *
 * Opens the file specified by inode.
 *
 * Returns zero on success; non-zero otherwise
 */
static int ecryptfs_open(struct inode *inode, struct file *file)
{
	int rc = 0;
	struct ecryptfs_crypt_stat *crypt_stat = NULL;
	struct dentry *ecryptfs_dentry = file->f_path.dentry;
	/* Private value of ecryptfs_dentry allocated in
	 * ecryptfs_lookup() */
	struct ecryptfs_file_info *file_info;
#ifdef CONFIG_DLP
	sdp_fs_command_t *cmd = NULL;

	ssize_t dlp_len = 0;
	struct knox_dlp_data dlp_data;
	struct timespec ts;
#endif

#if defined(CONFIG_MMC_DW_FMP_ECRYPT_FS) || defined(CONFIG_UFS_FMP_ECRYPT_FS) || defined(CONFIG_SDP)
	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;	
	mount_crypt_stat = &ecryptfs_superblock_to_private(
							inode->i_sb)->mount_crypt_stat;
#endif

	/* Released in ecryptfs_release or end of function if failure */
	file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
	ecryptfs_set_file_private(file, file_info);
	if (!file_info) {
		ecryptfs_printk(KERN_ERR,
				"Error attempting to allocate memory\n");
		rc = -ENOMEM;
		goto out;
	}
	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
	mutex_lock(&crypt_stat->cs_mutex);
	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
		ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
		/* Policy code enabled in future release */
		crypt_stat->flags |= (ECRYPTFS_POLICY_APPLIED
				      | ECRYPTFS_ENCRYPTED);
	}
	mutex_unlock(&crypt_stat->cs_mutex);
	rc = ecryptfs_get_lower_file(ecryptfs_dentry, inode);
	if (rc) {
		printk(KERN_ERR "%s: Error attempting to initialize "
			"the lower file for the dentry with name "
			"[%pd]; rc = [%d]\n", __func__,
			ecryptfs_dentry, rc);
		goto out_free;
	}
	if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE)
	    == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) {
		rc = -EPERM;
		printk(KERN_WARNING "%s: Lower file is RO; eCryptfs "
		       "file must hence be opened RO\n", __func__);
		goto out_put;
	}
	ecryptfs_set_file_lower(
		file, ecryptfs_inode_to_private(inode)->lower_file);
	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
#ifdef CONFIG_SDP
		/*
		 * it's possible to have a sensitive directory. (vault)
		 */
		if (mount_crypt_stat->flags & ECRYPTFS_MOUNT_SDP_ENABLED)
			crypt_stat->flags |= ECRYPTFS_DEK_SDP_ENABLED;
#endif
		ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
		mutex_lock(&crypt_stat->cs_mutex);
		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
		mutex_unlock(&crypt_stat->cs_mutex);
		rc = 0;
		goto out;
	}
	rc = read_or_initialize_metadata(ecryptfs_dentry);
	if (rc) {
#ifdef CONFIG_SDP
		if(file->f_flags & O_SDP){
			printk("Failed to initialize metadata, "
					"but let it continue cause current call is from SDP API\n");
			mutex_lock(&crypt_stat->cs_mutex);
			crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
			mutex_unlock(&crypt_stat->cs_mutex);
			rc = 0;
			/*
			 * Letting this continue doesn't mean to allow read/writing. It will anyway fail later.
			 *
			 * 1. In this stage, ecryptfs_stat won't have key/iv and encryption ctx.
			 * 2. ECRYPTFS_KEY_VALID bit is off, next attempt will try reading metadata again.
			 * 3. Skip DEK conversion. it cannot be done anyway.
			 */
			goto out;
		}
#endif
		goto out_put;
	}

#if defined(CONFIG_MMC_DW_FMP_ECRYPT_FS) || defined(CONFIG_UFS_FMP_ECRYPT_FS)
	if (mount_crypt_stat->flags & ECRYPTFS_USE_FMP)
		rc = ecryptfs_propagate_fmpinfo(inode, FMPINFO_SET);
	else
		rc = ecryptfs_propagate_fmpinfo(inode, FMPINFO_CLEAR);
#endif
	if (rc)
		goto out_put;
#ifdef CONFIG_SDP
	if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
#ifdef CONFIG_SDP_KEY_DUMP
		if (S_ISREG(ecryptfs_dentry->d_inode->i_mode)) {
			if(get_sdp_sysfs_key_dump()) {
				printk("FEK[%s] : ", ecryptfs_dentry->d_name.name);
				key_dump(crypt_stat->key, 32);
			}
		}
#endif
		/*
		 * Need to update sensitive mapping on file open
		 */
		if (S_ISREG(ecryptfs_dentry->d_inode->i_mode)) {
			ecryptfs_set_mapping_sensitive(inode, mount_crypt_stat->userid, TO_SENSITIVE);
		}
		
		if (ecryptfs_is_sdp_locked(crypt_stat->engine_id)) {
			ecryptfs_printk(KERN_INFO, "ecryptfs_open: persona is locked, rc=%d\n", rc);
		} else {
			int dek_type = crypt_stat->sdp_dek.type;

			ecryptfs_printk(KERN_INFO, "ecryptfs_open: persona is unlocked, rc=%d\n", rc);
			if(dek_type != DEK_TYPE_AES_ENC) {
				ecryptfs_printk(KERN_DEBUG, "converting dek...\n");
				rc = ecryptfs_sdp_convert_dek(ecryptfs_dentry);
				ecryptfs_printk(KERN_DEBUG, "conversion ready, rc=%d\n", rc);
				rc = 0; // TODO: Do we need to return error if conversion fails?
			}
		}
	}
#if ECRYPTFS_DEK_DEBUG
	else {
		ecryptfs_printk(KERN_INFO, "ecryptfs_open: dek_file_type is protected\n");
	}
#endif
#endif

#ifdef CONFIG_DLP
	if(crypt_stat->flags & ECRYPTFS_DLP_ENABLED) {
#if DLP_DEBUG
		printk("DLP %s: try to open %s with crypt_stat->flags %d\n",
				__func__, ecryptfs_dentry->d_name.name, crypt_stat->flags);
#endif
		if (dlp_is_locked(mount_crypt_stat->userid)) {
			printk("%s: DLP locked\n", __func__);
			rc = -EPERM;
			goto out_put;
		}
		if(in_egroup_p(AID_KNOX_DLP) || in_egroup_p(AID_KNOX_DLP_RESTRICTED)) {
			dlp_len = ecryptfs_getxattr_lower(
					ecryptfs_dentry_to_lower(ecryptfs_dentry),
					KNOX_DLP_XATTR_NAME,
					&dlp_data, sizeof(dlp_data));
			if (dlp_len == sizeof(dlp_data)) {
				getnstimeofday(&ts);
#if DLP_DEBUG
				printk("DLP %s: current time [%ld/%ld] %s\n",
						__func__, (long)ts.tv_sec, (long)dlp_data.expiry_time.tv_sec, ecryptfs_dentry->d_name.name);
#endif
				if ((ts.tv_sec > dlp_data.expiry_time.tv_sec) && dlp_isInterestedFile(ecryptfs_dentry->d_name.name)==0) {
					/* Command to delete expired file  */
					cmd = sdp_fs_command_alloc(FSOP_DLP_FILE_REMOVE,
							current->tgid, mount_crypt_stat->userid, mount_crypt_stat->partition_id,
							inode->i_ino, GFP_KERNEL);
					rc = -ENOENT;
					goto out_put;
				}
			} else if (dlp_len == -ENODATA) {
				/* DLP flag is set, but no DLP data. Let it continue, xattr will be set later */
				printk("DLP %s: normal file [%s]\n",
						__func__, ecryptfs_dentry->d_name.name);
			} else {
				printk("DLP %s: Error, len [%ld], [%s]\n",
						__func__, (long)dlp_len, ecryptfs_dentry->d_name.name);
				rc = -EFAULT;
				goto out_put;
			}

#if DLP_DEBUG
			printk("DLP %s: DLP file [%s] opened with tgid %d, %d\n" ,
					__func__, ecryptfs_dentry->d_name.name, current->tgid, in_egroup_p(AID_KNOX_DLP_RESTRICTED));
#endif
			if(in_egroup_p(AID_KNOX_DLP_RESTRICTED)) {
				cmd = sdp_fs_command_alloc(FSOP_DLP_FILE_OPENED,
						current->tgid, mount_crypt_stat->userid, mount_crypt_stat->partition_id,
						inode->i_ino, GFP_KERNEL);
			}
		} else {
			printk("DLP %s: not DLP app [%s]\n", __func__, current->comm);
			rc = -EPERM;
			goto out_put;
		}
	}
#endif

	ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = "
			"[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
			(unsigned long long)i_size_read(inode));
	goto out;
out_put:
	ecryptfs_put_lower_file(inode);
out_free:
	kmem_cache_free(ecryptfs_file_info_cache,
			ecryptfs_file_to_private(file));
out:
#ifdef CONFIG_DLP
	if(cmd) {
		sdp_fs_request(cmd, NULL);
		sdp_fs_command_free(cmd);
	}
#endif
	return rc;
}
示例#19
0
static unsigned long read_current_us(void)
{
	struct timespec now;
	getnstimeofday(&now);
	return (now.tv_sec * 1000000) + (now.tv_nsec/1000);
}
示例#20
0
int
pscnv_dma_bo_to_bo(struct pscnv_bo *tgt, struct pscnv_bo *src, int flags) {
	
	struct drm_device *dev = tgt->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct pscnv_dma *dma = dev_priv->dma;
	
	struct pscnv_mm_node *tgt_node;
	struct pscnv_mm_node *src_node;
	const uint32_t size = tgt->size;
	
	struct timespec start, start_real, end, end_real;
	s64 start_ns, start_real_ns, duration, duration_real;
	
	int ret;
	
	flags = pscnv_dma_setup_flags(flags);
	
	if (!dma) {
		NV_ERROR(dev, "DMA: not available\n");
		return -ENOENT;
	}
	
	BUG_ON(tgt->dev != src->dev);
	
	mutex_lock(&dma->lock);
	
	getnstimeofday(&start_real);
	start_real_ns = timespec_to_ns(&start_real);
	
	if (tgt->size < src->size) {
		NV_INFO(dev, "DMA: source bo (cookie=%x) has size %lld, but target bo "
			"(cookie=%x) only has size %lld\n",
			src->cookie, src->size, tgt->cookie, tgt->size);
		return -ENOSPC;
	}
	
	ret = pscnv_vspace_map(dma->vs, tgt,
			0x20000000, /* start */
			1ull << 40, /* end */
			0, /* back, nonsense? */
			&tgt_node);
	
	if (ret) {
		NV_INFO(dev, "DMA: failed to map target bo\n");
		goto fail_map_tgt;
	}
	
	ret = pscnv_vspace_map(dma->vs, src,
			0x20000000, /* start */
			1ull << 40, /* end */
			0, /* back, nonsense? */
			&src_node);
	
	if (ret) {
		NV_INFO(dev, "DMA: failed to map source bo\n");
		goto fail_map_src;
	}
	
	if (flags & PSCNV_DMA_DEBUG) {
		dev_priv->chan->pd_dump_chan(dev, NULL /* seq_file */, PSCNV_DMA_CHAN);
	}
	
	getnstimeofday(&start);
	start_ns = timespec_to_ns(&start);
	
	pscnv_ib_membar(dma->ib_chan);
	
	if (flags & PSCNV_DMA_ASYNC) {
		pscnv_ib_fence_write(dma->ib_chan, GDEV_SUBCH_NV_PCOPY0);
	
		nvc0_memcpy_pcopy0(dma->ib_chan, tgt_node->start, src_node->start, size, flags);
	} else {
		pscnv_ib_fence_write(dma->ib_chan, GDEV_SUBCH_NV_M2MF);
	
		nvc0_memcpy_m2mf(dma->ib_chan, tgt_node->start, src_node->start, size, flags);
	}
	
	
	ret = pscnv_ib_fence_wait(dma->ib_chan);
	
	if (ret) {
		NV_INFO(dev, "DMA: failed to wait for fence completion\n");
		goto fail_fence_wait;
	}
	
	getnstimeofday(&end);
	
	/* no return here, always unmap memory */

fail_fence_wait:
	pscnv_vspace_unmap_node(src_node);

fail_map_src:
	pscnv_vspace_unmap_node(tgt_node);
	
fail_map_tgt:
	mutex_unlock(&dma->lock);
	
	getnstimeofday(&end_real);
	
	if (!ret) {
		duration = timespec_to_ns(&end) - start_ns;
		duration_real = timespec_to_ns(&end_real) - start_real_ns;
		if (flags & PSCNV_DMA_VERBOSE) {
			NV_INFO(dev, "DMA: took %lld.%04lld ms (real %lld.%04lld ms)\n",
				duration / 1000000,
				(duration % 1000000) / 100,
				duration_real / 1000000,
				(duration_real % 1000000) / 100);
		}
		
		pscnv_client_track_time(src->client, start_ns, duration, size, "DMA");
		pscnv_client_track_time(src->client, start_ns, duration_real, size, "DMA_REAL");
		if (src->client)
			src->client->pause_bytes_transferred += size;
	}

	return ret;
}
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	/* Using u32 instead of int for 32bit uspace and 64bit kernel */
	u32 rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	uint32_t alarm_type_mask = 0;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);

	if (alarm_type == ANDROID_ALARM_RTC_DEVICEUP)
            alarm_type=ANDROID_ALARM_POWER_OFF_WAKEUP;

	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
		return -EINVAL;

	alarm_type_mask = 1U << alarm_type;

	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		alarm_try_to_cancel(&alarms[alarm_type]);
		if (alarm_pending) {
			alarm_pending &= ~alarm_type_mask;
			if (!alarm_pending && !wait_pending)
				wake_unlock(&alarm_wake_lock);
		}
		alarm_enabled &= ~alarm_type_mask;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
		alarm_enabled |= alarm_type_mask;
		alarm_start_range(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time),
			timespec_to_ktime(new_alarm_time));
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		//AndyPan add
		if (alarm_pending & pwoff_mask)
		{
			//printk("andy alarm_pending &= ~ pwoff_mask =%d \r\n",alarm_pending);
			alarm_pending &= ~ pwoff_mask;
			alarm_pending |= deviceup_mask;
			//printk("andy alarm_pending |= deviceup_mask =%d \r\n",alarm_pending);
		}
		//AndyPan add
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rv = alarm_set_rtc(new_rtc_time);
		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv < 0)
			goto err1;
		break;
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
		case ANDROID_ALARM_POWER_OFF_WAKEUP:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			tmp_time =
				ktime_to_timespec(alarm_get_elapsed_realtime());
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}
示例#22
0
int
pscnv_dma_chunk_to_chunk(struct pscnv_chunk *from, struct pscnv_chunk *to, int flags)
{
	struct drm_device *dev = from->bo->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct pscnv_dma *dma = dev_priv->dma;
	struct pscnv_client *client = from->bo->client;
	
	struct pscnv_mm_node *from_node;
	struct pscnv_mm_node *to_node;
	const uint64_t size = pscnv_chunk_size(from);
	
	struct timespec start, start_real, end, end_real;
	s64 start_ns, start_real_ns, duration, duration_real;
	
	int ret;
	
	flags = pscnv_dma_setup_flags(flags);
	
	if (!dma) {
		NV_ERROR(dev, "DMA: not available\n");
		return -ENOENT;
	}
	
	BUG_ON(from->bo->dev != to->bo->dev);
	
	mutex_lock(&dma->lock);
	
	getnstimeofday(&start_real);
	start_real_ns = timespec_to_ns(&start_real);
	
	if (pscnv_chunk_size(to) < size) {
		NV_INFO(dev, "DMA: source chunk %08x/%d-%u has size %lld, but "
			"target chunk %08x/%d-%u only has size %lld\n",
			from->bo->cookie, from->bo->serial, from->idx,
			size, to->bo->cookie, to->bo->serial, to->idx,
			pscnv_chunk_size(to));
		return -ENOSPC;
	}
	
	ret = pscnv_vspace_map_chunk(dma->vs, to,
			0x20000000, /* start */
			1ull << 40, /* end */
			0, /* back, nonsense? */
			&to_node);
	
	if (ret) {
		NV_INFO(dev, "DMA: failed to map 'to' chunk\n");
		goto fail_map_to;
	}
	
	ret = pscnv_vspace_map_chunk(dma->vs, from,
			0x20000000, /* start */
			1ull << 40, /* end */
			0, /* back, nonsense? */
			&from_node);
	
	if (ret) {
		NV_INFO(dev, "DMA: failed to map 'from' chunk\n");
		goto fail_map_from;
	}
	
	if (flags & PSCNV_DMA_DEBUG) {
		dev_priv->chan->pd_dump_chan(dev, NULL /* seq_file */, PSCNV_DMA_CHAN);
	}
	
	getnstimeofday(&start);
	start_ns = timespec_to_ns(&start);
	
	pscnv_ib_membar(dma->ib_chan);
	
	if (flags & PSCNV_DMA_ASYNC) {
		pscnv_ib_fence_write(dma->ib_chan, GDEV_SUBCH_NV_PCOPY0);
	
		nvc0_memcpy_pcopy0(dma->ib_chan, to_node->start, from_node->start, size, flags);
	} else {
		pscnv_ib_fence_write(dma->ib_chan, GDEV_SUBCH_NV_M2MF);
	
		nvc0_memcpy_m2mf(dma->ib_chan, to_node->start, from_node->start, size, flags);
	}
	
	ret = pscnv_ib_fence_wait(dma->ib_chan);
	
	if (ret) {
		NV_INFO(dev, "DMA: failed to wait for fence completion\n");
		goto fail_fence_wait;
	}
	
	getnstimeofday(&end);
	
	/* no return here, always unmap memory */

fail_fence_wait:
	pscnv_vspace_unmap_node(from_node);

fail_map_from:
	pscnv_vspace_unmap_node(to_node);
	
fail_map_to:
	mutex_unlock(&dma->lock);
	
	getnstimeofday(&end_real);
	
	if (!ret) {
		duration = timespec_to_ns(&end) - start_ns;
		duration_real = timespec_to_ns(&end_real) - start_real_ns;
		if (flags & PSCNV_DMA_VERBOSE) {
			NV_INFO(dev, "DMA: took %lld.%04lld ms (real %lld.%04lld ms)\n",
				duration / 1000000,
				(duration % 1000000) / 100,
				duration_real / 1000000,
				(duration_real % 1000000) / 100);
		}
		pscnv_client_track_time(client, start_ns, duration, size, "DMA");
		pscnv_client_track_time(client, start_ns, duration_real, size, "DMA_REAL");
		if (client)
			client->pause_bytes_transferred += size;

	}

	return ret;
}
示例#23
0
int ip_options_compile(struct net *net,
		       struct ip_options *opt, struct sk_buff *skb)
{
	__be32 spec_dst = htonl(INADDR_ANY);
	unsigned char *pp_ptr = NULL;
	struct rtable *rt = NULL;
	unsigned char *optptr;
	unsigned char *iph;
	int optlen, l;

	if (skb) {
		rt = skb_rtable(skb);
		optptr = (unsigned char *)&(ip_hdr(skb)[1]);
	} else
		optptr = opt->__data;
	iph = optptr - sizeof(struct iphdr);

	for (l = opt->optlen; l > 0; ) {
		switch (*optptr) {
		case IPOPT_END:
			for (optptr++, l--; l > 0; optptr++, l--) {
				if (*optptr != IPOPT_END) {
					*optptr = IPOPT_END;
					opt->is_changed = 1;
				}
			}
			goto eol;
		case IPOPT_NOOP:
			l--;
			optptr++;
			continue;
		}
		if (unlikely(l < 2)) {
			pp_ptr = optptr;
			goto error;
		}
		optlen = optptr[1];
		if (optlen < 2 || optlen > l) {
			pp_ptr = optptr;
			goto error;
		}
		switch (*optptr) {
		case IPOPT_SSRR:
		case IPOPT_LSRR:
			if (optlen < 3) {
				pp_ptr = optptr + 1;
				goto error;
			}
			if (optptr[2] < 4) {
				pp_ptr = optptr + 2;
				goto error;
			}
			/* NB: cf RFC-1812 5.2.4.1 */
			if (opt->srr) {
				pp_ptr = optptr;
				goto error;
			}
			if (!skb) {
				if (optptr[2] != 4 || optlen < 7 || ((optlen-3) & 3)) {
					pp_ptr = optptr + 1;
					goto error;
				}
				memcpy(&opt->faddr, &optptr[3], 4);
				if (optlen > 7)
					memmove(&optptr[3], &optptr[7], optlen-7);
			}
			opt->is_strictroute = (optptr[0] == IPOPT_SSRR);
			opt->srr = optptr - iph;
			break;
		case IPOPT_RR:
			if (opt->rr) {
				pp_ptr = optptr;
				goto error;
			}
			if (optlen < 3) {
				pp_ptr = optptr + 1;
				goto error;
			}
			if (optptr[2] < 4) {
				pp_ptr = optptr + 2;
				goto error;
			}
			if (optptr[2] <= optlen) {
				if (optptr[2]+3 > optlen) {
					pp_ptr = optptr + 2;
					goto error;
				}
				if (rt) {
					spec_dst_fill(&spec_dst, skb);
					memcpy(&optptr[optptr[2]-1], &spec_dst, 4);
					opt->is_changed = 1;
				}
				optptr[2] += 4;
				opt->rr_needaddr = 1;
			}
			opt->rr = optptr - iph;
			break;
		case IPOPT_TIMESTAMP:
			if (opt->ts) {
				pp_ptr = optptr;
				goto error;
			}
			if (optlen < 4) {
				pp_ptr = optptr + 1;
				goto error;
			}
			if (optptr[2] < 5) {
				pp_ptr = optptr + 2;
				goto error;
			}
			if (optptr[2] <= optlen) {
				unsigned char *timeptr = NULL;
				if (optptr[2]+3 > optlen) {
					pp_ptr = optptr + 2;
					goto error;
				}
				switch (optptr[3]&0xF) {
				case IPOPT_TS_TSONLY:
					if (skb)
						timeptr = &optptr[optptr[2]-1];
					opt->ts_needtime = 1;
					optptr[2] += 4;
					break;
				case IPOPT_TS_TSANDADDR:
					if (optptr[2]+7 > optlen) {
						pp_ptr = optptr + 2;
						goto error;
					}
					if (rt)  {
						spec_dst_fill(&spec_dst, skb);
						memcpy(&optptr[optptr[2]-1], &spec_dst, 4);
						timeptr = &optptr[optptr[2]+3];
					}
					opt->ts_needaddr = 1;
					opt->ts_needtime = 1;
					optptr[2] += 8;
					break;
				case IPOPT_TS_PRESPEC:
					if (optptr[2]+7 > optlen) {
						pp_ptr = optptr + 2;
						goto error;
					}
					{
						__be32 addr;
						memcpy(&addr, &optptr[optptr[2]-1], 4);
						if (inet_addr_type(net, addr) == RTN_UNICAST)
							break;
						if (skb)
							timeptr = &optptr[optptr[2]+3];
					}
					opt->ts_needtime = 1;
					optptr[2] += 8;
					break;
				default:
					if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
						pp_ptr = optptr + 3;
						goto error;
					}
					break;
				}
				if (timeptr) {
					struct timespec tv;
					u32  midtime;
					getnstimeofday(&tv);
					midtime = (tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC;
					put_unaligned_be32(midtime, timeptr);
					opt->is_changed = 1;
				}
			} else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) {
				unsigned int overflow = optptr[3]>>4;
				if (overflow == 15) {
					pp_ptr = optptr + 3;
					goto error;
				}
				if (skb) {
					optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
					opt->is_changed = 1;
				}
			}
			opt->ts = optptr - iph;
			break;
		case IPOPT_RA:
			if (optlen < 4) {
				pp_ptr = optptr + 1;
				goto error;
			}
			if (optptr[2] == 0 && optptr[3] == 0)
				opt->router_alert = optptr - iph;
			break;
		case IPOPT_CIPSO:
			if ((!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) || opt->cipso) {
				pp_ptr = optptr;
				goto error;
			}
			opt->cipso = optptr - iph;
			if (cipso_v4_validate(skb, &optptr)) {
				pp_ptr = optptr;
				goto error;
			}
			break;
		case IPOPT_SEC:
		case IPOPT_SID:
		default:
			if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
				pp_ptr = optptr;
				goto error;
			}
			break;
		}
		l -= optlen;
		optptr += optlen;
	}
示例#24
0
文件: isr.c 项目: commtech/fscc-linux
void iframe_worker(unsigned long data)
{
	struct fscc_port *port = 0;
	int receive_length = 0; /* Needs to be signed */
	unsigned finished_frame = 0;
	unsigned long board_flags = 0;
	unsigned long frame_flags = 0;
	unsigned long queued_flags = 0;
	static int rejected_last_frame = 0;
	unsigned current_memory = 0;
	unsigned memory_cap = 0;
	unsigned rfcnt = 0;

	port = (struct fscc_port *)data;

	return_if_untrue(port);

	do {
		current_memory = fscc_port_get_input_memory_usage(port);
		memory_cap = fscc_port_get_input_memory_cap(port);

		spin_lock_irqsave(&port->board_rx_spinlock, board_flags);
		spin_lock_irqsave(&port->pending_iframe_spinlock, frame_flags);

		rfcnt = fscc_port_get_RFCNT(port);
		finished_frame = (rfcnt > 0) ? 1 : 0;

		if (finished_frame) {
			unsigned bc_fifo_l = 0;
			unsigned current_length = 0;

			bc_fifo_l = fscc_port_get_register(port, 0, BC_FIFO_L_OFFSET);

			if (port->pending_iframe)
				current_length = fscc_frame_get_length(port->pending_iframe);

			receive_length = bc_fifo_l - current_length;
		} else {
			unsigned rxcnt = 0;

			// Refresh rfcnt, if the frame is now complete, reloop through
			// This prevents the situation where the frame has finished being
			// received between the original rfcnt and now, causing a possible
			// read of a larger byte count than in the actual frame due to
			// another incoming frame
			rxcnt = fscc_port_get_RXCNT(port);
			rfcnt = fscc_port_get_RFCNT(port);

			if (rfcnt) {
				spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
				spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
				break;
			}

			/* We choose a safe amount to read due to more data coming in after we
			   get our values. The rest will be read on the next interrupt. */
			receive_length = max((int)(rxcnt - rxcnt % 4), (int)0);
		}

		if (receive_length <= 0) {
			spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
			spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
			return;
		}

		/* Make sure we don't go over the user's memory constraint. */
		if (current_memory + receive_length > memory_cap) {
			if (rejected_last_frame == 0) {
				dev_warn(port->device,
						 "Rejecting frames (memory constraint)\n");
				rejected_last_frame = 1; /* Track that we dropped a frame so we
								don't have to warn the user again. */
			}

			if (port->pending_iframe) {
				fscc_frame_delete(port->pending_iframe);
				port->pending_iframe = 0;
			}

			spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
			spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
			return;
		}

		if (!port->pending_iframe) {
			port->pending_iframe = fscc_frame_new(port);

			if (!port->pending_iframe) {
				spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
				spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
				return;
			}
		}

		fscc_frame_add_data_from_port(port->pending_iframe, port, receive_length);

	#ifdef __BIG_ENDIAN
		{
			char status[STATUS_LENGTH];

			/* Moves the status bytes to the end. */
			memmove(&status, port->pending_iframe->data, STATUS_LENGTH);
			memmove(port->pending_iframe->data, port->pending_iframe->data + STATUS_LENGTH, port->pending_iframe->current_length - STATUS_LENGTH);
			memmove(port->pending_iframe->data + port->pending_iframe->current_length - STATUS_LENGTH, &status, STATUS_LENGTH);
		}
	#endif

		dev_dbg(port->device, "F#%i <= %i byte%s (%sfinished)\n",
				port->pending_iframe->number, receive_length,
				(receive_length == 1) ? "" : "s",
				(finished_frame) ? "" : "un");

		if (!finished_frame) {
			spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
			spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);
			return;
		}

		if (port->pending_iframe) {
#ifdef RELEASE_PREVIEW
			getnstimeofday(&port->pending_iframe->timestamp);
#else
			do_gettimeofday(&port->pending_iframe->timestamp);
#endif
			spin_lock_irqsave(&port->queued_iframes_spinlock, queued_flags);
			fscc_flist_add_frame(&port->queued_iframes, port->pending_iframe);
			spin_unlock_irqrestore(&port->queued_iframes_spinlock, queued_flags);
		}

		rejected_last_frame = 0; /* Track that we received a frame to reset the
									memory constraint warning print message. */

		port->pending_iframe = 0;

		spin_unlock_irqrestore(&port->pending_iframe_spinlock, frame_flags);
	    spin_unlock_irqrestore(&port->board_rx_spinlock, board_flags);

		wake_up_interruptible(&port->input_queue);
	}
	while (receive_length);
}
static void process_cb_request(void *buffer)
{
	struct rtc_cb_recv *rtc_cb = buffer;
	struct timespec ts, tv;

	rtc_cb->client_cb_id = be32_to_cpu(rtc_cb->client_cb_id);
	rtc_cb->event = be32_to_cpu(rtc_cb->event);
	rtc_cb->cb_info_ptr = be32_to_cpu(rtc_cb->cb_info_ptr);

	if (rtc_cb->event == EVENT_TOD_CHANGE) {
		/* A TOD update has been received from the Modem */
		rtc_cb->cb_info_data.tod_update.tick =
			be32_to_cpu(rtc_cb->cb_info_data.tod_update.tick);
		rtc_cb->cb_info_data.tod_update.stamp =
			be64_to_cpu(rtc_cb->cb_info_data.tod_update.stamp);
		rtc_cb->cb_info_data.tod_update.freq =
			be32_to_cpu(rtc_cb->cb_info_data.tod_update.freq);
		pr_info("RPC CALL -- TOD TIME UPDATE: ttick = %d\n"
			"stamp=%lld, freq = %d\n",
			rtc_cb->cb_info_data.tod_update.tick,
			rtc_cb->cb_info_data.tod_update.stamp,
			rtc_cb->cb_info_data.tod_update.freq);

		getnstimeofday(&ts);

/* CR 291540 - Function/Feature Failure (Partial)
 * system uptime gets corrupted with overflow in slow clock.
 * 
 * Problem description
 * During power collapse, APPS sleep time is calculated using slow clock
 * ticks. The calculation of sleep time does not considers slow clock
 * overflow and thus If slow clock overflows during suspend state then we
 * get wrong sleep time and thus system uptime values gets corrupted.
 * earlier sleep time was calculates as follows:
 * sleep = current_sclk_tick - suspend_state_sclk_tick
 * 
 * Failure frequency: Occasionally
 * Scenario frequency: Uncommon
 * Change description
 * Modified the sleep time calculation to include slow clock overflow as follows:
 * Now sleep time is calculated as:
 * sleep = Maximum_sclk_tick_val - suspend_state_sclk_tick + current_sclk_tick.
 * Files affected
 * kernel/drivers/rtc/rtc-msm.c
 * kernel/arch/arm/mach-msm/rpc_server_time_remote.c
*/	
		if (atomic_read(&suspend_state.state)) {
#if 1 //QCT SBA 404016
			int64_t now, sleep, sclk_max;
			now = msm_timer_get_sclk_time(&sclk_max);
#else
			int64_t now, sleep;
			now = msm_timer_get_sclk_time(NULL);
#endif
			if (now && suspend_state.tick_at_suspend) {
#if 1 //QCT SBA 404016
				if (now < suspend_state.tick_at_suspend) {
					sleep = sclk_max -
							suspend_state.tick_at_suspend
							+ now;
				} else {
					sleep = now -
							suspend_state.tick_at_suspend;
				}
#else
				sleep = now -
					suspend_state.tick_at_suspend;
#endif
				timespec_add_ns(&ts, sleep);
/* CR 293735 - Function/Feature Failure (Partial)
 * When system was in suspend, could make invalid "elapsed system time" at AP side.
 * 
 * Problem description
 * When system is in suspend mode and if more than one network time update
 * comes while system is in suspend mode then the uptime gets corrupted.
 * 
 * Failure frequency: Occasionally
 * Scenario frequency: Uncommon
 * Change description
 * Added change to modify tick_at_suspend (variable that stores time tick
 * while entering suspend) after each update to the current time tick.
 * Setting the suspend mode variable in case alarm time expires the current
 * RTC time as in thic case also system enters suspend mode.
 * to sdcc irq handlers returning IRQ_NONE without handling the interrupt.
 * When interrupt is disabled the communication between the SDIO client and
 * SDCC host controller is stopped while a pending command is in progress
 * and hence WLAN operation is stuck forever and LOGP recovery cannot be
 * processed.
 * Files affected
 * arch/arm/mach-msm/rpc_server_time_remote.c
 * drivers/rtc/rtc-msm.c
 * include/linux/rtc-msm.h
 */
#if 1 //QCT SBA 404017
				suspend_state.tick_at_suspend = now;
#endif
			} else
				pr_err("%s: Invalid ticks from SCLK"
					"now=%lld tick_at_suspend=%lld",
					__func__, now,
					suspend_state.tick_at_suspend);
		}
		rtc_hctosys();
		getnstimeofday(&tv);
		/* Update the alarm information with the new time info. */
		alarm_update_timedelta(ts, tv);

	} else
		pr_err("%s: Unknown event EVENT=%x\n",
					__func__, rtc_cb->event);
}
示例#26
0
static void omap2_enter_full_retention(void)
{
	u32 l;
	struct timespec ts_preidle, ts_postidle, ts_idle;

	/* There is 1 reference hold for all children of the oscillator
	 * clock, the following will remove it. If no one else uses the
	 * oscillator itself it will be disabled if/when we enter retention
	 * mode.
	 */
	clk_disable(osc_ck);

	/* Clear old wake-up events */
	/* REVISIT: These write to reserved bits? */
	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
	prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);

	/*
	 * Set MPU powerdomain's next power state to RETENTION;
	 * preserve logic state during retention
	 */
	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);

	/* Workaround to kill USB */
	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);

	omap2_gpio_prepare_for_idle(PWRDM_POWER_RET);

	if (omap2_pm_debug) {
		omap2_pm_dump(0, 0, 0);
		getnstimeofday(&ts_preidle);
	}

	/* One last check for pending IRQs to avoid extra latency due
	 * to sleeping unnecessarily. */
	if (omap_irq_pending())
		goto no_sleep;

	omap_uart_prepare_idle(0);
	omap_uart_prepare_idle(1);
	omap_uart_prepare_idle(2);

	/* Jump to SRAM suspend code */
	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
			   OMAP_SDRC_REGADDR(SDRC_POWER));

	omap_uart_resume_idle(2);
	omap_uart_resume_idle(1);
	omap_uart_resume_idle(0);

no_sleep:
	if (omap2_pm_debug) {
		unsigned long long tmp;

		getnstimeofday(&ts_postidle);
		ts_idle = timespec_sub(ts_postidle, ts_preidle);
		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
		omap2_pm_dump(0, 1, tmp);
	}
	omap2_gpio_resume_after_idle();

	clk_enable(osc_ck);

	/* clear CORE wake-up events */
	prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1);
	prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);

	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
	prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST);

	/* MPU domain wake events */
	l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
	if (l & 0x01)
		prm_write_mod_reg(0x01, OCP_MOD,
				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
	if (l & 0x20)
		prm_write_mod_reg(0x20, OCP_MOD,
				  OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);

	/* Mask future PRCM-to-MPU interrupts */
	prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
}
示例#27
0
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
	uint32_t alarm_type_mask = 1U << alarm_type;
/*[[_SHP_STMC_BSP:[email protected] 2012-5-15 [Mod] [P120503-3333]
add auto power alarm for CHN feature */
#if defined(CONFIG_MACH_ZANIN_CHN_OPEN)
	char bootalarm_data[14];
#endif
/*]]_SHP_STMC_BSP:[email protected] 2012-5-15*/
	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
		return -EINVAL;

	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		alarm_try_to_cancel(&alarms[alarm_type]);
		if (alarm_pending) {
			alarm_pending &= ~alarm_type_mask;
			if (!alarm_pending && !wait_pending)
				wake_unlock(&alarm_wake_lock);
		}
		alarm_enabled &= ~alarm_type_mask;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
		alarm_enabled |= alarm_type_mask;
		alarm_start_range(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time),
			timespec_to_ktime(new_alarm_time));
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rv = alarm_set_rtc(new_rtc_time);
		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv < 0)
			goto err1;
		break;
/*[[_SHP_STMC_BSP:[email protected] 2012-5-15 [Mod] [P120503-3333]
add auto power alarm for CHN feature */
#if defined(CONFIG_MACH_ZANIN_CHN_OPEN)
	 case ANDROID_ALARM_SET_ALARM:					
	 	if (copy_from_user(bootalarm_data, (void __user *)arg, 14)) 
		{				
			printk("%s error!\n", __func__);				
			rv = -EFAULT;				
			goto err1;			
		}					
		printk("%s set alarm: %d\n", __func__,bootalarm_data);			
		rv = alarm_set_alarm(bootalarm_data);		
		break;
#endif
/*]]_SHP_STMC_BSP:[email protected] 2012-5-15*/
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			tmp_time =
				ktime_to_timespec(alarm_get_elapsed_realtime());
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}
/* return time in microseconds */
u64 bpf_get_usec_time(void)
{
	struct timespec now;
	getnstimeofday(&now);
	return (((u64)now.tv_sec) * 1000000) + now.tv_nsec / 1000;
}
/* -------------------------------------------------------------------- */
int fpc1020_capture_task(fpc1020_data_t *fpc1020)
{
	struct timespec ts_t1, ts_t2, ts_t3, ts_delta;
	int time_settings_us[FPC1020_BUFFER_MAX_IMAGES];
	int time_capture_us[FPC1020_BUFFER_MAX_IMAGES];
	int time_capture_sum_us;
	int error = 0;
	bool wait_finger_down = false;
	bool wait_finger_up = false;
	bool adjust_settings;
	fpc1020_capture_mode_t mode = fpc1020->capture.current_mode;
	int current_capture, capture_count;
	int image_offset;
	size_t image_byte_size;

	fpc1020->capture.state = FPC1020_CAPTURE_STATE_WRITE_SETTINGS;

	error = fpc1020_wake_up(fpc1020);
	if (error < 0)
		goto out_error;

	switch (mode) {
	case FPC1020_MODE_WAIT_AND_CAPTURE:
		wait_finger_down =
		wait_finger_up   = true;

	case FPC1020_MODE_SINGLE_CAPTURE:
	case FPC1020_MODE_SINGLE_CAPTURE_CAL:
		capture_count = fpc1020->setup.capture_count;
		adjust_settings = true;
		error = fpc1020_write_capture_setup(fpc1020);
		break;

	case FPC1020_MODE_CHECKERBOARD_TEST_NORM:
		capture_count = 1;
		adjust_settings = false;
		error = fpc1020_write_cb_test_setup(fpc1020, false);
		break;

	case FPC1020_MODE_CHECKERBOARD_TEST_INV:
		capture_count = 1;
		adjust_settings = false;
		error = fpc1020_write_cb_test_setup(fpc1020, true);
		break;

	case FPC1020_MODE_BOARD_TEST_ONE:
		capture_count = 1;
		adjust_settings = false;
		error = fpc1020_write_test_setup(fpc1020, 0xffff);
		break;

	case FPC1020_MODE_BOARD_TEST_ZERO:
		capture_count = 1;
		adjust_settings = false;
		error = fpc1020_write_test_setup(fpc1020, 0x0000);
		break;

	case FPC1020_MODE_WAIT_FINGER_DOWN:
		wait_finger_down = true;
		capture_count = 0;
		adjust_settings = false;
		error = fpc1020_write_capture_setup(fpc1020);
		break;

	case FPC1020_MODE_WAIT_FINGER_UP:
		wait_finger_up = true;
		capture_count = 0;
		adjust_settings = false;
		error = fpc1020_write_capture_setup(fpc1020);
		break;

	case FPC1020_MODE_IDLE:
	default:
		capture_count = 0;
		adjust_settings = false;
		error = -EINVAL;
		break;
	}

	if (error < 0)
		goto out_error;

	error = fpc1020_capture_set_crop(fpc1020,
					fpc1020->setup.capture_col_start,
					fpc1020->setup.capture_col_groups,
					fpc1020->setup.capture_row_start,
					fpc1020->setup.capture_row_count);
	if (error < 0)
		goto out_error;

	image_byte_size = fpc1020_calc_image_size(fpc1020);

	dev_dbg(&fpc1020->spi->dev,
		"Start capture, mode %d, (%d frames)\n",
		mode,
		capture_count);

	if (!wait_finger_down)
		fpc1020->capture.deferred_finger_up = false;

	if (wait_finger_down) {
		error = fpc1020_capture_finger_detect_settings(fpc1020);
		if (error < 0)
			goto out_error;
	}

	if (wait_finger_down && fpc1020->capture.deferred_finger_up) {
		fpc1020->capture.state =
				FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_UP;

		dev_dbg(&fpc1020->spi->dev, "Waiting for (deferred) finger up\n");

		error = fpc1020_capture_wait_finger_up(fpc1020);

		if (error < 0)
			goto out_error;

		dev_dbg(&fpc1020->spi->dev, "Finger up\n");

		fpc1020->capture.deferred_finger_up = false;
	}

	if (wait_finger_down) {
		fpc1020->capture.state =
				FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_DOWN;

		error = fpc1020_capture_wait_finger_down(fpc1020);

		if (error < 0)
			goto out_error;

		dev_dbg(&fpc1020->spi->dev, "Finger down\n");

		if (mode == FPC1020_MODE_WAIT_FINGER_DOWN) {

			fpc1020->capture.available_bytes = 4;
			fpc1020->huge_buffer[0] = 'F';
			fpc1020->huge_buffer[1] = ':';
			fpc1020->huge_buffer[2] = 'D';
			fpc1020->huge_buffer[3] = 'N';
		}
	}

	current_capture = 0;
	image_offset = 0;

	fpc1020->diag.last_capture_time = 0;

	if (mode == FPC1020_MODE_SINGLE_CAPTURE_CAL) {
		error = fpc1020_capture_set_sample_mode(fpc1020, true);
		if (error)
			goto out_error;
	}

	while (capture_count && (error >= 0))
	{
		getnstimeofday(&ts_t1);

		fpc1020->capture.state = FPC1020_CAPTURE_STATE_ACQUIRE;

		dev_dbg(&fpc1020->spi->dev,
			"Capture, frame #%d \n",
			current_capture + 1);

		error =	(!adjust_settings) ? 0 :
			fpc1020_capture_settings(fpc1020, current_capture);

		if (error < 0)
			goto out_error;

		getnstimeofday(&ts_t2);

		error = fpc1020_cmd(fpc1020,
				FPC1020_CMD_CAPTURE_IMAGE,
				FPC_1020_IRQ_REG_BIT_FIFO_NEW_DATA);

		if (error < 0)
			goto out_error;

		fpc1020->capture.state = FPC1020_CAPTURE_STATE_FETCH;

		error = fpc1020_fetch_image(fpc1020,
					    fpc1020->huge_buffer,
					    image_offset,
					    image_byte_size,
					    (size_t)fpc1020->huge_buffer_size);
		if (error < 0)
			goto out_error;

		fpc1020->capture.available_bytes += (error >= 0) ?
							(int)image_byte_size : 0;
		fpc1020->capture.last_error = error;

		getnstimeofday(&ts_t3);

		ts_delta = timespec_sub(ts_t2, ts_t1);
		time_settings_us[current_capture] =
			ts_delta.tv_sec * USEC_PER_SEC +
			(ts_delta.tv_nsec / NSEC_PER_USEC);

		ts_delta = timespec_sub(ts_t3, ts_t2);
		time_capture_us[current_capture] =
			ts_delta.tv_sec * USEC_PER_SEC +
			(ts_delta.tv_nsec / NSEC_PER_USEC);

		capture_count--;
		current_capture++;
		image_offset += (int)image_byte_size;
	}


	error = fpc1020_capture_set_sample_mode(fpc1020, false);
	if (error)
		goto out_error;


	if (mode != FPC1020_MODE_WAIT_FINGER_UP)
		wake_up_interruptible(&fpc1020->capture.wq_data_avail);

	if (wait_finger_up) {
		fpc1020->capture.state =
				FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_UP;

		error = fpc1020_capture_finger_detect_settings(fpc1020);
		if (error < 0)
			goto out_error;

		error = fpc1020_capture_wait_finger_up(fpc1020);

		if(error == -EINTR) {
			dev_dbg(&fpc1020->spi->dev, "Finger up check interrupted\n");
			fpc1020->capture.deferred_finger_up = true;
			goto out_interrupted;

		} else if (error < 0)
			goto out_error;

		if (mode == FPC1020_MODE_WAIT_FINGER_UP) {
			fpc1020->capture.available_bytes = 4;
			fpc1020->huge_buffer[0] = 'F';
			fpc1020->huge_buffer[1] = ':';
			fpc1020->huge_buffer[2] = 'U';
			fpc1020->huge_buffer[3] = 'P';

			wake_up_interruptible(&fpc1020->capture.wq_data_avail);
		}

		dev_dbg(&fpc1020->spi->dev, "Finger up\n");
	}

out_interrupted:

	capture_count = 0;
	time_capture_sum_us = 0;

	while (current_capture){

		current_capture--;

		dev_dbg(&fpc1020->spi->dev,
			"Frame #%d acq. time %d+%d=%d (us)\n",
			capture_count + 1,
			time_settings_us[capture_count],
			time_capture_us[capture_count],
			time_settings_us[capture_count] +
				time_capture_us[capture_count]);

		time_capture_sum_us += time_settings_us[capture_count];
		time_capture_sum_us += time_capture_us[capture_count];

		capture_count++;
	}
	fpc1020->diag.last_capture_time = time_capture_sum_us / 1000;

	dev_dbg(&fpc1020->spi->dev,
		"Total acq. time %d (us)\n", time_capture_sum_us);

out_error:
	fpc1020->capture.last_error = error;

	if (error) {
		fpc1020->capture.state = FPC1020_CAPTURE_STATE_FAILED;
		dev_err(&fpc1020->spi->dev, "%s %s %d\n", __func__,
			(error == -EINTR) ? "TERMINATED" : "FAILED", error);
	} else {
		fpc1020->capture.state = FPC1020_CAPTURE_STATE_COMPLETED;
		dev_dbg(&fpc1020->spi->dev, "%s OK\n", __func__);
	}
	return error;
}
static int read(int **buffer)
{
	int cnt;
	int len = 0;
	long sample_interval_us = 0;
	struct timespec read_timestamp;

	if (!on_primary_core()) {
		return 0;
	}

	/* Get the start of this sample period. */
	getnstimeofday(&read_timestamp);

	/*
	 * Calculate the sample interval if the previous sample time is valid.
	 * We use tv_sec since it will not be 0.
	 */
	if (prev_timestamp.tv_sec != 0) {
		sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp);
	}

	/* Structure copy. Update the previous timestamp. */
	prev_timestamp = read_timestamp;

	/*
	 * Report the timeline counters (ACTIVITY_START/STOP)
	 */
	for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) {
		mali_counter *counter = &counters[cnt];
		if (counter->enabled) {
			const int index = cnt - FIRST_TIMELINE_EVENT;
			unsigned int value;

			/* If the activity is still running, reset its start time to the start of this sample period
			 * to correct the count.  Add the time up to the end of the sample onto the count. */
			if (timeline_event_starttime[index].tv_sec != 0) {
				const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp);
				timeline_data[index] += event_duration;
				timeline_event_starttime[index] = read_timestamp;	/* Activity is still running. */
			}

			if (sample_interval_us != 0) {
				/* Convert the counter to a percent-of-sample value */
				value = (timeline_data[index] * 100) / sample_interval_us;
			} else {
				pr_debug("gator: Mali-T6xx: setting value to zero\n");
				value = 0;
			}

			/* Clear the counter value ready for the next sample. */
			timeline_data[index] = 0;

			counter_dump[len++] = counter->key;
			counter_dump[len++] = value;
		}
	}

	/* Report the software counters */
	for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) {
		const mali_counter *counter = &counters[cnt];
		if (counter->enabled) {
			const int index = cnt - FIRST_SOFTWARE_COUNTER;
			counter_dump[len++] = counter->key;
			counter_dump[len++] = sw_counter_data[index];
			/* Set the value to zero for the next time */
			sw_counter_data[index] = 0;
		}
	}

	/* Report the accumulators */
	for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) {
		const mali_counter *counter = &counters[cnt];
		if (counter->enabled) {
			const int index = cnt - FIRST_ACCUMULATOR;
			counter_dump[len++] = counter->key;
			counter_dump[len++] = accumulators_data[index];
			/* Do not zero the accumulator */
		}
	}

	/* Update the buffer */
	if (buffer) {
		*buffer = (int *)counter_dump;
	}

	return len;
}