mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 07:39:12 -04:00
Merge branch 'eth-bnxt-fix-irq-notifier-bugs'
Jakub Kicinski says: ==================== eth: bnxt: fix IRQ notifier bugs I was trying to make bnxt preserve IRQ mappings across reconfiguration. While hacking on that I noticed 2 bugs in the notifiers that should probably be fixed before development work. First one is simple - TPH recofig makes aARFs not work. There can only be one notifier per IRQ and TPH "steals" the callback from the rmap updates. Fix by patches 1 and 2. Second one is a deadlock between the affinity notifier and reconfig. This one is a bit more involved (patch 3 and 4). Unfortunately, I can't really verify the problem or test the fix. I managed to get my hands on a system with an AMD Venice CPU which is supposed to support TPH, but the ACPI is missing some bits to actually advertise it. pcie_tph_get_cpu_st() returns -EINVAL. ==================== Link: https://patch.msgid.link/20260803193135.2030368-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -11789,10 +11789,21 @@ static void bnxt_irq_affinity_notify(struct irq_affinity_notify *notify,
|
||||
{
|
||||
struct bnxt_irq *irq;
|
||||
u16 tag;
|
||||
int err;
|
||||
|
||||
irq = container_of(notify, struct bnxt_irq, affinity_notify);
|
||||
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
if (irq->bp->dev->rx_cpu_rmap && irq->ring_nr < irq->bp->rx_nr_rings) {
|
||||
int err;
|
||||
|
||||
err = cpu_rmap_update(irq->bp->dev->rx_cpu_rmap, irq->ring_nr,
|
||||
mask);
|
||||
if (err)
|
||||
netdev_warn(irq->bp->dev,
|
||||
"aRFS rmap update failed: %d\n", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!irq->bp->tph_mode)
|
||||
return;
|
||||
|
||||
@@ -11802,20 +11813,11 @@ static void bnxt_irq_affinity_notify(struct irq_affinity_notify *notify,
|
||||
return;
|
||||
|
||||
if (pcie_tph_get_cpu_st(irq->bp->pdev, TPH_MEM_TYPE_VM,
|
||||
cpumask_first(irq->cpu_mask), &tag))
|
||||
cpumask_first(mask), &tag))
|
||||
return;
|
||||
|
||||
if (pcie_tph_set_st_entry(irq->bp->pdev, irq->msix_nr, tag))
|
||||
return;
|
||||
|
||||
netdev_lock(irq->bp->dev);
|
||||
if (netif_running(irq->bp->dev)) {
|
||||
err = netdev_rx_queue_restart(irq->bp->dev, irq->ring_nr);
|
||||
if (err)
|
||||
netdev_err(irq->bp->dev,
|
||||
"RX queue restart failed: err=%d\n", err);
|
||||
}
|
||||
netdev_unlock(irq->bp->dev);
|
||||
WRITE_ONCE(irq->new_tag, tag);
|
||||
bnxt_queue_sp_work(irq->bp, BNXT_TPH_UPDATE_SP_EVENT);
|
||||
}
|
||||
|
||||
static void bnxt_irq_affinity_release(struct kref *ref)
|
||||
@@ -11866,10 +11868,6 @@ static void bnxt_free_irq(struct bnxt *bp)
|
||||
struct bnxt_irq *irq;
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
free_irq_cpu_rmap(bp->dev->rx_cpu_rmap);
|
||||
bp->dev->rx_cpu_rmap = NULL;
|
||||
#endif
|
||||
if (!bp->irq_tbl || !bp->bnapi)
|
||||
return;
|
||||
|
||||
@@ -11878,27 +11876,35 @@ static void bnxt_free_irq(struct bnxt *bp)
|
||||
|
||||
irq = &bp->irq_tbl[map_idx];
|
||||
if (irq->requested) {
|
||||
bnxt_release_irq_notifier(irq);
|
||||
|
||||
if (irq->have_cpumask) {
|
||||
irq_update_affinity_hint(irq->vector, NULL);
|
||||
free_cpumask_var(irq->cpu_mask);
|
||||
irq->have_cpumask = 0;
|
||||
}
|
||||
|
||||
bnxt_release_irq_notifier(irq);
|
||||
|
||||
free_irq(irq->vector, bp->bnapi[i]);
|
||||
}
|
||||
|
||||
irq->requested = 0;
|
||||
irq->tag = 0;
|
||||
irq->new_tag = 0;
|
||||
}
|
||||
|
||||
/* Disable TPH support */
|
||||
pcie_disable_tph(bp->pdev);
|
||||
bp->tph_mode = 0;
|
||||
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
free_irq_cpu_rmap(bp->dev->rx_cpu_rmap);
|
||||
bp->dev->rx_cpu_rmap = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bnxt_request_irq(struct bnxt *bp)
|
||||
{
|
||||
const int numa_node = dev_to_node(&bp->pdev->dev);
|
||||
struct cpu_rmap *rmap = NULL;
|
||||
int i, j, rc = 0;
|
||||
unsigned long flags = 0;
|
||||
@@ -11921,6 +11927,8 @@ static int bnxt_request_irq(struct bnxt *bp)
|
||||
for (i = 0, j = 0; i < bp->cp_nr_rings; i++) {
|
||||
int map_idx = bnxt_cp_num_to_irq_num(bp, i);
|
||||
struct bnxt_irq *irq = &bp->irq_tbl[map_idx];
|
||||
unsigned int cpu_num;
|
||||
u16 tag;
|
||||
|
||||
if (IS_ENABLED(CONFIG_RFS_ACCEL) &&
|
||||
rmap && bp->bnapi[i]->rx_ring) {
|
||||
@@ -11939,32 +11947,31 @@ static int bnxt_request_irq(struct bnxt *bp)
|
||||
netif_napi_set_irq_locked(&bp->bnapi[i]->napi, irq->vector);
|
||||
irq->requested = 1;
|
||||
|
||||
if (zalloc_cpumask_var(&irq->cpu_mask, GFP_KERNEL)) {
|
||||
int numa_node = dev_to_node(&bp->pdev->dev);
|
||||
u16 tag;
|
||||
if (!zalloc_cpumask_var(&irq->cpu_mask, GFP_KERNEL))
|
||||
continue;
|
||||
|
||||
irq->have_cpumask = 1;
|
||||
irq->msix_nr = map_idx;
|
||||
irq->ring_nr = i;
|
||||
cpumask_set_cpu(cpumask_local_spread(i, numa_node),
|
||||
irq->cpu_mask);
|
||||
rc = irq_update_affinity_hint(irq->vector, irq->cpu_mask);
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev,
|
||||
"Update affinity hint failed, IRQ = %d\n",
|
||||
irq->vector);
|
||||
break;
|
||||
}
|
||||
irq->have_cpumask = 1;
|
||||
irq->msix_nr = map_idx;
|
||||
irq->ring_nr = i;
|
||||
cpu_num = cpumask_local_spread(i, numa_node);
|
||||
cpumask_set_cpu(cpu_num, irq->cpu_mask);
|
||||
|
||||
bnxt_register_irq_notifier(bp, irq);
|
||||
/* Init ST table entry if we can get the mapping */
|
||||
if (!pcie_tph_get_cpu_st(bp->pdev, TPH_MEM_TYPE_VM,
|
||||
cpu_num, &tag)) {
|
||||
pcie_tph_set_st_entry(bp->pdev, irq->msix_nr, tag);
|
||||
irq->tag = tag;
|
||||
irq->new_tag = tag;
|
||||
}
|
||||
|
||||
/* Init ST table entry */
|
||||
if (pcie_tph_get_cpu_st(irq->bp->pdev, TPH_MEM_TYPE_VM,
|
||||
cpumask_first(irq->cpu_mask),
|
||||
&tag))
|
||||
continue;
|
||||
bnxt_register_irq_notifier(bp, irq);
|
||||
|
||||
pcie_tph_set_st_entry(irq->bp->pdev, irq->msix_nr, tag);
|
||||
rc = irq_update_affinity_hint(irq->vector, irq->cpu_mask);
|
||||
if (rc) {
|
||||
netdev_warn(bp->dev,
|
||||
"Update affinity hint failed, IRQ = %d\n",
|
||||
irq->vector);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -14468,6 +14475,43 @@ static void bnxt_rtnl_unlock_sp(struct bnxt *bp)
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static void bnxt_tph_update(struct bnxt *bp)
|
||||
{
|
||||
struct net_device *dev = bp->dev;
|
||||
int i;
|
||||
|
||||
bnxt_lock_sp(bp);
|
||||
if (!test_bit(BNXT_STATE_OPEN, &bp->state))
|
||||
goto unlock;
|
||||
|
||||
for (i = 0; i < bp->rx_nr_rings; i++) {
|
||||
struct bnxt_irq *irq;
|
||||
int map_idx, err;
|
||||
u16 tag;
|
||||
|
||||
map_idx = bnxt_cp_num_to_irq_num(bp, i);
|
||||
irq = &bp->irq_tbl[map_idx];
|
||||
tag = READ_ONCE(irq->new_tag);
|
||||
if (irq->tag == tag)
|
||||
continue;
|
||||
|
||||
if (pcie_tph_set_st_entry(bp->pdev, irq->msix_nr, tag))
|
||||
continue;
|
||||
|
||||
err = netdev_rx_queue_restart(dev, irq->ring_nr);
|
||||
if (err) {
|
||||
netdev_err(dev, "RX queue restart failed: err=%d\n",
|
||||
err);
|
||||
continue;
|
||||
}
|
||||
|
||||
irq->tag = tag;
|
||||
}
|
||||
|
||||
unlock:
|
||||
bnxt_unlock_sp(bp);
|
||||
}
|
||||
|
||||
/* Only called from bnxt_sp_task() */
|
||||
static void bnxt_reset(struct bnxt *bp, bool silent)
|
||||
{
|
||||
@@ -14892,6 +14936,9 @@ static void bnxt_sp_task(struct work_struct *work)
|
||||
bnxt_devlink_health_fw_report(bp);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(BNXT_TPH_UPDATE_SP_EVENT, &bp->sp_event))
|
||||
bnxt_tph_update(bp);
|
||||
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
|
||||
}
|
||||
|
||||
@@ -1268,6 +1268,8 @@ struct bnxt_irq {
|
||||
struct bnxt *bp;
|
||||
int msix_nr;
|
||||
int ring_nr;
|
||||
u16 tag;
|
||||
u16 new_tag;
|
||||
struct irq_affinity_notify affinity_notify;
|
||||
};
|
||||
|
||||
@@ -2642,6 +2644,7 @@ struct bnxt {
|
||||
#define BNXT_RING_COAL_NOW_SP_EVENT 17
|
||||
#define BNXT_FW_RESET_NOTIFY_SP_EVENT 18
|
||||
#define BNXT_FW_EXCEPTION_SP_EVENT 19
|
||||
#define BNXT_TPH_UPDATE_SP_EVENT 20
|
||||
#define BNXT_LINK_CFG_CHANGE_SP_EVENT 21
|
||||
#define BNXT_THERMAL_THRESHOLD_SP_EVENT 22
|
||||
#define BNXT_FW_ECHO_REQUEST_SP_EVENT 23
|
||||
|
||||
Reference in New Issue
Block a user