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

Configure Feed

Select the types of activity you want to include in your feed.

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 <Bonnie_Lo@wiwynn.com>
Tested-by: Jerry C Chen <Jerry_C_Chen@wiwynn.com>
Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jeremy Kerr and committed by
David S. Miller
338a93cf 2146b7dd

+41
+41
drivers/net/mctp/mctp-i2c.c
··· 442 442 i2c_unlock_bus(midev->adapter, I2C_LOCK_SEGMENT); 443 443 } 444 444 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 + 445 481 static void mctp_i2c_xmit(struct mctp_i2c_dev *midev, struct sk_buff *skb) 446 482 { 447 483 struct net_device_stats *stats = &midev->ndev->stats; ··· 536 500 case MCTP_I2C_TX_FLOW_EXISTING: 537 501 /* existing flow: we already have the lock; just tx */ 538 502 rc = __i2c_transfer(midev->adapter, &msg, 1); 503 + 504 + /* on tx errors, the flow can no longer be considered valid */ 505 + if (rc) 506 + mctp_i2c_invalidate_tx_flow(midev, skb); 507 + 539 508 break; 540 509 541 510 case MCTP_I2C_TX_FLOW_INVALID: