@@ -127,6 +127,7 @@ struct oa_tc6 {
u16 tx_credits;
u8 rx_chunks_available;
bool rx_buf_overflow;
+ bool int_flag;
};
enum oa_tc6_header_type {
@@ -1052,6 +1053,14 @@ static int oa_tc6_try_spi_transfer(struct oa_tc6 *tc6)
if (tc6->rx_chunks_available)
spi_length = oa_tc6_prepare_spi_tx_buf_for_rx_chunks(tc6, spi_length);
+ if (tc6->int_flag) {
+ tc6->int_flag = false;
+ if (spi_length == 0) {
+ oa_tc6_add_empty_chunks_to_spi_buf(tc6, 1);
+ spi_length = OA_TC6_CHUNK_SIZE;
+ }
+ }
+
if (spi_length == 0)
break;
@@ -1087,8 +1096,10 @@ static int oa_tc6_spi_thread_handler(void *data)
int ret;
while (likely(!kthread_should_stop())) {
- /* This kthread will be waken up if there is a tx skb */
- wait_event_interruptible(tc6->spi_wq,
+ /* This kthread will be waken up if there is a tx skb or mac-phy
+ * interrupt to perform spi transfer with tx chunks.
+ */
+ wait_event_interruptible(tc6->spi_wq, tc6->int_flag ||
!skb_queue_empty(&tc6->tx_skb_q) ||
kthread_should_stop());
@@ -1123,6 +1134,24 @@ static int oa_tc6_update_buffer_status_from_register(struct oa_tc6 *tc6)
return 0;
}
+static irqreturn_t oa_tc6_macphy_isr(int irq, void *data)
+{
+ struct oa_tc6 *tc6 = data;
+
+ /* MAC-PHY interrupt can occur for the following reasons.
+ * - availability of tx credits if it was 0 before and not reported in
+ * the previous rx footer.
+ * - availability of rx chunks if it was 0 before and not reported in
+ * the previous rx footer.
+ * - extended status event not reported in the previous rx footer.
+ */
+ tc6->int_flag = true;
+ /* Wake spi kthread to perform spi transfer */
+ wake_up_interruptible(&tc6->spi_wq);
+
+ return IRQ_HANDLED;
+}
+
/**
* oa_tc6_start_xmit - function for sending the tx skb which consists ethernet
* frame.
@@ -1247,8 +1276,28 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct net_device *netdev)
sched_set_fifo(tc6->spi_thread);
+ ret = devm_request_irq(&tc6->spi->dev, tc6->spi->irq, oa_tc6_macphy_isr,
+ IRQF_TRIGGER_FALLING, dev_name(&tc6->spi->dev),
+ tc6);
+ if (ret) {
+ dev_err(&tc6->spi->dev, "Failed to request macphy isr %d\n",
+ ret);
+ goto kthread_stop;
+ }
+
+ /* oa_tc6_sw_reset_macphy() function resets and clears the MAC-PHY reset
+ * complete status. IRQ is also asserted on reset completion and it is
+ * remain asserted until MAC-PHY receives a data chunk. So performing an
+ * empty data chunk transmission will deassert the IRQ. Refer section
+ * 7.7 and 9.2.8.8 in the OPEN Alliance specification for more details.
+ */
+ tc6->int_flag = true;
+ wake_up_interruptible(&tc6->spi_wq);
+
return tc6;
+kthread_stop:
+ kthread_stop(tc6->spi_thread);
phy_exit:
oa_tc6_phy_exit(tc6);
return NULL;