Skip to content

Commit 29a5dca

Browse files
jahurleydavem330
authored andcommitted
nfp: flower: offload phys port MTU change
Trigger a port mod message to request an MTU change on the NIC when any physical port representor is assigned a new MTU value. The driver waits 10 msec for an ack that the FW has set the MTU. If no ack is received the request is rejected and an appropriate warning flagged. Rather than maintain an MTU queue per repr, one is maintained per app. Because the MTU ndo is protected by the rtnl lock, there can never be contention here. Portmod messages from the NIC are also protected by rtnl so we first check if the portmod is an ack and, if so, handle outside rtnl and the cmsg work queue. Acks are detected by the marking of a bit in a portmod response. They are then verfied by checking the port number and MTU value expected by the app. If the expected MTU is 0 then no acks are currently expected. Also, ensure that the packet headroom reserved by the flower firmware is considered when accepting an MTU change on any repr. Signed-off-by: John Hurley <[email protected]> Reviewed-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 167cebe commit 29a5dca

File tree

4 files changed

+146
-5
lines changed

4 files changed

+146
-5
lines changed

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 {

0 commit comments

Comments
 (0)