OSDN Git Service

drm/vmwgfx: Initial DX support
[uclinux-h8/linux.git] / drivers / gpu / drm / vmwgfx / vmwgfx_mob.c
index 5b0287e..a8203a9 100644 (file)
@@ -67,9 +67,23 @@ struct vmw_mob {
  * @size:           Size of the table (page-aligned).
  * @page_table:     Pointer to a struct vmw_mob holding the page table.
  */
-struct vmw_otable {
-       unsigned long size;
-       struct vmw_mob *page_table;
+static const struct vmw_otable pre_dx_tables[] = {
+       {VMWGFX_NUM_MOB * SVGA3D_OTABLE_MOB_ENTRY_SIZE, NULL, true},
+       {VMWGFX_NUM_GB_SURFACE * SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, NULL, true},
+       {VMWGFX_NUM_GB_CONTEXT * SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE, NULL, true},
+       {VMWGFX_NUM_GB_SHADER * SVGA3D_OTABLE_SHADER_ENTRY_SIZE, NULL, true},
+       {VMWGFX_NUM_GB_SCREEN_TARGET * SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE,
+        NULL, VMWGFX_ENABLE_SCREEN_TARGET_OTABLE}
+};
+
+static const struct vmw_otable dx_tables[] = {
+       {VMWGFX_NUM_MOB * SVGA3D_OTABLE_MOB_ENTRY_SIZE, NULL, true},
+       {VMWGFX_NUM_GB_SURFACE * SVGA3D_OTABLE_SURFACE_ENTRY_SIZE, NULL, true},
+       {VMWGFX_NUM_GB_CONTEXT * SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE, NULL, true},
+       {VMWGFX_NUM_GB_SHADER * SVGA3D_OTABLE_SHADER_ENTRY_SIZE, NULL, true},
+       {VMWGFX_NUM_GB_SCREEN_TARGET * SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE,
+        NULL, VMWGFX_ENABLE_SCREEN_TARGET_OTABLE},
+       {VMWGFX_NUM_DXCONTEXT * sizeof(SVGAOTableDXContextEntry), NULL, true},
 };
 
 static int vmw_mob_pt_populate(struct vmw_private *dev_priv,
@@ -92,6 +106,7 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob,
  */
 static int vmw_setup_otable_base(struct vmw_private *dev_priv,
                                 SVGAOTableType type,
+                                struct ttm_buffer_object *otable_bo,
                                 unsigned long offset,
                                 struct vmw_otable *otable)
 {
@@ -106,7 +121,7 @@ static int vmw_setup_otable_base(struct vmw_private *dev_priv,
 
        BUG_ON(otable->page_table != NULL);
 
-       vsgt = vmw_bo_sg_table(dev_priv->otable_bo);
+       vsgt = vmw_bo_sg_table(otable_bo);
        vmw_piter_start(&iter, vsgt, offset >> PAGE_SHIFT);
        WARN_ON(!vmw_piter_next(&iter));
 
@@ -193,7 +208,7 @@ static void vmw_takedown_otable_base(struct vmw_private *dev_priv,
                          "takedown.\n");
                return;
        }
+
        memset(cmd, 0, sizeof(*cmd));
        cmd->header.id = SVGA_3D_CMD_SET_OTABLE_BASE;
        cmd->header.size = sizeof(cmd->body);
@@ -218,47 +233,21 @@ static void vmw_takedown_otable_base(struct vmw_private *dev_priv,
        otable->page_table = NULL;
 }
 
-/*
- * vmw_otables_setup - Set up guest backed memory object tables
- *
- * @dev_priv:       Pointer to a device private structure
- *
- * Takes care of the device guest backed surface
- * initialization, by setting up the guest backed memory object tables.
- * Returns 0 on success and various error codes on failure. A succesful return
- * means the object tables can be taken down using the vmw_otables_takedown
- * function.
- */
-int vmw_otables_setup(struct vmw_private *dev_priv)
+
+static int vmw_otable_batch_setup(struct vmw_private *dev_priv,
+                                 struct vmw_otable_batch *batch)
 {
        unsigned long offset;
        unsigned long bo_size;
-       struct vmw_otable *otables;
+       struct vmw_otable *otables = batch->otables;
        SVGAOTableType i;
        int ret;
 
-       otables = kzalloc(SVGA_OTABLE_DX9_MAX * sizeof(*otables),
-                         GFP_KERNEL);
-       if (unlikely(otables == NULL)) {
-               DRM_ERROR("Failed to allocate space for otable "
-                         "metadata.\n");
-               return -ENOMEM;
-       }
-
-       otables[SVGA_OTABLE_MOB].size =
-               VMWGFX_NUM_MOB * SVGA3D_OTABLE_MOB_ENTRY_SIZE;
-       otables[SVGA_OTABLE_SURFACE].size =
-               VMWGFX_NUM_GB_SURFACE * SVGA3D_OTABLE_SURFACE_ENTRY_SIZE;
-       otables[SVGA_OTABLE_CONTEXT].size =
-               VMWGFX_NUM_GB_CONTEXT * SVGA3D_OTABLE_CONTEXT_ENTRY_SIZE;
-       otables[SVGA_OTABLE_SHADER].size =
-               VMWGFX_NUM_GB_SHADER * SVGA3D_OTABLE_SHADER_ENTRY_SIZE;
-       otables[SVGA_OTABLE_SCREENTARGET].size =
-               VMWGFX_NUM_GB_SCREEN_TARGET *
-               SVGA3D_OTABLE_SCREEN_TARGET_ENTRY_SIZE;
-
        bo_size = 0;
-       for (i = 0; i < SVGA_OTABLE_DX9_MAX; ++i) {
+       for (i = 0; i < batch->num_otables; ++i) {
+               if (!otables[i].enabled)
+                       continue;
+
                otables[i].size =
                        (otables[i].size + PAGE_SIZE - 1) & PAGE_MASK;
                bo_size += otables[i].size;
@@ -268,63 +257,105 @@ int vmw_otables_setup(struct vmw_private *dev_priv)
                            ttm_bo_type_device,
                            &vmw_sys_ne_placement,
                            0, false, NULL,
-                           &dev_priv->otable_bo);
+                           &batch->otable_bo);
 
        if (unlikely(ret != 0))
                goto out_no_bo;
 
-       ret = ttm_bo_reserve(dev_priv->otable_bo, false, true, false, NULL);
+       ret = ttm_bo_reserve(batch->otable_bo, false, true, false, NULL);
        BUG_ON(ret != 0);
-       ret = vmw_bo_driver.ttm_tt_populate(dev_priv->otable_bo->ttm);
+       ret = vmw_bo_driver.ttm_tt_populate(batch->otable_bo->ttm);
        if (unlikely(ret != 0))
                goto out_unreserve;
-       ret = vmw_bo_map_dma(dev_priv->otable_bo);
+       ret = vmw_bo_map_dma(batch->otable_bo);
        if (unlikely(ret != 0))
                goto out_unreserve;
 
-       ttm_bo_unreserve(dev_priv->otable_bo);
+       ttm_bo_unreserve(batch->otable_bo);
 
        offset = 0;
-       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i) {
-               ret = vmw_setup_otable_base(dev_priv, i, offset,
+       for (i = 0; i < batch->num_otables; ++i) {
+               if (!batch->otables[i].enabled)
+                       continue;
+
+               ret = vmw_setup_otable_base(dev_priv, i, batch->otable_bo,
+                                           offset,
                                            &otables[i]);
                if (unlikely(ret != 0))
                        goto out_no_setup;
                offset += otables[i].size;
        }
 
-       dev_priv->otables = otables;
        return 0;
 
 out_unreserve:
-       ttm_bo_unreserve(dev_priv->otable_bo);
+       ttm_bo_unreserve(batch->otable_bo);
 out_no_setup:
-       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i)
-               vmw_takedown_otable_base(dev_priv, i, &otables[i]);
+       for (i = 0; i < batch->num_otables; ++i) {
+               if (batch->otables[i].enabled)
+                       vmw_takedown_otable_base(dev_priv, i,
+                                                &batch->otables[i]);
+       }
 
-       ttm_bo_unref(&dev_priv->otable_bo);
+       ttm_bo_unref(&batch->otable_bo);
 out_no_bo:
-       kfree(otables);
        return ret;
 }
 
-
 /*
- * vmw_otables_takedown - Take down guest backed memory object tables
+ * vmw_otables_setup - Set up guest backed memory object tables
  *
  * @dev_priv:       Pointer to a device private structure
  *
- * Take down the Guest Memory Object tables.
+ * Takes care of the device guest backed surface
+ * initialization, by setting up the guest backed memory object tables.
+ * Returns 0 on success and various error codes on failure. A successful return
+ * means the object tables can be taken down using the vmw_otables_takedown
+ * function.
  */
-void vmw_otables_takedown(struct vmw_private *dev_priv)
+int vmw_otables_setup(struct vmw_private *dev_priv)
+{
+       struct vmw_otable **otables = &dev_priv->otable_batch.otables;
+       int ret;
+
+       if (dev_priv->has_dx) {
+               *otables = kmalloc(sizeof(dx_tables), GFP_KERNEL);
+               if (*otables == NULL)
+                       return -ENOMEM;
+
+               memcpy(*otables, dx_tables, sizeof(dx_tables));
+               dev_priv->otable_batch.num_otables = ARRAY_SIZE(dx_tables);
+       } else {
+               *otables = kmalloc(sizeof(pre_dx_tables), GFP_KERNEL);
+               if (*otables == NULL)
+                       return -ENOMEM;
+
+               memcpy(*otables, pre_dx_tables, sizeof(pre_dx_tables));
+               dev_priv->otable_batch.num_otables = ARRAY_SIZE(pre_dx_tables);
+       }
+
+       ret = vmw_otable_batch_setup(dev_priv, &dev_priv->otable_batch);
+       if (unlikely(ret != 0))
+               goto out_setup;
+
+       return 0;
+
+out_setup:
+       kfree(*otables);
+       return ret;
+}
+
+static void vmw_otable_batch_takedown(struct vmw_private *dev_priv,
+                              struct vmw_otable_batch *batch)
 {
        SVGAOTableType i;
-       struct ttm_buffer_object *bo = dev_priv->otable_bo;
+       struct ttm_buffer_object *bo = batch->otable_bo;
        int ret;
 
-       for (i = 0; i < SVGA_OTABLE_DX9_MAX - VMW_OTABLE_SETUP_SUB; ++i)
-               vmw_takedown_otable_base(dev_priv, i,
-                                        &dev_priv->otables[i]);
+       for (i = 0; i < batch->num_otables; ++i)
+               if (batch->otables[i].enabled)
+                       vmw_takedown_otable_base(dev_priv, i,
+                                                &batch->otables[i]);
 
        ret = ttm_bo_reserve(bo, false, true, false, NULL);
        BUG_ON(ret != 0);
@@ -332,11 +363,21 @@ void vmw_otables_takedown(struct vmw_private *dev_priv)
        vmw_fence_single_bo(bo, NULL);
        ttm_bo_unreserve(bo);
 
-       ttm_bo_unref(&dev_priv->otable_bo);
-       kfree(dev_priv->otables);
-       dev_priv->otables = NULL;
+       ttm_bo_unref(&batch->otable_bo);
 }
 
+/*
+ * vmw_otables_takedown - Take down guest backed memory object tables
+ *
+ * @dev_priv:       Pointer to a device private structure
+ *
+ * Take down the Guest Memory Object tables.
+ */
+void vmw_otables_takedown(struct vmw_private *dev_priv)
+{
+       vmw_otable_batch_takedown(dev_priv, &dev_priv->otable_batch);
+       kfree(dev_priv->otable_batch.otables);
+}
 
 /*
  * vmw_mob_calculate_pt_pages - Calculate the number of page table pages
@@ -410,7 +451,7 @@ static int vmw_mob_pt_populate(struct vmw_private *dev_priv,
                goto out_unreserve;
 
        ttm_bo_unreserve(mob->pt_bo);
-       
+
        return 0;
 
 out_unreserve: