From: Troy Kisky <troy.ki...@boundarydevices.com> Sent: Wednesday, November 01, 2017 4:17 AM >This is better for code locality and should slightly speed up normal >interrupts. > >This also allows PPS clock output to start working for i.mx7. This is because >i.mx7 was already using the limit of 3 interrupts, and needed another. > >Signed-off-by: Troy Kisky <troy.ki...@boundarydevices.com> > >--- > >v2: made this change independent of any devicetree change so that old dtbs >continue to work. > >Continue to register ptp clock if interrupt is not found. > >v3: renamed "ptp" interrupt to "pps" interrupt > >v4: no change >--- > drivers/net/ethernet/freescale/fec.h | 3 +- > drivers/net/ethernet/freescale/fec_main.c | 25 ++++++---- >drivers/net/ethernet/freescale/fec_ptp.c | 82 ++++++++++++++++++-------- >----- > 3 files changed, 65 insertions(+), 45 deletions(-) > >diff --git a/drivers/net/ethernet/freescale/fec.h >b/drivers/net/ethernet/freescale/fec.h >index ede1876a9a19..be56ac1f1ac4 100644 >--- a/drivers/net/ethernet/freescale/fec.h >+++ b/drivers/net/ethernet/freescale/fec.h >@@ -582,12 +582,11 @@ struct fec_enet_private { > u64 ethtool_stats[0]; > }; > >-void fec_ptp_init(struct platform_device *pdev); >+void fec_ptp_init(struct platform_device *pdev, int irq_index);
Seems change irq_index to irq_idx much better. > void fec_ptp_stop(struct platform_device *pdev); void >fec_ptp_start_cyclecounter(struct net_device *ndev); int fec_ptp_set(struct >net_device *ndev, struct ifreq *ifr); int fec_ptp_get(struct net_device *ndev, >struct ifreq *ifr); -uint fec_ptp_check_pps_event(struct fec_enet_private >*fep); > > >/********************************************************** >******************/ > #endif /* FEC_H */ >diff --git a/drivers/net/ethernet/freescale/fec_main.c >b/drivers/net/ethernet/freescale/fec_main.c >index 3dc2d771a222..18fc136817c9 100644 >--- a/drivers/net/ethernet/freescale/fec_main.c >+++ b/drivers/net/ethernet/freescale/fec_main.c >@@ -1602,10 +1602,6 @@ fec_enet_interrupt(int irq, void *dev_id) > ret = IRQ_HANDLED; > complete(&fep->mdio_done); > } >- >- if (fep->ptp_clock) >- if (fec_ptp_check_pps_event(fep)) >- ret = IRQ_HANDLED; > return ret; > } > >@@ -3325,6 +3321,8 @@ fec_probe(struct platform_device *pdev) > struct device_node *np = pdev->dev.of_node, *phy_node; > int num_tx_qs; > int num_rx_qs; >+ char irq_name[8]; >+ int irq_cnt; > > fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); > >@@ -3465,18 +3463,27 @@ fec_probe(struct platform_device *pdev) > if (ret) > goto failed_reset; > >+ irq_cnt = platform_irq_count(pdev); >+ if (irq_cnt > FEC_IRQ_NUM) >+ irq_cnt = FEC_IRQ_NUM; /* last for pps */ >+ else if (irq_cnt == 2) >+ irq_cnt = 1; /* last for pps */ >+ else if (irq_cnt <= 0) >+ irq_cnt = 1; /* Let the for loop fail */ >+ Do some parse on probe function seems uncomfortable...can you encapsulate these code into one api ? Others seems fine to me. Thanks. > if (fep->bufdesc_ex) >- fec_ptp_init(pdev); >+ fec_ptp_init(pdev, irq_cnt); > > ret = fec_enet_init(ndev); > if (ret) > goto failed_init; > >- for (i = 0; i < FEC_IRQ_NUM; i++) { >- irq = platform_get_irq(pdev, i); >+ for (i = 0; i < irq_cnt; i++) { >+ sprintf(irq_name, "int%d", i); >+ irq = platform_get_irq_byname(pdev, irq_name); >+ if (irq < 0) >+ irq = platform_get_irq(pdev, i); > if (irq < 0) { >- if (i) >- break; > ret = irq; > goto failed_irq; > } >diff --git a/drivers/net/ethernet/freescale/fec_ptp.c >b/drivers/net/ethernet/freescale/fec_ptp.c >index 6ebad3fac81d..0f59b0ea1001 100644 >--- a/drivers/net/ethernet/freescale/fec_ptp.c >+++ b/drivers/net/ethernet/freescale/fec_ptp.c >@@ -549,6 +549,37 @@ static void fec_time_keep(struct work_struct *work) > schedule_delayed_work(&fep->time_keep, HZ); } > >+/* This function checks the pps event and reloads the timer compare >+counter. */ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id) >+{ >+ struct net_device *ndev = dev_id; >+ struct fec_enet_private *fep = netdev_priv(ndev); >+ u32 val; >+ u8 channel = fep->pps_channel; >+ struct ptp_clock_event event; >+ >+ val = readl(fep->hwp + FEC_TCSR(channel)); >+ if (val & FEC_T_TF_MASK) { >+ /* Write the next next compare(not the next according the >spec) >+ * value to the register >+ */ >+ writel(fep->next_counter, fep->hwp + FEC_TCCR(channel)); >+ do { >+ writel(val, fep->hwp + FEC_TCSR(channel)); >+ } while (readl(fep->hwp + FEC_TCSR(channel)) & >FEC_T_TF_MASK); >+ >+ /* Update the counter; */ >+ fep->next_counter = (fep->next_counter + fep- >>reload_period) & >+ fep->cc.mask; >+ >+ event.type = PTP_CLOCK_PPS; >+ ptp_clock_event(fep->ptp_clock, &event); >+ return IRQ_HANDLED; >+ } >+ >+ return IRQ_NONE; >+} >+ > /** > * fec_ptp_init > * @ndev: The FEC network adapter >@@ -558,10 +589,12 @@ static void fec_time_keep(struct work_struct *work) > * cyclecounter init routine and exits. > */ > >-void fec_ptp_init(struct platform_device *pdev) >+void fec_ptp_init(struct platform_device *pdev, int irq_index) > { > struct net_device *ndev = platform_get_drvdata(pdev); > struct fec_enet_private *fep = netdev_priv(ndev); >+ int irq; >+ int ret; > > fep->ptp_caps.owner = THIS_MODULE; > snprintf(fep->ptp_caps.name, 16, "fec ptp"); @@ -587,6 +620,20 @@ >void fec_ptp_init(struct platform_device *pdev) > > INIT_DELAYED_WORK(&fep->time_keep, fec_time_keep); > >+ irq = platform_get_irq_byname(pdev, "pps"); >+ if (irq < 0) >+ irq = platform_get_irq(pdev, irq_index); >+ /* Failure to get an irq is not fatal, >+ * only the PTP_CLOCK_PPS clock events should stop >+ */ >+ if (irq >= 0) { >+ ret = devm_request_irq(&pdev->dev, irq, fec_pps_interrupt, >+ 0, pdev->name, ndev); >+ if (ret < 0) >+ dev_warn(&pdev->dev, "request for ptp irq >failed(%d)\n", >+ ret); >+ } >+ > fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev); > if (IS_ERR(fep->ptp_clock)) { > fep->ptp_clock = NULL; >@@ -605,36 +652,3 @@ void fec_ptp_stop(struct platform_device *pdev) > if (fep->ptp_clock) > ptp_clock_unregister(fep->ptp_clock); > } >- >-/** >- * fec_ptp_check_pps_event >- * @fep: the fec_enet_private structure handle >- * >- * This function check the pps event and reload the timer compare counter. >- */ >-uint fec_ptp_check_pps_event(struct fec_enet_private *fep) -{ >- u32 val; >- u8 channel = fep->pps_channel; >- struct ptp_clock_event event; >- >- val = readl(fep->hwp + FEC_TCSR(channel)); >- if (val & FEC_T_TF_MASK) { >- /* Write the next next compare(not the next according the >spec) >- * value to the register >- */ >- writel(fep->next_counter, fep->hwp + FEC_TCCR(channel)); >- do { >- writel(val, fep->hwp + FEC_TCSR(channel)); >- } while (readl(fep->hwp + FEC_TCSR(channel)) & >FEC_T_TF_MASK); >- >- /* Update the counter; */ >- fep->next_counter = (fep->next_counter + fep- >>reload_period) & fep->cc.mask; >- >- event.type = PTP_CLOCK_PPS; >- ptp_clock_event(fep->ptp_clock, &event); >- return 1; >- } >- >- return 0; >-} >-- >2.11.0