|
43 | 43 | enum {
|
44 | 44 | MCTP_I2C_FLOW_STATE_NEW = 0,
|
45 | 45 | MCTP_I2C_FLOW_STATE_ACTIVE,
|
| 46 | + MCTP_I2C_FLOW_STATE_INVALID, |
46 | 47 | };
|
47 | 48 |
|
48 | 49 | /* 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)
|
374 | 375 | */
|
375 | 376 | if (!key->valid) {
|
376 | 377 | 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; |
381 | 378 | } 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 | + } |
383 | 390 | }
|
384 | 391 |
|
385 | 392 | spin_unlock_irqrestore(&key->lock, flags);
|
@@ -617,21 +624,31 @@ static void mctp_i2c_release_flow(struct mctp_dev *mdev,
|
617 | 624 |
|
618 | 625 | {
|
619 | 626 | struct mctp_i2c_dev *midev = netdev_priv(mdev->dev);
|
| 627 | + bool queue_release = false; |
620 | 628 | unsigned long flags;
|
621 | 629 |
|
622 | 630 | 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 |
628 | 633 | */
|
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); |
633 | 640 |
|
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 | + } |
635 | 652 | }
|
636 | 653 |
|
637 | 654 | static const struct net_device_ops mctp_i2c_ops = {
|
|
0 commit comments