Skip to content

Commit ff7c7d9

Browse files
danielj-mellanoxPaolo Abeni
authored andcommitted
virtio_net: Remove command data from control_buf
Allocate memory for the data when it's used. Ideally the struct could be on the stack, but we can't DMA stack memory. With this change only the header and status memory are shared between commands, which will allow using a tighter lock than RTNL. Signed-off-by: Daniel Jurgens <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Reviewed-by: Heng Qi <[email protected]> Tested-by: Heng Qi <[email protected]> Acked-by: Jason Wang <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent fce2903 commit ff7c7d9

File tree

1 file changed

+85
-39
lines changed

1 file changed

+85
-39
lines changed

drivers/net/virtio_net.c

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -368,15 +368,6 @@ struct virtio_net_ctrl_rss {
368368
struct control_buf {
369369
struct virtio_net_ctrl_hdr hdr;
370370
virtio_net_ctrl_ack status;
371-
struct virtio_net_ctrl_mq mq;
372-
u8 promisc;
373-
u8 allmulti;
374-
__virtio16 vid;
375-
__virtio64 offloads;
376-
struct virtio_net_ctrl_coal_tx coal_tx;
377-
struct virtio_net_ctrl_coal_rx coal_rx;
378-
struct virtio_net_ctrl_coal_vq coal_vq;
379-
struct virtio_net_stats_capabilities stats_cap;
380371
};
381372

382373
struct virtnet_info {
@@ -2828,14 +2819,19 @@ static void virtnet_ack_link_announce(struct virtnet_info *vi)
28282819

28292820
static int _virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
28302821
{
2822+
struct virtio_net_ctrl_mq *mq __free(kfree) = NULL;
28312823
struct scatterlist sg;
28322824
struct net_device *dev = vi->dev;
28332825

28342826
if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ))
28352827
return 0;
28362828

2837-
vi->ctrl->mq.virtqueue_pairs = cpu_to_virtio16(vi->vdev, queue_pairs);
2838-
sg_init_one(&sg, &vi->ctrl->mq, sizeof(vi->ctrl->mq));
2829+
mq = kzalloc(sizeof(*mq), GFP_KERNEL);
2830+
if (!mq)
2831+
return -ENOMEM;
2832+
2833+
mq->virtqueue_pairs = cpu_to_virtio16(vi->vdev, queue_pairs);
2834+
sg_init_one(&sg, mq, sizeof(*mq));
28392835

28402836
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
28412837
VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg)) {
@@ -2864,6 +2860,7 @@ static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
28642860

28652861
static int virtnet_close(struct net_device *dev)
28662862
{
2863+
u8 *promisc_allmulti __free(kfree) = NULL;
28672864
struct virtnet_info *vi = netdev_priv(dev);
28682865
int i;
28692866

@@ -2888,6 +2885,7 @@ static void virtnet_rx_mode_work(struct work_struct *work)
28882885
struct scatterlist sg[2];
28892886
struct virtio_net_ctrl_mac *mac_data;
28902887
struct netdev_hw_addr *ha;
2888+
u8 *promisc_allmulti;
28912889
int uc_count;
28922890
int mc_count;
28932891
void *buf;
@@ -2899,22 +2897,27 @@ static void virtnet_rx_mode_work(struct work_struct *work)
28992897

29002898
rtnl_lock();
29012899

2902-
vi->ctrl->promisc = ((dev->flags & IFF_PROMISC) != 0);
2903-
vi->ctrl->allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
2900+
promisc_allmulti = kzalloc(sizeof(*promisc_allmulti), GFP_ATOMIC);
2901+
if (!promisc_allmulti) {
2902+
dev_warn(&dev->dev, "Failed to set RX mode, no memory.\n");
2903+
return;
2904+
}
29042905

2905-
sg_init_one(sg, &vi->ctrl->promisc, sizeof(vi->ctrl->promisc));
2906+
*promisc_allmulti = !!(dev->flags & IFF_PROMISC);
2907+
sg_init_one(sg, promisc_allmulti, sizeof(*promisc_allmulti));
29062908

29072909
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
29082910
VIRTIO_NET_CTRL_RX_PROMISC, sg))
29092911
dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
2910-
vi->ctrl->promisc ? "en" : "dis");
2912+
*promisc_allmulti ? "en" : "dis");
29112913

2912-
sg_init_one(sg, &vi->ctrl->allmulti, sizeof(vi->ctrl->allmulti));
2914+
*promisc_allmulti = !!(dev->flags & IFF_ALLMULTI);
2915+
sg_init_one(sg, promisc_allmulti, sizeof(*promisc_allmulti));
29132916

29142917
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
29152918
VIRTIO_NET_CTRL_RX_ALLMULTI, sg))
29162919
dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
2917-
vi->ctrl->allmulti ? "en" : "dis");
2920+
*promisc_allmulti ? "en" : "dis");
29182921

29192922
netif_addr_lock_bh(dev);
29202923

@@ -2975,10 +2978,15 @@ static int virtnet_vlan_rx_add_vid(struct net_device *dev,
29752978
__be16 proto, u16 vid)
29762979
{
29772980
struct virtnet_info *vi = netdev_priv(dev);
2981+
__virtio16 *_vid __free(kfree) = NULL;
29782982
struct scatterlist sg;
29792983

2980-
vi->ctrl->vid = cpu_to_virtio16(vi->vdev, vid);
2981-
sg_init_one(&sg, &vi->ctrl->vid, sizeof(vi->ctrl->vid));
2984+
_vid = kzalloc(sizeof(*_vid), GFP_KERNEL);
2985+
if (!_vid)
2986+
return -ENOMEM;
2987+
2988+
*_vid = cpu_to_virtio16(vi->vdev, vid);
2989+
sg_init_one(&sg, _vid, sizeof(*_vid));
29822990

29832991
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
29842992
VIRTIO_NET_CTRL_VLAN_ADD, &sg))
@@ -2990,10 +2998,15 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev,
29902998
__be16 proto, u16 vid)
29912999
{
29923000
struct virtnet_info *vi = netdev_priv(dev);
3001+
__virtio16 *_vid __free(kfree) = NULL;
29933002
struct scatterlist sg;
29943003

2995-
vi->ctrl->vid = cpu_to_virtio16(vi->vdev, vid);
2996-
sg_init_one(&sg, &vi->ctrl->vid, sizeof(vi->ctrl->vid));
3004+
_vid = kzalloc(sizeof(*_vid), GFP_KERNEL);
3005+
if (!_vid)
3006+
return -ENOMEM;
3007+
3008+
*_vid = cpu_to_virtio16(vi->vdev, vid);
3009+
sg_init_one(&sg, _vid, sizeof(*_vid));
29973010

29983011
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
29993012
VIRTIO_NET_CTRL_VLAN_DEL, &sg))
@@ -3106,12 +3119,17 @@ static void virtnet_cpu_notif_remove(struct virtnet_info *vi)
31063119
static int virtnet_send_ctrl_coal_vq_cmd(struct virtnet_info *vi,
31073120
u16 vqn, u32 max_usecs, u32 max_packets)
31083121
{
3122+
struct virtio_net_ctrl_coal_vq *coal_vq __free(kfree) = NULL;
31093123
struct scatterlist sgs;
31103124

3111-
vi->ctrl->coal_vq.vqn = cpu_to_le16(vqn);
3112-
vi->ctrl->coal_vq.coal.max_usecs = cpu_to_le32(max_usecs);
3113-
vi->ctrl->coal_vq.coal.max_packets = cpu_to_le32(max_packets);
3114-
sg_init_one(&sgs, &vi->ctrl->coal_vq, sizeof(vi->ctrl->coal_vq));
3125+
coal_vq = kzalloc(sizeof(*coal_vq), GFP_KERNEL);
3126+
if (!coal_vq)
3127+
return -ENOMEM;
3128+
3129+
coal_vq->vqn = cpu_to_le16(vqn);
3130+
coal_vq->coal.max_usecs = cpu_to_le32(max_usecs);
3131+
coal_vq->coal.max_packets = cpu_to_le32(max_packets);
3132+
sg_init_one(&sgs, coal_vq, sizeof(*coal_vq));
31153133

31163134
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL,
31173135
VIRTIO_NET_CTRL_NOTF_COAL_VQ_SET,
@@ -3257,11 +3275,15 @@ static bool virtnet_commit_rss_command(struct virtnet_info *vi)
32573275

32583276
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
32593277
vi->has_rss ? VIRTIO_NET_CTRL_MQ_RSS_CONFIG
3260-
: VIRTIO_NET_CTRL_MQ_HASH_CONFIG, sgs)) {
3261-
dev_warn(&dev->dev, "VIRTIONET issue with committing RSS sgs\n");
3262-
return false;
3263-
}
3278+
: VIRTIO_NET_CTRL_MQ_HASH_CONFIG, sgs))
3279+
goto err;
3280+
32643281
return true;
3282+
3283+
err:
3284+
dev_warn(&dev->dev, "VIRTIONET issue with committing RSS sgs\n");
3285+
return false;
3286+
32653287
}
32663288

32673289
static void virtnet_init_default_rss(struct virtnet_info *vi)
@@ -4193,12 +4215,17 @@ static int virtnet_get_link_ksettings(struct net_device *dev,
41934215
static int virtnet_send_tx_notf_coal_cmds(struct virtnet_info *vi,
41944216
struct ethtool_coalesce *ec)
41954217
{
4218+
struct virtio_net_ctrl_coal_tx *coal_tx __free(kfree) = NULL;
41964219
struct scatterlist sgs_tx;
41974220
int i;
41984221

4199-
vi->ctrl->coal_tx.tx_usecs = cpu_to_le32(ec->tx_coalesce_usecs);
4200-
vi->ctrl->coal_tx.tx_max_packets = cpu_to_le32(ec->tx_max_coalesced_frames);
4201-
sg_init_one(&sgs_tx, &vi->ctrl->coal_tx, sizeof(vi->ctrl->coal_tx));
4222+
coal_tx = kzalloc(sizeof(*coal_tx), GFP_KERNEL);
4223+
if (!coal_tx)
4224+
return -ENOMEM;
4225+
4226+
coal_tx->tx_usecs = cpu_to_le32(ec->tx_coalesce_usecs);
4227+
coal_tx->tx_max_packets = cpu_to_le32(ec->tx_max_coalesced_frames);
4228+
sg_init_one(&sgs_tx, coal_tx, sizeof(*coal_tx));
42024229

42034230
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL,
42044231
VIRTIO_NET_CTRL_NOTF_COAL_TX_SET,
@@ -4218,6 +4245,7 @@ static int virtnet_send_tx_notf_coal_cmds(struct virtnet_info *vi,
42184245
static int virtnet_send_rx_notf_coal_cmds(struct virtnet_info *vi,
42194246
struct ethtool_coalesce *ec)
42204247
{
4248+
struct virtio_net_ctrl_coal_rx *coal_rx __free(kfree) = NULL;
42214249
bool rx_ctrl_dim_on = !!ec->use_adaptive_rx_coalesce;
42224250
struct scatterlist sgs_rx;
42234251
int i;
@@ -4236,6 +4264,10 @@ static int virtnet_send_rx_notf_coal_cmds(struct virtnet_info *vi,
42364264
return 0;
42374265
}
42384266

4267+
coal_rx = kzalloc(sizeof(*coal_rx), GFP_KERNEL);
4268+
if (!coal_rx)
4269+
return -ENOMEM;
4270+
42394271
if (!rx_ctrl_dim_on && vi->rx_dim_enabled) {
42404272
vi->rx_dim_enabled = false;
42414273
for (i = 0; i < vi->max_queue_pairs; i++)
@@ -4246,9 +4278,9 @@ static int virtnet_send_rx_notf_coal_cmds(struct virtnet_info *vi,
42464278
* we need apply the global new params even if they
42474279
* are not updated.
42484280
*/
4249-
vi->ctrl->coal_rx.rx_usecs = cpu_to_le32(ec->rx_coalesce_usecs);
4250-
vi->ctrl->coal_rx.rx_max_packets = cpu_to_le32(ec->rx_max_coalesced_frames);
4251-
sg_init_one(&sgs_rx, &vi->ctrl->coal_rx, sizeof(vi->ctrl->coal_rx));
4281+
coal_rx->rx_usecs = cpu_to_le32(ec->rx_coalesce_usecs);
4282+
coal_rx->rx_max_packets = cpu_to_le32(ec->rx_max_coalesced_frames);
4283+
sg_init_one(&sgs_rx, coal_rx, sizeof(*coal_rx));
42524284

42534285
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL,
42544286
VIRTIO_NET_CTRL_NOTF_COAL_RX_SET,
@@ -4823,10 +4855,16 @@ static int virtnet_restore_up(struct virtio_device *vdev)
48234855

48244856
static int virtnet_set_guest_offloads(struct virtnet_info *vi, u64 offloads)
48254857
{
4858+
__virtio64 *_offloads __free(kfree) = NULL;
48264859
struct scatterlist sg;
4827-
vi->ctrl->offloads = cpu_to_virtio64(vi->vdev, offloads);
48284860

4829-
sg_init_one(&sg, &vi->ctrl->offloads, sizeof(vi->ctrl->offloads));
4861+
_offloads = kzalloc(sizeof(*_offloads), GFP_KERNEL);
4862+
if (!_offloads)
4863+
return -ENOMEM;
4864+
4865+
*_offloads = cpu_to_virtio64(vi->vdev, offloads);
4866+
4867+
sg_init_one(&sg, _offloads, sizeof(*_offloads));
48304868

48314869
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_GUEST_OFFLOADS,
48324870
VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET, &sg)) {
@@ -5810,10 +5848,18 @@ static int virtnet_probe(struct virtio_device *vdev)
58105848
}
58115849

58125850
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_DEVICE_STATS)) {
5851+
struct virtio_net_stats_capabilities *stats_cap __free(kfree) = NULL;
58135852
struct scatterlist sg;
58145853
__le64 v;
58155854

5816-
sg_init_one(&sg, &vi->ctrl->stats_cap, sizeof(vi->ctrl->stats_cap));
5855+
stats_cap = kzalloc(sizeof(*stats_cap), GFP_KERNEL);
5856+
if (!stats_cap) {
5857+
rtnl_unlock();
5858+
err = -ENOMEM;
5859+
goto free_unregister_netdev;
5860+
}
5861+
5862+
sg_init_one(&sg, stats_cap, sizeof(*stats_cap));
58175863

58185864
if (!virtnet_send_command_reply(vi, VIRTIO_NET_CTRL_STATS,
58195865
VIRTIO_NET_CTRL_STATS_QUERY,
@@ -5824,7 +5870,7 @@ static int virtnet_probe(struct virtio_device *vdev)
58245870
goto free_unregister_netdev;
58255871
}
58265872

5827-
v = vi->ctrl->stats_cap.supported_stats_types[0];
5873+
v = stats_cap->supported_stats_types[0];
58285874
vi->device_stats_cap = le64_to_cpu(v);
58295875
}
58305876

0 commit comments

Comments
 (0)