Skip to content

Commit 64e828d

Browse files
committed
Merge branch 'nfp-flower-handle-MTU-changes'
Jakub Kicinski says: ==================== nfp: flower: handle MTU changes This set improves MTU handling for flower offload. The max MTU is correctly capped and physical port MTU is communicated to the FW (and indirectly HW). ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 44465c4 + 29a5dca commit 64e828d

File tree

8 files changed

+179
-16
lines changed

8 files changed

+179
-16
lines changed

drivers/net/ethernet/netronome/nfp/bpf/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
221221
}
222222

223223
static int
224-
nfp_bpf_change_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu)
224+
nfp_bpf_check_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu)
225225
{
226226
struct nfp_net *nn = netdev_priv(netdev);
227227
unsigned int max_mtu;
@@ -413,7 +413,7 @@ const struct nfp_app_type app_bpf = {
413413
.init = nfp_bpf_init,
414414
.clean = nfp_bpf_clean,
415415

416-
.change_mtu = nfp_bpf_change_mtu,
416+
.check_mtu = nfp_bpf_check_mtu,
417417

418418
.extra_cap = nfp_bpf_extra_cap,
419419

drivers/net/ethernet/netronome/nfp/flower/cmsg.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ nfp_flower_cmsg_mac_repr_add(struct sk_buff *skb, unsigned int idx,
104104
msg->ports[idx].phys_port = phys_port;
105105
}
106106

107-
int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok)
107+
int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok,
108+
unsigned int mtu, bool mtu_only)
108109
{
109110
struct nfp_flower_cmsg_portmod *msg;
110111
struct sk_buff *skb;
@@ -118,7 +119,11 @@ int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok)
118119
msg->portnum = cpu_to_be32(repr->dst->u.port_info.port_id);
119120
msg->reserved = 0;
120121
msg->info = carrier_ok;
121-
msg->mtu = cpu_to_be16(repr->netdev->mtu);
122+
123+
if (mtu_only)
124+
msg->info |= NFP_FLOWER_CMSG_PORTMOD_MTU_CHANGE_ONLY;
125+
126+
msg->mtu = cpu_to_be16(mtu);
122127

123128
nfp_ctrl_tx(repr->app->ctrl, skb);
124129

@@ -146,6 +151,34 @@ int nfp_flower_cmsg_portreify(struct nfp_repr *repr, bool exists)
146151
return 0;
147152
}
148153

154+
static bool
155+
nfp_flower_process_mtu_ack(struct nfp_app *app, struct sk_buff *skb)
156+
{
157+
struct nfp_flower_priv *app_priv = app->priv;
158+
struct nfp_flower_cmsg_portmod *msg;
159+
160+
msg = nfp_flower_cmsg_get_data(skb);
161+
162+
if (!(msg->info & NFP_FLOWER_CMSG_PORTMOD_MTU_CHANGE_ONLY))
163+
return false;
164+
165+
spin_lock_bh(&app_priv->mtu_conf.lock);
166+
if (!app_priv->mtu_conf.requested_val ||
167+
app_priv->mtu_conf.portnum != be32_to_cpu(msg->portnum) ||
168+
be16_to_cpu(msg->mtu) != app_priv->mtu_conf.requested_val) {
169+
/* Not an ack for requested MTU change. */
170+
spin_unlock_bh(&app_priv->mtu_conf.lock);
171+
return false;
172+
}
173+
174+
app_priv->mtu_conf.ack = true;
175+
app_priv->mtu_conf.requested_val = 0;
176+
wake_up(&app_priv->mtu_conf.wait_q);
177+
spin_unlock_bh(&app_priv->mtu_conf.lock);
178+
179+
return true;
180+
}
181+
149182
static void
150183
nfp_flower_cmsg_portmod_rx(struct nfp_app *app, struct sk_buff *skb)
151184
{
@@ -269,6 +302,10 @@ void nfp_flower_cmsg_rx(struct nfp_app *app, struct sk_buff *skb)
269302
/* We need to deal with stats updates from HW asap */
270303
nfp_flower_rx_flow_stats(app, skb);
271304
dev_consume_skb_any(skb);
305+
} else if (cmsg_hdr->type == NFP_FLOWER_CMSG_TYPE_PORT_MOD &&
306+
nfp_flower_process_mtu_ack(app, skb)) {
307+
/* Handle MTU acks outside wq to prevent RTNL conflict. */
308+
dev_consume_skb_any(skb);
272309
} else {
273310
skb_queue_tail(&priv->cmsg_skbs, skb);
274311
schedule_work(&priv->cmsg_work);

drivers/net/ethernet/netronome/nfp/flower/cmsg.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ struct nfp_flower_cmsg_portmod {
397397
};
398398

399399
#define NFP_FLOWER_CMSG_PORTMOD_INFO_LINK BIT(0)
400+
#define NFP_FLOWER_CMSG_PORTMOD_MTU_CHANGE_ONLY BIT(1)
400401

401402
/* NFP_FLOWER_CMSG_TYPE_PORT_REIFY */
402403
struct nfp_flower_cmsg_portreify {
@@ -464,7 +465,8 @@ void
464465
nfp_flower_cmsg_mac_repr_add(struct sk_buff *skb, unsigned int idx,
465466
unsigned int nbi, unsigned int nbi_port,
466467
unsigned int phys_port);
467-
int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok);
468+
int nfp_flower_cmsg_portmod(struct nfp_repr *repr, bool carrier_ok,
469+
unsigned int mtu, bool mtu_only);
468470
int nfp_flower_cmsg_portreify(struct nfp_repr *repr, bool exists);
469471
void nfp_flower_cmsg_process_rx(struct work_struct *work);
470472
void nfp_flower_cmsg_rx(struct nfp_app *app, struct sk_buff *skb);

drivers/net/ethernet/netronome/nfp/flower/main.c

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252

5353
#define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
5454

55+
#define NFP_FLOWER_FRAME_HEADROOM 158
56+
5557
static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn)
5658
{
5759
return "FLOWER";
@@ -157,7 +159,7 @@ nfp_flower_repr_netdev_open(struct nfp_app *app, struct nfp_repr *repr)
157159
{
158160
int err;
159161

160-
err = nfp_flower_cmsg_portmod(repr, true);
162+
err = nfp_flower_cmsg_portmod(repr, true, repr->netdev->mtu, false);
161163
if (err)
162164
return err;
163165

@@ -171,7 +173,7 @@ nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr)
171173
{
172174
netif_tx_disable(repr->netdev);
173175

174-
return nfp_flower_cmsg_portmod(repr, false);
176+
return nfp_flower_cmsg_portmod(repr, false, repr->netdev->mtu, false);
175177
}
176178

177179
static int
@@ -521,6 +523,9 @@ static int nfp_flower_init(struct nfp_app *app)
521523
INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx);
522524
init_waitqueue_head(&app_priv->reify_wait_queue);
523525

526+
init_waitqueue_head(&app_priv->mtu_conf.wait_q);
527+
spin_lock_init(&app_priv->mtu_conf.lock);
528+
524529
err = nfp_flower_metadata_init(app);
525530
if (err)
526531
goto err_free_app_priv;
@@ -552,6 +557,81 @@ static void nfp_flower_clean(struct nfp_app *app)
552557
app->priv = NULL;
553558
}
554559

560+
static int
561+
nfp_flower_check_mtu(struct nfp_app *app, struct net_device *netdev,
562+
int new_mtu)
563+
{
564+
/* The flower fw reserves NFP_FLOWER_FRAME_HEADROOM bytes of the
565+
* supported max MTU to allow for appending tunnel headers. To prevent
566+
* unexpected behaviour this needs to be accounted for.
567+
*/
568+
if (new_mtu > netdev->max_mtu - NFP_FLOWER_FRAME_HEADROOM) {
569+
nfp_err(app->cpp, "New MTU (%d) is not valid\n", new_mtu);
570+
return -EINVAL;
571+
}
572+
573+
return 0;
574+
}
575+
576+
static bool nfp_flower_check_ack(struct nfp_flower_priv *app_priv)
577+
{
578+
bool ret;
579+
580+
spin_lock_bh(&app_priv->mtu_conf.lock);
581+
ret = app_priv->mtu_conf.ack;
582+
spin_unlock_bh(&app_priv->mtu_conf.lock);
583+
584+
return ret;
585+
}
586+
587+
static int
588+
nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev,
589+
int new_mtu)
590+
{
591+
struct nfp_flower_priv *app_priv = app->priv;
592+
struct nfp_repr *repr = netdev_priv(netdev);
593+
int err, ack;
594+
595+
/* Only need to config FW for physical port MTU change. */
596+
if (repr->port->type != NFP_PORT_PHYS_PORT)
597+
return 0;
598+
599+
if (!(app_priv->flower_ext_feats & NFP_FL_NBI_MTU_SETTING)) {
600+
nfp_err(app->cpp, "Physical port MTU setting not supported\n");
601+
return -EINVAL;
602+
}
603+
604+
spin_lock_bh(&app_priv->mtu_conf.lock);
605+
app_priv->mtu_conf.ack = false;
606+
app_priv->mtu_conf.requested_val = new_mtu;
607+
app_priv->mtu_conf.portnum = repr->dst->u.port_info.port_id;
608+
spin_unlock_bh(&app_priv->mtu_conf.lock);
609+
610+
err = nfp_flower_cmsg_portmod(repr, netif_carrier_ok(netdev), new_mtu,
611+
true);
612+
if (err) {
613+
spin_lock_bh(&app_priv->mtu_conf.lock);
614+
app_priv->mtu_conf.requested_val = 0;
615+
spin_unlock_bh(&app_priv->mtu_conf.lock);
616+
return err;
617+
}
618+
619+
/* Wait for fw to ack the change. */
620+
ack = wait_event_timeout(app_priv->mtu_conf.wait_q,
621+
nfp_flower_check_ack(app_priv),
622+
msecs_to_jiffies(10));
623+
624+
if (!ack) {
625+
spin_lock_bh(&app_priv->mtu_conf.lock);
626+
app_priv->mtu_conf.requested_val = 0;
627+
spin_unlock_bh(&app_priv->mtu_conf.lock);
628+
nfp_warn(app->cpp, "MTU change not verified with fw\n");
629+
return -EIO;
630+
}
631+
632+
return 0;
633+
}
634+
555635
static int nfp_flower_start(struct nfp_app *app)
556636
{
557637
return nfp_tunnel_config_start(app);
@@ -574,6 +654,9 @@ const struct nfp_app_type app_flower = {
574654
.init = nfp_flower_init,
575655
.clean = nfp_flower_clean,
576656

657+
.check_mtu = nfp_flower_check_mtu,
658+
.repr_change_mtu = nfp_flower_repr_change_mtu,
659+
577660
.vnic_alloc = nfp_flower_vnic_alloc,
578661
.vnic_init = nfp_flower_vnic_init,
579662
.vnic_clean = nfp_flower_vnic_clean,

drivers/net/ethernet/netronome/nfp/flower/main.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct nfp_app;
6565

6666
/* Extra features bitmap. */
6767
#define NFP_FL_FEATS_GENEVE BIT(0)
68+
#define NFP_FL_NBI_MTU_SETTING BIT(1)
6869

6970
struct nfp_fl_mask_id {
7071
struct circ_buf mask_id_free_list;
@@ -78,6 +79,22 @@ struct nfp_fl_stats_id {
7879
u8 repeated_em_count;
7980
};
8081

82+
/**
83+
* struct nfp_mtu_conf - manage MTU setting
84+
* @portnum: NFP port number of repr with requested MTU change
85+
* @requested_val: MTU value requested for repr
86+
* @ack: Received ack that MTU has been correctly set
87+
* @wait_q: Wait queue for MTU acknowledgements
88+
* @lock: Lock for setting/reading MTU variables
89+
*/
90+
struct nfp_mtu_conf {
91+
u32 portnum;
92+
unsigned int requested_val;
93+
bool ack;
94+
wait_queue_head_t wait_q;
95+
spinlock_t lock;
96+
};
97+
8198
/**
8299
* struct nfp_flower_priv - Flower APP per-vNIC priv data
83100
* @app: Back pointer to app
@@ -106,6 +123,7 @@ struct nfp_fl_stats_id {
106123
* @reify_replies: atomically stores the number of replies received
107124
* from firmware for repr reify
108125
* @reify_wait_queue: wait queue for repr reify response counting
126+
* @mtu_conf: Configuration of repr MTU value
109127
*/
110128
struct nfp_flower_priv {
111129
struct nfp_app *app;
@@ -133,6 +151,7 @@ struct nfp_flower_priv {
133151
struct notifier_block nfp_tun_neigh_nb;
134152
atomic_t reify_replies;
135153
wait_queue_head_t reify_wait_queue;
154+
struct nfp_mtu_conf mtu_conf;
136155
};
137156

138157
struct nfp_fl_key_ls {

drivers/net/ethernet/netronome/nfp/nfp_app.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ extern const struct nfp_app_type app_flower;
8686
* @repr_clean: representor about to be unregistered
8787
* @repr_open: representor netdev open callback
8888
* @repr_stop: representor netdev stop callback
89-
* @change_mtu: MTU change on a netdev has been requested (veto-only, change
90-
* is not guaranteed to be committed)
89+
* @check_mtu: MTU change request on a netdev (verify it is valid)
90+
* @repr_change_mtu: MTU change request on repr (make and verify change)
9191
* @start: start application logic
9292
* @stop: stop application logic
9393
* @ctrl_msg_rx: control message handler
@@ -124,8 +124,10 @@ struct nfp_app_type {
124124
int (*repr_open)(struct nfp_app *app, struct nfp_repr *repr);
125125
int (*repr_stop)(struct nfp_app *app, struct nfp_repr *repr);
126126

127-
int (*change_mtu)(struct nfp_app *app, struct net_device *netdev,
128-
int new_mtu);
127+
int (*check_mtu)(struct nfp_app *app, struct net_device *netdev,
128+
int new_mtu);
129+
int (*repr_change_mtu)(struct nfp_app *app, struct net_device *netdev,
130+
int new_mtu);
129131

130132
int (*start)(struct nfp_app *app);
131133
void (*stop)(struct nfp_app *app);
@@ -247,11 +249,20 @@ nfp_app_repr_clean(struct nfp_app *app, struct net_device *netdev)
247249
}
248250

249251
static inline int
250-
nfp_app_change_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu)
252+
nfp_app_check_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu)
251253
{
252-
if (!app || !app->type->change_mtu)
254+
if (!app || !app->type->check_mtu)
253255
return 0;
254-
return app->type->change_mtu(app, netdev, new_mtu);
256+
return app->type->check_mtu(app, netdev, new_mtu);
257+
}
258+
259+
static inline int
260+
nfp_app_repr_change_mtu(struct nfp_app *app, struct net_device *netdev,
261+
int new_mtu)
262+
{
263+
if (!app || !app->type->repr_change_mtu)
264+
return 0;
265+
return app->type->repr_change_mtu(app, netdev, new_mtu);
255266
}
256267

257268
static inline int nfp_app_start(struct nfp_app *app, struct nfp_net *ctrl)

drivers/net/ethernet/netronome/nfp/nfp_net_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3066,7 +3066,7 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu)
30663066
struct nfp_net_dp *dp;
30673067
int err;
30683068

3069-
err = nfp_app_change_mtu(nn->app, netdev, new_mtu);
3069+
err = nfp_app_check_mtu(nn->app, netdev, new_mtu);
30703070
if (err)
30713071
return err;
30723072

drivers/net/ethernet/netronome/nfp/nfp_net_repr.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,19 @@ nfp_repr_get_offload_stats(int attr_id, const struct net_device *dev,
196196
static int nfp_repr_change_mtu(struct net_device *netdev, int new_mtu)
197197
{
198198
struct nfp_repr *repr = netdev_priv(netdev);
199+
int err;
199200

200-
return nfp_app_change_mtu(repr->app, netdev, new_mtu);
201+
err = nfp_app_check_mtu(repr->app, netdev, new_mtu);
202+
if (err)
203+
return err;
204+
205+
err = nfp_app_repr_change_mtu(repr->app, netdev, new_mtu);
206+
if (err)
207+
return err;
208+
209+
netdev->mtu = new_mtu;
210+
211+
return 0;
201212
}
202213

203214
static netdev_tx_t nfp_repr_xmit(struct sk_buff *skb, struct net_device *netdev)

0 commit comments

Comments
 (0)