Skip to content

Commit 4c83f17

Browse files
caildavem330
authored andcommitted
net: aquantia: link status irq handling
Here we define and request an extra interrupt line, assign it on link isr handler and restructure abit aq_pci code to better support that. We also remove logic for using different timer intervals depending on link state, since thats now useless. Signed-off-by: Igor Russkikh <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5860808 commit 4c83f17

File tree

4 files changed

+50
-19
lines changed

4 files changed

+50
-19
lines changed

drivers/net/ethernet/aquantia/atlantic/aq_nic.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "aq_vec.h"
1515
#include "aq_hw.h"
1616
#include "aq_pci_func.h"
17+
#include "aq_main.h"
1718

1819
#include <linux/moduleparam.h>
1920
#include <linux/netdevice.h>
@@ -92,7 +93,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
9293
/*rss rings */
9394
cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF);
9495
cfg->vecs = min(cfg->vecs, num_online_cpus());
95-
cfg->vecs = min(cfg->vecs, self->irqvecs);
96+
if (self->irqvecs > AQ_HW_SERVICE_IRQS)
97+
cfg->vecs = min(cfg->vecs, self->irqvecs - AQ_HW_SERVICE_IRQS);
9698
/* cfg->vecs should be power of 2 for RSS */
9799
if (cfg->vecs >= 8U)
98100
cfg->vecs = 8U;
@@ -116,6 +118,15 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
116118
cfg->vecs = 1U;
117119
}
118120

121+
/* Check if we have enough vectors allocated for
122+
* link status IRQ. If no - we'll know link state from
123+
* slower service task.
124+
*/
125+
if (AQ_HW_SERVICE_IRQS > 0 && cfg->vecs + 1 <= self->irqvecs)
126+
cfg->link_irq_vec = cfg->vecs;
127+
else
128+
cfg->link_irq_vec = 0;
129+
119130
cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk;
120131
cfg->features = cfg->aq_hw_caps->hw_features;
121132
}
@@ -178,7 +189,6 @@ static irqreturn_t aq_linkstate_threaded_isr(int irq, void *private)
178189
static void aq_nic_service_timer_cb(struct timer_list *t)
179190
{
180191
struct aq_nic_s *self = from_timer(self, t, service_timer);
181-
int ctimer = AQ_CFG_SERVICE_TIMER_INTERVAL;
182192
int err = 0;
183193

184194
if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY))
@@ -193,12 +203,8 @@ static void aq_nic_service_timer_cb(struct timer_list *t)
193203

194204
aq_nic_update_ndev_stats(self);
195205

196-
/* If no link - use faster timer rate to detect link up asap */
197-
if (!netif_carrier_ok(self->ndev))
198-
ctimer = max(ctimer / 2, 1);
199-
200206
err_exit:
201-
mod_timer(&self->service_timer, jiffies + ctimer);
207+
mod_timer(&self->service_timer, jiffies + AQ_CFG_SERVICE_TIMER_INTERVAL);
202208
}
203209

204210
static void aq_nic_polling_timer_cb(struct timer_list *t)
@@ -359,13 +365,25 @@ int aq_nic_start(struct aq_nic_s *self)
359365
} else {
360366
for (i = 0U, aq_vec = self->aq_vec[0];
361367
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) {
362-
err = aq_pci_func_alloc_irq(self, i,
363-
self->ndev->name, aq_vec,
368+
err = aq_pci_func_alloc_irq(self, i, self->ndev->name,
369+
aq_vec_isr, aq_vec,
364370
aq_vec_get_affinity_mask(aq_vec));
365371
if (err < 0)
366372
goto err_exit;
367373
}
368374

375+
if (self->aq_nic_cfg.link_irq_vec) {
376+
int irqvec = pci_irq_vector(self->pdev,
377+
self->aq_nic_cfg.link_irq_vec);
378+
err = request_threaded_irq(irqvec, NULL,
379+
aq_linkstate_threaded_isr,
380+
IRQF_SHARED,
381+
self->ndev->name, self);
382+
if (err < 0)
383+
goto err_exit;
384+
self->msix_entry_mask |= (1 << self->aq_nic_cfg.link_irq_vec);
385+
}
386+
369387
err = self->aq_hw_ops->hw_irq_enable(self->aq_hw,
370388
AQ_CFG_IRQ_MASK);
371389
if (err < 0)

drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,43 +140,50 @@ int aq_pci_func_init(struct pci_dev *pdev)
140140
}
141141

142142
int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i,
143-
char *name, void *aq_vec, cpumask_t *affinity_mask)
143+
char *name, irq_handler_t irq_handler,
144+
void *irq_arg, cpumask_t *affinity_mask)
144145
{
145146
struct pci_dev *pdev = self->pdev;
146147
int err;
147148

148149
if (pdev->msix_enabled || pdev->msi_enabled)
149-
err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr, 0,
150-
name, aq_vec);
150+
err = request_irq(pci_irq_vector(pdev, i), irq_handler, 0,
151+
name, irq_arg);
151152
else
152153
err = request_irq(pci_irq_vector(pdev, i), aq_vec_isr_legacy,
153-
IRQF_SHARED, name, aq_vec);
154+
IRQF_SHARED, name, irq_arg);
154155

155156
if (err >= 0) {
156157
self->msix_entry_mask |= (1 << i);
157-
self->aq_vec[i] = aq_vec;
158158

159-
if (pdev->msix_enabled)
159+
if (pdev->msix_enabled && affinity_mask)
160160
irq_set_affinity_hint(pci_irq_vector(pdev, i),
161161
affinity_mask);
162162
}
163+
163164
return err;
164165
}
165166

166167
void aq_pci_func_free_irqs(struct aq_nic_s *self)
167168
{
168169
struct pci_dev *pdev = self->pdev;
169170
unsigned int i;
171+
void *irq_data;
170172

171173
for (i = 32U; i--;) {
172174
if (!((1U << i) & self->msix_entry_mask))
173175
continue;
174-
if (i >= AQ_CFG_VECS_MAX)
176+
if (self->aq_nic_cfg.link_irq_vec &&
177+
i == self->aq_nic_cfg.link_irq_vec)
178+
irq_data = self;
179+
else if (i < AQ_CFG_VECS_MAX)
180+
irq_data = self->aq_vec[i];
181+
else
175182
continue;
176183

177184
if (pdev->msix_enabled)
178185
irq_set_affinity_hint(pci_irq_vector(pdev, i), NULL);
179-
free_irq(pci_irq_vector(pdev, i), self->aq_vec[i]);
186+
free_irq(pci_irq_vector(pdev, i), irq_data);
180187
self->msix_entry_mask &= ~(1U << i);
181188
}
182189
}
@@ -269,6 +276,7 @@ static int aq_pci_probe(struct pci_dev *pdev,
269276
numvecs = min((u8)AQ_CFG_VECS_DEF,
270277
aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs);
271278
numvecs = min(numvecs, num_online_cpus());
279+
numvecs += AQ_HW_SERVICE_IRQS;
272280
/*enable interrupts */
273281
#if !AQ_CFG_FORCE_LEGACY_INT
274282
err = pci_alloc_irq_vectors(self->pdev, 1, numvecs,

drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ struct aq_board_revision_s {
2424

2525
int aq_pci_func_init(struct pci_dev *pdev);
2626
int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i,
27-
char *name, void *aq_vec,
28-
cpumask_t *affinity_mask);
27+
char *name, irq_handler_t irq_handler,
28+
void *irq_arg, cpumask_t *affinity_mask);
2929
void aq_pci_func_free_irqs(struct aq_nic_s *self);
3030
unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self);
3131

drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,11 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
443443
((HW_ATL_B0_ERR_INT << 0x18) | (1U << 0x1F)) |
444444
((HW_ATL_B0_ERR_INT << 0x10) | (1U << 0x17)), 0U);
445445

446+
/* Enable link interrupt */
447+
if (aq_nic_cfg->link_irq_vec)
448+
hw_atl_reg_gen_irq_map_set(self, BIT(7) |
449+
aq_nic_cfg->link_irq_vec, 3U);
450+
446451
hw_atl_b0_hw_offload_set(self, aq_nic_cfg);
447452

448453
err_exit:

0 commit comments

Comments
 (0)