@@ -51,6 +51,8 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver");
51
51
MODULE_LICENSE ("Dual BSD/GPL" );
52
52
MODULE_VERSION (DRV_VERSION );
53
53
54
+ struct workqueue_struct * mlx4_wq ;
55
+
54
56
#ifdef CONFIG_MLX4_DEBUG
55
57
56
58
int mlx4_debug_level = 0 ;
@@ -98,24 +100,23 @@ module_param_named(use_prio, use_prio, bool, 0444);
98
100
MODULE_PARM_DESC (use_prio , "Enable steering by VLAN priority on ETH ports "
99
101
"(0/1, default 0)" );
100
102
101
- static int mlx4_check_port_params (struct mlx4_dev * dev ,
102
- enum mlx4_port_type * port_type )
103
+ int mlx4_check_port_params (struct mlx4_dev * dev ,
104
+ enum mlx4_port_type * port_type )
103
105
{
104
106
int i ;
105
107
106
108
for (i = 0 ; i < dev -> caps .num_ports - 1 ; i ++ ) {
107
- if (port_type [i ] != port_type [i + 1 ] &&
108
- !(dev -> caps .flags & MLX4_DEV_CAP_FLAG_DPDP )) {
109
- mlx4_err (dev , "Only same port types supported "
110
- "on this HCA, aborting.\n" );
111
- return - EINVAL ;
109
+ if (port_type [i ] != port_type [i + 1 ]) {
110
+ if (!(dev -> caps .flags & MLX4_DEV_CAP_FLAG_DPDP )) {
111
+ mlx4_err (dev , "Only same port types supported "
112
+ "on this HCA, aborting.\n" );
113
+ return - EINVAL ;
114
+ }
115
+ if (port_type [i ] == MLX4_PORT_TYPE_ETH &&
116
+ port_type [i + 1 ] == MLX4_PORT_TYPE_IB )
117
+ return - EINVAL ;
112
118
}
113
119
}
114
- if ((port_type [0 ] == MLX4_PORT_TYPE_ETH ) &&
115
- (port_type [1 ] == MLX4_PORT_TYPE_IB )) {
116
- mlx4_err (dev , "eth-ib configuration is not supported.\n" );
117
- return - EINVAL ;
118
- }
119
120
120
121
for (i = 0 ; i < dev -> caps .num_ports ; i ++ ) {
121
122
if (!(port_type [i ] & dev -> caps .supported_type [i + 1 ])) {
@@ -225,6 +226,9 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
225
226
dev -> caps .port_type [i ] = MLX4_PORT_TYPE_IB ;
226
227
else
227
228
dev -> caps .port_type [i ] = MLX4_PORT_TYPE_ETH ;
229
+ dev -> caps .possible_type [i ] = dev -> caps .port_type [i ];
230
+ mlx4_priv (dev )-> sense .sense_allowed [i ] =
231
+ dev -> caps .supported_type [i ] == MLX4_PORT_TYPE_AUTO ;
228
232
229
233
if (dev -> caps .log_num_macs > dev_cap -> log_max_macs [i ]) {
230
234
dev -> caps .log_num_macs = dev_cap -> log_max_macs [i ];
@@ -263,14 +267,16 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
263
267
* Change the port configuration of the device.
264
268
* Every user of this function must hold the port mutex.
265
269
*/
266
- static int mlx4_change_port_types (struct mlx4_dev * dev ,
267
- enum mlx4_port_type * port_types )
270
+ int mlx4_change_port_types (struct mlx4_dev * dev ,
271
+ enum mlx4_port_type * port_types )
268
272
{
269
273
int err = 0 ;
270
274
int change = 0 ;
271
275
int port ;
272
276
273
277
for (port = 0 ; port < dev -> caps .num_ports ; port ++ ) {
278
+ /* Change the port type only if the new type is different
279
+ * from the current, and not set to Auto */
274
280
if (port_types [port ] != dev -> caps .port_type [port + 1 ]) {
275
281
change = 1 ;
276
282
dev -> caps .port_type [port + 1 ] = port_types [port ];
@@ -302,10 +308,17 @@ static ssize_t show_port_type(struct device *dev,
302
308
struct mlx4_port_info * info = container_of (attr , struct mlx4_port_info ,
303
309
port_attr );
304
310
struct mlx4_dev * mdev = info -> dev ;
311
+ char type [8 ];
312
+
313
+ sprintf (type , "%s" ,
314
+ (mdev -> caps .port_type [info -> port ] == MLX4_PORT_TYPE_IB ) ?
315
+ "ib" : "eth" );
316
+ if (mdev -> caps .possible_type [info -> port ] == MLX4_PORT_TYPE_AUTO )
317
+ sprintf (buf , "auto (%s)\n" , type );
318
+ else
319
+ sprintf (buf , "%s\n" , type );
305
320
306
- return sprintf (buf , "%s\n" ,
307
- mdev -> caps .port_type [info -> port ] == MLX4_PORT_TYPE_IB ?
308
- "ib" : "eth" );
321
+ return strlen (buf );
309
322
}
310
323
311
324
static ssize_t set_port_type (struct device * dev ,
@@ -317,33 +330,64 @@ static ssize_t set_port_type(struct device *dev,
317
330
struct mlx4_dev * mdev = info -> dev ;
318
331
struct mlx4_priv * priv = mlx4_priv (mdev );
319
332
enum mlx4_port_type types [MLX4_MAX_PORTS ];
333
+ enum mlx4_port_type new_types [MLX4_MAX_PORTS ];
320
334
int i ;
321
335
int err = 0 ;
322
336
323
337
if (!strcmp (buf , "ib\n" ))
324
338
info -> tmp_type = MLX4_PORT_TYPE_IB ;
325
339
else if (!strcmp (buf , "eth\n" ))
326
340
info -> tmp_type = MLX4_PORT_TYPE_ETH ;
341
+ else if (!strcmp (buf , "auto\n" ))
342
+ info -> tmp_type = MLX4_PORT_TYPE_AUTO ;
327
343
else {
328
344
mlx4_err (mdev , "%s is not supported port type\n" , buf );
329
345
return - EINVAL ;
330
346
}
331
347
348
+ mlx4_stop_sense (mdev );
332
349
mutex_lock (& priv -> port_mutex );
333
- for (i = 0 ; i < mdev -> caps .num_ports ; i ++ )
350
+ /* Possible type is always the one that was delivered */
351
+ mdev -> caps .possible_type [info -> port ] = info -> tmp_type ;
352
+
353
+ for (i = 0 ; i < mdev -> caps .num_ports ; i ++ ) {
334
354
types [i ] = priv -> port [i + 1 ].tmp_type ? priv -> port [i + 1 ].tmp_type :
335
- mdev -> caps .port_type [i + 1 ];
355
+ mdev -> caps .possible_type [i + 1 ];
356
+ if (types [i ] == MLX4_PORT_TYPE_AUTO )
357
+ types [i ] = mdev -> caps .port_type [i + 1 ];
358
+ }
336
359
337
- err = mlx4_check_port_params (mdev , types );
360
+ if (!(mdev -> caps .flags & MLX4_DEV_CAP_FLAG_DPDP )) {
361
+ for (i = 1 ; i <= mdev -> caps .num_ports ; i ++ ) {
362
+ if (mdev -> caps .possible_type [i ] == MLX4_PORT_TYPE_AUTO ) {
363
+ mdev -> caps .possible_type [i ] = mdev -> caps .port_type [i ];
364
+ err = - EINVAL ;
365
+ }
366
+ }
367
+ }
368
+ if (err ) {
369
+ mlx4_err (mdev , "Auto sensing is not supported on this HCA. "
370
+ "Set only 'eth' or 'ib' for both ports "
371
+ "(should be the same)\n" );
372
+ goto out ;
373
+ }
374
+
375
+ mlx4_do_sense_ports (mdev , new_types , types );
376
+
377
+ err = mlx4_check_port_params (mdev , new_types );
338
378
if (err )
339
379
goto out ;
340
380
341
- for (i = 1 ; i <= mdev -> caps .num_ports ; i ++ )
342
- priv -> port [i ].tmp_type = 0 ;
381
+ /* We are about to apply the changes after the configuration
382
+ * was verified, no need to remember the temporary types
383
+ * any more */
384
+ for (i = 0 ; i < mdev -> caps .num_ports ; i ++ )
385
+ priv -> port [i + 1 ].tmp_type = 0 ;
343
386
344
- err = mlx4_change_port_types (mdev , types );
387
+ err = mlx4_change_port_types (mdev , new_types );
345
388
346
389
out :
390
+ mlx4_start_sense (mdev );
347
391
mutex_unlock (& priv -> port_mutex );
348
392
return err ? err : count ;
349
393
}
@@ -1117,6 +1161,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
1117
1161
if (err )
1118
1162
goto err_port ;
1119
1163
1164
+ mlx4_sense_init (dev );
1165
+ mlx4_start_sense (dev );
1166
+
1120
1167
pci_set_drvdata (pdev , dev );
1121
1168
1122
1169
return 0 ;
@@ -1182,6 +1229,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
1182
1229
int p ;
1183
1230
1184
1231
if (dev ) {
1232
+ mlx4_stop_sense (dev );
1185
1233
mlx4_unregister_device (dev );
1186
1234
1187
1235
for (p = 1 ; p <= dev -> caps .num_ports ; p ++ ) {
@@ -1266,9 +1314,11 @@ static int __init mlx4_init(void)
1266
1314
if (mlx4_verify_params ())
1267
1315
return - EINVAL ;
1268
1316
1269
- ret = mlx4_catas_init ();
1270
- if (ret )
1271
- return ret ;
1317
+ mlx4_catas_init ();
1318
+
1319
+ mlx4_wq = create_singlethread_workqueue ("mlx4" );
1320
+ if (!mlx4_wq )
1321
+ return - ENOMEM ;
1272
1322
1273
1323
ret = pci_register_driver (& mlx4_driver );
1274
1324
return ret < 0 ? ret : 0 ;
@@ -1277,7 +1327,7 @@ static int __init mlx4_init(void)
1277
1327
static void __exit mlx4_cleanup (void )
1278
1328
{
1279
1329
pci_unregister_driver (& mlx4_driver );
1280
- mlx4_catas_cleanup ( );
1330
+ destroy_workqueue ( mlx4_wq );
1281
1331
}
1282
1332
1283
1333
module_init (mlx4_init );
0 commit comments