@@ -1201,6 +1201,298 @@ static const struct file_operations mbox_debugfs_fops = {
1201
1201
.write = mbox_write
1202
1202
};
1203
1203
1204
+ static int mps_trc_show (struct seq_file * seq , void * v )
1205
+ {
1206
+ int enabled , i ;
1207
+ struct trace_params tp ;
1208
+ unsigned int trcidx = (uintptr_t )seq -> private & 3 ;
1209
+ struct adapter * adap = seq -> private - trcidx ;
1210
+
1211
+ t4_get_trace_filter (adap , & tp , trcidx , & enabled );
1212
+ if (!enabled ) {
1213
+ seq_puts (seq , "tracer is disabled\n" );
1214
+ return 0 ;
1215
+ }
1216
+
1217
+ if (tp .skip_ofst * 8 >= TRACE_LEN ) {
1218
+ dev_err (adap -> pdev_dev , "illegal trace pattern skip offset\n" );
1219
+ return - EINVAL ;
1220
+ }
1221
+ if (tp .port < 8 ) {
1222
+ i = adap -> chan_map [tp .port & 3 ];
1223
+ if (i >= MAX_NPORTS ) {
1224
+ dev_err (adap -> pdev_dev , "tracer %u is assigned "
1225
+ "to non-existing port\n" , trcidx );
1226
+ return - EINVAL ;
1227
+ }
1228
+ seq_printf (seq , "tracer is capturing %s %s, " ,
1229
+ adap -> port [i ]-> name , tp .port < 4 ? "Rx" : "Tx" );
1230
+ } else
1231
+ seq_printf (seq , "tracer is capturing loopback %d, " ,
1232
+ tp .port - 8 );
1233
+ seq_printf (seq , "snap length: %u, min length: %u\n" , tp .snap_len ,
1234
+ tp .min_len );
1235
+ seq_printf (seq , "packets captured %smatch filter\n" ,
1236
+ tp .invert ? "do not " : "" );
1237
+
1238
+ if (tp .skip_ofst ) {
1239
+ seq_puts (seq , "filter pattern: " );
1240
+ for (i = 0 ; i < tp .skip_ofst * 2 ; i += 2 )
1241
+ seq_printf (seq , "%08x%08x" , tp .data [i ], tp .data [i + 1 ]);
1242
+ seq_putc (seq , '/' );
1243
+ for (i = 0 ; i < tp .skip_ofst * 2 ; i += 2 )
1244
+ seq_printf (seq , "%08x%08x" , tp .mask [i ], tp .mask [i + 1 ]);
1245
+ seq_puts (seq , "@0\n" );
1246
+ }
1247
+
1248
+ seq_puts (seq , "filter pattern: " );
1249
+ for (i = tp .skip_ofst * 2 ; i < TRACE_LEN / 4 ; i += 2 )
1250
+ seq_printf (seq , "%08x%08x" , tp .data [i ], tp .data [i + 1 ]);
1251
+ seq_putc (seq , '/' );
1252
+ for (i = tp .skip_ofst * 2 ; i < TRACE_LEN / 4 ; i += 2 )
1253
+ seq_printf (seq , "%08x%08x" , tp .mask [i ], tp .mask [i + 1 ]);
1254
+ seq_printf (seq , "@%u\n" , (tp .skip_ofst + tp .skip_len ) * 8 );
1255
+ return 0 ;
1256
+ }
1257
+
1258
+ static int mps_trc_open (struct inode * inode , struct file * file )
1259
+ {
1260
+ return single_open (file , mps_trc_show , inode -> i_private );
1261
+ }
1262
+
1263
+ static unsigned int xdigit2int (unsigned char c )
1264
+ {
1265
+ return isdigit (c ) ? c - '0' : tolower (c ) - 'a' + 10 ;
1266
+ }
1267
+
1268
+ #define TRC_PORT_NONE 0xff
1269
+ #define TRC_RSS_ENABLE 0x33
1270
+ #define TRC_RSS_DISABLE 0x13
1271
+
1272
+ /* Set an MPS trace filter. Syntax is:
1273
+ *
1274
+ * disable
1275
+ *
1276
+ * to disable tracing, or
1277
+ *
1278
+ * interface qid=<qid no> [snaplen=<val>] [minlen=<val>] [not] [<pattern>]...
1279
+ *
1280
+ * where interface is one of rxN, txN, or loopbackN, N = 0..3, qid can be one
1281
+ * of the NIC's response qid obtained from sge_qinfo and pattern has the form
1282
+ *
1283
+ * <pattern data>[/<pattern mask>][@<anchor>]
1284
+ *
1285
+ * Up to 2 filter patterns can be specified. If 2 are supplied the first one
1286
+ * must be anchored at 0. An omited mask is taken as a mask of 1s, an omitted
1287
+ * anchor is taken as 0.
1288
+ */
1289
+ static ssize_t mps_trc_write (struct file * file , const char __user * buf ,
1290
+ size_t count , loff_t * pos )
1291
+ {
1292
+ int i , j , enable , ret ;
1293
+ u32 * data , * mask ;
1294
+ struct trace_params tp ;
1295
+ const struct inode * ino ;
1296
+ unsigned int trcidx ;
1297
+ char * s , * p , * word , * end ;
1298
+ struct adapter * adap ;
1299
+
1300
+ ino = file_inode (file );
1301
+ trcidx = (uintptr_t )ino -> i_private & 3 ;
1302
+ adap = ino -> i_private - trcidx ;
1303
+
1304
+ /* Don't accept input more than 1K, can't be anything valid except lots
1305
+ * of whitespace. Well, use less.
1306
+ */
1307
+ if (count > 1024 )
1308
+ return - EFBIG ;
1309
+ p = s = kzalloc (count + 1 , GFP_USER );
1310
+ if (!s )
1311
+ return - ENOMEM ;
1312
+ if (copy_from_user (s , buf , count )) {
1313
+ count = - EFAULT ;
1314
+ goto out ;
1315
+ }
1316
+
1317
+ if (s [count - 1 ] == '\n' )
1318
+ s [count - 1 ] = '\0' ;
1319
+
1320
+ enable = strcmp ("disable" , s ) != 0 ;
1321
+ if (!enable )
1322
+ goto apply ;
1323
+
1324
+ /* enable or disable trace multi rss filter */
1325
+ if (adap -> trace_rss )
1326
+ t4_write_reg (adap , MPS_TRC_CFG_A , TRC_RSS_ENABLE );
1327
+ else
1328
+ t4_write_reg (adap , MPS_TRC_CFG_A , TRC_RSS_DISABLE );
1329
+
1330
+ memset (& tp , 0 , sizeof (tp ));
1331
+ tp .port = TRC_PORT_NONE ;
1332
+ i = 0 ; /* counts pattern nibbles */
1333
+
1334
+ while (p ) {
1335
+ while (isspace (* p ))
1336
+ p ++ ;
1337
+ word = strsep (& p , " " );
1338
+ if (!* word )
1339
+ break ;
1340
+
1341
+ if (!strncmp (word , "qid=" , 4 )) {
1342
+ end = (char * )word + 4 ;
1343
+ ret = kstrtoul (end , 10 , (unsigned long * )& j );
1344
+ if (ret )
1345
+ goto out ;
1346
+ if (!adap -> trace_rss ) {
1347
+ t4_write_reg (adap , MPS_T5_TRC_RSS_CONTROL_A , j );
1348
+ continue ;
1349
+ }
1350
+
1351
+ switch (trcidx ) {
1352
+ case 0 :
1353
+ t4_write_reg (adap , MPS_TRC_RSS_CONTROL_A , j );
1354
+ break ;
1355
+ case 1 :
1356
+ t4_write_reg (adap ,
1357
+ MPS_TRC_FILTER1_RSS_CONTROL_A , j );
1358
+ break ;
1359
+ case 2 :
1360
+ t4_write_reg (adap ,
1361
+ MPS_TRC_FILTER2_RSS_CONTROL_A , j );
1362
+ break ;
1363
+ case 3 :
1364
+ t4_write_reg (adap ,
1365
+ MPS_TRC_FILTER3_RSS_CONTROL_A , j );
1366
+ break ;
1367
+ }
1368
+ continue ;
1369
+ }
1370
+ if (!strncmp (word , "snaplen=" , 8 )) {
1371
+ end = (char * )word + 8 ;
1372
+ ret = kstrtoul (end , 10 , (unsigned long * )& j );
1373
+ if (ret || j > 9600 ) {
1374
+ inval : count = - EINVAL ;
1375
+ goto out ;
1376
+ }
1377
+ tp .snap_len = j ;
1378
+ continue ;
1379
+ }
1380
+ if (!strncmp (word , "minlen=" , 7 )) {
1381
+ end = (char * )word + 7 ;
1382
+ ret = kstrtoul (end , 10 , (unsigned long * )& j );
1383
+ if (ret || j > TFMINPKTSIZE_M )
1384
+ goto inval ;
1385
+ tp .min_len = j ;
1386
+ continue ;
1387
+ }
1388
+ if (!strcmp (word , "not" )) {
1389
+ tp .invert = !tp .invert ;
1390
+ continue ;
1391
+ }
1392
+ if (!strncmp (word , "loopback" , 8 ) && tp .port == TRC_PORT_NONE ) {
1393
+ if (word [8 ] < '0' || word [8 ] > '3' || word [9 ])
1394
+ goto inval ;
1395
+ tp .port = word [8 ] - '0' + 8 ;
1396
+ continue ;
1397
+ }
1398
+ if (!strncmp (word , "tx" , 2 ) && tp .port == TRC_PORT_NONE ) {
1399
+ if (word [2 ] < '0' || word [2 ] > '3' || word [3 ])
1400
+ goto inval ;
1401
+ tp .port = word [2 ] - '0' + 4 ;
1402
+ if (adap -> chan_map [tp .port & 3 ] >= MAX_NPORTS )
1403
+ goto inval ;
1404
+ continue ;
1405
+ }
1406
+ if (!strncmp (word , "rx" , 2 ) && tp .port == TRC_PORT_NONE ) {
1407
+ if (word [2 ] < '0' || word [2 ] > '3' || word [3 ])
1408
+ goto inval ;
1409
+ tp .port = word [2 ] - '0' ;
1410
+ if (adap -> chan_map [tp .port ] >= MAX_NPORTS )
1411
+ goto inval ;
1412
+ continue ;
1413
+ }
1414
+ if (!isxdigit (* word ))
1415
+ goto inval ;
1416
+
1417
+ /* we have found a trace pattern */
1418
+ if (i ) { /* split pattern */
1419
+ if (tp .skip_len ) /* too many splits */
1420
+ goto inval ;
1421
+ tp .skip_ofst = i / 16 ;
1422
+ }
1423
+
1424
+ data = & tp .data [i / 8 ];
1425
+ mask = & tp .mask [i / 8 ];
1426
+ j = i ;
1427
+
1428
+ while (isxdigit (* word )) {
1429
+ if (i >= TRACE_LEN * 2 ) {
1430
+ count = - EFBIG ;
1431
+ goto out ;
1432
+ }
1433
+ * data = (* data << 4 ) + xdigit2int (* word ++ );
1434
+ if (++ i % 8 == 0 )
1435
+ data ++ ;
1436
+ }
1437
+ if (* word == '/' ) {
1438
+ word ++ ;
1439
+ while (isxdigit (* word )) {
1440
+ if (j >= i ) /* mask longer than data */
1441
+ goto inval ;
1442
+ * mask = (* mask << 4 ) + xdigit2int (* word ++ );
1443
+ if (++ j % 8 == 0 )
1444
+ mask ++ ;
1445
+ }
1446
+ if (i != j ) /* mask shorter than data */
1447
+ goto inval ;
1448
+ } else { /* no mask, use all 1s */
1449
+ for ( ; i - j >= 8 ; j += 8 )
1450
+ * mask ++ = 0xffffffff ;
1451
+ if (i % 8 )
1452
+ * mask = (1 << (i % 8 ) * 4 ) - 1 ;
1453
+ }
1454
+ if (* word == '@' ) {
1455
+ end = (char * )word + 1 ;
1456
+ ret = kstrtoul (end , 10 , (unsigned long * )& j );
1457
+ if (* end && * end != '\n' )
1458
+ goto inval ;
1459
+ if (j & 7 ) /* doesn't start at multiple of 8 */
1460
+ goto inval ;
1461
+ j /= 8 ;
1462
+ if (j < tp .skip_ofst ) /* overlaps earlier pattern */
1463
+ goto inval ;
1464
+ if (j - tp .skip_ofst > 31 ) /* skip too big */
1465
+ goto inval ;
1466
+ tp .skip_len = j - tp .skip_ofst ;
1467
+ }
1468
+ if (i % 8 ) {
1469
+ * data <<= (8 - i % 8 ) * 4 ;
1470
+ * mask <<= (8 - i % 8 ) * 4 ;
1471
+ i = (i + 15 ) & ~15 ; /* 8-byte align */
1472
+ }
1473
+ }
1474
+
1475
+ if (tp .port == TRC_PORT_NONE )
1476
+ goto inval ;
1477
+
1478
+ apply :
1479
+ i = t4_set_trace_filter (adap , & tp , trcidx , enable );
1480
+ if (i )
1481
+ count = i ;
1482
+ out :
1483
+ kfree (s );
1484
+ return count ;
1485
+ }
1486
+
1487
+ static const struct file_operations mps_trc_debugfs_fops = {
1488
+ .owner = THIS_MODULE ,
1489
+ .open = mps_trc_open ,
1490
+ .read = seq_read ,
1491
+ .llseek = seq_lseek ,
1492
+ .release = single_release ,
1493
+ .write = mps_trc_write
1494
+ };
1495
+
1204
1496
static ssize_t flash_read (struct file * file , char __user * buf , size_t count ,
1205
1497
loff_t * ppos )
1206
1498
{
@@ -2708,6 +3000,10 @@ int t4_setup_debugfs(struct adapter *adap)
2708
3000
{ "mbox5" , & mbox_debugfs_fops , S_IRUSR | S_IWUSR , 5 },
2709
3001
{ "mbox6" , & mbox_debugfs_fops , S_IRUSR | S_IWUSR , 6 },
2710
3002
{ "mbox7" , & mbox_debugfs_fops , S_IRUSR | S_IWUSR , 7 },
3003
+ { "trace0" , & mps_trc_debugfs_fops , S_IRUSR | S_IWUSR , 0 },
3004
+ { "trace1" , & mps_trc_debugfs_fops , S_IRUSR | S_IWUSR , 1 },
3005
+ { "trace2" , & mps_trc_debugfs_fops , S_IRUSR | S_IWUSR , 2 },
3006
+ { "trace3" , & mps_trc_debugfs_fops , S_IRUSR | S_IWUSR , 3 },
2711
3007
{ "l2t" , & t4_l2t_fops , S_IRUSR , 0 },
2712
3008
{ "mps_tcam" , & mps_tcam_debugfs_fops , S_IRUSR , 0 },
2713
3009
{ "rss" , & rss_debugfs_fops , S_IRUSR , 0 },
@@ -2789,6 +3085,8 @@ int t4_setup_debugfs(struct adapter *adap)
2789
3085
& flash_debugfs_fops , adap -> params .sf_size );
2790
3086
debugfs_create_bool ("use_backdoor" , S_IWUSR | S_IRUSR ,
2791
3087
adap -> debugfs_root , & adap -> use_bd );
3088
+ debugfs_create_bool ("trace_rss" , S_IWUSR | S_IRUSR ,
3089
+ adap -> debugfs_root , & adap -> trace_rss );
2792
3090
2793
3091
return 0 ;
2794
3092
}
0 commit comments