Skip to content

Commit a82457f

Browse files
Intiyaz Bashadavem330
authored andcommitted
liquidio: added support for ethtool --set-channels feature
adding support for ethtool --set-channels feature Signed-off-by: Intiyaz Basha <[email protected]> Signed-off-by: Raghu Vatsavayi <[email protected]> Signed-off-by: Felix Manlunas <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 14aec73 commit a82457f

File tree

6 files changed

+226
-50
lines changed

6 files changed

+226
-50
lines changed

drivers/net/ethernet/cavium/liquidio/lio_core.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,11 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
275275
netif_info(lio, probe, lio->netdev, "Set RX/TX flow control parameters\n");
276276
break;
277277

278+
case OCTNET_CMD_QUEUE_COUNT_CTL:
279+
netif_info(lio, probe, lio->netdev, "Queue count updated to %d\n",
280+
nctrl->ncmd.s.param1);
281+
break;
282+
278283
default:
279284
dev_err(&oct->pci_dev->dev, "%s Unknown cmd %d\n", __func__,
280285
nctrl->ncmd.s.cmd);
@@ -689,7 +694,8 @@ static int liquidio_napi_poll(struct napi_struct *napi, int budget)
689694
* an input queue is for egress packets, and output queues
690695
* are for ingress packets.
691696
*/
692-
int liquidio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx)
697+
int liquidio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx,
698+
u32 num_iqs, u32 num_oqs)
693699
{
694700
struct octeon_droq_ops droq_ops;
695701
struct net_device *netdev;
@@ -717,7 +723,7 @@ int liquidio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx)
717723
cpu_id_modulus = num_present_cpus();
718724

719725
/* set up DROQs. */
720-
for (q = 0; q < lio->linfo.num_rxpciq; q++) {
726+
for (q = 0; q < num_oqs; q++) {
721727
q_no = lio->linfo.rxpciq[q].s.q_no;
722728
dev_dbg(&octeon_dev->pci_dev->dev,
723729
"%s index:%d linfo.rxpciq.s.q_no:%d\n",
@@ -761,7 +767,7 @@ int liquidio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx)
761767
}
762768

763769
/* set up IQs. */
764-
for (q = 0; q < lio->linfo.num_txpciq; q++) {
770+
for (q = 0; q < num_iqs; q++) {
765771
num_tx_descs = CFG_GET_NUM_TX_DESCS_NIC_IF(
766772
octeon_get_conf(octeon_dev), lio->ifidx);
767773
retval = octeon_setup_iq(octeon_dev, ifidx, q,
@@ -892,7 +898,7 @@ irqreturn_t liquidio_legacy_intr_handler(int irq __attribute__((unused)),
892898
*
893899
* Enable interrupt in Octeon device as given in the PCI interrupt mask.
894900
*/
895-
int octeon_setup_interrupt(struct octeon_device *oct)
901+
int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs)
896902
{
897903
struct msix_entry *msix_entries;
898904
char *queue_irq_names = NULL;
@@ -902,17 +908,16 @@ int octeon_setup_interrupt(struct octeon_device *oct)
902908
int num_ioq_vectors;
903909
int irqret, err;
904910

911+
oct->num_msix_irqs = num_ioqs;
905912
if (oct->msix_on) {
906913
if (OCTEON_CN23XX_PF(oct)) {
907-
oct->num_msix_irqs = oct->sriov_info.num_pf_rings;
908914
num_interrupts = MAX_IOQ_INTERRUPTS_PER_PF + 1;
909915

910916
/* one non ioq interrupt for handling
911917
* sli_mac_pf_int_sum
912918
*/
913919
oct->num_msix_irqs += 1;
914920
} else if (OCTEON_CN23XX_VF(oct)) {
915-
oct->num_msix_irqs = oct->sriov_info.rings_per_vf;
916921
num_interrupts = MAX_IOQ_INTERRUPTS_PER_VF;
917922
}
918923

drivers/net/ethernet/cavium/liquidio/lio_ethtool.c

Lines changed: 172 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "cn23xx_pf_device.h"
3232
#include "cn23xx_vf_device.h"
3333

34+
static int lio_reset_queues(struct net_device *netdev, uint32_t num_qs);
3435
static int octnet_get_link_stats(struct net_device *netdev);
3536

3637
struct oct_intrmod_context {
@@ -300,13 +301,43 @@ lio_get_vf_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
300301
strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32);
301302
}
302303

304+
static int
305+
lio_send_queue_count_update(struct net_device *netdev, uint32_t num_queues)
306+
{
307+
struct lio *lio = GET_LIO(netdev);
308+
struct octeon_device *oct = lio->oct_dev;
309+
struct octnic_ctrl_pkt nctrl;
310+
int ret = 0;
311+
312+
memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
313+
314+
nctrl.ncmd.u64 = 0;
315+
nctrl.ncmd.s.cmd = OCTNET_CMD_QUEUE_COUNT_CTL;
316+
nctrl.ncmd.s.param1 = num_queues;
317+
nctrl.ncmd.s.param2 = num_queues;
318+
nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
319+
nctrl.wait_time = 100;
320+
nctrl.netpndev = (u64)netdev;
321+
nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
322+
323+
ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
324+
if (ret < 0) {
325+
dev_err(&oct->pci_dev->dev, "Failed to send Queue reset command (ret: 0x%x)\n",
326+
ret);
327+
return -1;
328+
}
329+
330+
return 0;
331+
}
332+
303333
static void
304334
lio_ethtool_get_channels(struct net_device *dev,
305335
struct ethtool_channels *channel)
306336
{
307337
struct lio *lio = GET_LIO(dev);
308338
struct octeon_device *oct = lio->oct_dev;
309339
u32 max_rx = 0, max_tx = 0, tx_count = 0, rx_count = 0;
340+
u32 combined_count = 0, max_combined = 0;
310341

311342
if (OCTEON_CN6XXX(oct)) {
312343
struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
@@ -316,22 +347,137 @@ lio_ethtool_get_channels(struct net_device *dev,
316347
rx_count = CFG_GET_NUM_RXQS_NIC_IF(conf6x, lio->ifidx);
317348
tx_count = CFG_GET_NUM_TXQS_NIC_IF(conf6x, lio->ifidx);
318349
} else if (OCTEON_CN23XX_PF(oct)) {
319-
320-
max_rx = oct->sriov_info.num_pf_rings;
321-
max_tx = oct->sriov_info.num_pf_rings;
322-
rx_count = lio->linfo.num_rxpciq;
323-
tx_count = lio->linfo.num_txpciq;
350+
max_combined = lio->linfo.num_txpciq;
351+
combined_count = oct->num_iqs;
324352
} else if (OCTEON_CN23XX_VF(oct)) {
325-
max_tx = oct->sriov_info.rings_per_vf;
326-
max_rx = oct->sriov_info.rings_per_vf;
327-
rx_count = lio->linfo.num_rxpciq;
328-
tx_count = lio->linfo.num_txpciq;
353+
u64 reg_val = 0ULL;
354+
u64 ctrl = CN23XX_VF_SLI_IQ_PKT_CONTROL64(0);
355+
356+
reg_val = octeon_read_csr64(oct, ctrl);
357+
reg_val = reg_val >> CN23XX_PKT_INPUT_CTL_RPVF_POS;
358+
max_combined = reg_val & CN23XX_PKT_INPUT_CTL_RPVF_MASK;
359+
combined_count = oct->num_iqs;
329360
}
330361

331362
channel->max_rx = max_rx;
332363
channel->max_tx = max_tx;
364+
channel->max_combined = max_combined;
333365
channel->rx_count = rx_count;
334366
channel->tx_count = tx_count;
367+
channel->combined_count = combined_count;
368+
}
369+
370+
static int
371+
lio_irq_reallocate_irqs(struct octeon_device *oct, uint32_t num_ioqs)
372+
{
373+
struct msix_entry *msix_entries;
374+
int num_msix_irqs = 0;
375+
int i;
376+
377+
if (!oct->msix_on)
378+
return 0;
379+
380+
/* Disable the input and output queues now. No more packets will
381+
* arrive from Octeon.
382+
*/
383+
oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
384+
385+
if (oct->msix_on) {
386+
if (OCTEON_CN23XX_PF(oct))
387+
num_msix_irqs = oct->num_msix_irqs - 1;
388+
else if (OCTEON_CN23XX_VF(oct))
389+
num_msix_irqs = oct->num_msix_irqs;
390+
391+
msix_entries = (struct msix_entry *)oct->msix_entries;
392+
for (i = 0; i < num_msix_irqs; i++) {
393+
if (oct->ioq_vector[i].vector) {
394+
/* clear the affinity_cpumask */
395+
irq_set_affinity_hint(msix_entries[i].vector,
396+
NULL);
397+
free_irq(msix_entries[i].vector,
398+
&oct->ioq_vector[i]);
399+
oct->ioq_vector[i].vector = 0;
400+
}
401+
}
402+
403+
/* non-iov vector's argument is oct struct */
404+
if (OCTEON_CN23XX_PF(oct))
405+
free_irq(msix_entries[i].vector, oct);
406+
407+
pci_disable_msix(oct->pci_dev);
408+
kfree(oct->msix_entries);
409+
oct->msix_entries = NULL;
410+
}
411+
412+
kfree(oct->irq_name_storage);
413+
oct->irq_name_storage = NULL;
414+
if (octeon_setup_interrupt(oct, num_ioqs)) {
415+
dev_info(&oct->pci_dev->dev, "Setup interuupt failed\n");
416+
return 1;
417+
}
418+
419+
/* Enable Octeon device interrupts */
420+
oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
421+
422+
return 0;
423+
}
424+
425+
static int
426+
lio_ethtool_set_channels(struct net_device *dev,
427+
struct ethtool_channels *channel)
428+
{
429+
u32 combined_count, max_combined;
430+
struct lio *lio = GET_LIO(dev);
431+
struct octeon_device *oct = lio->oct_dev;
432+
int stopped = 0;
433+
434+
if (strcmp(oct->fw_info.liquidio_firmware_version, "1.6.1") < 0) {
435+
dev_err(&oct->pci_dev->dev, "Minimum firmware version required is 1.6.1\n");
436+
return -EINVAL;
437+
}
438+
439+
if (!channel->combined_count || channel->other_count ||
440+
channel->rx_count || channel->tx_count)
441+
return -EINVAL;
442+
443+
combined_count = channel->combined_count;
444+
445+
if (OCTEON_CN23XX_PF(oct)) {
446+
max_combined = channel->max_combined;
447+
} else if (OCTEON_CN23XX_VF(oct)) {
448+
u64 reg_val = 0ULL;
449+
u64 ctrl = CN23XX_VF_SLI_IQ_PKT_CONTROL64(0);
450+
451+
reg_val = octeon_read_csr64(oct, ctrl);
452+
reg_val = reg_val >> CN23XX_PKT_INPUT_CTL_RPVF_POS;
453+
max_combined = reg_val & CN23XX_PKT_INPUT_CTL_RPVF_MASK;
454+
} else {
455+
return -EINVAL;
456+
}
457+
458+
if (combined_count > max_combined || combined_count < 1)
459+
return -EINVAL;
460+
461+
if (combined_count == oct->num_iqs)
462+
return 0;
463+
464+
ifstate_set(lio, LIO_IFSTATE_RESETTING);
465+
466+
if (netif_running(dev)) {
467+
dev->netdev_ops->ndo_stop(dev);
468+
stopped = 1;
469+
}
470+
471+
if (lio_reset_queues(dev, combined_count))
472+
return -EINVAL;
473+
474+
lio_irq_reallocate_irqs(oct, combined_count);
475+
if (stopped)
476+
dev->netdev_ops->ndo_open(dev);
477+
478+
ifstate_reset(lio, LIO_IFSTATE_RESETTING);
479+
480+
return 0;
335481
}
336482

337483
static int lio_get_eeprom_len(struct net_device *netdev)
@@ -664,15 +810,12 @@ lio_ethtool_get_ringparam(struct net_device *netdev,
664810
ering->rx_jumbo_max_pending = 0;
665811
}
666812

667-
static int lio_reset_queues(struct net_device *netdev)
813+
static int lio_reset_queues(struct net_device *netdev, uint32_t num_qs)
668814
{
669815
struct lio *lio = GET_LIO(netdev);
670816
struct octeon_device *oct = lio->oct_dev;
671817
struct napi_struct *napi, *n;
672-
int i;
673-
674-
dev_dbg(&oct->pci_dev->dev, "%s:%d ifidx %d\n",
675-
__func__, __LINE__, lio->ifidx);
818+
int i, update = 0;
676819

677820
if (wait_for_pending_requests(oct))
678821
dev_err(&oct->pci_dev->dev, "There were pending requests\n");
@@ -693,6 +836,12 @@ static int lio_reset_queues(struct net_device *netdev)
693836
list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
694837
netif_napi_del(napi);
695838

839+
if (num_qs != oct->num_iqs) {
840+
netif_set_real_num_rx_queues(netdev, num_qs);
841+
netif_set_real_num_tx_queues(netdev, num_qs);
842+
update = 1;
843+
}
844+
696845
for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
697846
if (!(oct->io_qmask.oq & BIT_ULL(i)))
698847
continue;
@@ -710,7 +859,7 @@ static int lio_reset_queues(struct net_device *netdev)
710859
return -1;
711860
}
712861

713-
if (liquidio_setup_io_queues(oct, 0)) {
862+
if (liquidio_setup_io_queues(oct, 0, num_qs, num_qs)) {
714863
dev_err(&oct->pci_dev->dev, "IO queues initialization failed\n");
715864
return -1;
716865
}
@@ -721,6 +870,9 @@ static int lio_reset_queues(struct net_device *netdev)
721870
return -1;
722871
}
723872

873+
if (update && lio_send_queue_count_update(netdev, num_qs))
874+
return -1;
875+
724876
return 0;
725877
}
726878

@@ -764,7 +916,7 @@ static int lio_ethtool_set_ringparam(struct net_device *netdev,
764916
CFG_SET_NUM_RX_DESCS_NIC_IF(octeon_get_conf(oct), lio->ifidx,
765917
rx_count);
766918

767-
if (lio_reset_queues(netdev))
919+
if (lio_reset_queues(netdev, lio->linfo.num_txpciq))
768920
goto err_lio_reset_queues;
769921

770922
if (stopped)
@@ -1194,7 +1346,7 @@ static void lio_vf_get_ethtool_stats(struct net_device *netdev,
11941346
/* lio->link_changes */
11951347
data[i++] = CVM_CAST64(lio->link_changes);
11961348

1197-
for (vj = 0; vj < lio->linfo.num_txpciq; vj++) {
1349+
for (vj = 0; vj < oct_dev->num_iqs; vj++) {
11981350
j = lio->linfo.txpciq[vj].s.q_no;
11991351

12001352
/* packets to network port */
@@ -1236,7 +1388,7 @@ static void lio_vf_get_ethtool_stats(struct net_device *netdev,
12361388
}
12371389

12381390
/* RX */
1239-
for (vj = 0; vj < lio->linfo.num_rxpciq; vj++) {
1391+
for (vj = 0; vj < oct_dev->num_oqs; vj++) {
12401392
j = lio->linfo.rxpciq[vj].s.q_no;
12411393

12421394
/* packets send to TCP/IP network stack */
@@ -2705,6 +2857,7 @@ static const struct ethtool_ops lio_ethtool_ops = {
27052857
.get_ringparam = lio_ethtool_get_ringparam,
27062858
.set_ringparam = lio_ethtool_set_ringparam,
27072859
.get_channels = lio_ethtool_get_channels,
2860+
.set_channels = lio_ethtool_set_channels,
27082861
.set_phys_id = lio_set_phys_id,
27092862
.get_eeprom_len = lio_get_eeprom_len,
27102863
.get_eeprom = lio_get_eeprom,
@@ -2731,6 +2884,7 @@ static const struct ethtool_ops lio_vf_ethtool_ops = {
27312884
.get_ringparam = lio_ethtool_get_ringparam,
27322885
.set_ringparam = lio_ethtool_set_ringparam,
27332886
.get_channels = lio_ethtool_get_channels,
2887+
.set_channels = lio_ethtool_set_channels,
27342888
.get_strings = lio_vf_get_strings,
27352889
.get_ethtool_stats = lio_vf_get_ethtool_stats,
27362890
.get_regs_len = lio_get_regs_len,

0 commit comments

Comments
 (0)