提交 f94bc1e7 编写于 作者: S Sucheta Chakraborty 提交者: David S. Miller

qlcnic: support rcv ring configuration through ethtool

o Support ethtool command ETHTOOL_GCHANNELS and ETHTOOL_SCHANNELS.
o Number of rcv rings configuration depend upon number of msix vector.
Signed-off-by: NSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: NAmit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 ad246c99
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -118,7 +118,6 @@
#define PHAN_PEG_RCV_INITIALIZED 0xff01
#define NUM_RCV_DESC_RINGS 3
#define NUM_STS_DESC_RINGS 4
#define RCV_RING_NORMAL 0
#define RCV_RING_JUMBO 1
......@@ -871,7 +870,8 @@ struct qlcnic_ipaddr {
#define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
#define MSIX_ENTRIES_PER_ADAPTER NUM_STS_DESC_RINGS
#define QLCNIC_DEF_NUM_STS_DESC_RINGS 4
#define QLCNIC_MIN_NUM_RSS_RINGS 2
#define QLCNIC_MSIX_TBL_SPACE 8192
#define QLCNIC_PCI_REG_MSIX_TBL 0x44
#define QLCNIC_MSIX_TBL_PGSIZE 4096
......@@ -987,7 +987,7 @@ struct qlcnic_adapter {
void __iomem *crb_int_state_reg;
void __iomem *isr_int_vec;
struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
struct msix_entry *msix_entries;
struct delayed_work fw_work;
......@@ -1262,6 +1262,8 @@ u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val);
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data);
/* Management functions */
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
......
......@@ -474,6 +474,39 @@ qlcnic_set_ringparam(struct net_device *dev,
return qlcnic_reset_context(adapter);
}
static void qlcnic_get_channels(struct net_device *dev,
struct ethtool_channels *channel)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
channel->max_rx = rounddown_pow_of_two(min_t(int,
adapter->max_rx_ques, num_online_cpus()));
channel->max_tx = adapter->max_tx_ques;
channel->rx_count = adapter->max_sds_rings;
channel->tx_count = adapter->max_tx_ques;
}
static int qlcnic_set_channels(struct net_device *dev,
struct ethtool_channels *channel)
{
struct qlcnic_adapter *adapter = netdev_priv(dev);
int err;
if (channel->other_count || channel->combined_count ||
channel->tx_count != channel->max_tx)
return -EINVAL;
err = qlcnic_validate_max_rss(dev, channel->max_rx, channel->rx_count);
if (err)
return err;
err = qlcnic_set_max_rss(adapter, channel->rx_count);
netdev_info(dev, "allocated 0x%x sds rings\n",
adapter->max_sds_rings);
return err;
}
static void
qlcnic_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
......@@ -949,6 +982,8 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
.get_eeprom = qlcnic_get_eeprom,
.get_ringparam = qlcnic_get_ringparam,
.set_ringparam = qlcnic_set_ringparam,
.get_channels = qlcnic_get_channels,
.set_channels = qlcnic_set_channels,
.get_pauseparam = qlcnic_get_pauseparam,
.set_pauseparam = qlcnic_set_pauseparam,
.get_wol = qlcnic_get_wol,
......
......@@ -18,6 +18,7 @@
#include <linux/inetdevice.h>
#include <linux/sysfs.h>
#include <linux/aer.h>
#include <linux/log2.h>
MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver");
MODULE_LICENSE("GPL");
......@@ -350,39 +351,17 @@ static struct qlcnic_nic_template qlcnic_vf_ops = {
.start_firmware = qlcnicvf_start_firmware
};
static void
qlcnic_setup_intr(struct qlcnic_adapter *adapter)
static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
{
const struct qlcnic_legacy_intr_set *legacy_intrp;
struct pci_dev *pdev = adapter->pdev;
int err, num_msix;
if (adapter->msix_supported) {
num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ?
MSIX_ENTRIES_PER_ADAPTER : 2;
} else
num_msix = 1;
int err = -1;
adapter->max_sds_rings = 1;
adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
adapter->int_vec_bit = legacy_intrp->int_vec_bit;
adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
legacy_intrp->tgt_status_reg);
adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter,
legacy_intrp->tgt_mask_reg);
adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR);
adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter,
ISR_INT_STATE_REG);
qlcnic_set_msix_bit(pdev, 0);
if (adapter->msix_supported) {
enable_msix:
qlcnic_init_msix_entries(adapter, num_msix);
err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
if (err == 0) {
......@@ -392,14 +371,22 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
adapter->max_sds_rings = num_msix;
dev_info(&pdev->dev, "using msi-x interrupts\n");
return;
return err;
}
if (err > 0) {
num_msix = rounddown_pow_of_two(err);
if (num_msix)
goto enable_msix;
}
}
return err;
}
if (err > 0)
pci_disable_msix(pdev);
/* fall through for msi */
}
static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
{
const struct qlcnic_legacy_intr_set *legacy_intrp;
struct pci_dev *pdev = adapter->pdev;
if (use_msi && !pci_enable_msi(pdev)) {
adapter->flags |= QLCNIC_MSI_ENABLED;
......@@ -410,10 +397,40 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
return;
}
legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
adapter->int_vec_bit = legacy_intrp->int_vec_bit;
adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
legacy_intrp->tgt_status_reg);
adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter,
legacy_intrp->tgt_mask_reg);
adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR);
adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter,
ISR_INT_STATE_REG);
dev_info(&pdev->dev, "using legacy interrupts\n");
adapter->msix_entries[0].vector = pdev->irq;
}
static void
qlcnic_setup_intr(struct qlcnic_adapter *adapter)
{
int num_msix;
if (adapter->msix_supported) {
num_msix = (num_online_cpus() >=
QLCNIC_DEF_NUM_STS_DESC_RINGS) ?
QLCNIC_DEF_NUM_STS_DESC_RINGS :
QLCNIC_MIN_NUM_RSS_RINGS;
} else
num_msix = 1;
if (!qlcnic_enable_msix(adapter, num_msix))
return;
qlcnic_enable_msi_legacy(adapter);
}
static void
qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
{
......@@ -1493,6 +1510,19 @@ static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac)
return 0;
}
static int
qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count)
{
adapter->msix_entries = kcalloc(count, sizeof(struct msix_entry),
GFP_KERNEL);
if (adapter->msix_entries)
return 0;
dev_err(&adapter->pdev->dev, "failed allocating msix_entries\n");
return -ENOMEM;
}
static int __devinit
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
......@@ -1587,6 +1617,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
qlcnic_clear_stats(adapter);
err = qlcnic_alloc_msix_entries(adapter, adapter->max_rx_ques);
if (err)
goto err_out_decr_ref;
qlcnic_setup_intr(adapter);
err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
......@@ -1615,6 +1649,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_disable_msi:
qlcnic_teardown_intr(adapter);
kfree(adapter->msix_entries);
err_out_decr_ref:
qlcnic_clr_all_drv_state(adapter, 0);
......@@ -1666,6 +1701,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
qlcnic_free_lb_filters_mem(adapter);
qlcnic_teardown_intr(adapter);
kfree(adapter->msix_entries);
qlcnic_remove_diag_entries(adapter);
......@@ -3299,6 +3335,56 @@ static struct device_attribute dev_attr_diag_mode = {
.store = qlcnic_store_diag_mode,
};
int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
{
if (!use_msi_x && !use_msi) {
netdev_info(netdev, "no msix or msi support, hence no rss\n");
return -EINVAL;
}
if ((val > max_hw) || (val < 2) || !is_power_of_2(val)) {
netdev_info(netdev, "rss_ring valid range [2 - %x] in "
" powers of 2\n", max_hw);
return -EINVAL;
}
return 0;
}
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
{
struct net_device *netdev = adapter->netdev;
int err = 0;
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
return -EBUSY;
netif_device_detach(netdev);
if (netif_running(netdev))
__qlcnic_down(adapter, netdev);
qlcnic_detach(adapter);
qlcnic_teardown_intr(adapter);
if (qlcnic_enable_msix(adapter, data)) {
netdev_info(netdev, "failed setting max_rss; rss disabled\n");
qlcnic_enable_msi_legacy(adapter);
}
if (netif_running(netdev)) {
err = qlcnic_attach(adapter);
if (err)
goto done;
err = __qlcnic_up(adapter, netdev);
if (err)
goto done;
qlcnic_restore_indev_addr(netdev, NETDEV_UP);
}
done:
netif_device_attach(netdev);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
return err;
}
static int
qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
loff_t offset, size_t size)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部