Skip to content

Commit 9cbd48d

Browse files
jk-ozlabskuba-moo
authored andcommitted
mctp i2c: don't count unused / invalid keys for flow release
We're currently hitting the WARN_ON in mctp_i2c_flow_release: if (midev->release_count > midev->i2c_lock_count) { WARN_ONCE(1, "release count overflow"); This may be hit if we expire a flow before sending the first packet it contains - as we will not be pairing the increment of release_count (performed on flow release) with the i2c lock operation (only performed on actual TX). To fix this, only release a flow if we've encountered it previously (ie, dev_flow_state does not indicate NEW), as we will mark the flow as ACTIVE at the same time as accounting for the i2c lock operation. We also need to add an INVALID flow state, to indicate when we've done the release. Fixes: f5b8abf ("mctp i2c: MCTP I2C binding driver") Reported-by: Jian Zhang <[email protected]> Tested-by: Jian Zhang <[email protected]> Signed-off-by: Jeremy Kerr <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 0834ced commit 9cbd48d

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

drivers/net/mctp/mctp-i2c.c

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
enum {
4444
MCTP_I2C_FLOW_STATE_NEW = 0,
4545
MCTP_I2C_FLOW_STATE_ACTIVE,
46+
MCTP_I2C_FLOW_STATE_INVALID,
4647
};
4748

4849
/* List of all struct mctp_i2c_client
@@ -374,12 +375,18 @@ mctp_i2c_get_tx_flow_state(struct mctp_i2c_dev *midev, struct sk_buff *skb)
374375
*/
375376
if (!key->valid) {
376377
state = MCTP_I2C_TX_FLOW_INVALID;
377-
378-
} else if (key->dev_flow_state == MCTP_I2C_FLOW_STATE_NEW) {
379-
key->dev_flow_state = MCTP_I2C_FLOW_STATE_ACTIVE;
380-
state = MCTP_I2C_TX_FLOW_NEW;
381378
} else {
382-
state = MCTP_I2C_TX_FLOW_EXISTING;
379+
switch (key->dev_flow_state) {
380+
case MCTP_I2C_FLOW_STATE_NEW:
381+
key->dev_flow_state = MCTP_I2C_FLOW_STATE_ACTIVE;
382+
state = MCTP_I2C_TX_FLOW_NEW;
383+
break;
384+
case MCTP_I2C_FLOW_STATE_ACTIVE:
385+
state = MCTP_I2C_TX_FLOW_EXISTING;
386+
break;
387+
default:
388+
state = MCTP_I2C_TX_FLOW_INVALID;
389+
}
383390
}
384391

385392
spin_unlock_irqrestore(&key->lock, flags);
@@ -617,21 +624,31 @@ static void mctp_i2c_release_flow(struct mctp_dev *mdev,
617624

618625
{
619626
struct mctp_i2c_dev *midev = netdev_priv(mdev->dev);
627+
bool queue_release = false;
620628
unsigned long flags;
621629

622630
spin_lock_irqsave(&midev->lock, flags);
623-
midev->release_count++;
624-
spin_unlock_irqrestore(&midev->lock, flags);
625-
626-
/* Ensure we have a release operation queued, through the fake
627-
* marker skb
631+
/* if we have seen the flow/key previously, we need to pair the
632+
* original lock with a release
628633
*/
629-
spin_lock(&midev->tx_queue.lock);
630-
if (!midev->unlock_marker.next)
631-
__skb_queue_tail(&midev->tx_queue, &midev->unlock_marker);
632-
spin_unlock(&midev->tx_queue.lock);
634+
if (key->dev_flow_state == MCTP_I2C_FLOW_STATE_ACTIVE) {
635+
midev->release_count++;
636+
queue_release = true;
637+
}
638+
key->dev_flow_state = MCTP_I2C_FLOW_STATE_INVALID;
639+
spin_unlock_irqrestore(&midev->lock, flags);
633640

634-
wake_up(&midev->tx_wq);
641+
if (queue_release) {
642+
/* Ensure we have a release operation queued, through the fake
643+
* marker skb
644+
*/
645+
spin_lock(&midev->tx_queue.lock);
646+
if (!midev->unlock_marker.next)
647+
__skb_queue_tail(&midev->tx_queue,
648+
&midev->unlock_marker);
649+
spin_unlock(&midev->tx_queue.lock);
650+
wake_up(&midev->tx_wq);
651+
}
635652
}
636653

637654
static const struct net_device_ops mctp_i2c_ops = {

0 commit comments

Comments
 (0)