On Thu, Mar 25, 2021 at 08:00:57AM +0100, Theo Buehler wrote:
> On Wed, Mar 24, 2021 at 05:11:52PM +0100, Mark Kettenis wrote:
> > > Date: Wed, 24 Mar 2021 09:47:56 +0100
> > > From: Theo Buehler <t...@theobuehler.org>
> > > 
> > > On Tue, Mar 23, 2021 at 08:29:29PM +0100, Mark Kettenis wrote:
> > > > > Date: Tue, 23 Mar 2021 17:39:45 +0100
> > > > > From: Theo Buehler <t...@theobuehler.org>
> > > > > 
> > > > > On Tue, Mar 23, 2021 at 05:28:37PM +0100, Mark Kettenis wrote:
> > > > > > > Date: Tue, 23 Mar 2021 16:56:33 +0100
> > > > > > > From: Theo Buehler <t...@theobuehler.org>
> > > > > > > 
> > > > > > > On Tue, Mar 23, 2021 at 04:13:53PM +0100, Mark Kettenis wrote:
> > > > > > > > > Date: Tue, 23 Mar 2021 14:14:40 +0100
> > > > > > > > > From: Theo Buehler <t...@theobuehler.org>
> > > > > > > > 
> > > > > > > > It would help if you could try and boot a kernel that adds some 
> > > > > > > > debug
> > > > > > > > prints instead of calling aml_die().  Probably need to know the 
> > > > > > > > values
> > > > > > > > of alen, bpos, blen, mode and flag for starters.
> > > > > > > 
> > > > > > > Thanks.
> > > > > > > 
> > > > > > > alen 0x00, bpos 0x278, blen 0x10, mode 0x00, flag 0x605
> > > > > > > 
> > > > > > > So: AML_FIELD_ACCESS(flag) == AML_FIELD_BUFFER_ACC, bpos & 0x03 
> > > > > > > == 0
> > > > > > > and the aml_die("Invalid GenericSerialBus access") is hit because 
> > > > > > > blen
> > > > > > > is twice as long as it should be according to the conditional 
> > > > > > > preceding
> > > > > > > it:
> > > > > > > 
> > > > > > >   if (AML_FIELD_ACCESS(flag) != AML_FIELD_BUFFERACC ||
> > > > > > >       bpos & 0x3 || blen != 8)
> > > > > > 
> > > > > > Right, we need to figure out what this actually means.  The ACPI
> > > > > > standard isn't exactly clear on this...
> > > > > > 
> > > > > > > If I skip the aml_die("Invalid GenericSerialBus access"), it hits 
> > > > > > > the
> > > > > > > next aml_die("Could not find GenericSerialBus controller"); 
> > > > > > > because
> > > > > > > node->i2c == NULL.
> > > > > > 
> > > > > > If I'm reading the AML and FreeBSD dmesg correctly this is an i2c
> > > > > > controller that attaches to PCI.  I suspect that it is dwiic(4).  D
> > > > > > you see dwiic(4) attach?
> > > > > 
> > > > > Two of them:
> > > > > 
> > > > > dwiic0 at pci0 dev 21 function 0 "Intel 400 Series I2C" rev 0x00: 
> > > > > apic 2 int 22
> > > > > iic0 at dwiic0
> > > > > dwiic1 at pci0 dev 21 function 1 "Intel 400 Series I2C" rev 0x00: 
> > > > > apic 2 int 23
> > > > > iic1 at dwiic1
> > > > > 
> > > > > > If so, the problem is that we dont't call acpi_register_gsb() for
> > > > > > dwiic(4) instances that attach to PCI.  I'll see if I can come up 
> > > > > > with
> > > > > > a diff for that.
> > > > > 
> > > > > Thanks a lot!
> > > > 
> > > > Can you try the diff below?
> > > 
> > > I tried to install a release built with this. With miniroot69.img I
> > > still hit the reboot loop described in my first mail:
> > > 
> > > ...
> > > wsdisplay0 at efifb0 mux 1: console (std, vt100 emulation), using wskbd0
> > > aml_rwgen: unregistered RegionSpace 0x9
> > > Could not convert 0 to 3
> > > 
> > > panic: aml_die aml_convert: 2095
> > > syncing disks...uvmfault(0xffffffff818e5d78, 0xbc8, 0, 1) -> e
> > > fatal page fault in supervisor mode
> > > trap type 6 code 0 rip ffffffff810e216b cs 8 rflags 10286 cr2 bc8 cpl 0 
> > > rsp ffff80001f76f120
> > > gsbase 0xffffffff818d0ff0 kgsbase 0x0
> > > panic trap type 6, code=0, pc=ffffffff810e216b
> > > 
> > > dump to dev 17,1 not possible
> > > rebooting...
> > > 
> > > I tried to move acpi_register_gsb() and the call to it in dwiic_pci.c
> > > out of SMALL_KERNEL, but that didn't help.
> > > 
> > > What info would be useful to debug this further?
> > 
> > SMALL_KERNEL deliberately doesn't GenericSerialBus support as this
> > requires the presence of a whole set of I2C drivers that we have no
> > space for on the install media.
> > 
> > This machine violates the ACPI spec, since the AML should check that
> > the i2c bus is actually available before using it.  But pointing this
> > out to Dell is probably not going to help.
> > 
> > Here is a diff that may work better.  The GenericSerialBuffer stuff
> > allows us to propagate the status of an I2C transfer back up the
> > chain.  So here is a diff that simply returns EIO if the controller
> > can't be found.
> 
> The new blen and EIO logic isn't included in bsd.rd since aml_rwgsb() is
> inside #ifndef SMALL_KERNEL.  We instead fall back to aml_rwgen() in the
> switch over ref1->v_opregion.iospace in aml_rwfield().
> 
> The diff below gives me a working bsd.rd. It pushes SMALL_KERNEL down a
> bit so as to only guard iic_exec(), but perhaps it would be preferable
> to signal the error from aml_rwfield() instead (I don't know how).

Sorry, I meant "signal the error from aml_rwgen()".

> 
> Index: dev/acpi/dsdt.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v
> retrieving revision 1.261
> diff -u -p -r1.261 dsdt.c
> --- dev/acpi/dsdt.c   18 Mar 2021 00:17:26 -0000      1.261
> +++ dev/acpi/dsdt.c   25 Mar 2021 06:44:48 -0000
> @@ -2524,8 +2524,6 @@ aml_rwgpio(struct aml_value *conn, int b
>       }
>  }
>  
> -#ifndef SMALL_KERNEL
> -
>  void
>  aml_rwgsb(struct aml_value *conn, int alen, int bpos, int blen,
>      struct aml_value *val, int mode, int flag)
> @@ -2535,51 +2533,56 @@ aml_rwgsb(struct aml_value *conn, int al
>       i2c_tag_t tag;
>       i2c_op_t op;
>       i2c_addr_t addr;
> -     int cmdlen, buflen;
> +     int cmdlen, buflen, acclen;
>       uint8_t cmd;
>       uint8_t *buf;
> -     int err;
> +#ifndef SMALL_KERNEL
> +     int pos;
> +#endif
> +     int err = 0;
>  
>       if (conn->type != AML_OBJTYPE_BUFFER || conn->length < 5 ||
>           AML_CRSTYPE(crs) != LR_SERBUS || AML_CRSLEN(crs) > conn->length ||
>           crs->lr_i2cbus.revid != 1 || crs->lr_i2cbus.type != LR_SERBUS_I2C)
>               aml_die("Invalid GenericSerialBus");
>       if (AML_FIELD_ACCESS(flag) != AML_FIELD_BUFFERACC ||
> -         bpos & 0x3 || blen != 8)
> +         bpos & 0x3 || (blen % 8) != 0)
>               aml_die("Invalid GenericSerialBus access");
>  
>       node = aml_searchname(conn->node,
>           (char *)&crs->lr_i2cbus.vdata[crs->lr_i2cbus.tlength - 6]);
>  
> -     if (node == NULL || node->i2c == NULL)
> -             aml_die("Could not find GenericSerialBus controller");
> -
>       switch (((flag >> 6) & 0x3)) {
>       case 0:                 /* Normal */
>               switch (AML_FIELD_ATTR(flag)) {
>               case 0x02:      /* AttribQuick */
>                       cmdlen = 0;
> -                     buflen = 0;
> +                     buflen = acclen = 0;
>                       break;
>               case 0x04:      /* AttribSendReceive */
>                       cmdlen = 0;
> -                     buflen = 1;
> +                     acclen = 1;
> +                     buflen = blen / 8;
>                       break;
>               case 0x06:      /* AttribByte */
>                       cmdlen = 1;
> -                     buflen = 1;
> +                     acclen = 1;
> +                     buflen = blen / 8;
>                       break;
>               case 0x08:      /* AttribWord */
>                       cmdlen = 1;
> -                     buflen = 2;
> +                     acclen = 2;
> +                     buflen = blen / 8;
>                       break;
>               case 0x0b:      /* AttribBytes */
>                       cmdlen = 1;
> -                     buflen = alen;
> +                     acclen = alen;
> +                     buflen = blen / 8;
>                       break;
>               case 0x0e:      /* AttribRawBytes */
>                       cmdlen = 0;
> -                     buflen = alen;
> +                     acclen = alen;
> +                     buflen = blen / 8;
>                       break;
>               default:
>                       aml_die("unsupported access type 0x%x", flag);
> @@ -2588,11 +2591,11 @@ aml_rwgsb(struct aml_value *conn, int al
>               break;
>       case 1:                 /* AttribBytes */
>               cmdlen = 1;
> -             buflen = AML_FIELD_ATTR(flag);
> +             acclen = buflen = AML_FIELD_ATTR(flag);
>               break;
>       case 2:                 /* AttribRawBytes */
>               cmdlen = 0;
> -             buflen = AML_FIELD_ATTR(flag);
> +             acclen = buflen = AML_FIELD_ATTR(flag);
>               break;
>       default:
>               aml_die("unsupported access type 0x%x", flag);
> @@ -2606,14 +2609,35 @@ aml_rwgsb(struct aml_value *conn, int al
>               op = I2C_OP_WRITE_WITH_STOP;
>       }
>  
> +     buf = val->v_buffer;
> +
> +     /*
> +      * Return an error if we can't find the I2C controller that
> +      * we're supposed to use for this request.  This shouldn't
> +      * happen as AML should only make use of GenericSerialBus
> +      * address space after verifying that support for it has been
> +      * registered.
> +      */
> +     if (node == NULL || node->i2c == NULL) {
> +             buf[0] = EIO;
> +             return;
> +     }
> +
>       tag = node->i2c;
>       addr = crs->lr_i2cbus._adr;
>       cmd = bpos >> 3;
> -     buf = val->v_buffer;
>  
> +#ifndef SMALL_KERNEL
>       iic_acquire_bus(tag, 0);
> -     err = iic_exec(tag, op, addr, &cmd, cmdlen, &buf[2], buflen, 0);
> +     for (pos = 0; pos < buflen; pos += acclen) {
> +             err = iic_exec(tag, op, addr, &cmd, cmdlen,
> +                 &buf[pos + 2], acclen, 0);
> +             if (err)
> +                     break;
> +             cmd++;
> +     }
>       iic_release_bus(tag, 0);
> +#endif
>  
>       /*
>        * The ACPI specification doesn't tell us what the status
> @@ -2624,8 +2648,6 @@ aml_rwgsb(struct aml_value *conn, int al
>       buf[0] = err;
>  }
>  
> -#endif
> -
>  void
>  aml_rwindexfield(struct aml_value *fld, struct aml_value *val, int mode)
>  {
> @@ -2727,13 +2749,11 @@ aml_rwfield(struct aml_value *fld, int b
>                       aml_rwgpio(ref2, bpos, blen, val, mode,
>                           fld->v_field.flags);
>                       break;
> -#ifndef SMALL_KERNEL
>               case ACPI_OPREG_GSB:
>                       aml_rwgsb(ref2, fld->v_field.ref3,
>                           fld->v_field.bitpos + bpos, blen,
>                           val, mode, fld->v_field.flags);
>                       break;
> -#endif
>               default:
>                       aml_rwgen(ref1, fld->v_field.bitpos + bpos, blen,
>                           val, mode, fld->v_field.flags);
> Index: dev/pci/dwiic_pci.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/dwiic_pci.c,v
> retrieving revision 1.15
> diff -u -p -r1.15 dwiic_pci.c
> --- dev/pci/dwiic_pci.c       25 Dec 2020 21:48:27 -0000      1.15
> +++ dev/pci/dwiic_pci.c       24 Mar 2021 18:48:46 -0000
> @@ -225,7 +225,12 @@ dwiic_pci_attach(struct device *parent, 
>  
>       config_found((struct device *)sc, &sc->sc_iba, iicbus_print);
>  
> -     return;
> +#if NACPI > 0 && !defined(SMALL_KERNEL)
> +     if (sc->sc_devnode) {
> +             sc->sc_devnode->i2c = &sc->sc_i2c_tag;
> +             acpi_register_gsb(acpi_softc, sc->sc_devnode);
> +     }
> +#endif
>  }
>  
>  int

Reply via email to