alx: add msi-x support
Subsystems (3)
cover alx: add msi-x support
This patchset adds msi-x support to the alx driver. It is a preparatory series for multi queue support, which I am currently working on. As there is no advantage over msi interrupts without multi queue support, msi-x interrupts are disabled by default. In order to test for regressions, a new module parameter is added to enable msi-x interrupts.
Based on information of the downstream driver at github.com/qca/alx
Tobias Regnery (4):
alx: refactor msi enablement and disablement
alx: factor out part of the interrupt handler
alx: add msi-x support
alx: add module parameter to enable msi-x support
drivers/net/ethernet/atheros/alx/alx.h | 10 +- drivers/net/ethernet/atheros/alx/hw.c | 14 ++ drivers/net/ethernet/atheros/alx/hw.h | 1 + drivers/net/ethernet/atheros/alx/main.c | 235 ++++++++++++++++++++++++++++---- 4 files changed, 231 insertions(+), 29 deletions(-)
Signature · 1 line
2.7.4
PATCH 1/4 alx: refactor msi enablement and disablement
Introduce a new flag field for the advanced interrupt capatibilities and add new functions to enable and disable msi interrupts. These functions will be extended later to cover msi-x interrupts.
We enable msi interrupts earlier in alx_init_intr because with msi-x and multi queue support the number of queues must be set before we allocate resources for the rx and tx paths.
--- drivers/net/ethernet/atheros/alx/alx.h | 5 ++++- drivers/net/ethernet/atheros/alx/main.c | 30 ++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 9 deletions(-)
drivers/net/ethernet/atheros/alx/alx.h +4 -1
@@ -76,6 +76,9 @@ enum alx_device_quirks { ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG = BIT(0), }; +#define ALX_FLAG_USING_MSIX BIT(0) +#define ALX_FLAG_USING_MSI BIT(1) +struct alx_priv {struct net_device *dev;
@@ -105,7 +108,7 @@ struct alx_priv {u16 msg_enable; -bool msi; +int flags;/* protects hw.stats */ spinlock_t stats_lock;
drivers/net/ethernet/atheros/alx/main.c +22 -8
@@ -620,6 +620,22 @@ static void alx_config_vector_mapping(struct alx_priv *alx)alx_write_mem32 (hw,ALX_MSI_ID_MAP ,0 ); } +static void alx_init_intr (struct alx_priv *alx,bool msix) +{ +if (!(alx->flags &ALX_FLAG_USING_MSIX )) { +if (!pci_enable_msi (alx->hw.pdev)) + alx->flags |=ALX_FLAG_USING_MSI ; + } +} + +static void alx_disable_advanced_intr (struct alx_priv *alx) +{ +if (alx->flags &ALX_FLAG_USING_MSI ) { +pci_disable_msi (alx->hw.pdev); + alx->flags &= ~ALX_FLAG_USING_MSI ; + } +} +static void alx_irq_enable (struct alx_priv *alx) {struct alx_hw *hw = &alx->hw;
@@ -650,9 +666,7 @@ static int alx_request_irq(struct alx_priv *alx) msi_ctrl = (hw->imt >>1 ) <<ALX_MSI_RETRANS_TM_SHIFT ; -if (!pci_enable_msi (alx->hw.pdev)) { - alx->msi = true; - +if (alx->flags &ALX_FLAG_USING_MSI ) {alx_write_mem32 (hw,ALX_MSI_RETRANS_TIMER , msi_ctrl |ALX_MSI_MASK_SEL_LINE ); err = request_irq(pdev->irq, alx_intr_msi, 0,
@@ -660,6 +674,7 @@ static int alx_request_irq(struct alx_priv *alx)if (!err) goto out;/* fall back to legacy interrupt */ + alx->flags &= ~ALX_FLAG_USING_MSI ;pci_disable_msi (alx->hw.pdev); }
@@ -678,10 +693,7 @@ static void alx_free_irq(struct alx_priv *alx)free_irq (pdev->irq, alx); -if (alx->msi) { -pci_disable_msi (alx->hw.pdev); - alx->msi = false; - } +alx_disable_advanced_intr (alx); }static int alx_identify_hw (struct alx_priv *alx)
@@ -847,6 +859,8 @@ static int __alx_open(struct alx_priv *alx, bool resume) {int err; +alx_init_intr (alx, false); +if (!resume)netif_carrier_off (alx->dev);
@@ -1236,7 +1250,7 @@ static void alx_poll_controller(struct net_device *netdev) {struct alx_priv *alx =netdev_priv (netdev); -if (alx->msi) +if (alx->flags &ALX_FLAG_USING_MSI )alx_intr_msi (0 , alx);else alx_intr_legacy (0 , alx);
Signature · 1 line
2.7.4
PATCH 2/4 alx: factor out part of the interrupt handler
In reply to Tobias RegneryFactor out the handling of misc interrupts into a new function. This function can be reused later for msi-x interrupts.
--- drivers/net/ethernet/atheros/alx/main.c | 34 +++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-)
drivers/net/ethernet/atheros/alx/main.c +20 -14
@@ -302,22 +302,15 @@ static int alx_poll(struct napi_struct *napi, int budget)return work; } -static irqreturn_t alx_intr_handle (struct alx_priv *alx,u32 intr) +static bool alx_intr_handle_misc (struct alx_priv *alx,u32 intr) {struct alx_hw *hw = &alx->hw; -bool write_int_mask = false; - -spin_lock (&alx->irq_lock); - -/* ACK interrupt */ -alx_write_mem32 (hw,ALX_ISR , intr |ALX_ISR_DIS ); - intr &= alx->int_mask;if (intr &ALX_ISR_FATAL ) {netif_warn (alx, hw, alx->dev,"fatal interrupt 0x%x, resetting\n" , intr);alx_schedule_reset (alx); - goto out; +return true; }if (intr &ALX_ISR_ALERT )
@@ -329,19 +322,32 @@ static irqreturn_t alx_intr_handle(struct alx_priv *alx, u32 intr)* is cleared, the interrupt status could be cleared. */ alx->int_mask &= ~ALX_ISR_PHY ; - write_int_mask = true; +alx_write_mem32 (hw,ALX_IMR , alx->int_mask);alx_schedule_link_check (alx); } +return false; +} + +static irqreturn_t alx_intr_handle (struct alx_priv *alx,u32 intr) +{ +struct alx_hw *hw = &alx->hw; + +spin_lock (&alx->irq_lock); + +/* ACK interrupt */ +alx_write_mem32 (hw,ALX_ISR , intr |ALX_ISR_DIS ); + intr &= alx->int_mask; + +if (alx_intr_handle_misc (alx, intr)) + goto out; +if (intr & (ALX_ISR_TX_Q0 |ALX_ISR_RX_Q0 )) {napi_schedule (&alx->napi);/* mask rx/tx interrupt, enable them when napi complete */ alx->int_mask &= ~ALX_ISR_ALL_QUEUES ; - write_int_mask = true; - } - -if (write_int_mask)alx_write_mem32 (hw,ALX_IMR , alx->int_mask); + }alx_write_mem32 (hw,ALX_ISR ,0 );
Signature · 1 line
2.7.4
PATCH 3/4 alx: add msi-x support
In reply to Tobias RegneryAdd msi-x support to the alx driver. This is in preparation for multi queue support.
msi-x interrupts are disabled by default because without multi queue support there is no advantage over msi interrupts. The performance numbers observed with iperf stay the same.
Based on information of the downstream driver at github.com/qca/alx
--- drivers/net/ethernet/atheros/alx/alx.h | 5 + drivers/net/ethernet/atheros/alx/hw.c | 14 +++ drivers/net/ethernet/atheros/alx/hw.h | 1 + drivers/net/ethernet/atheros/alx/main.c | 172 ++++++++++++++++++++++++++++++-- 4 files changed, 184 insertions(+), 8 deletions(-)
drivers/net/ethernet/atheros/alx/alx.h +5 -0
@@ -84,6 +84,11 @@ struct alx_priv {struct alx_hw hw; +/* msi-x vectors */ +int num_vec; +struct msix_entry *msix_entries; +char irq_lbl[IFNAMSIZ +8 ]; +/* all descriptor memory */ struct {dma_addr_t dma;
drivers/net/ethernet/atheros/alx/hw.c +14 -0
@@ -1031,6 +1031,20 @@ void alx_configure_basic(struct alx_hw *hw)alx_write_mem32 (hw,ALX_WRR , val); } +void alx_mask_msix (struct alx_hw *hw,int index,bool mask) +{ +u32 reg, val; + + reg =ALX_MSIX_ENTRY_BASE + index *PCI_MSIX_ENTRY_SIZE + +PCI_MSIX_ENTRY_VECTOR_CTRL ; + + val = mask ?PCI_MSIX_ENTRY_CTRL_MASKBIT :0 ; + +alx_write_mem32 (hw, reg, val); +alx_post_write (hw); +} + +bool alx_get_phy_info (struct alx_hw *hw) {u16 devs1, devs2;
drivers/net/ethernet/atheros/alx/hw.h +1 -0
@@ -562,6 +562,7 @@ int alx_reset_mac(struct alx_hw *hw);void alx_set_macaddr (struct alx_hw *hw,const u8 *addr);bool alx_phy_configured (struct alx_hw *hw);void alx_configure_basic (struct alx_hw *hw); +void alx_mask_msix (struct alx_hw *hw,int index,bool mask);void alx_disable_rss (struct alx_hw *hw);bool alx_get_phy_info (struct alx_hw *hw);void alx_update_hw_stats (struct alx_hw *hw);
drivers/net/ethernet/atheros/alx/main.c +164 -8
250 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH 4/4 alx: add module parameter to enable msi-x support
In reply to Tobias Regnerymsi-x support is default disabled in the alx driver. In order to test msi-x interrupts for regressions add a module parameter to the driver.
--- drivers/net/ethernet/atheros/alx/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/atheros/alx/main.c +4 -1
@@ -51,6 +51,9 @@const char alx_drv_name[] ="alx" ; +static bool msix = false; +module_param (msix, bool,0 ); +MODULE_PARM_DESC (msix,"Enable msi-x interrupt support" );static void alx_free_txbuf (struct alx_priv *alx,int entry) {
@@ -1018,7 +1021,7 @@ static int __alx_open(struct alx_priv *alx, bool resume) {int err; -alx_init_intr (alx, false); +alx_init_intr (alx, msix);if (!resume)netif_carrier_off (alx->dev);
Signature · 1 line
2.7.4
David Miller
maintainerFrom: Tobias Regnery <[email protected]>
Date: Fri, 9 Sep 2016 12:19:51 +0200
Quoted 7 lines
This patchset adds msi-x support to the alx driver. It is a preparatory series for multi queue support, which I am currently working on. As there is no advantage over msi interrupts without multi queue support, msi-x interrupts are disabled by default. In order to test for regressions, a new module parameter is added to enable msi-x interrupts.
Based on information of the downstream driver at github.com/qca/alx
Series applied, thanks.