[PATCH net v4 2/2] net: fec: Let fec_ptp have its own interrupt routine
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 --- 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); 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 */ + 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; +
RE: [PATCH net v4 2/2] net: fec: Let fec_ptp have its own interrupt routine
From: Troy Kisky 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 > >--- > >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); >+
Re: [PATCH net v4 2/2] net: fec: Let fec_ptp have its own interrupt routine
On 10/31/2017 7:43 PM, Andy Duan wrote: > From: Troy Kisky 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 >> >> --- >> >> 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. no problem >> @@ -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 ? > Do you mean something like irq_cnt = limit_irq(pdev); int limit_irq(struct platform_device *pdev) { int 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;/* At least 1 irq is needed */ return irq_cnt; } ___ Can you give some code to your idea? I don't think I understand. > Others seems fine to me. > Thanks. >
RE: [PATCH net v4 2/2] net: fec: Let fec_ptp have its own interrupt routine
From: Troy Kisky Sent: Thursday, November 02, 2017 1:36 AM >To: Andy Duan ; shawn@linaro.org; >netdev@vger.kernel.org; da...@davemloft.net >Cc: Fabio Estevam ; lzn...@gmail.com; >and...@lunn.ch >Subject: Re: [PATCH net v4 2/2] net: fec: Let fec_ptp have its own interrupt >routine > >On 10/31/2017 7:43 PM, Andy Duan wrote: >> From: Troy Kisky 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 >>> >>> --- >>> >>> 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. > > >no problem > >>> @@ -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 ? >> > > >Do you mean something like > irq_cnt = limit_irq(pdev); > > >int limit_irq(struct platform_device *pdev) { It is better: fec_enet_get_irq_cnt() > int 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;/* At least 1 irq is needed */ > return irq_cnt; >} >___ >Can you give some code to your idea? I don't think I understand. Others seems fine for me.