Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-virtio
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-virtio:
virtio: enhance id_matching for virtio drivers
virtio: fix id_matching for virtio drivers
virtio: handle short buffers in virtio_rng.
virtio_blk: add missing __dev{init,exit} markings
virtio: indirect ring entries (VIRTIO_RING_F_INDIRECT_DESC)
virtio: teach virtio_has_feature() about transport features
virtio: expose features in sysfs
virtio_pci: optional MSI-X support
virtio_pci: split up vp_interrupt
virtio: find_vqs/del_vqs virtio operations
virtio: add names to virtqueue struct, mapping from devices to queues.
virtio: meet virtio spec by finalizing features before using device
virtio: fix obsolete documentation on probe function
This commit is contained in:
@@ -10,14 +10,17 @@
|
||||
|
||||
/**
|
||||
* virtqueue - a queue to register buffers for sending or receiving.
|
||||
* @list: the chain of virtqueues for this device
|
||||
* @callback: the function to call when buffers are consumed (can be NULL).
|
||||
* @name: the name of this virtqueue (mainly for debugging)
|
||||
* @vdev: the virtio device this queue was created for.
|
||||
* @vq_ops: the operations for this virtqueue (see below).
|
||||
* @priv: a pointer for the virtqueue implementation to use.
|
||||
*/
|
||||
struct virtqueue
|
||||
{
|
||||
struct virtqueue {
|
||||
struct list_head list;
|
||||
void (*callback)(struct virtqueue *vq);
|
||||
const char *name;
|
||||
struct virtio_device *vdev;
|
||||
struct virtqueue_ops *vq_ops;
|
||||
void *priv;
|
||||
@@ -76,15 +79,16 @@ struct virtqueue_ops {
|
||||
* @dev: underlying device.
|
||||
* @id: the device type identification (used to match it with a driver).
|
||||
* @config: the configuration ops for this device.
|
||||
* @vqs: the list of virtqueues for this device.
|
||||
* @features: the features supported by both driver and device.
|
||||
* @priv: private pointer for the driver's use.
|
||||
*/
|
||||
struct virtio_device
|
||||
{
|
||||
struct virtio_device {
|
||||
int index;
|
||||
struct device dev;
|
||||
struct virtio_device_id id;
|
||||
struct virtio_config_ops *config;
|
||||
struct list_head vqs;
|
||||
/* Note that this is a Linux set_bit-style bitmap. */
|
||||
unsigned long features[1];
|
||||
void *priv;
|
||||
@@ -99,8 +103,7 @@ void unregister_virtio_device(struct virtio_device *dev);
|
||||
* @id_table: the ids serviced by this driver.
|
||||
* @feature_table: an array of feature numbers supported by this device.
|
||||
* @feature_table_size: number of entries in the feature table array.
|
||||
* @probe: the function to call when a device is found. Returns a token for
|
||||
* remove, or PTR_ERR().
|
||||
* @probe: the function to call when a device is found. Returns 0 or -errno.
|
||||
* @remove: the function when a device is removed.
|
||||
* @config_changed: optional function to call when the device configuration
|
||||
* changes; may be called in interrupt context.
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/err.h>
|
||||
#include <linux/virtio.h>
|
||||
|
||||
/**
|
||||
@@ -49,15 +50,26 @@
|
||||
* @set_status: write the status byte
|
||||
* vdev: the virtio_device
|
||||
* status: the new status byte
|
||||
* @request_vqs: request the specified number of virtqueues
|
||||
* vdev: the virtio_device
|
||||
* max_vqs: the max number of virtqueues we want
|
||||
* If supplied, must call before any virtqueues are instantiated.
|
||||
* To modify the max number of virtqueues after request_vqs has been
|
||||
* called, call free_vqs and then request_vqs with a new value.
|
||||
* @free_vqs: cleanup resources allocated by request_vqs
|
||||
* vdev: the virtio_device
|
||||
* If supplied, must call after all virtqueues have been deleted.
|
||||
* @reset: reset the device
|
||||
* vdev: the virtio device
|
||||
* After this, status and feature negotiation must be done again
|
||||
* @find_vq: find a virtqueue and instantiate it.
|
||||
* @find_vqs: find virtqueues and instantiate them.
|
||||
* vdev: the virtio_device
|
||||
* index: the 0-based virtqueue number in case there's more than one.
|
||||
* callback: the virqtueue callback
|
||||
* Returns the new virtqueue or ERR_PTR() (eg. -ENOENT).
|
||||
* @del_vq: free a virtqueue found by find_vq().
|
||||
* nvqs: the number of virtqueues to find
|
||||
* vqs: on success, includes new virtqueues
|
||||
* callbacks: array of callbacks, for each virtqueue
|
||||
* names: array of virtqueue names (mainly for debugging)
|
||||
* Returns 0 on success or error status
|
||||
* @del_vqs: free virtqueues found by find_vqs().
|
||||
* @get_features: get the array of feature bits for this device.
|
||||
* vdev: the virtio_device
|
||||
* Returns the first 32 feature bits (all we currently need).
|
||||
@@ -66,6 +78,7 @@
|
||||
* This gives the final feature bits for the device: it can change
|
||||
* the dev->feature bits if it wants.
|
||||
*/
|
||||
typedef void vq_callback_t(struct virtqueue *);
|
||||
struct virtio_config_ops
|
||||
{
|
||||
void (*get)(struct virtio_device *vdev, unsigned offset,
|
||||
@@ -75,10 +88,11 @@ struct virtio_config_ops
|
||||
u8 (*get_status)(struct virtio_device *vdev);
|
||||
void (*set_status)(struct virtio_device *vdev, u8 status);
|
||||
void (*reset)(struct virtio_device *vdev);
|
||||
struct virtqueue *(*find_vq)(struct virtio_device *vdev,
|
||||
unsigned index,
|
||||
void (*callback)(struct virtqueue *));
|
||||
void (*del_vq)(struct virtqueue *vq);
|
||||
int (*find_vqs)(struct virtio_device *, unsigned nvqs,
|
||||
struct virtqueue *vqs[],
|
||||
vq_callback_t *callbacks[],
|
||||
const char *names[]);
|
||||
void (*del_vqs)(struct virtio_device *);
|
||||
u32 (*get_features)(struct virtio_device *vdev);
|
||||
void (*finalize_features)(struct virtio_device *vdev);
|
||||
};
|
||||
@@ -99,7 +113,9 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev,
|
||||
if (__builtin_constant_p(fbit))
|
||||
BUILD_BUG_ON(fbit >= 32);
|
||||
|
||||
virtio_check_driver_offered_feature(vdev, fbit);
|
||||
if (fbit < VIRTIO_TRANSPORT_F_START)
|
||||
virtio_check_driver_offered_feature(vdev, fbit);
|
||||
|
||||
return test_bit(fbit, vdev->features);
|
||||
}
|
||||
|
||||
@@ -126,5 +142,18 @@ static inline int virtio_config_buf(struct virtio_device *vdev,
|
||||
vdev->config->get(vdev, offset, buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
|
||||
vq_callback_t *c, const char *n)
|
||||
{
|
||||
vq_callback_t *callbacks[] = { c };
|
||||
const char *names[] = { n };
|
||||
struct virtqueue *vq;
|
||||
int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names);
|
||||
if (err < 0)
|
||||
return ERR_PTR(err);
|
||||
return vq;
|
||||
}
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_VIRTIO_CONFIG_H */
|
||||
|
||||
@@ -47,9 +47,17 @@
|
||||
/* The bit of the ISR which indicates a device configuration change. */
|
||||
#define VIRTIO_PCI_ISR_CONFIG 0x2
|
||||
|
||||
/* MSI-X registers: only enabled if MSI-X is enabled. */
|
||||
/* A 16-bit vector for configuration changes. */
|
||||
#define VIRTIO_MSI_CONFIG_VECTOR 20
|
||||
/* A 16-bit vector for selected queue notifications. */
|
||||
#define VIRTIO_MSI_QUEUE_VECTOR 22
|
||||
/* Vector value used to disable MSI for queue */
|
||||
#define VIRTIO_MSI_NO_VECTOR 0xffff
|
||||
|
||||
/* The remaining space is defined by each driver as the per-driver
|
||||
* configuration space */
|
||||
#define VIRTIO_PCI_CONFIG 20
|
||||
#define VIRTIO_PCI_CONFIG(dev) ((dev)->msix_enabled ? 24 : 20)
|
||||
|
||||
/* Virtio ABI version, this must match exactly */
|
||||
#define VIRTIO_PCI_ABI_VERSION 0
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#define VRING_DESC_F_NEXT 1
|
||||
/* This marks a buffer as write-only (otherwise read-only). */
|
||||
#define VRING_DESC_F_WRITE 2
|
||||
/* This means the buffer contains a list of buffer descriptors. */
|
||||
#define VRING_DESC_F_INDIRECT 4
|
||||
|
||||
/* The Host uses this in used->flags to advise the Guest: don't kick me when
|
||||
* you add a buffer. It's unreliable, so it's simply an optimization. Guest
|
||||
@@ -24,6 +26,9 @@
|
||||
* optimization. */
|
||||
#define VRING_AVAIL_F_NO_INTERRUPT 1
|
||||
|
||||
/* We support indirect buffer descriptors */
|
||||
#define VIRTIO_RING_F_INDIRECT_DESC 28
|
||||
|
||||
/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
|
||||
struct vring_desc
|
||||
{
|
||||
@@ -119,7 +124,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
|
||||
struct virtio_device *vdev,
|
||||
void *pages,
|
||||
void (*notify)(struct virtqueue *vq),
|
||||
void (*callback)(struct virtqueue *vq));
|
||||
void (*callback)(struct virtqueue *vq),
|
||||
const char *name);
|
||||
void vring_del_virtqueue(struct virtqueue *vq);
|
||||
/* Filter out transport-specific feature bits. */
|
||||
void vring_transport_features(struct virtio_device *vdev);
|
||||
|
||||
Reference in New Issue
Block a user