aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDimitris Michailidis <dm@chelsio.com>2010-07-11 08:01:17 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-11 20:07:46 -0400
commit671b0060d82984a566f2e75ffd166a9b61c6da7d (patch)
tree13fe5d130f8d837f095563fca1d1e7546c9c3464 /drivers/net
parent065463915c3a2a2ce142f64ed3ed591d72ad88b1 (diff)
cxgb4: add user manipulation of the RSS table
Implement the get_rxnfc, get_rxfh_indir, and set_rxfh_indir ethtool methods for user manipulation of the RSS table. Besides the methods themselves the rest of the changes here store, initialize, and write the table contents. Signed-off-by: Dimitris Michailidis <dm@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/cxgb4/cxgb4.h1
-rw-r--r--drivers/net/cxgb4/cxgb4_main.c113
2 files changed, 98 insertions, 16 deletions
diff --git a/drivers/net/cxgb4/cxgb4.h b/drivers/net/cxgb4/cxgb4.h
index 62804bb4022d..a614eb5d85d5 100644
--- a/drivers/net/cxgb4/cxgb4.h
+++ b/drivers/net/cxgb4/cxgb4.h
@@ -295,6 +295,7 @@ struct port_info {
295 u8 nqsets; /* # of qsets */ 295 u8 nqsets; /* # of qsets */
296 u8 first_qset; /* index of first qset */ 296 u8 first_qset; /* index of first qset */
297 struct link_config link_cfg; 297 struct link_config link_cfg;
298 u16 *rss;
298}; 299};
299 300
300/* port_info.rx_offload flags */ 301/* port_info.rx_offload flags */
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index 653bb546edd3..61d43130eff2 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -597,30 +597,47 @@ static void free_msix_queue_irqs(struct adapter *adap)
597} 597}
598 598
599/** 599/**
600 * write_rss - write the RSS table for a given port
601 * @pi: the port
602 * @queues: array of queue indices for RSS
603 *
604 * Sets up the portion of the HW RSS table for the port's VI to distribute
605 * packets to the Rx queues in @queues.
606 */
607static int write_rss(const struct port_info *pi, const u16 *queues)
608{
609 u16 *rss;
610 int i, err;
611 const struct sge_eth_rxq *q = &pi->adapter->sge.ethrxq[pi->first_qset];
612
613 rss = kmalloc(pi->rss_size * sizeof(u16), GFP_KERNEL);
614 if (!rss)
615 return -ENOMEM;
616
617 /* map the queue indices to queue ids */
618 for (i = 0; i < pi->rss_size; i++, queues++)
619 rss[i] = q[*queues].rspq.abs_id;
620
621 err = t4_config_rss_range(pi->adapter, 0, pi->viid, 0, pi->rss_size,
622 rss, pi->rss_size);
623 kfree(rss);
624 return err;
625}
626
627/**
600 * setup_rss - configure RSS 628 * setup_rss - configure RSS
601 * @adap: the adapter 629 * @adap: the adapter
602 * 630 *
603 * Sets up RSS to distribute packets to multiple receive queues. We 631 * Sets up RSS for each port.
604 * configure the RSS CPU lookup table to distribute to the number of HW
605 * receive queues, and the response queue lookup table to narrow that
606 * down to the response queues actually configured for each port.
607 * We always configure the RSS mapping for all ports since the mapping
608 * table has plenty of entries.
609 */ 632 */
610static int setup_rss(struct adapter *adap) 633static int setup_rss(struct adapter *adap)
611{ 634{
612 int i, j, err; 635 int i, err;
613 u16 rss[MAX_ETH_QSETS];
614 636
615 for_each_port(adap, i) { 637 for_each_port(adap, i) {
616 const struct port_info *pi = adap2pinfo(adap, i); 638 const struct port_info *pi = adap2pinfo(adap, i);
617 const struct sge_eth_rxq *q = &adap->sge.ethrxq[pi->first_qset];
618
619 for (j = 0; j < pi->nqsets; j++)
620 rss[j] = q[j].rspq.abs_id;
621 639
622 err = t4_config_rss_range(adap, 0, pi->viid, 0, pi->rss_size, 640 err = write_rss(pi, pi->rss);
623 rss, pi->nqsets);
624 if (err) 641 if (err)
625 return err; 642 return err;
626 } 643 }
@@ -1802,6 +1819,46 @@ static int set_flags(struct net_device *dev, u32 flags)
1802 return ethtool_op_set_flags(dev, flags, ETH_FLAG_RXHASH); 1819 return ethtool_op_set_flags(dev, flags, ETH_FLAG_RXHASH);
1803} 1820}
1804 1821
1822static int get_rss_table(struct net_device *dev, struct ethtool_rxfh_indir *p)
1823{
1824 const struct port_info *pi = netdev_priv(dev);
1825 unsigned int n = min_t(unsigned int, p->size, pi->rss_size);
1826
1827 p->size = pi->rss_size;
1828 while (n--)
1829 p->ring_index[n] = pi->rss[n];
1830 return 0;
1831}
1832
1833static int set_rss_table(struct net_device *dev,
1834 const struct ethtool_rxfh_indir *p)
1835{
1836 unsigned int i;
1837 struct port_info *pi = netdev_priv(dev);
1838
1839 if (p->size != pi->rss_size)
1840 return -EINVAL;
1841 for (i = 0; i < p->size; i++)
1842 if (p->ring_index[i] >= pi->nqsets)
1843 return -EINVAL;
1844 for (i = 0; i < p->size; i++)
1845 pi->rss[i] = p->ring_index[i];
1846 if (pi->adapter->flags & FULL_INIT_DONE)
1847 return write_rss(pi, pi->rss);
1848 return 0;
1849}
1850
1851static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
1852 void *rules)
1853{
1854 switch (info->cmd) {
1855 case ETHTOOL_GRXRINGS:
1856 info->data = netdev2pinfo(dev)->nqsets;
1857 return 0;
1858 }
1859 return -EOPNOTSUPP;
1860}
1861
1805static struct ethtool_ops cxgb_ethtool_ops = { 1862static struct ethtool_ops cxgb_ethtool_ops = {
1806 .get_settings = get_settings, 1863 .get_settings = get_settings,
1807 .set_settings = set_settings, 1864 .set_settings = set_settings,
@@ -1833,6 +1890,9 @@ static struct ethtool_ops cxgb_ethtool_ops = {
1833 .set_wol = set_wol, 1890 .set_wol = set_wol,
1834 .set_tso = set_tso, 1891 .set_tso = set_tso,
1835 .set_flags = set_flags, 1892 .set_flags = set_flags,
1893 .get_rxnfc = get_rxnfc,
1894 .get_rxfh_indir = get_rss_table,
1895 .set_rxfh_indir = set_rss_table,
1836 .flash_device = set_flash, 1896 .flash_device = set_flash,
1837}; 1897};
1838 1898
@@ -3318,6 +3378,22 @@ static int __devinit enable_msix(struct adapter *adap)
3318 3378
3319#undef EXTRA_VECS 3379#undef EXTRA_VECS
3320 3380
3381static int __devinit init_rss(struct adapter *adap)
3382{
3383 unsigned int i, j;
3384
3385 for_each_port(adap, i) {
3386 struct port_info *pi = adap2pinfo(adap, i);
3387
3388 pi->rss = kcalloc(pi->rss_size, sizeof(u16), GFP_KERNEL);
3389 if (!pi->rss)
3390 return -ENOMEM;
3391 for (j = 0; j < pi->rss_size; j++)
3392 pi->rss[j] = j % pi->nqsets;
3393 }
3394 return 0;
3395}
3396
3321static void __devinit print_port_info(struct adapter *adap) 3397static void __devinit print_port_info(struct adapter *adap)
3322{ 3398{
3323 static const char *base[] = { 3399 static const char *base[] = {
@@ -3380,9 +3456,10 @@ static void free_some_resources(struct adapter *adapter)
3380 disable_msi(adapter); 3456 disable_msi(adapter);
3381 3457
3382 for_each_port(adapter, i) 3458 for_each_port(adapter, i)
3383 if (adapter->port[i]) 3459 if (adapter->port[i]) {
3460 kfree(adap2pinfo(adapter, i)->rss);
3384 free_netdev(adapter->port[i]); 3461 free_netdev(adapter->port[i]);
3385 3462 }
3386 if (adapter->flags & FW_OK) 3463 if (adapter->flags & FW_OK)
3387 t4_fw_bye(adapter, 0); 3464 t4_fw_bye(adapter, 0);
3388} 3465}
@@ -3536,6 +3613,10 @@ static int __devinit init_one(struct pci_dev *pdev,
3536 else if (msi > 0 && pci_enable_msi(pdev) == 0) 3613 else if (msi > 0 && pci_enable_msi(pdev) == 0)
3537 adapter->flags |= USING_MSI; 3614 adapter->flags |= USING_MSI;
3538 3615
3616 err = init_rss(adapter);
3617 if (err)
3618 goto out_free_dev;
3619
3539 /* 3620 /*
3540 * The card is now ready to go. If any errors occur during device 3621 * The card is now ready to go. If any errors occur during device
3541 * registration we do not fail the whole card but rather proceed only 3622 * registration we do not fail the whole card but rather proceed only