struct control_buf {
        struct virtio_net_ctrl_hdr hdr;
        virtio_net_ctrl_ack status;
-       struct virtio_net_ctrl_mq mq;
-       u8 promisc;
-       u8 allmulti;
-       __virtio16 vid;
-       __virtio64 offloads;
-       struct virtio_net_ctrl_coal_tx coal_tx;
-       struct virtio_net_ctrl_coal_rx coal_rx;
-       struct virtio_net_ctrl_coal_vq coal_vq;
-       struct virtio_net_stats_capabilities stats_cap;
 };
 
 struct virtnet_info {
 
 static int _virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
 {
+       struct virtio_net_ctrl_mq *mq __free(kfree) = NULL;
        struct scatterlist sg;
        struct net_device *dev = vi->dev;
 
        if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ))
                return 0;
 
-       vi->ctrl->mq.virtqueue_pairs = cpu_to_virtio16(vi->vdev, queue_pairs);
-       sg_init_one(&sg, &vi->ctrl->mq, sizeof(vi->ctrl->mq));
+       mq = kzalloc(sizeof(*mq), GFP_KERNEL);
+       if (!mq)
+               return -ENOMEM;
+
+       mq->virtqueue_pairs = cpu_to_virtio16(vi->vdev, queue_pairs);
+       sg_init_one(&sg, mq, sizeof(*mq));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
                                  VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg)) {
 
 static int virtnet_close(struct net_device *dev)
 {
+       u8 *promisc_allmulti  __free(kfree) = NULL;
        struct virtnet_info *vi = netdev_priv(dev);
        int i;
 
        struct scatterlist sg[2];
        struct virtio_net_ctrl_mac *mac_data;
        struct netdev_hw_addr *ha;
+       u8 *promisc_allmulti;
        int uc_count;
        int mc_count;
        void *buf;
 
        rtnl_lock();
 
-       vi->ctrl->promisc = ((dev->flags & IFF_PROMISC) != 0);
-       vi->ctrl->allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
+       promisc_allmulti = kzalloc(sizeof(*promisc_allmulti), GFP_ATOMIC);
+       if (!promisc_allmulti) {
+               dev_warn(&dev->dev, "Failed to set RX mode, no memory.\n");
+               return;
+       }
 
-       sg_init_one(sg, &vi->ctrl->promisc, sizeof(vi->ctrl->promisc));
+       *promisc_allmulti = !!(dev->flags & IFF_PROMISC);
+       sg_init_one(sg, promisc_allmulti, sizeof(*promisc_allmulti));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
                                  VIRTIO_NET_CTRL_RX_PROMISC, sg))
                dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
-                        vi->ctrl->promisc ? "en" : "dis");
+                        *promisc_allmulti ? "en" : "dis");
 
-       sg_init_one(sg, &vi->ctrl->allmulti, sizeof(vi->ctrl->allmulti));
+       *promisc_allmulti = !!(dev->flags & IFF_ALLMULTI);
+       sg_init_one(sg, promisc_allmulti, sizeof(*promisc_allmulti));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
                                  VIRTIO_NET_CTRL_RX_ALLMULTI, sg))
                dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
-                        vi->ctrl->allmulti ? "en" : "dis");
+                        *promisc_allmulti ? "en" : "dis");
 
        netif_addr_lock_bh(dev);
 
                                   __be16 proto, u16 vid)
 {
        struct virtnet_info *vi = netdev_priv(dev);
+       __virtio16 *_vid __free(kfree) = NULL;
        struct scatterlist sg;
 
-       vi->ctrl->vid = cpu_to_virtio16(vi->vdev, vid);
-       sg_init_one(&sg, &vi->ctrl->vid, sizeof(vi->ctrl->vid));
+       _vid = kzalloc(sizeof(*_vid), GFP_KERNEL);
+       if (!_vid)
+               return -ENOMEM;
+
+       *_vid = cpu_to_virtio16(vi->vdev, vid);
+       sg_init_one(&sg, _vid, sizeof(*_vid));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
                                  VIRTIO_NET_CTRL_VLAN_ADD, &sg))
                                    __be16 proto, u16 vid)
 {
        struct virtnet_info *vi = netdev_priv(dev);
+       __virtio16 *_vid __free(kfree) = NULL;
        struct scatterlist sg;
 
-       vi->ctrl->vid = cpu_to_virtio16(vi->vdev, vid);
-       sg_init_one(&sg, &vi->ctrl->vid, sizeof(vi->ctrl->vid));
+       _vid = kzalloc(sizeof(*_vid), GFP_KERNEL);
+       if (!_vid)
+               return -ENOMEM;
+
+       *_vid = cpu_to_virtio16(vi->vdev, vid);
+       sg_init_one(&sg, _vid, sizeof(*_vid));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
                                  VIRTIO_NET_CTRL_VLAN_DEL, &sg))
 static int virtnet_send_ctrl_coal_vq_cmd(struct virtnet_info *vi,
                                         u16 vqn, u32 max_usecs, u32 max_packets)
 {
+       struct virtio_net_ctrl_coal_vq *coal_vq __free(kfree) = NULL;
        struct scatterlist sgs;
 
-       vi->ctrl->coal_vq.vqn = cpu_to_le16(vqn);
-       vi->ctrl->coal_vq.coal.max_usecs = cpu_to_le32(max_usecs);
-       vi->ctrl->coal_vq.coal.max_packets = cpu_to_le32(max_packets);
-       sg_init_one(&sgs, &vi->ctrl->coal_vq, sizeof(vi->ctrl->coal_vq));
+       coal_vq = kzalloc(sizeof(*coal_vq), GFP_KERNEL);
+       if (!coal_vq)
+               return -ENOMEM;
+
+       coal_vq->vqn = cpu_to_le16(vqn);
+       coal_vq->coal.max_usecs = cpu_to_le32(max_usecs);
+       coal_vq->coal.max_packets = cpu_to_le32(max_packets);
+       sg_init_one(&sgs, coal_vq, sizeof(*coal_vq));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL,
                                  VIRTIO_NET_CTRL_NOTF_COAL_VQ_SET,
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
                                  vi->has_rss ? VIRTIO_NET_CTRL_MQ_RSS_CONFIG
-                                 : VIRTIO_NET_CTRL_MQ_HASH_CONFIG, sgs)) {
-               dev_warn(&dev->dev, "VIRTIONET issue with committing RSS sgs\n");
-               return false;
-       }
+                                 : VIRTIO_NET_CTRL_MQ_HASH_CONFIG, sgs))
+               goto err;
+
        return true;
+
+err:
+       dev_warn(&dev->dev, "VIRTIONET issue with committing RSS sgs\n");
+       return false;
+
 }
 
 static void virtnet_init_default_rss(struct virtnet_info *vi)
 static int virtnet_send_tx_notf_coal_cmds(struct virtnet_info *vi,
                                          struct ethtool_coalesce *ec)
 {
+       struct virtio_net_ctrl_coal_tx *coal_tx __free(kfree) = NULL;
        struct scatterlist sgs_tx;
        int i;
 
-       vi->ctrl->coal_tx.tx_usecs = cpu_to_le32(ec->tx_coalesce_usecs);
-       vi->ctrl->coal_tx.tx_max_packets = cpu_to_le32(ec->tx_max_coalesced_frames);
-       sg_init_one(&sgs_tx, &vi->ctrl->coal_tx, sizeof(vi->ctrl->coal_tx));
+       coal_tx = kzalloc(sizeof(*coal_tx), GFP_KERNEL);
+       if (!coal_tx)
+               return -ENOMEM;
+
+       coal_tx->tx_usecs = cpu_to_le32(ec->tx_coalesce_usecs);
+       coal_tx->tx_max_packets = cpu_to_le32(ec->tx_max_coalesced_frames);
+       sg_init_one(&sgs_tx, coal_tx, sizeof(*coal_tx));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL,
                                  VIRTIO_NET_CTRL_NOTF_COAL_TX_SET,
 static int virtnet_send_rx_notf_coal_cmds(struct virtnet_info *vi,
                                          struct ethtool_coalesce *ec)
 {
+       struct virtio_net_ctrl_coal_rx *coal_rx __free(kfree) = NULL;
        bool rx_ctrl_dim_on = !!ec->use_adaptive_rx_coalesce;
        struct scatterlist sgs_rx;
        int i;
                return 0;
        }
 
+       coal_rx = kzalloc(sizeof(*coal_rx), GFP_KERNEL);
+       if (!coal_rx)
+               return -ENOMEM;
+
        if (!rx_ctrl_dim_on && vi->rx_dim_enabled) {
                vi->rx_dim_enabled = false;
                for (i = 0; i < vi->max_queue_pairs; i++)
         * we need apply the global new params even if they
         * are not updated.
         */
-       vi->ctrl->coal_rx.rx_usecs = cpu_to_le32(ec->rx_coalesce_usecs);
-       vi->ctrl->coal_rx.rx_max_packets = cpu_to_le32(ec->rx_max_coalesced_frames);
-       sg_init_one(&sgs_rx, &vi->ctrl->coal_rx, sizeof(vi->ctrl->coal_rx));
+       coal_rx->rx_usecs = cpu_to_le32(ec->rx_coalesce_usecs);
+       coal_rx->rx_max_packets = cpu_to_le32(ec->rx_max_coalesced_frames);
+       sg_init_one(&sgs_rx, coal_rx, sizeof(*coal_rx));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL,
                                  VIRTIO_NET_CTRL_NOTF_COAL_RX_SET,
 
 static int virtnet_set_guest_offloads(struct virtnet_info *vi, u64 offloads)
 {
+       __virtio64 *_offloads __free(kfree) = NULL;
        struct scatterlist sg;
-       vi->ctrl->offloads = cpu_to_virtio64(vi->vdev, offloads);
 
-       sg_init_one(&sg, &vi->ctrl->offloads, sizeof(vi->ctrl->offloads));
+       _offloads = kzalloc(sizeof(*_offloads), GFP_KERNEL);
+       if (!_offloads)
+               return -ENOMEM;
+
+       *_offloads = cpu_to_virtio64(vi->vdev, offloads);
+
+       sg_init_one(&sg, _offloads, sizeof(*_offloads));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_GUEST_OFFLOADS,
                                  VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET, &sg)) {
        }
 
        if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_DEVICE_STATS)) {
+               struct virtio_net_stats_capabilities *stats_cap  __free(kfree) = NULL;
                struct scatterlist sg;
                __le64 v;
 
-               sg_init_one(&sg, &vi->ctrl->stats_cap, sizeof(vi->ctrl->stats_cap));
+               stats_cap = kzalloc(sizeof(*stats_cap), GFP_KERNEL);
+               if (!stats_cap) {
+                       rtnl_unlock();
+                       err = -ENOMEM;
+                       goto free_unregister_netdev;
+               }
+
+               sg_init_one(&sg, stats_cap, sizeof(*stats_cap));
 
                if (!virtnet_send_command_reply(vi, VIRTIO_NET_CTRL_STATS,
                                                VIRTIO_NET_CTRL_STATS_QUERY,
                        goto free_unregister_netdev;
                }
 
-               v = vi->ctrl->stats_cap.supported_stats_types[0];
+               v = stats_cap->supported_stats_types[0];
                vi->device_stats_cap = le64_to_cpu(v);
        }