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.

i3c: mipi-i3c-hci: Consolidate spinlocks

The MIPI I3C HCI driver currently uses separate spinlocks for different
contexts (PIO vs. DMA rings). This split is unnecessary and complicates
upcoming fixes. The driver does not support concurrent PIO and DMA
operation, and it only supports a single DMA ring, so a single lock is
sufficient for all paths.

Introduce a unified spinlock in struct i3c_hci, switch both PIO and DMA
code to use it, and remove the per-context locks.

No functional change is intended in this patch.

Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver")
Cc: stable@vger.kernel.org
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260306072451.11131-5-adrian.hunter@intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

Adrian Hunter and committed by
Alexandre Belloni
fa12bb90 f3bcbfe1

+16 -17
+2
drivers/i3c/master/mipi-i3c-hci/core.c
··· 926 926 if (!hci) 927 927 return -ENOMEM; 928 928 929 + spin_lock_init(&hci->lock); 930 + 929 931 /* 930 932 * Multi-bus instances share the same MMIO address range, but not 931 933 * necessarily in separate contiguous sub-ranges. To avoid overlapping
+6 -8
drivers/i3c/master/mipi-i3c-hci/dma.c
··· 131 131 unsigned int xfer_struct_sz, resp_struct_sz, ibi_status_sz, ibi_chunk_sz; 132 132 unsigned int done_ptr, ibi_chunk_ptr; 133 133 struct hci_xfer **src_xfers; 134 - spinlock_t lock; 135 134 struct completion op_done; 136 135 }; 137 136 ··· 343 344 goto err_out; 344 345 rh = &rings->headers[i]; 345 346 rh->regs = hci->base_regs + offset; 346 - spin_lock_init(&rh->lock); 347 347 init_completion(&rh->op_done); 348 348 349 349 rh->xfer_entries = XFER_RING_ENTRIES; ··· 532 534 } 533 535 534 536 /* take care to update the hardware enqueue pointer atomically */ 535 - spin_lock_irq(&rh->lock); 537 + spin_lock_irq(&hci->lock); 536 538 op1_val = rh_reg_read(RING_OPERATION1); 537 539 op1_val &= ~RING_OP1_CR_ENQ_PTR; 538 540 op1_val |= FIELD_PREP(RING_OP1_CR_ENQ_PTR, enqueue_ptr); 539 541 rh_reg_write(RING_OPERATION1, op1_val); 540 - spin_unlock_irq(&rh->lock); 542 + spin_unlock_irq(&hci->lock); 541 543 542 544 return 0; 543 545 } ··· 635 637 } 636 638 637 639 /* take care to update the software dequeue pointer atomically */ 638 - spin_lock(&rh->lock); 640 + spin_lock(&hci->lock); 639 641 op1_val = rh_reg_read(RING_OPERATION1); 640 642 op1_val &= ~RING_OP1_CR_SW_DEQ_PTR; 641 643 op1_val |= FIELD_PREP(RING_OP1_CR_SW_DEQ_PTR, done_ptr); 642 644 rh_reg_write(RING_OPERATION1, op1_val); 643 - spin_unlock(&rh->lock); 645 + spin_unlock(&hci->lock); 644 646 } 645 647 646 648 static int hci_dma_request_ibi(struct i3c_hci *hci, struct i3c_dev_desc *dev, ··· 821 823 822 824 done: 823 825 /* take care to update the ibi dequeue pointer atomically */ 824 - spin_lock(&rh->lock); 826 + spin_lock(&hci->lock); 825 827 op1_val = rh_reg_read(RING_OPERATION1); 826 828 op1_val &= ~RING_OP1_IBI_DEQ_PTR; 827 829 op1_val |= FIELD_PREP(RING_OP1_IBI_DEQ_PTR, deq_ptr); 828 830 rh_reg_write(RING_OPERATION1, op1_val); 829 - spin_unlock(&rh->lock); 831 + spin_unlock(&hci->lock); 830 832 831 833 /* update the chunk pointer */ 832 834 rh->ibi_chunk_ptr += ibi_chunks;
+1
drivers/i3c/master/mipi-i3c-hci/hci.h
··· 50 50 const struct hci_io_ops *io; 51 51 void *io_data; 52 52 const struct hci_cmd_ops *cmd; 53 + spinlock_t lock; 53 54 atomic_t next_cmd_tid; 54 55 bool irq_inactive; 55 56 u32 caps;
+7 -9
drivers/i3c/master/mipi-i3c-hci/pio.c
··· 123 123 }; 124 124 125 125 struct hci_pio_data { 126 - spinlock_t lock; 127 126 struct hci_xfer *curr_xfer, *xfer_queue; 128 127 struct hci_xfer *curr_rx, *rx_queue; 129 128 struct hci_xfer *curr_tx, *tx_queue; ··· 211 212 return -ENOMEM; 212 213 213 214 hci->io_data = pio; 214 - spin_lock_init(&pio->lock); 215 215 216 216 __hci_pio_init(hci, &size_val); 217 217 ··· 629 631 xfer[i].data_left = xfer[i].data_len; 630 632 } 631 633 632 - spin_lock_irq(&pio->lock); 634 + spin_lock_irq(&hci->lock); 633 635 prev_queue_tail = pio->xfer_queue; 634 636 pio->xfer_queue = &xfer[n - 1]; 635 637 if (pio->curr_xfer) { ··· 643 645 pio_reg_read(INTR_STATUS), 644 646 pio_reg_read(INTR_SIGNAL_ENABLE)); 645 647 } 646 - spin_unlock_irq(&pio->lock); 648 + spin_unlock_irq(&hci->lock); 647 649 return 0; 648 650 } 649 651 ··· 714 716 struct hci_pio_data *pio = hci->io_data; 715 717 int ret; 716 718 717 - spin_lock_irq(&pio->lock); 719 + spin_lock_irq(&hci->lock); 718 720 dev_dbg(&hci->master.dev, "n=%d status=%#x/%#x", n, 719 721 pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE)); 720 722 dev_dbg(&hci->master.dev, "main_status = %#x/%#x", 721 723 readl(hci->base_regs + 0x20), readl(hci->base_regs + 0x28)); 722 724 723 725 ret = hci_pio_dequeue_xfer_common(hci, pio, xfer, n); 724 - spin_unlock_irq(&pio->lock); 726 + spin_unlock_irq(&hci->lock); 725 727 return ret; 726 728 } 727 729 ··· 1014 1016 struct hci_pio_data *pio = hci->io_data; 1015 1017 u32 status; 1016 1018 1017 - spin_lock(&pio->lock); 1019 + spin_lock(&hci->lock); 1018 1020 status = pio_reg_read(INTR_STATUS); 1019 1021 dev_dbg(&hci->master.dev, "PIO_INTR_STATUS %#x/%#x", 1020 1022 status, pio->enabled_irqs); 1021 1023 status &= pio->enabled_irqs | STAT_LATENCY_WARNINGS; 1022 1024 if (!status) { 1023 - spin_unlock(&pio->lock); 1025 + spin_unlock(&hci->lock); 1024 1026 return false; 1025 1027 } 1026 1028 ··· 1056 1058 pio_reg_write(INTR_SIGNAL_ENABLE, pio->enabled_irqs); 1057 1059 dev_dbg(&hci->master.dev, "PIO_INTR_STATUS %#x/%#x", 1058 1060 pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE)); 1059 - spin_unlock(&pio->lock); 1061 + spin_unlock(&hci->lock); 1060 1062 return true; 1061 1063 } 1062 1064