Skip to content

Commit ef0f622

Browse files
mellanoxbmcdvhart
authored andcommitted
platform/x86: mlx-platform: Add physical bus number auto detection
mlx-platform does not provide a bus number to i2c-mlxcpld, assuming it is always one. On some x86 systems, other i2c drivers may probe before i2c-mlxcpld, causing bus one to be busy. Make mlx-platform determine which adapter number is free prior to activating i2c-mlxpld, adjusting the mux base numbers accordingly. Update the mlxreg-hotplug pdata similarly. This adds an explicit mlx-platform build dependency on I2C, update the Kconfig accordingly. Add the missing REGMAP dependency while we're at it. Signed-off-by: Vadim Pasternak <[email protected]> [dvhart: Rewrite commit message more concisely] [dvhart: Add build dependencies] Signed-off-by: Darren Hart (VMware) <[email protected]>
1 parent f709e1b commit ef0f622

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-6
lines changed

drivers/platform/mellanox/mlxreg-hotplug.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,26 +96,30 @@ struct mlxreg_hotplug_priv_data {
9696
static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
9797
struct mlxreg_core_data *data)
9898
{
99+
struct mlxreg_core_hotplug_platform_data *pdata;
100+
99101
/*
100102
* Return if adapter number is negative. It could be in case hotplug
101103
* event is not associated with hotplug device.
102104
*/
103105
if (data->hpdev.nr < 0)
104106
return 0;
105107

106-
data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
108+
pdata = dev_get_platdata(&priv->pdev->dev);
109+
data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr +
110+
pdata->shift_nr);
107111
if (!data->hpdev.adapter) {
108112
dev_err(priv->dev, "Failed to get adapter for bus %d\n",
109-
data->hpdev.nr);
113+
data->hpdev.nr + pdata->shift_nr);
110114
return -EFAULT;
111115
}
112116

113117
data->hpdev.client = i2c_new_device(data->hpdev.adapter,
114118
data->hpdev.brdinfo);
115119
if (!data->hpdev.client) {
116120
dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
117-
data->hpdev.brdinfo->type, data->hpdev.nr,
118-
data->hpdev.brdinfo->addr);
121+
data->hpdev.brdinfo->type, data->hpdev.nr +
122+
pdata->shift_nr, data->hpdev.brdinfo->addr);
119123

120124
i2c_put_adapter(data->hpdev.adapter);
121125
data->hpdev.adapter = NULL;

drivers/platform/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,7 @@ config INTEL_TELEMETRY
11751175

11761176
config MLX_PLATFORM
11771177
tristate "Mellanox Technologies platform support"
1178+
depends on I2C && REGMAP
11781179
---help---
11791180
This option enables system support for the Mellanox Technologies
11801181
platform. The Mellanox systems provide data center networking

drivers/platform/x86/mlx-platform.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@
8585
#define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0)
8686
#define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0)
8787

88+
/* Default I2C parent bus number */
89+
#define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1
90+
91+
/* Maximum number of possible physical buses equipped on system */
92+
#define MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM 16
93+
8894
/* Number of channels in group */
8995
#define MLXPLAT_CPLD_GRP_CHNL_NUM 8
9096

@@ -843,10 +849,48 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
843849

844850
MODULE_DEVICE_TABLE(dmi, mlxplat_dmi_table);
845851

852+
static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
853+
{
854+
struct i2c_adapter *search_adap;
855+
int shift, i;
856+
857+
/* Scan adapters from expected id to verify it is free. */
858+
*nr = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR;
859+
for (i = MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR; i <
860+
MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM; i++) {
861+
search_adap = i2c_get_adapter(i);
862+
if (search_adap) {
863+
i2c_put_adapter(search_adap);
864+
continue;
865+
}
866+
867+
/* Return if expected parent adapter is free. */
868+
if (i == MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR)
869+
return 0;
870+
break;
871+
}
872+
873+
/* Return with error if free id for adapter is not found. */
874+
if (i == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM)
875+
return -ENODEV;
876+
877+
/* Shift adapter ids, since expected parent adapter is not free. */
878+
*nr = i;
879+
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
880+
shift = *nr - mlxplat_mux_data[i].parent;
881+
mlxplat_mux_data[i].parent = *nr;
882+
mlxplat_mux_data[i].base_nr += shift;
883+
if (shift > 0)
884+
mlxplat_hotplug->shift_nr = shift;
885+
}
886+
887+
return 0;
888+
}
889+
846890
static int __init mlxplat_init(void)
847891
{
848892
struct mlxplat_priv *priv;
849-
int i, err;
893+
int i, nr, err;
850894

851895
if (!dmi_check_system(mlxplat_dmi_table))
852896
return -ENODEV;
@@ -866,7 +910,12 @@ static int __init mlxplat_init(void)
866910
}
867911
platform_set_drvdata(mlxplat_dev, priv);
868912

869-
priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", -1,
913+
err = mlxplat_mlxcpld_verify_bus_topology(&nr);
914+
if (nr < 0)
915+
goto fail_alloc;
916+
917+
nr = (nr == MLXPLAT_CPLD_MAX_PHYS_ADAPTER_NUM) ? -1 : nr;
918+
priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", nr,
870919
NULL, 0);
871920
if (IS_ERR(priv->pdev_i2c)) {
872921
err = PTR_ERR(priv->pdev_i2c);

include/linux/platform_data/mlxreg.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct mlxreg_core_platform_data {
130130
* @cell_low: location of low aggregation interrupt register;
131131
* @mask_low: low aggregation interrupt common mask;
132132
* @deferred_nr: I2C adapter number must be exist prior probing execution;
133+
* @shift_nr: I2C adapter numbers must be incremented by this value;
133134
*/
134135
struct mlxreg_core_hotplug_platform_data {
135136
struct mlxreg_core_item *items;
@@ -141,6 +142,7 @@ struct mlxreg_core_hotplug_platform_data {
141142
u32 cell_low;
142143
u32 mask_low;
143144
int deferred_nr;
145+
int shift_nr;
144146
};
145147

146148
#endif /* __LINUX_PLATFORM_DATA_MLXREG_H */

0 commit comments

Comments
 (0)