[Nouveau] [PATCH] bios: fix OF loading

Ilia Mirkin imirkin at alum.mit.edu
Fri Oct 2 00:26:28 PDT 2015


On Fri, Oct 2, 2015 at 3:18 AM, Hans de Goede <hdegoede at redhat.com> wrote:
> Hi,
>
> On 02-10-15 05:41, Ilia Mirkin wrote:
>
> <nothing>
>
> As someone who has recently started following nouveau I must say that
> it would greatly help me (and likely others) if patches likes this would
> come with a somewhat more descriptive commit message.

Duly noted. I normally try to say a bit, but have gotten lazy of late.
Ben's pretty terse too :) How about something like

"""
Currently OF bios load fails for a few reasons:
 - checksum failure
 - bios size too small
 - no PCIR header
 - bios length not a multiple of 4

In this change, we resolve all of the above by ignoring any checksum
failures, and faking the PCIR data when loading from OF.
"""

>
> Otherwise keep up the good work!
>
> Regards,
>
> Hans
>
>
> p.s.
>
> I've seen your message on the mesa fire demo on nv34, firing that up now.
>
>
>> 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
>>
>


More information about the Nouveau mailing list