Add extensible counters for statistics via ioctl

This commit is contained in:
Rik Faith 2001-02-09 16:00:14 +00:00
parent 9a426ec53e
commit db6b1ce9b8
17 changed files with 504 additions and 93 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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 );

View file

@ -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;
}

View file

@ -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) {

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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;

View file

@ -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 );

View file

@ -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;
}

View file

@ -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) {

View file

@ -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;
}

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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);
}
}