summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRik Faith <faith@alephnull.com>2001-02-09 16:00:14 +0000
committerRik Faith <faith@alephnull.com>2001-02-09 16:00:14 +0000
commitdb6b1ce9b814f36431dee6468cfb60e47222831e (patch)
treee8c695a945c7a7ba5877c7013b89a2ac6618ecb1
parent9a426ec53e78d0e91e47b28c9bcf52f3585a7c1d (diff)
Add extensible counters for statistics via ioctl
-rw-r--r--linux-core/drmP.h19
-rw-r--r--linux-core/drm_context.c2
-rw-r--r--linux-core/drm_drv.c64
-rw-r--r--linux-core/drm_ioctl.c31
-rw-r--r--linux-core/drm_proc.c22
-rw-r--r--linux-core/mga_drv.c6
-rw-r--r--linux/drm.h27
-rw-r--r--linux/drmP.h19
-rw-r--r--linux/drm_context.h2
-rw-r--r--linux/drm_drv.h64
-rw-r--r--linux/drm_ioctl.h31
-rw-r--r--linux/drm_proc.h22
-rw-r--r--linux/mga_dma.c8
-rw-r--r--linux/mga_drv.c6
-rw-r--r--shared-core/drm.h27
-rw-r--r--shared/drm.h27
-rw-r--r--tests/dristat.c220
17 files changed, 504 insertions, 93 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 3270952e..f4052f01 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -485,6 +485,7 @@ typedef struct drm_lock_data {
} drm_lock_data_t;
typedef struct drm_device_dma {
+#if 0
/* Performance Counters */
atomic_t total_prio; /* Total DRM_DMA_PRIORITY */
atomic_t total_bytes; /* Total bytes DMA'd */
@@ -498,6 +499,7 @@ typedef struct drm_device_dma {
atomic_t total_tried; /* Tried next_buffer */
atomic_t total_hit; /* Sent next_buffer */
atomic_t total_lost; /* Lost interrupt */
+#endif
drm_buf_entry_t bufs[DRM_MAX_ORDER+1];
int buf_count;
@@ -565,17 +567,10 @@ typedef struct drm_device {
int buf_use; /* Buffers in use -- cannot alloc */
atomic_t buf_alloc; /* Buffer allocation in progress */
- /* Performance Counters */
- atomic_t total_open;
- atomic_t total_close;
- atomic_t total_ioctl;
- atomic_t total_irq; /* Total interruptions */
- atomic_t total_ctx; /* Total context switches */
-
- atomic_t total_locks;
- atomic_t total_unlocks;
- atomic_t total_contends;
- atomic_t total_sleeps;
+ /* Performance counters */
+ unsigned long counters;
+ drm_stat_type_t types[15];
+ atomic_t counts[15];
/* Authentication */
drm_file_t *file_first;
@@ -732,6 +727,8 @@ extern int DRM(getmap)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(getclient)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int DRM(getstats)(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* Context IOCTL support (context.c) */
extern int DRM(resctx)( struct inode *inode, struct file *filp,
diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c
index fd2cf94d..6bbcfca8 100644
--- a/linux-core/drm_context.c
+++ b/linux-core/drm_context.c
@@ -93,8 +93,6 @@ int DRM(context_switch)( drm_device_t *dev, int old, int new )
{
char buf[64];
- atomic_inc( &dev->total_ctx );
-
if ( test_and_set_bit( 0, &dev->context_flag ) ) {
DRM_ERROR( "Reentering -- FIXME\n" );
return -EBUSY;
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 18935309..7999b140 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -146,15 +146,46 @@ static int DRM(setup)( drm_device_t *dev )
return i;
#endif
- atomic_set( &dev->total_open, 0 );
- atomic_set( &dev->total_close, 0 );
- atomic_set( &dev->total_ioctl, 0 );
- atomic_set( &dev->total_irq, 0 );
- atomic_set( &dev->total_ctx, 0 );
- atomic_set( &dev->total_locks, 0 );
- atomic_set( &dev->total_unlocks, 0 );
- atomic_set( &dev->total_contends, 0 );
- atomic_set( &dev->total_sleeps, 0 );
+ dev->counters = 6 + __HAVE_COUNTERS;
+ dev->types[0] = _DRM_STAT_LOCK;
+ dev->types[1] = _DRM_STAT_OPENS;
+ dev->types[2] = _DRM_STAT_CLOSES;
+ dev->types[3] = _DRM_STAT_IOCTLS;
+ dev->types[4] = _DRM_STAT_LOCKS;
+ dev->types[5] = _DRM_STAT_UNLOCKS;
+#ifdef __HAVE_COUNTER6
+ dev->types[6] = __HAVE_COUNTER6;
+#endif
+#ifdef __HAVE_COUNTER7
+ dev->types[7] = __HAVE_COUNTER7;
+#endif
+#ifdef __HAVE_COUNTER8
+ dev->types[8] = __HAVE_COUNTER8;
+#endif
+#ifdef __HAVE_COUNTER9
+ dev->types[9] = __HAVE_COUNTER9;
+#endif
+#ifdef __HAVE_COUNTER10
+ dev->types[10] = __HAVE_COUNTER10;
+#endif
+#ifdef __HAVE_COUNTER11
+ dev->types[11] = __HAVE_COUNTER11;
+#endif
+#ifdef __HAVE_COUNTER12
+ dev->types[12] = __HAVE_COUNTER12;
+#endif
+#ifdef __HAVE_COUNTER13
+ dev->types[13] = __HAVE_COUNTER13;
+#endif
+#ifdef __HAVE_COUNTER14
+ dev->types[14] = __HAVE_COUNTER14;
+#endif
+#ifdef __HAVE_COUNTER15
+ dev->types[14] = __HAVE_COUNTER14;
+#endif
+
+ for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
+ atomic_set(&dev->counts[i], 0);
for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
dev->magiclist[i].head = NULL;
@@ -499,7 +530,7 @@ int DRM(open)( struct inode *inode, struct file *filp )
#if LINUX_VERSION_CODE < 0x020333
MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
#endif
- atomic_inc( &dev->total_open );
+ atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
spin_lock( &dev->count_lock );
if ( !dev->open_count++ ) {
spin_unlock( &dev->count_lock );
@@ -562,7 +593,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
DRM_KERNEL_CONTEXT ) ) {
dev->lock.pid = priv->pid;
dev->lock.lock_time = jiffies;
- atomic_inc( &dev->total_locks );
+ atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
break; /* Got lock */
}
/* Contention */
@@ -616,7 +647,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
#if LINUX_VERSION_CODE < 0x020333
MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
#endif
- atomic_inc( &dev->total_close );
+ atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
spin_lock( &dev->count_lock );
if ( !--dev->open_count ) {
if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
@@ -650,7 +681,7 @@ int DRM(ioctl)( struct inode *inode, struct file *filp,
int retcode = 0;
atomic_inc( &dev->ioctl_count );
- atomic_inc( &dev->total_ioctl );
+ atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
++priv->ioctl_count;
DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%x, auth=%d\n",
@@ -735,7 +766,7 @@ int DRM(lock)( struct inode *inode, struct file *filp,
lock.context ) ) {
dev->lock.pid = current->pid;
dev->lock.lock_time = jiffies;
- atomic_inc( &dev->total_locks );
+ atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
#if __HAVE_MULTIPLE_DMA_QUEUES
atomic_inc( &q->total_locks );
#endif
@@ -743,7 +774,6 @@ int DRM(lock)( struct inode *inode, struct file *filp,
}
/* Contention */
- atomic_inc( &dev->total_sleeps );
schedule();
if ( signal_pending( current ) ) {
ret = -ERESTARTSYS;
@@ -806,9 +836,7 @@ int DRM(unlock)( struct inode *inode, struct file *filp,
return -EINVAL;
}
- atomic_inc( &dev->total_unlocks );
- if ( _DRM_LOCK_IS_CONT( dev->lock.hw_lock->lock ) )
- atomic_inc( &dev->total_contends );
+ atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT );
diff --git a/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c
index cb3775a7..ce6ac2e6 100644
--- a/linux-core/drm_ioctl.c
+++ b/linux-core/drm_ioctl.c
@@ -159,3 +159,34 @@ int DRM(getclient)( struct inode *inode, struct file *filp,
return -EFAULT;
return 0;
}
+
+int DRM(getstats)( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_stats_t stats;
+ int i;
+
+ memset(&stats, 0, sizeof(stats));
+
+ down(&dev->struct_sem);
+
+ for (i = 0; i < dev->counters; i++) {
+ if (dev->types[i] == _DRM_STAT_LOCK)
+ stats.data[i].value
+ = (dev->lock.hw_lock
+ ? dev->lock.hw_lock->lock : 0);
+ else
+ stats.data[i].value = atomic_read(&dev->counts[i]);
+ stats.data[i].type = dev->types[i];
+ }
+
+ stats.count = dev->counters;
+
+ up(&dev->struct_sem);
+
+ if (copy_to_user((drm_stats_t *)arg, &stats, sizeof(stats)))
+ return -EFAULT;
+ return 0;
+}
diff --git a/linux-core/drm_proc.c b/linux-core/drm_proc.c
index a3958241..defabdf6 100644
--- a/linux-core/drm_proc.c
+++ b/linux-core/drm_proc.c
@@ -506,20 +506,21 @@ static int DRM(_histo_info)(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("general statistics:\n");
DRM_PROC_PRINT("total %10u\n", atomic_read(&dev->histo.total));
- DRM_PROC_PRINT("open %10u\n", atomic_read(&dev->total_open));
- DRM_PROC_PRINT("close %10u\n", atomic_read(&dev->total_close));
- DRM_PROC_PRINT("ioctl %10u\n", atomic_read(&dev->total_ioctl));
- DRM_PROC_PRINT("irq %10u\n", atomic_read(&dev->total_irq));
- DRM_PROC_PRINT("ctx %10u\n", atomic_read(&dev->total_ctx));
+ DRM_PROC_PRINT("open %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_OPENS]));
+ DRM_PROC_PRINT("close %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_CLOSES]));
+ DRM_PROC_PRINT("ioctl %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_IOCTLS]));
DRM_PROC_PRINT("\nlock statistics:\n");
- DRM_PROC_PRINT("locks %10u\n", atomic_read(&dev->total_locks));
- DRM_PROC_PRINT("unlocks %10u\n", atomic_read(&dev->total_unlocks));
- DRM_PROC_PRINT("contends %10u\n", atomic_read(&dev->total_contends));
- DRM_PROC_PRINT("sleeps %10u\n", atomic_read(&dev->total_sleeps));
-
+ DRM_PROC_PRINT("locks %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_LOCKS]));
+ DRM_PROC_PRINT("unlocks %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_UNLOCKS]));
if (dma) {
+#if 0
DRM_PROC_PRINT("\ndma statistics:\n");
DRM_PROC_PRINT("prio %10u\n",
atomic_read(&dma->total_prio));
@@ -542,6 +543,7 @@ static int DRM(_histo_info)(char *buf, char **start, off_t offset, int request,
atomic_read(&dma->total_hit));
DRM_PROC_PRINT("lost %10u\n",
atomic_read(&dma->total_lost));
+#endif
buffer = dma->next_buffer;
if (buffer) {
diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c
index 3d9a4f45..d458afb4 100644
--- a/linux-core/mga_drv.c
+++ b/linux-core/mga_drv.c
@@ -54,6 +54,7 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { mga_irq_busid, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { mga_getmap, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { mga_getclient, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { mga_getstats, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { mga_setunique, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { mga_block, 1, 1 },
@@ -118,6 +119,11 @@ static drm_ioctl_desc_t mga_ioctls[] = {
#define __HAVE_DMA 1
#define __HAVE_DMA_IRQ 1
+#define __HAVE_COUNTERS 3
+#define __HAVE_COUNTER6 _DRM_STAT_IRQ
+#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY
+
#if 0
#define __HAVE_DMA_QUEUE 1
#define __HAVE_DMA_SCHEDULE 1
diff --git a/linux/drm.h b/linux/drm.h
index a3e7875f..6885a83a 100644
--- a/linux/drm.h
+++ b/linux/drm.h
@@ -164,6 +164,32 @@ typedef struct drm_client {
unsigned long iocs; /* Ioctl count */
} drm_client_t;
+typedef enum {
+ _DRM_STAT_LOCK,
+ _DRM_STAT_OPENS,
+ _DRM_STAT_CLOSES,
+ _DRM_STAT_IOCTLS,
+ _DRM_STAT_LOCKS,
+ _DRM_STAT_UNLOCKS,
+ _DRM_STAT_VALUE, /* Generic value */
+ _DRM_STAT_BYTE, /* Generic byte counter (1024bytes/K) */
+ _DRM_STAT_COUNT, /* Generic non-byte counter (1000/k) */
+
+ _DRM_STAT_IRQ,
+ _DRM_STAT_PRIMARY,
+ _DRM_STAT_SECONDARY
+
+ /* Add to the *END* of the list */
+} drm_stat_type_t;
+
+typedef struct drm_stats {
+ unsigned long count;
+ struct {
+ unsigned long value;
+ drm_stat_type_t type;
+ } data[15];
+} drm_stats_t;
+
typedef enum drm_lock_flags {
_DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
_DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
@@ -325,6 +351,7 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
+#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
diff --git a/linux/drmP.h b/linux/drmP.h
index 3270952e..f4052f01 100644
--- a/linux/drmP.h
+++ b/linux/drmP.h
@@ -485,6 +485,7 @@ typedef struct drm_lock_data {
} drm_lock_data_t;
typedef struct drm_device_dma {
+#if 0
/* Performance Counters */
atomic_t total_prio; /* Total DRM_DMA_PRIORITY */
atomic_t total_bytes; /* Total bytes DMA'd */
@@ -498,6 +499,7 @@ typedef struct drm_device_dma {
atomic_t total_tried; /* Tried next_buffer */
atomic_t total_hit; /* Sent next_buffer */
atomic_t total_lost; /* Lost interrupt */
+#endif
drm_buf_entry_t bufs[DRM_MAX_ORDER+1];
int buf_count;
@@ -565,17 +567,10 @@ typedef struct drm_device {
int buf_use; /* Buffers in use -- cannot alloc */
atomic_t buf_alloc; /* Buffer allocation in progress */
- /* Performance Counters */
- atomic_t total_open;
- atomic_t total_close;
- atomic_t total_ioctl;
- atomic_t total_irq; /* Total interruptions */
- atomic_t total_ctx; /* Total context switches */
-
- atomic_t total_locks;
- atomic_t total_unlocks;
- atomic_t total_contends;
- atomic_t total_sleeps;
+ /* Performance counters */
+ unsigned long counters;
+ drm_stat_type_t types[15];
+ atomic_t counts[15];
/* Authentication */
drm_file_t *file_first;
@@ -732,6 +727,8 @@ extern int DRM(getmap)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(getclient)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int DRM(getstats)(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* Context IOCTL support (context.c) */
extern int DRM(resctx)( struct inode *inode, struct file *filp,
diff --git a/linux/drm_context.h b/linux/drm_context.h
index fd2cf94d..6bbcfca8 100644
--- a/linux/drm_context.h
+++ b/linux/drm_context.h
@@ -93,8 +93,6 @@ int DRM(context_switch)( drm_device_t *dev, int old, int new )
{
char buf[64];
- atomic_inc( &dev->total_ctx );
-
if ( test_and_set_bit( 0, &dev->context_flag ) ) {
DRM_ERROR( "Reentering -- FIXME\n" );
return -EBUSY;
diff --git a/linux/drm_drv.h b/linux/drm_drv.h
index 18935309..7999b140 100644
--- a/linux/drm_drv.h
+++ b/linux/drm_drv.h
@@ -146,15 +146,46 @@ static int DRM(setup)( drm_device_t *dev )
return i;
#endif
- atomic_set( &dev->total_open, 0 );
- atomic_set( &dev->total_close, 0 );
- atomic_set( &dev->total_ioctl, 0 );
- atomic_set( &dev->total_irq, 0 );
- atomic_set( &dev->total_ctx, 0 );
- atomic_set( &dev->total_locks, 0 );
- atomic_set( &dev->total_unlocks, 0 );
- atomic_set( &dev->total_contends, 0 );
- atomic_set( &dev->total_sleeps, 0 );
+ dev->counters = 6 + __HAVE_COUNTERS;
+ dev->types[0] = _DRM_STAT_LOCK;
+ dev->types[1] = _DRM_STAT_OPENS;
+ dev->types[2] = _DRM_STAT_CLOSES;
+ dev->types[3] = _DRM_STAT_IOCTLS;
+ dev->types[4] = _DRM_STAT_LOCKS;
+ dev->types[5] = _DRM_STAT_UNLOCKS;
+#ifdef __HAVE_COUNTER6
+ dev->types[6] = __HAVE_COUNTER6;
+#endif
+#ifdef __HAVE_COUNTER7
+ dev->types[7] = __HAVE_COUNTER7;
+#endif
+#ifdef __HAVE_COUNTER8
+ dev->types[8] = __HAVE_COUNTER8;
+#endif
+#ifdef __HAVE_COUNTER9
+ dev->types[9] = __HAVE_COUNTER9;
+#endif
+#ifdef __HAVE_COUNTER10
+ dev->types[10] = __HAVE_COUNTER10;
+#endif
+#ifdef __HAVE_COUNTER11
+ dev->types[11] = __HAVE_COUNTER11;
+#endif
+#ifdef __HAVE_COUNTER12
+ dev->types[12] = __HAVE_COUNTER12;
+#endif
+#ifdef __HAVE_COUNTER13
+ dev->types[13] = __HAVE_COUNTER13;
+#endif
+#ifdef __HAVE_COUNTER14
+ dev->types[14] = __HAVE_COUNTER14;
+#endif
+#ifdef __HAVE_COUNTER15
+ dev->types[14] = __HAVE_COUNTER14;
+#endif
+
+ for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++)
+ atomic_set(&dev->counts[i], 0);
for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
dev->magiclist[i].head = NULL;
@@ -499,7 +530,7 @@ int DRM(open)( struct inode *inode, struct file *filp )
#if LINUX_VERSION_CODE < 0x020333
MOD_INC_USE_COUNT; /* Needed before Linux 2.3.51 */
#endif
- atomic_inc( &dev->total_open );
+ atomic_inc( &dev->counts[_DRM_STAT_OPENS] );
spin_lock( &dev->count_lock );
if ( !dev->open_count++ ) {
spin_unlock( &dev->count_lock );
@@ -562,7 +593,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
DRM_KERNEL_CONTEXT ) ) {
dev->lock.pid = priv->pid;
dev->lock.lock_time = jiffies;
- atomic_inc( &dev->total_locks );
+ atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
break; /* Got lock */
}
/* Contention */
@@ -616,7 +647,7 @@ int DRM(release)( struct inode *inode, struct file *filp )
#if LINUX_VERSION_CODE < 0x020333
MOD_DEC_USE_COUNT; /* Needed before Linux 2.3.51 */
#endif
- atomic_inc( &dev->total_close );
+ atomic_inc( &dev->counts[_DRM_STAT_CLOSES] );
spin_lock( &dev->count_lock );
if ( !--dev->open_count ) {
if ( atomic_read( &dev->ioctl_count ) || dev->blocked ) {
@@ -650,7 +681,7 @@ int DRM(ioctl)( struct inode *inode, struct file *filp,
int retcode = 0;
atomic_inc( &dev->ioctl_count );
- atomic_inc( &dev->total_ioctl );
+ atomic_inc( &dev->counts[_DRM_STAT_IOCTLS] );
++priv->ioctl_count;
DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%x, auth=%d\n",
@@ -735,7 +766,7 @@ int DRM(lock)( struct inode *inode, struct file *filp,
lock.context ) ) {
dev->lock.pid = current->pid;
dev->lock.lock_time = jiffies;
- atomic_inc( &dev->total_locks );
+ atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
#if __HAVE_MULTIPLE_DMA_QUEUES
atomic_inc( &q->total_locks );
#endif
@@ -743,7 +774,6 @@ int DRM(lock)( struct inode *inode, struct file *filp,
}
/* Contention */
- atomic_inc( &dev->total_sleeps );
schedule();
if ( signal_pending( current ) ) {
ret = -ERESTARTSYS;
@@ -806,9 +836,7 @@ int DRM(unlock)( struct inode *inode, struct file *filp,
return -EINVAL;
}
- atomic_inc( &dev->total_unlocks );
- if ( _DRM_LOCK_IS_CONT( dev->lock.hw_lock->lock ) )
- atomic_inc( &dev->total_contends );
+ atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT );
diff --git a/linux/drm_ioctl.h b/linux/drm_ioctl.h
index cb3775a7..ce6ac2e6 100644
--- a/linux/drm_ioctl.h
+++ b/linux/drm_ioctl.h
@@ -159,3 +159,34 @@ int DRM(getclient)( struct inode *inode, struct file *filp,
return -EFAULT;
return 0;
}
+
+int DRM(getstats)( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_stats_t stats;
+ int i;
+
+ memset(&stats, 0, sizeof(stats));
+
+ down(&dev->struct_sem);
+
+ for (i = 0; i < dev->counters; i++) {
+ if (dev->types[i] == _DRM_STAT_LOCK)
+ stats.data[i].value
+ = (dev->lock.hw_lock
+ ? dev->lock.hw_lock->lock : 0);
+ else
+ stats.data[i].value = atomic_read(&dev->counts[i]);
+ stats.data[i].type = dev->types[i];
+ }
+
+ stats.count = dev->counters;
+
+ up(&dev->struct_sem);
+
+ if (copy_to_user((drm_stats_t *)arg, &stats, sizeof(stats)))
+ return -EFAULT;
+ return 0;
+}
diff --git a/linux/drm_proc.h b/linux/drm_proc.h
index a3958241..defabdf6 100644
--- a/linux/drm_proc.h
+++ b/linux/drm_proc.h
@@ -506,20 +506,21 @@ static int DRM(_histo_info)(char *buf, char **start, off_t offset, int request,
DRM_PROC_PRINT("general statistics:\n");
DRM_PROC_PRINT("total %10u\n", atomic_read(&dev->histo.total));
- DRM_PROC_PRINT("open %10u\n", atomic_read(&dev->total_open));
- DRM_PROC_PRINT("close %10u\n", atomic_read(&dev->total_close));
- DRM_PROC_PRINT("ioctl %10u\n", atomic_read(&dev->total_ioctl));
- DRM_PROC_PRINT("irq %10u\n", atomic_read(&dev->total_irq));
- DRM_PROC_PRINT("ctx %10u\n", atomic_read(&dev->total_ctx));
+ DRM_PROC_PRINT("open %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_OPENS]));
+ DRM_PROC_PRINT("close %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_CLOSES]));
+ DRM_PROC_PRINT("ioctl %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_IOCTLS]));
DRM_PROC_PRINT("\nlock statistics:\n");
- DRM_PROC_PRINT("locks %10u\n", atomic_read(&dev->total_locks));
- DRM_PROC_PRINT("unlocks %10u\n", atomic_read(&dev->total_unlocks));
- DRM_PROC_PRINT("contends %10u\n", atomic_read(&dev->total_contends));
- DRM_PROC_PRINT("sleeps %10u\n", atomic_read(&dev->total_sleeps));
-
+ DRM_PROC_PRINT("locks %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_LOCKS]));
+ DRM_PROC_PRINT("unlocks %10u\n",
+ atomic_read(&dev->counts[_DRM_STAT_UNLOCKS]));
if (dma) {
+#if 0
DRM_PROC_PRINT("\ndma statistics:\n");
DRM_PROC_PRINT("prio %10u\n",
atomic_read(&dma->total_prio));
@@ -542,6 +543,7 @@ static int DRM(_histo_info)(char *buf, char **start, off_t offset, int request,
atomic_read(&dma->total_hit));
DRM_PROC_PRINT("lost %10u\n",
atomic_read(&dma->total_lost));
+#endif
buffer = dma->next_buffer;
if (buffer) {
diff --git a/linux/mga_dma.c b/linux/mga_dma.c
index fb054a9c..7b66e887 100644
--- a/linux/mga_dma.c
+++ b/linux/mga_dma.c
@@ -1183,7 +1183,7 @@ void mga_do_dma_flush( drm_mga_private_t *dev_priv )
primary->space = head - tail;
}
primary->space -= MGA_DMA_SOFTRAP_SIZE;
-
+
DRM_DEBUG( " space = 0x%06x\n", primary->space );
primary->last_flush = primary->tail;
@@ -1249,14 +1249,14 @@ static void mga_dma_service( int irq, void *device, struct pt_regs *regs )
u32 head = dev_priv->primary->offset;
u32 tail;
- atomic_inc( &dev->total_irq );
-
/* Verify the interrupt we're servicing is actually the one we
* want to service.
*/
if ( (MGA_READ( MGA_STATUS ) & MGA_SOFTRAPEN) != MGA_SOFTRAPEN )
return;
+ atomic_inc( &dev->counts[_DRM_STAT_IRQ] );
+
MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
spin_lock( &primary->tail_lock );
@@ -1896,7 +1896,7 @@ if ( 0 ) {
dev_priv->prim.space,
dev_priv->prim.size - MGA_DMA_SOFTRAP_SIZE );
DRM_INFO( "\n" );
- DRM_INFO( " irqs = %d\n", atomic_read( &dev->total_irq ) );
+ DRM_INFO( " irqs = %d\n", atomic_read( &dev->counts[_DRM_STAT_IRQ] ) );
return ret;
}
diff --git a/linux/mga_drv.c b/linux/mga_drv.c
index 3d9a4f45..d458afb4 100644
--- a/linux/mga_drv.c
+++ b/linux/mga_drv.c
@@ -54,6 +54,7 @@ static drm_ioctl_desc_t mga_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { mga_irq_busid, 0, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { mga_getmap, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { mga_getclient, 0, 0 },
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { mga_getstats, 0, 0 },
[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { mga_setunique, 1, 1 },
[DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { mga_block, 1, 1 },
@@ -118,6 +119,11 @@ static drm_ioctl_desc_t mga_ioctls[] = {
#define __HAVE_DMA 1
#define __HAVE_DMA_IRQ 1
+#define __HAVE_COUNTERS 3
+#define __HAVE_COUNTER6 _DRM_STAT_IRQ
+#define __HAVE_COUNTER7 _DRM_STAT_PRIMARY
+#define __HAVE_COUNTER8 _DRM_STAT_SECONDARY
+
#if 0
#define __HAVE_DMA_QUEUE 1
#define __HAVE_DMA_SCHEDULE 1
diff --git a/shared-core/drm.h b/shared-core/drm.h
index a3e7875f..6885a83a 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -164,6 +164,32 @@ typedef struct drm_client {
unsigned long iocs; /* Ioctl count */
} drm_client_t;
+typedef enum {
+ _DRM_STAT_LOCK,
+ _DRM_STAT_OPENS,
+ _DRM_STAT_CLOSES,
+ _DRM_STAT_IOCTLS,
+ _DRM_STAT_LOCKS,
+ _DRM_STAT_UNLOCKS,
+ _DRM_STAT_VALUE, /* Generic value */
+ _DRM_STAT_BYTE, /* Generic byte counter (1024bytes/K) */
+ _DRM_STAT_COUNT, /* Generic non-byte counter (1000/k) */
+
+ _DRM_STAT_IRQ,
+ _DRM_STAT_PRIMARY,
+ _DRM_STAT_SECONDARY
+
+ /* Add to the *END* of the list */
+} drm_stat_type_t;
+
+typedef struct drm_stats {
+ unsigned long count;
+ struct {
+ unsigned long value;
+ drm_stat_type_t type;
+ } data[15];
+} drm_stats_t;
+
typedef enum drm_lock_flags {
_DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
_DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
@@ -325,6 +351,7 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
+#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
diff --git a/shared/drm.h b/shared/drm.h
index a3e7875f..6885a83a 100644
--- a/shared/drm.h
+++ b/shared/drm.h
@@ -164,6 +164,32 @@ typedef struct drm_client {
unsigned long iocs; /* Ioctl count */
} drm_client_t;
+typedef enum {
+ _DRM_STAT_LOCK,
+ _DRM_STAT_OPENS,
+ _DRM_STAT_CLOSES,
+ _DRM_STAT_IOCTLS,
+ _DRM_STAT_LOCKS,
+ _DRM_STAT_UNLOCKS,
+ _DRM_STAT_VALUE, /* Generic value */
+ _DRM_STAT_BYTE, /* Generic byte counter (1024bytes/K) */
+ _DRM_STAT_COUNT, /* Generic non-byte counter (1000/k) */
+
+ _DRM_STAT_IRQ,
+ _DRM_STAT_PRIMARY,
+ _DRM_STAT_SECONDARY
+
+ /* Add to the *END* of the list */
+} drm_stat_type_t;
+
+typedef struct drm_stats {
+ unsigned long count;
+ struct {
+ unsigned long value;
+ drm_stat_type_t type;
+ } data[15];
+} drm_stats_t;
+
typedef enum drm_lock_flags {
_DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
_DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
@@ -325,6 +351,7 @@ typedef struct drm_agp_info {
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
+#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
diff --git a/tests/dristat.c b/tests/dristat.c
index 87a9ef9a..693335b9 100644
--- a/tests/dristat.c
+++ b/tests/dristat.c
@@ -41,6 +41,22 @@
#define DRM_VERSION 0x00000001
#define DRM_MEMORY 0x00000002
#define DRM_CLIENTS 0x00000004
+#define DRM_STATS 0x00000008
+
+typedef struct drmStatsS {
+ unsigned long count;
+ struct {
+ unsigned long value;
+ const char *long_format;
+ const char *long_name;
+ const char *rate_format;
+ const char *rate_name;
+ int isvalue;
+ const char *mult_names;
+ int mult;
+ int verbose;
+ } data[15];
+} drmStatsT;
static void getversion(int fd)
{
@@ -105,6 +121,113 @@ int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
return 0;
}
+int drmGetStats(int fd, drmStatsT *stats)
+{
+ drm_stats_t s;
+ int i;
+
+ if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno;
+
+ stats->count = 0;
+ memset(stats, 0, sizeof(*stats));
+ if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
+ return -1;
+
+#define SET_VALUE \
+ stats->data[i].long_format = "%-9.9s"; \
+ stats->data[i].rate_format = "%8.8s"; \
+ stats->data[i].isvalue = 1; \
+ stats->data[i].verbose = 0
+
+#define SET_COUNT \
+ stats->data[i].long_format = "%-9.9s"; \
+ stats->data[i].rate_format = "%5.5s"; \
+ stats->data[i].isvalue = 0; \
+ stats->data[i].mult_names = "kgm"; \
+ stats->data[i].mult = 1000; \
+ stats->data[i].verbose = 0
+
+#define SET_BYTE \
+ stats->data[i].long_format = "%-9.9s"; \
+ stats->data[i].rate_format = "%5.5s"; \
+ stats->data[i].isvalue = 0; \
+ stats->data[i].mult_names = "KGM"; \
+ stats->data[i].mult = 1024; \
+ stats->data[i].verbose = 0
+
+
+ stats->count = s.count;
+ for (i = 0; i < s.count; i++) {
+ stats->data[i].value = s.data[i].value;
+ switch (s.data[i].type) {
+ case _DRM_STAT_LOCK:
+ stats->data[i].long_name = "Lock";
+ stats->data[i].rate_name = "Lock";
+ SET_VALUE;
+ break;
+ case _DRM_STAT_OPENS:
+ stats->data[i].long_name = "Opens";
+ stats->data[i].rate_name = "O";
+ SET_COUNT;
+ stats->data[i].verbose = 1;
+ break;
+ case _DRM_STAT_CLOSES:
+ stats->data[i].long_name = "Closes";
+ stats->data[i].rate_name = "Lock";
+ SET_COUNT;
+ stats->data[i].verbose = 1;
+ break;
+ case _DRM_STAT_IOCTLS:
+ stats->data[i].long_name = "Ioctls";
+ stats->data[i].rate_name = "Ioc/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_LOCKS:
+ stats->data[i].long_name = "Locks";
+ stats->data[i].rate_name = "Lck/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_UNLOCKS:
+ stats->data[i].long_name = "Unlocks";
+ stats->data[i].rate_name = "Unl/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_IRQ:
+ stats->data[i].long_name = "IRQs";
+ stats->data[i].rate_name = "IRQ/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_PRIMARY:
+ stats->data[i].long_name = "Primary";
+ stats->data[i].rate_name = "Pri/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_SECONDARY:
+ stats->data[i].long_name = "Secondary";
+ stats->data[i].rate_name = "Sec/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_VALUE:
+ stats->data[i].long_name = "Value";
+ stats->data[i].rate_name = "Value";
+ SET_VALUE;
+ break;
+ case _DRM_STAT_BYTE:
+ stats->data[i].long_name = "Bytes";
+ stats->data[i].rate_name = "B/s";
+ SET_BYTE;
+ break;
+ case _DRM_STAT_COUNT:
+ default:
+ stats->data[i].long_name = "Count";
+ stats->data[i].rate_name = "Cnt/s";
+ SET_COUNT;
+ break;
+ }
+ }
+ return 0;
+}
+
static void getvm(int fd)
{
int i;
@@ -178,6 +301,84 @@ static void getclients(int fd)
}
}
+static void printhuman(unsigned long value, const char *name, int mult)
+{
+ const char *p;
+ double f;
+ /* Print width 5 number in width 6 space */
+ if (value < 100000) {
+ printf(" %5lu", value);
+ return;
+ }
+
+ p = name;
+ f = (double)value / (double)mult;
+ if (f < 10.0) {
+ printf(" %4.2f%c", f, *p);
+ return;
+ }
+
+ p++;
+ f = (double)value / (double)mult;
+ if (f < 10.0) {
+ printf(" %4.2f%c", f, *p);
+ return;
+ }
+
+ p++;
+ f = (double)value / (double)mult;
+ if (f < 10.0) {
+ printf(" %4.2f%c", f, *p);
+ return;
+ }
+}
+
+static void getstats(int fd, int i)
+{
+ drmStatsT prev, curr;
+ int j;
+ double rate;
+
+ printf(" System statistics:\n");
+
+ if (drmGetStats(fd, &prev)) return;
+ if (!i) {
+ for (j = 0; j < prev.count; j++) {
+ printf(" ");
+ printf(prev.data[j].long_format, prev.data[j].long_name);
+ if (prev.data[j].isvalue) printf(" 0x%08lx\n", prev.data[j].value);
+ else printf(" %10lu\n", prev.data[j].value);
+ }
+ return;
+ }
+
+ printf(" ");
+ for (j = 0; j < prev.count; j++)
+ if (!prev.data[j].verbose) {
+ printf(" ");
+ printf(prev.data[j].rate_format, prev.data[j].rate_name);
+ }
+ printf("\n");
+
+ for (;;) {
+ sleep(i);
+ if (drmGetStats(fd, &curr)) return;
+ printf(" ");
+ for (j = 0; j < curr.count; j++) {
+ if (curr.data[j].verbose) continue;
+ if (curr.data[j].isvalue) {
+ printf(" %08lx", curr.data[j].value);
+ } else {
+ rate = (curr.data[j].value - prev.data[j].value) / (double)i;
+ printhuman(rate, curr.data[j].mult_names, curr.data[j].mult);
+ }
+ }
+ printf("\n");
+ memcpy(&prev, &curr, sizeof(prev));
+ }
+
+}
+
static int drmOpenMinor(int minor, uid_t user, gid_t group,
mode_t dirmode, mode_t devmode, int force)
{
@@ -219,18 +420,22 @@ static int drmOpenMinor(int minor, uid_t user, gid_t group,
int main(int argc, char **argv)
{
int c;
- int mask = 0;
- int minor = 0;
+ int mask = 0;
+ int minor = 0;
+ int interval = 0;
int fd;
char buf[64];
int i;
- while ((c = getopt(argc, argv, "vmcM:")) != EOF)
+ while ((c = getopt(argc, argv, "avmcsM:i:")) != EOF)
switch (c) {
- case 'v': mask |= DRM_VERSION; break;
- case 'm': mask |= DRM_MEMORY; break;
- case 'c': mask |= DRM_CLIENTS; break;
- case 'M': minor = strtol(optarg, NULL, 0); break;
+ case 'a': mask = ~0; break;
+ case 'v': mask |= DRM_VERSION; break;
+ case 'm': mask |= DRM_MEMORY; break;
+ case 'c': mask |= DRM_CLIENTS; break;
+ case 's': mask |= DRM_STATS; break;
+ case 'i': interval = strtol(optarg, NULL, 0); break;
+ case 'M': minor = strtol(optarg, NULL, 0); break;
default:
fprintf( stderr, "Usage: dristat [options]\n" );
return 1;
@@ -244,6 +449,7 @@ int main(int argc, char **argv)
if (mask & DRM_VERSION) getversion(fd);
if (mask & DRM_MEMORY) getvm(fd);
if (mask & DRM_CLIENTS) getclients(fd);
+ if (mask & DRM_STATS) getstats(fd, interval);
close(fd);
}
}