Commit d726f6b1 authored by Vadim Pasternak's avatar Vadim Pasternak Committed by Darren Hart (VMware)

platform/x86: mlx-platform: Add deffered bus functionality

mlx-platform activates i2c-mux-reg, which creates buses needed by
mlxreg-hotplug. If the mlxreg-hotplug probe runs before the i2c-mux-reg
probe completes, it may attempt to connect a device to an adapter number
that has not been created yet, and fail.

Make mlx-platform driver record the highest bus number in mlxreg-hotplug
platform data and defer mlxreg-hotplug probe until all the buses are
created.
Signed-off-by: default avatarVadim Pasternak <vadimp@mellanox.com>
[dvhart: rewrite commit message more concisely]
Signed-off-by: default avatarDarren Hart (VMware) <dvhart@infradead.org>
parent d066f144
...@@ -550,6 +550,7 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev) ...@@ -550,6 +550,7 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
{ {
struct mlxreg_core_hotplug_platform_data *pdata; struct mlxreg_core_hotplug_platform_data *pdata;
struct mlxreg_hotplug_priv_data *priv; struct mlxreg_hotplug_priv_data *priv;
struct i2c_adapter *deferred_adap;
int err; int err;
pdata = dev_get_platdata(&pdev->dev); pdata = dev_get_platdata(&pdev->dev);
...@@ -558,6 +559,12 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev) ...@@ -558,6 +559,12 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
/* Defer probing if the necessary adapter is not configured yet. */
deferred_adap = i2c_get_adapter(pdata->deferred_nr);
if (!deferred_adap)
return -EPROBE_DEFER;
i2c_put_adapter(deferred_adap);
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
......
...@@ -697,6 +697,8 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) ...@@ -697,6 +697,8 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_default_channels[i]); ARRAY_SIZE(mlxplat_default_channels[i]);
} }
mlxplat_hotplug = &mlxplat_mlxcpld_default_data; mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1; return 1;
}; };
...@@ -711,6 +713,8 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi) ...@@ -711,6 +713,8 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_msn21xx_channels); ARRAY_SIZE(mlxplat_msn21xx_channels);
} }
mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data; mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1; return 1;
}; };
...@@ -725,6 +729,8 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi) ...@@ -725,6 +729,8 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_msn21xx_channels); ARRAY_SIZE(mlxplat_msn21xx_channels);
} }
mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data; mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1; return 1;
}; };
...@@ -739,6 +745,8 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) ...@@ -739,6 +745,8 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_msn21xx_channels); ARRAY_SIZE(mlxplat_msn21xx_channels);
} }
mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1; return 1;
}; };
...@@ -753,6 +761,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) ...@@ -753,6 +761,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
ARRAY_SIZE(mlxplat_msn21xx_channels); ARRAY_SIZE(mlxplat_msn21xx_channels);
} }
mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
return 1; return 1;
}; };
......
...@@ -129,6 +129,7 @@ struct mlxreg_core_platform_data { ...@@ -129,6 +129,7 @@ struct mlxreg_core_platform_data {
* @mask: top aggregation interrupt common mask; * @mask: top aggregation interrupt common mask;
* @cell_low: location of low aggregation interrupt register; * @cell_low: location of low aggregation interrupt register;
* @mask_low: low aggregation interrupt common mask; * @mask_low: low aggregation interrupt common mask;
* @deferred_nr: I2C adapter number must be exist prior probing execution;
*/ */
struct mlxreg_core_hotplug_platform_data { struct mlxreg_core_hotplug_platform_data {
struct mlxreg_core_item *items; struct mlxreg_core_item *items;
...@@ -139,6 +140,7 @@ struct mlxreg_core_hotplug_platform_data { ...@@ -139,6 +140,7 @@ struct mlxreg_core_hotplug_platform_data {
u32 mask; u32 mask;
u32 cell_low; u32 cell_low;
u32 mask_low; u32 mask_low;
int deferred_nr;
}; };
#endif /* __LINUX_PLATFORM_DATA_MLXREG_H */ #endif /* __LINUX_PLATFORM_DATA_MLXREG_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment