2828/* ASIC good health mask. */
2929#define MLXREG_HOTPLUG_GOOD_HEALTH_MASK 0x02
3030
31- #define MLXREG_HOTPLUG_ATTRS_MAX 24
31+ #define MLXREG_HOTPLUG_ATTRS_MAX 128
3232#define MLXREG_HOTPLUG_NOT_ASSERT 3
3333
3434/**
@@ -89,9 +89,20 @@ mlxreg_hotplug_udev_event_send(struct kobject *kobj,
8989 return kobject_uevent_env (kobj , KOBJ_CHANGE , mlxreg_hotplug_udev_envp );
9090}
9191
92+ static void
93+ mlxreg_hotplug_pdata_export (void * pdata , void * regmap )
94+ {
95+ struct mlxreg_core_hotplug_platform_data * dev_pdata = pdata ;
96+
97+ /* Export regmap to underlying device. */
98+ dev_pdata -> regmap = regmap ;
99+ }
100+
92101static int mlxreg_hotplug_device_create (struct mlxreg_hotplug_priv_data * priv ,
93- struct mlxreg_core_data * data )
102+ struct mlxreg_core_data * data ,
103+ enum mlxreg_hotplug_kind kind )
94104{
105+ struct i2c_board_info * brdinfo = data -> hpdev .brdinfo ;
95106 struct mlxreg_core_hotplug_platform_data * pdata ;
96107 struct i2c_client * client ;
97108
@@ -106,46 +117,88 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
106117 return 0 ;
107118
108119 pdata = dev_get_platdata (& priv -> pdev -> dev );
109- data -> hpdev .adapter = i2c_get_adapter (data -> hpdev .nr +
110- pdata -> shift_nr );
111- if (!data -> hpdev .adapter ) {
112- dev_err (priv -> dev , "Failed to get adapter for bus %d\n" ,
113- data -> hpdev .nr + pdata -> shift_nr );
114- return - EFAULT ;
115- }
120+ switch (data -> hpdev .action ) {
121+ case MLXREG_HOTPLUG_DEVICE_DEFAULT_ACTION :
122+ data -> hpdev .adapter = i2c_get_adapter (data -> hpdev .nr +
123+ pdata -> shift_nr );
124+ if (!data -> hpdev .adapter ) {
125+ dev_err (priv -> dev , "Failed to get adapter for bus %d\n" ,
126+ data -> hpdev .nr + pdata -> shift_nr );
127+ return - EFAULT ;
128+ }
116129
117- client = i2c_new_client_device (data -> hpdev .adapter ,
118- data -> hpdev .brdinfo );
119- if (IS_ERR (client )) {
120- dev_err (priv -> dev , "Failed to create client %s at bus %d at addr 0x%02x\n" ,
121- data -> hpdev .brdinfo -> type , data -> hpdev .nr +
122- pdata -> shift_nr , data -> hpdev .brdinfo -> addr );
130+ /* Export platform data to underlying device. */
131+ if (brdinfo -> platform_data )
132+ mlxreg_hotplug_pdata_export (brdinfo -> platform_data , pdata -> regmap );
123133
124- i2c_put_adapter (data -> hpdev .adapter );
125- data -> hpdev .adapter = NULL ;
126- return PTR_ERR (client );
134+ client = i2c_new_client_device (data -> hpdev .adapter ,
135+ brdinfo );
136+ if (IS_ERR (client )) {
137+ dev_err (priv -> dev , "Failed to create client %s at bus %d at addr 0x%02x\n" ,
138+ brdinfo -> type , data -> hpdev .nr +
139+ pdata -> shift_nr , brdinfo -> addr );
140+
141+ i2c_put_adapter (data -> hpdev .adapter );
142+ data -> hpdev .adapter = NULL ;
143+ return PTR_ERR (client );
144+ }
145+
146+ data -> hpdev .client = client ;
147+ break ;
148+ case MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION :
149+ /* Export platform data to underlying device. */
150+ if (data -> hpdev .brdinfo && data -> hpdev .brdinfo -> platform_data )
151+ mlxreg_hotplug_pdata_export (data -> hpdev .brdinfo -> platform_data ,
152+ pdata -> regmap );
153+ /* Pass parent hotplug device handle to underlying device. */
154+ data -> notifier = data -> hpdev .notifier ;
155+ data -> hpdev .pdev = platform_device_register_resndata (& priv -> pdev -> dev ,
156+ brdinfo -> type ,
157+ data -> hpdev .nr ,
158+ NULL , 0 , data ,
159+ sizeof (* data ));
160+ if (IS_ERR (data -> hpdev .pdev ))
161+ return PTR_ERR (data -> hpdev .pdev );
162+
163+ break ;
164+ default :
165+ break ;
127166 }
128167
129- data -> hpdev .client = client ;
168+ if (data -> hpdev .notifier && data -> hpdev .notifier -> user_handler )
169+ return data -> hpdev .notifier -> user_handler (data -> hpdev .notifier -> handle , kind , 1 );
130170
131171 return 0 ;
132172}
133173
134174static void
135175mlxreg_hotplug_device_destroy (struct mlxreg_hotplug_priv_data * priv ,
136- struct mlxreg_core_data * data )
176+ struct mlxreg_core_data * data ,
177+ enum mlxreg_hotplug_kind kind )
137178{
138179 /* Notify user by sending hwmon uevent. */
139180 mlxreg_hotplug_udev_event_send (& priv -> hwmon -> kobj , data , false);
181+ if (data -> hpdev .notifier && data -> hpdev .notifier -> user_handler )
182+ data -> hpdev .notifier -> user_handler (data -> hpdev .notifier -> handle , kind , 0 );
183+
184+ switch (data -> hpdev .action ) {
185+ case MLXREG_HOTPLUG_DEVICE_DEFAULT_ACTION :
186+ if (data -> hpdev .client ) {
187+ i2c_unregister_device (data -> hpdev .client );
188+ data -> hpdev .client = NULL ;
189+ }
140190
141- if (data -> hpdev .client ) {
142- i2c_unregister_device (data -> hpdev .client );
143- data -> hpdev .client = NULL ;
144- }
145-
146- if (data -> hpdev .adapter ) {
147- i2c_put_adapter (data -> hpdev .adapter );
148- data -> hpdev .adapter = NULL ;
191+ if (data -> hpdev .adapter ) {
192+ i2c_put_adapter (data -> hpdev .adapter );
193+ data -> hpdev .adapter = NULL ;
194+ }
195+ break ;
196+ case MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION :
197+ if (data -> hpdev .pdev )
198+ platform_device_unregister (data -> hpdev .pdev );
199+ break ;
200+ default :
201+ break ;
149202 }
150203}
151204
@@ -317,14 +370,14 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
317370 data = item -> data + bit ;
318371 if (regval & BIT (bit )) {
319372 if (item -> inversed )
320- mlxreg_hotplug_device_destroy (priv , data );
373+ mlxreg_hotplug_device_destroy (priv , data , item -> kind );
321374 else
322- mlxreg_hotplug_device_create (priv , data );
375+ mlxreg_hotplug_device_create (priv , data , item -> kind );
323376 } else {
324377 if (item -> inversed )
325- mlxreg_hotplug_device_create (priv , data );
378+ mlxreg_hotplug_device_create (priv , data , item -> kind );
326379 else
327- mlxreg_hotplug_device_destroy (priv , data );
380+ mlxreg_hotplug_device_destroy (priv , data , item -> kind );
328381 }
329382 }
330383
@@ -381,7 +434,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
381434 * ASIC is in steady state. Connect associated
382435 * device, if configured.
383436 */
384- mlxreg_hotplug_device_create (priv , data );
437+ mlxreg_hotplug_device_create (priv , data , item -> kind );
385438 data -> attached = true;
386439 }
387440 } else {
@@ -391,7 +444,7 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
391444 * in steady state. Disconnect associated
392445 * device, if it has been connected.
393446 */
394- mlxreg_hotplug_device_destroy (priv , data );
447+ mlxreg_hotplug_device_destroy (priv , data , item -> kind );
395448 data -> attached = false;
396449 data -> health_cntr = 0 ;
397450 }
@@ -630,7 +683,7 @@ static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
630683 /* Remove all the attached devices in group. */
631684 count = item -> count ;
632685 for (j = 0 ; j < count ; j ++ , data ++ )
633- mlxreg_hotplug_device_destroy (priv , data );
686+ mlxreg_hotplug_device_destroy (priv , data , item -> kind );
634687 }
635688}
636689
0 commit comments