[PATCH] drm/nouveau/agp: add a quirk list to limit agp modes

Ilia Mirkin imirkin at alum.mit.edu
Mon Oct 28 04:12:47 CET 2013


On Sun, Oct 27, 2013 at 11:01 PM, Robert Hancock <hancockrwd at gmail.com> wrote:
> On 10/27/2013 09:54 AM, Ilia Mirkin wrote:
>>
>> Certain combinations of hardware can't actually support the maximum
>> detected speed. Add a quirk list that lists pairs of hostbridge/chip pci
>> ids and the mode that they should work with.
>>
>> See https://bugs.freedesktop.org/show_bug.cgi?id=20341
>
>
> It seems like this quirk is likely too specific. This almost certainly
> affects more than 5600 Ultra cards and probably not just NV cards either. It
> probably affects more VIA chipsets than this too.

Extremely likely. But I don't have any of the hardware to test. Note
that this quirk list is based on the radeon one (except the radeon one
also has subdevice id's).

>
> Given the amount of breakage that seems to exist with VIA AGP chipsets, I
> would think that being much more aggressive and forcing AGP mode to 2X
> maximum at the AGP driver level for all VIA chipsets doesn't seem like it
> would be a bad idea.

That's what I thought. However it has been suggested that the
incompatibilities are highly card/chipset combination-dependent.
Furthermore, in some instances, it _only_ works at the higher speeds,
so blanket "max" restrictions wouldn't work.

See http://lists.freedesktop.org/archives/dri-devel/2013-October/047117.html.
I seem to recall more to the discussion, perhaps it happened over IRC
in #dri-devel.

>
>
>>
>> Reported-by: Jason Detring <detringj at gmail.com>
>> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
>> ---
>>
>> I didn't go as far as subdevice matching... IMO that's overkill for now.
>>
>>   drivers/gpu/drm/nouveau/nouveau_agp.c | 44
>> +++++++++++++++++++++++++++++++----
>>   1 file changed, 39 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c
>> b/drivers/gpu/drm/nouveau/nouveau_agp.c
>> index 6e7a55f..2953c4e 100644
>> --- a/drivers/gpu/drm/nouveau/nouveau_agp.c
>> +++ b/drivers/gpu/drm/nouveau/nouveau_agp.c
>> @@ -11,10 +11,28 @@ MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable
>> AGP)");
>>   static int nouveau_agpmode = -1;
>>   module_param_named(agpmode, nouveau_agpmode, int, 0400);
>>
>> +struct nouveau_agpmode_quirk {
>> +       u16 hostbridge_vendor;
>> +       u16 hostbridge_device;
>> +       u16 chip_vendor;
>> +       u16 chip_device;
>> +       int mode;
>> +};
>> +
>> +static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = {
>> +       /* VIA Apollo PRO133x / GeForce FX 5600 Ultra, max agpmode 2, fdo
>> #20341 */
>> +       { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 },
>> +
>> +       {},
>> +};
>> +
>>   static unsigned long
>> -get_agp_mode(struct nouveau_drm *drm, unsigned long mode)
>> +get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info)
>>   {
>>         struct nouveau_device *device = nv_device(drm->device);
>> +       struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list;
>> +       int agpmode = nouveau_agpmode;
>> +       unsigned long mode = info->mode;
>>
>>         /*
>>          * FW seems to be broken on nv18, it makes the card lock up
>> @@ -24,11 +42,27 @@ get_agp_mode(struct nouveau_drm *drm, unsigned long
>> mode)
>>                 mode &= ~PCI_AGP_COMMAND_FW;
>>
>>         /*
>> +        * Go through the quirks list and adjust the agpmode accordingly.
>> +        */
>> +       while (agpmode == -1 && quirk->hostbridge_vendor) {
>> +               if (info->id_vendor == quirk->hostbridge_vendor &&
>> +                   info->id_device == quirk->hostbridge_device &&
>> +                   device->pdev->vendor == quirk->chip_vendor &&
>> +                   device->pdev->device == quirk->chip_device) {
>> +                       agpmode = quirk->mode;
>> +                       nv_info(device, "Forcing agp mode to %dX. Use
>> agpmode to override.\n",
>> +                               agpmode);
>> +                       break;
>> +               }
>> +               ++quirk;
>> +       }
>> +
>> +       /*
>>          * AGP mode set in the command line.
>>          */
>> -       if (nouveau_agpmode > 0) {
>> +       if (agpmode > 0) {
>>                 bool agpv3 = mode & 0x8;
>> -               int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode;
>> +               int rate = agpv3 ? agpmode / 4 : agpmode;
>>
>>                 mode = (mode & ~0x7) | (rate & 0x7);
>>         }
>> @@ -90,7 +124,7 @@ nouveau_agp_reset(struct nouveau_drm *drm)
>>                 if (ret)
>>                         return;
>>
>> -               mode.mode  = get_agp_mode(drm, info.mode);
>> +               mode.mode  = get_agp_mode(drm, &info);
>>                 mode.mode &= ~PCI_AGP_COMMAND_FW;
>>
>>                 ret = drm_agp_enable(dev, mode);
>> @@ -139,7 +173,7 @@ nouveau_agp_init(struct nouveau_drm *drm)
>>         }
>>
>>         /* see agp.h for the AGPSTAT_* modes available */
>> -       mode.mode = get_agp_mode(drm, info.mode);
>> +       mode.mode = get_agp_mode(drm, &info);
>>
>>         ret = drm_agp_enable(dev, mode);
>>         if (ret) {
>>
>


More information about the dri-devel mailing list