struct xfrm_dev_offload *xso = &x->xso;
        xfrm_address_t *saddr;
        xfrm_address_t *daddr;
+       bool is_packet_offload;
 
        if (!x->type_offload) {
                NL_SET_ERR_MSG(extack, "Type doesn't support offload");
                return -EINVAL;
        }
 
-       if (xuo->flags & ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND)) {
+       if (xuo->flags &
+           ~(XFRM_OFFLOAD_IPV6 | XFRM_OFFLOAD_INBOUND | XFRM_OFFLOAD_PACKET)) {
                NL_SET_ERR_MSG(extack, "Unrecognized flags in offload request");
                return -EINVAL;
        }
 
+       is_packet_offload = xuo->flags & XFRM_OFFLOAD_PACKET;
        dev = dev_get_by_index(net, xuo->ifindex);
        if (!dev) {
                if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) {
                                        x->props.family,
                                        xfrm_smark_get(0, x));
                if (IS_ERR(dst))
-                       return 0;
+                       return (is_packet_offload) ? -EINVAL : 0;
 
                dev = dst->dev;
 
        if (!dev->xfrmdev_ops || !dev->xfrmdev_ops->xdo_dev_state_add) {
                xso->dev = NULL;
                dev_put(dev);
-               return 0;
+               return (is_packet_offload) ? -EINVAL : 0;
        }
 
        if (x->props.flags & XFRM_STATE_ESN &&
        else
                xso->dir = XFRM_DEV_OFFLOAD_OUT;
 
-       xso->type = XFRM_DEV_OFFLOAD_CRYPTO;
+       if (is_packet_offload)
+               xso->type = XFRM_DEV_OFFLOAD_PACKET;
+       else
+               xso->type = XFRM_DEV_OFFLOAD_CRYPTO;
 
        err = dev->xfrmdev_ops->xdo_dev_state_add(x);
        if (err) {
                netdev_put(dev, &xso->dev_tracker);
                xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
 
-               if (err != -EOPNOTSUPP) {
+               /* User explicitly requested packet offload mode and configured
+                * policy in addition to the XFRM state. So be civil to users,
+                * and return an error instead of taking fallback path.
+                *
+                * This WARN_ON() can be seen as a documentation for driver
+                * authors to do not return -EOPNOTSUPP in packet offload mode.
+                */
+               WARN_ON(err == -EOPNOTSUPP && is_packet_offload);
+               if (err != -EOPNOTSUPP || is_packet_offload) {
                        NL_SET_ERR_MSG(extack, "Device failed to offload this state");
                        return err;
                }