net: convert mvneta to build_skb()
Subsystems (3)
PATCH 1/1 net: convert mvneta to build_skb()
Quoted 1 line
From
0180a5e651dd771de18bf2c031ecfe7bb4c88d3eMon Sep 17 00:00:00 2001
From: Willy Tarreau <[email protected]>
Date: Sat, 15 Jun 2013 23:25:15 +0200
Subject: [PATCH] net: convert mvneta to build_skb()
We store the frag_size in the mvneta_port struct. In practice we'd need a single bit to know how to free the data, but since we need the size to call build_skb() anyway, let's store the full size.
With this patch, I observed a reproducible 2% performance improvement on HTTP-based benchmarks.
--- drivers/net/ethernet/marvell/mvneta.c | 71 ++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 21 deletions(-)
drivers/net/ethernet/marvell/mvneta.c +50 -21
@@ -225,6 +225,7 @@ struct mvneta_stats {struct mvneta_port {int pkt_size; +unsigned int frag_size;void __iomem *base;struct mvneta_rx_queue *rxqs;struct mvneta_tx_queue *txqs;
@@ -1259,22 +1260,33 @@ static int mvneta_rx_refill(struct mvneta_port *pp, {dma_addr_t phys_addr; -struct sk_buff *skb; - - skb =netdev_alloc_skb (pp->dev, pp->pkt_size); -if (!skb) +void *data; +unsigned int skb_size; + + skb_size =SKB_DATA_ALIGN (pp->pkt_size +MVNETA_MH_SIZE +NET_SKB_PAD ) + +SKB_DATA_ALIGN (sizeof (struct skb_shared_info )); +if (skb_size <=PAGE_SIZE ) { + data =netdev_alloc_frag (skb_size); + pp->frag_size = skb_size; + }else { + data =kmalloc (skb_size,GFP_ATOMIC ); + pp->frag_size =0 ; + } +if (!data)return -ENOMEM ; - phys_addr =dma_map_single (pp->dev->dev.parent, skb->head, + phys_addr =dma_map_single (pp->dev->dev.parent, data,MVNETA_RX_BUF_SIZE (pp->pkt_size),DMA_FROM_DEVICE );if (unlikely (dma_mapping_error (pp->dev->dev.parent, phys_addr))) { -dev_kfree_skb (skb); +if (pp->frag_size) +put_page (virt_to_head_page (data)); +else +kfree (data);return -ENOMEM ; } -mvneta_rx_desc_fill (rx_desc, phys_addr, (u32 )skb); - +mvneta_rx_desc_fill (rx_desc, phys_addr, (u32 )data);return 0 ; }
@@ -1328,9 +1340,13 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp, rx_done =mvneta_rxq_busy_desc_num_get (pp, rxq);for (i =0 ; i < rxq->size; i++) {struct mvneta_rx_desc *rx_desc = rxq->descs + i; -struct sk_buff *skb = (struct sk_buff *)rx_desc->buf_cookie; +void *data = (void *)rx_desc->buf_cookie; + +if (pp->frag_size) +put_page (virt_to_head_page (data)); +else +kfree (data); -dev_kfree_skb_any (skb);dma_unmap_single (pp->dev->dev.parent, rx_desc->buf_phys_addr, rx_desc->data_size,DMA_FROM_DEVICE ); }
@@ -1359,6 +1375,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,while (rx_done < rx_todo) {struct mvneta_rx_desc *rx_desc =mvneta_rxq_next_desc_get (rxq);struct sk_buff *skb; +unsigned char *data;u32 rx_status;int rx_bytes, err;
@@ -1366,14 +1383,14 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, rx_done++; rx_filled++; rx_status = rx_desc->status; - skb = (struct sk_buff *)rx_desc->buf_cookie; + data = (unsigned char *)rx_desc->buf_cookie;if (!mvneta_rxq_desc_is_first_last (rx_desc) || - (rx_status &MVNETA_RXD_ERR_SUMMARY )) { + (rx_status &MVNETA_RXD_ERR_SUMMARY ) || + !(skb =build_skb (data, pp->frag_size))) { dev->stats.rx_errors++;mvneta_rx_error (pp, rx_desc); -mvneta_rx_desc_fill (rx_desc, rx_desc->buf_phys_addr, - (u32 )skb); +/* leave the descriptor untouched */ continue ; }
@@ -1388,7 +1405,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,u64_stats_update_end (&pp->rx_stats.syncp);/* Linux processing */ -skb_reserve (skb,MVNETA_MH_SIZE ); +skb_reserve (skb,MVNETA_MH_SIZE +NET_SKB_PAD );skb_put (skb, rx_bytes); skb->protocol =eth_type_trans (skb, dev);
@@ -1905,12 +1922,21 @@ static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,int i;for (i =0 ; i < num; i++) { -struct sk_buff *skb; +void *data;struct mvneta_rx_desc *rx_desc;unsigned long phys_addr; +unsigned int skb_size; - skb =dev_alloc_skb (pp->pkt_size); -if (!skb) { + skb_size =SKB_DATA_ALIGN (pp->pkt_size +MVNETA_MH_SIZE +NET_SKB_PAD ) + +SKB_DATA_ALIGN (sizeof (struct skb_shared_info )); +if (skb_size <=PAGE_SIZE ) { + data =netdev_alloc_frag (skb_size); + pp->frag_size = skb_size; + }else { + data =kmalloc (skb_size,GFP_ATOMIC ); + pp->frag_size =0 ; + } +if (!data) {netdev_err (dev,"%s:rxq %d, %d of %d buffs filled\n" , __func__, rxq->id, i, num);break ;
@@ -1918,15 +1944,18 @@ static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq, rx_desc = rxq->descs + i;memset (rx_desc,0 ,sizeof (struct mvneta_rx_desc )); - phys_addr =dma_map_single (dev->dev.parent, skb->head, + phys_addr =dma_map_single (dev->dev.parent, data,MVNETA_RX_BUF_SIZE (pp->pkt_size),DMA_FROM_DEVICE );if (unlikely (dma_mapping_error (dev->dev.parent, phys_addr))) { -dev_kfree_skb (skb); +if (pp->frag_size) +put_page (virt_to_head_page (data)); +else +kfree (data);break ; } -mvneta_rx_desc_fill (rx_desc, phys_addr, (u32 )skb); +mvneta_rx_desc_fill (rx_desc, phys_addr, (u32 )data); }/* Add this number of RX descriptors as non occupied (ready to
Signature · 1 line
1.7.12.2.21.g234cd45.dirty
David Miller
maintainerFrom: Willy Tarreau <[email protected]>
Date: Thu, 4 Jul 2013 19:35:52 +0200
Quoted 5 lines
From
0180a5e651dd771de18bf2c031ecfe7bb4c88d3eMon Sep 17 00:00:00 2001
From: Willy Tarreau <[email protected]>
Date: Sat, 15 Jun 2013 23:25:15 +0200
Subject: [PATCH] net: convert mvneta tobuild_skb()
Quoted 8 lines
We store the
frag_sizein themvneta_portstruct. In practice we'd need a single bit to know how to free the data, but since we need the size to callbuild_skb()anyway, let's store the full size.With this patch, I observed a reproducible 2% performance improvement on HTTP-based benchmarks.
Signed-off-by Willy Tarreau <[email protected]>
The net-next tree is closed now that the merge window is open, therefore submissions such as this are not appropriate at this time.
Please resubmit this when net-next opens again, an event which I will clearly announce here on netdev.
Thanks.
Quoted 15 lines · David Miller
From: Willy Tarreau <[email protected]>
Date: Thu, 4 Jul 2013 19:35:52 +0200Quoted 12 lines
From
0180a5e651dd771de18bf2c031ecfe7bb4c88d3eMon Sep 17 00:00:00 2001
From: Willy Tarreau <[email protected]>
Date: Sat, 15 Jun 2013 23:25:15 +0200
Subject: [PATCH] net: convert mvneta tobuild_skb()We store the
frag_sizein themvneta_portstruct. In practice we'd need a single bit to know how to free the data, but since we need the size to callbuild_skb()anyway, let's store the full size.With this patch, I observed a reproducible 2% performance improvement on HTTP-based benchmarks.
Quoted 7 lines
Quoted 1 line
Signed-off-by Willy Tarreau <[email protected]>The net-next tree is closed now that the merge window is open, therefore submissions such as this are not appropriate at this time.
Please resubmit this when net-next opens again, an event which I will clearly announce here on netdev.
OK no problem, thanks.
Willy
Dear Willy Tarreau,
Quoted 25 lines · Willy Tarreau
From
0180a5e651dd771de18bf2c031ecfe7bb4c88d3eMon Sep 17 00:00:00 2001
From: Willy Tarreau <[email protected]>
Date: Sat, 15 Jun 2013 23:25:15 +0200
Subject: [PATCH] net: convert mvneta tobuild_skb()We store the
frag_sizein themvneta_portstruct. In practice we'd need a single bit to know how to free the data, but since we need the size to callbuild_skb()anyway, let's store the full size.With this patch, I observed a reproducible 2% performance improvement on HTTP-based benchmarks.
Signed-off-by Willy Tarreau <[email protected]>Cc Thomas Petazzoni <[email protected]>Cc Gregory CLEMENT <[email protected]>Cc Eric Dumazet <[email protected]>--- drivers/net/ethernet/marvell/mvneta.c | 71 ++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 21 deletions(-)drivers/net/ethernet/marvell/mvneta.c +0
-0
drivers/net/ethernet/marvell/mvneta.c struct mvneta_stats { · line 231
Quoted 7 lines
drivers/net/ethernet/marvell/mvneta.c +1
-0@@ -225,6 +225,7 @@ struct mvneta_stats {struct mvneta_port {int pkt_size; +unsigned int frag_size;void __iomem *base;struct mvneta_rx_queue *rxqs;struct mvneta_tx_queue *txqs;
Thanks Willy. Sorry for asking such a stupid question, but I'm not very familiar with how this mechanism works. Can you explain why a single 'frag_size' field per port is sufficient? My concern is that this frag_size seems to be a per-packet information, but we have potentially multiple packets being received, and multiple RX queues. Is one single 'frag_size' per network interface sufficient?
For example, in mvneta_rx_refill(), you store the skb_size in pp->frag_size, and then you later re-use it in mvneta_rxq_drop_pkts. What guarantees you that mvneta_rx_refill() hasn't be called in the mean time for a different packet, in a different rxq, for the same network interface, and the value of pp->frag_size has been overridden?
Again, sorry for this stupid question, this is maybe just some basic networking knowledge that I'm missing here, but I thought it would be good to ask anyway.
Thanks!
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Hi Thomas,
Quoted 4 lines · Thomas Petazzoni
Quoted 4 lines
drivers/net/ethernet/marvell/mvneta.c +0
-0@@ -225,6 +225,7 @@ struct mvneta_stats {
Quoted 13 lines
drivers/net/ethernet/marvell/mvneta.c struct mvneta_stats { · line 231
Quoted 6 lines
drivers/net/ethernet/marvell/mvneta.c +1
-0struct mvneta_port {int pkt_size; +unsigned int frag_size;void __iomem *base;struct mvneta_rx_queue *rxqs;struct mvneta_tx_queue *txqs;Thanks Willy. Sorry for asking such a stupid question, but I'm not very familiar with how this mechanism works. Can you explain why a single '
frag_size' field per port is sufficient? My concern is that thisfrag_sizeseems to be a per-packet information, but we have potentially multiple packets being received, and multiple RX queues. Is one single 'frag_size' per network interface sufficient?
I had the exact same question when Eric sent me an experimental patch to do this on mv64xxx_eth a few months ago. Then I checked how the frag_size is computed. As you can see below, it does not depend on a per-packet size but on a per-port size which is in fact the MTU ("pkt_size" is the misleading part here) :
skb_size = SKB_DATA_ALIGN(pp->pkt_size + MVNETA_MH_SIZE + NET_SKB_PAD) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));So if skb_size depends solely on pp (struct mvneta_port), then it makes sense to have frag_size stored at the same place.
In practice we don't really need to store the frag_size in the struct, we just need to know if the data were allocated using netdev_alloc_frag() or kmalloc() to know how to free them. So a single bit would be enough, and I thought about just doing a +1 on the pointer when we need to free using kmalloc(). But that would add unneeded extra work in the fast path to fix the pointers. And since we need to pass frag_size to build_skb() it was a reasonable solution in my opinion.
Quoted 5 lines
For example, in
mvneta_rx_refill(), you store theskb_sizeinpp->frag_size, and then you later re-use it inmvneta_rxq_drop_pkts. What guarantees you thatmvneta_rx_refill()hasn't be called in the mean time for a different packet, in a different rxq, for the same network interface, and the value ofpp->frag_sizehas been overridden?
It's not a problem since the refill() applies pp->pkt_size which doesn't change between calls. It's only changed in mvneta_change_mtu() which first stops the device. So I think it's safe.
Quoted 3 lines
Again, sorry for this stupid question, this is maybe just some basic networking knowledge that I'm missing here, but I thought it would be good to ask anyway.
No it's neither stupid nor basic. It's a bit tricky to understand first but it looks really nice once you get it. I think I will study the ability to use +/-1 on the pointer and see if we can get rid of frag_size (eg: tg3 doesn't store it).
Hoping this clarifies some points,
Willy
Dear Willy Tarreau,
Quoted 19 lines · Willy Tarreau
Quoted 6 lines
Thanks Willy. Sorry for asking such a stupid question, but I'm not very familiar with how this mechanism works. Can you explain why a single '
frag_size' field per port is sufficient? My concern is that thisfrag_sizeseems to be a per-packet information, but we have potentially multiple packets being received, and multiple RX queues. Is one single 'frag_size' per network interface sufficient?I had the exact same question when Eric sent me an experimental patch to do this on
mv64xxx_etha few months ago. Then I checked how thefrag_sizeis computed. As you can see below, it does not depend on a per-packet size but on a per-port size which is in fact the MTU ("pkt_size" is the misleading part here) :skb_size = SKB_DATA_ALIGN(pp->pkt_size + MVNETA_MH_SIZE + NET_SKB_PAD) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info));So if
skb_sizedepends solely on pp (structmvneta_port), then it makes sense to havefrag_sizestored at the same place.
Quoted 7 lines
In practice we don't really need to store the
frag_sizein the struct, we just need to know if the data were allocated usingnetdev_alloc_frag()orkmalloc()to know how to free them. So a single bit would be enough, and I thought about just doing a +1 on the pointer when we need to free usingkmalloc(). But that would add unneeded extra work in the fast path to fix the pointers. And since we need to passfrag_sizetobuild_skb()it was a reasonable solution in my opinion.
Aah, okay makes sense. So now, the question that comes up is why this skb_size calculation is done in every call of mvneta_rx_refill() ? It should be computed once, at the same time pkt_size is calculated, and stored in the mvneta_port structure? Then you just need to test whether it is smaller or larger than PAGE_SIZE to decide whether to use netdev_alloc_frag() vs. kmalloc().
I.e, I would turn all the:
if (pp->frag_size) ... else ...
into:
if (pp->skb_size <= PAGE_SIZE) ... else ...
Of course, you can always hide this test behind a small macro or inline function, to make it something like:
if (mvneta_uses_small_skbs(pp)) ... else ...
A better name than mvneta_uses_small_skbs() would of course be useful.
Quoted 9 lines
Quoted 5 lines
For example, in
mvneta_rx_refill(), you store theskb_sizeinpp->frag_size, and then you later re-use it inmvneta_rxq_drop_pkts. What guarantees you thatmvneta_rx_refill()hasn't be called in the mean time for a different packet, in a different rxq, for the same network interface, and the value ofpp->frag_sizehas been overridden?It's not a problem since the
refill()appliespp->pkt_sizewhich doesn't change between calls. It's only changed inmvneta_change_mtu()which first stops the device. So I think it's safe.
Yeah, sure, now that I see that pp->frag_size is constant for a given MTU configuration, it looks safe. But I find the current code that retests and reassigns pp->frag_size at every call of rxq_refill() to be very confusing.
Thanks!
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Quoted 22 lines · Thomas Petazzoni
Quoted 7 lines
In practice we don't really need to store the
frag_sizein the struct, we just need to know if the data were allocated usingnetdev_alloc_frag()orkmalloc()to know how to free them. So a single bit would be enough, and I thought about just doing a +1 on the pointer when we need to free usingkmalloc(). But that would add unneeded extra work in the fast path to fix the pointers. And since we need to passfrag_sizetobuild_skb()it was a reasonable solution in my opinion.Aah, okay makes sense. So now, the question that comes up is why this
skb_sizecalculation is done in every call ofmvneta_rx_refill()? It should be computed once, at the same timepkt_sizeis calculated, and stored in themvneta_portstructure? Then you just need to test whether it is smaller or larger thanPAGE_SIZEto decide whether to usenetdev_alloc_frag()vs.kmalloc().I.e, I would turn all the:
if (pp->frag_size) ... else ...
Quoted 6 lines
into:
if (pp->skb_size <= PAGE_SIZE) ... else ...
I was concerned by the same thing and saw that tg3 does the same. Then I realized that we're only using constants here, so there isn't much calculation (basically it's skb_size = pkt_size + something). However it would probably make the code less confusing, especially if we were two different readers concerned about this frag_size not changing per packet.
Quoted 16 lines
Of course, you can always hide this test behind a small macro or inline function, to make it something like:
if (mvneta_uses_small_skbs(pp)) ... else ...A better name than
mvneta_uses_small_skbs()would of course be useful.Quoted 6 lines
Quoted 5 lines
For example, in
mvneta_rx_refill(), you store theskb_sizeinpp->frag_size, and then you later re-use it inmvneta_rxq_drop_pkts. What guarantees you thatmvneta_rx_refill()hasn't be called in the mean time for a different packet, in a different rxq, for the same network interface, and the value ofpp->frag_sizehas been overridden?
Quoted 8 lines
Quoted 3 lines
It's not a problem since the
refill()appliespp->pkt_sizewhich doesn't change between calls. It's only changed inmvneta_change_mtu()which first stops the device. So I think it's safe.Yeah, sure, now that I see that
pp->frag_sizeis constant for a given MTU configuration, it looks safe. But I find the current code that retests and reassignspp->frag_sizeat every call ofrxq_refill()to be very confusing.
Yes I agree. I think I'll experiment with the +/-1 on the pointer to see the impact on the rest of the code, because probably that with a few macros we could make that more transparent this way.
Best regards,
Willy
Dear Willy Tarreau,
Quoted 5 lines · Willy Tarreau
From
0180a5e651dd771de18bf2c031ecfe7bb4c88d3eMon Sep 17 00:00:00 2001
From: Willy Tarreau <[email protected]>
Date: Sat, 15 Jun 2013 23:25:15 +0200
Subject: [PATCH] net: convert mvneta tobuild_skb()
Quoted 8 lines
We store the
frag_sizein themvneta_portstruct. In practice we'd need a single bit to know how to free the data, but since we need the size to callbuild_skb()anyway, let's store the full size.With this patch, I observed a reproducible 2% performance improvement on HTTP-based benchmarks.
Signed-off-by Willy Tarreau <[email protected]>
3.11-rc1 is now out. Do you intend to resend an updated version of your patches, according to the discussions we had?
Thanks!
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Hi Thomas,
Quoted 12 lines · Thomas Petazzoni
Dear Willy Tarreau,
Quoted 9 lines · Willy Tarreau
From
0180a5e651dd771de18bf2c031ecfe7bb4c88d3eMon Sep 17 00:00:00 2001
From: Willy Tarreau <[email protected]>
Date: Sat, 15 Jun 2013 23:25:15 +0200
Subject: [PATCH] net: convert mvneta tobuild_skb()We store the
frag_sizein themvneta_portstruct. In practice we'd need a single bit to know how to free the data, but since we need the size to callbuild_skb()anyway, let's store the full size.
Quoted 7 lines
Quoted 4 lines
With this patch, I observed a reproducible 2% performance improvement on HTTP-based benchmarks.
Signed-off-by Willy Tarreau <[email protected]>3.11-rc1 is now out. Do you intend to resend an updated version of your patches, according to the discussions we had?
Yes I'll do. This week-end I have tried to pre-compute the frag_size. The performance did not change, nor the driver size, but the code is cleaner and more readable (in my opinion).
I have noticed your recent patches to support big-endian, and since we risk to get conflicts by touching similar areas, I guess you'll prefer to have a clean patch series that applies well.
I'm still checking a little bit what can be easily improved (if any) and will resend.
Best regards,
Willy
Dear Willy Tarreau,
Quoted 6 lines · Willy Tarreau
Quoted 2 lines
3.11-rc1 is now out. Do you intend to resend an updated version of your patches, according to the discussions we had?
Yes I'll do. This week-end I have tried to pre-compute the
frag_size. The performance did not change, nor the driver size, but the code is cleaner and more readable (in my opinion).
Ok.
Quoted 3 lines
I have noticed your recent patches to support big-endian, and since we risk to get conflicts by touching similar areas, I guess you'll prefer to have a clean patch series that applies well.
The big-endian support is pretty light in terms of driver changes, so if there are conflicts, they should be easy to solve.
Quoted 2 lines
I'm still checking a little bit what can be easily improved (if any) and will resend.
Excellent, thanks!
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
[ removing Eric from Cc who's probably not interested by this ]
Quoted 2 lines · Thomas Petazzoni
The big-endian support is pretty light in terms of driver changes, so if there are conflicts, they should be easy to solve.
I agree.
BTW, I'm still having the patch to re-enable phy-polling at boot in my queue. Last time I tried without it I still only had eth0 working. I completely forgot about this one. Since I did it blindly, I have no way to verify if what I've done is necessary according to the specs. But I'm quite sure that the NICs that are not enabled by the boot loaders don't work.
If you want, I'll resend it to you at the same time.
Best regards,
Willy
Dear Willy Tarreau,
Quoted 6 lines · Willy Tarreau
Quoted 2 lines · Thomas Petazzoni
The big-endian support is pretty light in terms of driver changes, so if there are conflicts, they should be easy to solve.
I agree.
Quoted 8 lines
BTW, I'm still having the patch to re-enable phy-polling at boot in my queue. Last time I tried without it I still only had eth0 working. I completely forgot about this one. Since I did it blindly, I have no way to verify if what I've done is necessary according to the specs. But I'm quite sure that the NICs that are not enabled by the boot loaders don't work.
If you want, I'll resend it to you at the same time.
I still believe this is not the right fix, but unfortunately, I haven't had the time to work on what would be the right fix. Hardware PHY polling has been intentionally disabled, and the driver should work without, since the PHY polling is done in software by the phylib.
Best regards,
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Hello Thomas, Willy,
2013/7/15 Thomas Petazzoni <[email protected]>:
Quoted 17 lines
Dear Willy Tarreau,
Quoted 13 lines · Willy Tarreau
Quoted 2 lines · Thomas Petazzoni
The big-endian support is pretty light in terms of driver changes, so if there are conflicts, they should be easy to solve.
I agree.
BTW, I'm still having the patch to re-enable phy-polling at boot in my queue. Last time I tried without it I still only had eth0 working. I completely forgot about this one. Since I did it blindly, I have no way to verify if what I've done is necessary according to the specs. But I'm quite sure that the NICs that are not enabled by the boot loaders don't work.
Quoted 6 lines
Quoted 1 line
If you want, I'll resend it to you at the same time.
I still believe this is not the right fix, but unfortunately, I haven't had the time to work on what would be the right fix. Hardware PHY polling has been intentionally disabled, and the driver should work without, since the PHY polling is done in software by the phylib.
You may now be able to use the PHY interrupt bit from your MAC interrupt handler and call phy_mac_interrupt() provided by libphy. I added it specifically to be able to use PHY link interrupts connected to the MAC.
--
Florian
Hi Florian,
Quoted 9 lines · Florian Fainelli
Quoted 4 lines
I still believe this is not the right fix, but unfortunately, I haven't had the time to work on what would be the right fix. Hardware PHY polling has been intentionally disabled, and the driver should work without, since the PHY polling is done in software by the phylib.
You may now be able to use the PHY interrupt bit from your MAC interrupt handler and call
phy_mac_interrupt()provided by libphy. I added it specifically to be able to use PHY link interrupts connected to the MAC.
Thanks for the tip. I'm not seeing any interrupt when I plug/unplug a cable, so maybe we first need to set a specific bit in the interrupt mask to enable interrupt delivery on link state change prior to this.
Regards,
Willy
Dear Florian Fainelli,
Quoted 9 lines · Florian Fainelli
Quoted 4 lines
I still believe this is not the right fix, but unfortunately, I haven't had the time to work on what would be the right fix. Hardware PHY polling has been intentionally disabled, and the driver should work without, since the PHY polling is done in software by the phylib.
You may now be able to use the PHY interrupt bit from your MAC interrupt handler and call
phy_mac_interrupt()provided by libphy. I added it specifically to be able to use PHY link interrupts connected to the MAC.
Right, but the MAC feature in question makes the MAC directly talks to the PHY to configure it, completely bypassing the entire libphy logic. I am not sure how to handle this together with libphy.
Thomas
Signature · 4 lines
Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com
Hello Thomas,
2013/7/15 Thomas Petazzoni <[email protected]>:
Quoted 9 lines
Dear Florian Fainelli,
Quoted 5 lines · Florian Fainelli
Quoted 4 lines
I still believe this is not the right fix, but unfortunately, I haven't had the time to work on what would be the right fix. Hardware PHY polling has been intentionally disabled, and the driver should work without, since the PHY polling is done in software by the phylib.
Quoted 8 lines
Quoted 4 lines
You may now be able to use the PHY interrupt bit from your MAC interrupt handler and call
phy_mac_interrupt()provided by libphy. I added it specifically to be able to use PHY link interrupts connected to the MAC.Right, but the MAC feature in question makes the MAC directly talks to the PHY to configure it, completely bypassing the entire libphy logic. I am not sure how to handle this together with libphy.
Then you might just replace the default libphy with your PHY state machine and manage it from within the mvneta driver. This is something less usual but libphy still allows that.
--
Florian