summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-05-14 22:42:21 +1000
committerDave Airlie <airlied@redhat.com>2008-05-14 22:42:21 +1000
commitbc0836e12a9790f1cc83f8bc29bc05043c4bc840 (patch)
treef587f1cec2fa65ace7cd6fd517e8d18862154fed
parentdd1f33f83cbbb9917e13f194fadda4f7066ea98a (diff)
ati_pcigart: fixup properly this version might even work
-rw-r--r--linux-core/ati_pcigart.c21
-rw-r--r--linux-core/drm_object.c57
-rw-r--r--linux-core/drm_objects.h6
3 files changed, 51 insertions, 33 deletions
diff --git a/linux-core/ati_pcigart.c b/linux-core/ati_pcigart.c
index 34081d4f..f7752b5e 100644
--- a/linux-core/ati_pcigart.c
+++ b/linux-core/ati_pcigart.c
@@ -36,6 +36,9 @@
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
# define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1))
+#define ATI_PCIE_WRITE 0x4
+#define ATI_PCIE_READ 0x8
+
static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
struct drm_ati_pcigart_info *gart_info)
{
@@ -105,6 +108,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
dma_addr_t bus_address = 0;
int i, j, ret = 0;
int max_pages;
+ dma_addr_t entry_addr;
if (!entry) {
DRM_ERROR("no scatter/gather memory!\n");
@@ -151,27 +155,26 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
goto done;
}
+ entry_addr = entry->busaddr[i];
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+ page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK;
switch(gart_info->gart_reg_if) {
case DRM_ATI_GART_IGP:
- page_base = (u32) entry->busaddr[i] & ATI_PCIGART_PAGE_MASK;
- page_base |= (upper_32_bits(entry->busaddr[i]) & 0xff) << 4;
- *pci_gart = cpu_to_le32((page_base) | 0xc);
+ page_base |= (upper_32_bits(entry_addr) & 0xff) << 4;
+ page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;
break;
case DRM_ATI_GART_PCIE:
- page_base = (u32)(entry->busaddr[i] & ATI_PCIGART_PAGE_MASK);
page_base >>= 8;
- page_base |= (upper_32_bits(entry->busaddr[i]) & 0xff) << 24;
- *pci_gart = cpu_to_le32((page_base >> 8) | 0xc);
+ page_base |= (upper_32_bits(entry_addr) & 0xff) << 24;
+ page_base |= 0xc;
break;
default:
case DRM_ATI_GART_PCI:
- page_base = (u32) entry->busaddr[i];
- *pci_gart = cpu_to_le32(page_base);
break;
}
+ *pci_gart = cpu_to_le32(page_base);
pci_gart++;
- page_base += ATI_PCIGART_PAGE_SIZE;
+ entry_addr += ATI_PCIGART_PAGE_SIZE;
}
}
diff --git a/linux-core/drm_object.c b/linux-core/drm_object.c
index 2994b716..10924cf5 100644
--- a/linux-core/drm_object.c
+++ b/linux-core/drm_object.c
@@ -39,7 +39,7 @@ int drm_add_user_object(struct drm_file *priv, struct drm_user_object *item,
DRM_ASSERT_LOCKED(&dev->struct_mutex);
/* The refcount will be bumped to 1 when we add the ref object below. */
- atomic_set(&item->refcount, 0);
+ kref_init(&item->refcount);
item->shareable = shareable;
item->owner = priv;
@@ -83,16 +83,20 @@ struct drm_user_object *drm_lookup_user_object(struct drm_file *priv, uint32_t k
}
EXPORT_SYMBOL(drm_lookup_user_object);
-static void drm_deref_user_object(struct drm_file *priv, struct drm_user_object *item)
+static void drm_user_object_free(struct kref *kref)
{
- struct drm_device *dev = priv->minor->dev;
+ struct drm_user_object *item = container_of(kref, struct drm_user_object, refcount);
int ret;
+ struct drm_device *dev = item->owner->minor->dev;
- if (atomic_dec_and_test(&item->refcount)) {
- ret = drm_ht_remove_item(&dev->object_hash, &item->hash);
- BUG_ON(ret);
- item->remove(priv, item);
- }
+ ret = drm_ht_remove_item(&dev->object_hash, &item->hash);
+ BUG_ON(ret);
+ item->remove(item->owner, item);
+}
+
+static void drm_deref_user_object(struct drm_user_object *item)
+{
+ kref_put(&item->refcount, drm_user_object_free);
}
static int drm_object_ref_action(struct drm_file *priv, struct drm_user_object *ro,
@@ -102,7 +106,7 @@ static int drm_object_ref_action(struct drm_file *priv, struct drm_user_object *
switch (action) {
case _DRM_REF_USE:
- atomic_inc(&ro->refcount);
+ kref_get(&ro->refcount);
break;
default:
if (!ro->ref_struct_locked) {
@@ -146,7 +150,7 @@ int drm_add_ref_object(struct drm_file *priv, struct drm_user_object *referenced
if (NULL !=
(item =
drm_lookup_ref_object(priv, referenced_object, ref_action))) {
- atomic_inc(&item->refcount);
+ kref_get(&item->refcount);
return drm_object_ref_action(priv, referenced_object,
ref_action);
}
@@ -157,8 +161,10 @@ int drm_add_ref_object(struct drm_file *priv, struct drm_user_object *referenced
return -ENOMEM;
}
- atomic_set(&item->refcount, 1);
+ kref_init(&item->refcount);
+ kref_get(&item->refcount);
item->hash.key = (unsigned long)referenced_object;
+ item->owner = priv;
ret = drm_ht_insert_item(ht, &item->hash);
item->unref_action = ref_action;
@@ -205,27 +211,34 @@ static void drm_remove_other_references(struct drm_file *priv,
}
}
-void drm_remove_ref_object(struct drm_file *priv, struct drm_ref_object *item)
+void drm_object_ref_free(struct kref *kref)
{
- int ret;
+ struct drm_ref_object *item = container_of(kref, struct drm_ref_object, refcount);
struct drm_user_object *user_object = (struct drm_user_object *) item->hash.key;
+ struct drm_file *priv = item->owner;
struct drm_open_hash *ht = &priv->refd_object_hash[item->unref_action];
+ int ret;
+
+ ret = drm_ht_remove_item(ht, &item->hash);
+ BUG_ON(ret);
+ list_del_init(&item->list);
+ if (item->unref_action == _DRM_REF_USE)
+ drm_remove_other_references(priv, user_object);
+ drm_ctl_free(item, sizeof(*item), DRM_MEM_OBJECTS);
+}
+
+void drm_remove_ref_object(struct drm_file *priv, struct drm_ref_object *item)
+{
+ struct drm_user_object *user_object = (struct drm_user_object *) item->hash.key;
enum drm_ref_type unref_action;
DRM_ASSERT_LOCKED(&priv->minor->dev->struct_mutex);
unref_action = item->unref_action;
- if (atomic_dec_and_test(&item->refcount)) {
- ret = drm_ht_remove_item(ht, &item->hash);
- BUG_ON(ret);
- list_del_init(&item->list);
- if (unref_action == _DRM_REF_USE)
- drm_remove_other_references(priv, user_object);
- drm_ctl_free(item, sizeof(*item), DRM_MEM_OBJECTS);
- }
+ kref_put(&item->refcount, drm_object_ref_free);
switch (unref_action) {
case _DRM_REF_USE:
- drm_deref_user_object(priv, user_object);
+ drm_deref_user_object(user_object);
break;
default:
BUG_ON(!user_object->unref);
diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h
index 770fbc56..427a9170 100644
--- a/linux-core/drm_objects.h
+++ b/linux-core/drm_objects.h
@@ -65,7 +65,8 @@ struct drm_user_object {
struct drm_hash_item hash;
struct list_head list;
enum drm_object_type type;
- atomic_t refcount;
+ struct kref refcount;
+
int shareable;
struct drm_file *owner;
void (*ref_struct_locked) (struct drm_file *priv,
@@ -86,8 +87,9 @@ struct drm_user_object {
struct drm_ref_object {
struct drm_hash_item hash;
struct list_head list;
- atomic_t refcount;
+ struct kref refcount;
enum drm_ref_type unref_action;
+ struct drm_file *owner;
};
/**