diff options
author | Rik Faith <faith@alephnull.com> | 2001-02-09 16:00:14 +0000 |
---|---|---|
committer | Rik Faith <faith@alephnull.com> | 2001-02-09 16:00:14 +0000 |
commit | db6b1ce9b814f36431dee6468cfb60e47222831e (patch) | |
tree | e8c695a945c7a7ba5877c7013b89a2ac6618ecb1 | |
parent | 9a426ec53e78d0e91e47b28c9bcf52f3585a7c1d (diff) |
Add extensible counters for statistics via ioctl
-rw-r--r-- | linux-core/drmP.h | 19 | ||||
-rw-r--r-- | linux-core/drm_context.c | 2 | ||||
-rw-r--r-- | linux-core/drm_drv.c | 64 | ||||
-rw-r--r-- | linux-core/drm_ioctl.c | 31 | ||||
-rw-r--r-- | linux-core/drm_proc.c | 22 | ||||
-rw-r--r-- | linux-core/mga_drv.c | 6 | ||||
-rw-r--r-- | linux/drm.h | 27 | ||||
-rw-r--r-- | linux/drmP.h | 19 | ||||
-rw-r--r-- | linux/drm_context.h | 2 | ||||
-rw-r--r-- | linux/drm_drv.h | 64 | ||||
-rw-r--r-- | linux/drm_ioctl.h | 31 | ||||
-rw-r--r-- | linux/drm_proc.h | 22 | ||||
-rw-r--r-- | linux/mga_dma.c | 8 | ||||
-rw-r--r-- | linux/mga_drv.c | 6 | ||||
-rw-r--r-- | shared-core/drm.h | 27 | ||||
-rw-r--r-- | shared/drm.h | 27 | ||||
-rw-r--r-- | tests/dristat.c | 220 |
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); } } |