On Fri, Aug 2, 2013 at 12:41 AM, Peter Wu <lekensteyn@xxxxxxxxx> wrote: > Observe that nouveau_optimus_dsm and nouveau_dsm are equal except for > the parameters handling (UUID, revision ID and function arguments). The > function arguments are passed as Buffer in the "optimus dsm" and Integer > in "nvidia dsm". As buffers are implicitly converted to integers, merge > both functions. > > The ACPI spec defines the fourth parameter (Arg3 a.k.a. "function > arguments") as Package, but many BIOSes expect a Buffer instead. For > instance, for the "nvidia DSM", the Lenovo T410s uses CreateByteField on > Arg3 which does not work with a package. The Clevo B7130 does something > similar for the "Optimus DSM". Unfortunately, this means that the > following ACPI warning (introduced with 29a241c) cannot be fixed (when > toggling power or muxing): By cannot be fixed, why is it there then? maybe ask the ACPI folks to drop this error, since as far as I can see all optimus dsm want a buffer here. Dave. > > ACPI Warning: \_SB_.PCI0.GFX0._DSM: Argument #4 type mismatch - Found [Buffer], ACPI requires [Package] (20130517/nsarguments-95) > ACPI Warning: \_SB_.PCI0.GFX0._DSM: Argument #4 type mismatch - Found [Buffer], ACPI requires [Package] (20130517/nsarguments-95) > ACPI Warning: \_SB_.PCI0.P0P2.PEGP._DSM: Argument #4 type mismatch - Found [Buffer], ACPI requires [Package] (20130517/nsarguments-95) > ACPI Warning: \_SB_.PCI0.P0P2.PEGP._DSM: Argument #4 type mismatch - Found [Buffer], ACPI requires [Package] (20130517/nsarguments-95) > > Signed-off-by: Peter Wu <lekensteyn@xxxxxxxxx> > --- > drivers/gpu/drm/nouveau/nouveau_acpi.c | 67 ++++++++++------------------------ > 1 file changed, 20 insertions(+), 47 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c > index d97f200..a75684f 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c > +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c > @@ -46,6 +46,9 @@ bool nouveau_is_v1_dsm(void) { > #define NOUVEAU_DSM_HAS_MUX 0x1 > #define NOUVEAU_DSM_HAS_OPT 0x2 > > +#define NOUVEAU_DSM_REVID_NVIDIA 0x102 > +#define NOUVEAU_DSM_REVID_OPTIMUS 0x100 > + > static const char nouveau_dsm_muid[] = { > 0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D, > 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, > @@ -56,7 +59,8 @@ static const char nouveau_op_dsm_muid[] = { > 0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0, > }; > > -static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result) > +static int nouveau_call_dsm(acpi_handle handle, const char *uuid, int revid, > + int func, int arg, uint32_t *result) > { > struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; > struct acpi_object_list input; > @@ -68,12 +72,15 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * > input.count = 4; > input.pointer = params; > params[0].type = ACPI_TYPE_BUFFER; > - params[0].buffer.length = sizeof(nouveau_op_dsm_muid); > - params[0].buffer.pointer = (char *)nouveau_op_dsm_muid; > + params[0].buffer.length = 16; > + params[0].buffer.pointer = (char *)uuid; > params[1].type = ACPI_TYPE_INTEGER; > - params[1].integer.value = 0x00000100; > + params[1].integer.value = revid; > params[2].type = ACPI_TYPE_INTEGER; > params[2].integer.value = func; > + /* Although the ACPI spec defines Arg3 as a Package, in practise > + * implementations expect a Buffer (CreateWordField and Index functions > + * are applied to it). */ > params[3].type = ACPI_TYPE_BUFFER; > params[3].buffer.length = 4; > /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ > @@ -108,50 +115,16 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * > return 0; > } > > -static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) > -{ > - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; > - struct acpi_object_list input; > - union acpi_object params[4]; > - union acpi_object *obj; > - int err; > - > - input.count = 4; > - input.pointer = params; > - params[0].type = ACPI_TYPE_BUFFER; > - params[0].buffer.length = sizeof(nouveau_dsm_muid); > - params[0].buffer.pointer = (char *)nouveau_dsm_muid; > - params[1].type = ACPI_TYPE_INTEGER; > - params[1].integer.value = 0x00000102; > - params[2].type = ACPI_TYPE_INTEGER; > - params[2].integer.value = func; > - params[3].type = ACPI_TYPE_INTEGER; > - params[3].integer.value = arg; > - > - err = acpi_evaluate_object(handle, "_DSM", &input, &output); > - if (err) { > - printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); > - return err; > - } > - > - obj = (union acpi_object *)output.pointer; > - > - if (obj->type == ACPI_TYPE_INTEGER) > - if (obj->integer.value == 0x80000002) > - return -ENODEV; > - > - if (obj->type == ACPI_TYPE_BUFFER) { > - if (obj->buffer.length == 4 && result) { > - *result = 0; > - *result |= obj->buffer.pointer[0]; > - *result |= (obj->buffer.pointer[1] << 8); > - *result |= (obj->buffer.pointer[2] << 16); > - *result |= (obj->buffer.pointer[3] << 24); > - } > - } > +static int nouveau_optimus_dsm(acpi_handle handle, int func, > + int arg, uint32_t *result) { > + return nouveau_call_dsm(handle, nouveau_op_dsm_muid, > + NOUVEAU_DSM_REVID_OPTIMUS, func, arg, result); > +} > > - kfree(output.pointer); > - return 0; > +static int nouveau_dsm(acpi_handle handle, int func, > + int arg, uint32_t *result) { > + return nouveau_call_dsm(handle, nouveau_dsm_muid, > + NOUVEAU_DSM_REVID_NVIDIA, func, arg, result); > } > > /* Returns 1 if a DSM function is usable and 0 otherwise */ > -- > 1.8.3.4 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel