Hello everyone,

I would need testers to check that this patch doesn't break working
NVAA/NVAC configurations. It fixes an issue where some NVAC would hang on boot;
if similar issues exist on NVAA, it may fix them too.
You will find the patch below in two different versions: one will apply on Ben
Skeggs' repository, the other one will apply on a regular Linux tree.

Thanks in advance,

Pierre Moreau


If you are using Ben Skeggs' repository:
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
diff --git a/drm/core/subdev/fb/nvaa.h b/drm/core/subdev/fb/nvaa.h
new file mode 120000
index 0000000..b450e8c
--- /dev/null
+++ b/drm/core/subdev/fb/nvaa.h
@@ -0,0 +1 @@
+../../../../nvkm/subdev/fb/nvaa.h
\ No newline at end of file
diff --git a/nvkm/subdev/fb/nv50.h b/nvkm/subdev/fb/nv50.h
index c5e5a88..0b20975 100644
--- a/nvkm/subdev/fb/nv50.h
+++ b/nvkm/subdev/fb/nv50.h
@@ -9,6 +9,10 @@ struct nv50_fb_priv {
        dma_addr_t r100c08;
 };
 
+#define nv50_fb_create(p,e,c,d,o)                                              
\
+       nv50_fb_ctor((p), (e), (c), (d), sizeof(**o),                          \
+                       (struct nouveau_object **)o)
+
 int  nv50_fb_ctor(struct nouveau_object *, struct nouveau_object *,
                  struct nouveau_oclass *, void *, u32,
                  struct nouveau_object **);
diff --git a/nvkm/subdev/fb/nvaa.c b/nvkm/subdev/fb/nvaa.c
index cba8e68..b70ab2f 100644
--- a/nvkm/subdev/fb/nvaa.c
+++ b/nvkm/subdev/fb/nvaa.c
@@ -22,15 +22,81 @@
  * Authors: Ben Skeggs
  */
 
-#include "nv50.h"
+#include "nvaa.h"
+
+int
+nvaa_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+            struct nouveau_oclass *oclass, void *data, u32 size,
+            struct nouveau_object **pobject)
+{
+       struct nouveau_device *device = nv_device(parent);
+       struct nvaa_fb_priv *priv;
+       int ret;
+
+       ret = nv50_fb_create(parent, engine, oclass, data, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv = (struct nvaa_fb_priv *)(*pobject);
+
+       priv->r100c18_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+       if (priv->r100c18_page) {
+               priv->r100c18 = dma_map_page(nv_device_base(device),
+                                            priv->r100c18_page, 0, PAGE_SIZE,
+                                            DMA_BIDIRECTIONAL);
+               if (dma_mapping_error(nv_device_base(device), priv->r100c18))
+                       return -EFAULT;
+       } else {
+               nv_warn(priv, "failed 0x100c18 page alloc\n");
+       }
+       return 0;
+}
+
+void
+nvaa_fb_dtor(struct nouveau_object *object)
+{
+       struct nouveau_device *device = nv_device(object);
+       struct nvaa_fb_priv *priv = (void *)object;
+
+       if (priv->r100c18_page) {
+               dma_unmap_page(nv_device_base(device), priv->r100c18, PAGE_SIZE,
+                              DMA_BIDIRECTIONAL);
+               __free_page(priv->r100c18_page);
+       }
+
+       nv50_fb_dtor(object);
+}
+
+int
+nvaa_fb_init(struct nouveau_object *object)
+{
+       struct nvaa_fb_priv *priv = (void *)object;
+       int ret;
+
+       ret = nv50_fb_init(object);
+       if (ret)
+               return ret;
+
+       /* Enable NISO poller for various clients and set their associated
+        * read address, only for MCP77/78 and MCP79/7A. (fd#25701)
+        */
+       nv_wr32(priv, 0x100c18, priv->r100c18 >> 8);
+       nv_mask(priv, 0x100c14, 0x00000000, 0x00000001);
+       nv_wr32(priv, 0x100c1c, (priv->r100c18 >> 8) + 1);
+       nv_mask(priv, 0x100c14, 0x00000000, 0x00000002);
+       nv_wr32(priv, 0x100c24, (priv->r100c18 >> 8) + 2);
+       nv_mask(priv, 0x100c14, 0x00000000, 0x00010000);
+       return 0;
+}
 
 struct nouveau_oclass *
 nvaa_fb_oclass = &(struct nv50_fb_impl) {
        .base.base.handle = NV_SUBDEV(FB, 0xaa),
        .base.base.ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv50_fb_ctor,
-               .dtor = nv50_fb_dtor,
-               .init = nv50_fb_init,
+               .ctor = nvaa_fb_ctor,
+               .dtor = nvaa_fb_dtor,
+               .init = nvaa_fb_init,
                .fini = _nouveau_fb_fini,
        },
        .base.memtype = nv50_fb_memtype_valid,
diff --git a/nvkm/subdev/fb/nvaa.h b/nvkm/subdev/fb/nvaa.h
new file mode 100644
index 0000000..84e1eca
--- /dev/null
+++ b/nvkm/subdev/fb/nvaa.h
@@ -0,0 +1,19 @@
+#ifndef __NVKM_FB_NVAA_H__
+#define __NVKM_FB_NVAA_H__
+
+#include "nv50.h"
+
+struct nvaa_fb_priv {
+       struct nv50_fb_priv base;
+       struct page *r100c18_page;
+       dma_addr_t r100c18;
+};
+
+int  nvaa_fb_ctor(struct nouveau_object *, struct nouveau_object *,
+                 struct nouveau_oclass *, void *, u32,
+                 struct nouveau_object **);
+void nvaa_fb_dtor(struct nouveau_object *);
+int  nvaa_fb_init(struct nouveau_object *);
+
+
+#endif
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/


Or if you are using the regular tree:
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.h 
b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.h
index c5e5a88..0b20975 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.h
@@ -9,6 +9,10 @@ struct nv50_fb_priv {
        dma_addr_t r100c08;
 };
 
+#define nv50_fb_create(p,e,c,d,o)                                              
\
+       nv50_fb_ctor((p), (e), (c), (d), sizeof(**o),                          \
+                       (struct nouveau_object **)o)
+
 int  nv50_fb_ctor(struct nouveau_object *, struct nouveau_object *,
                  struct nouveau_oclass *, void *, u32,
                  struct nouveau_object **);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.c 
b/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.c
index cba8e68..b70ab2f 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.c
@@ -22,15 +22,81 @@
  * Authors: Ben Skeggs
  */
 
-#include "nv50.h"
+#include "nvaa.h"
+
+int
+nvaa_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+            struct nouveau_oclass *oclass, void *data, u32 size,
+            struct nouveau_object **pobject)
+{
+       struct nouveau_device *device = nv_device(parent);
+       struct nvaa_fb_priv *priv;
+       int ret;
+
+       ret = nv50_fb_create(parent, engine, oclass, data, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv = (struct nvaa_fb_priv *)(*pobject);
+
+       priv->r100c18_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+       if (priv->r100c18_page) {
+               priv->r100c18 = dma_map_page(nv_device_base(device),
+                                            priv->r100c18_page, 0, PAGE_SIZE,
+                                            DMA_BIDIRECTIONAL);
+               if (dma_mapping_error(nv_device_base(device), priv->r100c18))
+                       return -EFAULT;
+       } else {
+               nv_warn(priv, "failed 0x100c18 page alloc\n");
+       }
+       return 0;
+}
+
+void
+nvaa_fb_dtor(struct nouveau_object *object)
+{
+       struct nouveau_device *device = nv_device(object);
+       struct nvaa_fb_priv *priv = (void *)object;
+
+       if (priv->r100c18_page) {
+               dma_unmap_page(nv_device_base(device), priv->r100c18, PAGE_SIZE,
+                              DMA_BIDIRECTIONAL);
+               __free_page(priv->r100c18_page);
+       }
+
+       nv50_fb_dtor(object);
+}
+
+int
+nvaa_fb_init(struct nouveau_object *object)
+{
+       struct nvaa_fb_priv *priv = (void *)object;
+       int ret;
+
+       ret = nv50_fb_init(object);
+       if (ret)
+               return ret;
+
+       /* Enable NISO poller for various clients and set their associated
+        * read address, only for MCP77/78 and MCP79/7A. (fd#25701)
+        */
+       nv_wr32(priv, 0x100c18, priv->r100c18 >> 8);
+       nv_mask(priv, 0x100c14, 0x00000000, 0x00000001);
+       nv_wr32(priv, 0x100c1c, (priv->r100c18 >> 8) + 1);
+       nv_mask(priv, 0x100c14, 0x00000000, 0x00000002);
+       nv_wr32(priv, 0x100c24, (priv->r100c18 >> 8) + 2);
+       nv_mask(priv, 0x100c14, 0x00000000, 0x00010000);
+       return 0;
+}
 
 struct nouveau_oclass *
 nvaa_fb_oclass = &(struct nv50_fb_impl) {
        .base.base.handle = NV_SUBDEV(FB, 0xaa),
        .base.base.ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv50_fb_ctor,
-               .dtor = nv50_fb_dtor,
-               .init = nv50_fb_init,
+               .ctor = nvaa_fb_ctor,
+               .dtor = nvaa_fb_dtor,
+               .init = nvaa_fb_init,
                .fini = _nouveau_fb_fini,
        },
        .base.memtype = nv50_fb_memtype_valid,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.h 
b/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.h
new file mode 100644
index 0000000..84e1eca
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.h
@@ -0,0 +1,19 @@
+#ifndef __NVKM_FB_NVAA_H__
+#define __NVKM_FB_NVAA_H__
+
+#include "nv50.h"
+
+struct nvaa_fb_priv {
+       struct nv50_fb_priv base;
+       struct page *r100c18_page;
+       dma_addr_t r100c18;
+};
+
+int  nvaa_fb_ctor(struct nouveau_object *, struct nouveau_object *,
+                 struct nouveau_oclass *, void *, u32,
+                 struct nouveau_object **);
+void nvaa_fb_dtor(struct nouveau_object *);
+int  nvaa_fb_init(struct nouveau_object *);
+
+
+#endif
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to