diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qede/qede_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 99 |
1 files changed, 64 insertions, 35 deletions
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index 25a9b293ee8f..12251a1032d1 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c | |||
@@ -756,6 +756,8 @@ static void qede_get_channels(struct net_device *dev, | |||
756 | struct qede_dev *edev = netdev_priv(dev); | 756 | struct qede_dev *edev = netdev_priv(dev); |
757 | 757 | ||
758 | channels->max_combined = QEDE_MAX_RSS_CNT(edev); | 758 | channels->max_combined = QEDE_MAX_RSS_CNT(edev); |
759 | channels->max_rx = QEDE_MAX_RSS_CNT(edev); | ||
760 | channels->max_tx = QEDE_MAX_RSS_CNT(edev); | ||
759 | channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - | 761 | channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx - |
760 | edev->fp_num_rx; | 762 | edev->fp_num_rx; |
761 | channels->tx_count = edev->fp_num_tx; | 763 | channels->tx_count = edev->fp_num_tx; |
@@ -820,6 +822,13 @@ static int qede_set_channels(struct net_device *dev, | |||
820 | edev->req_queues = count; | 822 | edev->req_queues = count; |
821 | edev->req_num_tx = channels->tx_count; | 823 | edev->req_num_tx = channels->tx_count; |
822 | edev->req_num_rx = channels->rx_count; | 824 | edev->req_num_rx = channels->rx_count; |
825 | /* Reset the indirection table if rx queue count is updated */ | ||
826 | if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) { | ||
827 | edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED; | ||
828 | memset(&edev->rss_params.rss_ind_table, 0, | ||
829 | sizeof(edev->rss_params.rss_ind_table)); | ||
830 | } | ||
831 | |||
823 | if (netif_running(dev)) | 832 | if (netif_running(dev)) |
824 | qede_reload(edev, NULL, NULL); | 833 | qede_reload(edev, NULL, NULL); |
825 | 834 | ||
@@ -1053,6 +1062,12 @@ static int qede_set_rxfh(struct net_device *dev, const u32 *indir, | |||
1053 | struct qede_dev *edev = netdev_priv(dev); | 1062 | struct qede_dev *edev = netdev_priv(dev); |
1054 | int i; | 1063 | int i; |
1055 | 1064 | ||
1065 | if (edev->dev_info.common.num_hwfns > 1) { | ||
1066 | DP_INFO(edev, | ||
1067 | "RSS configuration is not supported for 100G devices\n"); | ||
1068 | return -EOPNOTSUPP; | ||
1069 | } | ||
1070 | |||
1056 | if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) | 1071 | if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) |
1057 | return -EOPNOTSUPP; | 1072 | return -EOPNOTSUPP; |
1058 | 1073 | ||
@@ -1184,8 +1199,8 @@ static int qede_selftest_transmit_traffic(struct qede_dev *edev, | |||
1184 | } | 1199 | } |
1185 | 1200 | ||
1186 | first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); | 1201 | first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); |
1187 | dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), | 1202 | dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), |
1188 | BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); | 1203 | BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE); |
1189 | txq->sw_tx_cons++; | 1204 | txq->sw_tx_cons++; |
1190 | txq->sw_tx_ring[idx].skb = NULL; | 1205 | txq->sw_tx_ring[idx].skb = NULL; |
1191 | 1206 | ||
@@ -1199,8 +1214,8 @@ static int qede_selftest_receive_traffic(struct qede_dev *edev) | |||
1199 | struct qede_rx_queue *rxq = NULL; | 1214 | struct qede_rx_queue *rxq = NULL; |
1200 | struct sw_rx_data *sw_rx_data; | 1215 | struct sw_rx_data *sw_rx_data; |
1201 | union eth_rx_cqe *cqe; | 1216 | union eth_rx_cqe *cqe; |
1217 | int i, rc = 0; | ||
1202 | u8 *data_ptr; | 1218 | u8 *data_ptr; |
1203 | int i; | ||
1204 | 1219 | ||
1205 | for_each_queue(i) { | 1220 | for_each_queue(i) { |
1206 | if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { | 1221 | if (edev->fp_array[i].type & QEDE_FASTPATH_RX) { |
@@ -1219,46 +1234,60 @@ static int qede_selftest_receive_traffic(struct qede_dev *edev) | |||
1219 | * queue and that the loopback traffic is not IP. | 1234 | * queue and that the loopback traffic is not IP. |
1220 | */ | 1235 | */ |
1221 | for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { | 1236 | for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) { |
1222 | if (qede_has_rx_work(rxq)) | 1237 | if (!qede_has_rx_work(rxq)) { |
1238 | usleep_range(100, 200); | ||
1239 | continue; | ||
1240 | } | ||
1241 | |||
1242 | hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); | ||
1243 | sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); | ||
1244 | |||
1245 | /* Memory barrier to prevent the CPU from doing speculative | ||
1246 | * reads of CQE/BD before reading hw_comp_cons. If the CQE is | ||
1247 | * read before it is written by FW, then FW writes CQE and SB, | ||
1248 | * and then the CPU reads the hw_comp_cons, it will use an old | ||
1249 | * CQE. | ||
1250 | */ | ||
1251 | rmb(); | ||
1252 | |||
1253 | /* Get the CQE from the completion ring */ | ||
1254 | cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); | ||
1255 | |||
1256 | /* Get the data from the SW ring */ | ||
1257 | sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; | ||
1258 | sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; | ||
1259 | fp_cqe = &cqe->fast_path_regular; | ||
1260 | len = le16_to_cpu(fp_cqe->len_on_first_bd); | ||
1261 | data_ptr = (u8 *)(page_address(sw_rx_data->data) + | ||
1262 | fp_cqe->placement_offset + | ||
1263 | sw_rx_data->page_offset); | ||
1264 | if (ether_addr_equal(data_ptr, edev->ndev->dev_addr) && | ||
1265 | ether_addr_equal(data_ptr + ETH_ALEN, | ||
1266 | edev->ndev->dev_addr)) { | ||
1267 | for (i = ETH_HLEN; i < len; i++) | ||
1268 | if (data_ptr[i] != (unsigned char)(i & 0xff)) { | ||
1269 | rc = -1; | ||
1270 | break; | ||
1271 | } | ||
1272 | |||
1273 | qede_recycle_rx_bd_ring(rxq, edev, 1); | ||
1274 | qed_chain_recycle_consumed(&rxq->rx_comp_ring); | ||
1223 | break; | 1275 | break; |
1224 | usleep_range(100, 200); | 1276 | } |
1277 | |||
1278 | DP_INFO(edev, "Not the transmitted packet\n"); | ||
1279 | qede_recycle_rx_bd_ring(rxq, edev, 1); | ||
1280 | qed_chain_recycle_consumed(&rxq->rx_comp_ring); | ||
1225 | } | 1281 | } |
1226 | 1282 | ||
1227 | if (!qede_has_rx_work(rxq)) { | 1283 | if (i == QEDE_SELFTEST_POLL_COUNT) { |
1228 | DP_NOTICE(edev, "Failed to receive the traffic\n"); | 1284 | DP_NOTICE(edev, "Failed to receive the traffic\n"); |
1229 | return -1; | 1285 | return -1; |
1230 | } | 1286 | } |
1231 | 1287 | ||
1232 | hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); | 1288 | qede_update_rx_prod(edev, rxq); |
1233 | sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); | ||
1234 | 1289 | ||
1235 | /* Memory barrier to prevent the CPU from doing speculative reads of CQE | 1290 | return rc; |
1236 | * / BD before reading hw_comp_cons. If the CQE is read before it is | ||
1237 | * written by FW, then FW writes CQE and SB, and then the CPU reads the | ||
1238 | * hw_comp_cons, it will use an old CQE. | ||
1239 | */ | ||
1240 | rmb(); | ||
1241 | |||
1242 | /* Get the CQE from the completion ring */ | ||
1243 | cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring); | ||
1244 | |||
1245 | /* Get the data from the SW ring */ | ||
1246 | sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; | ||
1247 | sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; | ||
1248 | fp_cqe = &cqe->fast_path_regular; | ||
1249 | len = le16_to_cpu(fp_cqe->len_on_first_bd); | ||
1250 | data_ptr = (u8 *)(page_address(sw_rx_data->data) + | ||
1251 | fp_cqe->placement_offset + sw_rx_data->page_offset); | ||
1252 | for (i = ETH_HLEN; i < len; i++) | ||
1253 | if (data_ptr[i] != (unsigned char)(i & 0xff)) { | ||
1254 | DP_NOTICE(edev, "Loopback test failed\n"); | ||
1255 | qede_recycle_rx_bd_ring(rxq, edev, 1); | ||
1256 | return -1; | ||
1257 | } | ||
1258 | |||
1259 | qede_recycle_rx_bd_ring(rxq, edev, 1); | ||
1260 | |||
1261 | return 0; | ||
1262 | } | 1291 | } |
1263 | 1292 | ||
1264 | static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) | 1293 | static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode) |