summaryrefslogtreecommitdiff
path: root/lib/main.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-08-20 14:54:05 +1000
committerBen Skeggs <bskeggs@redhat.com>2015-08-28 12:37:26 +1000
commitcf43fc0391a257fb17414d8b41746b9e16093578 (patch)
tree389b7f77db26a321fe0368262aa8888edcb55a5c /lib/main.c
parenta1d7077da37dfe2c3f89d1445f5b78e63de5666c (diff)
downloadnouveau-cf43fc0391a257fb17414d8b41746b9e16093578.tar.gz
lib: various tweaks
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'lib/main.c')
-rw-r--r--lib/main.c89
1 files changed, 47 insertions, 42 deletions
diff --git a/lib/main.c b/lib/main.c
index ac03c9684..6201c3ca3 100644
--- a/lib/main.c
+++ b/lib/main.c
@@ -47,6 +47,7 @@ static int os_client_nr = 0;
/******************************************************************************
* horrific stuff to implement linux's ioremap interface on top of pciaccess
*****************************************************************************/
+static DEFINE_MUTEX(os_ioremap_mutex);
static struct os_ioremap_info {
struct pci_device *pdev;
int refs;
@@ -56,54 +57,54 @@ static struct os_ioremap_info {
} os_ioremap[32];
void __iomem *
-nvos_ioremap(u64 addr, u64 size)
+nvos_ioremap_bar(struct pci_device *pdev, int bar, u64 addr)
{
- struct pci_device *pdev = NULL;
- struct os_ioremap_info *info;
- struct os_device *odev;
- u64 m_page = addr & 0xfff;
- u64 m_addr = addr & ~0xfff;
- u64 m_size = (size + 0xfff) & ~0xfff;
+ u64 base = pdev->regions[bar].base_addr;
+ u64 size = pdev->regions[bar].size;
+ u64 offset = addr - base;
+ void __iomem *ptr = NULL;
int i;
- list_for_each_entry(odev, &os_device_list, head) {
- for (i = 0; i < 6; i++) {
- pdev = odev->base.pdev->pdev;
- if (m_addr >= pdev->regions[i].base_addr &&
- m_addr + m_size <= pdev->regions[i].base_addr +
- pdev->regions[i].size)
- break;
- pdev = NULL;
+ mutex_lock(&os_ioremap_mutex);
+ for (i = 0; !ptr && i < ARRAY_SIZE(os_ioremap); i++) {
+ if (os_ioremap[i].refs && os_ioremap[i].addr == base) {
+ os_ioremap[i].refs++;
+ ptr = os_ioremap[i].ptr + offset;
}
- if (pdev)
- break;
}
- for (i = 0, info = NULL; pdev && i < ARRAY_SIZE(os_ioremap); i++) {
- if (os_ioremap[i].refs) {
- if (os_ioremap[i].addr != m_addr ||
- os_ioremap[i].size != m_size)
- continue;
- } else {
- info = &os_ioremap[i];
- continue;
+ for (i = 0; !ptr && i < ARRAY_SIZE(os_ioremap); i++) {
+ if (!os_ioremap[i].refs &&
+ !pci_device_map_range(pdev, base, size,
+ PCI_DEV_MAP_FLAG_WRITABLE,
+ &os_ioremap[i].ptr)) {
+ os_ioremap[i].pdev = pdev;
+ os_ioremap[i].refs = 1;
+ os_ioremap[i].addr = base;
+ os_ioremap[i].size = size;
+ ptr = os_ioremap[i].ptr + offset;
}
-
- os_ioremap[i].refs++;
- return os_ioremap[i].ptr + m_page;
}
+ mutex_unlock(&os_ioremap_mutex);
+
+ return ptr;
+}
- if (info) {
- if (pci_device_map_range(pdev, m_addr, m_size,
- PCI_DEV_MAP_FLAG_WRITABLE,
- &info->ptr))
- return NULL;
-
- info->pdev = pdev;
- info->refs = 1;
- info->addr = m_addr;
- info->size = m_size;
- return info->ptr + m_page;
+void __iomem *
+nvos_ioremap(u64 addr, u64 size)
+{
+ struct os_device *odev;
+ int i;
+
+ list_for_each_entry(odev, &os_device_list, head) {
+ struct pci_device *pdev = odev->base.pdev->pdev;
+ for (i = 0; i < ARRAY_SIZE(pdev->regions); i++) {
+ if (addr >= pdev->regions[i].base_addr &&
+ addr + size <= pdev->regions[i].base_addr +
+ pdev->regions[i].size) {
+ return nvos_ioremap_bar(pdev, i, addr);
+ }
+ }
}
return NULL;
@@ -114,17 +115,20 @@ nvos_iounmap(void __iomem *ptr)
{
int i;
+ mutex_lock(&os_ioremap_mutex);
for (i = 0; ptr && i < ARRAY_SIZE(os_ioremap); i++) {
if (os_ioremap[i].refs &&
ptr >= os_ioremap[i].ptr &&
ptr < os_ioremap[i].ptr + os_ioremap[i].size) {
if (!--os_ioremap[i].refs) {
- pci_device_unmap_range(os_ioremap[i].pdev, ptr,
+ pci_device_unmap_range(os_ioremap[i].pdev,
+ os_ioremap[i].ptr,
os_ioremap[i].size);
}
break;
}
}
+ mutex_unlock(&os_ioremap_mutex);
}
/******************************************************************************
@@ -152,7 +156,7 @@ os_init_device(struct pci_device *pdev, u64 handle, const char *cfg, const char
return -EEXIST;
}
- ldev = malloc(sizeof(*ldev));
+ ldev = calloc(1, sizeof(*ldev));
ldev->pdev = pdev;
ldev->device = pdev->dev;
ldev->subsystem_vendor = pdev->subvendor_id;
@@ -163,6 +167,7 @@ os_init_device(struct pci_device *pdev, u64 handle, const char *cfg, const char
cfg, dbg, &odev);
if (ret) {
fprintf(stderr, "failed to create device, %d\n", ret);
+ free(name);
return ret;
}
@@ -196,7 +201,7 @@ os_init(const char *cfg, const char *dbg, bool init)
(pdev->dev << 8) | pdev->func;
if (!init) {
- printf("%d: 0x%010"PRIx64" PCI:%04x:%02x:%02x:%02x "
+ printf("%d: 0x%010llx PCI:%04x:%02x:%02x:%02x "
"(%04x:%04x)\n", n++, handle, pdev->domain,
pdev->bus, pdev->dev, pdev->func,
pdev->vendor_id, pdev->device_id);