[Nouveau] [PATCH] bios: fix OF loading
Ilia Mirkin
imirkin at alum.mit.edu
Thu Oct 1 20:41:21 PDT 2015
Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
---
Tested on a PowerMac7,3 with a NV34 AGP adapter.
drm/nouveau/nvkm/subdev/bios/priv.h | 3 +++
drm/nouveau/nvkm/subdev/bios/shadow.c | 27 ++++++++++++++++++---------
drm/nouveau/nvkm/subdev/bios/shadowof.c | 18 ++++++++++++++++--
3 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/drm/nouveau/nvkm/subdev/bios/priv.h b/drm/nouveau/nvkm/subdev/bios/priv.h
index e0ec2a6..212800e 100644
--- a/drm/nouveau/nvkm/subdev/bios/priv.h
+++ b/drm/nouveau/nvkm/subdev/bios/priv.h
@@ -8,7 +8,10 @@ struct nvbios_source {
void *(*init)(struct nvkm_bios *, const char *);
void (*fini)(void *);
u32 (*read)(void *, u32 offset, u32 length, struct nvkm_bios *);
+ u32 (*size)(void *);
bool rw;
+ bool ignore_checksum;
+ bool no_pcir;
};
int nvbios_extend(struct nvkm_bios *, u32 length);
diff --git a/drm/nouveau/nvkm/subdev/bios/shadow.c b/drm/nouveau/nvkm/subdev/bios/shadow.c
index 792f017..b2557e8 100644
--- a/drm/nouveau/nvkm/subdev/bios/shadow.c
+++ b/drm/nouveau/nvkm/subdev/bios/shadow.c
@@ -45,7 +45,7 @@ shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto)
u32 read = mthd->func->read(data, start, limit - start, bios);
bios->size = start + read;
}
- return bios->size >= limit;
+ return bios->size >= upto;
}
static int
@@ -55,14 +55,22 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
struct nvbios_image image;
int score = 1;
- if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
- nvkm_debug(subdev, "%08x: header fetch failed\n", offset);
- return 0;
- }
+ if (mthd->func->no_pcir) {
+ image.base = 0;
+ image.type = 0;
+ image.size = mthd->func->size(mthd->data);
+ image.last = 1;
+ } else {
+ if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
+ nvkm_debug(subdev, "%08x: header fetch failed\n",
+ offset);
+ return 0;
+ }
- if (!nvbios_image(bios, idx, &image)) {
- nvkm_debug(subdev, "image %d invalid\n", idx);
- return 0;
+ if (!nvbios_image(bios, idx, &image)) {
+ nvkm_debug(subdev, "image %d invalid\n", idx);
+ return 0;
+ }
}
nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
image.base, image.type, image.size);
@@ -74,7 +82,8 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
switch (image.type) {
case 0x00:
- if (nvbios_checksum(&bios->data[image.base], image.size)) {
+ if (!mthd->func->ignore_checksum &&
+ nvbios_checksum(&bios->data[image.base], image.size)) {
nvkm_debug(subdev, "%08x: checksum failed\n",
image.base);
if (mthd->func->rw)
diff --git a/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drm/nouveau/nvkm/subdev/bios/shadowof.c
index 29a37f0..4a20584 100644
--- a/drm/nouveau/nvkm/subdev/bios/shadowof.c
+++ b/drm/nouveau/nvkm/subdev/bios/shadowof.c
@@ -22,6 +22,7 @@
*/
#include "priv.h"
+#include <core/pci.h>
#if defined(__powerpc__)
struct priv {
@@ -33,17 +34,27 @@ static u32
of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{
struct priv *priv = data;
- if (offset + length <= priv->size) {
+ if (offset < priv->size) {
+ length = min_t(u32, length, priv->size - offset);
memcpy_fromio(bios->data + offset, priv->data + offset, length);
return length;
}
return 0;
}
+static u32
+of_size(void *data)
+{
+ struct priv *priv = data;
+
+ return priv->size;
+}
+
static void *
of_init(struct nvkm_bios *bios, const char *name)
{
- struct pci_dev *pdev = bios->subdev.device->pdev;
+ struct nvkm_device *device = bios->subdev.device;
+ struct pci_dev *pdev = device->func->pci(device)->pdev;
struct device_node *dn;
struct priv *priv;
if (!(dn = pci_device_to_OF_node(pdev)))
@@ -62,7 +73,10 @@ nvbios_of = {
.init = of_init,
.fini = (void(*)(void *))kfree,
.read = of_read,
+ .size = of_size,
.rw = false,
+ .ignore_checksum = true,
+ .no_pcir = true,
};
#else
const struct nvbios_source
--
2.4.9
More information about the Nouveau
mailing list