To be used by modern code, as well as to handle LE only fields such as balloon.
Unified · Split
| @@ -375,6 +375,71 @@ static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val) · 374 unmodified lines | ||
| 375 | 375 | sizeof(virtio_cwrite_v)); \ |
| 376 | 376 | } while(0) |
| 377 | 377 | |
| 378 | +/* | |
| 379 | + * Nothing virtio-specific about these, but let's worry about generalizing | |
| 380 | + * these later. | |
| 381 | + */ | |
| 382 | +#define virtio_le_to_cpu(x) \ | |
| 383 | + _Generic((x), \ | |
| 384 | + __u8: (x), \ | |
| 385 | + __le16: le16_to_cpu(x), \ | |
| 386 | + __le32: le32_to_cpu(x), \ | |
| 387 | + __le64: le64_to_cpu(x) \ | |
| 388 | + ) | |
| 389 | + | |
| 390 | +#define virtio_cpu_to_le(x, m) \ | |
| 391 | + _Generic((m), \ | |
| 392 | + __u8: (x), \ | |
| 393 | + __le16: cpu_to_le16(x), \ | |
| 394 | + __le32: cpu_to_le32(x), \ | |
| 395 | + __le64: cpu_to_le64(x) \ | |
| 396 | + ) | |
| 397 | + | |
| 398 | +/* LE (e.g. modern) Config space accessors. */ | |
| 399 | +#define virtio_cread_le(vdev, structname, member, ptr) \ | |
| 400 | + do { \ | |
| 401 | + typeof(((structname*)0)->member) virtio_cread_v; \ | |
| 402 | + \ | |
| 403 | + might_sleep(); \ | |
| 404 | + /* Sanity check: must match the member's type */ \ | |
| 405 | + typecheck(typeof(virtio_le_to_cpu(virtio_cread_v)), *(ptr)); \ | |
| 406 | + \ | |
| 407 | + switch (sizeof(virtio_cread_v)) { \ | |
| 408 | + case 1: \ | |
| 409 | + case 2: \ | |
| 410 | + case 4: \ | |
| 411 | + vdev->config->get((vdev), \ | |
| 412 | + offsetof(structname, member), \ | |
| 413 | + &virtio_cread_v, \ | |
| 414 | + sizeof(virtio_cread_v)); \ | |
| 415 | + break; \ | |
| 416 | + default: \ | |
| 417 | + __virtio_cread_many((vdev), \ | |
| 418 | + offsetof(structname, member), \ | |
| 419 | + &virtio_cread_v, \ | |
| 420 | + 1, \ | |
| 421 | + sizeof(virtio_cread_v)); \ | |
| 422 | + break; \ | |
| 423 | + } \ | |
| 424 | + *(ptr) = virtio_le_to_cpu(virtio_cread_v); \ | |
| 425 | + } while(0) | |
| 426 | + | |
| 427 | +/* Config space accessors. */ | |
| 428 | +#define virtio_cwrite_le(vdev, structname, member, ptr) \ | |
| 429 | + do { \ | |
| 430 | + typeof(((structname*)0)->member) virtio_cwrite_v = \ | |
| 431 | + virtio_cpu_to_le(*(ptr), ((structname*)0)->member); \ | |
| 432 | + \ | |
| 433 | + might_sleep(); \ | |
| 434 | + /* Sanity check: must match the member's type */ \ | |
| 435 | + typecheck(typeof(virtio_le_to_cpu(virtio_cwrite_v)), *(ptr)); \ | |
| 436 | + \ | |
| 437 | + vdev->config->set((vdev), offsetof(structname, member), \ | |
| 438 | + &virtio_cwrite_v, \ | |
| 439 | + sizeof(virtio_cwrite_v)); \ | |
| 440 | + } while(0) | |
| 441 | + | |
| 442 | + | |
| 378 | 443 | /* Read @count fields, @bytes each. */ |
| 379 | 444 | static inline void __virtio_cread_many(struct virtio_device *vdev, |
| 380 | 445 | unsigned int offset, |