Skip to content

Commit 338a93c

Browse files
jk-ozlabsdavem330
authored andcommitted
net: mctp-i2c: invalidate flows immediately on TX errors
If we encounter an error on i2c packet transmit, we won't have a valid flow anymore; since we didn't transmit a valid packet sequence, we'll have to wait for the key to timeout instead of dropping it on the reply. This causes the i2c lock to be held for longer than necessary. Instead, invalidate the flow on TX error, and release the i2c lock immediately. Cc: Bonnie Lo <[email protected]> Tested-by: Jerry C Chen <[email protected]> Signed-off-by: Jeremy Kerr <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2146b7d commit 338a93c

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

drivers/net/mctp/mctp-i2c.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,42 @@ static void mctp_i2c_unlock_reset(struct mctp_i2c_dev *midev)
442442
i2c_unlock_bus(midev->adapter, I2C_LOCK_SEGMENT);
443443
}
444444

445+
static void mctp_i2c_invalidate_tx_flow(struct mctp_i2c_dev *midev,
446+
struct sk_buff *skb)
447+
{
448+
struct mctp_sk_key *key;
449+
struct mctp_flow *flow;
450+
unsigned long flags;
451+
bool release;
452+
453+
flow = skb_ext_find(skb, SKB_EXT_MCTP);
454+
if (!flow)
455+
return;
456+
457+
key = flow->key;
458+
if (!key)
459+
return;
460+
461+
spin_lock_irqsave(&key->lock, flags);
462+
if (key->manual_alloc) {
463+
/* we don't have control over lifetimes for manually-allocated
464+
* keys, so cannot assume we can invalidate all future flows
465+
* that would use this key.
466+
*/
467+
release = false;
468+
} else {
469+
release = key->dev_flow_state == MCTP_I2C_FLOW_STATE_ACTIVE;
470+
key->dev_flow_state = MCTP_I2C_FLOW_STATE_INVALID;
471+
}
472+
spin_unlock_irqrestore(&key->lock, flags);
473+
474+
/* if we have changed state from active, the flow held a reference on
475+
* the lock; release that now.
476+
*/
477+
if (release)
478+
mctp_i2c_unlock_nest(midev);
479+
}
480+
445481
static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb)
446482
{
447483
struct net_device_stats *stats = &midev->ndev->stats;
@@ -500,6 +536,11 @@ static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb)
500536
case MCTP_I2C_TX_FLOW_EXISTING:
501537
/* existing flow: we already have the lock; just tx */
502538
rc = __i2c_transfer(midev->adapter, &msg, 1);
539+
540+
/* on tx errors, the flow can no longer be considered valid */
541+
if (rc)
542+
mctp_i2c_invalidate_tx_flow(midev, skb);
543+
503544
break;
504545

505546
case MCTP_I2C_TX_FLOW_INVALID:

0 commit comments

Comments
 (0)