2bc5145cf2774b2f3d5ae987db7753a2031604bd
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7bac49b4f6 |
i2c-imc-skylake: harden the checks for the v4 respin
All of this came out of a self-review of v3 plus one robot report; none of it changes what the driver supports. The read-back check required the whole command word to come back as written, and the interference check on the driven channel compared against the pre-transfer word. Both implicitly demanded that every undocumented bit of the command register reads as zero, which held on the test system but is not something to assume across steppings. Compare only the bits this driver produces, with the post-write read-back as the baseline for the driven channel; GO clearing remains the single permitted difference. Read the result before the interference check, not after, so the check also covers the window in which the data latch is read. Re-run the TSOD-polling check on resume and keep the adapters suspended if firmware enabled polling across suspend; the probe-time refusal cannot see that, and the S3 observation in the cover letter is exactly this scenario. Stop before writing a saved command word back if the config read that fetched it had already failed. Rename the register accessors: the command register is CMD and the data latch DATA. v3 called the command register DATA and the data latch CTRL, which read backwards. Cast ~COMMAND_OUR_BITS to u32 in the interference check. BIT() and GENMASK() are unsigned long, so the complement was computed in 64 bits and truncated on assignment; the truncated value was already correct, this only silences a clang W=1 -Wconstant-conversion warning. Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/ The Kconfig help and the .rst now say that PCI ID 8086:2085 also matches Skylake-SP / Cascade Lake-SP servers, where a BMC is far more likely to own the engine, and the .rst states plainly that jc42 itself has not been run here, only the transactions it needs. |
||
|
|
6ae520c1ba |
i2c-imc-skylake: the i2cdetect example shows what the driver does now
The documentation's sample scan predates SPD instantiation at probe. It
shows 0x36, 0x50 and 0x52 as detected addresses, but the driver claims
them itself now, so a real run reports UU there and 0x37 as well. The
example printed output the driver can no longer produce.
Measured on the X299 system, both channels identical:
0 1 2 3 4 5 6 7 8 9 a b c d e f
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
30: 30 31 -- -- 34 35 UU UU -- -- -- -- -- -- -- --
50: UU -- UU -- -- -- -- -- -- -- -- -- -- -- -- --
Say what the UU entries are, since the section that explains
instantiation comes further down and a reader scanning the bus meets
them first.
|
||
|
|
694ed6a712 |
i2c-imc-skylake: instantiate the SPD EEPROMs at probe
Call i2c_register_spd() per adapter, like i801 and piix4, instead of
telling the user to echo into new_device. The helper counts populated
slots from DMI and probes upwards from 0x50 via i2c_new_scanned_device(),
so it claims no address that does not answer; each channel carries half
the DIMMs and the scan is per adapter, so each finds its own. Verified:
four clients on load, two per channel, none on the empty slots, and
decode-dimms works with no manual step.
This needed Receive Byte to be worth doing — without I2C_FUNC_SMBUS_BYTE
ee1004 would not have bound to what was instantiated.
The write_disable variant is deliberate. This part is DDR4 only, where
the two are equivalent (the split gates spd5118 on DDR5), and of two
equivalent calls the one that does not read as "this driver enables SPD
writes" is the better name to leave in a driver whose bus is the memory
bus. In-tree convention is write_enable; the cover letter offers to
switch.
Kconfig gains select I2C_SMBUS.
Out-of-tree, compat.h maps the call onto the older unsplit
i2c_register_spd() where that is what the target kernel has. It is force
included from the Makefile so i2c-imc-skylake.c stays byte-identical to
the submitted file, and the Makefile detects the API by grepping the
target kernel's header rather than testing a version number, which keeps
it correct on backported trees. Builds clean against both 6.8 and 7.0
headers; DKMS 1.0.2 installs on all four kernels here.
test-smoke.sh needed two fixes to keep testing what it claims:
- A bound driver owns its address, so the raw transaction checks lost
the SPDs the moment the driver started instantiating them. The script
now unbinds ee1004 for the duration rather than deleting the clients:
sysfs delete_device only removes clients that new_device created,
and unbinding is sufficient because i2c-dev refuses an address only
while a driver is bound (i2cdev_check: `return dev->driver ? -EBUSY
: 0`). Rebound from an EXIT trap.
- Those checks were guarded on an SPD address having been found, and
when the lookup failed they vanished from the run silently: the suite
reported "12 passed, 0 failed" while seven checks had not executed.
Skipped checks are now counted and printed, which is how the above
was noticed at all.
Smoke suite: 20 passed, 0 failed, 0 skipped. checkpatch --strict 0/0/0,
in-tree W=1 and Sparse clean.
|
||
|
|
cd6e8cf145 |
i2c-imc-skylake: document the ee1004 address-ownership trade-off
A bound ee1004 owns 0x50-0x57, so userspace loses /dev/i2c access to them. On this bus that is not academic: furyd's SPD guard reports 0/4 present while ee1004 holds the addresses. |
||
|
|
c04e0ec5a8 |
i2c-imc-skylake: implement Receive Byte and Send Byte
The engine encodes an address-only transaction in command word bit 18, which is what SMBus Receive Byte and Send Byte need and what was missing for ee1004 to bind. The bit is not documented for the PCU function. It was located by structure rather than by sweeping: SMBCMD on the iMC channel function (datasheet ref. 614073 section 3.1.8) places PNTR_SEL immediately above WORD_ACCESS, and word access here is bit 17. Bit 17 had itself been unknown until it turned out to be word access, and an earlier sweep of this register covered bits 31:20 only, so 18 was untried rather than already ruled out. Validated against the device rather than against the register. An EEPROM auto-increments its pointer after a read, so priming the pointer and repeating the read with the bit set has a predicted answer: the next byte, not the one named. Eight consecutive reads returned SPD bytes 0x01 through 0x08 in order, matching an ordinary dump. Send Byte was confirmed on the DDR4 page-select addresses, which hold a latch and store no data, so the page state is itself the readout. Result: ee1004 binds on all four SPD addresses and decode-dimms decodes all four modules with both CRCs valid on each. The part number comes off page 1, so the page select runs end to end. The four module serial numbers are unchanged from the baseline recorded before this series. SMBus Quick stays unimplemented. Beyond having no obvious encoding, a write into the 0x30-0x37 range is how an EE1004 SPD is write-protected, permanently on many modules, so an adapter on the memory bus should not advertise a probe that writes. i2cdetect scans in read mode. Also fix test-smoke.sh resolving the module through modinfo, which silently tested the installed DKMS build instead of the one just compiled. It now prefers the local .ko and prints which it loaded. Smoke suite: 19 passed, 0 failed. checkpatch --strict 0/0/0, in-tree W=1 and Sparse clean. |
||
|
|
c9b8799f69 |
i2c-imc-skylake: suspend/resume, and correct the ee1004 claim
Two things came out of preparing the suspend test, and one of them is a correction. ee1004 does not bind to this adapter. Both functionality combinations it accepts include I2C_FUNC_SMBUS_BYTE (drivers/misc/eeprom/ee1004.c:301), which this driver does not implement, so the probe fails with -EPFNOSUPPORT. The cover letter claimed BYTE_DATA and WORD_DATA "cover ee1004 and jc42" and the .rst told the reader to instantiate it; both were wrong and are corrected. jc42 is fine, it only needs BYTE_DATA and WORD_DATA, but no TSOD is populated here to bind to. The practical cost is that decode-dimms does not work through this adapter. SPD bytes stay readable byte by byte with i2cget. Receive Byte is what PawnIO implements with its pointer-select bit and what this project chose not to advertise for want of validation; that choice was not free, and adding it validated is the most useful thing left. Suspend and resume tested with continuous traffic on both adapters, s2idle and S3. Transfers recover, nothing complains. Across S3 the engine comes back reprogrammed on both channels: DATA 0x2000b600 -> 0x20005000 STATUS 0x0000500c -> 0x00005004 The command word addresses SPD 0x50 for a read and the status drops to READ_DONE alone. Linux issued none of it: the adapter was marked suspended and userspace frozen. This is consistent with firmware reading SPD during memory training on resume, and it is the first direct observation of a second master on this engine. It is also the concrete justification for restoring command state per transfer and comparing it afterwards. Add tools/test-suspend.sh, which drives that test and reports the register delta across the sleep. Traffic goes through i2c-dev rather than a bound client: with ee1004 unable to attach and no TSOD present, there is no in-kernel client to use, and the PM path exercised is the same either way -- i2c_smbus_xfer() consults __i2c_check_suspended() before reaching the adapter. |
||
|
|
b021fe4087 |
i2c-imc-skylake: close F2 with the register Intel documents
The open question was how to know whether the memory controller is polling
the DIMM thermal sensors, which is what killed the Broadwell-E attempt's
predecessor and what this driver had no answer for.
Intel documents it. The Xeon Processor Scalable Family datasheet volume 2
(reference 614073, section 3.1.9) puts SMBCNTL on the iMC channel function,
device 10 and 12 function 0, at offsets 0xe88 and 0xe98. SMB_TSOD_POLL_EN
is documented as mutually exclusive with SPD command access, so it answers
the question directly. The driver now reads it on every channel at probe
and refuses to bind if it is set.
This is deliberately weaker than the Broadwell-E driver, which switched the
polling off for the duration of a transfer. Reading and declining is a
smaller claim on hardware the driver does not own and needs no write to a
firmware-configured register. It covers the memory controller only; SMM and
a BMC are still out of reach, which is what the opt-in is for.
On the test system all four channels read 0xac000000: polling disabled,
TSOD_PRESENT empty, which also explains why no jc42 ever appeared at
0x18-0x1f on these DIMMs. Offset 0xe0, where the Broadwell driver has its
TSODCNTL, reads zero on all seven PCU functions here: that layout does not
transfer.
Two more measurements, both recorded in the cover letter:
- the SMBus interface Intel documents, at 0xe80-0xe9c on the iMC, does not
reach the bus on this platform. Issuing SMBCMD with CMD_TRIGGER sets
SMB_RDO and clears SMB_BUSY, but returns 0x00 for a populated DIMM at
0x50, a second one at 0x52 and an empty slot at 0x57 alike, with SMB_SBE
never set. The path this driver uses returns the correct SPD contents
and a NACK for the empty slot. The datasheet does not describe PCU
function 5 at all, so the choice is now stated with data rather than
left for a reviewer to ask about;
- writes are issued on the bus: a byte write to an unpopulated address
returns -ENXIO with the engine reporting the address NACK. This matters
because SMB_DIS_WRT is set in the documented SMBCNTL and is SMM-writable
only, so it evidently governs that interface and not this one.
Engine registers sampled every 2 s for an hour with the driver unloaded:
1791 samples, 0 changes.
Add tools/probe-imc-documented.sh, which produced the comparison above.
Smoke test with the new probe check: 15 checks, 0 failures.
|
||
|
|
88a8b7eb27 |
i2c-imc-skylake: retract the CF8/CFC claim, harden the state machine
v2 said firmware filters CF8/CFC config writes to this function and that
the registers are reachable only through ECAM. That was never tested; the
only evidence was the boot line "PCI: Using configuration type 1", which
names the accessor and says nothing about a write failing.
Measured on the board, driver unloaded:
# setpci -s 16:1e.5 9c.L=20085002 # read SPD 0x50 register 0x02
# setpci -s 16:1e.5 9c.L
20005002 # GO consumed by the engine
# setpci -s 16:1e.5 a8.L
0000500c # READ_DONE, no error
# setpci -s 16:1e.5 b4.L
0000000c # SPD byte 2, DDR4 type code
The command executes and returns correct data through the ordinary
accessors, and MSR_SMI_COUNT does not move across it. So the driver now
uses pci_read_config_dword() and pci_write_config_dword(), the submission
is a single patch again, and nothing in it touches the PCI core. The
cover letter retracts the claim explicitly rather than dropping it
quietly, because v2 was posted with it.
Correctness work in the same pass:
- the completion bits are latched, so a command word that never reaches
the register is indistinguishable from a completed transfer and the
caller gets the previous transaction's data. Read the command word
back and require it to be the one just written; the engine only ever
clears GO, which the measurement above shows directly;
- compare the command registers after every transfer against what the
driver left in them and fail with -EAGAIN on a mismatch. The original
iMC driver had this check and it is what makes an unarbitrated system
detectable instead of silently wrong;
- use the i2c core's suspended-adapter mechanism rather than a private
flag and -EHOSTDOWN;
- use devm_mutex_init(), drop the unnecessary pci_enable_device(), and
return -ENODEV rather than -EPERM from the default-off gate, which was
printing a driver-core error on every boot;
- mask GO when restoring a saved command word.
An earlier version of the latched-DONE check required the GO bit to be
seen set or the status word to change. That was wrong: repeated transfers
with the same outcome leave STATUS bit for bit identical, and GO is
consumed faster than a config read-back can observe it. It produced false
positives on 3 of 15 smoke-test items before being replaced.
Add Documentation/i2c/busses/i2c-imc-skylake.rst, which every other PC
SMBus driver has and which was asked for on the 2020 iMC thread, and the
tools/ scripts for the hardware measurements: probe-cf8-write.sh and
probe-cf8-transaction.sh produced the result above, dump-pcu-config.sh is
the search for a TSOD polling control, watch-engine.sh is the firmware
activity measurement.
Smoke test on the X299 system with the current module: 15 checks, 0
failures, dmesg clean.
|
||
|
|
3cd1d6e0a6 |
i2c-imc-skylake: split the submission into a PCI patch and the driver
The driver reached the PCU function's config space by walking the ACPI MCFG
table and mapping the ECAM page itself. That is one leaf driver deciding
config-space policy, and no other driver in mainline does it, so it was the
single most likely reason for a NAK.
Move that decision where it belongs: the upstream series is now two patches,
a PCI/x86 accessor that forces the memory-mapped path with the core's
locking, and this driver on top of it. Reviewers on each side now get
something they can act on, and get_maintainer.pl selects the PCI and x86
people by itself.
Correctness work in the same pass:
- the completion bits are latched, so a command the engine never accepted
was indistinguishable from a completed one and returned the previous
transaction's data as valid. Require a positive sign that the engine
acted on the command;
- compare the command registers after every transfer against what the
driver left in them and fail with -EAGAIN on a mismatch. The original
iMC driver had this check and it is what makes an unarbitrated system
detectable instead of silently wrong;
- use the i2c core's suspended-adapter mechanism rather than a private
flag and -EHOSTDOWN;
- use devm_mutex_init(), drop the unnecessary pci_enable_device(), and
return -ENODEV rather than -EPERM from the default-off gate, which was
printing a driver-core error on every boot;
- mask GO when restoring a saved command word.
Stop attributing the dropped CF8/CFC write to System Management Mode. The
only evidence was a boot log line naming the access method, which says
nothing about who filters the write. tools/probe-cf8-write.sh is there to
settle it with an MSR_SMI_COUNT measurement.
Add Documentation/i2c/busses/i2c-imc-skylake.rst, which every other PC SMBus
driver has and which was explicitly asked for on the 2020 iMC thread, the
tools/ scripts for the hardware measurements the submission still owes, and
compat/pci-mmcfg-compat.h so the driver still builds out-of-tree against a
kernel without the new accessor while the source stays byte-identical to the
submitted patch.
|