diff options
Diffstat (limited to 'drivers/net/ethernet/amd/xgbe/xgbe-dev.c')
| -rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 148 |
1 files changed, 147 insertions, 1 deletions
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index ac3d319ffab3..551794c29d09 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c | |||
| @@ -351,6 +351,127 @@ static void xgbe_config_sph_mode(struct xgbe_prv_data *pdata) | |||
| 351 | XGMAC_IOWRITE_BITS(pdata, MAC_RCR, HDSMS, XGBE_SPH_HDSMS_SIZE); | 351 | XGMAC_IOWRITE_BITS(pdata, MAC_RCR, HDSMS, XGBE_SPH_HDSMS_SIZE); |
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | static int xgbe_write_rss_reg(struct xgbe_prv_data *pdata, unsigned int type, | ||
| 355 | unsigned int index, unsigned int val) | ||
| 356 | { | ||
| 357 | unsigned int wait; | ||
| 358 | int ret = 0; | ||
| 359 | |||
| 360 | mutex_lock(&pdata->rss_mutex); | ||
| 361 | |||
| 362 | if (XGMAC_IOREAD_BITS(pdata, MAC_RSSAR, OB)) { | ||
| 363 | ret = -EBUSY; | ||
| 364 | goto unlock; | ||
| 365 | } | ||
| 366 | |||
| 367 | XGMAC_IOWRITE(pdata, MAC_RSSDR, val); | ||
| 368 | |||
| 369 | XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, RSSIA, index); | ||
| 370 | XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, ADDRT, type); | ||
| 371 | XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, CT, 0); | ||
| 372 | XGMAC_IOWRITE_BITS(pdata, MAC_RSSAR, OB, 1); | ||
| 373 | |||
| 374 | wait = 1000; | ||
| 375 | while (wait--) { | ||
| 376 | if (!XGMAC_IOREAD_BITS(pdata, MAC_RSSAR, OB)) | ||
| 377 | goto unlock; | ||
| 378 | |||
| 379 | usleep_range(1000, 1500); | ||
| 380 | } | ||
| 381 | |||
| 382 | ret = -EBUSY; | ||
| 383 | |||
| 384 | unlock: | ||
| 385 | mutex_unlock(&pdata->rss_mutex); | ||
| 386 | |||
| 387 | return ret; | ||
| 388 | } | ||
| 389 | |||
| 390 | static int xgbe_write_rss_hash_key(struct xgbe_prv_data *pdata) | ||
| 391 | { | ||
| 392 | unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32); | ||
| 393 | unsigned int *key = (unsigned int *)&pdata->rss_key; | ||
| 394 | int ret; | ||
| 395 | |||
| 396 | while (key_regs--) { | ||
| 397 | ret = xgbe_write_rss_reg(pdata, XGBE_RSS_HASH_KEY_TYPE, | ||
| 398 | key_regs, *key++); | ||
| 399 | if (ret) | ||
| 400 | return ret; | ||
| 401 | } | ||
| 402 | |||
| 403 | return 0; | ||
| 404 | } | ||
| 405 | |||
| 406 | static int xgbe_write_rss_lookup_table(struct xgbe_prv_data *pdata) | ||
| 407 | { | ||
| 408 | unsigned int i; | ||
| 409 | int ret; | ||
| 410 | |||
| 411 | for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) { | ||
| 412 | ret = xgbe_write_rss_reg(pdata, | ||
| 413 | XGBE_RSS_LOOKUP_TABLE_TYPE, i, | ||
| 414 | pdata->rss_table[i]); | ||
| 415 | if (ret) | ||
| 416 | return ret; | ||
| 417 | } | ||
| 418 | |||
| 419 | return 0; | ||
| 420 | } | ||
| 421 | |||
| 422 | static int xgbe_enable_rss(struct xgbe_prv_data *pdata) | ||
| 423 | { | ||
| 424 | int ret; | ||
| 425 | |||
| 426 | if (!pdata->hw_feat.rss) | ||
| 427 | return -EOPNOTSUPP; | ||
| 428 | |||
| 429 | /* Program the hash key */ | ||
| 430 | ret = xgbe_write_rss_hash_key(pdata); | ||
| 431 | if (ret) | ||
| 432 | return ret; | ||
| 433 | |||
| 434 | /* Program the lookup table */ | ||
| 435 | ret = xgbe_write_rss_lookup_table(pdata); | ||
| 436 | if (ret) | ||
| 437 | return ret; | ||
| 438 | |||
| 439 | /* Set the RSS options */ | ||
| 440 | XGMAC_IOWRITE(pdata, MAC_RSSCR, pdata->rss_options); | ||
| 441 | |||
| 442 | /* Enable RSS */ | ||
| 443 | XGMAC_IOWRITE_BITS(pdata, MAC_RSSCR, RSSE, 1); | ||
| 444 | |||
| 445 | return 0; | ||
| 446 | } | ||
| 447 | |||
| 448 | static int xgbe_disable_rss(struct xgbe_prv_data *pdata) | ||
| 449 | { | ||
| 450 | if (!pdata->hw_feat.rss) | ||
| 451 | return -EOPNOTSUPP; | ||
| 452 | |||
| 453 | XGMAC_IOWRITE_BITS(pdata, MAC_RSSCR, RSSE, 0); | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | static void xgbe_config_rss(struct xgbe_prv_data *pdata) | ||
| 459 | { | ||
| 460 | int ret; | ||
| 461 | |||
| 462 | if (!pdata->hw_feat.rss) | ||
| 463 | return; | ||
| 464 | |||
| 465 | if (pdata->netdev->features & NETIF_F_RXHASH) | ||
| 466 | ret = xgbe_enable_rss(pdata); | ||
| 467 | else | ||
| 468 | ret = xgbe_disable_rss(pdata); | ||
| 469 | |||
| 470 | if (ret) | ||
| 471 | netdev_err(pdata->netdev, | ||
| 472 | "error configuring RSS, RSS disabled\n"); | ||
| 473 | } | ||
| 474 | |||
| 354 | static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata) | 475 | static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata) |
| 355 | { | 476 | { |
| 356 | unsigned int max_q_count, q_count; | 477 | unsigned int max_q_count, q_count; |
| @@ -1408,7 +1529,7 @@ static int xgbe_dev_read(struct xgbe_channel *channel) | |||
| 1408 | struct xgbe_ring_desc *rdesc; | 1529 | struct xgbe_ring_desc *rdesc; |
| 1409 | struct xgbe_packet_data *packet = &ring->packet_data; | 1530 | struct xgbe_packet_data *packet = &ring->packet_data; |
| 1410 | struct net_device *netdev = channel->pdata->netdev; | 1531 | struct net_device *netdev = channel->pdata->netdev; |
| 1411 | unsigned int err, etlt; | 1532 | unsigned int err, etlt, l34t; |
| 1412 | 1533 | ||
| 1413 | DBGPR("-->xgbe_dev_read: cur = %d\n", ring->cur); | 1534 | DBGPR("-->xgbe_dev_read: cur = %d\n", ring->cur); |
| 1414 | 1535 | ||
| @@ -1447,6 +1568,26 @@ static int xgbe_dev_read(struct xgbe_channel *channel) | |||
| 1447 | rdata->hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, | 1568 | rdata->hdr_len = XGMAC_GET_BITS_LE(rdesc->desc2, |
| 1448 | RX_NORMAL_DESC2, HL); | 1569 | RX_NORMAL_DESC2, HL); |
| 1449 | 1570 | ||
| 1571 | /* Get the RSS hash */ | ||
| 1572 | if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, RSV)) { | ||
| 1573 | XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, | ||
| 1574 | RSS_HASH, 1); | ||
| 1575 | |||
| 1576 | packet->rss_hash = le32_to_cpu(rdesc->desc1); | ||
| 1577 | |||
| 1578 | l34t = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, L34T); | ||
| 1579 | switch (l34t) { | ||
| 1580 | case RX_DESC3_L34T_IPV4_TCP: | ||
| 1581 | case RX_DESC3_L34T_IPV4_UDP: | ||
| 1582 | case RX_DESC3_L34T_IPV6_TCP: | ||
| 1583 | case RX_DESC3_L34T_IPV6_UDP: | ||
| 1584 | packet->rss_hash_type = PKT_HASH_TYPE_L4; | ||
| 1585 | |||
| 1586 | default: | ||
| 1587 | packet->rss_hash_type = PKT_HASH_TYPE_L3; | ||
| 1588 | } | ||
| 1589 | } | ||
| 1590 | |||
| 1450 | /* Get the packet length */ | 1591 | /* Get the packet length */ |
| 1451 | rdata->len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); | 1592 | rdata->len = XGMAC_GET_BITS_LE(rdesc->desc3, RX_NORMAL_DESC3, PL); |
| 1452 | 1593 | ||
| @@ -2479,6 +2620,7 @@ static int xgbe_init(struct xgbe_prv_data *pdata) | |||
| 2479 | xgbe_config_rx_buffer_size(pdata); | 2620 | xgbe_config_rx_buffer_size(pdata); |
| 2480 | xgbe_config_tso_mode(pdata); | 2621 | xgbe_config_tso_mode(pdata); |
| 2481 | xgbe_config_sph_mode(pdata); | 2622 | xgbe_config_sph_mode(pdata); |
| 2623 | xgbe_config_rss(pdata); | ||
| 2482 | desc_if->wrapper_tx_desc_init(pdata); | 2624 | desc_if->wrapper_tx_desc_init(pdata); |
| 2483 | desc_if->wrapper_rx_desc_init(pdata); | 2625 | desc_if->wrapper_rx_desc_init(pdata); |
| 2484 | xgbe_enable_dma_interrupts(pdata); | 2626 | xgbe_enable_dma_interrupts(pdata); |
| @@ -2614,5 +2756,9 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) | |||
| 2614 | hw_if->config_dcb_tc = xgbe_config_dcb_tc; | 2756 | hw_if->config_dcb_tc = xgbe_config_dcb_tc; |
| 2615 | hw_if->config_dcb_pfc = xgbe_config_dcb_pfc; | 2757 | hw_if->config_dcb_pfc = xgbe_config_dcb_pfc; |
| 2616 | 2758 | ||
| 2759 | /* For Receive Side Scaling */ | ||
| 2760 | hw_if->enable_rss = xgbe_enable_rss; | ||
| 2761 | hw_if->disable_rss = xgbe_disable_rss; | ||
| 2762 | |||
| 2617 | DBGPR("<--xgbe_init_function_ptrs\n"); | 2763 | DBGPR("<--xgbe_init_function_ptrs\n"); |
| 2618 | } | 2764 | } |
