Release 4.17 drivers/gpu/drm/ttm/ttm_tt.c
/**************************************************************************
*
* Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
**************************************************************************/
/*
* Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
*/
#define pr_fmt(fmt) "[TTM] " fmt
#include <linux/sched.h>
#include <linux/pagemap.h>
#include <linux/shmem_fs.h>
#include <linux/file.h>
#include <drm/drm_cache.h>
#include <drm/ttm/ttm_bo_driver.h>
#include <drm/ttm/ttm_page_alloc.h>
#ifdef CONFIG_X86
#include <asm/set_memory.h>
#endif
/**
* Allocates a ttm structure for the given BO.
*/
int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
{
struct ttm_bo_device *bdev = bo->bdev;
uint32_t page_flags = 0;
reservation_object_assert_held(bo->resv);
if (bdev->need_dma32)
page_flags |= TTM_PAGE_FLAG_DMA32;
if (bdev->no_retry)
page_flags |= TTM_PAGE_FLAG_NO_RETRY;
switch (bo->type) {
case ttm_bo_type_device:
if (zero_alloc)
page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC;
break;
case ttm_bo_type_kernel:
break;
case ttm_bo_type_sg:
page_flags |= TTM_PAGE_FLAG_SG;
break;
default:
bo->ttm = NULL;
pr_err("Illegal buffer object type\n");
return -EINVAL;
}
bo->ttm = bdev->driver->ttm_tt_create(bo, page_flags);
if (unlikely(bo->ttm == NULL))
return -ENOMEM;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christian König | 135 | 100.00% | 2 | 100.00% |
Total | 135 | 100.00% | 2 | 100.00% |
/**
* Allocates storage for pointers to the pages that back the ttm.
*/
static int ttm_tt_alloc_page_directory(struct ttm_tt *ttm)
{
ttm->pages = kvmalloc_array(ttm->num_pages, sizeof(void*),
GFP_KERNEL | __GFP_ZERO);
if (!ttm->pages)
return -ENOMEM;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 18 | 39.13% | 1 | 16.67% |
Tom St Denis | 15 | 32.61% | 1 | 16.67% |
Michal Hocko | 5 | 10.87% | 1 | 16.67% |
Dave Airlie | 4 | 8.70% | 1 | 16.67% |
Konrad Rzeszutek Wilk | 3 | 6.52% | 1 | 16.67% |
Jérôme Glisse | 1 | 2.17% | 1 | 16.67% |
Total | 46 | 100.00% | 6 | 100.00% |
static int ttm_dma_tt_alloc_page_directory(struct ttm_dma_tt *ttm)
{
ttm->ttm.pages = kvmalloc_array(ttm->ttm.num_pages,
sizeof(*ttm->ttm.pages) +
sizeof(*ttm->dma_address),
GFP_KERNEL | __GFP_ZERO);
if (!ttm->ttm.pages)
return -ENOMEM;
ttm->dma_address = (void *) (ttm->ttm.pages + ttm->ttm.num_pages);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Alexandre Courbot | 28 | 32.56% | 2 | 28.57% |
Tom St Denis | 17 | 19.77% | 1 | 14.29% |
Jérôme Glisse | 15 | 17.44% | 1 | 14.29% |
Thomas Hellstrom | 13 | 15.12% | 1 | 14.29% |
Konrad Rzeszutek Wilk | 8 | 9.30% | 1 | 14.29% |
Michal Hocko | 5 | 5.81% | 1 | 14.29% |
Total | 86 | 100.00% | 7 | 100.00% |
static int ttm_sg_tt_alloc_page_directory(struct ttm_dma_tt *ttm)
{
ttm->dma_address = kvmalloc_array(ttm->ttm.num_pages,
sizeof(*ttm->dma_address),
GFP_KERNEL | __GFP_ZERO);
if (!ttm->dma_address)
return -ENOMEM;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christian König | 50 | 100.00% | 1 | 100.00% |
Total | 50 | 100.00% | 1 | 100.00% |
#ifdef CONFIG_X86
static inline int ttm_tt_set_page_caching(struct page *p,
enum ttm_caching_state c_old,
enum ttm_caching_state c_new)
{
int ret = 0;
if (PageHighMem(p))
return 0;
if (c_old != tt_cached) {
/* p isn't in the default caching state, set it to
* writeback first to free its current memtype. */
ret = set_pages_wb(p, 1);
if (ret)
return ret;
}
if (c_new == tt_wc)
ret = set_memory_wc((unsigned long) page_address(p), 1);
else if (c_new == tt_uncached)
ret = set_pages_uc(p, 1);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 56 | 55.45% | 1 | 33.33% |
Francisco Jerez | 45 | 44.55% | 2 | 66.67% |
Total | 101 | 100.00% | 3 | 100.00% |
#else /* CONFIG_X86 */
static inline int ttm_tt_set_page_caching(struct page *p,
enum ttm_caching_state c_old,
enum ttm_caching_state c_new)
{
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 18 | 78.26% | 1 | 50.00% |
Francisco Jerez | 5 | 21.74% | 1 | 50.00% |
Total | 23 | 100.00% | 2 | 100.00% |
#endif /* CONFIG_X86 */
/*
* Change caching policy for the linear kernel map
* for range of pages in a ttm.
*/
static int ttm_tt_set_caching(struct ttm_tt *ttm,
enum ttm_caching_state c_state)
{
int i, j;
struct page *cur_page;
int ret;
if (ttm->caching_state == c_state)
return 0;
if (ttm->state == tt_unpopulated) {
/* Change caching but don't populate */
ttm->caching_state = c_state;
return 0;
}
if (ttm->caching_state == tt_cached)
drm_clflush_pages(ttm->pages, ttm->num_pages);
for (i = 0; i < ttm->num_pages; ++i) {
cur_page = ttm->pages[i];
if (likely(cur_page != NULL)) {
ret = ttm_tt_set_page_caching(cur_page,
ttm->caching_state,
c_state);
if (unlikely(ret != 0))
goto out_err;
}
}
ttm->caching_state = c_state;
return 0;
out_err:
for (j = 0; j < i; ++j) {
cur_page = ttm->pages[j];
if (likely(cur_page != NULL)) {
(void)ttm_tt_set_page_caching(cur_page, c_state,
ttm->caching_state);
}
}
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 185 | 91.13% | 1 | 25.00% |
Pauli Nieminen | 11 | 5.42% | 1 | 25.00% |
Francisco Jerez | 6 | 2.96% | 1 | 25.00% |
Dave Airlie | 1 | 0.49% | 1 | 25.00% |
Total | 203 | 100.00% | 4 | 100.00% |
int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement)
{
enum ttm_caching_state state;
if (placement & TTM_PL_FLAG_WC)
state = tt_wc;
else if (placement & TTM_PL_FLAG_UNCACHED)
state = tt_uncached;
else
state = tt_cached;
return ttm_tt_set_caching(ttm, state);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 51 | 100.00% | 1 | 100.00% |
Total | 51 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(ttm_tt_set_placement_caching);
void ttm_tt_destroy(struct ttm_tt *ttm)
{
if (ttm == NULL)
return;
ttm_tt_unbind(ttm);
if (ttm->state == tt_unbound)
ttm_tt_unpopulate(ttm);
if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) &&
ttm->swap_storage)
fput(ttm->swap_storage);
ttm->swap_storage = NULL;
ttm->func->destroy(ttm);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 54 | 75.00% | 1 | 20.00% |
Jérôme Glisse | 14 | 19.44% | 2 | 40.00% |
Ben Skeggs | 3 | 4.17% | 1 | 20.00% |
Jan Engelhardt | 1 | 1.39% | 1 | 20.00% |
Total | 72 | 100.00% | 5 | 100.00% |
void ttm_tt_init_fields(struct ttm_tt *ttm, struct ttm_buffer_object *bo,
uint32_t page_flags)
{
ttm->bdev = bo->bdev;
ttm->num_pages = bo->num_pages;
ttm->caching_state = tt_cached;
ttm->page_flags = page_flags;
ttm->state = tt_unpopulated;
ttm->swap_storage = NULL;
ttm->sg = bo->sg;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 32 | 48.48% | 1 | 16.67% |
Christian König | 18 | 27.27% | 3 | 50.00% |
Jérôme Glisse | 16 | 24.24% | 2 | 33.33% |
Total | 66 | 100.00% | 6 | 100.00% |
int ttm_tt_init(struct ttm_tt *ttm, struct ttm_buffer_object *bo,
uint32_t page_flags)
{
ttm_tt_init_fields(ttm, bo, page_flags);
if (ttm_tt_alloc_page_directory(ttm)) {
ttm_tt_destroy(ttm);
pr_err("Failed allocating page table\n");
return -ENOMEM;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christian König | 26 | 49.06% | 2 | 28.57% |
Jérôme Glisse | 19 | 35.85% | 1 | 14.29% |
Konrad Rzeszutek Wilk | 3 | 5.66% | 1 | 14.29% |
Tom St Denis | 2 | 3.77% | 1 | 14.29% |
Joe Perches | 2 | 3.77% | 1 | 14.29% |
Thomas Hellstrom | 1 | 1.89% | 1 | 14.29% |
Total | 53 | 100.00% | 7 | 100.00% |
EXPORT_SYMBOL(ttm_tt_init);
void ttm_tt_fini(struct ttm_tt *ttm)
{
kvfree(ttm->pages);
ttm->pages = NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jérôme Glisse | 22 | 95.65% | 1 | 50.00% |
Michal Hocko | 1 | 4.35% | 1 | 50.00% |
Total | 23 | 100.00% | 2 | 100.00% |
EXPORT_SYMBOL(ttm_tt_fini);
int ttm_dma_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo,
uint32_t page_flags)
{
struct ttm_tt *ttm = &ttm_dma->ttm;
ttm_tt_init_fields(ttm, bo, page_flags);
INIT_LIST_HEAD(&ttm_dma->pages_list);
if (ttm_dma_tt_alloc_page_directory(ttm_dma)) {
ttm_tt_destroy(ttm);
pr_err("Failed allocating page table\n");
return -ENOMEM;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christian König | 39 | 54.93% | 2 | 66.67% |
Jérôme Glisse | 32 | 45.07% | 1 | 33.33% |
Total | 71 | 100.00% | 3 | 100.00% |
EXPORT_SYMBOL(ttm_dma_tt_init);
int ttm_sg_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo,
uint32_t page_flags)
{
struct ttm_tt *ttm = &ttm_dma->ttm;
int ret;
ttm_tt_init_fields(ttm, bo, page_flags);
INIT_LIST_HEAD(&ttm_dma->pages_list);
if (page_flags & TTM_PAGE_FLAG_SG)
ret = ttm_sg_tt_alloc_page_directory(ttm_dma);
else
ret = ttm_dma_tt_alloc_page_directory(ttm_dma);
if (ret) {
ttm_tt_destroy(ttm);
pr_err("Failed allocating page table\n");
return -ENOMEM;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christian König | 54 | 58.70% | 2 | 25.00% |
Jérôme Glisse | 17 | 18.48% | 3 | 37.50% |
Thomas Hellstrom | 17 | 18.48% | 1 | 12.50% |
Joe Perches | 2 | 2.17% | 1 | 12.50% |
Tom St Denis | 2 | 2.17% | 1 | 12.50% |
Total | 92 | 100.00% | 8 | 100.00% |
EXPORT_SYMBOL(ttm_sg_tt_init);
void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma)
{
struct ttm_tt *ttm = &ttm_dma->ttm;
if (ttm->pages)
kvfree(ttm->pages);
else
kvfree(ttm_dma->dma_address);
ttm->pages = NULL;
ttm_dma->dma_address = NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jérôme Glisse | 37 | 69.81% | 1 | 25.00% |
Christian König | 14 | 26.42% | 1 | 25.00% |
Alexandre Courbot | 1 | 1.89% | 1 | 25.00% |
Michal Hocko | 1 | 1.89% | 1 | 25.00% |
Total | 53 | 100.00% | 4 | 100.00% |
EXPORT_SYMBOL(ttm_dma_tt_fini);
void ttm_tt_unbind(struct ttm_tt *ttm)
{
int ret;
if (ttm->state == tt_bound) {
ret = ttm->func->unbind(ttm);
BUG_ON(ret);
ttm->state = tt_unbound;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 43 | 95.56% | 1 | 50.00% |
Jérôme Glisse | 2 | 4.44% | 1 | 50.00% |
Total | 45 | 100.00% | 2 | 100.00% |
int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem,
struct ttm_operation_ctx *ctx)
{
int ret = 0;
if (!ttm)
return -EINVAL;
if (ttm->state == tt_bound)
return 0;
ret = ttm_tt_populate(ttm, ctx);
if (ret)
return ret;
ret = ttm->func->bind(ttm, bo_mem);
if (unlikely(ret != 0))
return ret;
ttm->state = tt_bound;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 84 | 88.42% | 2 | 40.00% |
Roger He | 9 | 9.47% | 2 | 40.00% |
Jérôme Glisse | 2 | 2.11% | 1 | 20.00% |
Total | 95 | 100.00% | 5 | 100.00% |
EXPORT_SYMBOL(ttm_tt_bind);
int ttm_tt_swapin(struct ttm_tt *ttm)
{
struct address_space *swap_space;
struct file *swap_storage;
struct page *from_page;
struct page *to_page;
int i;
int ret = -ENOMEM;
swap_storage = ttm->swap_storage;
BUG_ON(swap_storage == NULL);
swap_space = swap_storage->f_mapping;
for (i = 0; i < ttm->num_pages; ++i) {
gfp_t gfp_mask = mapping_gfp_mask(swap_space);
gfp_mask |= (ttm->page_flags & TTM_PAGE_FLAG_NO_RETRY ? __GFP_RETRY_MAYFAIL : 0);
from_page = shmem_read_mapping_page_gfp(swap_space, i, gfp_mask);
if (IS_ERR(from_page)) {
ret = PTR_ERR(from_page);
goto out_err;
}
to_page = ttm->pages[i];
if (unlikely(to_page == NULL))
goto out_err;
copy_highpage(to_page, from_page);
put_page(from_page);
}
if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP))
fput(swap_storage);
ttm->swap_storage = NULL;
ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED;
return 0;
out_err:
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 150 | 76.14% | 1 | 12.50% |
Andrey Grodzovsky | 25 | 12.69% | 1 | 12.50% |
Maarten Maathuis | 13 | 6.60% | 1 | 12.50% |
Jérôme Glisse | 4 | 2.03% | 1 | 12.50% |
Akinobu Mita | 2 | 1.02% | 1 | 12.50% |
Al Viro | 1 | 0.51% | 1 | 12.50% |
Jan Engelhardt | 1 | 0.51% | 1 | 12.50% |
Kirill A. Shutemov | 1 | 0.51% | 1 | 12.50% |
Total | 197 | 100.00% | 8 | 100.00% |
int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
{
struct address_space *swap_space;
struct file *swap_storage;
struct page *from_page;
struct page *to_page;
int i;
int ret = -ENOMEM;
BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated);
BUG_ON(ttm->caching_state != tt_cached);
if (!persistent_swap_storage) {
swap_storage = shmem_file_setup("ttm swap",
ttm->num_pages << PAGE_SHIFT,
0);
if (IS_ERR(swap_storage)) {
pr_err("Failed allocating swap storage\n");
return PTR_ERR(swap_storage);
}
} else {
swap_storage = persistent_swap_storage;
}
swap_space = swap_storage->f_mapping;
for (i = 0; i < ttm->num_pages; ++i) {
gfp_t gfp_mask = mapping_gfp_mask(swap_space);
gfp_mask |= (ttm->page_flags & TTM_PAGE_FLAG_NO_RETRY ? __GFP_RETRY_MAYFAIL : 0);
from_page = ttm->pages[i];
if (unlikely(from_page == NULL))
continue;
to_page = shmem_read_mapping_page_gfp(swap_space, i, gfp_mask);
if (IS_ERR(to_page)) {
ret = PTR_ERR(to_page);
goto out_err;
}
copy_highpage(to_page, from_page);
set_page_dirty(to_page);
mark_page_accessed(to_page);
put_page(to_page);
}
ttm_tt_unpopulate(ttm);
ttm->swap_storage = swap_storage;
ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED;
if (persistent_swap_storage)
ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;
return 0;
out_err:
if (!persistent_swap_storage)
fput(swap_storage);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 215 | 77.34% | 1 | 10.00% |
Andrey Grodzovsky | 25 | 8.99% | 1 | 10.00% |
Maarten Maathuis | 23 | 8.27% | 1 | 10.00% |
Jan Engelhardt | 6 | 2.16% | 1 | 10.00% |
Joe Perches | 2 | 0.72% | 1 | 10.00% |
Tom St Denis | 2 | 0.72% | 1 | 10.00% |
Akinobu Mita | 2 | 0.72% | 1 | 10.00% |
Kirill A. Shutemov | 1 | 0.36% | 1 | 10.00% |
Al Viro | 1 | 0.36% | 1 | 10.00% |
Jérôme Glisse | 1 | 0.36% | 1 | 10.00% |
Total | 278 | 100.00% | 10 | 100.00% |
static void ttm_tt_add_mapping(struct ttm_tt *ttm)
{
pgoff_t i;
if (ttm->page_flags & TTM_PAGE_FLAG_SG)
return;
for (i = 0; i < ttm->num_pages; ++i)
ttm->pages[i]->mapping = ttm->bdev->dev_mapping;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christian König | 53 | 100.00% | 1 | 100.00% |
Total | 53 | 100.00% | 1 | 100.00% |
int ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
{
int ret;
if (ttm->state != tt_unpopulated)
return 0;
if (ttm->bdev->driver->ttm_tt_populate)
ret = ttm->bdev->driver->ttm_tt_populate(ttm, ctx);
else
ret = ttm_pool_populate(ttm, ctx);
if (!ret)
ttm_tt_add_mapping(ttm);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christian König | 77 | 100.00% | 3 | 100.00% |
Total | 77 | 100.00% | 3 | 100.00% |
static void ttm_tt_clear_mapping(struct ttm_tt *ttm)
{
pgoff_t i;
struct page **page = ttm->pages;
if (ttm->page_flags & TTM_PAGE_FLAG_SG)
return;
for (i = 0; i < ttm->num_pages; ++i) {
(*page)->mapping = NULL;
(*page++)->index = 0;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 69 | 100.00% | 2 | 100.00% |
Total | 69 | 100.00% | 2 | 100.00% |
void ttm_tt_unpopulate(struct ttm_tt *ttm)
{
if (ttm->state == tt_unpopulated)
return;
ttm_tt_clear_mapping(ttm);
if (ttm->bdev->driver->ttm_tt_unpopulate)
ttm->bdev->driver->ttm_tt_unpopulate(ttm);
else
ttm_pool_unpopulate(ttm);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 35 | 68.63% | 1 | 50.00% |
Christian König | 16 | 31.37% | 1 | 50.00% |
Total | 51 | 100.00% | 2 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 1071 | 51.61% | 4 | 9.52% |
Christian König | 489 | 23.57% | 8 | 19.05% |
Jérôme Glisse | 201 | 9.69% | 4 | 9.52% |
Francisco Jerez | 56 | 2.70% | 2 | 4.76% |
Andrey Grodzovsky | 50 | 2.41% | 1 | 2.38% |
Tom St Denis | 38 | 1.83% | 2 | 4.76% |
Maarten Maathuis | 36 | 1.73% | 1 | 2.38% |
Alexandre Courbot | 29 | 1.40% | 2 | 4.76% |
Konrad Rzeszutek Wilk | 14 | 0.67% | 2 | 4.76% |
Dave Airlie | 13 | 0.63% | 3 | 7.14% |
Joe Perches | 13 | 0.63% | 1 | 2.38% |
Michal Hocko | 12 | 0.58% | 1 | 2.38% |
Pauli Nieminen | 11 | 0.53% | 1 | 2.38% |
Roger He | 9 | 0.43% | 2 | 4.76% |
Jan Engelhardt | 8 | 0.39% | 1 | 2.38% |
Laura Abbott | 8 | 0.39% | 1 | 2.38% |
Akinobu Mita | 4 | 0.19% | 1 | 2.38% |
David Howells | 3 | 0.14% | 1 | 2.38% |
Ben Skeggs | 3 | 0.14% | 1 | 2.38% |
Hugh Dickins | 3 | 0.14% | 1 | 2.38% |
Al Viro | 2 | 0.10% | 1 | 2.38% |
Kirill A. Shutemov | 2 | 0.10% | 1 | 2.38% |
Total | 2075 | 100.00% | 42 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.