Re: [PATCH 0/2] ACPI: Re-factor and remove ./drivers/acpi/atomicio.[ch]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Nov 4, 2011 at 5:54 PM, Myron Stowe <myron.stowe@xxxxxxxxx> wrote:
> The snag I've hit concerns these conversions with respect to
> __apei_exec_write_register().  If __apei_exec_write_register() is called with a
> APEI flag of APEI_EXEC_PRESERVE_REGISTER the code writes the
> target register's bits of interest, specified by 'mask' and 'bit_offset', while
> maintaining the current value of all the other bits of the register.
>
> If we believe that 'bit_offset' should be handled by generic GAS/GAR related
> code and 'mask' should be handled by APEI specific code, I do not see how
> to maintain the behavior of __apei_exec_write_register()'s
> APEI_EXEC_PRESERVE_REGISTER block.  With the 'bit_offset' handling
> split out into ACPI generic code as with such, we would end up losing the
> value of any bits below a 'bit_offset' value that need to be maintained.
>
> If you work through this example of __apei_exec_write_register() and assume
> 'bit_offset' has been moved into ACPI generic code I believe you will see what
> I am trying to point out.
>
> Assume val = 0x0123456789abcdef, mask = 0xff, bit_offset = 16 (0x10),
> valr = 0xfedcba987654321, and (flags & APEI_EXEC_PRESERVE_REGISTER)
> is true the the current code works as follows:
>  val &= mask     0x00000000000000ef
>  val <<= bit_offset     0x0000000000ef0000
>  now the APEI_EXEC_PRESERVE_REGISTER block
>  valr &= ~(mask << bit_offset)     0xfedcba9876003210
>  val |= valr     0xfedeba9876EF3210
>
> I don't see how to maintain this behavior with a converted acpi_write() that
> itself handles 'bit_offset' shifting.

I think this analysis is incorrect because it keeps the bit_offset
shift in __apei_exec_write_register() even though it assumes
acpi_read() uses bit_offset to extract the region.

Assume a 64-bit CSR at 0x1000, with bit_offset = 16 in the GAS and an
8-bit mask, so the region of interest is bits [23:16]:

    gas->address                0x1000
    gas->bit_offset             16 (0x10)
    entry->mask                 0x00000000000000ff

Here's how we handle this in the current __apei_exec_write_register(),
with acpi_read() ignoring bit_offset:

      val &= entry->mask;
      val <<= entry->register_region.bit_offset;
      if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
          acpi_atomic_read(&valr, &entry->register_region);
          valr &= ~(entry->mask << entry->register_region.bit_offset);
          val |= valr;
      }
      acpi_atomic_write(val, &entry->register_region);

      initial value @0x1000     0xfedcba9876543210
      value to write (val)      0x0123456789abcdef
      val &= mask               0x00000000000000EF
      val <<= bit_offset        0x0000000000EF0000
      valr                      0xfedcba9876543210 (from acpi_atomic_read)
      valr &= ~(mask << offset) 0xfedcba9876003210
      val |= valr               0xfedcba9876EF3210
      final value @0x1000       0xfedcba9876EF3210 (by acpi_atomic_write)

If we make acpi_read() & acpi_write() pay attention to bit_offset,
__apei_exec_write_register() should look like this:

      val &= entry->mask;
      if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) {
          acpi_read(&valr, &entry->register_region);  /* valr = bits [xx:16] */
          valr &= ~entry->mask;
          val |= valr;
      }
      acpi_write(val, &entry->register_region);  /* writes only bits [xx:16] */

      initial value @0x1000     0xfedcba9876543210
      value to write (val)      0x0123456789abcdef
      val &= mask               0x00000000000000EF
      valr                      0x0000fedcba987654 (from acpi_read)
      valr &= ~mask             0x0000fedcba987600
      val |= valr               0x0000fedcba9876EF
      final value @0x1000       0xfedcba9876EF3210 (by acpi_write)

This depends on some assumptions about how acpi_read() and
acpi_write() deal with bit_offset and probably bit_width.  I don't
think we have those behaviors all worked out yet, but I think it's
possible, and this is a good opportunity to do it.

Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux