diff options
| -rw-r--r-- | drivers/block/virtio_blk.c | 1 | ||||
| -rw-r--r-- | drivers/net/virtio_net.c | 22 | ||||
| -rw-r--r-- | drivers/virtio/virtio_balloon.c | 4 | ||||
| -rw-r--r-- | drivers/virtio/virtio_pci.c | 15 | ||||
| -rw-r--r-- | drivers/virtio/virtio_ring.c | 1 | ||||
| -rw-r--r-- | fs/hfs/brec.c | 18 | ||||
| -rw-r--r-- | include/linux/virtio.h | 5 |
7 files changed, 49 insertions, 17 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 3b1a68d6eddb..0cfbe8c594a5 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -238,6 +238,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 238 | vblk->disk->first_minor = index_to_minor(index); | 238 | vblk->disk->first_minor = index_to_minor(index); |
| 239 | vblk->disk->private_data = vblk; | 239 | vblk->disk->private_data = vblk; |
| 240 | vblk->disk->fops = &virtblk_fops; | 240 | vblk->disk->fops = &virtblk_fops; |
| 241 | vblk->disk->driverfs_dev = &vdev->dev; | ||
| 241 | index++; | 242 | index++; |
| 242 | 243 | ||
| 243 | /* If barriers are supported, tell block layer that queue is ordered */ | 244 | /* If barriers are supported, tell block layer that queue is ordered */ |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 19fd4cb0ddf8..b58472cf76f8 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -203,8 +203,11 @@ again: | |||
| 203 | if (received < budget) { | 203 | if (received < budget) { |
| 204 | netif_rx_complete(vi->dev, napi); | 204 | netif_rx_complete(vi->dev, napi); |
| 205 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) | 205 | if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq)) |
| 206 | && netif_rx_reschedule(vi->dev, napi)) | 206 | && napi_schedule_prep(napi)) { |
| 207 | vi->rvq->vq_ops->disable_cb(vi->rvq); | ||
| 208 | __netif_rx_schedule(vi->dev, napi); | ||
| 207 | goto again; | 209 | goto again; |
| 210 | } | ||
| 208 | } | 211 | } |
| 209 | 212 | ||
| 210 | return received; | 213 | return received; |
| @@ -278,10 +281,11 @@ again: | |||
| 278 | pr_debug("%s: virtio not prepared to send\n", dev->name); | 281 | pr_debug("%s: virtio not prepared to send\n", dev->name); |
| 279 | netif_stop_queue(dev); | 282 | netif_stop_queue(dev); |
| 280 | 283 | ||
| 281 | /* Activate callback for using skbs: if this fails it | 284 | /* Activate callback for using skbs: if this returns false it |
| 282 | * means some were used in the meantime. */ | 285 | * means some were used in the meantime. */ |
| 283 | if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { | 286 | if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) { |
| 284 | printk("Unlikely: restart svq failed\n"); | 287 | printk("Unlikely: restart svq race\n"); |
| 288 | vi->svq->vq_ops->disable_cb(vi->svq); | ||
| 285 | netif_start_queue(dev); | 289 | netif_start_queue(dev); |
| 286 | goto again; | 290 | goto again; |
| 287 | } | 291 | } |
| @@ -294,6 +298,15 @@ again: | |||
| 294 | return 0; | 298 | return 0; |
| 295 | } | 299 | } |
| 296 | 300 | ||
| 301 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 302 | static void virtnet_netpoll(struct net_device *dev) | ||
| 303 | { | ||
| 304 | struct virtnet_info *vi = netdev_priv(dev); | ||
| 305 | |||
| 306 | napi_schedule(&vi->napi); | ||
| 307 | } | ||
| 308 | #endif | ||
| 309 | |||
| 297 | static int virtnet_open(struct net_device *dev) | 310 | static int virtnet_open(struct net_device *dev) |
| 298 | { | 311 | { |
| 299 | struct virtnet_info *vi = netdev_priv(dev); | 312 | struct virtnet_info *vi = netdev_priv(dev); |
| @@ -336,6 +349,9 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
| 336 | dev->stop = virtnet_close; | 349 | dev->stop = virtnet_close; |
| 337 | dev->hard_start_xmit = start_xmit; | 350 | dev->hard_start_xmit = start_xmit; |
| 338 | dev->features = NETIF_F_HIGHDMA; | 351 | dev->features = NETIF_F_HIGHDMA; |
| 352 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 353 | dev->poll_controller = virtnet_netpoll; | ||
| 354 | #endif | ||
| 339 | SET_NETDEV_DEV(dev, &vdev->dev); | 355 | SET_NETDEV_DEV(dev, &vdev->dev); |
| 340 | 356 | ||
| 341 | /* Do we support "hardware" checksums? */ | 357 | /* Do we support "hardware" checksums? */ |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index c8a4332d1132..0b3efc31ee6d 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
| @@ -152,7 +152,7 @@ static void virtballoon_changed(struct virtio_device *vdev) | |||
| 152 | wake_up(&vb->config_change); | 152 | wake_up(&vb->config_change); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | static inline int towards_target(struct virtio_balloon *vb) | 155 | static inline s64 towards_target(struct virtio_balloon *vb) |
| 156 | { | 156 | { |
| 157 | u32 v; | 157 | u32 v; |
| 158 | __virtio_config_val(vb->vdev, | 158 | __virtio_config_val(vb->vdev, |
| @@ -176,7 +176,7 @@ static int balloon(void *_vballoon) | |||
| 176 | 176 | ||
| 177 | set_freezable(); | 177 | set_freezable(); |
| 178 | while (!kthread_should_stop()) { | 178 | while (!kthread_should_stop()) { |
| 179 | int diff; | 179 | s64 diff; |
| 180 | 180 | ||
| 181 | try_to_freeze(); | 181 | try_to_freeze(); |
| 182 | wait_event_interruptible(vb->config_change, | 182 | wait_event_interruptible(vb->config_change, |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 26f787ddd5ff..59a8f73dec73 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
| @@ -177,6 +177,7 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) | |||
| 177 | struct virtio_pci_device *vp_dev = opaque; | 177 | struct virtio_pci_device *vp_dev = opaque; |
| 178 | struct virtio_pci_vq_info *info; | 178 | struct virtio_pci_vq_info *info; |
| 179 | irqreturn_t ret = IRQ_NONE; | 179 | irqreturn_t ret = IRQ_NONE; |
| 180 | unsigned long flags; | ||
| 180 | u8 isr; | 181 | u8 isr; |
| 181 | 182 | ||
| 182 | /* reading the ISR has the effect of also clearing it so it's very | 183 | /* reading the ISR has the effect of also clearing it so it's very |
| @@ -197,12 +198,12 @@ static irqreturn_t vp_interrupt(int irq, void *opaque) | |||
| 197 | drv->config_changed(&vp_dev->vdev); | 198 | drv->config_changed(&vp_dev->vdev); |
| 198 | } | 199 | } |
| 199 | 200 | ||
| 200 | spin_lock(&vp_dev->lock); | 201 | spin_lock_irqsave(&vp_dev->lock, flags); |
| 201 | list_for_each_entry(info, &vp_dev->virtqueues, node) { | 202 | list_for_each_entry(info, &vp_dev->virtqueues, node) { |
| 202 | if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) | 203 | if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) |
| 203 | ret = IRQ_HANDLED; | 204 | ret = IRQ_HANDLED; |
| 204 | } | 205 | } |
| 205 | spin_unlock(&vp_dev->lock); | 206 | spin_unlock_irqrestore(&vp_dev->lock, flags); |
| 206 | 207 | ||
| 207 | return ret; | 208 | return ret; |
| 208 | } | 209 | } |
| @@ -214,6 +215,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
| 214 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | 215 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); |
| 215 | struct virtio_pci_vq_info *info; | 216 | struct virtio_pci_vq_info *info; |
| 216 | struct virtqueue *vq; | 217 | struct virtqueue *vq; |
| 218 | unsigned long flags; | ||
| 217 | u16 num; | 219 | u16 num; |
| 218 | int err; | 220 | int err; |
| 219 | 221 | ||
| @@ -255,9 +257,9 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index, | |||
| 255 | vq->priv = info; | 257 | vq->priv = info; |
| 256 | info->vq = vq; | 258 | info->vq = vq; |
| 257 | 259 | ||
| 258 | spin_lock(&vp_dev->lock); | 260 | spin_lock_irqsave(&vp_dev->lock, flags); |
| 259 | list_add(&info->node, &vp_dev->virtqueues); | 261 | list_add(&info->node, &vp_dev->virtqueues); |
| 260 | spin_unlock(&vp_dev->lock); | 262 | spin_unlock_irqrestore(&vp_dev->lock, flags); |
| 261 | 263 | ||
| 262 | return vq; | 264 | return vq; |
| 263 | 265 | ||
| @@ -274,10 +276,11 @@ static void vp_del_vq(struct virtqueue *vq) | |||
| 274 | { | 276 | { |
| 275 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | 277 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); |
| 276 | struct virtio_pci_vq_info *info = vq->priv; | 278 | struct virtio_pci_vq_info *info = vq->priv; |
| 279 | unsigned long flags; | ||
| 277 | 280 | ||
| 278 | spin_lock(&vp_dev->lock); | 281 | spin_lock_irqsave(&vp_dev->lock, flags); |
| 279 | list_del(&info->node); | 282 | list_del(&info->node); |
| 280 | spin_unlock(&vp_dev->lock); | 283 | spin_unlock_irqrestore(&vp_dev->lock, flags); |
| 281 | 284 | ||
| 282 | vring_del_virtqueue(vq); | 285 | vring_del_virtqueue(vq); |
| 283 | 286 | ||
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 3a28c1382131..aa714028641e 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
| @@ -232,7 +232,6 @@ static bool vring_enable_cb(struct virtqueue *_vq) | |||
| 232 | vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; | 232 | vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; |
| 233 | mb(); | 233 | mb(); |
| 234 | if (unlikely(more_used(vq))) { | 234 | if (unlikely(more_used(vq))) { |
| 235 | vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; | ||
| 236 | END_USE(vq); | 235 | END_USE(vq); |
| 237 | return false; | 236 | return false; |
| 238 | } | 237 | } |
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c index 878bf25dbc6a..92fb358ce824 100644 --- a/fs/hfs/brec.c +++ b/fs/hfs/brec.c | |||
| @@ -229,7 +229,7 @@ skip: | |||
| 229 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | 229 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) |
| 230 | { | 230 | { |
| 231 | struct hfs_btree *tree; | 231 | struct hfs_btree *tree; |
| 232 | struct hfs_bnode *node, *new_node; | 232 | struct hfs_bnode *node, *new_node, *next_node; |
| 233 | struct hfs_bnode_desc node_desc; | 233 | struct hfs_bnode_desc node_desc; |
| 234 | int num_recs, new_rec_off, new_off, old_rec_off; | 234 | int num_recs, new_rec_off, new_off, old_rec_off; |
| 235 | int data_start, data_end, size; | 235 | int data_start, data_end, size; |
| @@ -248,6 +248,17 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
| 248 | new_node->type = node->type; | 248 | new_node->type = node->type; |
| 249 | new_node->height = node->height; | 249 | new_node->height = node->height; |
| 250 | 250 | ||
| 251 | if (node->next) | ||
| 252 | next_node = hfs_bnode_find(tree, node->next); | ||
| 253 | else | ||
| 254 | next_node = NULL; | ||
| 255 | |||
| 256 | if (IS_ERR(next_node)) { | ||
| 257 | hfs_bnode_put(node); | ||
| 258 | hfs_bnode_put(new_node); | ||
| 259 | return next_node; | ||
| 260 | } | ||
| 261 | |||
| 251 | size = tree->node_size / 2 - node->num_recs * 2 - 14; | 262 | size = tree->node_size / 2 - node->num_recs * 2 - 14; |
| 252 | old_rec_off = tree->node_size - 4; | 263 | old_rec_off = tree->node_size - 4; |
| 253 | num_recs = 1; | 264 | num_recs = 1; |
| @@ -261,6 +272,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
| 261 | /* panic? */ | 272 | /* panic? */ |
| 262 | hfs_bnode_put(node); | 273 | hfs_bnode_put(node); |
| 263 | hfs_bnode_put(new_node); | 274 | hfs_bnode_put(new_node); |
| 275 | if (next_node) | ||
| 276 | hfs_bnode_put(next_node); | ||
| 264 | return ERR_PTR(-ENOSPC); | 277 | return ERR_PTR(-ENOSPC); |
| 265 | } | 278 | } |
| 266 | 279 | ||
| @@ -315,8 +328,7 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | |||
| 315 | hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); | 328 | hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); |
| 316 | 329 | ||
| 317 | /* update next bnode header */ | 330 | /* update next bnode header */ |
| 318 | if (new_node->next) { | 331 | if (next_node) { |
| 319 | struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next); | ||
| 320 | next_node->prev = new_node->this; | 332 | next_node->prev = new_node->this; |
| 321 | hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); | 333 | hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); |
| 322 | node_desc.prev = cpu_to_be32(next_node->prev); | 334 | node_desc.prev = cpu_to_be32(next_node->prev); |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 260d1fcf29a4..12c18ac1b973 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
| @@ -43,8 +43,9 @@ struct virtqueue | |||
| 43 | * vq: the struct virtqueue we're talking about. | 43 | * vq: the struct virtqueue we're talking about. |
| 44 | * @enable_cb: restart callbacks after disable_cb. | 44 | * @enable_cb: restart callbacks after disable_cb. |
| 45 | * vq: the struct virtqueue we're talking about. | 45 | * vq: the struct virtqueue we're talking about. |
| 46 | * This returns "false" (and doesn't re-enable) if there are pending | 46 | * This re-enables callbacks; it returns "false" if there are pending |
| 47 | * buffers in the queue, to avoid a race. | 47 | * buffers in the queue, to detect a possible race between the driver |
| 48 | * checking for more work, and enabling callbacks. | ||
| 48 | * | 49 | * |
| 49 | * Locking rules are straightforward: the driver is responsible for | 50 | * Locking rules are straightforward: the driver is responsible for |
| 50 | * locking. No two operations may be invoked simultaneously. | 51 | * locking. No two operations may be invoked simultaneously. |
