aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sfc/efx.c3
-rw-r--r--drivers/net/sfc/ethtool.c90
-rw-r--r--drivers/net/sfc/net_driver.h2
-rw-r--r--drivers/net/sfc/nic.c19
-rw-r--r--drivers/net/sfc/nic.h1
5 files changed, 105 insertions, 10 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 2a90bf9df913..35b3f2922e5c 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1121,6 +1121,7 @@ static void efx_set_channels(struct efx_nic *efx)
1121 1121
1122static int efx_probe_nic(struct efx_nic *efx) 1122static int efx_probe_nic(struct efx_nic *efx)
1123{ 1123{
1124 size_t i;
1124 int rc; 1125 int rc;
1125 1126
1126 netif_dbg(efx, probe, efx->net_dev, "creating NIC\n"); 1127 netif_dbg(efx, probe, efx->net_dev, "creating NIC\n");
@@ -1136,6 +1137,8 @@ static int efx_probe_nic(struct efx_nic *efx)
1136 1137
1137 if (efx->n_channels > 1) 1138 if (efx->n_channels > 1)
1138 get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key)); 1139 get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
1140 for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
1141 efx->rx_indir_table[i] = i % efx->n_rx_channels;
1139 1142
1140 efx_set_channels(efx); 1143 efx_set_channels(efx);
1141 efx->net_dev->real_num_tx_queues = efx->n_tx_channels; 1144 efx->net_dev->real_num_tx_queues = efx->n_tx_channels;
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 23372bf5cd59..3b8b0a062749 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -868,6 +868,93 @@ extern int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
868 return efx_reset(efx, method); 868 return efx_reset(efx, method);
869} 869}
870 870
871static int
872efx_ethtool_get_rxnfc(struct net_device *net_dev,
873 struct ethtool_rxnfc *info, void *rules __always_unused)
874{
875 struct efx_nic *efx = netdev_priv(net_dev);
876
877 switch (info->cmd) {
878 case ETHTOOL_GRXRINGS:
879 info->data = efx->n_rx_channels;
880 return 0;
881
882 case ETHTOOL_GRXFH: {
883 unsigned min_revision = 0;
884
885 info->data = 0;
886 switch (info->flow_type) {
887 case TCP_V4_FLOW:
888 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
889 /* fall through */
890 case UDP_V4_FLOW:
891 case SCTP_V4_FLOW:
892 case AH_ESP_V4_FLOW:
893 case IPV4_FLOW:
894 info->data |= RXH_IP_SRC | RXH_IP_DST;
895 min_revision = EFX_REV_FALCON_B0;
896 break;
897 case TCP_V6_FLOW:
898 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
899 /* fall through */
900 case UDP_V6_FLOW:
901 case SCTP_V6_FLOW:
902 case AH_ESP_V6_FLOW:
903 case IPV6_FLOW:
904 info->data |= RXH_IP_SRC | RXH_IP_DST;
905 min_revision = EFX_REV_SIENA_A0;
906 break;
907 default:
908 break;
909 }
910 if (efx_nic_rev(efx) < min_revision)
911 info->data = 0;
912 return 0;
913 }
914
915 default:
916 return -EOPNOTSUPP;
917 }
918}
919
920static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev,
921 struct ethtool_rxfh_indir *indir)
922{
923 struct efx_nic *efx = netdev_priv(net_dev);
924 size_t copy_size =
925 min_t(size_t, indir->size, ARRAY_SIZE(efx->rx_indir_table));
926
927 if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
928 return -EOPNOTSUPP;
929
930 indir->size = ARRAY_SIZE(efx->rx_indir_table);
931 memcpy(indir->ring_index, efx->rx_indir_table,
932 copy_size * sizeof(indir->ring_index[0]));
933 return 0;
934}
935
936static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
937 const struct ethtool_rxfh_indir *indir)
938{
939 struct efx_nic *efx = netdev_priv(net_dev);
940 size_t i;
941
942 if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
943 return -EOPNOTSUPP;
944
945 /* Validate size and indices */
946 if (indir->size != ARRAY_SIZE(efx->rx_indir_table))
947 return -EINVAL;
948 for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++)
949 if (indir->ring_index[i] >= efx->n_rx_channels)
950 return -EINVAL;
951
952 memcpy(efx->rx_indir_table, indir->ring_index,
953 sizeof(efx->rx_indir_table));
954 efx_nic_push_rx_indir_table(efx);
955 return 0;
956}
957
871const struct ethtool_ops efx_ethtool_ops = { 958const struct ethtool_ops efx_ethtool_ops = {
872 .get_settings = efx_ethtool_get_settings, 959 .get_settings = efx_ethtool_get_settings,
873 .set_settings = efx_ethtool_set_settings, 960 .set_settings = efx_ethtool_set_settings,
@@ -905,4 +992,7 @@ const struct ethtool_ops efx_ethtool_ops = {
905 .get_wol = efx_ethtool_get_wol, 992 .get_wol = efx_ethtool_get_wol,
906 .set_wol = efx_ethtool_set_wol, 993 .set_wol = efx_ethtool_set_wol,
907 .reset = efx_ethtool_reset, 994 .reset = efx_ethtool_reset,
995 .get_rxnfc = efx_ethtool_get_rxnfc,
996 .get_rxfh_indir = efx_ethtool_get_rxfh_indir,
997 .set_rxfh_indir = efx_ethtool_set_rxfh_indir,
908}; 998};
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 28f3ff4cff4a..bab836c22719 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -648,6 +648,7 @@ union efx_multicast_hash {
648 * @n_tx_channels: Number of channels used for TX 648 * @n_tx_channels: Number of channels used for TX
649 * @rx_buffer_len: RX buffer length 649 * @rx_buffer_len: RX buffer length
650 * @rx_buffer_order: Order (log2) of number of pages for each RX buffer 650 * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
651 * @rx_indir_table: Indirection table for RSS
651 * @int_error_count: Number of internal errors seen recently 652 * @int_error_count: Number of internal errors seen recently
652 * @int_error_expire: Time at which error count will be expired 653 * @int_error_expire: Time at which error count will be expired
653 * @irq_status: Interrupt status buffer 654 * @irq_status: Interrupt status buffer
@@ -736,6 +737,7 @@ struct efx_nic {
736 unsigned int rx_buffer_len; 737 unsigned int rx_buffer_len;
737 unsigned int rx_buffer_order; 738 unsigned int rx_buffer_order;
738 u8 rx_hash_key[40]; 739 u8 rx_hash_key[40];
740 u32 rx_indir_table[128];
739 741
740 unsigned int_error_count; 742 unsigned int_error_count;
741 unsigned long int_error_expire; 743 unsigned long int_error_expire;
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index 30836578c1cc..f595d920c7c4 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -1484,22 +1484,21 @@ static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
1484/* Setup RSS indirection table. 1484/* Setup RSS indirection table.
1485 * This maps from the hash value of the packet to RXQ 1485 * This maps from the hash value of the packet to RXQ
1486 */ 1486 */
1487static void efx_setup_rss_indir_table(struct efx_nic *efx) 1487void efx_nic_push_rx_indir_table(struct efx_nic *efx)
1488{ 1488{
1489 int i = 0; 1489 size_t i = 0;
1490 unsigned long offset;
1491 efx_dword_t dword; 1490 efx_dword_t dword;
1492 1491
1493 if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) 1492 if (efx_nic_rev(efx) < EFX_REV_FALCON_B0)
1494 return; 1493 return;
1495 1494
1496 for (offset = FR_BZ_RX_INDIRECTION_TBL; 1495 BUILD_BUG_ON(ARRAY_SIZE(efx->rx_indir_table) !=
1497 offset < FR_BZ_RX_INDIRECTION_TBL + 0x800; 1496 FR_BZ_RX_INDIRECTION_TBL_ROWS);
1498 offset += 0x10) { 1497
1498 for (i = 0; i < FR_BZ_RX_INDIRECTION_TBL_ROWS; i++) {
1499 EFX_POPULATE_DWORD_1(dword, FRF_BZ_IT_QUEUE, 1499 EFX_POPULATE_DWORD_1(dword, FRF_BZ_IT_QUEUE,
1500 i % efx->n_rx_channels); 1500 efx->rx_indir_table[i]);
1501 efx_writed(efx, &dword, offset); 1501 efx_writed_table(efx, &dword, FR_BZ_RX_INDIRECTION_TBL, i);
1502 i++;
1503 } 1502 }
1504} 1503}
1505 1504
@@ -1634,7 +1633,7 @@ void efx_nic_init_common(struct efx_nic *efx)
1634 EFX_INVERT_OWORD(temp); 1633 EFX_INVERT_OWORD(temp);
1635 efx_writeo(efx, &temp, FR_AZ_FATAL_INTR_KER); 1634 efx_writeo(efx, &temp, FR_AZ_FATAL_INTR_KER);
1636 1635
1637 efx_setup_rss_indir_table(efx); 1636 efx_nic_push_rx_indir_table(efx);
1638 1637
1639 /* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be 1638 /* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be
1640 * controlled by the RX FIFO fill level. Set arbitration to one pkt/Q. 1639 * controlled by the RX FIFO fill level. Set arbitration to one pkt/Q.
diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h
index a39822da081b..0438dc98722d 100644
--- a/drivers/net/sfc/nic.h
+++ b/drivers/net/sfc/nic.h
@@ -207,6 +207,7 @@ extern void falcon_stop_nic_stats(struct efx_nic *efx);
207extern void falcon_setup_xaui(struct efx_nic *efx); 207extern void falcon_setup_xaui(struct efx_nic *efx);
208extern int falcon_reset_xaui(struct efx_nic *efx); 208extern int falcon_reset_xaui(struct efx_nic *efx);
209extern void efx_nic_init_common(struct efx_nic *efx); 209extern void efx_nic_init_common(struct efx_nic *efx);
210extern void efx_nic_push_rx_indir_table(struct efx_nic *efx);
210 211
211int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer, 212int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
212 unsigned int len); 213 unsigned int len);