Pull virtio updates from Michael Tsirkin: - vdpa generic device type support - more virtio hardening for broken devices (but on the same theme, revert some virtio hotplug hardening patches - they were misusing some interrupt flags and had to be reverted) - RSS support in virtio-net - max device MTU support in mlx5 vdpa - akcipher support in virtio-crypto - shared IRQ support in ifcvf vdpa - a minor performance improvement in vhost - enable virtio mem for ARM64 - beginnings of advance dma support - cleanups, fixes all over the place * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (33 commits) vdpa/mlx5: Avoid processing works if workqueue was destroyed vhost: handle error while adding split ranges to iotlb vdpa: support exposing the count of vqs to userspace vdpa: change the type of nvqs to u32 vdpa: support exposing the config size to userspace vdpa/mlx5: re-create forwarding rules after mac modified virtio: pci: check bar values read from virtio config space Revert "virtio_pci: harden MSI-X interrupts" Revert "virtio-pci: harden INTX interrupts" drivers/net/virtio_net: Added RSS hash report control. drivers/net/virtio_net: Added RSS hash report. drivers/net/virtio_net: Added basic RSS support. drivers/net/virtio_net: Fixed padded vheader to use v1 with hash. virtio: use virtio_device_ready() in virtio_device_restore() tools/virtio: compile with -pthread tools/virtio: fix after premapped buf support virtio_ring: remove flags check for unmap packed indirect desc virtio_ring: remove flags check for unmap split indirect desc virtio_ring: rename vring_unmap_state_packed() to vring_unmap_extra_packed() net/mlx5: Add support for configuring max device MTU ...
Unified · Split
| @@ -3,8 +3,11 @@ config CRYPTO_DEV_VIRTIO · 2 unmodified lines | |||
| 3 | tristate "VirtIO crypto driver" | 3 | tristate "VirtIO crypto driver" |
| 4 | depends on VIRTIO | 4 | depends on VIRTIO |
| 5 | select CRYPTO_AEAD | 5 | select CRYPTO_AEAD |
| 6 | select CRYPTO_AKCIPHER2 | ||
| 6 | select CRYPTO_SKCIPHER | 7 | select CRYPTO_SKCIPHER |
| 7 | select CRYPTO_ENGINE | 8 | select CRYPTO_ENGINE |
| 9 | select CRYPTO_RSA | ||
| 10 | select MPILIB | ||
| 8 | help | 11 | help |
| 9 | This driver provides support for virtio crypto device. If you | 12 | This driver provides support for virtio crypto device. If you |
| 10 | choose 'M' here, this module will be called virtio_crypto. | 13 | choose 'M' here, this module will be called virtio_crypto. |
| @@ -1,6 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio_crypto.o | 2 | obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio_crypto.o |
| 3 | virtio_crypto-objs := \ | 3 | virtio_crypto-objs := \ |
| 4 | virtio_crypto_algs.o \ | 4 | virtio_crypto_skcipher_algs.o \ |
| 5 | virtio_crypto_akcipher_algs.o \ | ||
| 5 | virtio_crypto_mgr.o \ | 6 | virtio_crypto_mgr.o \ |
| 6 | virtio_crypto_core.o | 7 | virtio_crypto_core.o |
| @@ -0,0 +1,585 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 2 | /* Asymmetric algorithms supported by virtio crypto device | ||
| 3 | * | ||
| 4 | * Authors: zhenwei pi <pizhenwei@bytedance.com> | ||
| 5 | * lei he <helei.sig11@bytedance.com> | ||
| 6 | * | ||
| 7 | * Copyright 2022 Bytedance CO., LTD. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/mpi.h> | ||
| 11 | #include <linux/scatterlist.h> | ||
| 12 | #include <crypto/algapi.h> | ||
| 13 | #include <crypto/internal/akcipher.h> | ||
| 14 | #include <crypto/internal/rsa.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <crypto/scatterwalk.h> | ||
| 17 | #include <linux/atomic.h> | ||
| 18 | |||
| 19 | #include <uapi/linux/virtio_crypto.h> | ||
| 20 | #include "virtio_crypto_common.h" | ||
| 21 | |||
| 22 | struct virtio_crypto_rsa_ctx { | ||
| 23 | MPI n; | ||
| 24 | }; | ||
| 25 | |||
| 26 | struct virtio_crypto_akcipher_ctx { | ||
| 27 | struct crypto_engine_ctx enginectx; | ||
| 28 | struct virtio_crypto *vcrypto; | ||
| 29 | struct crypto_akcipher *tfm; | ||
| 30 | bool session_valid; | ||
| 31 | __u64 session_id; | ||
| 32 | union { | ||
| 33 | struct virtio_crypto_rsa_ctx rsa_ctx; | ||
| 34 | }; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct virtio_crypto_akcipher_request { | ||
| 38 | struct virtio_crypto_request base; | ||
| 39 | struct virtio_crypto_akcipher_ctx *akcipher_ctx; | ||
| 40 | struct akcipher_request *akcipher_req; | ||
| 41 | void *src_buf; | ||
| 42 | void *dst_buf; | ||
| 43 | uint32_t opcode; | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct virtio_crypto_akcipher_algo { | ||
| 47 | uint32_t algonum; | ||
| 48 | uint32_t service; | ||
| 49 | unsigned int active_devs; | ||
| 50 | struct akcipher_alg algo; | ||
| 51 | }; | ||
| 52 | |||
| 53 | static DEFINE_MUTEX(algs_lock); | ||
| 54 | |||
| 55 | static void virtio_crypto_akcipher_finalize_req( | ||
| 56 | struct virtio_crypto_akcipher_request *vc_akcipher_req, | ||
| 57 | struct akcipher_request *req, int err) | ||
| 58 | { | ||
| 59 | virtcrypto_clear_request(&vc_akcipher_req->base); | ||
| 60 | |||
| 61 | crypto_finalize_akcipher_request(vc_akcipher_req->base.dataq->engine, req, err); | ||
| 62 | } | ||
| 63 | |||
| 64 | static void virtio_crypto_dataq_akcipher_callback(struct virtio_crypto_request *vc_req, int len) | ||
| 65 | { | ||
| 66 | struct virtio_crypto_akcipher_request *vc_akcipher_req = | ||
| 67 | container_of(vc_req, struct virtio_crypto_akcipher_request, base); | ||
| 68 | struct akcipher_request *akcipher_req; | ||
| 69 | int error; | ||
| 70 | |||
| 71 | switch (vc_req->status) { | ||
| 72 | case VIRTIO_CRYPTO_OK: | ||
| 73 | error = 0; | ||
| 74 | break; | ||
| 75 | case VIRTIO_CRYPTO_INVSESS: | ||
| 76 | case VIRTIO_CRYPTO_ERR: | ||
| 77 | error = -EINVAL; | ||
| 78 | break; | ||
| 79 | case VIRTIO_CRYPTO_BADMSG: | ||
| 80 | error = -EBADMSG; | ||
| 81 | break; | ||
| 82 | |||
| 83 | case VIRTIO_CRYPTO_KEY_REJECTED: | ||
| 84 | error = -EKEYREJECTED; | ||
| 85 | break; | ||
| 86 | |||
| 87 | default: | ||
| 88 | error = -EIO; | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | |||
| 92 | akcipher_req = vc_akcipher_req->akcipher_req; | ||
| 93 | if (vc_akcipher_req->opcode != VIRTIO_CRYPTO_AKCIPHER_VERIFY) | ||
| 94 | sg_copy_from_buffer(akcipher_req->dst, sg_nents(akcipher_req->dst), | ||
| 95 | vc_akcipher_req->dst_buf, akcipher_req->dst_len); | ||
| 96 | virtio_crypto_akcipher_finalize_req(vc_akcipher_req, akcipher_req, error); | ||
| 97 | } | ||
| 98 | |||
| 99 | static int virtio_crypto_alg_akcipher_init_session(struct virtio_crypto_akcipher_ctx *ctx, | ||
| 100 | struct virtio_crypto_ctrl_header *header, void *para, | ||
| 101 | const uint8_t *key, unsigned int keylen) | ||
| 102 | { | ||
| 103 | struct scatterlist outhdr_sg, key_sg, inhdr_sg, *sgs[3]; | ||
| 104 | struct virtio_crypto *vcrypto = ctx->vcrypto; | ||
| 105 | uint8_t *pkey; | ||
| 106 | unsigned int inlen; | ||
| 107 | int err; | ||
| 108 | unsigned int num_out = 0, num_in = 0; | ||
| 109 | |||
| 110 | pkey = kmemdup(key, keylen, GFP_ATOMIC); | ||
| 111 | if (!pkey) | ||
| 112 | return -ENOMEM; | ||
| 113 | |||
| 114 | spin_lock(&vcrypto->ctrl_lock); | ||
| 115 | memcpy(&vcrypto->ctrl.header, header, sizeof(vcrypto->ctrl.header)); | ||
| 116 | memcpy(&vcrypto->ctrl.u, para, sizeof(vcrypto->ctrl.u)); | ||
| 117 | vcrypto->input.status = cpu_to_le32(VIRTIO_CRYPTO_ERR); | ||
| 118 | |||
| 119 | sg_init_one(&outhdr_sg, &vcrypto->ctrl, sizeof(vcrypto->ctrl)); | ||
| 120 | sgs[num_out++] = &outhdr_sg; | ||
| 121 | |||
| 122 | sg_init_one(&key_sg, pkey, keylen); | ||
| 123 | sgs[num_out++] = &key_sg; | ||
| 124 | |||
| 125 | sg_init_one(&inhdr_sg, &vcrypto->input, sizeof(vcrypto->input)); | ||
| 126 | sgs[num_out + num_in++] = &inhdr_sg; | ||
| 127 | |||
| 128 | err = virtqueue_add_sgs(vcrypto->ctrl_vq, sgs, num_out, num_in, vcrypto, GFP_ATOMIC); | ||
| 129 | if (err < 0) | ||
| 130 | goto out; | ||
| 131 | |||
| 132 | virtqueue_kick(vcrypto->ctrl_vq); | ||
| 133 | while (!virtqueue_get_buf(vcrypto->ctrl_vq, &inlen) && | ||
| 134 | !virtqueue_is_broken(vcrypto->ctrl_vq)) | ||
| 135 | cpu_relax(); | ||
| 136 | |||
| 137 | if (le32_to_cpu(vcrypto->input.status) != VIRTIO_CRYPTO_OK) { | ||
| 138 | err = -EINVAL; | ||
| 139 | goto out; | ||
| 140 | } | ||
| 141 | |||
| 142 | ctx->session_id = le64_to_cpu(vcrypto->input.session_id); | ||
| 143 | ctx->session_valid = true; | ||
| 144 | err = 0; | ||
| 145 | |||
| 146 | out: | ||
| 147 | spin_unlock(&vcrypto->ctrl_lock); | ||
| 148 | kfree_sensitive(pkey); | ||
| 149 | |||
| 150 | if (err < 0) | ||
| 151 | pr_err("virtio_crypto: Create session failed status: %u\n", | ||
| 152 | le32_to_cpu(vcrypto->input.status)); | ||
| 153 | |||
| 154 | return err; | ||
| 155 | } | ||
| 156 | |||
| 157 | static int virtio_crypto_alg_akcipher_close_session(struct virtio_crypto_akcipher_ctx *ctx) | ||
| 158 | { | ||
| 159 | struct scatterlist outhdr_sg, inhdr_sg, *sgs[2]; | ||
| 160 | struct virtio_crypto_destroy_session_req *destroy_session; | ||
| 161 | struct virtio_crypto *vcrypto = ctx->vcrypto; | ||
| 162 | unsigned int num_out = 0, num_in = 0, inlen; | ||
| 163 | int err; | ||
| 164 | |||
| 165 | spin_lock(&vcrypto->ctrl_lock); | ||
| 166 | if (!ctx->session_valid) { | ||
| 167 | err = 0; | ||
| 168 | goto out; | ||
| 169 | } | ||
| 170 | vcrypto->ctrl_status.status = VIRTIO_CRYPTO_ERR; | ||
| 171 | vcrypto->ctrl.header.opcode = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_DESTROY_SESSION); | ||
| 172 | vcrypto->ctrl.header.queue_id = 0; | ||
| 173 | |||
| 174 | destroy_session = &vcrypto->ctrl.u.destroy_session; | ||
| 175 | destroy_session->session_id = cpu_to_le64(ctx->session_id); | ||
| 176 | |||
| 177 | sg_init_one(&outhdr_sg, &vcrypto->ctrl, sizeof(vcrypto->ctrl)); | ||
| 178 | sgs[num_out++] = &outhdr_sg; | ||
| 179 | |||
| 180 | sg_init_one(&inhdr_sg, &vcrypto->ctrl_status.status, sizeof(vcrypto->ctrl_status.status)); | ||
| 181 | sgs[num_out + num_in++] = &inhdr_sg; | ||
| 182 | |||
| 183 | err = virtqueue_add_sgs(vcrypto->ctrl_vq, sgs, num_out, num_in, vcrypto, GFP_ATOMIC); | ||
| 184 | if (err < 0) | ||
| 185 | goto out; | ||
| 186 | |||
| 187 | virtqueue_kick(vcrypto->ctrl_vq); | ||
| 188 | while (!virtqueue_get_buf(vcrypto->ctrl_vq, &inlen) && | ||
| 189 | !virtqueue_is_broken(vcrypto->ctrl_vq)) | ||
| 190 | cpu_relax(); | ||
| 191 | |||
| 192 | if (vcrypto->ctrl_status.status != VIRTIO_CRYPTO_OK) { | ||
| 193 | err = -EINVAL; | ||
| 194 | goto out; | ||
| 195 | } | ||
| 196 | |||
| 197 | err = 0; | ||
| 198 | ctx->session_valid = false; | ||
| 199 | |||
| 200 | out: | ||
| 201 | spin_unlock(&vcrypto->ctrl_lock); | ||
| 202 | if (err < 0) { | ||
| 203 | pr_err("virtio_crypto: Close session failed status: %u, session_id: 0x%llx\n", | ||
| 204 | vcrypto->ctrl_status.status, destroy_session->session_id); | ||
| 205 | } | ||
| 206 | |||
| 207 | return err; | ||
| 208 | } | ||
| 209 | |||
| 210 | static int __virtio_crypto_akcipher_do_req(struct virtio_crypto_akcipher_request *vc_akcipher_req, | ||
| 211 | struct akcipher_request *req, struct data_queue *data_vq) | ||
| 212 | { | ||
| 213 | struct virtio_crypto_akcipher_ctx *ctx = vc_akcipher_req->akcipher_ctx; | ||
| 214 | struct virtio_crypto_request *vc_req = &vc_akcipher_req->base; | ||
| 215 | struct virtio_crypto *vcrypto = ctx->vcrypto; | ||
| 216 | struct virtio_crypto_op_data_req *req_data = vc_req->req_data; | ||
| 217 | struct scatterlist *sgs[4], outhdr_sg, inhdr_sg, srcdata_sg, dstdata_sg; | ||
| 218 | void *src_buf = NULL, *dst_buf = NULL; | ||
| 219 | unsigned int num_out = 0, num_in = 0; | ||
| 220 | int node = dev_to_node(&vcrypto->vdev->dev); | ||
| 221 | unsigned long flags; | ||
| 222 | int ret = -ENOMEM; | ||
| 223 | bool verify = vc_akcipher_req->opcode == VIRTIO_CRYPTO_AKCIPHER_VERIFY; | ||
| 224 | unsigned int src_len = verify ? req->src_len + req->dst_len : req->src_len; | ||
| 225 | |||
| 226 | /* out header */ | ||
| 227 | sg_init_one(&outhdr_sg, req_data, sizeof(*req_data)); | ||
| 228 | sgs[num_out++] = &outhdr_sg; | ||
| 229 | |||
| 230 | /* src data */ | ||
| 231 | src_buf = kcalloc_node(src_len, 1, GFP_KERNEL, node); | ||
| 232 | if (!src_buf) | ||
| 233 | goto err; | ||
| 234 | |||
| 235 | if (verify) { | ||
| 236 | /* for verify operation, both src and dst data work as OUT direction */ | ||
| 237 | sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, src_len); | ||
| 238 | sg_init_one(&srcdata_sg, src_buf, src_len); | ||
| 239 | sgs[num_out++] = &srcdata_sg; | ||
| 240 | } else { | ||
| 241 | sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, src_len); | ||
| 242 | sg_init_one(&srcdata_sg, src_buf, src_len); | ||
| 243 | sgs[num_out++] = &srcdata_sg; | ||
| 244 | |||
| 245 | /* dst data */ | ||
| 246 | dst_buf = kcalloc_node(req->dst_len, 1, GFP_KERNEL, node); | ||
| 247 | if (!dst_buf) | ||
| 248 | goto err; | ||
| 249 | |||
| 250 | sg_init_one(&dstdata_sg, dst_buf, req->dst_len); | ||
| 251 | sgs[num_out + num_in++] = &dstdata_sg; | ||
| 252 | } | ||
| 253 | |||
| 254 | vc_akcipher_req->src_buf = src_buf; | ||
| 255 | vc_akcipher_req->dst_buf = dst_buf; | ||
| 256 | |||
| 257 | /* in header */ | ||
| 258 | sg_init_one(&inhdr_sg, &vc_req->status, sizeof(vc_req->status)); | ||
| 259 | sgs[num_out + num_in++] = &inhdr_sg; | ||
| 260 | |||
| 261 | spin_lock_irqsave(&data_vq->lock, flags); | ||
| 262 | ret = virtqueue_add_sgs(data_vq->vq, sgs, num_out, num_in, vc_req, GFP_ATOMIC); | ||
| 263 | virtqueue_kick(data_vq->vq); | ||
| 264 | spin_unlock_irqrestore(&data_vq->lock, flags); | ||
| 265 | if (ret) | ||
| 266 | goto err; | ||
| 267 | |||
| 268 | return 0; | ||
| 269 | |||
| 270 | err: | ||
| 271 | kfree(src_buf); | ||
| 272 | kfree(dst_buf); | ||
| 273 | |||
| 274 | return -ENOMEM; | ||
| 275 | } | ||
| 276 | |||
| 277 | static int virtio_crypto_rsa_do_req(struct crypto_engine *engine, void *vreq) | ||
| 278 | { | ||
| 279 | struct akcipher_request *req = container_of(vreq, struct akcipher_request, base); | ||
| 280 | struct virtio_crypto_akcipher_request *vc_akcipher_req = akcipher_request_ctx(req); | ||
| 281 | struct virtio_crypto_request *vc_req = &vc_akcipher_req->base; | ||
| 282 | struct virtio_crypto_akcipher_ctx *ctx = vc_akcipher_req->akcipher_ctx; | ||
| 283 | struct virtio_crypto *vcrypto = ctx->vcrypto; | ||
| 284 | struct data_queue *data_vq = vc_req->dataq; | ||
| 285 | struct virtio_crypto_op_header *header; | ||
| 286 | struct virtio_crypto_akcipher_data_req *akcipher_req; | ||
| 287 | int ret; | ||
| 288 | |||
| 289 | vc_req->sgs = NULL; | ||
| 290 | vc_req->req_data = kzalloc_node(sizeof(*vc_req->req_data), | ||
| 291 | GFP_KERNEL, dev_to_node(&vcrypto->vdev->dev)); | ||
| 292 | if (!vc_req->req_data) | ||
| 293 | return -ENOMEM; | ||
| 294 | |||
| 295 | /* build request header */ | ||
| 296 | header = &vc_req->req_data->header; | ||
| 297 | header->opcode = cpu_to_le32(vc_akcipher_req->opcode); | ||
| 298 | header->algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_RSA); | ||
| 299 | header->session_id = cpu_to_le64(ctx->session_id); | ||
| 300 | |||
| 301 | /* build request akcipher data */ | ||
| 302 | akcipher_req = &vc_req->req_data->u.akcipher_req; | ||
| 303 | akcipher_req->para.src_data_len = cpu_to_le32(req->src_len); | ||
| 304 | akcipher_req->para.dst_data_len = cpu_to_le32(req->dst_len); | ||
| 305 | |||
| 306 | ret = __virtio_crypto_akcipher_do_req(vc_akcipher_req, req, data_vq); | ||
| 307 | if (ret < 0) { | ||
| 308 | kfree_sensitive(vc_req->req_data); | ||
| 309 | vc_req->req_data = NULL; | ||
| 310 | return ret; | ||
| 311 | } | ||
| 312 | |||
| 313 | return 0; | ||
| 314 | } | ||
| 315 | |||
| 316 | static int virtio_crypto_rsa_req(struct akcipher_request *req, uint32_t opcode) | ||
| 317 | { | ||
| 318 | struct crypto_akcipher *atfm = crypto_akcipher_reqtfm(req); | ||
| 319 | struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(atfm); | ||
| 320 | struct virtio_crypto_akcipher_request *vc_akcipher_req = akcipher_request_ctx(req); | ||
| 321 | struct virtio_crypto_request *vc_req = &vc_akcipher_req->base; | ||
| 322 | struct virtio_crypto *vcrypto = ctx->vcrypto; | ||
| 323 | /* Use the first data virtqueue as default */ | ||
| 324 | struct data_queue *data_vq = &vcrypto->data_vq[0]; | ||
| 325 | |||
| 326 | vc_req->dataq = data_vq; | ||
| 327 | vc_req->alg_cb = virtio_crypto_dataq_akcipher_callback; | ||
| 328 | vc_akcipher_req->akcipher_ctx = ctx; | ||
| 329 | vc_akcipher_req->akcipher_req = req; | ||
| 330 | vc_akcipher_req->opcode = opcode; | ||
| 331 | |||
| 332 | return crypto_transfer_akcipher_request_to_engine(data_vq->engine, req); | ||
| 333 | } | ||
| 334 | |||
| 335 | static int virtio_crypto_rsa_encrypt(struct akcipher_request *req) | ||
| 336 | { | ||
| 337 | return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_ENCRYPT); | ||
| 338 | } | ||
| 339 | |||
| 340 | static int virtio_crypto_rsa_decrypt(struct akcipher_request *req) | ||
| 341 | { | ||
| 342 | return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_DECRYPT); | ||
| 343 | } | ||
| 344 | |||
| 345 | static int virtio_crypto_rsa_sign(struct akcipher_request *req) | ||
| 346 | { | ||
| 347 | return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_SIGN); | ||
| 348 | } | ||
| 349 | |||
| 350 | static int virtio_crypto_rsa_verify(struct akcipher_request *req) | ||
| 351 | { | ||
| 352 | return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_VERIFY); | ||
| 353 | } | ||
| 354 | |||
| 355 | static int virtio_crypto_rsa_set_key(struct crypto_akcipher *tfm, | ||
| 356 | const void *key, | ||
| 357 | unsigned int keylen, | ||
| 358 | bool private, | ||
| 359 | int padding_algo, | ||
| 360 | int hash_algo) | ||
| 361 | { | ||
| 362 | struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm); | ||
| 363 | struct virtio_crypto_rsa_ctx *rsa_ctx = &ctx->rsa_ctx; | ||
| 364 | struct virtio_crypto *vcrypto; | ||
| 365 | struct virtio_crypto_ctrl_header header; | ||
| 366 | struct virtio_crypto_akcipher_session_para para; | ||
| 367 | struct rsa_key rsa_key = {0}; | ||
| 368 | int node = virtio_crypto_get_current_node(); | ||
| 369 | uint32_t keytype; | ||
| 370 | int ret; | ||
| 371 | |||
| 372 | /* mpi_free will test n, just free it. */ | ||
| 373 | mpi_free(rsa_ctx->n); | ||
| 374 | rsa_ctx->n = NULL; | ||
| 375 | |||
| 376 | if (private) { | ||
| 377 | keytype = VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE; | ||
| 378 | ret = rsa_parse_priv_key(&rsa_key, key, keylen); | ||
| 379 | } else { | ||
| 380 | keytype = VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC; | ||
| 381 | ret = rsa_parse_pub_key(&rsa_key, key, keylen); | ||
| 382 | } | ||
| 383 | |||
| 384 | if (ret) | ||
| 385 | return ret; | ||
| 386 | |||
| 387 | rsa_ctx->n = mpi_read_raw_data(rsa_key.n, rsa_key.n_sz); | ||
| 388 | if (!rsa_ctx->n) | ||
| 389 | return -ENOMEM; | ||
| 390 | |||
| 391 | if (!ctx->vcrypto) { | ||
| 392 | vcrypto = virtcrypto_get_dev_node(node, VIRTIO_CRYPTO_SERVICE_AKCIPHER, | ||
| 393 | VIRTIO_CRYPTO_AKCIPHER_RSA); | ||
| 394 | if (!vcrypto) { | ||
| 395 | pr_err("virtio_crypto: Could not find a virtio device in the system or unsupported algo\n"); | ||
| 396 | return -ENODEV; | ||
| 397 | } | ||
| 398 | |||
| 399 | ctx->vcrypto = vcrypto; | ||
| 400 | } else { | ||
| 401 | virtio_crypto_alg_akcipher_close_session(ctx); | ||
| 402 | } | ||
| 403 | |||
| 404 | /* set ctrl header */ | ||
| 405 | header.opcode = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION); | ||
| 406 | header.algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_RSA); | ||
| 407 | header.queue_id = 0; | ||
| 408 | |||
| 409 | /* set RSA para */ | ||
| 410 | para.algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_RSA); | ||
| 411 | para.keytype = cpu_to_le32(keytype); | ||
| 412 | para.keylen = cpu_to_le32(keylen); | ||
| 413 | para.u.rsa.padding_algo = cpu_to_le32(padding_algo); | ||
| 414 | para.u.rsa.hash_algo = cpu_to_le32(hash_algo); | ||
| 415 | |||
| 416 | return virtio_crypto_alg_akcipher_init_session(ctx, &header, ¶, key, keylen); | ||
| 417 | } | ||
| 418 | |||
| 419 | static int virtio_crypto_rsa_raw_set_priv_key(struct crypto_akcipher *tfm, | ||
| 420 | const void *key, | ||
| 421 | unsigned int keylen) | ||
| 422 | { | ||
| 423 | return virtio_crypto_rsa_set_key(tfm, key, keylen, 1, | ||
| 424 | VIRTIO_CRYPTO_RSA_RAW_PADDING, | ||
| 425 | VIRTIO_CRYPTO_RSA_NO_HASH); | ||
| 426 | } | ||
| 427 | |||
| 428 | |||
| 429 | static int virtio_crypto_p1pad_rsa_sha1_set_priv_key(struct crypto_akcipher *tfm, | ||
| 430 | const void *key, | ||
| 431 | unsigned int keylen) | ||
| 432 | { | ||
| 433 | return virtio_crypto_rsa_set_key(tfm, key, keylen, 1, | ||
| 434 | VIRTIO_CRYPTO_RSA_PKCS1_PADDING, | ||
| 435 | VIRTIO_CRYPTO_RSA_SHA1); | ||
| 436 | } | ||
| 437 | |||
| 438 | static int virtio_crypto_rsa_raw_set_pub_key(struct crypto_akcipher *tfm, | ||
| 439 | const void *key, | ||
| 440 | unsigned int keylen) | ||
| 441 | { | ||
| 442 | return virtio_crypto_rsa_set_key(tfm, key, keylen, 0, | ||
| 443 | VIRTIO_CRYPTO_RSA_RAW_PADDING, | ||
| 444 | VIRTIO_CRYPTO_RSA_NO_HASH); | ||
| 445 | } | ||
| 446 | |||
| 447 | static int virtio_crypto_p1pad_rsa_sha1_set_pub_key(struct crypto_akcipher *tfm, | ||
| 448 | const void *key, | ||
| 449 | unsigned int keylen) | ||
| 450 | { | ||
| 451 | return virtio_crypto_rsa_set_key(tfm, key, keylen, 0, | ||
| 452 | VIRTIO_CRYPTO_RSA_PKCS1_PADDING, | ||
| 453 | VIRTIO_CRYPTO_RSA_SHA1); | ||
| 454 | } | ||
| 455 | |||
| 456 | static unsigned int virtio_crypto_rsa_max_size(struct crypto_akcipher *tfm) | ||
| 457 | { | ||
| 458 | struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm); | ||
| 459 | struct virtio_crypto_rsa_ctx *rsa_ctx = &ctx->rsa_ctx; | ||
| 460 | |||
| 461 | return mpi_get_size(rsa_ctx->n); | ||
| 462 | } | ||
| 463 | |||
| 464 | static int virtio_crypto_rsa_init_tfm(struct crypto_akcipher *tfm) | ||
| 465 | { | ||
| 466 | struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm); | ||
| 467 | |||
| 468 | ctx->tfm = tfm; | ||
| 469 | ctx->enginectx.op.do_one_request = virtio_crypto_rsa_do_req; | ||
| 470 | ctx->enginectx.op.prepare_request = NULL; | ||
| 471 | ctx->enginectx.op.unprepare_request = NULL; | ||
| 472 | |||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | static void virtio_crypto_rsa_exit_tfm(struct crypto_akcipher *tfm) | ||
| 477 | { | ||
| 478 | struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm); | ||
| 479 | struct virtio_crypto_rsa_ctx *rsa_ctx = &ctx->rsa_ctx; | ||
| 480 | |||
| 481 | virtio_crypto_alg_akcipher_close_session(ctx); | ||
| 482 | virtcrypto_dev_put(ctx->vcrypto); | ||
| 483 | mpi_free(rsa_ctx->n); | ||
| 484 | rsa_ctx->n = NULL; | ||
| 485 | } | ||
| 486 | |||
| 487 | static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = { | ||
| 488 | { | ||
| 489 | .algonum = VIRTIO_CRYPTO_AKCIPHER_RSA, | ||
| 490 | .service = VIRTIO_CRYPTO_SERVICE_AKCIPHER, | ||
| 491 | .algo = { | ||
| 492 | .encrypt = virtio_crypto_rsa_encrypt, | ||
| 493 | .decrypt = virtio_crypto_rsa_decrypt, | ||
| 494 | .set_pub_key = virtio_crypto_rsa_raw_set_pub_key, | ||
| 495 | .set_priv_key = virtio_crypto_rsa_raw_set_priv_key, | ||
| 496 | .max_size = virtio_crypto_rsa_max_size, | ||
| 497 | .init = virtio_crypto_rsa_init_tfm, | ||
| 498 | .exit = virtio_crypto_rsa_exit_tfm, | ||
| 499 | .reqsize = sizeof(struct virtio_crypto_akcipher_request), | ||
| 500 | .base = { | ||
| 501 | .cra_name = "rsa", | ||
| 502 | .cra_driver_name = "virtio-crypto-rsa", | ||
| 503 | .cra_priority = 150, | ||
| 504 | .cra_module = THIS_MODULE, | ||
| 505 | .cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx), | ||
| 506 | }, | ||
| 507 | }, | ||
| 508 | }, | ||
| 509 | { | ||
| 510 | .algonum = VIRTIO_CRYPTO_AKCIPHER_RSA, | ||
| 511 | .service = VIRTIO_CRYPTO_SERVICE_AKCIPHER, | ||
| 512 | .algo = { | ||
| 513 | .encrypt = virtio_crypto_rsa_encrypt, | ||
| 514 | .decrypt = virtio_crypto_rsa_decrypt, | ||
| 515 | .sign = virtio_crypto_rsa_sign, | ||
| 516 | .verify = virtio_crypto_rsa_verify, | ||
| 517 | .set_pub_key = virtio_crypto_p1pad_rsa_sha1_set_pub_key, | ||
| 518 | .set_priv_key = virtio_crypto_p1pad_rsa_sha1_set_priv_key, | ||
| 519 | .max_size = virtio_crypto_rsa_max_size, | ||
| 520 | .init = virtio_crypto_rsa_init_tfm, | ||
| 521 | .exit = virtio_crypto_rsa_exit_tfm, | ||
| 522 | .reqsize = sizeof(struct virtio_crypto_akcipher_request), | ||
| 523 | .base = { | ||
| 524 | .cra_name = "pkcs1pad(rsa,sha1)", | ||
| 525 | .cra_driver_name = "virtio-pkcs1-rsa-with-sha1", | ||
| 526 | .cra_priority = 150, | ||
| 527 | .cra_module = THIS_MODULE, | ||
| 528 | .cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx), | ||
| 529 | }, | ||
| 530 | }, | ||
| 531 | }, | ||
| 532 | }; | ||
| 533 | |||
| 534 | int virtio_crypto_akcipher_algs_register(struct virtio_crypto *vcrypto) | ||
| 535 | { | ||
| 536 | int ret = 0; | ||
| 537 | int i = 0; | ||
| 538 | |||
| 539 | mutex_lock(&algs_lock); | ||
| 540 | |||
| 541 | for (i = 0; i < ARRAY_SIZE(virtio_crypto_akcipher_algs); i++) { | ||
| 542 | uint32_t service = virtio_crypto_akcipher_algs[i].service; | ||
| 543 | uint32_t algonum = virtio_crypto_akcipher_algs[i].algonum; | ||
| 544 | |||
| 545 | if (!virtcrypto_algo_is_supported(vcrypto, service, algonum)) | ||
| 546 | continue; | ||
| 547 | |||
| 548 | if (virtio_crypto_akcipher_algs[i].active_devs == 0) { | ||
| 549 | ret = crypto_register_akcipher(&virtio_crypto_akcipher_algs[i].algo); | ||
| 550 | if (ret) | ||
| 551 | goto unlock; | ||
| 552 | } | ||
| 553 | |||
| 554 | virtio_crypto_akcipher_algs[i].active_devs++; | ||
| 555 | dev_info(&vcrypto->vdev->dev, "Registered akcipher algo %s\n", | ||
| 556 | virtio_crypto_akcipher_algs[i].algo.base.cra_name); | ||
| 557 | } | ||
| 558 | |||
| 559 | unlock: | ||
| 560 | mutex_unlock(&algs_lock); | ||
| 561 | return ret; | ||
| 562 | } | ||
| 563 | |||
| 564 | void virtio_crypto_akcipher_algs_unregister(struct virtio_crypto *vcrypto) | ||
| 565 | { | ||
| 566 | int i = 0; | ||
| 567 | |||
| 568 | mutex_lock(&algs_lock); | ||
| 569 | |||
| 570 | for (i = 0; i < ARRAY_SIZE(virtio_crypto_akcipher_algs); i++) { | ||
| 571 | uint32_t service = virtio_crypto_akcipher_algs[i].service; | ||
| 572 | uint32_t algonum = virtio_crypto_akcipher_algs[i].algonum; | ||
| 573 | |||
| 574 | if (virtio_crypto_akcipher_algs[i].active_devs == 0 || | ||
| 575 | !virtcrypto_algo_is_supported(vcrypto, service, algonum)) | ||
| 576 | continue; | ||
| 577 | |||
| 578 | if (virtio_crypto_akcipher_algs[i].active_devs == 1) | ||
| 579 | crypto_unregister_akcipher(&virtio_crypto_akcipher_algs[i].algo); | ||
| 580 | |||
| 581 | virtio_crypto_akcipher_algs[i].active_devs--; | ||
| 582 | } | ||
| 583 | |||
| 584 | mutex_unlock(&algs_lock); | ||
| 585 | } | ||
| @@ -56,6 +56,7 @@ struct virtio_crypto { · 55 unmodified lines | |||
| 56 | u32 mac_algo_l; | 56 | u32 mac_algo_l; |
| 57 | u32 mac_algo_h; | 57 | u32 mac_algo_h; |
| 58 | u32 aead_algo; | 58 | u32 aead_algo; |
| 59 | u32 akcipher_algo; | ||
| 59 | 60 | ||
| 60 | /* Maximum length of cipher key */ | 61 | /* Maximum length of cipher key */ |
| 61 | u32 max_cipher_key_len; | 62 | u32 max_cipher_key_len; |
| @@ -129,7 +130,9 @@ static inline int virtio_crypto_get_current_node(void) · 67 unmodified lines | |||
| 129 | return node; | 130 | return node; |
| 130 | } | 131 | } |
| 131 | 132 | ||
| 132 | int virtio_crypto_algs_register(struct virtio_crypto *vcrypto); | 133 | int virtio_crypto_skcipher_algs_register(struct virtio_crypto *vcrypto); |
| 133 | void virtio_crypto_algs_unregister(struct virtio_crypto *vcrypto); | 134 | void virtio_crypto_skcipher_algs_unregister(struct virtio_crypto *vcrypto); |
| 135 | int virtio_crypto_akcipher_algs_register(struct virtio_crypto *vcrypto); | ||
| 136 | void virtio_crypto_akcipher_algs_unregister(struct virtio_crypto *vcrypto); | ||
| 134 | 137 | ||
| 135 | #endif /* _VIRTIO_CRYPTO_COMMON_H */ | 138 | #endif /* _VIRTIO_CRYPTO_COMMON_H */ |
| @@ -297,6 +297,7 @@ static int virtcrypto_probe(struct virtio_device *vdev) · 296 unmodified lines | |||
| 297 | u32 mac_algo_l = 0; | 297 | u32 mac_algo_l = 0; |
| 298 | u32 mac_algo_h = 0; | 298 | u32 mac_algo_h = 0; |
| 299 | u32 aead_algo = 0; | 299 | u32 aead_algo = 0; |
| 300 | u32 akcipher_algo = 0; | ||
| 300 | u32 crypto_services = 0; | 301 | u32 crypto_services = 0; |
| 301 | 302 | ||
| 302 | if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) | 303 | if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) |
| @@ -348,6 +349,9 @@ static int virtcrypto_probe(struct virtio_device *vdev) · 45 unmodified lines | |||
| 348 | mac_algo_h, &mac_algo_h); | 349 | mac_algo_h, &mac_algo_h); |
| 349 | virtio_cread_le(vdev, struct virtio_crypto_config, | 350 | virtio_cread_le(vdev, struct virtio_crypto_config, |
| 350 | aead_algo, &aead_algo); | 351 | aead_algo, &aead_algo); |
| 352 | if (crypto_services & (1 << VIRTIO_CRYPTO_SERVICE_AKCIPHER)) | ||
| 353 | virtio_cread_le(vdev, struct virtio_crypto_config, | ||
| 354 | akcipher_algo, &akcipher_algo); | ||
| 351 | 355 | ||
| 352 | /* Add virtio crypto device to global table */ | 356 | /* Add virtio crypto device to global table */ |
| 353 | err = virtcrypto_devmgr_add_dev(vcrypto); | 357 | err = virtcrypto_devmgr_add_dev(vcrypto); |
| @@ -374,7 +378,7 @@ static int virtcrypto_probe(struct virtio_device *vdev) · 20 unmodified lines | |||
| 374 | vcrypto->mac_algo_h = mac_algo_h; | 378 | vcrypto->mac_algo_h = mac_algo_h; |
| 375 | vcrypto->hash_algo = hash_algo; | 379 | vcrypto->hash_algo = hash_algo; |
| 376 | vcrypto->aead_algo = aead_algo; | 380 | vcrypto->aead_algo = aead_algo; |
| 377 | 381 | vcrypto->akcipher_algo = akcipher_algo; | |
| 378 | 382 | ||
| 379 | dev_info(&vdev->dev, | 383 | dev_info(&vdev->dev, |
| 380 | "max_queues: %u, max_cipher_key_len: %u, max_auth_key_len: %u, max_size 0x%llx\n", | 384 | "max_queues: %u, max_cipher_key_len: %u, max_auth_key_len: %u, max_size 0x%llx\n", |
| @@ -237,8 +237,14 @@ struct virtio_crypto *virtcrypto_get_dev_node(int node, uint32_t service, · 236 unmodified lines | |||
| 237 | */ | 237 | */ |
| 238 | int virtcrypto_dev_start(struct virtio_crypto *vcrypto) | 238 | int virtcrypto_dev_start(struct virtio_crypto *vcrypto) |
| 239 | { | 239 | { |
| 240 | if (virtio_crypto_algs_register(vcrypto)) { | 240 | if (virtio_crypto_skcipher_algs_register(vcrypto)) { |
| 241 | pr_err("virtio_crypto: Failed to register crypto algs\n"); | 241 | pr_err("virtio_crypto: Failed to register crypto skcipher algs\n"); |
| 242 | return -EFAULT; | ||
| 243 | } | ||
| 244 | |||
| 245 | if (virtio_crypto_akcipher_algs_register(vcrypto)) { | ||
| 246 | pr_err("virtio_crypto: Failed to register crypto akcipher algs\n"); | ||
| 247 | virtio_crypto_skcipher_algs_unregister(vcrypto); | ||
| 242 | return -EFAULT; | 248 | return -EFAULT; |
| 243 | } | 249 | } |
| 244 | 250 | ||
| @@ -257,7 +263,8 @@ int virtcrypto_dev_start(struct virtio_crypto *vcrypto) · 12 unmodified lines | |||
| 257 | */ | 263 | */ |
| 258 | void virtcrypto_dev_stop(struct virtio_crypto *vcrypto) | 264 | void virtcrypto_dev_stop(struct virtio_crypto *vcrypto) |
| 259 | { | 265 | { |
| 260 | virtio_crypto_algs_unregister(vcrypto); | 266 | virtio_crypto_skcipher_algs_unregister(vcrypto); |
| 267 | virtio_crypto_akcipher_algs_unregister(vcrypto); | ||
| 261 | } | 268 | } |
| 262 | 269 | ||
| 263 | /* | 270 | /* |
| @@ -312,6 +319,10 @@ bool virtcrypto_algo_is_supported(struct virtio_crypto *vcrypto, · 48 unmodified lines | |||
| 312 | case VIRTIO_CRYPTO_SERVICE_AEAD: | 319 | case VIRTIO_CRYPTO_SERVICE_AEAD: |
| 313 | algo_mask = vcrypto->aead_algo; | 320 | algo_mask = vcrypto->aead_algo; |
| 314 | break; | 321 | break; |
| 322 | |||
| 323 | case VIRTIO_CRYPTO_SERVICE_AKCIPHER: | ||
| 324 | algo_mask = vcrypto->akcipher_algo; | ||
| 325 | break; | ||
| 315 | } | 326 | } |
| 316 | 327 | ||
| 317 | if (!(algo_mask & (1u << algo))) | 328 | if (!(algo_mask & (1u << algo))) |
| @@ -613,7 +613,7 @@ static struct virtio_crypto_algo virtio_crypto_algs[] = { { · 612 unmodified lines | |||
| 613 | }, | 613 | }, |
| 614 | } }; | 614 | } }; |
| 615 | 615 | ||
| 616 | int virtio_crypto_algs_register(struct virtio_crypto *vcrypto) | 616 | int virtio_crypto_skcipher_algs_register(struct virtio_crypto *vcrypto) |
| 617 | { | 617 | { |
| 618 | int ret = 0; | 618 | int ret = 0; |
| 619 | int i = 0; | 619 | int i = 0; |
| @@ -644,7 +644,7 @@ unlock: · 24 unmodified lines | |||
| 644 | return ret; | 644 | return ret; |
| 645 | } | 645 | } |
| 646 | 646 | ||
| 647 | void virtio_crypto_algs_unregister(struct virtio_crypto *vcrypto) | 647 | void virtio_crypto_skcipher_algs_unregister(struct virtio_crypto *vcrypto) |
| 648 | { | 648 | { |
| 649 | int i = 0; | 649 | int i = 0; |
| 650 | 650 | ||
| @@ -169,6 +169,24 @@ struct receive_queue { · 168 unmodified lines | |||
| 169 | struct xdp_rxq_info xdp_rxq; | 169 | struct xdp_rxq_info xdp_rxq; |
| 170 | }; | 170 | }; |
| 171 | 171 | ||
| 172 | /* This structure can contain rss message with maximum settings for indirection table and keysize | ||
| 173 | * Note, that default structure that describes RSS configuration virtio_net_rss_config | ||
| 174 | * contains same info but can't handle table values. | ||
| 175 | * In any case, structure would be passed to virtio hw through sg_buf split by parts | ||
| 176 | * because table sizes may be differ according to the device configuration. | ||
| 177 | */ | ||
| 178 | #define VIRTIO_NET_RSS_MAX_KEY_SIZE 40 | ||
| 179 | #define VIRTIO_NET_RSS_MAX_TABLE_LEN 128 | ||
| 180 | struct virtio_net_ctrl_rss { | ||
| 181 | u32 hash_types; | ||
| 182 | u16 indirection_table_mask; | ||
| 183 | u16 unclassified_queue; | ||
| 184 | u16 indirection_table[VIRTIO_NET_RSS_MAX_TABLE_LEN]; | ||
| 185 | u16 max_tx_vq; | ||
| 186 | u8 hash_key_length; | ||
| 187 | u8 key[VIRTIO_NET_RSS_MAX_KEY_SIZE]; | ||
| 188 | }; | ||
| 189 | |||
| 172 | /* Control VQ buffers: protected by the rtnl lock */ | 190 | /* Control VQ buffers: protected by the rtnl lock */ |
| 173 | struct control_buf { | 191 | struct control_buf { |
| 174 | struct virtio_net_ctrl_hdr hdr; | 192 | struct virtio_net_ctrl_hdr hdr; |
| @@ -178,6 +196,7 @@ struct control_buf { · 3 unmodified lines | |||
| 178 | u8 allmulti; | 196 | u8 allmulti; |
| 179 | __virtio16 vid; | 197 | __virtio16 vid; |
| 180 | __virtio64 offloads; | 198 | __virtio64 offloads; |
| 199 | struct virtio_net_ctrl_rss rss; | ||
| 181 | }; | 200 | }; |
| 182 | 201 | ||
| 183 | struct virtnet_info { | 202 | struct virtnet_info { |
| @@ -206,6 +225,14 @@ struct virtnet_info { · 22 unmodified lines | |||
| 206 | /* Host will merge rx buffers for big packets (shake it! shake it!) */ | 225 | /* Host will merge rx buffers for big packets (shake it! shake it!) */ |
| 207 | bool mergeable_rx_bufs; | 226 | bool mergeable_rx_bufs; |
| 208 | 227 | ||
| 228 | /* Host supports rss and/or hash report */ | ||
| 229 | bool has_rss; | ||
| 230 | bool has_rss_hash_report; | ||
| 231 | u8 rss_key_size; | ||
| 232 | u16 rss_indir_table_size; | ||
| 233 | u32 rss_hash_types_supported; | ||
| 234 | u32 rss_hash_types_saved; | ||
| 235 | |||
| 209 | /* Has control virtqueue */ | 236 | /* Has control virtqueue */ |
| 210 | bool has_cvq; | 237 | bool has_cvq; |
| 211 | 238 | ||
| @@ -242,13 +269,13 @@ struct virtnet_info { · 30 unmodified lines | |||
| 242 | }; | 269 | }; |
| 243 | 270 | ||
| 244 | struct padded_vnet_hdr { | 271 | struct padded_vnet_hdr { |
| 245 | struct virtio_net_hdr_mrg_rxbuf hdr; | 272 | struct virtio_net_hdr_v1_hash hdr; |
| 246 | /* | 273 | /* |
| 247 | * hdr is in a separate sg buffer, and data sg buffer shares same page | 274 | * hdr is in a separate sg buffer, and data sg buffer shares same page |
| 248 | * with this header sg. This padding makes next sg 16 byte aligned | 275 | * with this header sg. This padding makes next sg 16 byte aligned |
| 249 | * after the header. | 276 | * after the header. |
| 250 | */ | 277 | */ |
| 251 | char padding[4]; | 278 | char padding[12]; |
| 252 | }; | 279 | }; |
| 253 | 280 | ||
| 254 | static bool is_xdp_frame(void *ptr) | 281 | static bool is_xdp_frame(void *ptr) |
| @@ -396,7 +423,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, · 141 unmodified lines | |||
| 396 | 423 | ||
| 397 | hdr_len = vi->hdr_len; | 424 | hdr_len = vi->hdr_len; |
| 398 | if (vi->mergeable_rx_bufs) | 425 | if (vi->mergeable_rx_bufs) |
| 399 | hdr_padded_len = sizeof(*hdr); | 426 | hdr_padded_len = hdr_len; |
| 400 | else | 427 | else |
| 401 | hdr_padded_len = sizeof(struct padded_vnet_hdr); | 428 | hdr_padded_len = sizeof(struct padded_vnet_hdr); |
| 402 | 429 | ||
| @@ -1123,6 +1150,35 @@ xdp_xmit: · 720 unmodified lines | |||
| 1123 | return NULL; | 1150 | return NULL; |
| 1124 | } | 1151 | } |
| 1125 | 1152 | ||
| 1153 | static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_hash, | ||
| 1154 | struct sk_buff *skb) | ||
| 1155 | { | ||
| 1156 | enum pkt_hash_types rss_hash_type; | ||
| 1157 | |||
| 1158 | if (!hdr_hash || !skb) | ||
| 1159 | return; | ||
| 1160 | |||
| 1161 | switch ((int)hdr_hash->hash_report) { | ||
| 1162 | case VIRTIO_NET_HASH_REPORT_TCPv4: | ||
| 1163 | case VIRTIO_NET_HASH_REPORT_UDPv4: | ||
| 1164 | case VIRTIO_NET_HASH_REPORT_TCPv6: | ||
| 1165 | case VIRTIO_NET_HASH_REPORT_UDPv6: | ||
| 1166 | case VIRTIO_NET_HASH_REPORT_TCPv6_EX: | ||
| 1167 | case VIRTIO_NET_HASH_REPORT_UDPv6_EX: | ||
| 1168 | rss_hash_type = PKT_HASH_TYPE_L4; | ||
| 1169 | break; | ||
| 1170 | case VIRTIO_NET_HASH_REPORT_IPv4: | ||
| 1171 | case VIRTIO_NET_HASH_REPORT_IPv6: | ||
| 1172 | case VIRTIO_NET_HASH_REPORT_IPv6_EX: | ||
| 1173 | rss_hash_type = PKT_HASH_TYPE_L3; | ||
| 1174 | break; | ||
| 1175 | case VIRTIO_NET_HASH_REPORT_NONE: | ||
| 1176 | default: | ||
| 1177 | rss_hash_type = PKT_HASH_TYPE_NONE; | ||
| 1178 | } | ||
| 1179 | skb_set_hash(skb, (unsigned int)hdr_hash->hash_value, rss_hash_type); | ||
| 1180 | } | ||
| 1181 | |||
| 1126 | static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, | 1182 | static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, |
| 1127 | void *buf, unsigned int len, void **ctx, | 1183 | void *buf, unsigned int len, void **ctx, |
| 1128 | unsigned int *xdp_xmit, | 1184 | unsigned int *xdp_xmit, |
| @@ -1157,6 +1213,8 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, · 28 unmodified lines | |||
| 1157 | return; | 1213 | return; |
| 1158 | 1214 | ||
| 1159 | hdr = skb_vnet_hdr(skb); | 1215 | hdr = skb_vnet_hdr(skb); |
| 1216 | if (dev->features & NETIF_F_RXHASH && vi->has_rss_hash_report) | ||
| 1217 | virtio_skb_set_hash((const struct virtio_net_hdr_v1_hash *)hdr, skb); | ||
| 1160 | 1218 | ||
| 1161 | if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) | 1219 | if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) |
| 1162 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1220 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| @@ -1266,7 +1324,8 @@ static unsigned int get_mergeable_buf_len(struct receive_queue *rq, · 103 unmodified lines | |||
| 1266 | struct ewma_pkt_len *avg_pkt_len, | 1324 | struct ewma_pkt_len *avg_pkt_len, |
| 1267 | unsigned int room) | 1325 | unsigned int room) |
| 1268 | { | 1326 | { |
| 1269 | const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); | 1327 | struct virtnet_info *vi = rq->vq->vdev->priv; |
| 1328 | const size_t hdr_len = vi->hdr_len; | ||
| 1270 | unsigned int len; | 1329 | unsigned int len; |
| 1271 | 1330 | ||
| 1272 | if (room) | 1331 | if (room) |
| @@ -2183,6 +2242,174 @@ static void virtnet_get_ringparam(struct net_device *dev, · 910 unmodified lines | |||
| 2183 | ring->tx_pending = ring->tx_max_pending; | 2242 | ring->tx_pending = ring->tx_max_pending; |
| 2184 | } | 2243 | } |
| 2185 | 2244 | ||
| 2245 | static bool virtnet_commit_rss_command(struct virtnet_info *vi) | ||
| 2246 | { | ||
| 2247 | struct net_device *dev = vi->dev; | ||
| 2248 | struct scatterlist sgs[4]; | ||
| 2249 | unsigned int sg_buf_size; | ||
| 2250 | |||
| 2251 | /* prepare sgs */ | ||
| 2252 | sg_init_table(sgs, 4); | ||
| 2253 | |||
| 2254 | sg_buf_size = offsetof(struct virtio_net_ctrl_rss, indirection_table); | ||
| 2255 | sg_set_buf(&sgs[0], &vi->ctrl->rss, sg_buf_size); | ||
| 2256 | |||
| 2257 | sg_buf_size = sizeof(uint16_t) * (vi->ctrl->rss.indirection_table_mask + 1); | ||
| 2258 | sg_set_buf(&sgs[1], vi->ctrl->rss.indirection_table, sg_buf_size); | ||
| 2259 | |||
| 2260 | sg_buf_size = offsetof(struct virtio_net_ctrl_rss, key) | ||
| 2261 | - offsetof(struct virtio_net_ctrl_rss, max_tx_vq); | ||
| 2262 | sg_set_buf(&sgs[2], &vi->ctrl->rss.max_tx_vq, sg_buf_size); | ||
| 2263 | |||
| 2264 | sg_buf_size = vi->rss_key_size; | ||
| 2265 | sg_set_buf(&sgs[3], vi->ctrl->rss.key, sg_buf_size); | ||
| 2266 | |||
| 2267 | if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ, | ||
| 2268 | vi->has_rss ? VIRTIO_NET_CTRL_MQ_RSS_CONFIG | ||
| 2269 | : VIRTIO_NET_CTRL_MQ_HASH_CONFIG, sgs)) { | ||
| 2270 | dev_warn(&dev->dev, "VIRTIONET issue with committing RSS sgs\n"); | ||
| 2271 | return false; | ||
| 2272 | } | ||
| 2273 | return true; | ||
| 2274 | } | ||
| 2275 | |||
| 2276 | static void virtnet_init_default_rss(struct virtnet_info *vi) | ||
| 2277 | { | ||
| 2278 | u32 indir_val = 0; | ||
| 2279 | int i = 0; | ||
| 2280 | |||
| 2281 | vi->ctrl->rss.hash_types = vi->rss_hash_types_supported; | ||
| 2282 | vi->rss_hash_types_saved = vi->rss_hash_types_supported; | ||
| 2283 | vi->ctrl->rss.indirection_table_mask = vi->rss_indir_table_size | ||
| 2284 | ? vi->rss_indir_table_size - 1 : 0; | ||
| 2285 | vi->ctrl->rss.unclassified_queue = 0; | ||
| 2286 | |||
| 2287 | for (; i < vi->rss_indir_table_size; ++i) { | ||
| 2288 | indir_val = ethtool_rxfh_indir_default(i, vi->curr_queue_pairs); | ||
| 2289 | vi->ctrl->rss.indirection_table[i] = indir_val; | ||
| 2290 | } | ||
| 2291 | |||
| 2292 | vi->ctrl->rss.max_tx_vq = vi->curr_queue_pairs; | ||
| 2293 | vi->ctrl->rss.hash_key_length = vi->rss_key_size; | ||
| 2294 | |||
| 2295 | netdev_rss_key_fill(vi->ctrl->rss.key, vi->rss_key_size); | ||
| 2296 | } | ||
| 2297 | |||
| 2298 | static void virtnet_get_hashflow(const struct virtnet_info *vi, struct ethtool_rxnfc *info) | ||
| 2299 | { | ||
| 2300 | info->data = 0; | ||
| 2301 | switch (info->flow_type) { | ||
| 2302 | case TCP_V4_FLOW: | ||
| 2303 | if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_TCPv4) { | ||
| 2304 | info->data = RXH_IP_SRC | RXH_IP_DST | | ||
| 2305 | RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||
| 2306 | } else if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv4) { | ||
| 2307 | info->data = RXH_IP_SRC | RXH_IP_DST; | ||
| 2308 | } | ||
| 2309 | break; | ||
| 2310 | case TCP_V6_FLOW: | ||
| 2311 | if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_TCPv6) { | ||
| 2312 | info->data = RXH_IP_SRC | RXH_IP_DST | | ||
| 2313 | RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||
| 2314 | } else if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv6) { | ||
| 2315 | info->data = RXH_IP_SRC | RXH_IP_DST; | ||
| 2316 | } | ||
| 2317 | break; | ||
| 2318 | case UDP_V4_FLOW: | ||
| 2319 | if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_UDPv4) { | ||
| 2320 | info->data = RXH_IP_SRC | RXH_IP_DST | | ||
| 2321 | RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||
| 2322 | } else if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv4) { | ||
| 2323 | info->data = RXH_IP_SRC | RXH_IP_DST; | ||
| 2324 | } | ||
| 2325 | break; | ||
| 2326 | case UDP_V6_FLOW: | ||
| 2327 | if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_UDPv6) { | ||
| 2328 | info->data = RXH_IP_SRC | RXH_IP_DST | | ||
| 2329 | RXH_L4_B_0_1 | RXH_L4_B_2_3; | ||
| 2330 | } else if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv6) { | ||
| 2331 | info->data = RXH_IP_SRC | RXH_IP_DST; | ||
| 2332 | } | ||
| 2333 | break; | ||
| 2334 | case IPV4_FLOW: | ||
| 2335 | if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv4) | ||
| 2336 | info->data = RXH_IP_SRC | RXH_IP_DST; | ||
| 2337 | |||
| 2338 | break; | ||
| 2339 | case IPV6_FLOW: | ||
| 2340 | if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv6) | ||
| 2341 | info->data = RXH_IP_SRC | RXH_IP_DST; | ||
| 2342 | |||
| 2343 | break; | ||
| 2344 | default: | ||
| 2345 | info->data = 0; | ||
| 2346 | break; | ||
| 2347 | } | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | static bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_rxnfc *info) | ||
| 2351 | { | ||
| 2352 | u32 new_hashtypes = vi->rss_hash_types_saved; | ||
| 2353 | bool is_disable = info->data & RXH_DISCARD; | ||
| 2354 | bool is_l4 = info->data == (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3); | ||
| 2355 | |||
| 2356 | /* supports only 'sd', 'sdfn' and 'r' */ | ||
| 2357 | if (!((info->data == (RXH_IP_SRC | RXH_IP_DST)) | is_l4 | is_disable)) | ||
| 2358 | return false; | ||
| 2359 | |||
| 2360 | switch (info->flow_type) { | ||
| 2361 | case TCP_V4_FLOW: | ||
| 2362 | new_hashtypes &= ~(VIRTIO_NET_RSS_HASH_TYPE_IPv4 | VIRTIO_NET_RSS_HASH_TYPE_TCPv4); | ||
| 2363 | if (!is_disable) | ||
| 2364 | new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_IPv4 | ||
| 2365 | | (is_l4 ? VIRTIO_NET_RSS_HASH_TYPE_TCPv4 : 0); | ||
| 2366 | break; | ||
| 2367 | case UDP_V4_FLOW: | ||
| 2368 | new_hashtypes &= ~(VIRTIO_NET_RSS_HASH_TYPE_IPv4 | VIRTIO_NET_RSS_HASH_TYPE_UDPv4); | ||
| 2369 | if (!is_disable) | ||
| 2370 | new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_IPv4 | ||
| 2371 | | (is_l4 ? VIRTIO_NET_RSS_HASH_TYPE_UDPv4 : 0); | ||
| 2372 | break; | ||
| 2373 | case IPV4_FLOW: | ||
| 2374 | new_hashtypes &= ~VIRTIO_NET_RSS_HASH_TYPE_IPv4; | ||
| 2375 | if (!is_disable) | ||
| 2376 | new_hashtypes = VIRTIO_NET_RSS_HASH_TYPE_IPv4; | ||
| 2377 | break; | ||
| 2378 | case TCP_V6_FLOW: | ||
| 2379 | new_hashtypes &= ~(VIRTIO_NET_RSS_HASH_TYPE_IPv6 | VIRTIO_NET_RSS_HASH_TYPE_TCPv6); | ||
| 2380 | if (!is_disable) | ||
| 2381 | new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_IPv6 | ||
| 2382 | | (is_l4 ? VIRTIO_NET_RSS_HASH_TYPE_TCPv6 : 0); | ||
| 2383 | break; | ||
| 2384 | case UDP_V6_FLOW: | ||
| 2385 | new_hashtypes &= ~(VIRTIO_NET_RSS_HASH_TYPE_IPv6 | VIRTIO_NET_RSS_HASH_TYPE_UDPv6); | ||
| 2386 | if (!is_disable) | ||
| 2387 | new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_IPv6 | ||
| 2388 | | (is_l4 ? VIRTIO_NET_RSS_HASH_TYPE_UDPv6 : 0); | ||
| 2389 | break; | ||
| 2390 | case IPV6_FLOW: | ||
| 2391 | new_hashtypes &= ~VIRTIO_NET_RSS_HASH_TYPE_IPv6; | ||
| 2392 | if (!is_disable) | ||
| 2393 | new_hashtypes = VIRTIO_NET_RSS_HASH_TYPE_IPv6; | ||
| 2394 | break; | ||
| 2395 | default: | ||
| 2396 | /* unsupported flow */ | ||
| 2397 | return false; | ||
| 2398 | } | ||
| 2399 | |||
| 2400 | /* if unsupported hashtype was set */ | ||
| 2401 | if (new_hashtypes != (new_hashtypes & vi->rss_hash_types_supported)) | ||
| 2402 | return false; | ||
| 2403 | |||
| 2404 | if (new_hashtypes != vi->rss_hash_types_saved) { | ||
| 2405 | vi->rss_hash_types_saved = new_hashtypes; | ||
| 2406 | vi->ctrl->rss.hash_types = vi->rss_hash_types_saved; | ||
| 2407 | if (vi->dev->features & NETIF_F_RXHASH) | ||
| 2408 | return virtnet_commit_rss_command(vi); | ||
| 2409 | } | ||
| 2410 | |||
| 2411 | return true; | ||
| 2412 | } | ||
| 2186 | 2413 | ||
| 2187 | static void virtnet_get_drvinfo(struct net_device *dev, | 2414 | static void virtnet_get_drvinfo(struct net_device *dev, |
| 2188 | struct ethtool_drvinfo *info) | 2415 | struct ethtool_drvinfo *info) |
| @@ -2411,6 +2638,92 @@ static void virtnet_update_settings(struct virtnet_info *vi) · 222 unmodified lines | |||
| 2411 | vi->duplex = duplex; | 2638 | vi->duplex = duplex; |
| 2412 | } | 2639 | } |
| 2413 | 2640 | ||
| 2641 | static u32 virtnet_get_rxfh_key_size(struct net_device *dev) | ||
| 2642 | { | ||
| 2643 | return ((struct virtnet_info *)netdev_priv(dev))->rss_key_size; | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | static u32 virtnet_get_rxfh_indir_size(struct net_device *dev) | ||
| 2647 | { | ||
| 2648 | return ((struct virtnet_info *)netdev_priv(dev))->rss_indir_table_size; | ||
| 2649 | } | ||
| 2650 | |||
| 2651 | static int virtnet_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) | ||
| 2652 | { | ||
| 2653 | struct virtnet_info *vi = netdev_priv(dev); | ||
| 2654 | int i; | ||
| 2655 | |||
| 2656 | if (indir) { | ||
| 2657 | for (i = 0; i < vi->rss_indir_table_size; ++i) | ||
| 2658 | indir[i] = vi->ctrl->rss.indirection_table[i]; | ||
| 2659 | } | ||
| 2660 | |||
| 2661 | if (key) | ||
| 2662 | memcpy(key, vi->ctrl->rss.key, vi->rss_key_size); | ||
| 2663 | |||
| 2664 | if (hfunc) | ||
| 2665 | *hfunc = ETH_RSS_HASH_TOP; | ||
| 2666 | |||
| 2667 | return 0; | ||
| 2668 | } | ||
| 2669 | |||
| 2670 | static int virtnet_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key, const u8 hfunc) | ||
| 2671 | { | ||
| 2672 | struct virtnet_info *vi = netdev_priv(dev); | ||
| 2673 | int i; | ||
| 2674 | |||
| 2675 | if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) | ||
| 2676 | return -EOPNOTSUPP; | ||
| 2677 | |||
| 2678 | if (indir) { | ||
| 2679 | for (i = 0; i < vi->rss_indir_table_size; ++i) | ||
| 2680 | vi->ctrl->rss.indirection_table[i] = indir[i]; | ||
| 2681 | } | ||
| 2682 | if (key) | ||
| 2683 | memcpy(vi->ctrl->rss.key, key, vi->rss_key_size); | ||
| 2684 | |||
| 2685 | virtnet_commit_rss_command(vi); | ||
| 2686 | |||
| 2687 | return 0; | ||
| 2688 | } | ||
| 2689 | |||
| 2690 | static int virtnet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, u32 *rule_locs) | ||
| 2691 | { | ||
| 2692 | struct virtnet_info *vi = netdev_priv(dev); | ||
| 2693 | int rc = 0; | ||
| 2694 | |||
| 2695 | switch (info->cmd) { | ||
| 2696 | case ETHTOOL_GRXRINGS: | ||
| 2697 | info->data = vi->curr_queue_pairs; | ||
| 2698 | break; | ||
| 2699 | case ETHTOOL_GRXFH: | ||
| 2700 | virtnet_get_hashflow(vi, info); | ||
| 2701 | break; | ||
| 2702 | default: | ||
| 2703 | rc = -EOPNOTSUPP; | ||
| 2704 | } | ||
| 2705 | |||
| 2706 | return rc; | ||
| 2707 | } | ||
| 2708 | |||
| 2709 | static int virtnet_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) | ||
| 2710 | { | ||
| 2711 | struct virtnet_info *vi = netdev_priv(dev); | ||
| 2712 | int rc = 0; | ||
| 2713 | |||
| 2714 | switch (info->cmd) { | ||
| 2715 | case ETHTOOL_SRXFH: | ||
| 2716 | if (!virtnet_set_hashflow(vi, info)) | ||
| 2717 | rc = -EINVAL; | ||
| 2718 | |||
| 2719 | break; | ||
| 2720 | default: | ||
| 2721 | rc = -EOPNOTSUPP; | ||
| 2722 | } | ||
| 2723 | |||
| 2724 | return rc; | ||
| 2725 | } | ||
| 2726 | |||
| 2414 | static const struct ethtool_ops virtnet_ethtool_ops = { | 2727 | static const struct ethtool_ops virtnet_ethtool_ops = { |
| 2415 | .supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES, | 2728 | .supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES, |
| 2416 | .get_drvinfo = virtnet_get_drvinfo, | 2729 | .get_drvinfo = virtnet_get_drvinfo, |
| @@ -2426,6 +2739,12 @@ static const struct ethtool_ops virtnet_ethtool_ops = { · 9 unmodified lines | |||
| 2426 | .set_link_ksettings = virtnet_set_link_ksettings, | 2739 | .set_link_ksettings = virtnet_set_link_ksettings, |
| 2427 | .set_coalesce = virtnet_set_coalesce, | 2740 | .set_coalesce = virtnet_set_coalesce, |
| 2428 | .get_coalesce = virtnet_get_coalesce, | 2741 | .get_coalesce = virtnet_get_coalesce, |
| 2742 | .get_rxfh_key_size = virtnet_get_rxfh_key_size, | ||
| 2743 | .get_rxfh_indir_size = virtnet_get_rxfh_indir_size, | ||
| 2744 | .get_rxfh = virtnet_get_rxfh, | ||
| 2745 | .set_rxfh = virtnet_set_rxfh, | ||
| 2746 | .get_rxnfc = virtnet_get_rxnfc, | ||
| 2747 | .set_rxnfc = virtnet_set_rxnfc, | ||
| 2429 | }; | 2748 | }; |
| 2430 | 2749 | ||
| 2431 | static void virtnet_freeze_down(struct virtio_device *vdev) | 2750 | static void virtnet_freeze_down(struct virtio_device *vdev) |
| @@ -2678,6 +2997,16 @@ static int virtnet_set_features(struct net_device *dev, · 246 unmodified lines | |||
| 2678 | vi->guest_offloads = offloads; | 2997 | vi->guest_offloads = offloads; |
| 2679 | } | 2998 | } |
| 2680 | 2999 | ||
| 3000 | if ((dev->features ^ features) & NETIF_F_RXHASH) { | ||
| 3001 | if (features & NETIF_F_RXHASH) | ||
| 3002 | vi->ctrl->rss.hash_types = vi->rss_hash_types_saved; | ||
| 3003 | else | ||
| 3004 | vi->ctrl->rss.hash_types = VIRTIO_NET_HASH_REPORT_NONE; | ||
| 3005 | |||
| 3006 | if (!virtnet_commit_rss_command(vi)) | ||
| 3007 | return -EINVAL; | ||
| 3008 | } | ||
| 3009 | |||
| 2681 | return 0; | 3010 | return 0; |
| 2682 | } | 3011 | } |
| 2683 | 3012 | ||
| @@ -2851,7 +3180,7 @@ static void virtnet_del_vqs(struct virtnet_info *vi) · 167 unmodified lines | |||
| 2851 | */ | 3180 | */ |
| 2852 | static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqueue *vq) | 3181 | static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqueue *vq) |
| 2853 | { | 3182 | { |
| 2854 | const unsigned int hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); | 3183 | const unsigned int hdr_len = vi->hdr_len; |
| 2855 | unsigned int rq_size = virtqueue_get_vring_size(vq); | 3184 | unsigned int rq_size = virtqueue_get_vring_size(vq); |
| 2856 | unsigned int packet_len = vi->big_packets ? IP_MAX_MTU : vi->dev->max_mtu; | 3185 | unsigned int packet_len = vi->big_packets ? IP_MAX_MTU : vi->dev->max_mtu; |
| 2857 | unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len; | 3186 | unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len; |
| @@ -3072,6 +3401,10 @@ static bool virtnet_validate_features(struct virtio_device *vdev) · 214 unmodified lines | |||
| 3072 | "VIRTIO_NET_F_CTRL_VQ") || | 3401 | "VIRTIO_NET_F_CTRL_VQ") || |
| 3073 | VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_MQ, "VIRTIO_NET_F_CTRL_VQ") || | 3402 | VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_MQ, "VIRTIO_NET_F_CTRL_VQ") || |
| 3074 | VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR, | 3403 | VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR, |
| 3404 | "VIRTIO_NET_F_CTRL_VQ") || | ||
| 3405 | VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_RSS, | ||
| 3406 | "VIRTIO_NET_F_CTRL_VQ") || | ||
| 3407 | VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_HASH_REPORT, | ||
| 3075 | "VIRTIO_NET_F_CTRL_VQ"))) { | 3408 | "VIRTIO_NET_F_CTRL_VQ"))) { |
| 3076 | return false; | 3409 | return false; |
| 3077 | } | 3410 | } |
| @@ -3112,13 +3445,14 @@ static int virtnet_probe(struct virtio_device *vdev) · 34 unmodified lines | |||
| 3112 | u16 max_queue_pairs; | 3445 | u16 max_queue_pairs; |
| 3113 | int mtu; | 3446 | int mtu; |
| 3114 | 3447 | ||
| 3115 | /* Find if host supports multiqueue virtio_net device */ | 3448 | /* Find if host supports multiqueue/rss virtio_net device */ |
| 3116 | err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ, | 3449 | max_queue_pairs = 1; |
| 3117 | struct virtio_net_config, | 3450 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MQ) || virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) |
| 3118 | max_virtqueue_pairs, &max_queue_pairs); | 3451 | max_queue_pairs = |
| 3452 | virtio_cread16(vdev, offsetof(struct virtio_net_config, max_virtqueue_pairs)); | ||
| 3119 | 3453 | ||
| 3120 | /* We need at least 2 queue's */ | 3454 | /* We need at least 2 queue's */ |
| 3121 | if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || | 3455 | if (max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || |
| 3122 | max_queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX || | 3456 | max_queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX || |
| 3123 | !virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) | 3457 | !virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) |
| 3124 | max_queue_pairs = 1; | 3458 | max_queue_pairs = 1; |
| @@ -3206,8 +3540,33 @@ static int virtnet_probe(struct virtio_device *vdev) · 81 unmodified lines | |||
| 3206 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) | 3540 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) |
| 3207 | vi->mergeable_rx_bufs = true; | 3541 | vi->mergeable_rx_bufs = true; |
| 3208 | 3542 | ||
| 3209 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || | 3543 | if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) |
| 3210 | virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) | 3544 | vi->has_rss_hash_report = true; |
| 3545 | |||
| 3546 | if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) | ||
| 3547 | vi->has_rss = true; | ||
| 3548 | |||
| 3549 | if (vi->has_rss || vi->has_rss_hash_report) { | ||
| 3550 | vi->rss_indir_table_size = | ||
| 3551 | virtio_cread16(vdev, offsetof(struct virtio_net_config, | ||
| 3552 | rss_max_indirection_table_length)); | ||
| 3553 | vi->rss_key_size = | ||
| 3554 | virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size)); | ||
| 3555 | |||
| 3556 | vi->rss_hash_types_supported = | ||
| 3557 | virtio_cread32(vdev, offsetof(struct virtio_net_config, supported_hash_types)); | ||
| 3558 | vi->rss_hash_types_supported &= | ||
| 3559 | ~(VIRTIO_NET_RSS_HASH_TYPE_IP_EX | | ||
| 3560 | VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | | ||
| 3561 | VIRTIO_NET_RSS_HASH_TYPE_UDP_EX); | ||
| 3562 | |||
| 3563 | dev->hw_features |= NETIF_F_RXHASH; | ||
| 3564 | } | ||
| 3565 | |||
| 3566 | if (vi->has_rss_hash_report) | ||
| 3567 | vi->hdr_len = sizeof(struct virtio_net_hdr_v1_hash); | ||
| 3568 | else if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || | ||
| 3569 | virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) | ||
| 3211 | vi->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); | 3570 | vi->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); |
| 3212 | else | 3571 | else |
| 3213 | vi->hdr_len = sizeof(struct virtio_net_hdr); | 3572 | vi->hdr_len = sizeof(struct virtio_net_hdr); |
| @@ -3274,6 +3633,9 @@ static int virtnet_probe(struct virtio_device *vdev) · 60 unmodified lines | |||
| 3274 | } | 3633 | } |
| 3275 | } | 3634 | } |
| 3276 | 3635 | ||
| 3636 | if (vi->has_rss || vi->has_rss_hash_report) | ||
| 3637 | virtnet_init_default_rss(vi); | ||
| 3638 | |||
| 3277 | err = register_netdev(dev); | 3639 | err = register_netdev(dev); |
| 3278 | if (err) { | 3640 | if (err) { |
| 3279 | pr_debug("virtio_net: registering device failed\n"); | 3641 | pr_debug("virtio_net: registering device failed\n"); |
| @@ -3405,7 +3767,8 @@ static struct virtio_device_id id_table[] = { · 125 unmodified lines | |||
| 3405 | VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \ | 3767 | VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \ |
| 3406 | VIRTIO_NET_F_CTRL_MAC_ADDR, \ | 3768 | VIRTIO_NET_F_CTRL_MAC_ADDR, \ |
| 3407 | VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ | 3769 | VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ |
| 3408 | VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY | 3770 | VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY, \ |
| 3771 | VIRTIO_NET_F_RSS, VIRTIO_NET_F_HASH_REPORT | ||
| 3409 | 3772 | ||
| 3410 | static unsigned int features[] = { | 3773 | static unsigned int features[] = { |
| 3411 | VIRTNET_FEATURES, | 3774 | VIRTNET_FEATURES, |
| @@ -10,45 +10,29 @@ · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | #include "ifcvf_base.h" | 11 | #include "ifcvf_base.h" |
| 12 | 12 | ||
| 13 | static inline u8 ifc_ioread8(u8 __iomem *addr) | 13 | struct ifcvf_adapter *vf_to_adapter(struct ifcvf_hw *hw) |
| 14 | { | ||
| 15 | return ioread8(addr); | ||
| 16 | } | ||
| 17 | static inline u16 ifc_ioread16 (__le16 __iomem *addr) | ||
| 18 | { | 14 | { |
| 19 | return ioread16(addr); | 15 | return container_of(hw, struct ifcvf_adapter, vf); |
| 20 | } | 16 | } |
| 21 | 17 | ||
| 22 | static inline u32 ifc_ioread32(__le32 __iomem *addr) | 18 | u16 ifcvf_set_vq_vector(struct ifcvf_hw *hw, u16 qid, int vector) |
| 23 | { | 19 | { |
| 24 | return ioread32(addr); | 20 | struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; |
| 25 | } | ||
| 26 | 21 | ||
| 27 | static inline void ifc_iowrite8(u8 value, u8 __iomem *addr) | 22 | vp_iowrite16(qid, &cfg->queue_select); |
| 28 | { | 23 | vp_iowrite16(vector, &cfg->queue_msix_vector); |
| 29 | iowrite8(value, addr); | ||
| 30 | } | ||
| 31 | 24 | ||
| 32 | static inline void ifc_iowrite16(u16 value, __le16 __iomem *addr) | 25 | return vp_ioread16(&cfg->queue_msix_vector); |
| 33 | { | ||
| 34 | iowrite16(value, addr); | ||
| 35 | } | 26 | } |
| 36 | 27 | ||
| 37 | static inline void ifc_iowrite32(u32 value, __le32 __iomem *addr) | 28 | u16 ifcvf_set_config_vector(struct ifcvf_hw *hw, int vector) |
| 38 | { | 29 | { |
| 39 | iowrite32(value, addr); | 30 | struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; |
| 40 | } | ||
| 41 | 31 | ||
| 42 | static void ifc_iowrite64_twopart(u64 val, | 32 | cfg = hw->common_cfg; |
| 43 | __le32 __iomem *lo, __le32 __iomem *hi) | 33 | vp_iowrite16(vector, &cfg->msix_config); |
| 44 | { | ||
| 45 | ifc_iowrite32((u32)val, lo); | ||
| 46 | ifc_iowrite32(val >> 32, hi); | ||
| 47 | } | ||
| 48 | 34 | ||
| 49 | struct ifcvf_adapter *vf_to_adapter(struct ifcvf_hw *hw) | 35 | return vp_ioread16(&cfg->msix_config); |
| 50 | { | ||
| 51 | return container_of(hw, struct ifcvf_adapter, vf); | ||
| 52 | } | 36 | } |
| 53 | 37 | ||
| 54 | static void __iomem *get_cap_addr(struct ifcvf_hw *hw, | 38 | static void __iomem *get_cap_addr(struct ifcvf_hw *hw, |
| @@ -158,15 +142,16 @@ next: · 103 unmodified lines | |||
| 158 | return -EIO; | 142 | return -EIO; |
| 159 | } | 143 | } |
| 160 | 144 | ||
| 161 | hw->nr_vring = ifc_ioread16(&hw->common_cfg->num_queues); | 145 | hw->nr_vring = vp_ioread16(&hw->common_cfg->num_queues); |
| 162 | 146 | ||
| 163 | for (i = 0; i < hw->nr_vring; i++) { | 147 | for (i = 0; i < hw->nr_vring; i++) { |
| 164 | ifc_iowrite16(i, &hw->common_cfg->queue_select); | 148 | vp_iowrite16(i, &hw->common_cfg->queue_select); |
| 165 | notify_off = ifc_ioread16(&hw->common_cfg->queue_notify_off); | 149 | notify_off = vp_ioread16(&hw->common_cfg->queue_notify_off); |
| 166 | hw->vring[i].notify_addr = hw->notify_base + | 150 | hw->vring[i].notify_addr = hw->notify_base + |
| 167 | notify_off * hw->notify_off_multiplier; | 151 | notify_off * hw->notify_off_multiplier; |
| 168 | hw->vring[i].notify_pa = hw->notify_base_pa + | 152 | hw->vring[i].notify_pa = hw->notify_base_pa + |
| 169 | notify_off * hw->notify_off_multiplier; | 153 | notify_off * hw->notify_off_multiplier; |
| 154 | hw->vring[i].irq = -EINVAL; | ||
| 170 | } | 155 | } |
| 171 | 156 | ||
| 172 | hw->lm_cfg = hw->base[IFCVF_LM_BAR]; | 157 | hw->lm_cfg = hw->base[IFCVF_LM_BAR]; |
| @@ -176,17 +161,20 @@ next: · 3 unmodified lines | |||
| 176 | hw->common_cfg, hw->notify_base, hw->isr, | 161 | hw->common_cfg, hw->notify_base, hw->isr, |
| 177 | hw->dev_cfg, hw->notify_off_multiplier); | 162 | hw->dev_cfg, hw->notify_off_multiplier); |
| 178 | 163 | ||
| 164 | hw->vqs_reused_irq = -EINVAL; | ||
| 165 | hw->config_irq = -EINVAL; | ||
| 166 | |||
| 179 | return 0; | 167 | return 0; |
| 180 | } | 168 | } |
| 181 | 169 | ||
| 182 | u8 ifcvf_get_status(struct ifcvf_hw *hw) | 170 | u8 ifcvf_get_status(struct ifcvf_hw *hw) |
| 183 | { | 171 | { |
| 184 | return ifc_ioread8(&hw->common_cfg->device_status); | 172 | return vp_ioread8(&hw->common_cfg->device_status); |
| 185 | } | 173 | } |
| 186 | 174 | ||
| 187 | void ifcvf_set_status(struct ifcvf_hw *hw, u8 status) | 175 | void ifcvf_set_status(struct ifcvf_hw *hw, u8 status) |
| 188 | { | 176 | { |
| 189 | ifc_iowrite8(status, &hw->common_cfg->device_status); | 177 | vp_iowrite8(status, &hw->common_cfg->device_status); |
| 190 | } | 178 | } |
| 191 | 179 | ||
| 192 | void ifcvf_reset(struct ifcvf_hw *hw) | 180 | void ifcvf_reset(struct ifcvf_hw *hw) |
| @@ -214,11 +202,11 @@ u64 ifcvf_get_hw_features(struct ifcvf_hw *hw) · 21 unmodified lines | |||
| 214 | u32 features_lo, features_hi; | 202 | u32 features_lo, features_hi; |
| 215 | u64 features; | 203 | u64 features; |
| 216 | 204 | ||
| 217 | ifc_iowrite32(0, &cfg->device_feature_select); | 205 | vp_iowrite32(0, &cfg->device_feature_select); |
| 218 | features_lo = ifc_ioread32(&cfg->device_feature); | 206 | features_lo = vp_ioread32(&cfg->device_feature); |
| 219 | 207 | ||
| 220 | ifc_iowrite32(1, &cfg->device_feature_select); | 208 | vp_iowrite32(1, &cfg->device_feature_select); |
| 221 | features_hi = ifc_ioread32(&cfg->device_feature); | 209 | features_hi = vp_ioread32(&cfg->device_feature); |
| 222 | 210 | ||
| 223 | features = ((u64)features_hi << 32) | features_lo; | 211 | features = ((u64)features_hi << 32) | features_lo; |
| 224 | 212 | ||
| @@ -271,12 +259,12 @@ void ifcvf_read_dev_config(struct ifcvf_hw *hw, u64 offset, · 46 unmodified lines | |||
| 271 | 259 | ||
| 272 | WARN_ON(offset + length > hw->config_size); | 260 | WARN_ON(offset + length > hw->config_size); |
| 273 | do { | 261 | do { |
| 274 | old_gen = ifc_ioread8(&hw->common_cfg->config_generation); | 262 | old_gen = vp_ioread8(&hw->common_cfg->config_generation); |
| 275 | p = dst; | 263 | p = dst; |
| 276 | for (i = 0; i < length; i++) | 264 | for (i = 0; i < length; i++) |
| 277 | *p++ = ifc_ioread8(hw->dev_cfg + offset + i); | 265 | *p++ = vp_ioread8(hw->dev_cfg + offset + i); |
| 278 | 266 | ||
| 279 | new_gen = ifc_ioread8(&hw->common_cfg->config_generation); | 267 | new_gen = vp_ioread8(&hw->common_cfg->config_generation); |
| 280 | } while (old_gen != new_gen); | 268 | } while (old_gen != new_gen); |
| 281 | } | 269 | } |
| 282 | 270 | ||
| @@ -289,18 +277,18 @@ void ifcvf_write_dev_config(struct ifcvf_hw *hw, u64 offset, · 6 unmodified lines | |||
| 289 | p = src; | 277 | p = src; |
| 290 | WARN_ON(offset + length > hw->config_size); | 278 | WARN_ON(offset + length > hw->config_size); |
| 291 | for (i = 0; i < length; i++) | 279 | for (i = 0; i < length; i++) |
| 292 | ifc_iowrite8(*p++, hw->dev_cfg + offset + i); | 280 | vp_iowrite8(*p++, hw->dev_cfg + offset + i); |
| 293 | } | 281 | } |
| 294 | 282 | ||
| 295 | static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features) | 283 | static void ifcvf_set_features(struct ifcvf_hw *hw, u64 features) |
| 296 | { | 284 | { |
| 297 | struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; | 285 | struct virtio_pci_common_cfg __iomem *cfg = hw->common_cfg; |
| 298 | 286 | ||
| 299 | ifc_iowrite32(0, &cfg->guest_feature_select); | 287 | vp_iowrite32(0, &cfg->guest_feature_select); |
| 300 | ifc_iowrite32((u32)features, &cfg->guest_feature); | 288 | vp_iowrite32((u32)features, &cfg->guest_feature); |
| 301 | 289 | ||
| 302 | ifc_iowrite32(1, &cfg->guest_feature_select); | 290 | vp_iowrite32(1, &cfg->guest_feature_select); |
| 303 | ifc_iowrite32(features >> 32, &cfg->guest_feature); | 291 | vp_iowrite32(features >> 32, &cfg->guest_feature); |
| 304 | } | 292 | } |
| 305 | 293 | ||
| 306 | static int ifcvf_config_features(struct ifcvf_hw *hw) | 294 | static int ifcvf_config_features(struct ifcvf_hw *hw) |
| @@ -329,7 +317,7 @@ u16 ifcvf_get_vq_state(struct ifcvf_hw *hw, u16 qid) · 22 unmodified lines | |||
| 329 | ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg; | 317 | ifcvf_lm = (struct ifcvf_lm_cfg __iomem *)hw->lm_cfg; |
| 330 | q_pair_id = qid / hw->nr_vring; | 318 | q_pair_id = qid / hw->nr_vring; |
| 331 | avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2]; | 319 | avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2]; |
| 332 | last_avail_idx = ifc_ioread16(avail_idx_addr); | 320 | last_avail_idx = vp_ioread16(avail_idx_addr); |
| 333 | 321 | ||
| 334 | return last_avail_idx; | 322 | return last_avail_idx; |
| 335 | } | 323 | } |
| @@ -344,7 +332,7 @@ int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num) · 8 unmodified lines | |||
| 344 | q_pair_id = qid / hw->nr_vring; | 332 | q_pair_id = qid / hw->nr_vring; |
| 345 | avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2]; | 333 | avail_idx_addr = &ifcvf_lm->vring_lm_cfg[q_pair_id].idx_addr[qid % 2]; |
| 346 | hw->vring[qid].last_avail_idx = num; | 334 | hw->vring[qid].last_avail_idx = num; |
| 347 | ifc_iowrite16(num, avail_idx_addr); | 335 | vp_iowrite16(num, avail_idx_addr); |
| 348 | 336 | ||
| 349 | return 0; | 337 | return 0; |
| 350 | } | 338 | } |
| @@ -352,41 +340,23 @@ int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num) · 1 unmodified line | |||
| 352 | static int ifcvf_hw_enable(struct ifcvf_hw *hw) | 340 | static int ifcvf_hw_enable(struct ifcvf_hw *hw) |
| 353 | { | 341 | { |
| 354 | struct virtio_pci_common_cfg __iomem *cfg; | 342 | struct virtio_pci_common_cfg __iomem *cfg; |
| 355 | struct ifcvf_adapter *ifcvf; | ||
| 356 | u32 i; | 343 | u32 i; |
| 357 | 344 | ||
| 358 | ifcvf = vf_to_adapter(hw); | ||
| 359 | cfg = hw->common_cfg; | 345 | cfg = hw->common_cfg; |
| 360 | ifc_iowrite16(IFCVF_MSI_CONFIG_OFF, &cfg->msix_config); | ||
| 361 | |||
| 362 | if (ifc_ioread16(&cfg->msix_config) == VIRTIO_MSI_NO_VECTOR) { | ||
| 363 | IFCVF_ERR(ifcvf->pdev, "No msix vector for device config\n"); | ||
| 364 | return -EINVAL; | ||
| 365 | } | ||
| 366 | |||
| 367 | for (i = 0; i < hw->nr_vring; i++) { | 346 | for (i = 0; i < hw->nr_vring; i++) { |
| 368 | if (!hw->vring[i].ready) | 347 | if (!hw->vring[i].ready) |
| 369 | break; | 348 | break; |
| 370 | 349 | ||
| 371 | ifc_iowrite16(i, &cfg->queue_select); | 350 | vp_iowrite16(i, &cfg->queue_select); |
| 372 | ifc_iowrite64_twopart(hw->vring[i].desc, &cfg->queue_desc_lo, | 351 | vp_iowrite64_twopart(hw->vring[i].desc, &cfg->queue_desc_lo, |
| 373 | &cfg->queue_desc_hi); | 352 | &cfg->queue_desc_hi); |
| 374 | ifc_iowrite64_twopart(hw->vring[i].avail, &cfg->queue_avail_lo, | 353 | vp_iowrite64_twopart(hw->vring[i].avail, &cfg->queue_avail_lo, |
| 375 | &cfg->queue_avail_hi); | 354 | &cfg->queue_avail_hi); |
| 376 | ifc_iowrite64_twopart(hw->vring[i].used, &cfg->queue_used_lo, | 355 | vp_iowrite64_twopart(hw->vring[i].used, &cfg->queue_used_lo, |
| 377 | &cfg->queue_used_hi); | 356 | &cfg->queue_used_hi); |
| 378 | ifc_iowrite16(hw->vring[i].size, &cfg->queue_size); | 357 | vp_iowrite16(hw->vring[i].size, &cfg->queue_size); |
| 379 | ifc_iowrite16(i + IFCVF_MSI_QUEUE_OFF, &cfg->queue_msix_vector); | ||
| 380 | |||
| 381 | if (ifc_ioread16(&cfg->queue_msix_vector) == | ||
| 382 | VIRTIO_MSI_NO_VECTOR) { | ||
| 383 | IFCVF_ERR(ifcvf->pdev, | ||
| 384 | "No msix vector for queue %u\n", i); | ||
| 385 | return -EINVAL; | ||
| 386 | } | ||
| 387 | |||
| 388 | ifcvf_set_vq_state(hw, i, hw->vring[i].last_avail_idx); | 358 | ifcvf_set_vq_state(hw, i, hw->vring[i].last_avail_idx); |
| 389 | ifc_iowrite16(1, &cfg->queue_enable); | 359 | vp_iowrite16(1, &cfg->queue_enable); |
| 390 | } | 360 | } |
| 391 | 361 | ||
| 392 | return 0; | 362 | return 0; |
| @@ -394,18 +364,12 @@ static int ifcvf_hw_enable(struct ifcvf_hw *hw) · 1 unmodified line | |||
| 394 | 364 | ||
| 395 | static void ifcvf_hw_disable(struct ifcvf_hw *hw) | 365 | static void ifcvf_hw_disable(struct ifcvf_hw *hw) |
| 396 | { | 366 | { |
| 397 | struct virtio_pci_common_cfg __iomem *cfg; | ||
| 398 | u32 i; | 367 | u32 i; |
| 399 | 368 | ||
| 400 | cfg = hw->common_cfg; | 369 | ifcvf_set_config_vector(hw, VIRTIO_MSI_NO_VECTOR); |
| 401 | ifc_iowrite16(VIRTIO_MSI_NO_VECTOR, &cfg->msix_config); | ||
| 402 | |||
| 403 | for (i = 0; i < hw->nr_vring; i++) { | 370 | for (i = 0; i < hw->nr_vring; i++) { |
| 404 | ifc_iowrite16(i, &cfg->queue_select); | 371 | ifcvf_set_vq_vector(hw, i, VIRTIO_MSI_NO_VECTOR); |
| 405 | ifc_iowrite16(VIRTIO_MSI_NO_VECTOR, &cfg->queue_msix_vector); | ||
| 406 | } | 372 | } |
| 407 | |||
| 408 | ifc_ioread16(&cfg->queue_msix_vector); | ||
| 409 | } | 373 | } |
| 410 | 374 | ||
| 411 | int ifcvf_start_hw(struct ifcvf_hw *hw) | 375 | int ifcvf_start_hw(struct ifcvf_hw *hw) |
| @@ -433,5 +397,5 @@ void ifcvf_stop_hw(struct ifcvf_hw *hw) · 21 unmodified lines | |||
| 433 | 397 | ||
| 434 | void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid) | 398 | void ifcvf_notify_queue(struct ifcvf_hw *hw, u16 qid) |
| 435 | { | 399 | { |
| 436 | ifc_iowrite16(qid, hw->vring[qid].notify_addr); | 400 | vp_iowrite16(qid, hw->vring[qid].notify_addr); |
| 437 | } | 401 | } |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
| 15 | #include <linux/pci_regs.h> | 15 | #include <linux/pci_regs.h> |
| 16 | #include <linux/vdpa.h> | 16 | #include <linux/vdpa.h> |
| 17 | #include <linux/virtio_pci_modern.h> | ||
| 17 | #include <uapi/linux/virtio_net.h> | 18 | #include <uapi/linux/virtio_net.h> |
| 18 | #include <uapi/linux/virtio_blk.h> | 19 | #include <uapi/linux/virtio_blk.h> |
| 19 | #include <uapi/linux/virtio_config.h> | 20 | #include <uapi/linux/virtio_config.h> |
| @@ -27,8 +28,6 @@ · 7 unmodified lines | |||
| 27 | 28 | ||
| 28 | #define IFCVF_QUEUE_ALIGNMENT PAGE_SIZE | 29 | #define IFCVF_QUEUE_ALIGNMENT PAGE_SIZE |
| 29 | #define IFCVF_QUEUE_MAX 32768 | 30 | #define IFCVF_QUEUE_MAX 32768 |
| 30 | #define IFCVF_MSI_CONFIG_OFF 0 | ||
| 31 | #define IFCVF_MSI_QUEUE_OFF 1 | ||
| 32 | #define IFCVF_PCI_MAX_RESOURCE 6 | 31 | #define IFCVF_PCI_MAX_RESOURCE 6 |
| 33 | 32 | ||
| 34 | #define IFCVF_LM_CFG_SIZE 0x40 | 33 | #define IFCVF_LM_CFG_SIZE 0x40 |
| @@ -42,6 +41,13 @@ · 7 unmodified lines | |||
| 42 | #define ifcvf_private_to_vf(adapter) \ | 41 | #define ifcvf_private_to_vf(adapter) \ |
| 43 | (&((struct ifcvf_adapter *)adapter)->vf) | 42 | (&((struct ifcvf_adapter *)adapter)->vf) |
| 44 | 43 | ||
| 44 | /* all vqs and config interrupt has its own vector */ | ||
| 45 | #define MSIX_VECTOR_PER_VQ_AND_CONFIG 1 | ||
| 46 | /* all vqs share a vector, and config interrupt has a separate vector */ | ||
| 47 | #define MSIX_VECTOR_SHARED_VQ_AND_CONFIG 2 | ||
| 48 | /* all vqs and config interrupt share a vector */ | ||
| 49 | #define MSIX_VECTOR_DEV_SHARED 3 | ||
| 50 | |||
| 45 | struct vring_info { | 51 | struct vring_info { |
| 46 | u64 desc; | 52 | u64 desc; |
| 47 | u64 avail; | 53 | u64 avail; |
| @@ -60,25 +66,27 @@ struct ifcvf_hw { · 12 unmodified lines | |||
| 60 | u8 __iomem *isr; | 66 | u8 __iomem *isr; |
| 61 | /* Live migration */ | 67 | /* Live migration */ |
| 62 | u8 __iomem *lm_cfg; | 68 | u8 __iomem *lm_cfg; |
| 63 | u16 nr_vring; | ||
| 64 | /* Notification bar number */ | 69 | /* Notification bar number */ |
| 65 | u8 notify_bar; | 70 | u8 notify_bar; |
| 71 | u8 msix_vector_status; | ||
| 72 | /* virtio-net or virtio-blk device config size */ | ||
| 73 | u32 config_size; | ||
| 66 | /* Notificaiton bar address */ | 74 | /* Notificaiton bar address */ |
| 67 | void __iomem *notify_base; | 75 | void __iomem *notify_base; |
| 68 | phys_addr_t notify_base_pa; | 76 | phys_addr_t notify_base_pa; |
| 69 | u32 notify_off_multiplier; | 77 | u32 notify_off_multiplier; |
| 78 | u32 dev_type; | ||
| 70 | u64 req_features; | 79 | u64 req_features; |
| 71 | u64 hw_features; | 80 | u64 hw_features; |
| 72 | u32 dev_type; | ||
| 73 | struct virtio_pci_common_cfg __iomem *common_cfg; | 81 | struct virtio_pci_common_cfg __iomem *common_cfg; |
| 74 | void __iomem *dev_cfg; | 82 | void __iomem *dev_cfg; |
| 75 | struct vring_info vring[IFCVF_MAX_QUEUES]; | 83 | struct vring_info vring[IFCVF_MAX_QUEUES]; |
| 76 | void __iomem * const *base; | 84 | void __iomem * const *base; |
| 77 | char config_msix_name[256]; | 85 | char config_msix_name[256]; |
| 78 | struct vdpa_callback config_cb; | 86 | struct vdpa_callback config_cb; |
| 79 | unsigned int config_irq; | 87 | int config_irq; |
| 80 | /* virtio-net or virtio-blk device config size */ | 88 | int vqs_reused_irq; |
| 81 | u32 config_size; | 89 | u16 nr_vring; |
| 82 | }; | 90 | }; |
| 83 | 91 | ||
| 84 | struct ifcvf_adapter { | 92 | struct ifcvf_adapter { |
| @@ -123,4 +131,6 @@ int ifcvf_set_vq_state(struct ifcvf_hw *hw, u16 qid, u16 num); · 38 unmodified lines | |||
| 123 | struct ifcvf_adapter *vf_to_adapter(struct ifcvf_hw *hw); | 131 | struct ifcvf_adapter *vf_to_adapter(struct ifcvf_hw *hw); |
| 124 | int ifcvf_probed_virtio_net(struct ifcvf_hw *hw); | 132 | int ifcvf_probed_virtio_net(struct ifcvf_hw *hw); |
| 125 | u32 ifcvf_get_config_size(struct ifcvf_hw *hw); | 133 | u32 ifcvf_get_config_size(struct ifcvf_hw *hw); |
| 134 | u16 ifcvf_set_vq_vector(struct ifcvf_hw *hw, u16 qid, int vector); | ||
| 135 | u16 ifcvf_set_config_vector(struct ifcvf_hw *hw, int vector); | ||
| 126 | #endif /* _IFCVF_H_ */ | 136 | #endif /* _IFCVF_H_ */ |
| @@ -27,7 +27,7 @@ static irqreturn_t ifcvf_config_changed(int irq, void *arg) · 26 unmodified lines | |||
| 27 | return IRQ_HANDLED; | 27 | return IRQ_HANDLED; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | static irqreturn_t ifcvf_intr_handler(int irq, void *arg) | 30 | static irqreturn_t ifcvf_vq_intr_handler(int irq, void *arg) |
| 31 | { | 31 | { |
| 32 | struct vring_info *vring = arg; | 32 | struct vring_info *vring = arg; |
| 33 | 33 | ||
| @@ -37,76 +37,324 @@ static irqreturn_t ifcvf_intr_handler(int irq, void *arg) · 3 unmodified lines | |||
| 37 | return IRQ_HANDLED; | 37 | return IRQ_HANDLED; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | static irqreturn_t ifcvf_vqs_reused_intr_handler(int irq, void *arg) | ||
| 41 | { | ||
| 42 | struct ifcvf_hw *vf = arg; | ||
| 43 | struct vring_info *vring; | ||
| 44 | int i; | ||
| 45 | |||
| 46 | for (i = 0; i < vf->nr_vring; i++) { | ||
| 47 | vring = &vf->vring[i]; | ||
| 48 | if (vring->cb.callback) | ||
| 49 | vring->cb.callback(vring->cb.private); | ||
| 50 | } | ||
| 51 | |||
| 52 | return IRQ_HANDLED; | ||
| 53 | } | ||
| 54 | |||
| 55 | static irqreturn_t ifcvf_dev_intr_handler(int irq, void *arg) | ||
| 56 | { | ||
| 57 | struct ifcvf_hw *vf = arg; | ||
| 58 | u8 isr; | ||
| 59 | |||
| 60 | isr = vp_ioread8(vf->isr); | ||
| 61 | if (isr & VIRTIO_PCI_ISR_CONFIG) | ||
| 62 | ifcvf_config_changed(irq, arg); | ||
| 63 | |||
| 64 | return ifcvf_vqs_reused_intr_handler(irq, arg); | ||
| 65 | } | ||
| 66 | |||
| 40 | static void ifcvf_free_irq_vectors(void *data) | 67 | static void ifcvf_free_irq_vectors(void *data) |
| 41 | { | 68 | { |
| 42 | pci_free_irq_vectors(data); | 69 | pci_free_irq_vectors(data); |
| 43 | } | 70 | } |
| 44 | 71 | ||
| 45 | static void ifcvf_free_irq(struct ifcvf_adapter *adapter, int queues) | 72 | static void ifcvf_free_per_vq_irq(struct ifcvf_adapter *adapter) |
| 46 | { | 73 | { |
| 47 | struct pci_dev *pdev = adapter->pdev; | 74 | struct pci_dev *pdev = adapter->pdev; |
| 48 | struct ifcvf_hw *vf = &adapter->vf; | 75 | struct ifcvf_hw *vf = &adapter->vf; |
| 49 | int i; | 76 | int i; |
| 50 | 77 | ||
| 78 | for (i = 0; i < vf->nr_vring; i++) { | ||
| 79 | if (vf->vring[i].irq != -EINVAL) { | ||
| 80 | devm_free_irq(&pdev->dev, vf->vring[i].irq, &vf->vring[i]); | ||
| 81 | vf->vring[i].irq = -EINVAL; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 51 | 85 | ||
| 52 | for (i = 0; i < queues; i++) { | 86 | static void ifcvf_free_vqs_reused_irq(struct ifcvf_adapter *adapter) |
| 53 | devm_free_irq(&pdev->dev, vf->vring[i].irq, &vf->vring[i]); | 87 | { |
| 54 | vf->vring[i].irq = -EINVAL; | 88 | struct pci_dev *pdev = adapter->pdev; |
| 89 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 90 | |||
| 91 | if (vf->vqs_reused_irq != -EINVAL) { | ||
| 92 | devm_free_irq(&pdev->dev, vf->vqs_reused_irq, vf); | ||
| 93 | vf->vqs_reused_irq = -EINVAL; | ||
| 55 | } | 94 | } |
| 56 | 95 | ||
| 57 | devm_free_irq(&pdev->dev, vf->config_irq, vf); | 96 | } |
| 97 | |||
| 98 | static void ifcvf_free_vq_irq(struct ifcvf_adapter *adapter) | ||
| 99 | { | ||
| 100 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 101 | |||
| 102 | if (vf->msix_vector_status == MSIX_VECTOR_PER_VQ_AND_CONFIG) | ||
| 103 | ifcvf_free_per_vq_irq(adapter); | ||
| 104 | else | ||
| 105 | ifcvf_free_vqs_reused_irq(adapter); | ||
| 106 | } | ||
| 107 | |||
| 108 | static void ifcvf_free_config_irq(struct ifcvf_adapter *adapter) | ||
| 109 | { | ||
| 110 | struct pci_dev *pdev = adapter->pdev; | ||
| 111 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 112 | |||
| 113 | if (vf->config_irq == -EINVAL) | ||
| 114 | return; | ||
| 115 | |||
| 116 | /* If the irq is shared by all vqs and the config interrupt, | ||
| 117 | * it is already freed in ifcvf_free_vq_irq, so here only | ||
| 118 | * need to free config irq when msix_vector_status != MSIX_VECTOR_DEV_SHARED | ||
| 119 | */ | ||
| 120 | if (vf->msix_vector_status != MSIX_VECTOR_DEV_SHARED) { | ||
| 121 | devm_free_irq(&pdev->dev, vf->config_irq, vf); | ||
| 122 | vf->config_irq = -EINVAL; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | static void ifcvf_free_irq(struct ifcvf_adapter *adapter) | ||
| 127 | { | ||
| 128 | struct pci_dev *pdev = adapter->pdev; | ||
| 129 | |||
| 130 | ifcvf_free_vq_irq(adapter); | ||
| 131 | ifcvf_free_config_irq(adapter); | ||
| 58 | ifcvf_free_irq_vectors(pdev); | 132 | ifcvf_free_irq_vectors(pdev); |
| 59 | } | 133 | } |
| 60 | 134 | ||
| 61 | static int ifcvf_request_irq(struct ifcvf_adapter *adapter) | 135 | /* ifcvf MSIX vectors allocator, this helper tries to allocate |
| 136 | * vectors for all virtqueues and the config interrupt. | ||
| 137 | * It returns the number of allocated vectors, negative | ||
| 138 | * return value when fails. | ||
| 139 | */ | ||
| 140 | static int ifcvf_alloc_vectors(struct ifcvf_adapter *adapter) | ||
| 62 | { | 141 | { |
| 63 | struct pci_dev *pdev = adapter->pdev; | 142 | struct pci_dev *pdev = adapter->pdev; |
| 64 | struct ifcvf_hw *vf = &adapter->vf; | 143 | struct ifcvf_hw *vf = &adapter->vf; |
| 65 | int vector, i, ret, irq; | 144 | int max_intr, ret; |
| 66 | u16 max_intr; | ||
| 67 | 145 | ||
| 68 | /* all queues and config interrupt */ | 146 | /* all queues and config interrupt */ |
| 69 | max_intr = vf->nr_vring + 1; | 147 | max_intr = vf->nr_vring + 1; |
| 148 | ret = pci_alloc_irq_vectors(pdev, 1, max_intr, PCI_IRQ_MSIX | PCI_IRQ_AFFINITY); | ||
| 70 | 149 | ||
| 71 | ret = pci_alloc_irq_vectors(pdev, max_intr, | ||
| 72 | max_intr, PCI_IRQ_MSIX); | ||
| 73 | if (ret < 0) { | 150 | if (ret < 0) { |
| 74 | IFCVF_ERR(pdev, "Failed to alloc IRQ vectors\n"); | 151 | IFCVF_ERR(pdev, "Failed to alloc IRQ vectors\n"); |
| 75 | return ret; | 152 | return ret; |
| 76 | } | 153 | } |
| 77 | 154 | ||
| 155 | if (ret < max_intr) | ||
| 156 | IFCVF_INFO(pdev, | ||
| 157 | "Requested %u vectors, however only %u allocated, lower performance\n", | ||
| 158 | max_intr, ret); | ||
| 159 | |||
| 160 | return ret; | ||
| 161 | } | ||
| 162 | |||
| 163 | static int ifcvf_request_per_vq_irq(struct ifcvf_adapter *adapter) | ||
| 164 | { | ||
| 165 | struct pci_dev *pdev = adapter->pdev; | ||
| 166 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 167 | int i, vector, ret, irq; | ||
| 168 | |||
| 169 | vf->vqs_reused_irq = -EINVAL; | ||
| 170 | for (i = 0; i < vf->nr_vring; i++) { | ||
| 171 | snprintf(vf->vring[i].msix_name, 256, "ifcvf[%s]-%d\n", pci_name(pdev), i); | ||
| 172 | vector = i; | ||
| 173 | irq = pci_irq_vector(pdev, vector); | ||
| 174 | ret = devm_request_irq(&pdev->dev, irq, | ||
| 175 | ifcvf_vq_intr_handler, 0, | ||
| 176 | vf->vring[i].msix_name, | ||
| 177 | &vf->vring[i]); | ||
| 178 | if (ret) { | ||
| 179 | IFCVF_ERR(pdev, "Failed to request irq for vq %d\n", i); | ||
| 180 | goto err; | ||
| 181 | } | ||
| 182 | |||
| 183 | vf->vring[i].irq = irq; | ||
| 184 | ret = ifcvf_set_vq_vector(vf, i, vector); | ||
| 185 | if (ret == VIRTIO_MSI_NO_VECTOR) { | ||
| 186 | IFCVF_ERR(pdev, "No msix vector for vq %u\n", i); | ||
| 187 | goto err; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | err: | ||
| 193 | ifcvf_free_irq(adapter); | ||
| 194 | |||
| 195 | return -EFAULT; | ||
| 196 | } | ||
| 197 | |||
| 198 | static int ifcvf_request_vqs_reused_irq(struct ifcvf_adapter *adapter) | ||
| 199 | { | ||
| 200 | struct pci_dev *pdev = adapter->pdev; | ||
| 201 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 202 | int i, vector, ret, irq; | ||
| 203 | |||
| 204 | vector = 0; | ||
| 205 | snprintf(vf->vring[0].msix_name, 256, "ifcvf[%s]-vqs-reused-irq\n", pci_name(pdev)); | ||
| 206 | irq = pci_irq_vector(pdev, vector); | ||
| 207 | ret = devm_request_irq(&pdev->dev, irq, | ||
| 208 | ifcvf_vqs_reused_intr_handler, 0, | ||
| 209 | vf->vring[0].msix_name, vf); | ||
| 210 | if (ret) { | ||
| 211 | IFCVF_ERR(pdev, "Failed to request reused irq for the device\n"); | ||
| 212 | goto err; | ||
| 213 | } | ||
| 214 | |||
| 215 | vf->vqs_reused_irq = irq; | ||
| 216 | for (i = 0; i < vf->nr_vring; i++) { | ||
| 217 | vf->vring[i].irq = -EINVAL; | ||
| 218 | ret = ifcvf_set_vq_vector(vf, i, vector); | ||
| 219 | if (ret == VIRTIO_MSI_NO_VECTOR) { | ||
| 220 | IFCVF_ERR(pdev, "No msix vector for vq %u\n", i); | ||
| 221 | goto err; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | return 0; | ||
| 226 | err: | ||
| 227 | ifcvf_free_irq(adapter); | ||
| 228 | |||
| 229 | return -EFAULT; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int ifcvf_request_dev_irq(struct ifcvf_adapter *adapter) | ||
| 233 | { | ||
| 234 | struct pci_dev *pdev = adapter->pdev; | ||
| 235 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 236 | int i, vector, ret, irq; | ||
| 237 | |||
| 238 | vector = 0; | ||
| 239 | snprintf(vf->vring[0].msix_name, 256, "ifcvf[%s]-dev-irq\n", pci_name(pdev)); | ||
| 240 | irq = pci_irq_vector(pdev, vector); | ||
| 241 | ret = devm_request_irq(&pdev->dev, irq, | ||
| 242 | ifcvf_dev_intr_handler, 0, | ||
| 243 | vf->vring[0].msix_name, vf); | ||
| 244 | if (ret) { | ||
| 245 | IFCVF_ERR(pdev, "Failed to request irq for the device\n"); | ||
| 246 | goto err; | ||
| 247 | } | ||
| 248 | |||
| 249 | vf->vqs_reused_irq = irq; | ||
| 250 | for (i = 0; i < vf->nr_vring; i++) { | ||
| 251 | vf->vring[i].irq = -EINVAL; | ||
| 252 | ret = ifcvf_set_vq_vector(vf, i, vector); | ||
| 253 | if (ret == VIRTIO_MSI_NO_VECTOR) { | ||
| 254 | IFCVF_ERR(pdev, "No msix vector for vq %u\n", i); | ||
| 255 | goto err; | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | vf->config_irq = irq; | ||
| 260 | ret = ifcvf_set_config_vector(vf, vector); | ||
| 261 | if (ret == VIRTIO_MSI_NO_VECTOR) { | ||
| 262 | IFCVF_ERR(pdev, "No msix vector for device config\n"); | ||
| 263 | goto err; | ||
| 264 | } | ||
| 265 | |||
| 266 | return 0; | ||
| 267 | err: | ||
| 268 | ifcvf_free_irq(adapter); | ||
| 269 | |||
| 270 | return -EFAULT; | ||
| 271 | |||
| 272 | } | ||
| 273 | |||
| 274 | static int ifcvf_request_vq_irq(struct ifcvf_adapter *adapter) | ||
| 275 | { | ||
| 276 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 277 | int ret; | ||
| 278 | |||
| 279 | if (vf->msix_vector_status == MSIX_VECTOR_PER_VQ_AND_CONFIG) | ||
| 280 | ret = ifcvf_request_per_vq_irq(adapter); | ||
| 281 | else | ||
| 282 | ret = ifcvf_request_vqs_reused_irq(adapter); | ||
| 283 | |||
| 284 | return ret; | ||
| 285 | } | ||
| 286 | |||
| 287 | static int ifcvf_request_config_irq(struct ifcvf_adapter *adapter) | ||
| 288 | { | ||
| 289 | struct pci_dev *pdev = adapter->pdev; | ||
| 290 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 291 | int config_vector, ret; | ||
| 292 | |||
| 293 | if (vf->msix_vector_status == MSIX_VECTOR_DEV_SHARED) | ||
| 294 | return 0; | ||
| 295 | |||
| 296 | if (vf->msix_vector_status == MSIX_VECTOR_PER_VQ_AND_CONFIG) | ||
| 297 | /* vector 0 ~ vf->nr_vring for vqs, num vf->nr_vring vector for config interrupt */ | ||
| 298 | config_vector = vf->nr_vring; | ||
| 299 | |||
| 300 | if (vf->msix_vector_status == MSIX_VECTOR_SHARED_VQ_AND_CONFIG) | ||
| 301 | /* vector 0 for vqs and 1 for config interrupt */ | ||
| 302 | config_vector = 1; | ||
| 303 | |||
| 78 | snprintf(vf->config_msix_name, 256, "ifcvf[%s]-config\n", | 304 | snprintf(vf->config_msix_name, 256, "ifcvf[%s]-config\n", |
| 79 | pci_name(pdev)); | 305 | pci_name(pdev)); |
| 80 | vector = 0; | 306 | vf->config_irq = pci_irq_vector(pdev, config_vector); |
| 81 | vf->config_irq = pci_irq_vector(pdev, vector); | ||
| 82 | ret = devm_request_irq(&pdev->dev, vf->config_irq, | 307 | ret = devm_request_irq(&pdev->dev, vf->config_irq, |
| 83 | ifcvf_config_changed, 0, | 308 | ifcvf_config_changed, 0, |
| 84 | vf->config_msix_name, vf); | 309 | vf->config_msix_name, vf); |
| 85 | if (ret) { | 310 | if (ret) { |
| 86 | IFCVF_ERR(pdev, "Failed to request config irq\n"); | 311 | IFCVF_ERR(pdev, "Failed to request config irq\n"); |
| 87 | return ret; | 312 | goto err; |
| 88 | } | 313 | } |
| 89 | 314 | ||
| 90 | for (i = 0; i < vf->nr_vring; i++) { | 315 | ret = ifcvf_set_config_vector(vf, config_vector); |
| 91 | snprintf(vf->vring[i].msix_name, 256, "ifcvf[%s]-%d\n", | 316 | if (ret == VIRTIO_MSI_NO_VECTOR) { |
| 92 | pci_name(pdev), i); | 317 | IFCVF_ERR(pdev, "No msix vector for device config\n"); |
| 93 | vector = i + IFCVF_MSI_QUEUE_OFF; | 318 | goto err; |
| 94 | irq = pci_irq_vector(pdev, vector); | 319 | } |
| 95 | ret = devm_request_irq(&pdev->dev, irq, | ||
| 96 | ifcvf_intr_handler, 0, | ||
| 97 | vf->vring[i].msix_name, | ||
| 98 | &vf->vring[i]); | ||
| 99 | if (ret) { | ||
| 100 | IFCVF_ERR(pdev, | ||
| 101 | "Failed to request irq for vq %d\n", i); | ||
| 102 | ifcvf_free_irq(adapter, i); | ||
| 103 | 320 | ||
| 104 | return ret; | 321 | return 0; |
| 105 | } | 322 | err: |
| 323 | ifcvf_free_irq(adapter); | ||
| 106 | 324 | ||
| 107 | vf->vring[i].irq = irq; | 325 | return -EFAULT; |
| 326 | } | ||
| 327 | |||
| 328 | static int ifcvf_request_irq(struct ifcvf_adapter *adapter) | ||
| 329 | { | ||
| 330 | struct ifcvf_hw *vf = &adapter->vf; | ||
| 331 | int nvectors, ret, max_intr; | ||
| 332 | |||
| 333 | nvectors = ifcvf_alloc_vectors(adapter); | ||
| 334 | if (nvectors <= 0) | ||
| 335 | return -EFAULT; | ||
| 336 | |||
| 337 | vf->msix_vector_status = MSIX_VECTOR_PER_VQ_AND_CONFIG; | ||
| 338 | max_intr = vf->nr_vring + 1; | ||
| 339 | if (nvectors < max_intr) | ||
| 340 | vf->msix_vector_status = MSIX_VECTOR_SHARED_VQ_AND_CONFIG; | ||
| 341 | |||
| 342 | if (nvectors == 1) { | ||
| 343 | vf->msix_vector_status = MSIX_VECTOR_DEV_SHARED; | ||
| 344 | ret = ifcvf_request_dev_irq(adapter); | ||
| 345 | |||
| 346 | return ret; | ||
| 108 | } | 347 | } |
| 109 | 348 | ||
| 349 | ret = ifcvf_request_vq_irq(adapter); | ||
| 350 | if (ret) | ||
| 351 | return ret; | ||
| 352 | |||
| 353 | ret = ifcvf_request_config_irq(adapter); | ||
| 354 | |||
| 355 | if (ret) | ||
| 356 | return ret; | ||
| 357 | |||
| 110 | return 0; | 358 | return 0; |
| 111 | } | 359 | } |
| 112 | 360 | ||
| @@ -263,7 +511,7 @@ static int ifcvf_vdpa_reset(struct vdpa_device *vdpa_dev) · 150 unmodified lines | |||
| 263 | 511 | ||
| 264 | if (status_old & VIRTIO_CONFIG_S_DRIVER_OK) { | 512 | if (status_old & VIRTIO_CONFIG_S_DRIVER_OK) { |
| 265 | ifcvf_stop_datapath(adapter); | 513 | ifcvf_stop_datapath(adapter); |
| 266 | ifcvf_free_irq(adapter, vf->nr_vring); | 514 | ifcvf_free_irq(adapter); |
| 267 | } | 515 | } |
| 268 | 516 | ||
| 269 | ifcvf_reset_vring(adapter); | 517 | ifcvf_reset_vring(adapter); |
| @@ -348,7 +596,7 @@ static u32 ifcvf_vdpa_get_generation(struct vdpa_device *vdpa_dev) · 78 unmodified lines | |||
| 348 | { | 596 | { |
| 349 | struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); | 597 | struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); |
| 350 | 598 | ||
| 351 | return ioread8(&vf->common_cfg->config_generation); | 599 | return vp_ioread8(&vf->common_cfg->config_generation); |
| 352 | } | 600 | } |
| 353 | 601 | ||
| 354 | static u32 ifcvf_vdpa_get_device_id(struct vdpa_device *vdpa_dev) | 602 | static u32 ifcvf_vdpa_get_device_id(struct vdpa_device *vdpa_dev) |
| @@ -410,7 +658,10 @@ static int ifcvf_vdpa_get_vq_irq(struct vdpa_device *vdpa_dev, · 55 unmodified lines | |||
| 410 | { | 658 | { |
| 411 | struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); | 659 | struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev); |
| 412 | 660 | ||
| 413 | return vf->vring[qid].irq; | 661 | if (vf->vqs_reused_irq < 0) |
| 662 | return vf->vring[qid].irq; | ||
| 663 | else | ||
| 664 | return -EINVAL; | ||
| 414 | } | 665 | } |
| 415 | 666 | ||
| 416 | static struct vdpa_notification_area ifcvf_get_vq_notification(struct vdpa_device *vdpa_dev, | 667 | static struct vdpa_notification_area ifcvf_get_vq_notification(struct vdpa_device *vdpa_dev, |
| @@ -1475,7 +1475,7 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd) · 1474 unmodified lines | |||
| 1475 | virtio_net_ctrl_ack status = VIRTIO_NET_ERR; | 1475 | virtio_net_ctrl_ack status = VIRTIO_NET_ERR; |
| 1476 | struct mlx5_core_dev *pfmdev; | 1476 | struct mlx5_core_dev *pfmdev; |
| 1477 | size_t read; | 1477 | size_t read; |
| 1478 | u8 mac[ETH_ALEN]; | 1478 | u8 mac[ETH_ALEN], mac_back[ETH_ALEN]; |
| 1479 | 1479 | ||
| 1480 | pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev)); | 1480 | pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev)); |
| 1481 | switch (cmd) { | 1481 | switch (cmd) { |
| @@ -1489,6 +1489,9 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd) · 7 unmodified lines | |||
| 1489 | break; | 1489 | break; |
| 1490 | } | 1490 | } |
| 1491 | 1491 | ||
| 1492 | if (is_zero_ether_addr(mac)) | ||
| 1493 | break; | ||
| 1494 | |||
| 1492 | if (!is_zero_ether_addr(ndev->config.mac)) { | 1495 | if (!is_zero_ether_addr(ndev->config.mac)) { |
| 1493 | if (mlx5_mpfs_del_mac(pfmdev, ndev->config.mac)) { | 1496 | if (mlx5_mpfs_del_mac(pfmdev, ndev->config.mac)) { |
| 1494 | mlx5_vdpa_warn(mvdev, "failed to delete old MAC %pM from MPFS table\n", | 1497 | mlx5_vdpa_warn(mvdev, "failed to delete old MAC %pM from MPFS table\n", |
| @@ -1503,7 +1506,47 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd) · 8 unmodified lines | |||
| 1503 | break; | 1506 | break; |
| 1504 | } | 1507 | } |
| 1505 | 1508 | ||
| 1509 | /* backup the original mac address so that if failed to add the forward rules | ||
| 1510 | * we could restore it | ||
| 1511 | */ | ||
| 1512 | memcpy(mac_back, ndev->config.mac, ETH_ALEN); | ||
| 1513 | |||
| 1506 | memcpy(ndev->config.mac, mac, ETH_ALEN); | 1514 | memcpy(ndev->config.mac, mac, ETH_ALEN); |
| 1515 | |||
| 1516 | /* Need recreate the flow table entry, so that the packet could forward back | ||
| 1517 | */ | ||
| 1518 | remove_fwd_to_tir(ndev); | ||
| 1519 | |||
| 1520 | if (add_fwd_to_tir(ndev)) { | ||
| 1521 | mlx5_vdpa_warn(mvdev, "failed to insert forward rules, try to restore\n"); | ||
| 1522 | |||
| 1523 | /* Although it hardly run here, we still need double check */ | ||
| 1524 | if (is_zero_ether_addr(mac_back)) { | ||
| 1525 | mlx5_vdpa_warn(mvdev, "restore mac failed: Original MAC is zero\n"); | ||
| 1526 | break; | ||
| 1527 | } | ||
| 1528 | |||
| 1529 | /* Try to restore original mac address to MFPS table, and try to restore | ||
| 1530 | * the forward rule entry. | ||
| 1531 | */ | ||
| 1532 | if (mlx5_mpfs_del_mac(pfmdev, ndev->config.mac)) { | ||
| 1533 | mlx5_vdpa_warn(mvdev, "restore mac failed: delete MAC %pM from MPFS table failed\n", | ||
| 1534 | ndev->config.mac); | ||
| 1535 | } | ||
| 1536 | |||
| 1537 | if (mlx5_mpfs_add_mac(pfmdev, mac_back)) { | ||
| 1538 | mlx5_vdpa_warn(mvdev, "restore mac failed: insert old MAC %pM into MPFS table failed\n", | ||
| 1539 | mac_back); | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | memcpy(ndev->config.mac, mac_back, ETH_ALEN); | ||
| 1543 | |||
| 1544 | if (add_fwd_to_tir(ndev)) | ||
| 1545 | mlx5_vdpa_warn(mvdev, "restore forward rules failed: insert forward rules failed\n"); | ||
| 1546 | |||
| 1547 | break; | ||
| 1548 | } | ||
| 1549 | |||
| 1507 | status = VIRTIO_NET_OK; | 1550 | status = VIRTIO_NET_OK; |
| 1508 | break; | 1551 | break; |
| 1509 | 1552 | ||
| @@ -1669,7 +1712,7 @@ static void mlx5_vdpa_kick_vq(struct vdpa_device *vdev, u16 idx) · 159 unmodified lines | |||
| 1669 | return; | 1712 | return; |
| 1670 | 1713 | ||
| 1671 | if (unlikely(is_ctrl_vq_idx(mvdev, idx))) { | 1714 | if (unlikely(is_ctrl_vq_idx(mvdev, idx))) { |
| 1672 | if (!mvdev->cvq.ready) | 1715 | if (!mvdev->wq || !mvdev->cvq.ready) |
| 1673 | return; | 1716 | return; |
| 1674 | 1717 | ||
| 1675 | wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC); | 1718 | wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC); |
| @@ -2565,6 +2608,28 @@ static int event_handler(struct notifier_block *nb, unsigned long event, void *p · 889 unmodified lines | |||
| 2565 | return ret; | 2608 | return ret; |
| 2566 | } | 2609 | } |
| 2567 | 2610 | ||
| 2611 | static int config_func_mtu(struct mlx5_core_dev *mdev, u16 mtu) | ||
| 2612 | { | ||
| 2613 | int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in); | ||
| 2614 | void *in; | ||
| 2615 | int err; | ||
| 2616 | |||
| 2617 | in = kvzalloc(inlen, GFP_KERNEL); | ||
| 2618 | if (!in) | ||
| 2619 | return -ENOMEM; | ||
| 2620 | |||
| 2621 | MLX5_SET(modify_nic_vport_context_in, in, field_select.mtu, 1); | ||
| 2622 | MLX5_SET(modify_nic_vport_context_in, in, nic_vport_context.mtu, | ||
| 2623 | mtu + MLX5V_ETH_HARD_MTU); | ||
| 2624 | MLX5_SET(modify_nic_vport_context_in, in, opcode, | ||
| 2625 | MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); | ||
| 2626 | |||
| 2627 | err = mlx5_cmd_exec_in(mdev, modify_nic_vport_context, in); | ||
| 2628 | |||
| 2629 | kvfree(in); | ||
| 2630 | return err; | ||
| 2631 | } | ||
| 2632 | |||
| 2568 | static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, | 2633 | static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, |
| 2569 | const struct vdpa_dev_set_config *add_config) | 2634 | const struct vdpa_dev_set_config *add_config) |
| 2570 | { | 2635 | { |
| @@ -2624,6 +2689,13 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name, · 53 unmodified lines | |||
| 2624 | init_mvqs(ndev); | 2689 | init_mvqs(ndev); |
| 2625 | mutex_init(&ndev->reslock); | 2690 | mutex_init(&ndev->reslock); |
| 2626 | config = &ndev->config; | 2691 | config = &ndev->config; |
| 2692 | |||
| 2693 | if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MTU)) { | ||
| 2694 | err = config_func_mtu(mdev, add_config->net.mtu); | ||
| 2695 | if (err) | ||
| 2696 | goto err_mtu; | ||
| 2697 | } | ||
| 2698 | |||
| 2627 | err = query_mtu(mdev, &mtu); | 2699 | err = query_mtu(mdev, &mtu); |
| 2628 | if (err) | 2700 | if (err) |
| 2629 | goto err_mtu; | 2701 | goto err_mtu; |
| @@ -2707,9 +2779,12 @@ static void mlx5_vdpa_dev_del(struct vdpa_mgmt_dev *v_mdev, struct vdpa_device * · 77 unmodified lines | |||
| 2707 | struct mlx5_vdpa_mgmtdev *mgtdev = container_of(v_mdev, struct mlx5_vdpa_mgmtdev, mgtdev); | 2779 | struct mlx5_vdpa_mgmtdev *mgtdev = container_of(v_mdev, struct mlx5_vdpa_mgmtdev, mgtdev); |
| 2708 | struct mlx5_vdpa_dev *mvdev = to_mvdev(dev); | 2780 | struct mlx5_vdpa_dev *mvdev = to_mvdev(dev); |
| 2709 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); | 2781 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); |
| 2782 | struct workqueue_struct *wq; | ||
| 2710 | 2783 | ||
| 2711 | mlx5_notifier_unregister(mvdev->mdev, &ndev->nb); | 2784 | mlx5_notifier_unregister(mvdev->mdev, &ndev->nb); |
| 2712 | destroy_workqueue(mvdev->wq); | 2785 | wq = mvdev->wq; |
| 2786 | mvdev->wq = NULL; | ||
| 2787 | destroy_workqueue(wq); | ||
| 2713 | _vdpa_unregister_device(dev); | 2788 | _vdpa_unregister_device(dev); |
| 2714 | mgtdev->ndev = NULL; | 2789 | mgtdev->ndev = NULL; |
| 2715 | } | 2790 | } |
| @@ -2741,7 +2816,8 @@ static int mlx5v_probe(struct auxiliary_device *adev, · 25 unmodified lines | |||
| 2741 | mgtdev->mgtdev.device = mdev->device; | 2816 | mgtdev->mgtdev.device = mdev->device; |
| 2742 | mgtdev->mgtdev.id_table = id_table; | 2817 | mgtdev->mgtdev.id_table = id_table; |
| 2743 | mgtdev->mgtdev.config_attr_mask = BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR) | | 2818 | mgtdev->mgtdev.config_attr_mask = BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR) | |
| 2744 | BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP); | 2819 | BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP) | |
| 2820 | BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MTU); | ||
| 2745 | mgtdev->mgtdev.max_supported_vqs = | 2821 | mgtdev->mgtdev.max_supported_vqs = |
| 2746 | MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues) + 1; | 2822 | MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues) + 1; |
| 2747 | mgtdev->mgtdev.supported_features = get_supported_features(mdev); | 2823 | mgtdev->mgtdev.supported_features = get_supported_features(mdev); |
| @@ -232,7 +232,7 @@ static int vdpa_name_match(struct device *dev, const void *data) · 231 unmodified lines | |||
| 232 | return (strcmp(dev_name(&vdev->dev), data) == 0); | 232 | return (strcmp(dev_name(&vdev->dev), data) == 0); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | static int __vdpa_register_device(struct vdpa_device *vdev, int nvqs) | 235 | static int __vdpa_register_device(struct vdpa_device *vdev, u32 nvqs) |
| 236 | { | 236 | { |
| 237 | struct device *dev; | 237 | struct device *dev; |
| 238 | 238 | ||
| @@ -257,7 +257,7 @@ static int __vdpa_register_device(struct vdpa_device *vdev, int nvqs) · 18 unmodified lines | |||
| 257 | * | 257 | * |
| 258 | * Return: Returns an error when fail to add device to vDPA bus | 258 | * Return: Returns an error when fail to add device to vDPA bus |
| 259 | */ | 259 | */ |
| 260 | int _vdpa_register_device(struct vdpa_device *vdev, int nvqs) | 260 | int _vdpa_register_device(struct vdpa_device *vdev, u32 nvqs) |
| 261 | { | 261 | { |
| 262 | if (!vdev->mdev) | 262 | if (!vdev->mdev) |
| 263 | return -EINVAL; | 263 | return -EINVAL; |
| @@ -274,7 +274,7 @@ EXPORT_SYMBOL_GPL(_vdpa_register_device); · 10 unmodified lines | |||
| 274 | * | 274 | * |
| 275 | * Return: Returns an error when fail to add to vDPA bus | 275 | * Return: Returns an error when fail to add to vDPA bus |
| 276 | */ | 276 | */ |
| 277 | int vdpa_register_device(struct vdpa_device *vdev, int nvqs) | 277 | int vdpa_register_device(struct vdpa_device *vdev, u32 nvqs) |
| 278 | { | 278 | { |
| 279 | int err; | 279 | int err; |
| 280 | 280 | ||
| @@ -62,8 +62,12 @@ int vhost_iotlb_add_range_ctx(struct vhost_iotlb *iotlb, · 61 unmodified lines | |||
| 62 | */ | 62 | */ |
| 63 | if (start == 0 && last == ULONG_MAX) { | 63 | if (start == 0 && last == ULONG_MAX) { |
| 64 | u64 mid = last / 2; | 64 | u64 mid = last / 2; |
| 65 | int err = vhost_iotlb_add_range_ctx(iotlb, start, mid, addr, | ||
| 66 | perm, opaque); | ||
| 67 | |||
| 68 | if (err) | ||
| 69 | return err; | ||
| 65 | 70 | ||
| 66 | vhost_iotlb_add_range_ctx(iotlb, start, mid, addr, perm, opaque); | ||
| 67 | addr += mid + 1; | 71 | addr += mid + 1; |
| 68 | start = mid + 1; | 72 | start = mid + 1; |
| 69 | } | 73 | } |
| @@ -42,7 +42,7 @@ struct vhost_vdpa { · 41 unmodified lines | |||
| 42 | struct device dev; | 42 | struct device dev; |
| 43 | struct cdev cdev; | 43 | struct cdev cdev; |
| 44 | atomic_t opened; | 44 | atomic_t opened; |
| 45 | int nvqs; | 45 | u32 nvqs; |
| 46 | int virtio_id; | 46 | int virtio_id; |
| 47 | int minor; | 47 | int minor; |
| 48 | struct eventfd_ctx *config_ctx; | 48 | struct eventfd_ctx *config_ctx; |
| @@ -97,8 +97,11 @@ static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid) · 48 unmodified lines | |||
| 97 | return; | 97 | return; |
| 98 | 98 | ||
| 99 | irq = ops->get_vq_irq(vdpa, qid); | 99 | irq = ops->get_vq_irq(vdpa, qid); |
| 100 | if (irq < 0) | ||
| 101 | return; | ||
| 102 | |||
| 100 | irq_bypass_unregister_producer(&vq->call_ctx.producer); | 103 | irq_bypass_unregister_producer(&vq->call_ctx.producer); |
| 101 | if (!vq->call_ctx.ctx || irq < 0) | 104 | if (!vq->call_ctx.ctx) |
| 102 | return; | 105 | return; |
| 103 | 106 | ||
| 104 | vq->call_ctx.producer.token = vq->call_ctx.ctx; | 107 | vq->call_ctx.producer.token = vq->call_ctx.ctx; |
| @@ -158,7 +161,8 @@ static long vhost_vdpa_set_status(struct vhost_vdpa *v, u8 __user *statusp) · 53 unmodified lines | |||
| 158 | struct vdpa_device *vdpa = v->vdpa; | 161 | struct vdpa_device *vdpa = v->vdpa; |
| 159 | const struct vdpa_config_ops *ops = vdpa->config; | 162 | const struct vdpa_config_ops *ops = vdpa->config; |
| 160 | u8 status, status_old; | 163 | u8 status, status_old; |
| 161 | int ret, nvqs = v->nvqs; | 164 | u32 nvqs = v->nvqs; |
| 165 | int ret; | ||
| 162 | u16 i; | 166 | u16 i; |
| 163 | 167 | ||
| 164 | if (copy_from_user(&status, statusp, sizeof(status))) | 168 | if (copy_from_user(&status, statusp, sizeof(status))) |
| @@ -355,6 +359,30 @@ static long vhost_vdpa_get_iova_range(struct vhost_vdpa *v, u32 __user *argp) · 190 unmodified lines | |||
| 355 | return 0; | 359 | return 0; |
| 356 | } | 360 | } |
| 357 | 361 | ||
| 362 | static long vhost_vdpa_get_config_size(struct vhost_vdpa *v, u32 __user *argp) | ||
| 363 | { | ||
| 364 | struct vdpa_device *vdpa = v->vdpa; | ||
| 365 | const struct vdpa_config_ops *ops = vdpa->config; | ||
| 366 | u32 size; | ||
| 367 | |||
| 368 | size = ops->get_config_size(vdpa); | ||
| 369 | |||
| 370 | if (copy_to_user(argp, &size, sizeof(size))) | ||
| 371 | return -EFAULT; | ||
| 372 | |||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | static long vhost_vdpa_get_vqs_count(struct vhost_vdpa *v, u32 __user *argp) | ||
| 377 | { | ||
| 378 | struct vdpa_device *vdpa = v->vdpa; | ||
| 379 | |||
| 380 | if (copy_to_user(argp, &vdpa->nvqs, sizeof(vdpa->nvqs))) | ||
| 381 | return -EFAULT; | ||
| 382 | |||
| 383 | return 0; | ||
| 384 | } | ||
| 385 | |||
| 358 | static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, | 386 | static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd, |
| 359 | void __user *argp) | 387 | void __user *argp) |
| 360 | { | 388 | { |
| @@ -492,6 +520,12 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, · 131 unmodified lines | |||
| 492 | case VHOST_VDPA_GET_IOVA_RANGE: | 520 | case VHOST_VDPA_GET_IOVA_RANGE: |
| 493 | r = vhost_vdpa_get_iova_range(v, argp); | 521 | r = vhost_vdpa_get_iova_range(v, argp); |
| 494 | break; | 522 | break; |
| 523 | case VHOST_VDPA_GET_CONFIG_SIZE: | ||
| 524 | r = vhost_vdpa_get_config_size(v, argp); | ||
| 525 | break; | ||
| 526 | case VHOST_VDPA_GET_VQS_COUNT: | ||
| 527 | r = vhost_vdpa_get_vqs_count(v, argp); | ||
| 528 | break; | ||
| 495 | default: | 529 | default: |
| 496 | r = vhost_dev_ioctl(&v->vdev, cmd, argp); | 530 | r = vhost_dev_ioctl(&v->vdev, cmd, argp); |
| 497 | if (r == -ENOIOCTLCMD) | 531 | if (r == -ENOIOCTLCMD) |
| @@ -948,7 +982,8 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep) · 450 unmodified lines | |||
| 948 | struct vhost_vdpa *v; | 982 | struct vhost_vdpa *v; |
| 949 | struct vhost_dev *dev; | 983 | struct vhost_dev *dev; |
| 950 | struct vhost_virtqueue **vqs; | 984 | struct vhost_virtqueue **vqs; |
| 951 | int nvqs, i, r, opened; | 985 | int r, opened; |
| 986 | u32 i, nvqs; | ||
| 952 | 987 | ||
| 953 | v = container_of(inode->i_cdev, struct vhost_vdpa, cdev); | 988 | v = container_of(inode->i_cdev, struct vhost_vdpa, cdev); |
| 954 | 989 | ||
| @@ -1001,7 +1036,7 @@ err: · 46 unmodified lines | |||
| 1001 | 1036 | ||
| 1002 | static void vhost_vdpa_clean_irq(struct vhost_vdpa *v) | 1037 | static void vhost_vdpa_clean_irq(struct vhost_vdpa *v) |
| 1003 | { | 1038 | { |
| 1004 | int i; | 1039 | u32 i; |
| 1005 | 1040 | ||
| 1006 | for (i = 0; i < v->nvqs; i++) | 1041 | for (i = 0; i < v->nvqs; i++) |
| 1007 | vhost_vdpa_unsetup_vq_irq(v, i); | 1042 | vhost_vdpa_unsetup_vq_irq(v, i); |
| @@ -2550,8 +2550,9 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) · 2549 unmodified lines | |||
| 2550 | &vq->avail->idx, r); | 2550 | &vq->avail->idx, r); |
| 2551 | return false; | 2551 | return false; |
| 2552 | } | 2552 | } |
| 2553 | vq->avail_idx = vhost16_to_cpu(vq, avail_idx); | ||
| 2553 | 2554 | ||
| 2554 | return vhost16_to_cpu(vq, avail_idx) != vq->avail_idx; | 2555 | return vq->avail_idx != vq->last_avail_idx; |
| 2555 | } | 2556 | } |
| 2556 | EXPORT_SYMBOL_GPL(vhost_enable_notify); | 2557 | EXPORT_SYMBOL_GPL(vhost_enable_notify); |
| 2557 | 2558 | ||
| @@ -105,7 +105,7 @@ config VIRTIO_BALLOON · 104 unmodified lines | |||
| 105 | 105 | ||
| 106 | config VIRTIO_MEM | 106 | config VIRTIO_MEM |
| 107 | tristate "Virtio mem driver" | 107 | tristate "Virtio mem driver" |
| 108 | depends on X86_64 | 108 | depends on X86_64 || ARM64 |
| 109 | depends on VIRTIO | 109 | depends on VIRTIO |
| 110 | depends on MEMORY_HOTPLUG | 110 | depends on MEMORY_HOTPLUG |
| 111 | depends on MEMORY_HOTREMOVE | 111 | depends on MEMORY_HOTREMOVE |
| @@ -115,8 +115,9 @@ config VIRTIO_MEM · 3 unmodified lines | |||
| 115 | This driver provides access to virtio-mem paravirtualized memory | 115 | This driver provides access to virtio-mem paravirtualized memory |
| 116 | devices, allowing to hotplug and hotunplug memory. | 116 | devices, allowing to hotplug and hotunplug memory. |
| 117 | 117 | ||
| 118 | This driver was only tested under x86-64, but should theoretically | 118 | This driver was only tested under x86-64 and arm64, but should |
| 119 | work on all architectures that support memory hotplug and hotremove. | 119 | theoretically work on all architectures that support memory hotplug |
| 120 | and hotremove. | ||
| 120 | 121 | ||
| 121 | If unsure, say M. | 122 | If unsure, say M. |
| 122 | 123 | ||
| @@ -526,8 +526,9 @@ int virtio_device_restore(struct virtio_device *dev) · 525 unmodified lines | |||
| 526 | goto err; | 526 | goto err; |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | /* Finally, tell the device we're all set */ | 529 | /* If restore didn't do it, mark device DRIVER_OK ourselves. */ |
| 530 | virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); | 530 | if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) |
| 531 | virtio_device_ready(dev); | ||
| 531 | 532 | ||
| 532 | virtio_config_enable(dev); | 533 | virtio_config_enable(dev); |
| 533 | 534 | ||
| @@ -24,46 +24,17 @@ MODULE_PARM_DESC(force_legacy, · 23 unmodified lines | |||
| 24 | "Force legacy mode for transitional virtio 1 devices"); | 24 | "Force legacy mode for transitional virtio 1 devices"); |
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| 27 | /* disable irq handlers */ | 27 | /* wait for pending irq handlers */ |
| 28 | void vp_disable_cbs(struct virtio_device *vdev) | 28 | void vp_synchronize_vectors(struct virtio_device *vdev) |
| 29 | { | 29 | { |
| 30 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 30 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
| 31 | int i; | 31 | int i; |
| 32 | 32 | ||
| 33 | if (vp_dev->intx_enabled) { | 33 | if (vp_dev->intx_enabled) |
| 34 | /* | ||
| 35 | * The below synchronize() guarantees that any | ||
| 36 | * interrupt for this line arriving after | ||
| 37 | * synchronize_irq() has completed is guaranteed to see | ||
| 38 | * intx_soft_enabled == false. | ||
| 39 | */ | ||
| 40 | WRITE_ONCE(vp_dev->intx_soft_enabled, false); | ||
| 41 | synchronize_irq(vp_dev->pci_dev->irq); | 34 | synchronize_irq(vp_dev->pci_dev->irq); |
| 42 | } | ||
| 43 | |||
| 44 | for (i = 0; i < vp_dev->msix_vectors; ++i) | ||
| 45 | disable_irq(pci_irq_vector(vp_dev->pci_dev, i)); | ||
| 46 | } | ||
| 47 | |||
| 48 | /* enable irq handlers */ | ||
| 49 | void vp_enable_cbs(struct virtio_device *vdev) | ||
| 50 | { | ||
| 51 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | ||
| 52 | int i; | ||
| 53 | |||
| 54 | if (vp_dev->intx_enabled) { | ||
| 55 | disable_irq(vp_dev->pci_dev->irq); | ||
| 56 | /* | ||
| 57 | * The above disable_irq() provides TSO ordering and | ||
| 58 | * as such promotes the below store to store-release. | ||
| 59 | */ | ||
| 60 | WRITE_ONCE(vp_dev->intx_soft_enabled, true); | ||
| 61 | enable_irq(vp_dev->pci_dev->irq); | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | 35 | ||
| 65 | for (i = 0; i < vp_dev->msix_vectors; ++i) | 36 | for (i = 0; i < vp_dev->msix_vectors; ++i) |
| 66 | enable_irq(pci_irq_vector(vp_dev->pci_dev, i)); | 37 | synchronize_irq(pci_irq_vector(vp_dev->pci_dev, i)); |
| 67 | } | 38 | } |
| 68 | 39 | ||
| 69 | /* the notify function used when creating a virt queue */ | 40 | /* the notify function used when creating a virt queue */ |
| @@ -113,9 +84,6 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) · 43 unmodified lines | |||
| 113 | struct virtio_pci_device *vp_dev = opaque; | 84 | struct virtio_pci_device *vp_dev = opaque; |
| 114 | u8 isr; | 85 | u8 isr; |
| 115 | 86 | ||
| 116 | if (!READ_ONCE(vp_dev->intx_soft_enabled)) | ||
| 117 | return IRQ_NONE; | ||
| 118 | |||
| 119 | /* reading the ISR has the effect of also clearing it so it's very | 87 | /* reading the ISR has the effect of also clearing it so it's very |
| 120 | * important to save off the value. */ | 88 | * important to save off the value. */ |
| 121 | isr = ioread8(vp_dev->isr); | 89 | isr = ioread8(vp_dev->isr); |
| @@ -173,8 +141,7 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, · 51 unmodified lines | |||
| 173 | snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, | 141 | snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, |
| 174 | "%s-config", name); | 142 | "%s-config", name); |
| 175 | err = request_irq(pci_irq_vector(vp_dev->pci_dev, v), | 143 | err = request_irq(pci_irq_vector(vp_dev->pci_dev, v), |
| 176 | vp_config_changed, IRQF_NO_AUTOEN, | 144 | vp_config_changed, 0, vp_dev->msix_names[v], |
| 177 | vp_dev->msix_names[v], | ||
| 178 | vp_dev); | 145 | vp_dev); |
| 179 | if (err) | 146 | if (err) |
| 180 | goto error; | 147 | goto error; |
| @@ -193,8 +160,7 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, · 12 unmodified lines | |||
| 193 | snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, | 160 | snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, |
| 194 | "%s-virtqueues", name); | 161 | "%s-virtqueues", name); |
| 195 | err = request_irq(pci_irq_vector(vp_dev->pci_dev, v), | 162 | err = request_irq(pci_irq_vector(vp_dev->pci_dev, v), |
| 196 | vp_vring_interrupt, IRQF_NO_AUTOEN, | 163 | vp_vring_interrupt, 0, vp_dev->msix_names[v], |
| 197 | vp_dev->msix_names[v], | ||
| 198 | vp_dev); | 164 | vp_dev); |
| 199 | if (err) | 165 | if (err) |
| 200 | goto error; | 166 | goto error; |
| @@ -371,7 +337,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, · 170 unmodified lines | |||
| 371 | "%s-%s", | 337 | "%s-%s", |
| 372 | dev_name(&vp_dev->vdev.dev), names[i]); | 338 | dev_name(&vp_dev->vdev.dev), names[i]); |
| 373 | err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec), | 339 | err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec), |
| 374 | vring_interrupt, IRQF_NO_AUTOEN, | 340 | vring_interrupt, 0, |
| 375 | vp_dev->msix_names[msix_vec], | 341 | vp_dev->msix_names[msix_vec], |
| 376 | vqs[i]); | 342 | vqs[i]); |
| 377 | if (err) | 343 | if (err) |
| @@ -63,7 +63,6 @@ struct virtio_pci_device { · 62 unmodified lines | |||
| 63 | /* MSI-X support */ | 63 | /* MSI-X support */ |
| 64 | int msix_enabled; | 64 | int msix_enabled; |
| 65 | int intx_enabled; | 65 | int intx_enabled; |
| 66 | bool intx_soft_enabled; | ||
| 67 | cpumask_var_t *msix_affinity_masks; | 66 | cpumask_var_t *msix_affinity_masks; |
| 68 | /* Name strings for interrupts. This size should be enough, | 67 | /* Name strings for interrupts. This size should be enough, |
| 69 | * and I'm too lazy to allocate each name separately. */ | 68 | * and I'm too lazy to allocate each name separately. */ |
| @@ -102,10 +101,8 @@ static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) · 32 unmodified lines | |||
| 102 | return container_of(vdev, struct virtio_pci_device, vdev); | 101 | return container_of(vdev, struct virtio_pci_device, vdev); |
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | /* disable irq handlers */ | 104 | /* wait for pending irq handlers */ |
| 106 | void vp_disable_cbs(struct virtio_device *vdev); | 105 | void vp_synchronize_vectors(struct virtio_device *vdev); |
| 107 | /* enable irq handlers */ | ||
| 108 | void vp_enable_cbs(struct virtio_device *vdev); | ||
| 109 | /* the notify function used when creating a virt queue */ | 106 | /* the notify function used when creating a virt queue */ |
| 110 | bool vp_notify(struct virtqueue *vq); | 107 | bool vp_notify(struct virtqueue *vq); |
| 111 | /* the config->del_vqs() implementation */ | 108 | /* the config->del_vqs() implementation */ |
| @@ -98,8 +98,8 @@ static void vp_reset(struct virtio_device *vdev) · 97 unmodified lines | |||
| 98 | /* Flush out the status write, and flush in device writes, | 98 | /* Flush out the status write, and flush in device writes, |
| 99 | * including MSi-X interrupts, if any. */ | 99 | * including MSi-X interrupts, if any. */ |
| 100 | vp_legacy_get_status(&vp_dev->ldev); | 100 | vp_legacy_get_status(&vp_dev->ldev); |
| 101 | /* Disable VQ/configuration callbacks. */ | 101 | /* Flush pending VQ/configuration callbacks. */ |
| 102 | vp_disable_cbs(vdev); | 102 | vp_synchronize_vectors(vdev); |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) | 105 | static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) |
| @@ -185,7 +185,6 @@ static void del_vq(struct virtio_pci_vq_info *info) · 79 unmodified lines | |||
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | static const struct virtio_config_ops virtio_pci_config_ops = { | 187 | static const struct virtio_config_ops virtio_pci_config_ops = { |
| 188 | .enable_cbs = vp_enable_cbs, | ||
| 189 | .get = vp_get, | 188 | .get = vp_get, |
| 190 | .set = vp_set, | 189 | .set = vp_set, |
| 191 | .get_status = vp_get_status, | 190 | .get_status = vp_get_status, |
| @@ -172,8 +172,8 @@ static void vp_reset(struct virtio_device *vdev) · 171 unmodified lines | |||
| 172 | */ | 172 | */ |
| 173 | while (vp_modern_get_status(mdev)) | 173 | while (vp_modern_get_status(mdev)) |
| 174 | msleep(1); | 174 | msleep(1); |
| 175 | /* Disable VQ/configuration callbacks. */ | 175 | /* Flush pending VQ/configuration callbacks. */ |
| 176 | vp_disable_cbs(vdev); | 176 | vp_synchronize_vectors(vdev); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) | 179 | static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) |
| @@ -293,7 +293,7 @@ static int virtio_pci_find_shm_cap(struct pci_dev *dev, u8 required_id, · 113 unmodified lines | |||
| 293 | 293 | ||
| 294 | for (pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); pos > 0; | 294 | for (pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); pos > 0; |
| 295 | pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_VNDR)) { | 295 | pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_VNDR)) { |
| 296 | u8 type, cap_len, id; | 296 | u8 type, cap_len, id, res_bar; |
| 297 | u32 tmp32; | 297 | u32 tmp32; |
| 298 | u64 res_offset, res_length; | 298 | u64 res_offset, res_length; |
| 299 | 299 | ||
| @@ -315,9 +315,14 @@ static int virtio_pci_find_shm_cap(struct pci_dev *dev, u8 required_id, · 15 unmodified lines | |||
| 315 | if (id != required_id) | 315 | if (id != required_id) |
| 316 | continue; | 316 | continue; |
| 317 | 317 | ||
| 318 | /* Type, and ID match, looks good */ | ||
| 319 | pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap, | 318 | pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap, |
| 320 | bar), bar); | 319 | bar), &res_bar); |
| 320 | if (res_bar >= PCI_STD_NUM_BARS) | ||
| 321 | continue; | ||
| 322 | |||
| 323 | /* Type and ID match, and the BAR value isn't reserved. | ||
| 324 | * Looks good. | ||
| 325 | */ | ||
| 321 | 326 | ||
| 322 | /* Read the lower 32bit of length and offset */ | 327 | /* Read the lower 32bit of length and offset */ |
| 323 | pci_read_config_dword(dev, pos + offsetof(struct virtio_pci_cap, | 328 | pci_read_config_dword(dev, pos + offsetof(struct virtio_pci_cap, |
| @@ -337,6 +342,7 @@ static int virtio_pci_find_shm_cap(struct pci_dev *dev, u8 required_id, · 13 unmodified lines | |||
| 337 | length_hi), &tmp32); | 342 | length_hi), &tmp32); |
| 338 | res_length |= ((u64)tmp32) << 32; | 343 | res_length |= ((u64)tmp32) << 32; |
| 339 | 344 | ||
| 345 | *bar = res_bar; | ||
| 340 | *offset = res_offset; | 346 | *offset = res_offset; |
| 341 | *len = res_length; | 347 | *len = res_length; |
| 342 | 348 | ||
| @@ -380,7 +386,6 @@ static bool vp_get_shm_region(struct virtio_device *vdev, · 37 unmodified lines | |||
| 380 | } | 386 | } |
| 381 | 387 | ||
| 382 | static const struct virtio_config_ops virtio_pci_config_nodev_ops = { | 388 | static const struct virtio_config_ops virtio_pci_config_nodev_ops = { |
| 383 | .enable_cbs = vp_enable_cbs, | ||
| 384 | .get = NULL, | 389 | .get = NULL, |
| 385 | .set = NULL, | 390 | .set = NULL, |
| 386 | .generation = vp_generation, | 391 | .generation = vp_generation, |
| @@ -398,7 +403,6 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = { · 11 unmodified lines | |||
| 398 | }; | 403 | }; |
| 399 | 404 | ||
| 400 | static const struct virtio_config_ops virtio_pci_config_ops = { | 405 | static const struct virtio_config_ops virtio_pci_config_ops = { |
| 401 | .enable_cbs = vp_enable_cbs, | ||
| 402 | .get = vp_get, | 406 | .get = vp_get, |
| 403 | .set = vp_set, | 407 | .set = vp_set, |
| 404 | .generation = vp_generation, | 408 | .generation = vp_generation, |
| @@ -35,6 +35,13 @@ vp_modern_map_capability(struct virtio_pci_modern_device *mdev, int off, · 34 unmodified lines | |||
| 35 | pci_read_config_dword(dev, off + offsetof(struct virtio_pci_cap, length), | 35 | pci_read_config_dword(dev, off + offsetof(struct virtio_pci_cap, length), |
| 36 | &length); | 36 | &length); |
| 37 | 37 | ||
| 38 | /* Check if the BAR may have changed since we requested the region. */ | ||
| 39 | if (bar >= PCI_STD_NUM_BARS || !(mdev->modern_bars & (1 << bar))) { | ||
| 40 | dev_err(&dev->dev, | ||
| 41 | "virtio_pci: bar unexpectedly changed to %u\n", bar); | ||
| 42 | return NULL; | ||
| 43 | } | ||
| 44 | |||
| 38 | if (length <= start) { | 45 | if (length <= start) { |
| 39 | dev_err(&dev->dev, | 46 | dev_err(&dev->dev, |
| 40 | "virtio_pci: bad capability len %u (>%u expected)\n", | 47 | "virtio_pci: bad capability len %u (>%u expected)\n", |
| @@ -120,7 +127,7 @@ static inline int virtio_pci_find_capability(struct pci_dev *dev, u8 cfg_type, · 79 unmodified lines | |||
| 120 | &bar); | 127 | &bar); |
| 121 | 128 | ||
| 122 | /* Ignore structures with reserved BAR values */ | 129 | /* Ignore structures with reserved BAR values */ |
| 123 | if (bar > 0x5) | 130 | if (bar >= PCI_STD_NUM_BARS) |
| 124 | continue; | 131 | continue; |
| 125 | 132 | ||
| 126 | if (type == cfg_type) { | 133 | if (type == cfg_type) { |
| @@ -379,19 +379,11 @@ static void vring_unmap_one_split_indirect(const struct vring_virtqueue *vq, · 378 unmodified lines | |||
| 379 | 379 | ||
| 380 | flags = virtio16_to_cpu(vq->vq.vdev, desc->flags); | 380 | flags = virtio16_to_cpu(vq->vq.vdev, desc->flags); |
| 381 | 381 | ||
| 382 | if (flags & VRING_DESC_F_INDIRECT) { | 382 | dma_unmap_page(vring_dma_dev(vq), |
| 383 | dma_unmap_single(vring_dma_dev(vq), | 383 | virtio64_to_cpu(vq->vq.vdev, desc->addr), |
| 384 | virtio64_to_cpu(vq->vq.vdev, desc->addr), | 384 | virtio32_to_cpu(vq->vq.vdev, desc->len), |
| 385 | virtio32_to_cpu(vq->vq.vdev, desc->len), | 385 | (flags & VRING_DESC_F_WRITE) ? |
| 386 | (flags & VRING_DESC_F_WRITE) ? | 386 | DMA_FROM_DEVICE : DMA_TO_DEVICE); |
| 387 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 388 | } else { | ||
| 389 | dma_unmap_page(vring_dma_dev(vq), | ||
| 390 | virtio64_to_cpu(vq->vq.vdev, desc->addr), | ||
| 391 | virtio32_to_cpu(vq->vq.vdev, desc->len), | ||
| 392 | (flags & VRING_DESC_F_WRITE) ? | ||
| 393 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 394 | } | ||
| 395 | } | 387 | } |
| 396 | 388 | ||
| 397 | static unsigned int vring_unmap_one_split(const struct vring_virtqueue *vq, | 389 | static unsigned int vring_unmap_one_split(const struct vring_virtqueue *vq, |
| @@ -984,24 +976,24 @@ static struct virtqueue *vring_create_virtqueue_split( · 586 unmodified lines | |||
| 984 | * Packed ring specific functions - *_packed(). | 976 | * Packed ring specific functions - *_packed(). |
| 985 | */ | 977 | */ |
| 986 | 978 | ||
| 987 | static void vring_unmap_state_packed(const struct vring_virtqueue *vq, | 979 | static void vring_unmap_extra_packed(const struct vring_virtqueue *vq, |
| 988 | struct vring_desc_extra *state) | 980 | struct vring_desc_extra *extra) |
| 989 | { | 981 | { |
| 990 | u16 flags; | 982 | u16 flags; |
| 991 | 983 | ||
| 992 | if (!vq->use_dma_api) | 984 | if (!vq->use_dma_api) |
| 993 | return; | 985 | return; |
| 994 | 986 | ||
| 995 | flags = state->flags; | 987 | flags = extra->flags; |
| 996 | 988 | ||
| 997 | if (flags & VRING_DESC_F_INDIRECT) { | 989 | if (flags & VRING_DESC_F_INDIRECT) { |
| 998 | dma_unmap_single(vring_dma_dev(vq), | 990 | dma_unmap_single(vring_dma_dev(vq), |
| 999 | state->addr, state->len, | 991 | extra->addr, extra->len, |
| 1000 | (flags & VRING_DESC_F_WRITE) ? | 992 | (flags & VRING_DESC_F_WRITE) ? |
| 1001 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | 993 | DMA_FROM_DEVICE : DMA_TO_DEVICE); |
| 1002 | } else { | 994 | } else { |
| 1003 | dma_unmap_page(vring_dma_dev(vq), | 995 | dma_unmap_page(vring_dma_dev(vq), |
| 1004 | state->addr, state->len, | 996 | extra->addr, extra->len, |
| 1005 | (flags & VRING_DESC_F_WRITE) ? | 997 | (flags & VRING_DESC_F_WRITE) ? |
| 1006 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | 998 | DMA_FROM_DEVICE : DMA_TO_DEVICE); |
| 1007 | } | 999 | } |
| @@ -1017,19 +1009,11 @@ static void vring_unmap_desc_packed(const struct vring_virtqueue *vq, · 9 unmodified lines | |||
| 1017 | 1009 | ||
| 1018 | flags = le16_to_cpu(desc->flags); | 1010 | flags = le16_to_cpu(desc->flags); |
| 1019 | 1011 | ||
| 1020 | if (flags & VRING_DESC_F_INDIRECT) { | 1012 | dma_unmap_page(vring_dma_dev(vq), |
| 1021 | dma_unmap_single(vring_dma_dev(vq), | 1013 | le64_to_cpu(desc->addr), |
| 1022 | le64_to_cpu(desc->addr), | 1014 | le32_to_cpu(desc->len), |
| 1023 | le32_to_cpu(desc->len), | 1015 | (flags & VRING_DESC_F_WRITE) ? |
| 1024 | (flags & VRING_DESC_F_WRITE) ? | 1016 | DMA_FROM_DEVICE : DMA_TO_DEVICE); |
| 1025 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 1026 | } else { | ||
| 1027 | dma_unmap_page(vring_dma_dev(vq), | ||
| 1028 | le64_to_cpu(desc->addr), | ||
| 1029 | le32_to_cpu(desc->len), | ||
| 1030 | (flags & VRING_DESC_F_WRITE) ? | ||
| 1031 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
| 1032 | } | ||
| 1033 | } | 1017 | } |
| 1034 | 1018 | ||
| 1035 | static struct vring_packed_desc *alloc_indirect_packed(unsigned int total_sg, | 1019 | static struct vring_packed_desc *alloc_indirect_packed(unsigned int total_sg, |
| @@ -1303,8 +1287,7 @@ unmap_release: · 267 unmodified lines | |||
| 1303 | for (n = 0; n < total_sg; n++) { | 1287 | for (n = 0; n < total_sg; n++) { |
| 1304 | if (i == err_idx) | 1288 | if (i == err_idx) |
| 1305 | break; | 1289 | break; |
| 1306 | vring_unmap_state_packed(vq, | 1290 | vring_unmap_extra_packed(vq, &vq->packed.desc_extra[curr]); |
| 1307 | &vq->packed.desc_extra[curr]); | ||
| 1308 | curr = vq->packed.desc_extra[curr].next; | 1291 | curr = vq->packed.desc_extra[curr].next; |
| 1309 | i++; | 1292 | i++; |
| 1310 | if (i >= vq->packed.vring.num) | 1293 | if (i >= vq->packed.vring.num) |
| @@ -1383,8 +1366,8 @@ static void detach_buf_packed(struct vring_virtqueue *vq, · 72 unmodified lines | |||
| 1383 | if (unlikely(vq->use_dma_api)) { | 1366 | if (unlikely(vq->use_dma_api)) { |
| 1384 | curr = id; | 1367 | curr = id; |
| 1385 | for (i = 0; i < state->num; i++) { | 1368 | for (i = 0; i < state->num; i++) { |
| 1386 | vring_unmap_state_packed(vq, | 1369 | vring_unmap_extra_packed(vq, |
| 1387 | &vq->packed.desc_extra[curr]); | 1370 | &vq->packed.desc_extra[curr]); |
| 1388 | curr = vq->packed.desc_extra[curr].next; | 1371 | curr = vq->packed.desc_extra[curr].next; |
| 1389 | } | 1372 | } |
| 1390 | } | 1373 | } |
| @@ -80,12 +80,6 @@ static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) · 79 unmodified lines | |||
| 80 | 80 | ||
| 81 | #ifdef CONFIG_BALLOON_COMPACTION | 81 | #ifdef CONFIG_BALLOON_COMPACTION |
| 82 | extern const struct address_space_operations balloon_aops; | 82 | extern const struct address_space_operations balloon_aops; |
| 83 | extern bool balloon_page_isolate(struct page *page, | ||
| 84 | isolate_mode_t mode); | ||
| 85 | extern void balloon_page_putback(struct page *page); | ||
| 86 | extern int balloon_page_migrate(struct address_space *mapping, | ||
| 87 | struct page *newpage, | ||
| 88 | struct page *page, enum migrate_mode mode); | ||
| 89 | 83 | ||
| 90 | /* | 84 | /* |
| 91 | * balloon_page_insert - insert a page into the balloon's page list and make | 85 | * balloon_page_insert - insert a page into the balloon's page list and make |
| @@ -155,22 +149,6 @@ static inline void balloon_page_delete(struct page *page) · 63 unmodified lines | |||
| 155 | list_del(&page->lru); | 149 | list_del(&page->lru); |
| 156 | } | 150 | } |
| 157 | 151 | ||
| 158 | static inline bool balloon_page_isolate(struct page *page) | ||
| 159 | { | ||
| 160 | return false; | ||
| 161 | } | ||
| 162 | |||
| 163 | static inline void balloon_page_putback(struct page *page) | ||
| 164 | { | ||
| 165 | return; | ||
| 166 | } | ||
| 167 | |||
| 168 | static inline int balloon_page_migrate(struct page *newpage, | ||
| 169 | struct page *page, enum migrate_mode mode) | ||
| 170 | { | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static inline gfp_t balloon_mapping_gfp_mask(void) | 152 | static inline gfp_t balloon_mapping_gfp_mask(void) |
| 175 | { | 153 | { |
| 176 | return GFP_HIGHUSER; | 154 | return GFP_HIGHUSER; |
| @@ -83,7 +83,7 @@ struct vdpa_device { · 82 unmodified lines | |||
| 83 | unsigned int index; | 83 | unsigned int index; |
| 84 | bool features_valid; | 84 | bool features_valid; |
| 85 | bool use_va; | 85 | bool use_va; |
| 86 | int nvqs; | 86 | u32 nvqs; |
| 87 | struct vdpa_mgmt_dev *mdev; | 87 | struct vdpa_mgmt_dev *mdev; |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| @@ -207,7 +207,8 @@ struct vdpa_map_file { · 117 unmodified lines | |||
| 207 | * @reset: Reset device | 207 | * @reset: Reset device |
| 208 | * @vdev: vdpa device | 208 | * @vdev: vdpa device |
| 209 | * Returns integer: success (0) or error (< 0) | 209 | * Returns integer: success (0) or error (< 0) |
| 210 | * @get_config_size: Get the size of the configuration space | 210 | * @get_config_size: Get the size of the configuration space includes |
| 211 | * fields that are conditional on feature bits. | ||
| 211 | * @vdev: vdpa device | 212 | * @vdev: vdpa device |
| 212 | * Returns size_t: configuration size | 213 | * Returns size_t: configuration size |
| 213 | * @get_config: Read from device specific configuration space | 214 | * @get_config: Read from device specific configuration space |
| @@ -337,10 +338,10 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent, · 123 unmodified lines | |||
| 337 | dev_struct, member)), name, use_va), \ | 338 | dev_struct, member)), name, use_va), \ |
| 338 | dev_struct, member) | 339 | dev_struct, member) |
| 339 | 340 | ||
| 340 | int vdpa_register_device(struct vdpa_device *vdev, int nvqs); | 341 | int vdpa_register_device(struct vdpa_device *vdev, u32 nvqs); |
| 341 | void vdpa_unregister_device(struct vdpa_device *vdev); | 342 | void vdpa_unregister_device(struct vdpa_device *vdev); |
| 342 | 343 | ||
| 343 | int _vdpa_register_device(struct vdpa_device *vdev, int nvqs); | 344 | int _vdpa_register_device(struct vdpa_device *vdev, u32 nvqs); |
| 344 | void _vdpa_unregister_device(struct vdpa_device *vdev); | 345 | void _vdpa_unregister_device(struct vdpa_device *vdev); |
| 345 | 346 | ||
| 346 | /** | 347 | /** |
| @@ -150,4 +150,11 @@ · 149 unmodified lines | |||
| 150 | /* Get the valid iova range */ | 150 | /* Get the valid iova range */ |
| 151 | #define VHOST_VDPA_GET_IOVA_RANGE _IOR(VHOST_VIRTIO, 0x78, \ | 151 | #define VHOST_VDPA_GET_IOVA_RANGE _IOR(VHOST_VIRTIO, 0x78, \ |
| 152 | struct vhost_vdpa_iova_range) | 152 | struct vhost_vdpa_iova_range) |
| 153 | |||
| 154 | /* Get the config size */ | ||
| 155 | #define VHOST_VDPA_GET_CONFIG_SIZE _IOR(VHOST_VIRTIO, 0x79, __u32) | ||
| 156 | |||
| 157 | /* Get the count of all virtqueues */ | ||
| 158 | #define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32) | ||
| 159 | |||
| 153 | #endif | 160 | #endif |
| @@ -82,6 +82,12 @@ · 81 unmodified lines | |||
| 82 | /* This feature indicates support for the packed virtqueue layout. */ | 82 | /* This feature indicates support for the packed virtqueue layout. */ |
| 83 | #define VIRTIO_F_RING_PACKED 34 | 83 | #define VIRTIO_F_RING_PACKED 34 |
| 84 | 84 | ||
| 85 | /* | ||
| 86 | * Inorder feature indicates that all buffers are used by the device | ||
| 87 | * in the same order in which they have been made available. | ||
| 88 | */ | ||
| 89 | #define VIRTIO_F_IN_ORDER 35 | ||
| 90 | |||
| 85 | /* | 91 | /* |
| 86 | * This feature indicates that memory accesses by the driver and the | 92 | * This feature indicates that memory accesses by the driver and the |
| 87 | * device are ordered in a way described by the platform. | 93 | * device are ordered in a way described by the platform. |
| @@ -37,6 +37,7 @@ · 36 unmodified lines | |||
| 37 | #define VIRTIO_CRYPTO_SERVICE_HASH 1 | 37 | #define VIRTIO_CRYPTO_SERVICE_HASH 1 |
| 38 | #define VIRTIO_CRYPTO_SERVICE_MAC 2 | 38 | #define VIRTIO_CRYPTO_SERVICE_MAC 2 |
| 39 | #define VIRTIO_CRYPTO_SERVICE_AEAD 3 | 39 | #define VIRTIO_CRYPTO_SERVICE_AEAD 3 |
| 40 | #define VIRTIO_CRYPTO_SERVICE_AKCIPHER 4 | ||
| 40 | 41 | ||
| 41 | #define VIRTIO_CRYPTO_OPCODE(service, op) (((service) << 8) | (op)) | 42 | #define VIRTIO_CRYPTO_OPCODE(service, op) (((service) << 8) | (op)) |
| 42 | 43 | ||
| @@ -57,6 +58,10 @@ struct virtio_crypto_ctrl_header { · 14 unmodified lines | |||
| 57 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x02) | 58 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x02) |
| 58 | #define VIRTIO_CRYPTO_AEAD_DESTROY_SESSION \ | 59 | #define VIRTIO_CRYPTO_AEAD_DESTROY_SESSION \ |
| 59 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x03) | 60 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x03) |
| 61 | #define VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION \ | ||
| 62 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x04) | ||
| 63 | #define VIRTIO_CRYPTO_AKCIPHER_DESTROY_SESSION \ | ||
| 64 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x05) | ||
| 60 | __le32 opcode; | 65 | __le32 opcode; |
| 61 | __le32 algo; | 66 | __le32 algo; |
| 62 | __le32 flag; | 67 | __le32 flag; |
| @@ -180,6 +185,58 @@ struct virtio_crypto_aead_create_session_req { · 117 unmodified lines | |||
| 180 | __u8 padding[32]; | 185 | __u8 padding[32]; |
| 181 | }; | 186 | }; |
| 182 | 187 | ||
| 188 | struct virtio_crypto_rsa_session_para { | ||
| 189 | #define VIRTIO_CRYPTO_RSA_RAW_PADDING 0 | ||
| 190 | #define VIRTIO_CRYPTO_RSA_PKCS1_PADDING 1 | ||
| 191 | __le32 padding_algo; | ||
| 192 | |||
| 193 | #define VIRTIO_CRYPTO_RSA_NO_HASH 0 | ||
| 194 | #define VIRTIO_CRYPTO_RSA_MD2 1 | ||
| 195 | #define VIRTIO_CRYPTO_RSA_MD3 2 | ||
| 196 | #define VIRTIO_CRYPTO_RSA_MD4 3 | ||
| 197 | #define VIRTIO_CRYPTO_RSA_MD5 4 | ||
| 198 | #define VIRTIO_CRYPTO_RSA_SHA1 5 | ||
| 199 | #define VIRTIO_CRYPTO_RSA_SHA256 6 | ||
| 200 | #define VIRTIO_CRYPTO_RSA_SHA384 7 | ||
| 201 | #define VIRTIO_CRYPTO_RSA_SHA512 8 | ||
| 202 | #define VIRTIO_CRYPTO_RSA_SHA224 9 | ||
| 203 | __le32 hash_algo; | ||
| 204 | }; | ||
| 205 | |||
| 206 | struct virtio_crypto_ecdsa_session_para { | ||
| 207 | #define VIRTIO_CRYPTO_CURVE_UNKNOWN 0 | ||
| 208 | #define VIRTIO_CRYPTO_CURVE_NIST_P192 1 | ||
| 209 | #define VIRTIO_CRYPTO_CURVE_NIST_P224 2 | ||
| 210 | #define VIRTIO_CRYPTO_CURVE_NIST_P256 3 | ||
| 211 | #define VIRTIO_CRYPTO_CURVE_NIST_P384 4 | ||
| 212 | #define VIRTIO_CRYPTO_CURVE_NIST_P521 5 | ||
| 213 | __le32 curve_id; | ||
| 214 | __le32 padding; | ||
| 215 | }; | ||
| 216 | |||
| 217 | struct virtio_crypto_akcipher_session_para { | ||
| 218 | #define VIRTIO_CRYPTO_NO_AKCIPHER 0 | ||
| 219 | #define VIRTIO_CRYPTO_AKCIPHER_RSA 1 | ||
| 220 | #define VIRTIO_CRYPTO_AKCIPHER_DSA 2 | ||
| 221 | #define VIRTIO_CRYPTO_AKCIPHER_ECDSA 3 | ||
| 222 | __le32 algo; | ||
| 223 | |||
| 224 | #define VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC 1 | ||
| 225 | #define VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE 2 | ||
| 226 | __le32 keytype; | ||
| 227 | __le32 keylen; | ||
| 228 | |||
| 229 | union { | ||
| 230 | struct virtio_crypto_rsa_session_para rsa; | ||
| 231 | struct virtio_crypto_ecdsa_session_para ecdsa; | ||
| 232 | } u; | ||
| 233 | }; | ||
| 234 | |||
| 235 | struct virtio_crypto_akcipher_create_session_req { | ||
| 236 | struct virtio_crypto_akcipher_session_para para; | ||
| 237 | __u8 padding[36]; | ||
| 238 | }; | ||
| 239 | |||
| 183 | struct virtio_crypto_alg_chain_session_para { | 240 | struct virtio_crypto_alg_chain_session_para { |
| 184 | #define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER 1 | 241 | #define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER 1 |
| 185 | #define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH 2 | 242 | #define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH 2 |
| @@ -247,6 +304,8 @@ struct virtio_crypto_op_ctrl_req { · 61 unmodified lines | |||
| 247 | mac_create_session; | 304 | mac_create_session; |
| 248 | struct virtio_crypto_aead_create_session_req | 305 | struct virtio_crypto_aead_create_session_req |
| 249 | aead_create_session; | 306 | aead_create_session; |
| 307 | struct virtio_crypto_akcipher_create_session_req | ||
| 308 | akcipher_create_session; | ||
| 250 | struct virtio_crypto_destroy_session_req | 309 | struct virtio_crypto_destroy_session_req |
| 251 | destroy_session; | 310 | destroy_session; |
| 252 | __u8 padding[56]; | 311 | __u8 padding[56]; |
| @@ -266,6 +325,14 @@ struct virtio_crypto_op_header { · 13 unmodified lines | |||
| 266 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x00) | 325 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x00) |
| 267 | #define VIRTIO_CRYPTO_AEAD_DECRYPT \ | 326 | #define VIRTIO_CRYPTO_AEAD_DECRYPT \ |
| 268 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x01) | 327 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x01) |
| 328 | #define VIRTIO_CRYPTO_AKCIPHER_ENCRYPT \ | ||
| 329 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x00) | ||
| 330 | #define VIRTIO_CRYPTO_AKCIPHER_DECRYPT \ | ||
| 331 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x01) | ||
| 332 | #define VIRTIO_CRYPTO_AKCIPHER_SIGN \ | ||
| 333 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x02) | ||
| 334 | #define VIRTIO_CRYPTO_AKCIPHER_VERIFY \ | ||
| 335 | VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x03) | ||
| 269 | __le32 opcode; | 336 | __le32 opcode; |
| 270 | /* algo should be service-specific algorithms */ | 337 | /* algo should be service-specific algorithms */ |
| 271 | __le32 algo; | 338 | __le32 algo; |
| @@ -390,6 +457,16 @@ struct virtio_crypto_aead_data_req { · 118 unmodified lines | |||
| 390 | __u8 padding[32]; | 457 | __u8 padding[32]; |
| 391 | }; | 458 | }; |
| 392 | 459 | ||
| 460 | struct virtio_crypto_akcipher_para { | ||
| 461 | __le32 src_data_len; | ||
| 462 | __le32 dst_data_len; | ||
| 463 | }; | ||
| 464 | |||
| 465 | struct virtio_crypto_akcipher_data_req { | ||
| 466 | struct virtio_crypto_akcipher_para para; | ||
| 467 | __u8 padding[40]; | ||
| 468 | }; | ||
| 469 | |||
| 393 | /* The request of the data virtqueue's packet */ | 470 | /* The request of the data virtqueue's packet */ |
| 394 | struct virtio_crypto_op_data_req { | 471 | struct virtio_crypto_op_data_req { |
| 395 | struct virtio_crypto_op_header header; | 472 | struct virtio_crypto_op_header header; |
| @@ -399,6 +476,7 @@ struct virtio_crypto_op_data_req { · 3 unmodified lines | |||
| 399 | struct virtio_crypto_hash_data_req hash_req; | 476 | struct virtio_crypto_hash_data_req hash_req; |
| 400 | struct virtio_crypto_mac_data_req mac_req; | 477 | struct virtio_crypto_mac_data_req mac_req; |
| 401 | struct virtio_crypto_aead_data_req aead_req; | 478 | struct virtio_crypto_aead_data_req aead_req; |
| 479 | struct virtio_crypto_akcipher_data_req akcipher_req; | ||
| 402 | __u8 padding[48]; | 480 | __u8 padding[48]; |
| 403 | } u; | 481 | } u; |
| 404 | }; | 482 | }; |
| @@ -408,6 +486,8 @@ struct virtio_crypto_op_data_req { · 3 unmodified lines | |||
| 408 | #define VIRTIO_CRYPTO_BADMSG 2 | 486 | #define VIRTIO_CRYPTO_BADMSG 2 |
| 409 | #define VIRTIO_CRYPTO_NOTSUPP 3 | 487 | #define VIRTIO_CRYPTO_NOTSUPP 3 |
| 410 | #define VIRTIO_CRYPTO_INVSESS 4 /* Invalid session id */ | 488 | #define VIRTIO_CRYPTO_INVSESS 4 /* Invalid session id */ |
| 489 | #define VIRTIO_CRYPTO_NOSPC 5 /* no free session ID */ | ||
| 490 | #define VIRTIO_CRYPTO_KEY_REJECTED 6 /* Signature verification failed */ | ||
| 411 | 491 | ||
| 412 | /* The accelerator hardware is ready */ | 492 | /* The accelerator hardware is ready */ |
| 413 | #define VIRTIO_CRYPTO_S_HW_READY (1 << 0) | 493 | #define VIRTIO_CRYPTO_S_HW_READY (1 << 0) |
| @@ -438,7 +518,7 @@ struct virtio_crypto_config { · 24 unmodified lines | |||
| 438 | __le32 max_cipher_key_len; | 518 | __le32 max_cipher_key_len; |
| 439 | /* Maximum length of authenticated key */ | 519 | /* Maximum length of authenticated key */ |
| 440 | __le32 max_auth_key_len; | 520 | __le32 max_auth_key_len; |
| 441 | __le32 reserve; | 521 | __le32 akcipher_algo; |
| 442 | /* Maximum size of each crypto request's content */ | 522 | /* Maximum size of each crypto request's content */ |
| 443 | __le64 max_size; | 523 | __le64 max_size; |
| 444 | }; | 524 | }; |
| @@ -203,7 +203,7 @@ EXPORT_SYMBOL_GPL(balloon_page_dequeue); · 202 unmodified lines | |||
| 203 | 203 | ||
| 204 | #ifdef CONFIG_BALLOON_COMPACTION | 204 | #ifdef CONFIG_BALLOON_COMPACTION |
| 205 | 205 | ||
| 206 | bool balloon_page_isolate(struct page *page, isolate_mode_t mode) | 206 | static bool balloon_page_isolate(struct page *page, isolate_mode_t mode) |
| 207 | 207 | ||
| 208 | { | 208 | { |
| 209 | struct balloon_dev_info *b_dev_info = balloon_page_device(page); | 209 | struct balloon_dev_info *b_dev_info = balloon_page_device(page); |
| @@ -217,7 +217,7 @@ bool balloon_page_isolate(struct page *page, isolate_mode_t mode) · 7 unmodified lines | |||
| 217 | return true; | 217 | return true; |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | void balloon_page_putback(struct page *page) | 220 | static void balloon_page_putback(struct page *page) |
| 221 | { | 221 | { |
| 222 | struct balloon_dev_info *b_dev_info = balloon_page_device(page); | 222 | struct balloon_dev_info *b_dev_info = balloon_page_device(page); |
| 223 | unsigned long flags; | 223 | unsigned long flags; |
| @@ -230,7 +230,7 @@ void balloon_page_putback(struct page *page) · 6 unmodified lines | |||
| 230 | 230 | ||
| 231 | 231 | ||
| 232 | /* move_to_new_page() counterpart for a ballooned page */ | 232 | /* move_to_new_page() counterpart for a ballooned page */ |
| 233 | int balloon_page_migrate(struct address_space *mapping, | 233 | static int balloon_page_migrate(struct address_space *mapping, |
| 234 | struct page *newpage, struct page *page, | 234 | struct page *newpage, struct page *page, |
| 235 | enum migrate_mode mode) | 235 | enum migrate_mode mode) |
| 236 | { | 236 | { |
| @@ -5,7 +5,8 @@ virtio_test: virtio_ring.o virtio_test.o · 4 unmodified lines | |||
| 5 | vringh_test: vringh_test.o vringh.o virtio_ring.o | 5 | vringh_test: vringh_test.o vringh.o virtio_ring.o |
| 6 | 6 | ||
| 7 | CFLAGS += -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h | 7 | CFLAGS += -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h |
| 8 | LDFLAGS += -lpthread | 8 | CFLAGS += -pthread |
| 9 | LDFLAGS += -pthread | ||
| 9 | vpath %.c ../../drivers/virtio ../../drivers/vhost | 10 | vpath %.c ../../drivers/virtio ../../drivers/vhost |
| 10 | mod: | 11 | mod: |
| 11 | ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V} | 12 | ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V} |
| @@ -26,8 +26,8 @@ enum dma_data_direction { · 25 unmodified lines | |||
| 26 | #define dma_map_single(d, p, s, dir) (virt_to_phys(p)) | 26 | #define dma_map_single(d, p, s, dir) (virt_to_phys(p)) |
| 27 | #define dma_mapping_error(...) (0) | 27 | #define dma_mapping_error(...) (0) |
| 28 | 28 | ||
| 29 | #define dma_unmap_single(...) do { } while (0) | 29 | #define dma_unmap_single(d, a, s, r) do { (void)(d); (void)(a); (void)(s); (void)(r); } while (0) |
| 30 | #define dma_unmap_page(...) do { } while (0) | 30 | #define dma_unmap_page(d, a, s, r) do { (void)(d); (void)(a); (void)(s); (void)(r); } while (0) |
| 31 | 31 | ||
| 32 | #define dma_max_mapping_size(...) SIZE_MAX | 32 | #define dma_max_mapping_size(...) SIZE_MAX |
| 33 | 33 | ||