|
@@ -52,6 +52,8 @@
|
|
|
|
|
|
#define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
|
|
|
|
|
|
+#define NFP_FLOWER_FRAME_HEADROOM 158
|
|
|
+
|
|
|
static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn)
|
|
|
{
|
|
|
return "FLOWER";
|
|
@@ -157,7 +159,7 @@ nfp_flower_repr_netdev_open(struct nfp_app *app, struct nfp_repr *repr)
|
|
|
{
|
|
|
int err;
|
|
|
|
|
|
- err = nfp_flower_cmsg_portmod(repr, true);
|
|
|
+ err = nfp_flower_cmsg_portmod(repr, true, repr->netdev->mtu, false);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
@@ -171,7 +173,7 @@ nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr)
|
|
|
{
|
|
|
netif_tx_disable(repr->netdev);
|
|
|
|
|
|
- return nfp_flower_cmsg_portmod(repr, false);
|
|
|
+ return nfp_flower_cmsg_portmod(repr, false, repr->netdev->mtu, false);
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -521,6 +523,9 @@ static int nfp_flower_init(struct nfp_app *app)
|
|
|
INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx);
|
|
|
init_waitqueue_head(&app_priv->reify_wait_queue);
|
|
|
|
|
|
+ init_waitqueue_head(&app_priv->mtu_conf.wait_q);
|
|
|
+ spin_lock_init(&app_priv->mtu_conf.lock);
|
|
|
+
|
|
|
err = nfp_flower_metadata_init(app);
|
|
|
if (err)
|
|
|
goto err_free_app_priv;
|
|
@@ -552,6 +557,81 @@ static void nfp_flower_clean(struct nfp_app *app)
|
|
|
app->priv = NULL;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+nfp_flower_check_mtu(struct nfp_app *app, struct net_device *netdev,
|
|
|
+ int new_mtu)
|
|
|
+{
|
|
|
+ /* The flower fw reserves NFP_FLOWER_FRAME_HEADROOM bytes of the
|
|
|
+ * supported max MTU to allow for appending tunnel headers. To prevent
|
|
|
+ * unexpected behaviour this needs to be accounted for.
|
|
|
+ */
|
|
|
+ if (new_mtu > netdev->max_mtu - NFP_FLOWER_FRAME_HEADROOM) {
|
|
|
+ nfp_err(app->cpp, "New MTU (%d) is not valid\n", new_mtu);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static bool nfp_flower_check_ack(struct nfp_flower_priv *app_priv)
|
|
|
+{
|
|
|
+ bool ret;
|
|
|
+
|
|
|
+ spin_lock_bh(&app_priv->mtu_conf.lock);
|
|
|
+ ret = app_priv->mtu_conf.ack;
|
|
|
+ spin_unlock_bh(&app_priv->mtu_conf.lock);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+nfp_flower_repr_change_mtu(struct nfp_app *app, struct net_device *netdev,
|
|
|
+ int new_mtu)
|
|
|
+{
|
|
|
+ struct nfp_flower_priv *app_priv = app->priv;
|
|
|
+ struct nfp_repr *repr = netdev_priv(netdev);
|
|
|
+ int err, ack;
|
|
|
+
|
|
|
+ /* Only need to config FW for physical port MTU change. */
|
|
|
+ if (repr->port->type != NFP_PORT_PHYS_PORT)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (!(app_priv->flower_ext_feats & NFP_FL_NBI_MTU_SETTING)) {
|
|
|
+ nfp_err(app->cpp, "Physical port MTU setting not supported\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ spin_lock_bh(&app_priv->mtu_conf.lock);
|
|
|
+ app_priv->mtu_conf.ack = false;
|
|
|
+ app_priv->mtu_conf.requested_val = new_mtu;
|
|
|
+ app_priv->mtu_conf.portnum = repr->dst->u.port_info.port_id;
|
|
|
+ spin_unlock_bh(&app_priv->mtu_conf.lock);
|
|
|
+
|
|
|
+ err = nfp_flower_cmsg_portmod(repr, netif_carrier_ok(netdev), new_mtu,
|
|
|
+ true);
|
|
|
+ if (err) {
|
|
|
+ spin_lock_bh(&app_priv->mtu_conf.lock);
|
|
|
+ app_priv->mtu_conf.requested_val = 0;
|
|
|
+ spin_unlock_bh(&app_priv->mtu_conf.lock);
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Wait for fw to ack the change. */
|
|
|
+ ack = wait_event_timeout(app_priv->mtu_conf.wait_q,
|
|
|
+ nfp_flower_check_ack(app_priv),
|
|
|
+ msecs_to_jiffies(10));
|
|
|
+
|
|
|
+ if (!ack) {
|
|
|
+ spin_lock_bh(&app_priv->mtu_conf.lock);
|
|
|
+ app_priv->mtu_conf.requested_val = 0;
|
|
|
+ spin_unlock_bh(&app_priv->mtu_conf.lock);
|
|
|
+ nfp_warn(app->cpp, "MTU change not verified with fw\n");
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int nfp_flower_start(struct nfp_app *app)
|
|
|
{
|
|
|
return nfp_tunnel_config_start(app);
|
|
@@ -574,6 +654,9 @@ const struct nfp_app_type app_flower = {
|
|
|
.init = nfp_flower_init,
|
|
|
.clean = nfp_flower_clean,
|
|
|
|
|
|
+ .check_mtu = nfp_flower_check_mtu,
|
|
|
+ .repr_change_mtu = nfp_flower_repr_change_mtu,
|
|
|
+
|
|
|
.vnic_alloc = nfp_flower_vnic_alloc,
|
|
|
.vnic_init = nfp_flower_vnic_init,
|
|
|
.vnic_clean = nfp_flower_vnic_clean,
|