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

net: ethernet: oa_tc6: implement mac-phy interrupt

The MAC-PHY interrupt is asserted when the following conditions are met.

Receive chunks available - This interrupt is asserted when the previous
data footer had no receive data chunks available and once the receive
data chunks become available for reading. On reception of the first data
header this interrupt will be deasserted.

Transmit chunk credits available - This interrupt is asserted when the
previous data footer indicated no transmit credits available and once the
transmit credits become available for transmitting transmit data chunks.
On reception of the first data header this interrupt will be deasserted.

Extended status event - This interrupt is asserted when the previous data
footer indicated no extended status and once the extended event become
available. In this case the host should read status #0 register to know
the corresponding error/event. On reception of the first data header this
interrupt will be deasserted.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Parthiban Veerasooran <Parthiban.Veerasooran@microchip.com>
Link: https://patch.msgid.link/20240909082514.262942-12-Parthiban.Veerasooran@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Parthiban Veerasooran and committed by
Jakub Kicinski
2c6ce535 d70a0d8f

+51 -1
+51 -1
drivers/net/ethernet/oa_tc6.c
··· 126 126 u16 tx_credits; 127 127 u8 rx_chunks_available; 128 128 bool rx_buf_overflow; 129 + bool int_flag; 129 130 }; 130 131 131 132 enum oa_tc6_header_type { ··· 1065 1064 1066 1065 spi_len = oa_tc6_prepare_spi_tx_buf_for_rx_chunks(tc6, spi_len); 1067 1066 1067 + if (tc6->int_flag) { 1068 + tc6->int_flag = false; 1069 + if (spi_len == 0) { 1070 + oa_tc6_add_empty_chunks_to_spi_buf(tc6, 1); 1071 + spi_len = OA_TC6_CHUNK_SIZE; 1072 + } 1073 + } 1074 + 1068 1075 if (spi_len == 0) 1069 1076 break; 1070 1077 ··· 1107 1098 int ret; 1108 1099 1109 1100 while (likely(!kthread_should_stop())) { 1110 - /* This kthread will be waken up if there is a tx skb */ 1101 + /* This kthread will be waken up if there is a tx skb or mac-phy 1102 + * interrupt to perform spi transfer with tx chunks. 1103 + */ 1111 1104 wait_event_interruptible(tc6->spi_wq, tc6->waiting_tx_skb || 1105 + tc6->int_flag || 1112 1106 kthread_should_stop()); 1113 1107 1114 1108 if (kthread_should_stop()) ··· 1143 1131 value); 1144 1132 1145 1133 return 0; 1134 + } 1135 + 1136 + static irqreturn_t oa_tc6_macphy_isr(int irq, void *data) 1137 + { 1138 + struct oa_tc6 *tc6 = data; 1139 + 1140 + /* MAC-PHY interrupt can occur for the following reasons. 1141 + * - availability of tx credits if it was 0 before and not reported in 1142 + * the previous rx footer. 1143 + * - availability of rx chunks if it was 0 before and not reported in 1144 + * the previous rx footer. 1145 + * - extended status event not reported in the previous rx footer. 1146 + */ 1147 + tc6->int_flag = true; 1148 + /* Wake spi kthread to perform spi transfer */ 1149 + wake_up_interruptible(&tc6->spi_wq); 1150 + 1151 + return IRQ_HANDLED; 1146 1152 } 1147 1153 1148 1154 /** ··· 1290 1260 1291 1261 sched_set_fifo(tc6->spi_thread); 1292 1262 1263 + ret = devm_request_irq(&tc6->spi->dev, tc6->spi->irq, oa_tc6_macphy_isr, 1264 + IRQF_TRIGGER_FALLING, dev_name(&tc6->spi->dev), 1265 + tc6); 1266 + if (ret) { 1267 + dev_err(&tc6->spi->dev, "Failed to request macphy isr %d\n", 1268 + ret); 1269 + goto kthread_stop; 1270 + } 1271 + 1272 + /* oa_tc6_sw_reset_macphy() function resets and clears the MAC-PHY reset 1273 + * complete status. IRQ is also asserted on reset completion and it is 1274 + * remain asserted until MAC-PHY receives a data chunk. So performing an 1275 + * empty data chunk transmission will deassert the IRQ. Refer section 1276 + * 7.7 and 9.2.8.8 in the OPEN Alliance specification for more details. 1277 + */ 1278 + tc6->int_flag = true; 1279 + wake_up_interruptible(&tc6->spi_wq); 1280 + 1293 1281 return tc6; 1294 1282 1283 + kthread_stop: 1284 + kthread_stop(tc6->spi_thread); 1295 1285 phy_exit: 1296 1286 oa_tc6_phy_exit(tc6); 1297 1287 return NULL;