Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: piix4: Fix probing of reserved ports on AMD Family 16h Model 30h

Prevent bus timeouts and resets on Family 16h Model 30h by not probing
reserved Ports 3 and 4.

According to the AMD BIOS and Kernel Developer's Guides (BKDG), Port 3
and Port 4 are reserved on the following devices:
- Family 15h Model 60h-6Fh
- Family 15h Model 70h-7Fh
- Family 16h Model 30h-3Fh

Based on earlier work by Andrew Cooks.

Reported-by: Andrew Cooks <andrew.cooks@opengear.com>
Signed-off-by: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

authored by

Jean Delvare and committed by
Wolfram Sang
528d53a1 ba919403

+13 -3
+13 -3
drivers/i2c/busses/i2c-piix4.c
··· 72 72 #define PIIX4_BLOCK_DATA 0x14 73 73 74 74 /* Multi-port constants */ 75 - #define PIIX4_MAX_ADAPTERS 4 75 + #define PIIX4_MAX_ADAPTERS 4 76 + #define HUDSON2_MAIN_PORTS 2 /* HUDSON2, KERNCZ reserves ports 3, 4 */ 76 77 77 78 /* SB800 constants */ 78 79 #define SB800_PIIX4_SMB_IDX 0xcd6 ··· 809 808 810 809 static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS]; 811 810 static struct i2c_adapter *piix4_aux_adapter; 811 + static int piix4_adapter_count; 812 812 813 813 static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, 814 814 bool sb800_main, u8 port, bool notify_imc, ··· 869 867 int port; 870 868 int retval; 871 869 872 - for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) { 870 + if (dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS || 871 + (dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && 872 + dev->revision >= 0x1F)) { 873 + piix4_adapter_count = HUDSON2_MAIN_PORTS; 874 + } else { 875 + piix4_adapter_count = PIIX4_MAX_ADAPTERS; 876 + } 877 + 878 + for (port = 0; port < piix4_adapter_count; port++) { 873 879 retval = piix4_add_adapter(dev, smba, true, port, notify_imc, 874 880 piix4_main_port_names_sb800[port], 875 881 &piix4_main_adapters[port]); ··· 999 989 1000 990 static void piix4_remove(struct pci_dev *dev) 1001 991 { 1002 - int port = PIIX4_MAX_ADAPTERS; 992 + int port = piix4_adapter_count; 1003 993 1004 994 while (--port >= 0) { 1005 995 if (piix4_main_adapters[port]) {