Skip to content

Commit 937d46e

Browse files
Jiawen Wudavem330
authored andcommitted
net: wangxun: add ethtool_ops for channel number
Add support to get RX/TX queue number with ethtool -l, and set RX/TX queue number with ethtool -L. Since interrupts need to be rescheduled, adjust the allocation of msix enties. Signed-off-by: Jiawen Wu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4ac2d9d commit 937d46e

File tree

12 files changed

+380
-68
lines changed

12 files changed

+380
-68
lines changed

drivers/net/ethernet/wangxun/libwx/wx_ethtool.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,60 @@ int wx_set_coalesce(struct net_device *netdev,
348348
return 0;
349349
}
350350
EXPORT_SYMBOL(wx_set_coalesce);
351+
352+
static unsigned int wx_max_channels(struct wx *wx)
353+
{
354+
unsigned int max_combined;
355+
356+
if (!wx->msix_q_entries) {
357+
/* We only support one q_vector without MSI-X */
358+
max_combined = 1;
359+
} else {
360+
/* support up to max allowed queues with RSS */
361+
if (wx->mac.type == wx_mac_sp)
362+
max_combined = 63;
363+
else
364+
max_combined = 8;
365+
}
366+
367+
return max_combined;
368+
}
369+
370+
void wx_get_channels(struct net_device *dev,
371+
struct ethtool_channels *ch)
372+
{
373+
struct wx *wx = netdev_priv(dev);
374+
375+
/* report maximum channels */
376+
ch->max_combined = wx_max_channels(wx);
377+
378+
/* report info for other vector */
379+
if (wx->msix_q_entries) {
380+
ch->max_other = 1;
381+
ch->other_count = 1;
382+
}
383+
384+
/* record RSS queues */
385+
ch->combined_count = wx->ring_feature[RING_F_RSS].indices;
386+
}
387+
EXPORT_SYMBOL(wx_get_channels);
388+
389+
int wx_set_channels(struct net_device *dev,
390+
struct ethtool_channels *ch)
391+
{
392+
unsigned int count = ch->combined_count;
393+
struct wx *wx = netdev_priv(dev);
394+
395+
/* verify other_count has not changed */
396+
if (ch->other_count != 1)
397+
return -EINVAL;
398+
399+
/* verify the number of channels does not exceed hardware limits */
400+
if (count > wx_max_channels(wx))
401+
return -EINVAL;
402+
403+
wx->ring_feature[RING_F_RSS].limit = count;
404+
405+
return 0;
406+
}
407+
EXPORT_SYMBOL(wx_set_channels);

drivers/net/ethernet/wangxun/libwx/wx_ethtool.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,8 @@ int wx_set_coalesce(struct net_device *netdev,
3434
struct ethtool_coalesce *ec,
3535
struct kernel_ethtool_coalesce *kernel_coal,
3636
struct netlink_ext_ack *extack);
37+
void wx_get_channels(struct net_device *dev,
38+
struct ethtool_channels *ch);
39+
int wx_set_channels(struct net_device *dev,
40+
struct ethtool_channels *ch);
3741
#endif /* _WX_ETHTOOL_H_ */

drivers/net/ethernet/wangxun/libwx/wx_hw.c

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ void wx_irq_disable(struct wx *wx)
149149
int vector;
150150

151151
for (vector = 0; vector < wx->num_q_vectors; vector++)
152-
synchronize_irq(wx->msix_entries[vector].vector);
152+
synchronize_irq(wx->msix_q_entries[vector].vector);
153153

154-
synchronize_irq(wx->msix_entries[vector].vector);
154+
synchronize_irq(wx->msix_entry->vector);
155155
} else {
156156
synchronize_irq(pdev->irq);
157157
}
@@ -1597,6 +1597,72 @@ static void wx_restore_vlan(struct wx *wx)
15971597
wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid);
15981598
}
15991599

1600+
static void wx_store_reta(struct wx *wx)
1601+
{
1602+
u8 *indir_tbl = wx->rss_indir_tbl;
1603+
u32 reta = 0;
1604+
u32 i;
1605+
1606+
/* Fill out the redirection table as follows:
1607+
* - 8 bit wide entries containing 4 bit RSS index
1608+
*/
1609+
for (i = 0; i < WX_MAX_RETA_ENTRIES; i++) {
1610+
reta |= indir_tbl[i] << (i & 0x3) * 8;
1611+
if ((i & 3) == 3) {
1612+
wr32(wx, WX_RDB_RSSTBL(i >> 2), reta);
1613+
reta = 0;
1614+
}
1615+
}
1616+
}
1617+
1618+
static void wx_setup_reta(struct wx *wx)
1619+
{
1620+
u16 rss_i = wx->ring_feature[RING_F_RSS].indices;
1621+
u32 random_key_size = WX_RSS_KEY_SIZE / 4;
1622+
u32 i, j;
1623+
1624+
/* Fill out hash function seeds */
1625+
for (i = 0; i < random_key_size; i++)
1626+
wr32(wx, WX_RDB_RSSRK(i), wx->rss_key[i]);
1627+
1628+
/* Fill out redirection table */
1629+
memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl));
1630+
1631+
for (i = 0, j = 0; i < WX_MAX_RETA_ENTRIES; i++, j++) {
1632+
if (j == rss_i)
1633+
j = 0;
1634+
1635+
wx->rss_indir_tbl[i] = j;
1636+
}
1637+
1638+
wx_store_reta(wx);
1639+
}
1640+
1641+
static void wx_setup_mrqc(struct wx *wx)
1642+
{
1643+
u32 rss_field = 0;
1644+
1645+
/* Disable indicating checksum in descriptor, enables RSS hash */
1646+
wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_PCSD, WX_PSR_CTL_PCSD);
1647+
1648+
/* Perform hash on these packet types */
1649+
rss_field = WX_RDB_RA_CTL_RSS_IPV4 |
1650+
WX_RDB_RA_CTL_RSS_IPV4_TCP |
1651+
WX_RDB_RA_CTL_RSS_IPV4_UDP |
1652+
WX_RDB_RA_CTL_RSS_IPV6 |
1653+
WX_RDB_RA_CTL_RSS_IPV6_TCP |
1654+
WX_RDB_RA_CTL_RSS_IPV6_UDP;
1655+
1656+
netdev_rss_key_fill(wx->rss_key, sizeof(wx->rss_key));
1657+
1658+
wx_setup_reta(wx);
1659+
1660+
if (wx->rss_enabled)
1661+
rss_field |= WX_RDB_RA_CTL_RSS_EN;
1662+
1663+
wr32(wx, WX_RDB_RA_CTL, rss_field);
1664+
}
1665+
16001666
/**
16011667
* wx_configure_rx - Configure Receive Unit after Reset
16021668
* @wx: pointer to private structure
@@ -1629,6 +1695,8 @@ void wx_configure_rx(struct wx *wx)
16291695
wr32(wx, WX_PSR_CTL, psrctl);
16301696
}
16311697

1698+
wx_setup_mrqc(wx);
1699+
16321700
/* set_rx_buffer_len must be called before ring initialization */
16331701
wx_set_rx_buffer_len(wx);
16341702

@@ -1826,6 +1894,28 @@ int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count)
18261894
}
18271895
EXPORT_SYMBOL(wx_get_pcie_msix_counts);
18281896

1897+
/**
1898+
* wx_init_rss_key - Initialize wx RSS key
1899+
* @wx: device handle
1900+
*
1901+
* Allocates and initializes the RSS key if it is not allocated.
1902+
**/
1903+
static int wx_init_rss_key(struct wx *wx)
1904+
{
1905+
u32 *rss_key;
1906+
1907+
if (!wx->rss_key) {
1908+
rss_key = kzalloc(WX_RSS_KEY_SIZE, GFP_KERNEL);
1909+
if (unlikely(!rss_key))
1910+
return -ENOMEM;
1911+
1912+
netdev_rss_key_fill(rss_key, WX_RSS_KEY_SIZE);
1913+
wx->rss_key = rss_key;
1914+
}
1915+
1916+
return 0;
1917+
}
1918+
18291919
int wx_sw_init(struct wx *wx)
18301920
{
18311921
struct pci_dev *pdev = wx->pdev;
@@ -1853,14 +1943,23 @@ int wx_sw_init(struct wx *wx)
18531943
wx->subsystem_device_id = swab16((u16)ssid);
18541944
}
18551945

1946+
err = wx_init_rss_key(wx);
1947+
if (err < 0) {
1948+
wx_err(wx, "rss key allocation failed\n");
1949+
return err;
1950+
}
1951+
18561952
wx->mac_table = kcalloc(wx->mac.num_rar_entries,
18571953
sizeof(struct wx_mac_addr),
18581954
GFP_KERNEL);
18591955
if (!wx->mac_table) {
18601956
wx_err(wx, "mac_table allocation failed\n");
1957+
kfree(wx->rss_key);
18611958
return -ENOMEM;
18621959
}
18631960

1961+
wx->msix_in_use = false;
1962+
18641963
return 0;
18651964
}
18661965
EXPORT_SYMBOL(wx_sw_init);

drivers/net/ethernet/wangxun/libwx/wx_lib.c

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,8 +1568,14 @@ EXPORT_SYMBOL(wx_napi_disable_all);
15681568
**/
15691569
static void wx_set_rss_queues(struct wx *wx)
15701570
{
1571-
wx->num_rx_queues = wx->mac.max_rx_queues;
1572-
wx->num_tx_queues = wx->mac.max_tx_queues;
1571+
struct wx_ring_feature *f;
1572+
1573+
/* set mask for 16 queue limit of RSS */
1574+
f = &wx->ring_feature[RING_F_RSS];
1575+
f->indices = f->limit;
1576+
1577+
wx->num_rx_queues = f->limit;
1578+
wx->num_tx_queues = f->limit;
15731579
}
15741580

15751581
static void wx_set_num_queues(struct wx *wx)
@@ -1595,35 +1601,51 @@ static int wx_acquire_msix_vectors(struct wx *wx)
15951601
struct irq_affinity affd = {0, };
15961602
int nvecs, i;
15971603

1598-
nvecs = min_t(int, num_online_cpus(), wx->mac.max_msix_vectors);
1604+
/* We start by asking for one vector per queue pair */
1605+
nvecs = max(wx->num_rx_queues, wx->num_tx_queues);
1606+
nvecs = min_t(int, nvecs, num_online_cpus());
1607+
nvecs = min_t(int, nvecs, wx->mac.max_msix_vectors);
15991608

1600-
wx->msix_entries = kcalloc(nvecs,
1601-
sizeof(struct msix_entry),
1602-
GFP_KERNEL);
1603-
if (!wx->msix_entries)
1609+
wx->msix_q_entries = kcalloc(nvecs, sizeof(struct msix_entry),
1610+
GFP_KERNEL);
1611+
if (!wx->msix_q_entries)
16041612
return -ENOMEM;
16051613

1614+
/* One for non-queue interrupts */
1615+
nvecs += 1;
1616+
1617+
if (!wx->msix_in_use) {
1618+
wx->msix_entry = kcalloc(1, sizeof(struct msix_entry),
1619+
GFP_KERNEL);
1620+
if (!wx->msix_entry) {
1621+
kfree(wx->msix_q_entries);
1622+
wx->msix_q_entries = NULL;
1623+
return -ENOMEM;
1624+
}
1625+
}
1626+
16061627
nvecs = pci_alloc_irq_vectors_affinity(wx->pdev, nvecs,
16071628
nvecs,
16081629
PCI_IRQ_MSIX | PCI_IRQ_AFFINITY,
16091630
&affd);
16101631
if (nvecs < 0) {
16111632
wx_err(wx, "Failed to allocate MSI-X interrupts. Err: %d\n", nvecs);
1612-
kfree(wx->msix_entries);
1613-
wx->msix_entries = NULL;
1633+
kfree(wx->msix_q_entries);
1634+
wx->msix_q_entries = NULL;
1635+
kfree(wx->msix_entry);
1636+
wx->msix_entry = NULL;
16141637
return nvecs;
16151638
}
16161639

1640+
wx->msix_entry->entry = 0;
1641+
wx->msix_entry->vector = pci_irq_vector(wx->pdev, 0);
1642+
nvecs -= 1;
16171643
for (i = 0; i < nvecs; i++) {
1618-
wx->msix_entries[i].entry = i;
1619-
wx->msix_entries[i].vector = pci_irq_vector(wx->pdev, i);
1644+
wx->msix_q_entries[i].entry = i;
1645+
wx->msix_q_entries[i].vector = pci_irq_vector(wx->pdev, i + 1);
16201646
}
16211647

1622-
/* one for msix_other */
1623-
nvecs -= 1;
16241648
wx->num_q_vectors = nvecs;
1625-
wx->num_rx_queues = nvecs;
1626-
wx->num_tx_queues = nvecs;
16271649

16281650
return 0;
16291651
}
@@ -1645,9 +1667,11 @@ static int wx_set_interrupt_capability(struct wx *wx)
16451667
if (ret == 0 || (ret == -ENOMEM))
16461668
return ret;
16471669

1648-
wx->num_rx_queues = 1;
1649-
wx->num_tx_queues = 1;
1650-
wx->num_q_vectors = 1;
1670+
/* Disable RSS */
1671+
dev_warn(&wx->pdev->dev, "Disabling RSS support\n");
1672+
wx->ring_feature[RING_F_RSS].limit = 1;
1673+
1674+
wx_set_num_queues(wx);
16511675

16521676
/* minmum one for queue, one for misc*/
16531677
nvecs = 1;
@@ -1905,8 +1929,12 @@ void wx_reset_interrupt_capability(struct wx *wx)
19051929
return;
19061930

19071931
if (pdev->msix_enabled) {
1908-
kfree(wx->msix_entries);
1909-
wx->msix_entries = NULL;
1932+
kfree(wx->msix_q_entries);
1933+
wx->msix_q_entries = NULL;
1934+
if (!wx->msix_in_use) {
1935+
kfree(wx->msix_entry);
1936+
wx->msix_entry = NULL;
1937+
}
19101938
}
19111939
pci_free_irq_vectors(wx->pdev);
19121940
}
@@ -1978,7 +2006,7 @@ void wx_free_irq(struct wx *wx)
19782006

19792007
for (vector = 0; vector < wx->num_q_vectors; vector++) {
19802008
struct wx_q_vector *q_vector = wx->q_vector[vector];
1981-
struct msix_entry *entry = &wx->msix_entries[vector];
2009+
struct msix_entry *entry = &wx->msix_q_entries[vector];
19822010

19832011
/* free only the irqs that were actually requested */
19842012
if (!q_vector->rx.ring && !q_vector->tx.ring)
@@ -1988,7 +2016,7 @@ void wx_free_irq(struct wx *wx)
19882016
}
19892017

19902018
if (wx->mac.type == wx_mac_em)
1991-
free_irq(wx->msix_entries[vector].vector, wx);
2019+
free_irq(wx->msix_entry->vector, wx);
19922020
}
19932021
EXPORT_SYMBOL(wx_free_irq);
19942022

@@ -2065,6 +2093,7 @@ static void wx_set_ivar(struct wx *wx, s8 direction,
20652093
wr32(wx, WX_PX_MISC_IVAR, ivar);
20662094
} else {
20672095
/* tx or rx causes */
2096+
msix_vector += 1; /* offset for queue vectors */
20682097
msix_vector |= WX_PX_IVAR_ALLOC_VAL;
20692098
index = ((16 * (queue & 1)) + (8 * direction));
20702099
ivar = rd32(wx, WX_PX_IVAR(queue >> 1));
@@ -2095,7 +2124,7 @@ void wx_write_eitr(struct wx_q_vector *q_vector)
20952124

20962125
itr_reg |= WX_PX_ITR_CNT_WDIS;
20972126

2098-
wr32(wx, WX_PX_ITR(v_idx), itr_reg);
2127+
wr32(wx, WX_PX_ITR(v_idx + 1), itr_reg);
20992128
}
21002129

21012130
/**
@@ -2141,9 +2170,9 @@ void wx_configure_vectors(struct wx *wx)
21412170
wx_write_eitr(q_vector);
21422171
}
21432172

2144-
wx_set_ivar(wx, -1, 0, v_idx);
2173+
wx_set_ivar(wx, -1, 0, 0);
21452174
if (pdev->msix_enabled)
2146-
wr32(wx, WX_PX_ITR(v_idx), 1950);
2175+
wr32(wx, WX_PX_ITR(0), 1950);
21472176
}
21482177
EXPORT_SYMBOL(wx_configure_vectors);
21492178

@@ -2656,11 +2685,14 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
26562685
netdev_features_t changed = netdev->features ^ features;
26572686
struct wx *wx = netdev_priv(netdev);
26582687

2659-
if (changed & NETIF_F_RXHASH)
2688+
if (features & NETIF_F_RXHASH) {
26602689
wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN,
26612690
WX_RDB_RA_CTL_RSS_EN);
2662-
else
2691+
wx->rss_enabled = true;
2692+
} else {
26632693
wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0);
2694+
wx->rss_enabled = false;
2695+
}
26642696

26652697
if (changed &
26662698
(NETIF_F_HW_VLAN_CTAG_RX |

0 commit comments

Comments
 (0)