diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/ati_pcigart.c | 21 | ||||
| -rw-r--r-- | linux-core/drm_object.c | 57 | ||||
| -rw-r--r-- | linux-core/drm_objects.h | 6 | 
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;  };  /** | 
