Comment 439 for bug 1734147

Sorry about the delay but we wanted to make sure the proposed fix can
recover the two test systems we have reliably before asking others to
try it.

I've attached a patch to this bug that should fix the still affected
systems. It applies on top of v4.15-rc6 and I'll be sending it upstream
as well. Canonical already created a kernel package including the fix
and it can be installed from the following link:

http://people.canonical.com/~ypwong/lp1734147/linux-image-4.15.0-041500rc6-generic_4.15.0-041500rc6.201712312330+20170103+1_amd64.deb

The reason why v4.14.9 which includes 9d63f17661e2 ("spi-nor: intel-spi:
Fix broken software sequencing codes") recovers many systems but not all
is because:

  - These systems have CMP=1 in the other status register (SR2) making
    the flash read-only (this is the symptom).

  - Linux SPI-NOR core clears status register properly for flash chips
    that have SPI_NOR_HAS_LOCK set.

  - Serial flashes automatically clear CMP and few other bits if 0 is
    written to the first status register using WRSR command.

  - In order to WRSR take effect the serial flash need to be write
    enabled (WREN must have been issued before WRSR at some point).

  - The systems that recovered the WREN was in effect (probably issued
    by the BIOS before handing off to the OS) so when Linux writes 0 to
    the status register CMP bit is also automatically cleared and the
    problem goes away.

Those systems that were not recovered WREN was not in effect so clearing
the status register and CMP bit was ignored by the serial flash chip.

Normally WREN is send as a preopcode part of an atomic sequence when
software sequencing is used. This has been enabled since commit
8c473dd61bb5 ("spi-nor: intel-spi: Don't assume OPMENU0/1 to be
programmed by BIOS").

However, many systems have two write enable preopcodes available the
PREOP_OPTYPE register:

  0x50 - Write enable for volatile status register
  0x06 - Write enable (WREN)

The current code picks the former which does not enable write for
non-volatile bits so any writes to the status register non-volatile
bits, including BP0/1/2 protection bits do not take effect.

The attached patch changes the driver so that it prefers WREN over other
write enable preopcodes. Booting to the kernel with the patch applied on
a system where the issue still persists should reset the protection bits
and allow the BIOS to save settings again.