Skip to content

Commit 52dc722

Browse files
committed
eth: fbnic: support ring channel set while up
Implement the channel count changes. Copy the netdev priv, allocate new channels using it. Stop, swap, start. Then free the copy of the priv along with the channels it holds, which are now the channels that used to be on the real priv. Reviewed-by: Przemek Kitszel <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 3a481cc commit 52dc722

File tree

7 files changed

+143
-6
lines changed

7 files changed

+143
-6
lines changed

drivers/net/ethernet/meta/fbnic/fbnic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ int fbnic_napi_request_irq(struct fbnic_dev *fbd,
162162
struct fbnic_napi_vector *nv);
163163
void fbnic_napi_free_irq(struct fbnic_dev *fbd,
164164
struct fbnic_napi_vector *nv);
165+
void fbnic_synchronize_irq(struct fbnic_dev *fbd, int nr);
165166
int fbnic_request_irq(struct fbnic_dev *dev, int nr, irq_handler_t handler,
166167
unsigned long flags, const char *name, void *data);
167168
void fbnic_free_irq(struct fbnic_dev *dev, int nr, void *data);

drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,76 @@ static void fbnic_get_regs(struct net_device *netdev,
6565
fbnic_csr_get_regs(fbn->fbd, data, &regs->version);
6666
}
6767

68+
static struct fbnic_net *fbnic_clone_create(struct fbnic_net *orig)
69+
{
70+
struct fbnic_net *clone;
71+
72+
clone = kmemdup(orig, sizeof(*orig), GFP_KERNEL);
73+
if (!clone)
74+
return NULL;
75+
76+
memset(clone->tx, 0, sizeof(clone->tx));
77+
memset(clone->rx, 0, sizeof(clone->rx));
78+
memset(clone->napi, 0, sizeof(clone->napi));
79+
return clone;
80+
}
81+
82+
static void fbnic_clone_swap_cfg(struct fbnic_net *orig,
83+
struct fbnic_net *clone)
84+
{
85+
swap(clone->rcq_size, orig->rcq_size);
86+
swap(clone->hpq_size, orig->hpq_size);
87+
swap(clone->ppq_size, orig->ppq_size);
88+
swap(clone->txq_size, orig->txq_size);
89+
swap(clone->num_rx_queues, orig->num_rx_queues);
90+
swap(clone->num_tx_queues, orig->num_tx_queues);
91+
swap(clone->num_napi, orig->num_napi);
92+
}
93+
94+
static void fbnic_aggregate_vector_counters(struct fbnic_net *fbn,
95+
struct fbnic_napi_vector *nv)
96+
{
97+
int i, j;
98+
99+
for (i = 0; i < nv->txt_count; i++) {
100+
fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].sub0);
101+
fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].sub1);
102+
fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].cmpl);
103+
}
104+
105+
for (j = 0; j < nv->rxt_count; j++, i++) {
106+
fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].sub0);
107+
fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].sub1);
108+
fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].cmpl);
109+
}
110+
}
111+
112+
static void fbnic_clone_swap(struct fbnic_net *orig,
113+
struct fbnic_net *clone)
114+
{
115+
struct fbnic_dev *fbd = orig->fbd;
116+
unsigned int i;
117+
118+
for (i = 0; i < max(clone->num_napi, orig->num_napi); i++)
119+
fbnic_synchronize_irq(fbd, FBNIC_NON_NAPI_VECTORS + i);
120+
for (i = 0; i < orig->num_napi; i++)
121+
fbnic_aggregate_vector_counters(orig, orig->napi[i]);
122+
123+
fbnic_clone_swap_cfg(orig, clone);
124+
125+
for (i = 0; i < ARRAY_SIZE(orig->napi); i++)
126+
swap(clone->napi[i], orig->napi[i]);
127+
for (i = 0; i < ARRAY_SIZE(orig->tx); i++)
128+
swap(clone->tx[i], orig->tx[i]);
129+
for (i = 0; i < ARRAY_SIZE(orig->rx); i++)
130+
swap(clone->rx[i], orig->rx[i]);
131+
}
132+
133+
static void fbnic_clone_free(struct fbnic_net *clone)
134+
{
135+
kfree(clone);
136+
}
137+
68138
static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
69139
{
70140
int i;
@@ -342,6 +412,8 @@ static int fbnic_set_channels(struct net_device *netdev,
342412
struct fbnic_net *fbn = netdev_priv(netdev);
343413
unsigned int max_napis, standalone;
344414
struct fbnic_dev *fbd = fbn->fbd;
415+
struct fbnic_net *clone;
416+
int err;
345417

346418
max_napis = fbd->num_irqs - FBNIC_NON_NAPI_VECTORS;
347419
standalone = ch->rx_count + ch->tx_count;
@@ -363,7 +435,54 @@ static int fbnic_set_channels(struct net_device *netdev,
363435
return 0;
364436
}
365437

366-
return -EBUSY;
438+
clone = fbnic_clone_create(fbn);
439+
if (!clone)
440+
return -ENOMEM;
441+
442+
fbnic_set_queues(clone, ch, max_napis);
443+
444+
err = fbnic_alloc_napi_vectors(clone);
445+
if (err)
446+
goto err_free_clone;
447+
448+
err = fbnic_alloc_resources(clone);
449+
if (err)
450+
goto err_free_napis;
451+
452+
fbnic_down_noidle(fbn);
453+
err = fbnic_wait_all_queues_idle(fbn->fbd, true);
454+
if (err)
455+
goto err_start_stack;
456+
457+
err = fbnic_set_netif_queues(clone);
458+
if (err)
459+
goto err_start_stack;
460+
461+
/* Nothing can fail past this point */
462+
fbnic_flush(fbn);
463+
464+
fbnic_clone_swap(fbn, clone);
465+
466+
/* Reset RSS indirection table */
467+
fbnic_reset_indir_tbl(fbn);
468+
469+
fbnic_up(fbn);
470+
471+
fbnic_free_resources(clone);
472+
fbnic_free_napi_vectors(clone);
473+
fbnic_clone_free(clone);
474+
475+
return 0;
476+
477+
err_start_stack:
478+
fbnic_flush(fbn);
479+
fbnic_up(fbn);
480+
fbnic_free_resources(clone);
481+
err_free_napis:
482+
fbnic_free_napi_vectors(clone);
483+
err_free_clone:
484+
fbnic_clone_free(clone);
485+
return err;
367486
}
368487

369488
static int

drivers/net/ethernet/meta/fbnic/fbnic_irq.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@ void fbnic_pcs_irq_disable(struct fbnic_dev *fbd)
146146
free_irq(fbd->pcs_msix_vector, fbd);
147147
}
148148

149+
void fbnic_synchronize_irq(struct fbnic_dev *fbd, int nr)
150+
{
151+
struct pci_dev *pdev = to_pci_dev(fbd->dev);
152+
int irq = pci_irq_vector(pdev, nr);
153+
154+
if (irq < 0)
155+
return;
156+
157+
synchronize_irq(irq);
158+
}
159+
149160
int fbnic_request_irq(struct fbnic_dev *fbd, int nr, irq_handler_t handler,
150161
unsigned long flags, const char *name, void *data)
151162
{

drivers/net/ethernet/meta/fbnic/fbnic_netdev.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct fbnic_net {
6565
int __fbnic_open(struct fbnic_net *fbn);
6666
void fbnic_up(struct fbnic_net *fbn);
6767
void fbnic_down(struct fbnic_net *fbn);
68+
void fbnic_down_noidle(struct fbnic_net *fbn);
6869

6970
struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd);
7071
void fbnic_netdev_free(struct fbnic_dev *fbd);

drivers/net/ethernet/meta/fbnic/fbnic_pci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ void fbnic_up(struct fbnic_net *fbn)
145145
fbnic_service_task_start(fbn);
146146
}
147147

148-
static void fbnic_down_noidle(struct fbnic_net *fbn)
148+
void fbnic_down_noidle(struct fbnic_net *fbn)
149149
{
150150
fbnic_service_task_stop(fbn);
151151

drivers/net/ethernet/meta/fbnic/fbnic_txrx.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,8 +1045,8 @@ irqreturn_t fbnic_msix_clean_rings(int __always_unused irq, void *data)
10451045
return IRQ_HANDLED;
10461046
}
10471047

1048-
static void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn,
1049-
struct fbnic_ring *rxr)
1048+
void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn,
1049+
struct fbnic_ring *rxr)
10501050
{
10511051
struct fbnic_queue_stats *stats = &rxr->stats;
10521052

@@ -1056,8 +1056,8 @@ static void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn,
10561056
fbn->rx_stats.dropped += stats->dropped;
10571057
}
10581058

1059-
static void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn,
1060-
struct fbnic_ring *txr)
1059+
void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn,
1060+
struct fbnic_ring *txr)
10611061
{
10621062
struct fbnic_queue_stats *stats = &txr->stats;
10631063

drivers/net/ethernet/meta/fbnic/fbnic_txrx.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ netdev_features_t
120120
fbnic_features_check(struct sk_buff *skb, struct net_device *dev,
121121
netdev_features_t features);
122122

123+
void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn,
124+
struct fbnic_ring *rxr);
125+
void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn,
126+
struct fbnic_ring *txr);
127+
123128
int fbnic_alloc_napi_vectors(struct fbnic_net *fbn);
124129
void fbnic_free_napi_vectors(struct fbnic_net *fbn);
125130
int fbnic_alloc_resources(struct fbnic_net *fbn);

0 commit comments

Comments
 (0)