virtio: explicit advertisement of driver features

A recent proposed feature addition to the virtio block driver revealed
some flaws in the API: in particular, we assume that feature
negotiation is complete once a driver's probe function returns.

There is nothing in the API to require this, however, and even I
didn't notice when it was violated.

So instead, we require the driver to specify what features it supports
in a table, we can then move the feature negotiation into the virtio
core.  The intersection of device and driver features are presented in
a new 'features' bitmap in the struct virtio_device.

Note that this highlights the difference between Linux unsigned-long
bitmaps where each unsigned long is in native endian, and a
straight-forward little-endian array of bytes.

Drivers can still remove feature bits in their probe routine if they
really have to.

API changes:
- dev->config->feature() no longer gets and acks a feature.
- drivers should advertise their features in the 'feature_table' field
- use virtio_has_feature() for extra sanity when checking feature bits

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index e7d1084..06005fa 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -76,6 +76,7 @@
  * @dev: underlying device.
  * @id: the device type identification (used to match it with a driver).
  * @config: the configuration ops for this device.
+ * @features: the features supported by both driver and device.
  * @priv: private pointer for the driver's use.
  */
 struct virtio_device
@@ -84,6 +85,8 @@
 	struct device dev;
 	struct virtio_device_id id;
 	struct virtio_config_ops *config;
+	/* Note that this is a Linux set_bit-style bitmap. */
+	unsigned long features[1];
 	void *priv;
 };
 
@@ -94,6 +97,8 @@
  * virtio_driver - operations for a virtio I/O driver
  * @driver: underlying device driver (populate name and owner).
  * @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().
  * @remove: the function when a device is removed.
@@ -103,6 +108,8 @@
 struct virtio_driver {
 	struct device_driver driver;
 	const struct virtio_device_id *id_table;
+	const unsigned int *feature_table;
+	unsigned int feature_table_size;
 	int (*probe)(struct virtio_device *dev);
 	void (*remove)(struct virtio_device *dev);
 	void (*config_changed)(struct virtio_device *dev);
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 475572e..50db245 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -20,11 +20,6 @@
 
 /**
  * virtio_config_ops - operations for configuring a virtio device
- * @feature: search for a feature in this config
- *	vdev: the virtio_device
- *	bit: the feature bit
- *	Returns true if the feature is supported.  Acknowledges the feature
- *	so the host can see it.
  * @get: read the value of a configuration field
  *	vdev: the virtio_device
  *	offset: the offset of the configuration field
@@ -50,10 +45,15 @@
  *	callback: the virqtueue callback
  *	Returns the new virtqueue or ERR_PTR() (eg. -ENOENT).
  * @del_vq: free a virtqueue found by find_vq().
+ * @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).
+ * @set_features: confirm what device features we'll be using.
+ *	vdev: the virtio_device
+ *	feature: the first 32 feature bits
  */
 struct virtio_config_ops
 {
-	bool (*feature)(struct virtio_device *vdev, unsigned bit);
 	void (*get)(struct virtio_device *vdev, unsigned offset,
 		    void *buf, unsigned len);
 	void (*set)(struct virtio_device *vdev, unsigned offset,
@@ -65,8 +65,30 @@
 				     unsigned index,
 				     void (*callback)(struct virtqueue *));
 	void (*del_vq)(struct virtqueue *vq);
+	u32 (*get_features)(struct virtio_device *vdev);
+	void (*set_features)(struct virtio_device *vdev, u32 features);
 };
 
+/* If driver didn't advertise the feature, it will never appear. */
+void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
+					 unsigned int fbit);
+
+/**
+ * virtio_has_feature - helper to determine if this device has this feature.
+ * @vdev: the device
+ * @fbit: the feature bit
+ */
+static inline bool virtio_has_feature(const struct virtio_device *vdev,
+				      unsigned int fbit)
+{
+	/* Did you forget to fix assumptions on max features? */
+	if (__builtin_constant_p(fbit))
+		BUILD_BUG_ON(fbit >= 32);
+
+	virtio_check_driver_offered_feature(vdev, fbit);
+	return test_bit(fbit, vdev->features);
+}
+
 /**
  * virtio_config_val - look for a feature and get a virtio config entry.
  * @vdev: the virtio device
@@ -84,7 +106,7 @@
 				    unsigned int offset,
 				    void *buf, unsigned len)
 {
-	if (!vdev->config->feature(vdev, fbit))
+	if (!virtio_has_feature(vdev, fbit))
 		return -ENOENT;
 
 	vdev->config->get(vdev, offset, buf, len);