staging: most: fix retrieval of buffer availability
authorChristian Gromm <christian.gromm@microchip.com>
Tue, 12 Jan 2016 13:00:03 +0000 (14:00 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 8 Feb 2016 01:34:58 +0000 (17:34 -0800)
This patch fixes the function channel_has_mbo that delivers the false
information in case two AIMs are using the same tx channel.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/most/aim-cdev/cdev.c
drivers/staging/most/mostcore/core.c
drivers/staging/most/mostcore/mostcore.h

index 533e2900ad63a1f67c9156c09ac7ba9b18d2bee9..c4bbf7d296e8b2d8c28c39b3404c3e429a1d0122 100644 (file)
@@ -50,6 +50,11 @@ struct aim_channel {
 static struct list_head channel_list;
 static spinlock_t ch_list_lock;
 
+static inline bool ch_has_mbo(struct aim_channel *c)
+{
+       return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0;
+}
+
 static struct aim_channel *get_channel(struct most_interface *iface, int id)
 {
        struct aim_channel *channel, *tmp;
@@ -279,11 +284,6 @@ start_copy:
        return copied;
 }
 
-static inline bool __must_check IS_ERR_OR_FALSE(int x)
-{
-       return x <= 0;
-}
-
 static unsigned int aim_poll(struct file *filp, poll_table *wait)
 {
        struct aim_channel *c = filp->private_data;
@@ -295,7 +295,7 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait)
                if (!kfifo_is_empty(&c->fifo))
                        mask |= POLLIN | POLLRDNORM;
        } else {
-               if (!IS_ERR_OR_FALSE(channel_has_mbo(c->iface, c->channel_id)))
+               if (ch_has_mbo(c))
                        mask |= POLLOUT | POLLWRNORM;
        }
        return mask;
index b085f0ac5b8c27d4956214b7e1010c1c6411964b..09a5a1a1138ef2bdc913189bace5345c4cc45bb7 100644 (file)
@@ -1352,7 +1352,7 @@ most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
        return i->channel[id];
 }
 
-int channel_has_mbo(struct most_interface *iface, int id)
+int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
 {
        struct most_c_obj *c = get_channel_by_iface(iface, id);
        unsigned long flags;
@@ -1361,6 +1361,11 @@ int channel_has_mbo(struct most_interface *iface, int id)
        if (unlikely(!c))
                return -EINVAL;
 
+       if (c->aim0.refs && c->aim1.refs &&
+           ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
+            (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
+               return 0;
+
        spin_lock_irqsave(&c->fifo_lock, flags);
        empty = list_empty(&c->fifo);
        spin_unlock_irqrestore(&c->fifo_lock, flags);
index bda3850d543587cea271b868caf14094eee66e53..60e018e499efbbf913ad9ca8f3f7417b526866bb 100644 (file)
@@ -310,7 +310,8 @@ int most_deregister_aim(struct most_aim *aim);
 struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
                         struct most_aim *);
 void most_put_mbo(struct mbo *mbo);
-int channel_has_mbo(struct most_interface *iface, int channel_idx);
+int channel_has_mbo(struct most_interface *iface, int channel_idx,
+                   struct most_aim *aim);
 int most_start_channel(struct most_interface *iface, int channel_idx,
                       struct most_aim *);
 int most_stop_channel(struct most_interface *iface, int channel_idx,