Date: Thu, 30 Apr 2026 09:18:12 +0000 From: Corvi=?utf-8?Q?n K=C3=B6h?=ne <corvink@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 226b37dc3ad5 - main - dev/ichsmb: disable block buffer if supported Message-ID: <69f31e54.416a2.7d72e12f@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by corvink: URL: https://cgit.FreeBSD.org/src/commit/?id=226b37dc3ad5641c18f8542c18baea3ea641c5af commit 226b37dc3ad5641c18f8542c18baea3ea641c5af Author: Corvin Köhne <corvink@FreeBSD.org> AuthorDate: 2026-03-30 09:33:20 +0000 Commit: Corvin Köhne <corvink@FreeBSD.org> CommitDate: 2026-04-30 09:15:18 +0000 dev/ichsmb: disable block buffer if supported In order to improve the efficiency of block read/write calls, Intel has introduced a block buffer. Instead of generating an interrupt after receiving/sending a single byte, the data is buffered in the block buffer. It allows the SMBus controller to generate a single interrupt for the whole transfer. At the moment, we don't support that and don't expect the SMBus controller to behave in that way. Unfortunately, BIOS code can also access the SMBus controller and may enable the block buffer. Poorly written BIOS code may also keep the block buffer enabled breaking our driver. Therefore, we should check if the device supports a block buffer and disable it for every request because we don't know if some BIOS code has reconfigured the SMBus controller in between. Reviewed by: emaste MFC after: 1 week Sponsored by: Beckhoff Automation GmbH & Co. KG Pull Request: https://github.com/freebsd/freebsd-src/pull/2161 --- sys/dev/ichsmb/ichsmb.c | 18 +++++++++++++++ sys/dev/ichsmb/ichsmb_pci.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ sys/dev/ichsmb/ichsmb_reg.h | 3 +++ sys/dev/ichsmb/ichsmb_var.h | 3 +++ 4 files changed, 78 insertions(+) diff --git a/sys/dev/ichsmb/ichsmb.c b/sys/dev/ichsmb/ichsmb.c index e40a8a8a3886..0df757d9cc0e 100644 --- a/sys/dev/ichsmb/ichsmb.c +++ b/sys/dev/ichsmb/ichsmb.c @@ -395,6 +395,15 @@ ichsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) sc->block_write = true; mtx_lock(&sc->mutex); + /* + * We don't expect the block buffer to be enabled. However, BIOS code + * might enable it and doesn't restore it at any time, so we should + * ensure it's disabled before sending an SMBus command. + */ + if (sc->features & ICHSMB_FEATURE_BLOCK_BUFFER) { + bus_write_1(sc->io_res, ICH_AUX_CNT, + bus_read_1(sc->io_res, ICH_AUX_CNT) & ~ICH_AUX_CNT_E32B); + } sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK; bus_write_1(sc->io_res, ICH_XMIT_SLVA, slave | ICH_XMIT_SLVA_WRITE); @@ -424,6 +433,15 @@ ichsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) sc->block_write = false; mtx_lock(&sc->mutex); + /* + * We don't expect the block buffer to be enabled. However, BIOS code + * might enable it and doesn't restore it at any time, so we should + * ensure it's disabled before sending an SMBus command. + */ + if (sc->features & ICHSMB_FEATURE_BLOCK_BUFFER) { + bus_write_1(sc->io_res, ICH_AUX_CNT, + bus_read_1(sc->io_res, ICH_AUX_CNT) & ~ICH_AUX_CNT_E32B); + } sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK; bus_write_1(sc->io_res, ICH_XMIT_SLVA, slave | ICH_XMIT_SLVA_READ); diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c index 7d6d94dbb4a4..af3e0f004b88 100644 --- a/sys/dev/ichsmb/ichsmb_pci.c +++ b/sys/dev/ichsmb/ichsmb_pci.c @@ -129,106 +129,153 @@ static const struct pci_device_table ichsmb_devices[] = { { PCI_DEV(PCI_VENDOR_INTEL, ID_82801CA), PCI_DESCR("Intel 82801CA (ICH3) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801DC), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801DC (ICH4) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801EB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801EB (ICH5) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801FB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801FB (ICH6) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801GB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801GB (ICH7) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801H), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801H (ICH8) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801I), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801I (ICH9) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801GB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801GB (ICH7) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801H), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801H (ICH8) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801I), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801I (ICH9) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_EP80579), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel EP80579 SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801JI), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801JI (ICH10) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801JD), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801JD (ICH10) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PCH), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel PCH SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_6300ESB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 6300ESB (ICH) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_631xESB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 631xESB/6321ESB (ESB2) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_DH89XXCC), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel DH89xxCC SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PATSBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Patsburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Cougar Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Panther Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_AVOTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Avoton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lynx Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lynx Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WCPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wildcat Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WCPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wildcat Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BAYTRAIL), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Baytrail SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BRASWELL), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Braswell SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COLETOCRK), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Coleto Creek SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WELLSBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wellsburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_SRPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Sunrise Point-H SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_SRPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Sunrise Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_DENVERTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Denverton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BROXTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Broxton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LEWISBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lewisburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LEWISBURG2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lewisburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_KABYLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Kaby Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CANNONLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Cannon Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COMETLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Comet Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COMETLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Comet Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_TIGERLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Tiger Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_TIGERLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Tiger Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ELKHARTLAKE), PCI_DESCR("Intel Elkhart Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_GEMINILAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Gemini Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CEDARFORK), PCI_DESCR("Intel Cedar Fork SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ICELAKE), PCI_DESCR("Intel Ice Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE3), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_RAPTORLAKE), PCI_DESCR("Intel Raptor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE3), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, }; @@ -288,6 +335,7 @@ ichsmb_pci_probe(device_t dev) static int ichsmb_pci_attach(device_t dev) { + const struct pci_device_table *tbl; const sc_p sc = device_get_softc(dev); int error; @@ -296,6 +344,12 @@ ichsmb_pci_attach(device_t dev) sc->ich_cmd = -1; sc->dev = dev; + tbl = PCI_MATCH(dev, ichsmb_devices); + if (tbl == NULL) + return (ENXIO); + + sc->features = (uint32_t)tbl->driver_data; + /* Allocate an I/O range */ sc->io_rid = ICH_SMB_BASE; sc->io_res = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, diff --git a/sys/dev/ichsmb/ichsmb_reg.h b/sys/dev/ichsmb/ichsmb_reg.h index 78e398a556ef..be3b9e4a899d 100644 --- a/sys/dev/ichsmb/ichsmb_reg.h +++ b/sys/dev/ichsmb/ichsmb_reg.h @@ -84,6 +84,9 @@ #define ICH_D0 0x05 /* host data 0 */ #define ICH_D1 0x06 /* host data 1 */ #define ICH_BLOCK_DB 0x07 /* block data byte */ +#define ICH_AUX_CNT 0x0d /* auxiliary control */ +#define ICH_AUX_CNT_E32B 0x02 /* enable 32 byte buffer */ +#define ICH_AUX_CNT_AAC 0x01 /* automatically append crc */ #endif /* _DEV_ICHSMB_ICHSMB_REG_H_ */ diff --git a/sys/dev/ichsmb/ichsmb_var.h b/sys/dev/ichsmb/ichsmb_var.h index 8aeaf403781b..f16a40be9777 100644 --- a/sys/dev/ichsmb/ichsmb_var.h +++ b/sys/dev/ichsmb/ichsmb_var.h @@ -41,6 +41,8 @@ #include "smbus_if.h" +#define ICHSMB_FEATURE_BLOCK_BUFFER 0x01 /* supports 32 byte block buffer */ + /* Per-device private info */ struct ichsmb_softc { @@ -52,6 +54,7 @@ struct ichsmb_softc { struct resource *irq_res; /* interrupt resource */ int irq_rid; /* interrupt bus id */ void *irq_handle; /* handle for interrupt code */ + uint32_t features; /* supported device features */ /* Device state */ int ich_cmd; /* ich command, or -1 */home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f31e54.416a2.7d72e12f>
