return dev;
 }
 
+static enum macsec_offload nla_get_offload(const struct nlattr *nla)
+{
+       return (__force enum macsec_offload)nla_get_u8(nla);
+}
+
 static sci_t nla_get_sci(const struct nlattr *nla)
 {
        return (__force sci_t)nla_get_u64(nla);
 
        macsec->real_dev = real_dev;
 
-       /* MACsec offloading is off by default */
-       macsec->offload = MACSEC_OFFLOAD_OFF;
+       if (data && data[IFLA_MACSEC_OFFLOAD])
+               macsec->offload = nla_get_offload(data[IFLA_MACSEC_OFFLOAD]);
+       else
+               /* MACsec offloading is off by default */
+               macsec->offload = MACSEC_OFFLOAD_OFF;
+
+       /* Check if the offloading mode is supported by the underlying layers */
+       if (macsec->offload != MACSEC_OFFLOAD_OFF &&
+           !macsec_check_offload(macsec->offload, macsec))
+               return -EOPNOTSUPP;
 
        if (data && data[IFLA_MACSEC_ICV_LEN])
                icv_len = nla_get_u8(data[IFLA_MACSEC_ICV_LEN]);
                        goto del_dev;
        }
 
+       /* If h/w offloading is available, propagate to the device */
+       if (macsec_is_offloaded(macsec)) {
+               const struct macsec_ops *ops;
+               struct macsec_context ctx;
+
+               ops = macsec_get_ops(macsec, &ctx);
+               if (ops) {
+                       ctx.secy = &macsec->secy;
+                       err = macsec_offload(ops->mdo_add_secy, &ctx);
+                       if (err)
+                               goto del_dev;
+               }
+       }
+
        err = register_macsec_dev(real_dev, dev);
        if (err < 0)
                goto del_dev;