Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio: add legacy feature table support

virtio-blk has some legacy feature bits that modern drivers
must not negotiate, but are needed for old legacy hosts
(that e.g. don't support virtio-scsi).
Allow a separate legacy feature table for such cases.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>




+28 -1
+24 -1
drivers/virtio/virtio.c
··· 113 113 for (i = 0; i < drv->feature_table_size; i++) 114 114 if (drv->feature_table[i] == fbit) 115 115 return; 116 + 117 + if (drv->feature_table_legacy) { 118 + for (i = 0; i < drv->feature_table_size_legacy; i++) 119 + if (drv->feature_table_legacy[i] == fbit) 120 + return; 121 + } 122 + 116 123 BUG(); 117 124 } 118 125 EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature); ··· 168 161 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); 169 162 u64 device_features; 170 163 u64 driver_features; 164 + u64 driver_features_legacy; 171 165 unsigned status; 172 166 173 167 /* We have a driver! */ ··· 185 177 driver_features |= (1ULL << f); 186 178 } 187 179 188 - dev->features = driver_features & device_features; 180 + /* Some drivers have a separate feature table for virtio v1.0 */ 181 + if (drv->feature_table_legacy) { 182 + driver_features_legacy = 0; 183 + for (i = 0; i < drv->feature_table_size_legacy; i++) { 184 + unsigned int f = drv->feature_table_legacy[i]; 185 + BUG_ON(f >= 64); 186 + driver_features_legacy |= (1ULL << f); 187 + } 188 + } else { 189 + driver_features_legacy = driver_features; 190 + } 191 + 192 + if (driver_features & device_features & (1ULL << VIRTIO_F_VERSION_1)) 193 + dev->features = driver_features & device_features; 194 + else 195 + dev->features = driver_features_legacy & device_features; 189 196 190 197 /* Transport features always preserved to pass to finalize_features. */ 191 198 for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)
+4
include/linux/virtio.h
··· 130 130 * @id_table: the ids serviced by this driver. 131 131 * @feature_table: an array of feature numbers supported by this driver. 132 132 * @feature_table_size: number of entries in the feature table array. 133 + * @feature_table_legacy: same as feature_table but when working in legacy mode. 134 + * @feature_table_size_legacy: number of entries in feature table legacy array. 133 135 * @probe: the function to call when a device is found. Returns 0 or -errno. 134 136 * @remove: the function to call when a device is removed. 135 137 * @config_changed: optional function to call when the device configuration ··· 142 140 const struct virtio_device_id *id_table; 143 141 const unsigned int *feature_table; 144 142 unsigned int feature_table_size; 143 + const unsigned int *feature_table_legacy; 144 + unsigned int feature_table_size_legacy; 145 145 int (*probe)(struct virtio_device *dev); 146 146 void (*scan)(struct virtio_device *dev); 147 147 void (*remove)(struct virtio_device *dev);