Release 4.11 drivers/gpu/drm/drm_context.c
/*
* Legacy: Generic DRM Contexts
*
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
* Author: Gareth Hughes <gareth@valinux.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <drm/drmP.h>
#include "drm_legacy.h"
struct drm_ctx_list {
struct list_head head;
drm_context_t handle;
struct drm_file *tag;
};
/******************************************************************/
/** \name Context bitmap support */
/*@{*/
/**
* Free a handle from the context bitmap.
*
* \param dev DRM device.
* \param ctx_handle context handle.
*
* Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
* in drm_device::ctx_idr, while holding the drm_device::struct_mutex
* lock.
*/
void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
{
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return;
mutex_lock(&dev->struct_mutex);
idr_remove(&dev->ctx_idr, ctx_handle);
mutex_unlock(&dev->struct_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peter Antoine | 17 | 29.31% | 1 | 12.50% |
Linus Torvalds (pre-git) | 15 | 25.86% | 1 | 12.50% |
Linus Torvalds | 12 | 20.69% | 1 | 12.50% |
Dave Airlie | 11 | 18.97% | 3 | 37.50% |
Daniel Vetter | 2 | 3.45% | 1 | 12.50% |
David Herrmann | 1 | 1.72% | 1 | 12.50% |
Total | 58 | 100.00% | 8 | 100.00% |
/**
* Context bitmap allocation.
*
* \param dev DRM device.
* \return (non-negative) context handle on success or a negative number on failure.
*
* Allocate a new idr from drm_device::ctx_idr while holding the
* drm_device::struct_mutex lock.
*/
static int drm_legacy_ctxbitmap_next(struct drm_device * dev)
{
int ret;
mutex_lock(&dev->struct_mutex);
ret = idr_alloc(&dev->ctx_idr, NULL, DRM_RESERVED_CONTEXTS, 0,
GFP_KERNEL);
mutex_unlock(&dev->struct_mutex);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Airlie | 16 | 31.37% | 4 | 40.00% |
Linus Torvalds (pre-git) | 14 | 27.45% | 1 | 10.00% |
Linus Torvalds | 13 | 25.49% | 2 | 20.00% |
Tejun Heo | 4 | 7.84% | 1 | 10.00% |
Ville Syrjälä | 3 | 5.88% | 1 | 10.00% |
David Herrmann | 1 | 1.96% | 1 | 10.00% |
Total | 51 | 100.00% | 10 | 100.00% |
/**
* Context bitmap initialization.
*
* \param dev DRM device.
*
* Initialise the drm_device::ctx_idr
*/
void drm_legacy_ctxbitmap_init(struct drm_device * dev)
{
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return;
idr_init(&dev->ctx_idr);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peter Antoine | 16 | 43.24% | 1 | 14.29% |
Linus Torvalds | 12 | 32.43% | 1 | 14.29% |
Daniel Vetter | 4 | 10.81% | 2 | 28.57% |
Dave Airlie | 4 | 10.81% | 2 | 28.57% |
David Herrmann | 1 | 2.70% | 1 | 14.29% |
Total | 37 | 100.00% | 7 | 100.00% |
/**
* Context bitmap cleanup.
*
* \param dev DRM device.
*
* Free all idr members using drm_ctx_sarea_free helper function
* while holding the drm_device::struct_mutex lock.
*/
void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev)
{
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return;
mutex_lock(&dev->struct_mutex);
idr_destroy(&dev->ctx_idr);
mutex_unlock(&dev->struct_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Peter Antoine | 17 | 32.08% | 1 | 11.11% |
Linus Torvalds | 14 | 26.42% | 1 | 11.11% |
Linus Torvalds (pre-git) | 10 | 18.87% | 1 | 11.11% |
Dave Airlie | 8 | 15.09% | 3 | 33.33% |
Daniel Vetter | 2 | 3.77% | 1 | 11.11% |
Tejun Heo | 1 | 1.89% | 1 | 11.11% |
David Herrmann | 1 | 1.89% | 1 | 11.11% |
Total | 53 | 100.00% | 9 | 100.00% |
/**
* drm_ctxbitmap_flush() - Flush all contexts owned by a file
* @dev: DRM device to operate on
* @file: Open file to flush contexts for
*
* This iterates over all contexts on @dev and drops them if they're owned by
* @file. Note that after this call returns, new contexts might be added if
* the file is still alive.
*/
void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file)
{
struct drm_ctx_list *pos, *tmp;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return;
mutex_lock(&dev->ctxlist_mutex);
list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) {
if (pos->tag == file &&
pos->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
dev->driver->context_dtor(dev, pos->handle);
drm_legacy_ctxbitmap_free(dev, pos->handle);
list_del(&pos->head);
kfree(pos);
}
}
mutex_unlock(&dev->ctxlist_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Herrmann | 110 | 85.27% | 2 | 50.00% |
Peter Antoine | 17 | 13.18% | 1 | 25.00% |
Daniel Vetter | 2 | 1.55% | 1 | 25.00% |
Total | 129 | 100.00% | 4 | 100.00% |
/*@}*/
/******************************************************************/
/** \name Per Context SAREA Support */
/*@{*/
/**
* Get per-context SAREA.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx_priv_map structure.
* \return zero on success or a negative number on failure.
*
* Gets the map from drm_device::ctx_idr with the handle specified and
* returns its handle.
*/
int drm_legacy_getsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx_priv_map *request = data;
struct drm_local_map *map;
struct drm_map_list *_entry;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return -EINVAL;
mutex_lock(&dev->struct_mutex);
map = idr_find(&dev->ctx_idr, request->ctx_id);
if (!map) {
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
request->handle = NULL;
list_for_each_entry(_entry, &dev->maplist, head) {
if (_entry->map == map) {
request->handle =
(void *)(unsigned long)_entry->user_token;
break;
}
}
mutex_unlock(&dev->struct_mutex);
if (request->handle == NULL)
return -EINVAL;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Airlie | 72 | 43.64% | 9 | 45.00% |
Linus Torvalds | 35 | 21.21% | 2 | 10.00% |
Peter Antoine | 20 | 12.12% | 1 | 5.00% |
Eric Anholt | 14 | 8.48% | 2 | 10.00% |
Linus Torvalds (pre-git) | 11 | 6.67% | 1 | 5.00% |
Ilija Hadzic | 8 | 4.85% | 1 | 5.00% |
Daniel Vetter | 2 | 1.21% | 1 | 5.00% |
David Herrmann | 1 | 0.61% | 1 | 5.00% |
Al Viro | 1 | 0.61% | 1 | 5.00% |
Benjamin Herrenschmidt | 1 | 0.61% | 1 | 5.00% |
Total | 165 | 100.00% | 20 | 100.00% |
/**
* Set per-context SAREA.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx_priv_map structure.
* \return zero on success or a negative number on failure.
*
* Searches the mapping specified in \p arg and update the entry in
* drm_device::ctx_idr with it.
*/
int drm_legacy_setsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx_priv_map *request = data;
struct drm_local_map *map = NULL;
struct drm_map_list *r_list = NULL;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return -EINVAL;
mutex_lock(&dev->struct_mutex);
list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map
&& r_list->user_token == (unsigned long) request->handle)
goto found;
}
bad:
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
found:
map = r_list->map;
if (!map)
goto bad;
if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id)))
goto bad;
mutex_unlock(&dev->struct_mutex);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 48 | 29.27% | 4 | 21.05% |
Linus Torvalds (pre-git) | 47 | 28.66% | 1 | 5.26% |
Dave Airlie | 32 | 19.51% | 8 | 42.11% |
Peter Antoine | 20 | 12.20% | 1 | 5.26% |
Eric Anholt | 13 | 7.93% | 2 | 10.53% |
Daniel Vetter | 2 | 1.22% | 1 | 5.26% |
Benjamin Herrenschmidt | 1 | 0.61% | 1 | 5.26% |
David Herrmann | 1 | 0.61% | 1 | 5.26% |
Total | 164 | 100.00% | 19 | 100.00% |
/*@}*/
/******************************************************************/
/** \name The actual DRM context handling routines */
/*@{*/
/**
* Switch context.
*
* \param dev DRM device.
* \param old old context handle.
* \param new new context handle.
* \return zero on success or a negative number on failure.
*
* Attempt to set drm_device::context_flag.
*/
static int drm_context_switch(struct drm_device * dev, int old, int new)
{
if (test_and_set_bit(0, &dev->context_flag)) {
DRM_ERROR("Reentering -- FIXME\n");
return -EBUSY;
}
DRM_DEBUG("Context switch from %d to %d\n", old, new);
if (new == dev->last_context) {
clear_bit(0, &dev->context_flag);
return 0;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 56 | 74.67% | 2 | 33.33% |
Linus Torvalds (pre-git) | 15 | 20.00% | 1 | 16.67% |
Dave Airlie | 4 | 5.33% | 3 | 50.00% |
Total | 75 | 100.00% | 6 | 100.00% |
/**
* Complete context switch.
*
* \param dev DRM device.
* \param new new context handle.
* \return zero on success or a negative number on failure.
*
* Updates drm_device::last_context and drm_device::last_switch. Verifies the
* hardware lock is held, clears the drm_device::context_flag and wakes up
* drm_device::context_wait.
*/
static int drm_context_switch_complete(struct drm_device *dev,
struct drm_file *file_priv, int new)
{
dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) {
DRM_ERROR("Lock isn't held after context switch\n");
}
/* If a context switch is ever initiated
when the kernel holds the lock, release
that lock here. */
clear_bit(0, &dev->context_flag);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 32 | 50.79% | 1 | 14.29% |
Linus Torvalds (pre-git) | 18 | 28.57% | 1 | 14.29% |
Dave Airlie | 13 | 20.63% | 5 | 71.43% |
Total | 63 | 100.00% | 7 | 100.00% |
/**
* Reserve contexts.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx_res structure.
* \return zero on success or a negative number on failure.
*/
int drm_legacy_resctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx_res *res = data;
struct drm_ctx ctx;
int i;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return -EINVAL;
if (res->count >= DRM_RESERVED_CONTEXTS) {
memset(&ctx, 0, sizeof(ctx));
for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
ctx.handle = i;
if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
return -EFAULT;
}
}
res->count = DRM_RESERVED_CONTEXTS;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 61 | 45.86% | 1 | 10.00% |
Linus Torvalds (pre-git) | 27 | 20.30% | 1 | 10.00% |
Peter Antoine | 20 | 15.04% | 1 | 10.00% |
Eric Anholt | 13 | 9.77% | 2 | 20.00% |
Dave Airlie | 6 | 4.51% | 2 | 20.00% |
Al Viro | 3 | 2.26% | 1 | 10.00% |
Daniel Vetter | 2 | 1.50% | 1 | 10.00% |
David Herrmann | 1 | 0.75% | 1 | 10.00% |
Total | 133 | 100.00% | 10 | 100.00% |
/**
* Add context.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*
* Get a new handle for the context and copy to userspace.
*/
int drm_legacy_addctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx_list *ctx_entry;
struct drm_ctx *ctx = data;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return -EINVAL;
ctx->handle = drm_legacy_ctxbitmap_next(dev);
if (ctx->handle == DRM_KERNEL_CONTEXT) {
/* Skip kernel's context and get a new one. */
ctx->handle = drm_legacy_ctxbitmap_next(dev);
}
DRM_DEBUG("%d\n", ctx->handle);
if (ctx->handle == -1) {
DRM_DEBUG("Not enough free contexts.\n");
/* Should this return -EBUSY instead? */
return -ENOMEM;
}
ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL);
if (!ctx_entry) {
DRM_DEBUG("out of memory\n");
return -ENOMEM;
}
INIT_LIST_HEAD(&ctx_entry->head);
ctx_entry->handle = ctx->handle;
ctx_entry->tag = file_priv;
mutex_lock(&dev->ctxlist_mutex);
list_add(&ctx_entry->head, &dev->ctxlist);
mutex_unlock(&dev->ctxlist_mutex);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Airlie | 83 | 42.56% | 5 | 38.46% |
Linus Torvalds | 65 | 33.33% | 1 | 7.69% |
Peter Antoine | 20 | 10.26% | 1 | 7.69% |
Eric Anholt | 19 | 9.74% | 3 | 23.08% |
Al Viro | 3 | 1.54% | 1 | 7.69% |
David Herrmann | 3 | 1.54% | 1 | 7.69% |
Daniel Vetter | 2 | 1.03% | 1 | 7.69% |
Total | 195 | 100.00% | 13 | 100.00% |
/**
* Get context.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*/
int drm_legacy_getctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return -EINVAL;
/* This is 0, because we don't handle any context flags */
ctx->flags = 0;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 21 | 36.21% | 1 | 12.50% |
Peter Antoine | 20 | 34.48% | 1 | 12.50% |
Eric Anholt | 11 | 18.97% | 2 | 25.00% |
Dave Airlie | 2 | 3.45% | 1 | 12.50% |
Daniel Vetter | 2 | 3.45% | 1 | 12.50% |
David Herrmann | 1 | 1.72% | 1 | 12.50% |
Al Viro | 1 | 1.72% | 1 | 12.50% |
Total | 58 | 100.00% | 8 | 100.00% |
/**
* Switch context.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*
* Calls context_switch().
*/
int drm_legacy_switchctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return -EINVAL;
DRM_DEBUG("%d\n", ctx->handle);
return drm_context_switch(dev, dev->last_context, ctx->handle);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 32 | 45.07% | 1 | 11.11% |
Peter Antoine | 20 | 28.17% | 1 | 11.11% |
Eric Anholt | 13 | 18.31% | 2 | 22.22% |
Dave Airlie | 3 | 4.23% | 3 | 33.33% |
Daniel Vetter | 2 | 2.82% | 1 | 11.11% |
David Herrmann | 1 | 1.41% | 1 | 11.11% |
Total | 71 | 100.00% | 9 | 100.00% |
/**
* New context.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*
* Calls context_switch_complete().
*/
int drm_legacy_newctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return -EINVAL;
DRM_DEBUG("%d\n", ctx->handle);
drm_context_switch_complete(dev, file_priv, ctx->handle);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 26 | 36.62% | 1 | 10.00% |
Peter Antoine | 20 | 28.17% | 1 | 10.00% |
Eric Anholt | 13 | 18.31% | 2 | 20.00% |
Dave Airlie | 9 | 12.68% | 4 | 40.00% |
Daniel Vetter | 2 | 2.82% | 1 | 10.00% |
David Herrmann | 1 | 1.41% | 1 | 10.00% |
Total | 71 | 100.00% | 10 | 100.00% |
/**
* Remove context.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg user argument pointing to a drm_ctx structure.
* \return zero on success or a negative number on failure.
*
* If not the special kernel context, calls ctxbitmap_free() to free the specified context.
*/
int drm_legacy_rmctx(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_ctx *ctx = data;
if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
!drm_core_check_feature(dev, DRIVER_LEGACY))
return -EINVAL;
DRM_DEBUG("%d\n", ctx->handle);
if (ctx->handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_dtor)
dev->driver->context_dtor(dev, ctx->handle);
drm_legacy_ctxbitmap_free(dev, ctx->handle);
}
mutex_lock(&dev->ctxlist_mutex);
if (!list_empty(&dev->ctxlist)) {
struct drm_ctx_list *pos, *n;
list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
if (pos->handle == ctx->handle) {
list_del(&pos->head);
kfree(pos);
}
}
}
mutex_unlock(&dev->ctxlist_mutex);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Airlie | 93 | 53.45% | 9 | 52.94% |
Linus Torvalds | 40 | 22.99% | 2 | 11.76% |
Peter Antoine | 20 | 11.49% | 1 | 5.88% |
Eric Anholt | 17 | 9.77% | 3 | 17.65% |
Daniel Vetter | 2 | 1.15% | 1 | 5.88% |
David Herrmann | 2 | 1.15% | 1 | 5.88% |
Total | 174 | 100.00% | 17 | 100.00% |
/*@}*/
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 478 | 30.88% | 7 | 16.67% |
Dave Airlie | 363 | 23.45% | 19 | 45.24% |
Peter Antoine | 227 | 14.66% | 1 | 2.38% |
Linus Torvalds (pre-git) | 159 | 10.27% | 1 | 2.38% |
David Herrmann | 147 | 9.50% | 2 | 4.76% |
Eric Anholt | 121 | 7.82% | 3 | 7.14% |
Daniel Vetter | 26 | 1.68% | 2 | 4.76% |
Ilija Hadzic | 8 | 0.52% | 1 | 2.38% |
Al Viro | 8 | 0.52% | 1 | 2.38% |
Tejun Heo | 5 | 0.32% | 2 | 4.76% |
Ville Syrjälä | 3 | 0.19% | 1 | 2.38% |
Benjamin Herrenschmidt | 2 | 0.13% | 1 | 2.38% |
David Howells | 1 | 0.06% | 1 | 2.38% |
Total | 1548 | 100.00% | 42 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.