mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-14 12:37:32 +00:00
qlcnic: Use shared interrupt vector for Tx and Rx
o VF will use shared MSI-X interrupt vector for Tx and Rx. o When QLCNIC_INTR_SHARED flag is set Tx and Rx will share MSI-X interrupt vector. Tx will use a separate MSI-X interrupt vector from Rx otherwise. Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f846833164
commit
da6c806311
5 changed files with 80 additions and 22 deletions
|
@ -897,6 +897,7 @@ struct qlcnic_ipaddr {
|
||||||
#define QLCNIC_FW_RESET_OWNER 0x2000
|
#define QLCNIC_FW_RESET_OWNER 0x2000
|
||||||
#define QLCNIC_FW_HANG 0x4000
|
#define QLCNIC_FW_HANG 0x4000
|
||||||
#define QLCNIC_FW_LRO_MSS_CAP 0x8000
|
#define QLCNIC_FW_LRO_MSS_CAP 0x8000
|
||||||
|
#define QLCNIC_TX_INTR_SHARED 0x10000
|
||||||
#define QLCNIC_IS_MSI_FAMILY(adapter) \
|
#define QLCNIC_IS_MSI_FAMILY(adapter) \
|
||||||
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
|
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
|
||||||
|
|
||||||
|
|
|
@ -410,7 +410,10 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
|
||||||
num_intr));
|
num_intr));
|
||||||
/* account for AEN interrupt MSI-X based interrupts */
|
/* account for AEN interrupt MSI-X based interrupts */
|
||||||
num_msix += 1;
|
num_msix += 1;
|
||||||
num_msix += adapter->max_drv_tx_rings;
|
|
||||||
|
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
|
||||||
|
num_msix += adapter->max_drv_tx_rings;
|
||||||
|
|
||||||
err = qlcnic_enable_msix(adapter, num_msix);
|
err = qlcnic_enable_msix(adapter, num_msix);
|
||||||
if (err == -ENOMEM)
|
if (err == -ENOMEM)
|
||||||
return err;
|
return err;
|
||||||
|
@ -1243,6 +1246,7 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
|
||||||
struct qlcnic_tx_mbx mbx;
|
struct qlcnic_tx_mbx mbx;
|
||||||
struct qlcnic_tx_mbx_out *mbx_out;
|
struct qlcnic_tx_mbx_out *mbx_out;
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
u32 msix_vector;
|
||||||
|
|
||||||
/* Reset host resources */
|
/* Reset host resources */
|
||||||
tx->producer = 0;
|
tx->producer = 0;
|
||||||
|
@ -1257,10 +1261,16 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
|
||||||
mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr);
|
mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr);
|
||||||
mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr);
|
mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr);
|
||||||
mbx.size = tx->num_desc;
|
mbx.size = tx->num_desc;
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED)
|
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
||||||
msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id;
|
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED))
|
||||||
else
|
msix_vector = adapter->max_sds_rings + ring;
|
||||||
|
else
|
||||||
|
msix_vector = adapter->max_sds_rings - 1;
|
||||||
|
msix_id = ahw->intr_tbl[msix_vector].id;
|
||||||
|
} else {
|
||||||
msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
|
msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID);
|
||||||
|
}
|
||||||
|
|
||||||
if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
|
if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST)
|
||||||
mbx.intr_id = msix_id;
|
mbx.intr_id = msix_id;
|
||||||
else
|
else
|
||||||
|
@ -1282,7 +1292,8 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,
|
||||||
mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
|
mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2];
|
||||||
tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod;
|
tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod;
|
||||||
tx->ctx_id = mbx_out->ctx_id;
|
tx->ctx_id = mbx_out->ctx_id;
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src;
|
intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src;
|
||||||
tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
|
tx->crb_intr_mask = ahw->pci_base0 + intr_mask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1691,6 +1691,29 @@ static int qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qlcnic_83xx_msix_sriov_vf_poll(struct napi_struct *napi, int budget)
|
||||||
|
{
|
||||||
|
int tx_complete;
|
||||||
|
int work_done;
|
||||||
|
struct qlcnic_host_sds_ring *sds_ring;
|
||||||
|
struct qlcnic_adapter *adapter;
|
||||||
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
|
|
||||||
|
sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
|
||||||
|
adapter = sds_ring->adapter;
|
||||||
|
/* tx ring count = 1 */
|
||||||
|
tx_ring = adapter->tx_ring;
|
||||||
|
|
||||||
|
tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget);
|
||||||
|
work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget);
|
||||||
|
if ((work_done < budget) && tx_complete) {
|
||||||
|
napi_complete(&sds_ring->napi);
|
||||||
|
qlcnic_83xx_enable_intr(adapter, sds_ring);
|
||||||
|
}
|
||||||
|
|
||||||
|
return work_done;
|
||||||
|
}
|
||||||
|
|
||||||
static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
|
static int qlcnic_83xx_poll(struct napi_struct *napi, int budget)
|
||||||
{
|
{
|
||||||
int tx_complete;
|
int tx_complete;
|
||||||
|
@ -1768,7 +1791,8 @@ void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter)
|
||||||
qlcnic_83xx_enable_intr(adapter, sds_ring);
|
qlcnic_83xx_enable_intr(adapter, sds_ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
napi_enable(&tx_ring->napi);
|
napi_enable(&tx_ring->napi);
|
||||||
|
@ -1795,7 +1819,8 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
|
||||||
napi_disable(&sds_ring->napi);
|
napi_disable(&sds_ring->napi);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
qlcnic_83xx_disable_tx_intr(adapter, tx_ring);
|
qlcnic_83xx_disable_tx_intr(adapter, tx_ring);
|
||||||
|
@ -1808,7 +1833,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter)
|
||||||
int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
|
int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
|
||||||
struct net_device *netdev)
|
struct net_device *netdev)
|
||||||
{
|
{
|
||||||
int ring, max_sds_rings;
|
int ring, max_sds_rings, temp;
|
||||||
struct qlcnic_host_sds_ring *sds_ring;
|
struct qlcnic_host_sds_ring *sds_ring;
|
||||||
struct qlcnic_host_tx_ring *tx_ring;
|
struct qlcnic_host_tx_ring *tx_ring;
|
||||||
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
|
||||||
|
@ -1819,14 +1844,23 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
|
||||||
max_sds_rings = adapter->max_sds_rings;
|
max_sds_rings = adapter->max_sds_rings;
|
||||||
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
|
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
|
||||||
sds_ring = &recv_ctx->sds_rings[ring];
|
sds_ring = &recv_ctx->sds_rings[ring];
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED)
|
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
||||||
netif_napi_add(netdev, &sds_ring->napi,
|
if (!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
qlcnic_83xx_rx_poll,
|
netif_napi_add(netdev, &sds_ring->napi,
|
||||||
QLCNIC_NETDEV_WEIGHT * 2);
|
qlcnic_83xx_rx_poll,
|
||||||
else
|
QLCNIC_NETDEV_WEIGHT * 2);
|
||||||
|
} else {
|
||||||
|
temp = QLCNIC_NETDEV_WEIGHT / max_sds_rings;
|
||||||
|
netif_napi_add(netdev, &sds_ring->napi,
|
||||||
|
qlcnic_83xx_msix_sriov_vf_poll,
|
||||||
|
temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
netif_napi_add(netdev, &sds_ring->napi,
|
netif_napi_add(netdev, &sds_ring->napi,
|
||||||
qlcnic_83xx_poll,
|
qlcnic_83xx_poll,
|
||||||
QLCNIC_NETDEV_WEIGHT / max_sds_rings);
|
QLCNIC_NETDEV_WEIGHT / max_sds_rings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qlcnic_alloc_tx_rings(adapter, netdev)) {
|
if (qlcnic_alloc_tx_rings(adapter, netdev)) {
|
||||||
|
@ -1834,7 +1868,8 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adapter->flags & QLCNIC_MSIX_ENABLED) {
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
netif_napi_add(netdev, &tx_ring->napi,
|
netif_napi_add(netdev, &tx_ring->napi,
|
||||||
|
@ -1860,7 +1895,8 @@ void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
qlcnic_free_sds_rings(adapter->recv_ctx);
|
qlcnic_free_sds_rings(adapter->recv_ctx);
|
||||||
|
|
||||||
if ((adapter->flags & QLCNIC_MSIX_ENABLED)) {
|
if ((adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
netif_napi_del(&tx_ring->napi);
|
netif_napi_del(&tx_ring->napi);
|
||||||
|
|
|
@ -400,7 +400,15 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = adapter->pdev;
|
struct pci_dev *pdev = adapter->pdev;
|
||||||
int err = -1, i;
|
int err = -1, i;
|
||||||
int max_tx_rings;
|
int max_tx_rings, tx_vector;
|
||||||
|
|
||||||
|
if (adapter->flags & QLCNIC_TX_INTR_SHARED) {
|
||||||
|
max_tx_rings = 0;
|
||||||
|
tx_vector = 0;
|
||||||
|
} else {
|
||||||
|
max_tx_rings = adapter->max_drv_tx_rings;
|
||||||
|
tx_vector = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!adapter->msix_entries) {
|
if (!adapter->msix_entries) {
|
||||||
adapter->msix_entries = kcalloc(num_msix,
|
adapter->msix_entries = kcalloc(num_msix,
|
||||||
|
@ -423,7 +431,6 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
|
||||||
if (qlcnic_83xx_check(adapter)) {
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
adapter->ahw->num_msix = num_msix;
|
adapter->ahw->num_msix = num_msix;
|
||||||
/* subtract mail box and tx ring vectors */
|
/* subtract mail box and tx ring vectors */
|
||||||
max_tx_rings = adapter->max_drv_tx_rings;
|
|
||||||
adapter->max_sds_rings = num_msix -
|
adapter->max_sds_rings = num_msix -
|
||||||
max_tx_rings - 1;
|
max_tx_rings - 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -436,11 +443,11 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
|
||||||
"Unable to allocate %d MSI-X interrupt vectors\n",
|
"Unable to allocate %d MSI-X interrupt vectors\n",
|
||||||
num_msix);
|
num_msix);
|
||||||
if (qlcnic_83xx_check(adapter)) {
|
if (qlcnic_83xx_check(adapter)) {
|
||||||
if (err < QLC_83XX_MINIMUM_VECTOR)
|
if (err < (QLC_83XX_MINIMUM_VECTOR - tx_vector))
|
||||||
return err;
|
return err;
|
||||||
err -= (adapter->max_drv_tx_rings + 1);
|
err -= (max_tx_rings + 1);
|
||||||
num_msix = rounddown_pow_of_two(err);
|
num_msix = rounddown_pow_of_two(err);
|
||||||
num_msix += (adapter->max_drv_tx_rings + 1);
|
num_msix += (max_tx_rings + 1);
|
||||||
} else {
|
} else {
|
||||||
num_msix = rounddown_pow_of_two(err);
|
num_msix = rounddown_pow_of_two(err);
|
||||||
}
|
}
|
||||||
|
@ -1285,7 +1292,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (qlcnic_83xx_check(adapter) &&
|
if (qlcnic_83xx_check(adapter) &&
|
||||||
(adapter->flags & QLCNIC_MSIX_ENABLED)) {
|
(adapter->flags & QLCNIC_MSIX_ENABLED) &&
|
||||||
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
handler = qlcnic_msix_tx_intr;
|
handler = qlcnic_msix_tx_intr;
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings;
|
for (ring = 0; ring < adapter->max_drv_tx_rings;
|
||||||
ring++) {
|
ring++) {
|
||||||
|
@ -1321,7 +1329,8 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter)
|
||||||
free_irq(sds_ring->irq, sds_ring);
|
free_irq(sds_ring->irq, sds_ring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (qlcnic_83xx_check(adapter)) {
|
if (qlcnic_83xx_check(adapter) &&
|
||||||
|
!(adapter->flags & QLCNIC_TX_INTR_SHARED)) {
|
||||||
for (ring = 0; ring < adapter->max_drv_tx_rings;
|
for (ring = 0; ring < adapter->max_drv_tx_rings;
|
||||||
ring++) {
|
ring++) {
|
||||||
tx_ring = &adapter->tx_ring[ring];
|
tx_ring = &adapter->tx_ring[ring];
|
||||||
|
|
|
@ -137,6 +137,7 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac)
|
||||||
spin_lock_init(&ahw->mbx_lock);
|
spin_lock_init(&ahw->mbx_lock);
|
||||||
set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
|
set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
|
||||||
ahw->msix_supported = 1;
|
ahw->msix_supported = 1;
|
||||||
|
adapter->flags |= QLCNIC_TX_INTR_SHARED;
|
||||||
|
|
||||||
if (qlcnic_sriov_setup_vf(adapter, pci_using_dac))
|
if (qlcnic_sriov_setup_vf(adapter, pci_using_dac))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
Loading…
Reference in a new issue