aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c345
1 files changed, 4 insertions, 341 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 3c0a8f825b63..5b90fcf96265 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -900,27 +900,6 @@ static int gfar_check_filer_hardware(struct gfar_private *priv)
900 return 0; 900 return 0;
901} 901}
902 902
903static int gfar_comp_asc(const void *a, const void *b)
904{
905 return memcmp(a, b, 4);
906}
907
908static int gfar_comp_desc(const void *a, const void *b)
909{
910 return -memcmp(a, b, 4);
911}
912
913static void gfar_swap(void *a, void *b, int size)
914{
915 u32 *_a = a;
916 u32 *_b = b;
917
918 swap(_a[0], _b[0]);
919 swap(_a[1], _b[1]);
920 swap(_a[2], _b[2]);
921 swap(_a[3], _b[3]);
922}
923
924/* Write a mask to filer cache */ 903/* Write a mask to filer cache */
925static void gfar_set_mask(u32 mask, struct filer_table *tab) 904static void gfar_set_mask(u32 mask, struct filer_table *tab)
926{ 905{
@@ -1270,310 +1249,6 @@ static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule,
1270 return 0; 1249 return 0;
1271} 1250}
1272 1251
1273/* Copy size filer entries */
1274static void gfar_copy_filer_entries(struct gfar_filer_entry dst[0],
1275 struct gfar_filer_entry src[0], s32 size)
1276{
1277 while (size > 0) {
1278 size--;
1279 dst[size].ctrl = src[size].ctrl;
1280 dst[size].prop = src[size].prop;
1281 }
1282}
1283
1284/* Delete the contents of the filer-table between start and end
1285 * and collapse them
1286 */
1287static int gfar_trim_filer_entries(u32 begin, u32 end, struct filer_table *tab)
1288{
1289 int length;
1290
1291 if (end > MAX_FILER_CACHE_IDX || end < begin)
1292 return -EINVAL;
1293
1294 end++;
1295 length = end - begin;
1296
1297 /* Copy */
1298 while (end < tab->index) {
1299 tab->fe[begin].ctrl = tab->fe[end].ctrl;
1300 tab->fe[begin++].prop = tab->fe[end++].prop;
1301
1302 }
1303 /* Fill up with don't cares */
1304 while (begin < tab->index) {
1305 tab->fe[begin].ctrl = 0x60;
1306 tab->fe[begin].prop = 0xFFFFFFFF;
1307 begin++;
1308 }
1309
1310 tab->index -= length;
1311 return 0;
1312}
1313
1314/* Make space on the wanted location */
1315static int gfar_expand_filer_entries(u32 begin, u32 length,
1316 struct filer_table *tab)
1317{
1318 if (length == 0 || length + tab->index > MAX_FILER_CACHE_IDX ||
1319 begin > MAX_FILER_CACHE_IDX)
1320 return -EINVAL;
1321
1322 gfar_copy_filer_entries(&(tab->fe[begin + length]), &(tab->fe[begin]),
1323 tab->index - length + 1);
1324
1325 tab->index += length;
1326 return 0;
1327}
1328
1329static int gfar_get_next_cluster_start(int start, struct filer_table *tab)
1330{
1331 for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1);
1332 start++) {
1333 if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) ==
1334 (RQFCR_AND | RQFCR_CLE))
1335 return start;
1336 }
1337 return -1;
1338}
1339
1340static int gfar_get_next_cluster_end(int start, struct filer_table *tab)
1341{
1342 for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1);
1343 start++) {
1344 if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) ==
1345 (RQFCR_CLE))
1346 return start;
1347 }
1348 return -1;
1349}
1350
1351/* Uses hardwares clustering option to reduce
1352 * the number of filer table entries
1353 */
1354static void gfar_cluster_filer(struct filer_table *tab)
1355{
1356 s32 i = -1, j, iend, jend;
1357
1358 while ((i = gfar_get_next_cluster_start(++i, tab)) != -1) {
1359 j = i;
1360 while ((j = gfar_get_next_cluster_start(++j, tab)) != -1) {
1361 /* The cluster entries self and the previous one
1362 * (a mask) must be identical!
1363 */
1364 if (tab->fe[i].ctrl != tab->fe[j].ctrl)
1365 break;
1366 if (tab->fe[i].prop != tab->fe[j].prop)
1367 break;
1368 if (tab->fe[i - 1].ctrl != tab->fe[j - 1].ctrl)
1369 break;
1370 if (tab->fe[i - 1].prop != tab->fe[j - 1].prop)
1371 break;
1372 iend = gfar_get_next_cluster_end(i, tab);
1373 jend = gfar_get_next_cluster_end(j, tab);
1374 if (jend == -1 || iend == -1)
1375 break;
1376
1377 /* First we make some free space, where our cluster
1378 * element should be. Then we copy it there and finally
1379 * delete in from its old location.
1380 */
1381 if (gfar_expand_filer_entries(iend, (jend - j), tab) ==
1382 -EINVAL)
1383 break;
1384
1385 gfar_copy_filer_entries(&(tab->fe[iend + 1]),
1386 &(tab->fe[jend + 1]), jend - j);
1387
1388 if (gfar_trim_filer_entries(jend - 1,
1389 jend + (jend - j),
1390 tab) == -EINVAL)
1391 return;
1392
1393 /* Mask out cluster bit */
1394 tab->fe[iend].ctrl &= ~(RQFCR_CLE);
1395 }
1396 }
1397}
1398
1399/* Swaps the masked bits of a1<>a2 and b1<>b2 */
1400static void gfar_swap_bits(struct gfar_filer_entry *a1,
1401 struct gfar_filer_entry *a2,
1402 struct gfar_filer_entry *b1,
1403 struct gfar_filer_entry *b2, u32 mask)
1404{
1405 u32 temp[4];
1406 temp[0] = a1->ctrl & mask;
1407 temp[1] = a2->ctrl & mask;
1408 temp[2] = b1->ctrl & mask;
1409 temp[3] = b2->ctrl & mask;
1410
1411 a1->ctrl &= ~mask;
1412 a2->ctrl &= ~mask;
1413 b1->ctrl &= ~mask;
1414 b2->ctrl &= ~mask;
1415
1416 a1->ctrl |= temp[1];
1417 a2->ctrl |= temp[0];
1418 b1->ctrl |= temp[3];
1419 b2->ctrl |= temp[2];
1420}
1421
1422/* Generate a list consisting of masks values with their start and
1423 * end of validity and block as indicator for parts belonging
1424 * together (glued by ANDs) in mask_table
1425 */
1426static u32 gfar_generate_mask_table(struct gfar_mask_entry *mask_table,
1427 struct filer_table *tab)
1428{
1429 u32 i, and_index = 0, block_index = 1;
1430
1431 for (i = 0; i < tab->index; i++) {
1432
1433 /* LSByte of control = 0 sets a mask */
1434 if (!(tab->fe[i].ctrl & 0xF)) {
1435 mask_table[and_index].mask = tab->fe[i].prop;
1436 mask_table[and_index].start = i;
1437 mask_table[and_index].block = block_index;
1438 if (and_index >= 1)
1439 mask_table[and_index - 1].end = i - 1;
1440 and_index++;
1441 }
1442 /* cluster starts and ends will be separated because they should
1443 * hold their position
1444 */
1445 if (tab->fe[i].ctrl & RQFCR_CLE)
1446 block_index++;
1447 /* A not set AND indicates the end of a depended block */
1448 if (!(tab->fe[i].ctrl & RQFCR_AND))
1449 block_index++;
1450 }
1451
1452 mask_table[and_index - 1].end = i - 1;
1453
1454 return and_index;
1455}
1456
1457/* Sorts the entries of mask_table by the values of the masks.
1458 * Important: The 0xFF80 flags of the first and last entry of a
1459 * block must hold their position (which queue, CLusterEnable, ReJEct,
1460 * AND)
1461 */
1462static void gfar_sort_mask_table(struct gfar_mask_entry *mask_table,
1463 struct filer_table *temp_table, u32 and_index)
1464{
1465 /* Pointer to compare function (_asc or _desc) */
1466 int (*gfar_comp)(const void *, const void *);
1467
1468 u32 i, size = 0, start = 0, prev = 1;
1469 u32 old_first, old_last, new_first, new_last;
1470
1471 gfar_comp = &gfar_comp_desc;
1472
1473 for (i = 0; i < and_index; i++) {
1474 if (prev != mask_table[i].block) {
1475 old_first = mask_table[start].start + 1;
1476 old_last = mask_table[i - 1].end;
1477 sort(mask_table + start, size,
1478 sizeof(struct gfar_mask_entry),
1479 gfar_comp, &gfar_swap);
1480
1481 /* Toggle order for every block. This makes the
1482 * thing more efficient!
1483 */
1484 if (gfar_comp == gfar_comp_desc)
1485 gfar_comp = &gfar_comp_asc;
1486 else
1487 gfar_comp = &gfar_comp_desc;
1488
1489 new_first = mask_table[start].start + 1;
1490 new_last = mask_table[i - 1].end;
1491
1492 gfar_swap_bits(&temp_table->fe[new_first],
1493 &temp_table->fe[old_first],
1494 &temp_table->fe[new_last],
1495 &temp_table->fe[old_last],
1496 RQFCR_QUEUE | RQFCR_CLE |
1497 RQFCR_RJE | RQFCR_AND);
1498
1499 start = i;
1500 size = 0;
1501 }
1502 size++;
1503 prev = mask_table[i].block;
1504 }
1505}
1506
1507/* Reduces the number of masks needed in the filer table to save entries
1508 * This is done by sorting the masks of a depended block. A depended block is
1509 * identified by gluing ANDs or CLE. The sorting order toggles after every
1510 * block. Of course entries in scope of a mask must change their location with
1511 * it.
1512 */
1513static int gfar_optimize_filer_masks(struct filer_table *tab)
1514{
1515 struct filer_table *temp_table;
1516 struct gfar_mask_entry *mask_table;
1517
1518 u32 and_index = 0, previous_mask = 0, i = 0, j = 0, size = 0;
1519 s32 ret = 0;
1520
1521 /* We need a copy of the filer table because
1522 * we want to change its order
1523 */
1524 temp_table = kmemdup(tab, sizeof(*temp_table), GFP_KERNEL);
1525 if (temp_table == NULL)
1526 return -ENOMEM;
1527
1528 mask_table = kcalloc(MAX_FILER_CACHE_IDX / 2 + 1,
1529 sizeof(struct gfar_mask_entry), GFP_KERNEL);
1530
1531 if (mask_table == NULL) {
1532 ret = -ENOMEM;
1533 goto end;
1534 }
1535
1536 and_index = gfar_generate_mask_table(mask_table, tab);
1537
1538 gfar_sort_mask_table(mask_table, temp_table, and_index);
1539
1540 /* Now we can copy the data from our duplicated filer table to
1541 * the real one in the order the mask table says
1542 */
1543 for (i = 0; i < and_index; i++) {
1544 size = mask_table[i].end - mask_table[i].start + 1;
1545 gfar_copy_filer_entries(&(tab->fe[j]),
1546 &(temp_table->fe[mask_table[i].start]), size);
1547 j += size;
1548 }
1549
1550 /* And finally we just have to check for duplicated masks and drop the
1551 * second ones
1552 */
1553 for (i = 0; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
1554 if (tab->fe[i].ctrl == 0x80) {
1555 previous_mask = i++;
1556 break;
1557 }
1558 }
1559 for (; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
1560 if (tab->fe[i].ctrl == 0x80) {
1561 if (tab->fe[i].prop == tab->fe[previous_mask].prop) {
1562 /* Two identical ones found!
1563 * So drop the second one!
1564 */
1565 gfar_trim_filer_entries(i, i, tab);
1566 } else
1567 /* Not identical! */
1568 previous_mask = i;
1569 }
1570 }
1571
1572 kfree(mask_table);
1573end: kfree(temp_table);
1574 return ret;
1575}
1576
1577/* Write the bit-pattern from software's buffer to hardware registers */ 1252/* Write the bit-pattern from software's buffer to hardware registers */
1578static int gfar_write_filer_table(struct gfar_private *priv, 1253static int gfar_write_filer_table(struct gfar_private *priv,
1579 struct filer_table *tab) 1254 struct filer_table *tab)
@@ -1583,11 +1258,10 @@ static int gfar_write_filer_table(struct gfar_private *priv,
1583 return -EBUSY; 1258 return -EBUSY;
1584 1259
1585 /* Fill regular entries */ 1260 /* Fill regular entries */
1586 for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].prop); 1261 for (; i < MAX_FILER_IDX && (tab->fe[i].ctrl | tab->fe[i].prop); i++)
1587 i++)
1588 gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop); 1262 gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop);
1589 /* Fill the rest with fall-troughs */ 1263 /* Fill the rest with fall-troughs */
1590 for (; i < MAX_FILER_IDX - 1; i++) 1264 for (; i < MAX_FILER_IDX; i++)
1591 gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF); 1265 gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF);
1592 /* Last entry must be default accept 1266 /* Last entry must be default accept
1593 * because that's what people expect 1267 * because that's what people expect
@@ -1621,7 +1295,6 @@ static int gfar_process_filer_changes(struct gfar_private *priv)
1621{ 1295{
1622 struct ethtool_flow_spec_container *j; 1296 struct ethtool_flow_spec_container *j;
1623 struct filer_table *tab; 1297 struct filer_table *tab;
1624 s32 i = 0;
1625 s32 ret = 0; 1298 s32 ret = 0;
1626 1299
1627 /* So index is set to zero, too! */ 1300 /* So index is set to zero, too! */
@@ -1646,17 +1319,6 @@ static int gfar_process_filer_changes(struct gfar_private *priv)
1646 } 1319 }
1647 } 1320 }
1648 1321
1649 i = tab->index;
1650
1651 /* Optimizations to save entries */
1652 gfar_cluster_filer(tab);
1653 gfar_optimize_filer_masks(tab);
1654
1655 pr_debug("\tSummary:\n"
1656 "\tData on hardware: %d\n"
1657 "\tCompression rate: %d%%\n",
1658 tab->index, 100 - (100 * tab->index) / i);
1659
1660 /* Write everything to hardware */ 1322 /* Write everything to hardware */
1661 ret = gfar_write_filer_table(priv, tab); 1323 ret = gfar_write_filer_table(priv, tab);
1662 if (ret == -EBUSY) { 1324 if (ret == -EBUSY) {
@@ -1722,13 +1384,14 @@ static int gfar_add_cls(struct gfar_private *priv,
1722 } 1384 }
1723 1385
1724process: 1386process:
1387 priv->rx_list.count++;
1725 ret = gfar_process_filer_changes(priv); 1388 ret = gfar_process_filer_changes(priv);
1726 if (ret) 1389 if (ret)
1727 goto clean_list; 1390 goto clean_list;
1728 priv->rx_list.count++;
1729 return ret; 1391 return ret;
1730 1392
1731clean_list: 1393clean_list:
1394 priv->rx_list.count--;
1732 list_del(&temp->list); 1395 list_del(&temp->list);
1733clean_mem: 1396clean_mem:
1734 kfree(temp); 1397 kfree(temp);