aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunil Goutham <sgoutham@cavium.com>2016-11-15 07:07:36 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-16 13:28:33 -0500
commit712c3185344050c591d78584542bd945e4f6f778 (patch)
treece9261287883d127ed3de07d2d55b934fc52ff66
parent612e94bd99912f3b2ac616c00c3dc7f166a98005 (diff)
net: thunderx: Program LMAC credits based on MTU
Programming LMAC credits taking 9K frame size by default is incorrect as for an interface which is one of the many on the same BGX/QLM no of credits available will be less as Tx FIFO will be divided across all interfaces. So let's say a BGX with 40G interface and another BGX with multiple 10G, bandwidth of 10G interfaces will be effected when traffic is running on both 40G and 10G interfaces simultaneously. This patch fixes this issue by programming credits based on netdev's MTU. Also fixed configuring MTU to HW and added CQE counter for pkts which exceed this value. Signed-off-by: Sunil Goutham <sgoutham@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic.h3
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic_main.c36
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic_reg.h1
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c38
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.c3
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.h2
6 files changed, 53 insertions, 30 deletions
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 30426109711c..cd2d379df5c5 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -47,7 +47,7 @@
47 47
48/* Min/Max packet size */ 48/* Min/Max packet size */
49#define NIC_HW_MIN_FRS 64 49#define NIC_HW_MIN_FRS 64
50#define NIC_HW_MAX_FRS 9200 /* 9216 max packet including FCS */ 50#define NIC_HW_MAX_FRS 9190 /* Excluding L2 header and FCS */
51 51
52/* Max pkinds */ 52/* Max pkinds */
53#define NIC_MAX_PKIND 16 53#define NIC_MAX_PKIND 16
@@ -282,7 +282,6 @@ struct nicvf {
282 282
283 u8 node; 283 u8 node;
284 u8 cpi_alg; 284 u8 cpi_alg;
285 u16 mtu;
286 bool link_up; 285 bool link_up;
287 u8 duplex; 286 u8 duplex;
288 u32 speed; 287 u32 speed;
diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c
index 2bbf4cbf08b2..85c9e6201e8b 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -11,6 +11,7 @@
11#include <linux/pci.h> 11#include <linux/pci.h>
12#include <linux/etherdevice.h> 12#include <linux/etherdevice.h>
13#include <linux/of.h> 13#include <linux/of.h>
14#include <linux/if_vlan.h>
14 15
15#include "nic_reg.h" 16#include "nic_reg.h"
16#include "nic.h" 17#include "nic.h"
@@ -260,18 +261,31 @@ static void nic_get_bgx_stats(struct nicpf *nic, struct bgx_stats_msg *bgx)
260/* Update hardware min/max frame size */ 261/* Update hardware min/max frame size */
261static int nic_update_hw_frs(struct nicpf *nic, int new_frs, int vf) 262static int nic_update_hw_frs(struct nicpf *nic, int new_frs, int vf)
262{ 263{
263 if ((new_frs > NIC_HW_MAX_FRS) || (new_frs < NIC_HW_MIN_FRS)) { 264 int bgx, lmac, lmac_cnt;
264 dev_err(&nic->pdev->dev, 265 u64 lmac_credits;
265 "Invalid MTU setting from VF%d rejected, should be between %d and %d\n", 266
266 vf, NIC_HW_MIN_FRS, NIC_HW_MAX_FRS); 267 if ((new_frs > NIC_HW_MAX_FRS) || (new_frs < NIC_HW_MIN_FRS))
267 return 1; 268 return 1;
268 }
269 new_frs += ETH_HLEN;
270 if (new_frs <= nic->pkind.maxlen)
271 return 0;
272 269
273 nic->pkind.maxlen = new_frs; 270 bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
274 nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG, *(u64 *)&nic->pkind); 271 lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
272 lmac += bgx * MAX_LMAC_PER_BGX;
273
274 new_frs += VLAN_ETH_HLEN + ETH_FCS_LEN + 4;
275
276 /* Update corresponding LMAC credits */
277 lmac_cnt = bgx_get_lmac_count(nic->node, bgx);
278 lmac_credits = nic_reg_read(nic, NIC_PF_LMAC_0_7_CREDIT + (lmac * 8));
279 lmac_credits &= ~(0xFFFFFULL << 12);
280 lmac_credits |= (((((48 * 1024) / lmac_cnt) - new_frs) / 16) << 12);
281 nic_reg_write(nic, NIC_PF_LMAC_0_7_CREDIT + (lmac * 8), lmac_credits);
282
283 /* Enforce MTU in HW
284 * This config is supported only from 88xx pass 2.0 onwards.
285 */
286 if (!pass1_silicon(nic->pdev))
287 nic_reg_write(nic,
288 NIC_PF_LMAC_0_7_CFG2 + (lmac * 8), new_frs);
275 return 0; 289 return 0;
276} 290}
277 291
@@ -464,7 +478,7 @@ static int nic_init_hw(struct nicpf *nic)
464 478
465 /* PKIND configuration */ 479 /* PKIND configuration */
466 nic->pkind.minlen = 0; 480 nic->pkind.minlen = 0;
467 nic->pkind.maxlen = NIC_HW_MAX_FRS + ETH_HLEN; 481 nic->pkind.maxlen = NIC_HW_MAX_FRS + VLAN_ETH_HLEN + ETH_FCS_LEN + 4;
468 nic->pkind.lenerr_en = 1; 482 nic->pkind.lenerr_en = 1;
469 nic->pkind.rx_hdr = 0; 483 nic->pkind.rx_hdr = 0;
470 nic->pkind.hdr_sl = 0; 484 nic->pkind.hdr_sl = 0;
diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h
index edf779f5a227..80d46337cf29 100644
--- a/drivers/net/ethernet/cavium/thunder/nic_reg.h
+++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h
@@ -106,6 +106,7 @@
106#define NIC_PF_MPI_0_2047_CFG (0x210000) 106#define NIC_PF_MPI_0_2047_CFG (0x210000)
107#define NIC_PF_RSSI_0_4097_RQ (0x220000) 107#define NIC_PF_RSSI_0_4097_RQ (0x220000)
108#define NIC_PF_LMAC_0_7_CFG (0x240000) 108#define NIC_PF_LMAC_0_7_CFG (0x240000)
109#define NIC_PF_LMAC_0_7_CFG2 (0x240100)
109#define NIC_PF_LMAC_0_7_SW_XOFF (0x242000) 110#define NIC_PF_LMAC_0_7_SW_XOFF (0x242000)
110#define NIC_PF_LMAC_0_7_CREDIT (0x244000) 111#define NIC_PF_LMAC_0_7_CREDIT (0x244000)
111#define NIC_PF_CHAN_0_255_TX_CFG (0x400000) 112#define NIC_PF_CHAN_0_255_TX_CFG (0x400000)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 45a13f718863..8f833612da77 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1189,6 +1189,17 @@ int nicvf_stop(struct net_device *netdev)
1189 return 0; 1189 return 0;
1190} 1190}
1191 1191
1192static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
1193{
1194 union nic_mbx mbx = {};
1195
1196 mbx.frs.msg = NIC_MBOX_MSG_SET_MAX_FRS;
1197 mbx.frs.max_frs = mtu;
1198 mbx.frs.vf_id = nic->vf_id;
1199
1200 return nicvf_send_msg_to_pf(nic, &mbx);
1201}
1202
1192int nicvf_open(struct net_device *netdev) 1203int nicvf_open(struct net_device *netdev)
1193{ 1204{
1194 int err, qidx; 1205 int err, qidx;
@@ -1196,8 +1207,6 @@ int nicvf_open(struct net_device *netdev)
1196 struct queue_set *qs = nic->qs; 1207 struct queue_set *qs = nic->qs;
1197 struct nicvf_cq_poll *cq_poll = NULL; 1208 struct nicvf_cq_poll *cq_poll = NULL;
1198 1209
1199 nic->mtu = netdev->mtu;
1200
1201 netif_carrier_off(netdev); 1210 netif_carrier_off(netdev);
1202 1211
1203 err = nicvf_register_misc_interrupt(nic); 1212 err = nicvf_register_misc_interrupt(nic);
@@ -1248,9 +1257,12 @@ int nicvf_open(struct net_device *netdev)
1248 if (nic->sqs_mode) 1257 if (nic->sqs_mode)
1249 nicvf_get_primary_vf_struct(nic); 1258 nicvf_get_primary_vf_struct(nic);
1250 1259
1251 /* Configure receive side scaling */ 1260 /* Configure receive side scaling and MTU */
1252 if (!nic->sqs_mode) 1261 if (!nic->sqs_mode) {
1253 nicvf_rss_init(nic); 1262 nicvf_rss_init(nic);
1263 if (nicvf_update_hw_max_frs(nic, netdev->mtu))
1264 goto cleanup;
1265 }
1254 1266
1255 err = nicvf_register_interrupts(nic); 1267 err = nicvf_register_interrupts(nic);
1256 if (err) 1268 if (err)
@@ -1297,17 +1309,6 @@ napi_del:
1297 return err; 1309 return err;
1298} 1310}
1299 1311
1300static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
1301{
1302 union nic_mbx mbx = {};
1303
1304 mbx.frs.msg = NIC_MBOX_MSG_SET_MAX_FRS;
1305 mbx.frs.max_frs = mtu;
1306 mbx.frs.vf_id = nic->vf_id;
1307
1308 return nicvf_send_msg_to_pf(nic, &mbx);
1309}
1310
1311static int nicvf_change_mtu(struct net_device *netdev, int new_mtu) 1312static int nicvf_change_mtu(struct net_device *netdev, int new_mtu)
1312{ 1313{
1313 struct nicvf *nic = netdev_priv(netdev); 1314 struct nicvf *nic = netdev_priv(netdev);
@@ -1318,10 +1319,13 @@ static int nicvf_change_mtu(struct net_device *netdev, int new_mtu)
1318 if (new_mtu < NIC_HW_MIN_FRS) 1319 if (new_mtu < NIC_HW_MIN_FRS)
1319 return -EINVAL; 1320 return -EINVAL;
1320 1321
1322 netdev->mtu = new_mtu;
1323
1324 if (!netif_running(netdev))
1325 return 0;
1326
1321 if (nicvf_update_hw_max_frs(nic, new_mtu)) 1327 if (nicvf_update_hw_max_frs(nic, new_mtu))
1322 return -EINVAL; 1328 return -EINVAL;
1323 netdev->mtu = new_mtu;
1324 nic->mtu = new_mtu;
1325 1329
1326 return 0; 1330 return 0;
1327} 1331}
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index a4fc50155881..f0e0ca61438e 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -1530,6 +1530,9 @@ int nicvf_check_cqe_tx_errs(struct nicvf *nic,
1530 case CQ_TX_ERROP_SUBDC_ERR: 1530 case CQ_TX_ERROP_SUBDC_ERR:
1531 stats->tx.subdesc_err++; 1531 stats->tx.subdesc_err++;
1532 break; 1532 break;
1533 case CQ_TX_ERROP_MAX_SIZE_VIOL:
1534 stats->tx.max_size_exceeded++;
1535 break;
1533 case CQ_TX_ERROP_IMM_SIZE_OFLOW: 1536 case CQ_TX_ERROP_IMM_SIZE_OFLOW:
1534 stats->tx.imm_size_oflow++; 1537 stats->tx.imm_size_oflow++;
1535 break; 1538 break;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
index 869f3386028b..8f4718edc0fe 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
@@ -158,6 +158,7 @@ enum CQ_TX_ERROP_E {
158 CQ_TX_ERROP_DESC_FAULT = 0x10, 158 CQ_TX_ERROP_DESC_FAULT = 0x10,
159 CQ_TX_ERROP_HDR_CONS_ERR = 0x11, 159 CQ_TX_ERROP_HDR_CONS_ERR = 0x11,
160 CQ_TX_ERROP_SUBDC_ERR = 0x12, 160 CQ_TX_ERROP_SUBDC_ERR = 0x12,
161 CQ_TX_ERROP_MAX_SIZE_VIOL = 0x13,
161 CQ_TX_ERROP_IMM_SIZE_OFLOW = 0x80, 162 CQ_TX_ERROP_IMM_SIZE_OFLOW = 0x80,
162 CQ_TX_ERROP_DATA_SEQUENCE_ERR = 0x81, 163 CQ_TX_ERROP_DATA_SEQUENCE_ERR = 0x81,
163 CQ_TX_ERROP_MEM_SEQUENCE_ERR = 0x82, 164 CQ_TX_ERROP_MEM_SEQUENCE_ERR = 0x82,
@@ -177,6 +178,7 @@ struct cmp_queue_stats {
177 u64 desc_fault; 178 u64 desc_fault;
178 u64 hdr_cons_err; 179 u64 hdr_cons_err;
179 u64 subdesc_err; 180 u64 subdesc_err;
181 u64 max_size_exceeded;
180 u64 imm_size_oflow; 182 u64 imm_size_oflow;
181 u64 data_seq_err; 183 u64 data_seq_err;
182 u64 mem_seq_err; 184 u64 mem_seq_err;