major port of multi-master ideas into modesetting
authorDave Airlie <airlied@redhat.com>
Wed, 13 Feb 2008 05:19:42 +0000 (15:19 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 13 Feb 2008 05:19:42 +0000 (15:19 +1000)
14 files changed:
linux-core/drmP.h
linux-core/drm_auth.c
linux-core/drm_bufs.c
linux-core/drm_context.c
linux-core/drm_drv.c
linux-core/drm_fops.c
linux-core/drm_ioctl.c
linux-core/drm_irq.c
linux-core/drm_lock.c
linux-core/drm_proc.c
linux-core/drm_stub.c
linux-core/i915_drv.c
linux-core/intel_display.c
linux-core/via_fence.c

index afc16f5..d01bf09 100644 (file)
@@ -262,11 +262,11 @@ struct drm_file;
  */
 #define LOCK_TEST_WITH_RETURN( dev, file_priv )                                \
 do {                                                                   \
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||           \
-            dev->lock.file_priv != file_priv ) {                       \
+       if ( !_DRM_LOCK_IS_HELD( dev->primary->master->lock.hw_lock->lock ) ||          \
+            dev->primary->master->lock.file_priv != file_priv )        {                       \
                DRM_ERROR( "%s called without lock held, held  %d owner %p %p\n",\
-                          __FUNCTION__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
-                          dev->lock.file_priv, file_priv );            \
+                          __FUNCTION__, _DRM_LOCK_IS_HELD( dev->primary->master->lock.hw_lock->lock ),\
+                          dev->primary->master->lock.file_priv, file_priv );           \
                return -EINVAL;                                         \
        }                                                               \
 } while (0)
@@ -410,7 +410,6 @@ enum drm_ref_type {
 /** File private data */
 struct drm_file {
        int authenticated;
-       int master;
        pid_t pid;
        uid_t uid;
        drm_magic_t magic;
@@ -431,6 +430,7 @@ struct drm_file {
 
        struct drm_open_hash refd_object_hash[_DRM_NO_REF_TYPES];
        struct file *filp;
+       struct drm_master *master; /* this private has a master associated with it */
        void *driver_priv;
 
        struct list_head fbs;
@@ -568,6 +568,8 @@ struct drm_map_list {
        struct drm_map *map;                    /**< mapping */
        uint64_t user_token;
        struct drm_mm_node *file_offset_node;
+       struct drm_master *master; /** if this map is associated with a specific
+                                      master */
 };
 
 typedef struct drm_map drm_local_map_t;
@@ -607,6 +609,27 @@ struct drm_ati_pcigart_info {
 
 #include "drm_objects.h"
 
+/* per-master structure */
+struct drm_master {
+       
+       struct drm_device *dev;
+
+       char *unique;                   /**< Unique identifier: e.g., busid */
+       int unique_len;                 /**< Length of unique field */
+
+       int blocked;                    /**< Blocked due to VC switch? */
+
+       /** \name Authentication */
+       /*@{ */
+       struct drm_open_hash magiclist;
+       struct list_head magicfree;
+       /*@} */
+
+       struct drm_lock_data lock;              /**< Information on hardware lock */
+
+       void *driver_priv; /**< Private structure for driver to use */
+};
+
 /**
  * DRM driver structure. This structure represent the common code for
  * a family of cards. There will one drm_device for each card present
@@ -711,6 +734,10 @@ struct drm_driver {
        int (*fb_remove)(struct drm_device *dev, struct drm_crtc *crtc);
        int (*fb_resize)(struct drm_device *dev, struct drm_crtc *crtc);
 
+       /* Master routines */
+       int (*master_create)(struct drm_device *dev, struct drm_master *master);
+       void (*master_destroy)(struct drm_device *dev, struct drm_master *master);
+
        struct drm_fence_driver *fence_driver;
        struct drm_bo_driver *bo_driver;
 
@@ -746,6 +773,9 @@ struct drm_minor {
        /* for render nodes */
        struct proc_dir_entry *dev_root;  /**< proc directory entry */
        struct class_device *dev_class;
+
+       /* for control nodes - a pointer to the current master for this control node */
+       struct drm_master *master;
 };
 
 
@@ -754,13 +784,9 @@ struct drm_minor {
  * may contain multiple heads.
  */
 struct drm_device {
-       char *unique;                   /**< Unique identifier: e.g., busid */
-       int unique_len;                 /**< Length of unique field */
        char *devname;                  /**< For /proc/interrupts */
        int if_version;                 /**< Highest interface version set */
 
-       int blocked;                    /**< Blocked due to VC switch? */
-
        /** \name Locks */
        /*@{ */
        spinlock_t count_lock;          /**< For inuse, drm_device::open_count, drm_device::buf_use */
@@ -783,12 +809,6 @@ struct drm_device {
        atomic_t counts[15];
        /*@} */
 
-       /** \name Authentication */
-       /*@{ */
-       struct list_head filelist;
-       struct drm_open_hash magiclist;
-       struct list_head magicfree;
-       /*@} */
 
        /** \name Memory management */
        /*@{ */
@@ -809,7 +829,9 @@ struct drm_device {
        struct idr ctx_idr;
 
        struct list_head vmalist;       /**< List of vmas (for debugging) */
-       struct drm_lock_data lock;              /**< Information on hardware lock */
+
+       struct list_head filelist;
+//     struct drm_master *master;
        /*@} */
 
        /** \name DMA queues (contexts) */
@@ -821,6 +843,7 @@ struct drm_device {
        struct drm_device_dma *dma;             /**< Optional pointer for DMA support */
        /*@} */
 
+
        /** \name Context support */
        /*@{ */
        int irq;                        /**< Interrupt used by board */
@@ -884,7 +907,7 @@ struct drm_device {
 
        /* minor number for control node */
        struct drm_minor *control;
-       struct drm_minor *primary;              /**< primary screen head */
+       struct drm_minor *primary;              /**< render type primary screen head */
 
        struct drm_fence_manager fm;
        struct drm_buffer_manager bm;
@@ -1212,6 +1235,8 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
 extern struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev);
 extern void drm_agp_chipset_flush(struct drm_device *dev);
                                /* Stub support (drm_stub.h) */
+extern struct drm_master *drm_get_master(struct drm_device *dev);
+extern void drm_put_master(struct drm_master *master);
 extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
                     struct drm_driver *driver);
 extern int drm_put_dev(struct drm_device *dev);
index c904a91..8e85a76 100644 (file)
  * the one with matching magic number, while holding the drm_device::struct_mutex
  * lock.
  */
-static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
+static struct drm_file *drm_find_file(struct drm_master *master , drm_magic_t magic)
 {
        struct drm_file *retval = NULL;
        struct drm_magic_entry *pt;
        struct drm_hash_item *hash;
+       struct drm_device *dev = master->dev;
 
        mutex_lock(&dev->struct_mutex);
-       if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+       if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
                pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
                retval = pt->priv;
        }
@@ -71,11 +72,11 @@ static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic
  * associated the magic number hash key in drm_device::magiclist, while holding
  * the drm_device::struct_mutex lock.
  */
-static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
+static int drm_add_magic(struct drm_master *master, struct drm_file * priv,
                         drm_magic_t magic)
 {
        struct drm_magic_entry *entry;
-
+       struct drm_device *dev = master->dev;
        DRM_DEBUG("%d\n", magic);
 
        entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
@@ -85,8 +86,8 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
        entry->priv = priv;
        entry->hash_item.key = (unsigned long)magic;
        mutex_lock(&dev->struct_mutex);
-       drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
-       list_add_tail(&entry->head, &dev->magicfree);
+       drm_ht_insert_item(&master->magiclist, &entry->hash_item);
+       list_add_tail(&entry->head, &master->magicfree);
        mutex_unlock(&dev->struct_mutex);
 
        return 0;
@@ -101,20 +102,21 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
  * Searches and unlinks the entry in drm_device::magiclist with the magic
  * number hash key, while holding the drm_device::struct_mutex lock.
  */
-static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
+static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
 {
        struct drm_magic_entry *pt;
        struct drm_hash_item *hash;
+       struct drm_device *dev = master->dev;
 
        DRM_DEBUG("%d\n", magic);
 
        mutex_lock(&dev->struct_mutex);
-       if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+       if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {
                mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
        }
        pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
-       drm_ht_remove_item(&dev->magiclist, hash);
+       drm_ht_remove_item(&master->magiclist, hash);
        list_del(&pt->head);
        mutex_unlock(&dev->struct_mutex);
 
@@ -152,9 +154,9 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
                                ++sequence;     /* reserve 0 */
                        auth->magic = sequence++;
                        spin_unlock(&lock);
-               } while (drm_find_file(dev, auth->magic));
+               } while (drm_find_file(dev->primary->master, auth->magic));
                file_priv->magic = auth->magic;
-               drm_add_magic(dev, file_priv, auth->magic);
+               drm_add_magic(dev->primary->master, file_priv, auth->magic);
        }
 
        DRM_DEBUG("%u\n", auth->magic);
@@ -180,9 +182,9 @@ int drm_authmagic(struct drm_device *dev, void *data,
        struct drm_file *file;
 
        DRM_DEBUG("%u\n", auth->magic);
-       if ((file = drm_find_file(dev, auth->magic))) {
+       if ((file = drm_find_file(dev->primary->master, auth->magic))) {
                file->authenticated = 1;
-               drm_remove_magic(dev, auth->magic);
+               drm_remove_magic(dev->primary->master, auth->magic);
                return 0;
        }
        return -EINVAL;
index 967e9a2..3e1767c 100644 (file)
@@ -52,7 +52,7 @@ struct drm_map_list *drm_find_matching_map(struct drm_device *dev, drm_local_map
 {
        struct drm_map_list *entry;
        list_for_each_entry(entry, &dev->maplist, head) {
-               if (entry->map && map->type == entry->map->type &&
+               if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) &&
                    ((entry->map->offset == map->offset) || 
                     ((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) {
                        return entry;
@@ -209,12 +209,12 @@ static int drm_addmap_core(struct drm_device *dev, unsigned int offset,
                map->offset = (unsigned long)map->handle;
                if (map->flags & _DRM_CONTAINS_LOCK) {
                        /* Prevent a 2nd X Server from creating a 2nd lock */
-                       if (dev->lock.hw_lock != NULL) {
+                       if (dev->primary->master->lock.hw_lock != NULL) {
                                vfree(map->handle);
                                drm_free(map, sizeof(*map), DRM_MEM_MAPS);
                                return -EBUSY;
                        }
-                       dev->sigdata.lock = dev->lock.hw_lock = map->handle;    /* Pointer to lock */
+                       dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle;   /* Pointer to lock */
                }
                break;
        case _DRM_AGP: {
@@ -412,9 +412,9 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
                break;
        case _DRM_SHM:
                vfree(map->handle);
-               dev->sigdata.lock = dev->lock.hw_lock = NULL;   /* SHM removed */
-               dev->lock.file_priv = NULL;
-               wake_up_interruptible(&dev->lock.lock_queue);
+               dev->sigdata.lock = dev->primary->master->lock.hw_lock = NULL;   /* SHM removed */
+               dev->primary->master->lock.file_priv = NULL;
+               wake_up_interruptible(&dev->primary->master->lock.lock_queue);
                break;
        case _DRM_AGP:
        case _DRM_SCATTER_GATHER:
index 83ad291..63a3825 100644 (file)
@@ -262,7 +262,7 @@ static int drm_context_switch_complete(struct drm_device *dev, int new)
        dev->last_context = new;        /* PRE/POST: This is the _only_ writer. */
        dev->last_switch = jiffies;
 
-       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+       if (!_DRM_LOCK_IS_HELD(dev->primary->master->lock.hw_lock->lock)) {
                DRM_ERROR("Lock isn't held after context switch\n");
        }
 
index e995523..4f5b364 100644 (file)
@@ -180,8 +180,6 @@ static struct drm_ioctl_desc drm_ioctls[] = {
  */
 int drm_lastclose(struct drm_device * dev)
 {
-       struct drm_magic_entry *pt, *next;
-       struct drm_map_list *r_list, *list_t;
        struct drm_vma_entry *vma, *vma_temp;
        int i;
 
@@ -196,11 +194,6 @@ int drm_lastclose(struct drm_device * dev)
                dev->driver->lastclose(dev);
        DRM_DEBUG("driver lastclose completed\n");
 
-       if (dev->unique) {
-               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
-               dev->unique = NULL;
-               dev->unique_len = 0;
-       }
 
 /*     if (dev->irq_enabled)
                drm_irq_uninstall(dev); */
@@ -211,22 +204,11 @@ int drm_lastclose(struct drm_device * dev)
        drm_drawable_free_all(dev);
        del_timer(&dev->timer);
 
-       if (dev->unique) {
-               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
-               dev->unique = NULL;
-               dev->unique_len = 0;
-       }
-
-       if (dev->magicfree.next) {
-               list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
-                       list_del(&pt->head);
-                       drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
-                       drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-               }
-               drm_ht_remove(&dev->magiclist);
+       if (dev->primary->master) {
+               drm_put_master(dev->primary->master);
+               dev->primary->master = NULL;
        }
-
-
+       
        /* Clear AGP information */
        if (drm_core_has_AGP(dev) && dev->agp) {
                struct drm_agp_mem *entry, *tempe;
index 344d90e..c699e96 100644 (file)
@@ -54,8 +54,6 @@ static int drm_setup(struct drm_device * dev)
                        return ret;
        }
 
-       dev->magicfree.next = NULL;
-
        /* prebuild the SAREA */
        sareapage = max(SAREA_MAX, PAGE_SIZE);
        i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
@@ -76,11 +74,8 @@ static int drm_setup(struct drm_device * dev)
        for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
                atomic_set(&dev->counts[i], 0);
 
-       drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
-       INIT_LIST_HEAD(&dev->magicfree);
-
        dev->sigdata.lock = NULL;
-       init_waitqueue_head(&dev->lock.lock_queue);
+
        dev->queue_count = 0;
        dev->queue_reserved = 0;
        dev->queue_slots = 0;
@@ -282,8 +277,26 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
        }
 
        mutex_lock(&dev->struct_mutex);
-       if (list_empty(&dev->filelist))
-               priv->master = 1;
+
+       /* if there is no current master make this fd it */
+       if (!dev->primary->master) {
+               priv->master = drm_get_master(dev);
+               if (!priv->master) {
+                       ret = -ENOMEM;
+                       goto out_free;
+               }
+               dev->primary->master = priv->master;
+
+               if (dev->driver->master_create) {
+                       ret = dev->driver->master_create(dev, dev->primary->master);
+                       if (ret) {
+                               drm_put_master(dev->primary->master);
+                               dev->primary->master = priv->master = NULL;
+                               goto out_free;
+                       }
+               }
+       } else
+               priv->master = NULL;
 
        list_add(&priv->lhead, &dev->filelist);
        mutex_unlock(&dev->struct_mutex);
@@ -390,23 +403,23 @@ int drm_release(struct inode *inode, struct file *filp)
                  current->pid, (long)old_encode_dev(file_priv->minor->device),
                  dev->open_count);
 
-       if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
+       if (dev->driver->reclaim_buffers_locked && dev->primary->master->lock.hw_lock) {
                if (drm_i_have_hw_lock(dev, file_priv)) {
                        dev->driver->reclaim_buffers_locked(dev, file_priv);
                } else {
                        unsigned long _end=jiffies + 3*DRM_HZ;
                        int locked = 0;
 
-                       drm_idlelock_take(&dev->lock);
+                       drm_idlelock_take(&dev->primary->master->lock);
 
                        /*
                         * Wait for a while.
                         */
 
                        do{
-                               spin_lock(&dev->lock.spinlock);
-                               locked = dev->lock.idle_has_lock;
-                               spin_unlock(&dev->lock.spinlock);
+                               spin_lock(&dev->primary->master->lock.spinlock);
+                               locked = dev->primary->master->lock.idle_has_lock;
+                               spin_unlock(&dev->primary->master->lock.spinlock);
                                if (locked)
                                        break;
                                schedule();
@@ -419,24 +432,24 @@ int drm_release(struct inode *inode, struct file *filp)
                        }
 
                        dev->driver->reclaim_buffers_locked(dev, file_priv);
-                       drm_idlelock_release(&dev->lock);
+                       drm_idlelock_release(&dev->primary->master->lock);
                }
        }
 
-       if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) {
+       if (dev->driver->reclaim_buffers_idlelocked && dev->primary->master->lock.hw_lock) {
 
-               drm_idlelock_take(&dev->lock);
+               drm_idlelock_take(&dev->primary->master->lock);
                dev->driver->reclaim_buffers_idlelocked(dev, file_priv);
-               drm_idlelock_release(&dev->lock);
+               drm_idlelock_release(&dev->primary->master->lock);
 
        }
 
        if (drm_i_have_hw_lock(dev, file_priv)) {
                DRM_DEBUG("File %p released, freeing lock for context %d\n",
-                         filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+                         filp, _DRM_LOCKING_CONTEXT(dev->primary->master->lock.hw_lock->lock));
 
-               drm_lock_free(&dev->lock,
-                             _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+               drm_lock_free(&dev->primary->master->lock,
+                             _DRM_LOCKING_CONTEXT(dev->primary->master->lock.hw_lock->lock));
        }
 
 
@@ -479,6 +492,14 @@ int drm_release(struct inode *inode, struct file *filp)
                        temp->authenticated = 0;
        }
        list_del(&file_priv->lhead);
+
+       if (file_priv->master) {
+               if (file_priv->master == dev->primary->master)
+                      dev->primary->master = NULL;
+              drm_put_master(file_priv->master);
+              file_priv->master = NULL;
+       }
+
        mutex_unlock(&dev->struct_mutex);
 
        if (dev->driver->postclose)
@@ -492,9 +513,9 @@ int drm_release(struct inode *inode, struct file *filp)
        atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
        spin_lock(&dev->count_lock);
        if (!--dev->open_count) {
-               if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-                       DRM_ERROR("Device busy: %d %d\n",
-                                 atomic_read(&dev->ioctl_count), dev->blocked);
+               if (atomic_read(&dev->ioctl_count)) {
+                       DRM_ERROR("Device busy: %d\n",
+                                 atomic_read(&dev->ioctl_count));
                        spin_unlock(&dev->count_lock);
                        unlock_kernel();
                        return -EBUSY;
index 3df163d..c15923e 100644 (file)
@@ -53,12 +53,13 @@ int drm_getunique(struct drm_device *dev, void *data,
                  struct drm_file *file_priv)
 {
        struct drm_unique *u = data;
+       struct drm_master *master = dev->primary->master;
 
-       if (u->unique_len >= dev->unique_len) {
-               if (copy_to_user(u->unique, dev->unique, dev->unique_len))
+       if (u->unique_len >= master->unique_len) {
+               if (copy_to_user(u->unique, master->unique, master->unique_len))
                        return -EFAULT;
        }
-       u->unique_len = dev->unique_len;
+       u->unique_len = master->unique_len;
 
        return 0;
 }
@@ -81,36 +82,37 @@ int drm_setunique(struct drm_device *dev, void *data,
                  struct drm_file *file_priv)
 {
        struct drm_unique *u = data;
+       struct drm_master *master = dev->primary->master;
        int domain, bus, slot, func, ret;
 
-       if (dev->unique_len || dev->unique)
+       if (master->unique_len || master->unique)
                return -EBUSY;
 
        if (!u->unique_len || u->unique_len > 1024)
                return -EINVAL;
 
-       dev->unique_len = u->unique_len;
-       dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER);
-       if (!dev->unique)
+       master->unique_len = u->unique_len;
+       master->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER);
+       if (!master->unique)
                return -ENOMEM;
-       if (copy_from_user(dev->unique, u->unique, dev->unique_len))
+       if (copy_from_user(master->unique, u->unique, master->unique_len))
                return -EFAULT;
 
-       dev->unique[dev->unique_len] = '\0';
+       master->unique[master->unique_len] = '\0';
 
        dev->devname =
            drm_alloc(strlen(dev->driver->pci_driver.name) +
-                     strlen(dev->unique) + 2, DRM_MEM_DRIVER);
+                     strlen(master->unique) + 2, DRM_MEM_DRIVER);
        if (!dev->devname)
                return -ENOMEM;
 
        sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-               dev->unique);
+               master->unique);
 
        /* Return error if the busid submitted doesn't match the device's actual
         * busid.
         */
-       ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+       ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
        if (ret != 3)
                return -EINVAL;
        domain = bus >> 8;
@@ -127,31 +129,33 @@ int drm_setunique(struct drm_device *dev, void *data,
 
 static int drm_set_busid(struct drm_device * dev)
 {
+       struct drm_master *master = dev->primary->master;
        int len;
-       if (dev->unique != NULL)
+
+       if (master->unique != NULL)
                return -EBUSY;
 
-       dev->unique_len = 40;
-       dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
-       if (dev->unique == NULL)
+       master->unique_len = 40;
+       master->unique = drm_alloc(master->unique_len + 1, DRM_MEM_DRIVER);
+       if (master->unique == NULL)
                return -ENOMEM;
 
-       len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+       len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d",
                       drm_get_pci_domain(dev),
                       dev->pdev->bus->number,
                       PCI_SLOT(dev->pdev->devfn),
                       PCI_FUNC(dev->pdev->devfn));
-       if (len > dev->unique_len)
+       if (len > master->unique_len)
                DRM_ERROR("buffer overflow");
 
        dev->devname =
-           drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
+           drm_alloc(strlen(dev->driver->pci_driver.name) + master->unique_len +
                      2, DRM_MEM_DRIVER);
        if (dev->devname == NULL)
                return -ENOMEM;
 
        sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-               dev->unique);
+               master->unique);
 
        return 0;
 }
@@ -275,7 +279,7 @@ int drm_getstats(struct drm_device *dev, void *data,
        for (i = 0; i < dev->counters; i++) {
                if (dev->types[i] == _DRM_STAT_LOCK)
                        stats->data[i].value =
-                           (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
+                           (dev->primary->master->lock.hw_lock ? dev->primary->master->lock.hw_lock->lock : 0);
                else
                        stats->data[i].value = atomic_read(&dev->counts[i]);
                stats->data[i].type = dev->types[i];
index c75f20b..d88269a 100644 (file)
@@ -636,18 +636,18 @@ static void drm_locked_tasklet_func(unsigned long data)
        spin_lock_irqsave(&dev->tasklet_lock, irqflags);
 
        if (!dev->locked_tasklet_func ||
-           !drm_lock_take(&dev->lock,
+           !drm_lock_take(&dev->primary->master->lock,
                           DRM_KERNEL_CONTEXT)) {
                spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
                return;
        }
 
-       dev->lock.lock_time = jiffies;
+       dev->primary->master->lock.lock_time = jiffies;
        atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
 
        dev->locked_tasklet_func(dev);
 
-       drm_lock_free(&dev->lock,
+       drm_lock_free(&dev->primary->master->lock,
                      DRM_KERNEL_CONTEXT);
 
        dev->locked_tasklet_func = NULL;
index b8e4a5d..7404856 100644 (file)
@@ -52,6 +52,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        DECLARE_WAITQUEUE(entry, current);
        struct drm_lock *lock = data;
+       struct drm_master *master = dev->primary->master;
        int ret = 0;
 
        ++file_priv->lock_count;
@@ -64,26 +65,26 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 
        DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
                  lock->context, current->pid,
-                 dev->lock.hw_lock->lock, lock->flags);
+                 master->lock.hw_lock->lock, lock->flags);
 
        if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
                if (lock->context < 0)
                        return -EINVAL;
 
-       add_wait_queue(&dev->lock.lock_queue, &entry);
-       spin_lock(&dev->lock.spinlock);
-       dev->lock.user_waiters++;
-       spin_unlock(&dev->lock.spinlock);
+       add_wait_queue(&master->lock.lock_queue, &entry);
+       spin_lock(&master->lock.spinlock);
+       master->lock.user_waiters++;
+       spin_unlock(&master->lock.spinlock);
        for (;;) {
                __set_current_state(TASK_INTERRUPTIBLE);
-               if (!dev->lock.hw_lock) {
+               if (!master->lock.hw_lock) {
                        /* Device has been unregistered */
                        ret = -EINTR;
                        break;
                }
-               if (drm_lock_take(&dev->lock, lock->context)) {
-                       dev->lock.file_priv = file_priv;
-                       dev->lock.lock_time = jiffies;
+               if (drm_lock_take(&master->lock, lock->context)) {
+                       master->lock.file_priv = file_priv;
+                       master->lock.lock_time = jiffies;
                        atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
                        break;  /* Got lock */
                }
@@ -95,11 +96,11 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
                        break;
                }
        }
-       spin_lock(&dev->lock.spinlock);
-       dev->lock.user_waiters--;
-       spin_unlock(&dev->lock.spinlock);
+       spin_lock(&master->lock.spinlock);
+       master->lock.user_waiters--;
+       spin_unlock(&master->lock.spinlock);
        __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&dev->lock.lock_queue, &entry);
+       remove_wait_queue(&master->lock.lock_queue, &entry);
 
        DRM_DEBUG("%d %s\n", lock->context,
                  ret ? "interrupted" : "has lock");
@@ -111,7 +112,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
        sigaddset(&dev->sigmask, SIGTTIN);
        sigaddset(&dev->sigmask, SIGTTOU);
        dev->sigdata.context = lock->context;
-       dev->sigdata.lock = dev->lock.hw_lock;
+       dev->sigdata.lock = master->lock.hw_lock;
        block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
 
        if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY))
@@ -149,6 +150,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        struct drm_lock *lock = data;
+       struct drm_master *master = dev->primary->master;
        unsigned long irqflags;
 
        if (lock->context == DRM_KERNEL_CONTEXT) {
@@ -175,7 +177,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
        if (dev->driver->kernel_context_switch_unlock)
                dev->driver->kernel_context_switch_unlock(dev);
        else {
-               if (drm_lock_free(&dev->lock,lock->context)) {
+               if (drm_lock_free(&master->lock,lock->context)) {
                        /* FIXME: Should really bail out here. */
                }
        }
@@ -384,10 +386,10 @@ EXPORT_SYMBOL(drm_idlelock_release);
 
 int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)
 {
-
-       return (file_priv->lock_count && dev->lock.hw_lock &&
-               _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
-               dev->lock.file_priv == file_priv);
+       struct drm_master *master = dev->primary->master;
+       return (file_priv->lock_count && master->lock.hw_lock &&
+               _DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) &&
+               master->lock.file_priv == file_priv);
 }
 
 EXPORT_SYMBOL(drm_i_have_hw_lock);
index b28d823..12c08c8 100644 (file)
@@ -166,6 +166,7 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
                         int *eof, void *data)
 {
        struct drm_device *dev = (struct drm_device *) data;
+       struct drm_master *master = dev->primary->master;
        int len = 0;
 
        if (offset > DRM_PROC_LIMIT) {
@@ -176,10 +177,10 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
        *start = &buf[offset];
        *eof = 0;
 
-       if (dev->unique) {
+       if (master->unique) {
                DRM_PROC_PRINT("%s %s %s\n",
                               dev->driver->pci_driver.name,
-                              pci_name(dev->pdev), dev->unique);
+                              pci_name(dev->pdev), master->unique);
        } else {
                DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
                               pci_name(dev->pdev));
index 5a39afb..66a7b8b 100644 (file)
@@ -91,13 +91,63 @@ again:
        return new_id;
 }
 
+struct drm_master *drm_get_master(struct drm_device *dev)
+{
+       struct drm_master *master;
+
+       master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER);
+       if (!master)
+               return NULL;
+
+//     INIT_LIST_HEAD(&master->filelist);
+       spin_lock_init(&master->lock.spinlock);
+       init_waitqueue_head(&master->lock.lock_queue);
+       drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER);
+       INIT_LIST_HEAD(&master->magicfree);
+       master->dev = dev;
+
+       return master;
+}
+
+void drm_put_master(struct drm_master *master)
+{
+       struct drm_magic_entry *pt, *next;
+       struct drm_device *dev = master->dev;
+
+       if (dev->driver->master_destroy)
+               dev->driver->master_destroy(dev, master);
+
+       if (master->unique) {
+               drm_free(master->unique, strlen(master->unique) + 1, DRM_MEM_DRIVER);
+               master->unique = NULL;
+               master->unique_len = 0;
+       }
+
+       list_for_each_entry_safe(pt, next, &master->magicfree, head) {
+               list_del(&pt->head);
+               drm_ht_remove_item(&master->magiclist, &pt->hash_item);
+               drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+       }
+
+       drm_ht_remove(&master->magiclist);
+
+       if (master->lock.hw_lock) {
+               if (dev->sigdata.lock == master->lock.hw_lock)
+                       dev->sigdata.lock = NULL;
+               master->lock.hw_lock = NULL;    /* SHM removed */
+               master->lock.file_priv = NULL;
+               wake_up_interruptible(&master->lock.lock_queue);
+       }
+
+       drm_free(master, sizeof(*master), DRM_MEM_DRIVER);
+}
+
 static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
                           const struct pci_device_id *ent,
                           struct drm_driver *driver)
 {
        int retcode;
 
-       INIT_LIST_HEAD(&dev->filelist);
        INIT_LIST_HEAD(&dev->ctxlist);
        INIT_LIST_HEAD(&dev->vmalist);
        INIT_LIST_HEAD(&dev->maplist);
@@ -105,7 +155,7 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
        spin_lock_init(&dev->count_lock);
        spin_lock_init(&dev->drw_lock);
        spin_lock_init(&dev->tasklet_lock);
-       spin_lock_init(&dev->lock.spinlock);
+//     spin_lock_init(&dev->lock.spinlock);
        init_timer(&dev->timer);
        mutex_init(&dev->struct_mutex);
        mutex_init(&dev->ctxlist_mutex);
@@ -168,10 +218,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
                }
        }
 
-       if (dev->driver->load)
-               if ((retcode = dev->driver->load(dev, ent->driver_data)))
-                       goto error_out_unreg;
-
        retcode = drm_ctxbitmap_init(dev);
        if (retcode) {
                DRM_ERROR("Cannot allocate memory for context bitmap.\n");
@@ -301,12 +347,17 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
        if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_RENDER)))
                goto err_g4;
 
+       if (dev->driver->load)
+               if ((ret = dev->driver->load(dev, ent->driver_data)))
+                       goto err_g5;
+
        DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
                 driver->name, driver->major, driver->minor, driver->patchlevel,
                 driver->date, dev->primary->index);
 
        return 0;
-
+err_g5:
+       drm_put_minor(&dev->primary);
 err_g4:
        drm_put_minor(&dev->control);
 err_g3:
@@ -340,11 +391,6 @@ int drm_put_dev(struct drm_device * dev)
 {
        DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
 
-       if (dev->unique) {
-               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
-               dev->unique = NULL;
-               dev->unique_len = 0;
-       }
        if (dev->devname) {
                drm_free(dev->devname, strlen(dev->devname) + 1,
                         DRM_MEM_DRIVER);
index 629a39b..1f84164 100644 (file)
@@ -558,6 +558,8 @@ static struct drm_driver driver = {
        .fb_probe = intelfb_probe,
        .fb_remove = intelfb_remove,
        .fb_resize = intelfb_resize,
+       .master_create = i915_master_create,
+       .master_destroy = i915_master_destroy,
        .ioctls = i915_ioctls,
        .fops = {
                .owner = THIS_MODULE,
index 5b7a510..db3aee8 100644 (file)
@@ -363,6 +363,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_master_private *master_priv;
        struct intel_crtc *intel_crtc = crtc->driver_private;
        int pipe = intel_crtc->pipe;
        unsigned long Start, Offset;
@@ -384,17 +385,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
        }
        
 
-       if (!dev_priv->sarea_priv) 
+       if (!dev->primary->master)
+               return;
+
+       master_priv = dev->primary->master->driver_priv;
+       if (!master_priv->sarea_priv) 
                return;
                
        switch (pipe) {
        case 0:
-               dev_priv->sarea_priv->planeA_x = x;
-               dev_priv->sarea_priv->planeA_y = y;
+               master_priv->sarea_priv->planeA_x = x;
+               master_priv->sarea_priv->planeA_y = y;
                break;
        case 1:
-               dev_priv->sarea_priv->planeB_x = x;
-               dev_priv->sarea_priv->planeB_y = y;
+               master_priv->sarea_priv->planeB_x = x;
+               master_priv->sarea_priv->planeB_y = y;
                break;
        default:
                DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
@@ -413,6 +418,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
 static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_i915_master_private *master_priv;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = crtc->driver_private;
        int pipe = intel_crtc->pipe;
@@ -506,21 +512,24 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
                udelay(150);
                break;
        }
-       
 
-       if (!dev_priv->sarea_priv)
+       if (!dev->primary->master)
+               return; 
+
+       master_priv = dev->primary->master->driver_priv;
+       if (!master_priv->sarea_priv)
                return;
 
        enabled = crtc->enabled && mode != DPMSModeOff;
        
        switch (pipe) {
        case 0:
-               dev_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0;
-               dev_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0;
+               master_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0;
+               master_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0;
                break;
        case 1:
-               dev_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0;
-               dev_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0;
+               master_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0;
+               master_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0;
                break;
        default:
                DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
index 9af1bf3..b853df5 100644 (file)
@@ -69,7 +69,7 @@ static uint32_t via_perform_flush(struct drm_device *dev, uint32_t class)
 
 
                if (!dev_priv->have_idlelock) {
-                       drm_idlelock_take(&dev->lock);
+                       drm_idlelock_take(&dev->primary->master->lock);
                        dev_priv->have_idlelock = 1;
                }
 
@@ -95,7 +95,7 @@ static uint32_t via_perform_flush(struct drm_device *dev, uint32_t class)
                if (signaled_flush_types) {
                        pending_flush_types &= ~signaled_flush_types;
                        if (!pending_flush_types && dev_priv->have_idlelock) {
-                               drm_idlelock_release(&dev->lock);
+                               drm_idlelock_release(&dev->primary->master->lock);
                                dev_priv->have_idlelock = 0;
                        }
                        drm_fence_handler(dev, 0, dev_priv->emit_0_sequence,