PageRenderTime 61ms CodeModel.GetById 18ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/gpu/mali/mali/linux/mali_kernel_sysfs.c

https://bitbucket.org/ndreys/linux-sunxi
C | 1281 lines | 1025 code | 207 blank | 49 comment | 174 complexity | 8c9ab4aaae4dd787c42c781b0d146995 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
   1/**
   2 * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
   3 * 
   4 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
   5 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
   6 * 
   7 * A copy of the licence is included with the program, and can also be obtained from Free Software
   8 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   9 */
  10
  11
  12/**
  13 * @file mali_kernel_sysfs.c
  14 * Implementation of some sysfs data exports
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/fs.h>
  19#include <linux/device.h>
  20#include <linux/version.h>
  21#include <linux/module.h>
  22#include "mali_kernel_license.h"
  23#include "mali_kernel_common.h"
  24#include "mali_kernel_linux.h"
  25#include "mali_ukk.h"
  26
  27#if MALI_LICENSE_IS_GPL
  28
  29#include <linux/seq_file.h>
  30#include <linux/debugfs.h>
  31#include <asm/uaccess.h>
  32#include <linux/module.h>
  33#include "mali_kernel_sysfs.h"
  34#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
  35#include <linux/slab.h>
  36#include "mali_osk_profiling.h"
  37#endif
  38#include "mali_pm.h"
  39#include "mali_cluster.h"
  40#include "mali_group.h"
  41#include "mali_gp.h"
  42#include "mali_pp.h"
  43#include "mali_l2_cache.h"
  44#include "mali_hw_core.h"
  45#include "mali_kernel_core.h"
  46#include "mali_user_settings_db.h"
  47#include "mali_device_pause_resume.h"
  48
  49#define POWER_BUFFER_SIZE 3
  50
  51static struct dentry *mali_debugfs_dir = NULL;
  52
  53typedef enum
  54{
  55        _MALI_DEVICE_SUSPEND,
  56        _MALI_DEVICE_RESUME,
  57        _MALI_DEVICE_DVFS_PAUSE,
  58        _MALI_DEVICE_DVFS_RESUME,
  59        _MALI_MAX_EVENTS
  60} _mali_device_debug_power_events;
  61
  62static const char* const mali_power_events[_MALI_MAX_EVENTS] = {
  63        [_MALI_DEVICE_SUSPEND] = "suspend",
  64        [_MALI_DEVICE_RESUME] = "resume",
  65        [_MALI_DEVICE_DVFS_PAUSE] = "dvfs_pause",
  66        [_MALI_DEVICE_DVFS_RESUME] = "dvfs_resume",
  67};
  68
  69static u32 virtual_power_status_register=0;
  70static char pwr_buf[POWER_BUFFER_SIZE];
  71
  72static int open_copy_private_data(struct inode *inode, struct file *filp)
  73{
  74	filp->private_data = inode->i_private;
  75	return 0;
  76}
  77
  78static ssize_t gp_gpx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
  79{
  80	char buf[64];
  81	int r;
  82	u32 val;
  83	struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
  84
  85	if (0 == src_id)
  86	{
  87		val = mali_gp_core_get_counter_src0(gp_core);
  88	}
  89	else
  90	{
  91		val = mali_gp_core_get_counter_src1(gp_core);
  92	}
  93
  94	if (MALI_HW_CORE_NO_COUNTER == val)
  95	{
  96		r = sprintf(buf, "-1\n");
  97	}
  98	else
  99	{
 100		r = sprintf(buf, "%u\n", val);
 101	}
 102	return simple_read_from_buffer(ubuf, cnt, gpos, buf, r);
 103}
 104
 105static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
 106{
 107	struct mali_gp_core *gp_core = (struct mali_gp_core *)filp->private_data;
 108	char buf[64];
 109	long val;
 110	int ret;
 111
 112	if (cnt >= sizeof(buf))
 113	{
 114		return -EINVAL;
 115	}
 116
 117	if (copy_from_user(&buf, ubuf, cnt))
 118	{
 119		return -EFAULT;
 120	}
 121
 122	buf[cnt] = 0;
 123
 124	ret = strict_strtol(buf, 10, &val);
 125	if (ret < 0)
 126	{
 127		return ret;
 128	}
 129
 130	if (val < 0)
 131	{
 132		/* any negative input will disable counter */
 133		val = MALI_HW_CORE_NO_COUNTER;
 134	}
 135
 136	if (0 == src_id)
 137	{
 138		if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
 139		{
 140			return 0;
 141		}
 142	}
 143	else
 144	{
 145		if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
 146		{
 147			return 0;
 148		}
 149	}
 150
 151	*gpos += cnt;
 152	return cnt;
 153}
 154
 155static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
 156{
 157	char buf[64];
 158	long val;
 159	int ret;
 160	u32 ci;
 161	struct mali_cluster *cluster;
 162
 163	if (cnt >= sizeof(buf))
 164	{
 165		return -EINVAL;
 166	}
 167
 168	if (copy_from_user(&buf, ubuf, cnt))
 169	{
 170		return -EFAULT;
 171	}
 172
 173	buf[cnt] = 0;
 174
 175	ret = strict_strtol(buf, 10, &val);
 176	if (ret < 0)
 177	{
 178		return ret;
 179	}
 180
 181	if (val < 0)
 182	{
 183		/* any negative input will disable counter */
 184		val = MALI_HW_CORE_NO_COUNTER;
 185	}
 186
 187	ci = 0;
 188	cluster = mali_cluster_get_global_cluster(ci);
 189	while (NULL != cluster)
 190	{
 191		u32 gi = 0;
 192		struct mali_group *group = mali_cluster_get_group(cluster, gi);
 193		while (NULL != group)
 194		{
 195			struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
 196			if (NULL != gp_core)
 197			{
 198				if (0 == src_id)
 199				{
 200					if (MALI_TRUE != mali_gp_core_set_counter_src0(gp_core, (u32)val))
 201					{
 202						return 0;
 203					}
 204				}
 205				else
 206				{
 207					if (MALI_TRUE != mali_gp_core_set_counter_src1(gp_core, (u32)val))
 208					{
 209						return 0;
 210					}
 211				}				
 212			}
 213
 214			/* try next group */
 215			gi++;
 216			group = mali_cluster_get_group(cluster, gi);
 217		}
 218
 219		/* try next cluster */
 220		ci++;
 221		cluster = mali_cluster_get_global_cluster(ci);
 222	}
 223
 224	*gpos += cnt;
 225	return cnt;
 226}
 227
 228static ssize_t gp_gpx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
 229{
 230	return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 0);
 231}
 232
 233static ssize_t gp_gpx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *gpos)
 234{
 235	return gp_gpx_counter_srcx_read(filp, ubuf, cnt, gpos, 1);
 236}
 237
 238static ssize_t gp_gpx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
 239{
 240	return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
 241}
 242
 243static ssize_t gp_gpx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
 244{
 245	return gp_gpx_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
 246}
 247
 248static ssize_t gp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
 249{
 250	return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 0);
 251}
 252
 253static ssize_t gp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos)
 254{
 255	return gp_all_counter_srcx_write(filp, ubuf, cnt, gpos, 1);
 256}
 257
 258static const struct file_operations gp_gpx_counter_src0_fops = {
 259	.owner = THIS_MODULE,
 260	.open  = open_copy_private_data,
 261	.read  = gp_gpx_counter_src0_read,
 262	.write = gp_gpx_counter_src0_write,
 263};
 264
 265static const struct file_operations gp_gpx_counter_src1_fops = {
 266	.owner = THIS_MODULE,
 267	.open  = open_copy_private_data,
 268	.read  = gp_gpx_counter_src1_read,
 269	.write = gp_gpx_counter_src1_write,
 270};
 271
 272static const struct file_operations gp_all_counter_src0_fops = {
 273	.owner = THIS_MODULE,
 274	.write = gp_all_counter_src0_write,
 275};
 276
 277static const struct file_operations gp_all_counter_src1_fops = {
 278	.owner = THIS_MODULE,
 279	.write = gp_all_counter_src1_write,
 280};
 281
 282static ssize_t pp_ppx_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
 283{
 284	char buf[64];
 285	int r;
 286	u32 val;
 287	struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
 288
 289	if (0 == src_id)
 290	{
 291		val = mali_pp_core_get_counter_src0(pp_core);
 292	}
 293	else
 294	{
 295		val = mali_pp_core_get_counter_src1(pp_core);
 296	}
 297
 298	if (MALI_HW_CORE_NO_COUNTER == val)
 299	{
 300		r = sprintf(buf, "-1\n");
 301	}
 302	else
 303	{
 304		r = sprintf(buf, "%u\n", val);
 305	}
 306	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
 307}
 308
 309static ssize_t pp_ppx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
 310{
 311	struct mali_pp_core *pp_core = (struct mali_pp_core *)filp->private_data;
 312	char buf[64];
 313	long val;
 314	int ret;
 315
 316	if (cnt >= sizeof(buf))
 317	{
 318		return -EINVAL;
 319	}
 320
 321	if (copy_from_user(&buf, ubuf, cnt))
 322	{
 323		return -EFAULT;
 324	}
 325
 326	buf[cnt] = 0;
 327
 328	ret = strict_strtol(buf, 10, &val);
 329	if (ret < 0)
 330	{
 331		return ret;
 332	}
 333
 334	if (val < 0)
 335	{
 336		/* any negative input will disable counter */
 337		val = MALI_HW_CORE_NO_COUNTER;
 338	}
 339
 340	if (0 == src_id)
 341	{
 342		if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
 343		{
 344			return 0;
 345		}
 346	}
 347	else
 348	{
 349		if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
 350		{
 351			return 0;
 352		}
 353	}
 354
 355	*ppos += cnt;
 356	return cnt;
 357}
 358
 359static ssize_t pp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
 360{
 361	char buf[64];
 362	long val;
 363	int ret;
 364	u32 ci;
 365	struct mali_cluster *cluster;
 366
 367	if (cnt >= sizeof(buf))
 368	{
 369		return -EINVAL;
 370	}
 371
 372	if (copy_from_user(&buf, ubuf, cnt))
 373	{
 374		return -EFAULT;
 375	}
 376
 377	buf[cnt] = 0;
 378
 379	ret = strict_strtol(buf, 10, &val);
 380	if (ret < 0)
 381	{
 382		return ret;
 383	}
 384
 385	if (val < 0)
 386	{
 387		/* any negative input will disable counter */
 388		val = MALI_HW_CORE_NO_COUNTER;
 389	}
 390
 391	ci = 0;
 392	cluster = mali_cluster_get_global_cluster(ci);
 393	while (NULL != cluster)
 394	{
 395		u32 gi = 0;
 396		struct mali_group *group = mali_cluster_get_group(cluster, gi);
 397		while (NULL != group)
 398		{
 399			struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
 400			if (NULL != pp_core)
 401			{
 402				if (0 == src_id)
 403				{
 404					if (MALI_TRUE != mali_pp_core_set_counter_src0(pp_core, (u32)val))
 405					{
 406						return 0;
 407					}
 408				}
 409				else
 410				{
 411					if (MALI_TRUE != mali_pp_core_set_counter_src1(pp_core, (u32)val))
 412					{
 413						return 0;
 414					}
 415				}				
 416			}
 417
 418			/* try next group */
 419			gi++;
 420			group = mali_cluster_get_group(cluster, gi);
 421		}
 422
 423		/* try next cluster */
 424		ci++;
 425		cluster = mali_cluster_get_global_cluster(ci);
 426	}
 427
 428	*ppos += cnt;
 429	return cnt;
 430}
 431
 432static ssize_t pp_ppx_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 433{
 434	return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
 435}
 436
 437static ssize_t pp_ppx_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 438{
 439	return pp_ppx_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
 440}
 441
 442static ssize_t pp_ppx_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 443{
 444	return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
 445}
 446
 447static ssize_t pp_ppx_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 448{
 449	return pp_ppx_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
 450}
 451
 452static ssize_t pp_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 453{
 454	return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
 455}
 456
 457static ssize_t pp_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 458{
 459	return pp_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
 460}
 461
 462static const struct file_operations pp_ppx_counter_src0_fops = {
 463	.owner = THIS_MODULE,
 464	.open  = open_copy_private_data,
 465	.read  = pp_ppx_counter_src0_read,
 466	.write = pp_ppx_counter_src0_write,
 467};
 468
 469static const struct file_operations pp_ppx_counter_src1_fops = {
 470	.owner = THIS_MODULE,
 471	.open  = open_copy_private_data,
 472	.read  = pp_ppx_counter_src1_read,
 473	.write = pp_ppx_counter_src1_write,
 474};
 475
 476static const struct file_operations pp_all_counter_src0_fops = {
 477	.owner = THIS_MODULE,
 478	.write = pp_all_counter_src0_write,
 479};
 480
 481static const struct file_operations pp_all_counter_src1_fops = {
 482	.owner = THIS_MODULE,
 483	.write = pp_all_counter_src1_write,
 484};
 485
 486
 487
 488
 489
 490
 491static ssize_t l2_l2x_counter_srcx_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
 492{
 493	char buf[64];
 494	int r;
 495	u32 val;
 496	struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
 497
 498	if (0 == src_id)
 499	{
 500		val = mali_l2_cache_core_get_counter_src0(l2_core);
 501	}
 502	else
 503	{
 504		val = mali_l2_cache_core_get_counter_src1(l2_core);
 505	}
 506
 507	if (MALI_HW_CORE_NO_COUNTER == val)
 508	{
 509		r = sprintf(buf, "-1\n");
 510	}
 511	else
 512	{
 513		r = sprintf(buf, "%u\n", val);
 514	}
 515	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
 516}
 517
 518static ssize_t l2_l2x_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
 519{
 520	struct mali_l2_cache_core *l2_core = (struct mali_l2_cache_core *)filp->private_data;
 521	char buf[64];
 522	long val;
 523	int ret;
 524
 525	if (cnt >= sizeof(buf))
 526	{
 527		return -EINVAL;
 528	}
 529
 530	if (copy_from_user(&buf, ubuf, cnt))
 531	{
 532		return -EFAULT;
 533	}
 534
 535	buf[cnt] = 0;
 536
 537	ret = strict_strtol(buf, 10, &val);
 538	if (ret < 0)
 539	{
 540		return ret;
 541	}
 542
 543	if (val < 0)
 544	{
 545		/* any negative input will disable counter */
 546		val = MALI_HW_CORE_NO_COUNTER;
 547	}
 548
 549	if (0 == src_id)
 550	{
 551		if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_core, (u32)val))
 552		{
 553			return 0;
 554		}
 555	}
 556	else
 557	{
 558		if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_core, (u32)val))
 559		{
 560			return 0;
 561		}
 562	}
 563
 564	*ppos += cnt;
 565	return cnt;
 566}
 567
 568static ssize_t l2_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, u32 src_id)
 569{
 570	char buf[64];
 571	long val;
 572	int ret;
 573	u32 l2_id;
 574	struct mali_l2_cache_core *l2_cache;
 575
 576	if (cnt >= sizeof(buf))
 577	{
 578		return -EINVAL;
 579	}
 580
 581	if (copy_from_user(&buf, ubuf, cnt))
 582	{
 583		return -EFAULT;
 584	}
 585
 586	buf[cnt] = 0;
 587
 588	ret = strict_strtol(buf, 10, &val);
 589	if (ret < 0)
 590	{
 591		return ret;
 592	}
 593
 594	if (val < 0)
 595	{
 596		/* any negative input will disable counter */
 597		val = MALI_HW_CORE_NO_COUNTER;
 598	}
 599
 600	l2_id = 0;
 601	l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
 602	while (NULL != l2_cache)
 603	{
 604		if (0 == src_id)
 605		{
 606			if (MALI_TRUE != mali_l2_cache_core_set_counter_src0(l2_cache, (u32)val))
 607			{
 608				return 0;
 609			}
 610		}
 611		else
 612		{
 613			if (MALI_TRUE != mali_l2_cache_core_set_counter_src1(l2_cache, (u32)val))
 614			{
 615				return 0;
 616			}
 617		}				
 618		
 619		/* try next L2 */
 620		l2_id++;
 621		l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
 622	}
 623
 624	*ppos += cnt;
 625	return cnt;
 626}
 627
 628static ssize_t l2_l2x_counter_src0_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 629{
 630	return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 0);
 631}
 632
 633static ssize_t l2_l2x_counter_src1_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 634{
 635	return l2_l2x_counter_srcx_read(filp, ubuf, cnt, ppos, 1);
 636}
 637
 638static ssize_t l2_l2x_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 639{
 640	return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
 641}
 642
 643static ssize_t l2_l2x_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 644{
 645	return l2_l2x_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
 646}
 647
 648static ssize_t l2_all_counter_src0_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 649{
 650	return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 0);
 651}
 652
 653static ssize_t l2_all_counter_src1_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 654{
 655	return l2_all_counter_srcx_write(filp, ubuf, cnt, ppos, 1);
 656}
 657
 658static const struct file_operations l2_l2x_counter_src0_fops = {
 659	.owner = THIS_MODULE,
 660	.open  = open_copy_private_data,
 661	.read  = l2_l2x_counter_src0_read,
 662	.write = l2_l2x_counter_src0_write,
 663};
 664
 665static const struct file_operations l2_l2x_counter_src1_fops = {
 666	.owner = THIS_MODULE,
 667	.open  = open_copy_private_data,
 668	.read  = l2_l2x_counter_src1_read,
 669	.write = l2_l2x_counter_src1_write,
 670};
 671
 672static const struct file_operations l2_all_counter_src0_fops = {
 673	.owner = THIS_MODULE,
 674	.write = l2_all_counter_src0_write,
 675};
 676
 677static const struct file_operations l2_all_counter_src1_fops = {
 678	.owner = THIS_MODULE,
 679	.write = l2_all_counter_src1_write,
 680};
 681
 682static ssize_t power_events_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 683{
 684	
 685	memset(pwr_buf,0,POWER_BUFFER_SIZE);
 686	virtual_power_status_register = 0;
 687	if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_SUSPEND],strlen(mali_power_events[_MALI_DEVICE_SUSPEND])))
 688	{
 689		mali_pm_os_suspend();
 690		/* @@@@ assuming currently suspend is successful later on to tune as per previous*/
 691		virtual_power_status_register =1;
 692
 693	}
 694	else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_RESUME],strlen(mali_power_events[_MALI_DEVICE_RESUME])))
 695	{
 696		mali_pm_os_resume();
 697
 698		/* @@@@ assuming currently resume is successful later on to tune as per previous */
 699		virtual_power_status_register = 1;
 700	}
 701	else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_PAUSE],strlen(mali_power_events[_MALI_DEVICE_DVFS_PAUSE])))
 702	{
 703		mali_bool power_on;
 704		mali_dev_pause(&power_on);
 705		if (!power_on)
 706		{
 707			virtual_power_status_register = 2;
 708			mali_dev_resume();		
 709		}
 710		else
 711		{
 712			/*  @@@@ assuming currently resume is successful later on to tune as per previous */
 713			virtual_power_status_register =1;
 714		}
 715	}
 716	else if (!strncmp(ubuf,mali_power_events[_MALI_DEVICE_DVFS_RESUME],strlen(mali_power_events[_MALI_DEVICE_DVFS_RESUME])))
 717	{
 718		mali_dev_resume();
 719		/*  @@@@ assuming currently resume is successful later on to tune as per previous */
 720		virtual_power_status_register = 1;
 721                
 722	}
 723	*ppos += cnt;
 724	sprintf(pwr_buf, "%d",virtual_power_status_register);
 725	return cnt;
 726}
 727
 728static ssize_t power_events_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 729{
 730	return simple_read_from_buffer(ubuf, cnt, ppos, pwr_buf, POWER_BUFFER_SIZE);
 731}
 732
 733static loff_t power_events_seek(struct file *file, loff_t offset, int orig)
 734{
 735	file->f_pos = offset;
 736        return 0;
 737}
 738
 739static const struct file_operations power_events_fops = {
 740	.owner = THIS_MODULE,
 741	.read  = power_events_read,
 742	.write = power_events_write,
 743	.llseek = power_events_seek,
 744};
 745
 746
 747#if MALI_STATE_TRACKING
 748static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v)
 749{
 750	u32 len = 0;
 751	u32 size;
 752	char *buf;
 753
 754	size = seq_get_buf(seq_file, &buf);
 755
 756	if(!size)
 757	{
 758			return -ENOMEM;
 759	}
 760
 761	/* Create the internal state dump. */
 762	len  = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING);
 763	len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE);
 764
 765	len += _mali_kernel_core_dump_state(buf + len, size - len);
 766
 767	seq_commit(seq_file, len);
 768
 769	return 0;
 770}
 771
 772static int mali_seq_internal_state_open(struct inode *inode, struct file *file)
 773{
 774	return single_open(file, mali_seq_internal_state_show, NULL);
 775}
 776
 777static const struct file_operations mali_seq_internal_state_fops = {
 778	.owner = THIS_MODULE,
 779	.open = mali_seq_internal_state_open,
 780	.read = seq_read,
 781	.llseek = seq_lseek,
 782	.release = single_release,
 783};
 784#endif /* MALI_STATE_TRACKING */
 785
 786
 787#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
 788static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 789{
 790	char buf[64];
 791	int r;
 792
 793	r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0);
 794	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
 795}
 796
 797static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 798{
 799	char buf[64];
 800	unsigned long val;
 801	int ret;
 802
 803	if (cnt >= sizeof(buf))
 804	{
 805		return -EINVAL;
 806	}
 807
 808	if (copy_from_user(&buf, ubuf, cnt))
 809	{
 810		return -EFAULT;
 811	}
 812
 813	buf[cnt] = 0;
 814
 815	ret = strict_strtoul(buf, 10, &val);
 816	if (ret < 0)
 817	{
 818		return ret;
 819	}
 820
 821	if (val != 0)
 822	{
 823		u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */
 824
 825		/* check if we are already recording */
 826		if (MALI_TRUE == _mali_osk_profiling_is_recording())
 827		{
 828			MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n"));
 829			return -EFAULT;
 830		}
 831
 832		/* check if we need to clear out an old recording first */
 833		if (MALI_TRUE == _mali_osk_profiling_have_recording())
 834		{
 835			if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear())
 836			{
 837				MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n"));
 838				return -EFAULT;
 839			}
 840		}
 841
 842		/* start recording profiling data */
 843		if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit))
 844		{
 845			MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n"));
 846			return -EFAULT;
 847		}
 848
 849		MALI_DEBUG_PRINT(3, ("Profiling recording started (max %u events)\n", limit));
 850	}
 851	else
 852	{
 853		/* stop recording profiling data */
 854		u32 count = 0;
 855		if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count))
 856		{
 857			MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n"));
 858			return -EFAULT;
 859		}
 860		
 861		MALI_DEBUG_PRINT(2, ("Profiling recording stopped (recorded %u events)\n", count));
 862	}
 863
 864	*ppos += cnt;
 865	return cnt;
 866}
 867
 868static const struct file_operations profiling_record_fops = {
 869	.owner = THIS_MODULE,
 870	.read  = profiling_record_read,
 871	.write = profiling_record_write,
 872};
 873
 874static void *profiling_events_start(struct seq_file *s, loff_t *pos)
 875{
 876	loff_t *spos;
 877
 878	/* check if we have data avaiable */
 879	if (MALI_TRUE != _mali_osk_profiling_have_recording())
 880	{
 881		return NULL;
 882	}
 883
 884	spos = kmalloc(sizeof(loff_t), GFP_KERNEL);
 885	if (NULL == spos)
 886	{
 887		return NULL;
 888	}
 889
 890	*spos = *pos;
 891	return spos;
 892}
 893
 894static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos)
 895{
 896	loff_t *spos = v;
 897
 898	/* check if we have data avaiable */
 899	if (MALI_TRUE != _mali_osk_profiling_have_recording())
 900	{
 901		return NULL;
 902	}
 903
 904	/* check if the next entry actually is avaiable */
 905	if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1))
 906	{
 907		return NULL;
 908	}
 909
 910	*pos = ++*spos;
 911	return spos;
 912}
 913
 914static void profiling_events_stop(struct seq_file *s, void *v)
 915{
 916	kfree(v);
 917}
 918
 919static int profiling_events_show(struct seq_file *seq_file, void *v)
 920{
 921	loff_t *spos = v;
 922	u32 index;
 923	u64 timestamp;
 924	u32 event_id;
 925	u32 data[5];
 926
 927	index = (u32)*spos;
 928
 929	/* Retrieve all events */
 930	if (_MALI_OSK_ERR_OK == _mali_osk_profiling_get_event(index, &timestamp, &event_id, data))
 931	{
 932		seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]);
 933		return 0;
 934	}
 935
 936	return 0;
 937}
 938
 939static const struct seq_operations profiling_events_seq_ops = {
 940	.start = profiling_events_start,
 941	.next  = profiling_events_next,
 942	.stop  = profiling_events_stop,
 943	.show  = profiling_events_show
 944};
 945
 946static int profiling_events_open(struct inode *inode, struct file *file)
 947{
 948	return seq_open(file, &profiling_events_seq_ops);
 949}
 950
 951static const struct file_operations profiling_events_fops = {
 952	.owner = THIS_MODULE,
 953	.open = profiling_events_open,
 954	.read = seq_read,
 955	.llseek = seq_lseek,
 956	.release = seq_release,
 957};
 958#endif
 959
 960static ssize_t memory_used_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 961{
 962	char buf[64];
 963	size_t r;
 964	u32 mem = _mali_ukk_report_memory_usage();
 965
 966	r = snprintf(buf, 64, "%u\n", mem);
 967	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
 968}
 969
 970static const struct file_operations memory_usage_fops = {
 971	.owner = THIS_MODULE,
 972	.read = memory_used_read,
 973};
 974
 975
 976static ssize_t user_settings_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
 977{
 978	unsigned long val;
 979	int ret;
 980	_mali_uk_user_setting_t setting;
 981	char buf[32];
 982
 983	cnt = min(cnt, sizeof(buf) - 1);
 984	if (copy_from_user(buf, ubuf, cnt))
 985	{
 986		return -EFAULT;
 987	}
 988	buf[cnt] = '\0';
 989
 990	ret = strict_strtoul(buf, 10, &val);
 991	if (0 != ret)
 992	{
 993		return ret;
 994	}
 995
 996	/* Update setting */
 997	setting = (_mali_uk_user_setting_t)(filp->private_data);
 998	mali_set_user_setting(setting, val);
 999
1000	*ppos += cnt;
1001	return cnt;
1002}
1003
1004static ssize_t user_settings_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
1005{
1006	char buf[64];
1007	size_t r;
1008	u32 value;
1009	_mali_uk_user_setting_t setting;
1010
1011	setting = (_mali_uk_user_setting_t)(filp->private_data);
1012	value = mali_get_user_setting(setting);
1013
1014	r = snprintf(buf, 64, "%u\n", value);
1015	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
1016}
1017
1018static const struct file_operations user_settings_fops = {
1019	.owner = THIS_MODULE,
1020	.open = open_copy_private_data,
1021	.read = user_settings_read,
1022	.write = user_settings_write,
1023};
1024
1025static int mali_sysfs_user_settings_register(void)
1026{
1027	struct dentry *mali_user_settings_dir = debugfs_create_dir("userspace_settings", mali_debugfs_dir);
1028
1029	if (mali_user_settings_dir != NULL)
1030	{
1031		int i;
1032		for (i = 0; i < _MALI_UK_USER_SETTING_MAX; i++)
1033		{
1034			debugfs_create_file(_mali_uk_user_setting_descriptions[i], 0600, mali_user_settings_dir, (void*)i, &user_settings_fops);
1035		}
1036	}
1037
1038	return 0;
1039}
1040
1041int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1042{
1043	int err = 0;
1044	struct device * mdev;
1045
1046	device->mali_class = class_create(THIS_MODULE, mali_dev_name);
1047	if (IS_ERR(device->mali_class))
1048	{
1049		err = PTR_ERR(device->mali_class);
1050		goto init_class_err;
1051	}
1052	mdev = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name);
1053	if (IS_ERR(mdev))
1054	{
1055		err = PTR_ERR(mdev);
1056		goto init_mdev_err;
1057	}
1058
1059	mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL);
1060	if(ERR_PTR(-ENODEV) == mali_debugfs_dir)
1061	{
1062		/* Debugfs not supported. */
1063		mali_debugfs_dir = NULL;
1064	}
1065	else
1066	{
1067		if(NULL != mali_debugfs_dir)
1068		{
1069			/* Debugfs directory created successfully; create files now */
1070			struct dentry *mali_power_dir;
1071			struct dentry *mali_gp_dir;
1072			struct dentry *mali_pp_dir;
1073			struct dentry *mali_l2_dir;
1074#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
1075			struct dentry *mali_profiling_dir;
1076#endif
1077
1078			mali_power_dir = debugfs_create_dir("power", mali_debugfs_dir);
1079			if (mali_power_dir != NULL)
1080			{
1081				debugfs_create_file("power_events", 0400, mali_power_dir, NULL, &power_events_fops);
1082			}
1083
1084			mali_gp_dir = debugfs_create_dir("gp", mali_debugfs_dir);
1085			if (mali_gp_dir != NULL)
1086			{
1087				struct dentry *mali_gp_all_dir;
1088				u32 ci;
1089				struct mali_cluster *cluster;
1090
1091				mali_gp_all_dir = debugfs_create_dir("all", mali_gp_dir);
1092				if (mali_gp_all_dir != NULL)
1093				{
1094					debugfs_create_file("counter_src0", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src0_fops);
1095					debugfs_create_file("counter_src1", 0400, mali_gp_all_dir, NULL, &gp_all_counter_src1_fops);
1096				}
1097
1098				ci = 0;
1099				cluster = mali_cluster_get_global_cluster(ci);
1100				while (NULL != cluster)
1101				{
1102					u32 gi = 0;
1103					struct mali_group *group = mali_cluster_get_group(cluster, gi);
1104					while (NULL != group)
1105					{
1106						struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
1107						if (NULL != gp_core)
1108						{
1109							struct dentry *mali_gp_gpx_dir;
1110							mali_gp_gpx_dir = debugfs_create_dir("gp0", mali_gp_dir);
1111							if (NULL != mali_gp_gpx_dir)
1112							{
1113								debugfs_create_file("counter_src0", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src0_fops);
1114								debugfs_create_file("counter_src1", 0600, mali_gp_gpx_dir, gp_core, &gp_gpx_counter_src1_fops);
1115							}
1116							break; /* no need to look for any other GP cores */
1117						}
1118
1119						/* try next group */
1120						gi++;
1121						group = mali_cluster_get_group(cluster, gi);
1122					}
1123
1124					/* try next cluster */
1125					ci++;
1126					cluster = mali_cluster_get_global_cluster(ci);
1127				}
1128			}
1129
1130			mali_pp_dir = debugfs_create_dir("pp", mali_debugfs_dir);
1131			if (mali_pp_dir != NULL)
1132			{
1133				struct dentry *mali_pp_all_dir;
1134				u32 ci;
1135				struct mali_cluster *cluster;
1136
1137				mali_pp_all_dir = debugfs_create_dir("all", mali_pp_dir);
1138				if (mali_pp_all_dir != NULL)
1139				{
1140					debugfs_create_file("counter_src0", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src0_fops);
1141					debugfs_create_file("counter_src1", 0400, mali_pp_all_dir, NULL, &pp_all_counter_src1_fops);
1142				}
1143
1144				ci = 0;
1145				cluster = mali_cluster_get_global_cluster(ci);
1146				while (NULL != cluster)
1147				{
1148					u32 gi = 0;
1149					struct mali_group *group = mali_cluster_get_group(cluster, gi);
1150					while (NULL != group)
1151					{
1152						struct mali_pp_core *pp_core = mali_group_get_pp_core(group);
1153						if (NULL != pp_core)
1154						{
1155							char buf[16];
1156							struct dentry *mali_pp_ppx_dir;
1157							_mali_osk_snprintf(buf, sizeof(buf), "pp%u", mali_pp_core_get_id(pp_core));
1158							mali_pp_ppx_dir = debugfs_create_dir(buf, mali_pp_dir);
1159							if (NULL != mali_pp_ppx_dir)
1160							{
1161								debugfs_create_file("counter_src0", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src0_fops);
1162								debugfs_create_file("counter_src1", 0600, mali_pp_ppx_dir, pp_core, &pp_ppx_counter_src1_fops);
1163							}
1164						}
1165
1166						/* try next group */
1167						gi++;
1168						group = mali_cluster_get_group(cluster, gi);
1169					}
1170
1171					/* try next cluster */
1172					ci++;
1173					cluster = mali_cluster_get_global_cluster(ci);
1174				}
1175			}
1176
1177			mali_l2_dir = debugfs_create_dir("l2", mali_debugfs_dir);
1178			if (mali_l2_dir != NULL)
1179			{
1180				struct dentry *mali_l2_all_dir;
1181				u32 l2_id;
1182				struct mali_l2_cache_core *l2_cache;
1183
1184				mali_l2_all_dir = debugfs_create_dir("all", mali_l2_dir);
1185				if (mali_l2_all_dir != NULL)
1186				{
1187					debugfs_create_file("counter_src0", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src0_fops);
1188					debugfs_create_file("counter_src1", 0400, mali_l2_all_dir, NULL, &l2_all_counter_src1_fops);
1189				}
1190
1191				l2_id = 0;
1192				l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1193				while (NULL != l2_cache)
1194				{
1195					char buf[16];
1196					struct dentry *mali_l2_l2x_dir;
1197					_mali_osk_snprintf(buf, sizeof(buf), "l2%u", l2_id);
1198					mali_l2_l2x_dir = debugfs_create_dir(buf, mali_l2_dir);
1199					if (NULL != mali_l2_l2x_dir)
1200					{
1201						debugfs_create_file("counter_src0", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src0_fops);
1202						debugfs_create_file("counter_src1", 0600, mali_l2_l2x_dir, l2_cache, &l2_l2x_counter_src1_fops);
1203					}
1204					
1205					/* try next L2 */
1206					l2_id++;
1207					l2_cache = mali_l2_cache_core_get_glob_l2_core(l2_id);
1208				}
1209			}
1210
1211			debugfs_create_file("memory_usage", 0400, mali_debugfs_dir, NULL, &memory_usage_fops);
1212
1213#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED
1214			mali_profiling_dir = debugfs_create_dir("profiling", mali_debugfs_dir);
1215			if (mali_profiling_dir != NULL)
1216			{
1217				struct dentry *mali_profiling_proc_dir = debugfs_create_dir("proc", mali_profiling_dir);
1218				if (mali_profiling_proc_dir != NULL)
1219				{
1220					struct dentry *mali_profiling_proc_default_dir = debugfs_create_dir("default", mali_profiling_proc_dir);
1221					if (mali_profiling_proc_default_dir != NULL)
1222					{
1223						debugfs_create_file("enable", 0600, mali_profiling_proc_default_dir, (void*)_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, &user_settings_fops);
1224					}
1225				}
1226				debugfs_create_file("record", 0600, mali_profiling_dir, NULL, &profiling_record_fops);
1227				debugfs_create_file("events", 0400, mali_profiling_dir, NULL, &profiling_events_fops);
1228			}
1229#endif
1230
1231#if MALI_STATE_TRACKING
1232			debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops);
1233#endif
1234
1235			if (mali_sysfs_user_settings_register())
1236			{
1237				/* Failed to create the debugfs entries for the user settings DB. */
1238				MALI_DEBUG_PRINT(2, ("Failed to create user setting debugfs files. Ignoring...\n"));
1239			}
1240		}
1241	}
1242
1243	/* Success! */
1244	return 0;
1245
1246	/* Error handling */
1247init_mdev_err:
1248	class_destroy(device->mali_class);
1249init_class_err:
1250
1251	return err;
1252}
1253
1254int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1255{
1256	if(NULL != mali_debugfs_dir)
1257	{
1258		debugfs_remove_recursive(mali_debugfs_dir);
1259	}
1260	device_destroy(device->mali_class, dev);
1261	class_destroy(device->mali_class);
1262
1263	return 0;
1264}
1265
1266#else
1267
1268/* Dummy implementations for non-GPL */
1269
1270int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1271{
1272	return 0;
1273}
1274
1275int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name)
1276{
1277	return 0;
1278}
1279
1280
1281#endif