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.
77 lines
2.7 KiB
Makefile
77 lines
2.7 KiB
Makefile
obj-m := i2c-imc-skylake.o
|
|
|
|
KVER ?= $(shell uname -r)
|
|
KDIR ?= /lib/modules/$(KVER)/build
|
|
|
|
# Out-of-tree only. The driver targets current mainline and calls
|
|
# i2c_register_spd_write_disable(); older kernels have the unsplit
|
|
# i2c_register_spd(). compat.h bridges that, force included here so
|
|
# i2c-imc-skylake.c is exactly the file sent upstream. Detected from the target
|
|
# kernel's header rather than from a version number, which keeps it right on
|
|
# backported and vendor trees.
|
|
SPD_SPLIT := $(shell grep -qs i2c_register_spd_write_disable \
|
|
$(KDIR)/include/linux/i2c-smbus.h && echo -DHAVE_I2C_REGISTER_SPD_SPLIT)
|
|
ccflags-y += -include $(src)/compat.h $(SPD_SPLIT)
|
|
INSTALL_MOD_PATH ?= $(DESTDIR)
|
|
INSTALL_MOD_DIR ?= updates
|
|
PWD := $(shell pwd)
|
|
|
|
all:
|
|
$(MAKE) -C $(KDIR) M=$(PWD) modules
|
|
|
|
clean:
|
|
$(MAKE) -C $(KDIR) M=$(PWD) clean
|
|
|
|
# Install through Kbuild so ownership, compression and destination follow the
|
|
# target kernel/distribution policy. Invoke this target with suitable privileges.
|
|
install: all
|
|
$(MAKE) -C $(KDIR) M=$(PWD) modules_install \
|
|
INSTALL_MOD_PATH=$(INSTALL_MOD_PATH) \
|
|
INSTALL_MOD_DIR=$(INSTALL_MOD_DIR)
|
|
|
|
# Remove a module installed in INSTALL_MOD_DIR. Invoke with suitable privileges.
|
|
uninstall:
|
|
rm -f $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR)/i2c-imc-skylake.ko*
|
|
depmod -a -b $(INSTALL_MOD_PATH) $(KVER)
|
|
|
|
# Runtime helpers require explicit acknowledgement of the firmware-arbitration
|
|
# risk: make reload ALLOW_UNSAFE=1 (or make load ALLOW_UNSAFE=1).
|
|
reload: all
|
|
@test "$(ALLOW_UNSAFE)" = "1" || \
|
|
{ echo "Refusing: rerun with ALLOW_UNSAFE=1" >&2; exit 2; }
|
|
sudo rmmod i2c-imc-skylake 2>/dev/null || true
|
|
sudo insmod i2c-imc-skylake.ko allow_unsafe_access=1
|
|
|
|
# Load without build (use after install)
|
|
load:
|
|
@test "$(ALLOW_UNSAFE)" = "1" || \
|
|
{ echo "Refusing: rerun with ALLOW_UNSAFE=1" >&2; exit 2; }
|
|
sudo modprobe i2c-dev
|
|
sudo modprobe i2c-imc-skylake allow_unsafe_access=1
|
|
|
|
unload:
|
|
sudo rmmod i2c-imc-skylake 2>/dev/null || true
|
|
|
|
# Checkpatch (must be clean before submission)
|
|
checkpatch:
|
|
perl $(KDIR)/scripts/checkpatch.pl --strict --no-tree -f i2c-imc-skylake.c
|
|
|
|
# Sparse static analysis (requires sparse >= kernel version; may show header errors on old sparse)
|
|
sparse:
|
|
$(MAKE) -C $(KDIR) M=$(PWD) C=1 CF="-D__CHECK_ENDIAN__"
|
|
|
|
# Smoke test requires root or non-interactive sudo.
|
|
test: all
|
|
MODULE_PATH=$(PWD)/i2c-imc-skylake.ko bash test-smoke.sh
|
|
|
|
# Hardware measurements that the upstream submission still needs. Read-only
|
|
# unless explicitly asked otherwise; see tools/README.md.
|
|
measure:
|
|
@echo "Run the scripts under tools/ individually; see tools/README.md" >&2
|
|
@false
|
|
|
|
log:
|
|
sudo dmesg | grep i2c-imc-skylake | tail -80
|
|
|
|
.PHONY: all clean install uninstall reload load unload checkpatch sparse test measure log
|