Netdev List
 help / color / mirror / Atom feed
* [patch net-next] liquidio CN23XX: bitwise vs logical AND typo
From: Dan Carpenter @ 2016-11-18 11:47 UTC (permalink / raw)
  To: Derek Chickles, Raghu Vatsavayi
  Cc: Satanand Burla, Felix Manlunas, netdev, kernel-janitors

We obviously intended a bitwise AND here, not a logical one.

Fixes: 8c978d059224 ("liquidio CN23XX: Mailbox support")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
index 5309384..73696b42 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
@@ -301,7 +301,7 @@ int octeon_mbox_process_message(struct octeon_mbox *mbox)
 		       sizeof(struct octeon_mbox_cmd));
 		if (!mbox_cmd.msg.s.resp_needed) {
 			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVED;
-			if (!(mbox->state &&
+			if (!(mbox->state &
 			      OCTEON_MBOX_STATE_RESPONSE_PENDING))
 				mbox->state = OCTEON_MBOX_STATE_IDLE;
 			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);

^ permalink raw reply related

* Re: [PATCH net-next] cadence: Add hardware PTP support.
From: Harini Katakam @ 2016-11-18 11:44 UTC (permalink / raw)
  To: Rafal Ozieblo
  Cc: Nicolas Ferre, Andrei Pistirica, netdev,
	linux-kernel@vger.kernel.org
In-Reply-To: <1479466028-29914-1-git-send-email-rafalo@cadence.com>

Hi Rafal

I'm still comparing the full solution but just a couple of things first:
<snip>
> @@ -876,6 +964,17 @@ static int gem_rx(struct macb *bp, int budget)
>                 bp->stats.rx_packets++;
>                 bp->stats.rx_bytes += skb->len;
>
> +#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
> +               if (bp->ptp_hw_support) {
> +                       struct timespec64 ts;
> +
> +                       if (MACB_BFEXT(DMA_RX_TS_VALID, desc->addr)) {
> +                               macb_hw_timestamp(bp, desc->dma_desc_ts_1, desc->dma_desc_ts_2, &ts);
> +                               skb_hwtstamps(skb)->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
> +                       }
> +               }
> +#endif
> +

I've had to read PTP event registers for upper part of seconds timestamp
in addition to the descriptor (since descriptor only has 5 bits of seconds TS).
I don't know which version of the IP you use - it could be different.
Please let me know so that I can check the spec.
Same with tx timestamp of course.

<snip>
> @@ -1195,6 +1297,87 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
>                                 queue_writel(queue, ISR, MACB_BIT(HRESP));
>                 }
>
> +#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
> +               if (status & MACB_BIT(PTP_DELAY_REQ_FRAME_RECEIVED)) {
> +                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> +                               queue_writel(queue, ISR, MACB_BIT(PTP_DELAY_REQ_FRAME_RECEIVED));
> +                       if (macb_ptp_time_frame_rx_get(bp, &ts) != 0) {
> +                               ts.tv_sec = 0;
> +                               ts.tv_nsec = 0;
> +                       }
> +                       macb_ptp_event(bp, &ts);
> +               }
> +
> +               if (status & MACB_BIT(PTP_SYNC_FRAME_RECEIVED)) {
> +                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> +                               queue_writel(queue, ISR, MACB_BIT(PTP_SYNC_FRAME_RECEIVED));
> +                       if (macb_ptp_time_frame_rx_get(bp, &ts) != 0) {
> +                               ts.tv_sec = 0;
> +                               ts.tv_nsec = 0;
> +                       }
> +                       macb_ptp_event(bp, &ts);
> +               }
> +
> +               if (status & MACB_BIT(PTP_DELAY_REQ_FRAME_TRANSMITTED)) {
> +                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> +                               queue_writel(queue, ISR, MACB_BIT(PTP_DELAY_REQ_FRAME_TRANSMITTED));
> +                       if (macb_ptp_time_frame_tx_get(bp, &ts) != 0) {
> +                               ts.tv_sec = 0;
> +                               ts.tv_nsec = 0;
> +                       }
> +                       macb_ptp_event(bp, &ts);
> +               }
> +
> +               if (status & MACB_BIT(PTP_SYNC_FRAME_TRANSMITTED)) {
> +                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> +                               queue_writel(queue, ISR, MACB_BIT(PTP_SYNC_FRAME_TRANSMITTED));
> +                       if (macb_ptp_time_frame_tx_get(bp, &ts) != 0) {
> +                               ts.tv_sec = 0;
> +                               ts.tv_nsec = 0;
> +                       }
> +                       macb_ptp_event(bp, &ts);
> +               }
> +
> +               if (status & MACB_BIT(PTP_PDELAY_REQ_FRAME_RECEIVED)) {
> +                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> +                               queue_writel(queue, ISR, MACB_BIT(PTP_PDELAY_REQ_FRAME_RECEIVED));
> +                       if (macb_ptp_time_peer_frame_rx_get(bp, &ts) != 0) {
> +                               ts.tv_sec = 0;
> +                               ts.tv_nsec = 0;
> +                       }
> +                       macb_ptp_event(bp, &ts);
> +               }
> +
> +               if (status & MACB_BIT(PTP_PDELAY_RESP_FRAME_RECEIVED)) {
> +                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> +                               queue_writel(queue, ISR, MACB_BIT(PTP_PDELAY_RESP_FRAME_RECEIVED));
> +                       if (macb_ptp_time_peer_frame_rx_get(bp, &ts) != 0) {
> +                               ts.tv_sec = 0;
> +                               ts.tv_nsec = 0;
> +                       }
> +                       macb_ptp_event(bp, &ts);
> +               }
> +
> +               if (status & MACB_BIT(PTP_PDELAY_REQ_FRAME_TRANSMITTED)) {
> +                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> +                               queue_writel(queue, ISR, MACB_BIT(PTP_PDELAY_REQ_FRAME_TRANSMITTED));
> +                       if (macb_ptp_time_peer_frame_tx_get(bp, &ts) != 0) {
> +                               ts.tv_sec = 0;
> +                               ts.tv_nsec = 0;
> +                       }
> +                       macb_ptp_event(bp, &ts);
> +               }
> +
> +               if (status & MACB_BIT(PTP_PDELAY_RESP_FRAME_TRANSMITTED)) {
> +                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
> +                               queue_writel(queue, ISR, MACB_BIT(PTP_PDELAY_RESP_FRAME_TRANSMITTED));
> +                       if (macb_ptp_time_peer_frame_tx_get(bp, &ts) != 0) {
> +                               ts.tv_sec = 0;
> +                               ts.tv_nsec = 0;
> +                       }
> +                       macb_ptp_event(bp, &ts);
> +               }
> +#endif

I'm not sure of your application and why this is necessary.
Can you please check Andrei's patches and mine and
Richard Cochran's comments?
I use linuxptp to test.

Regards,
Harini

^ permalink raw reply

* RE: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Rafal Ozieblo @ 2016-11-18 11:28 UTC (permalink / raw)
  To: Harini Katakam
  Cc: Nicolas Ferre, harini.katakam@xilinx.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <CAFcVECK=tUrfz=ejKHLimVU3uX7GgBNLrObjSP=87RmV4CSLkw@mail.gmail.com>

>Hi Rafal,                                  
>                                           
>On Fri, Nov 18, 2016 at 2:29 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>> Hello,                                                                  
>>                                                                         
>>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com]             
>>> Sent: 18 listopada 2016 05:30                                          
>>> To: Rafal Ozieblo                                                      
>>> Cc: Nicolas Ferre; harini.katakam@xilinx.com; netdev@vger.kernel.org;  
>>> linux-kernel@vger.kernel.org                                           
>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support  
>>> for GEM                                                                
>>>                                                                        
>>> Hi Rafal,                                                              
>>>                                                                        
>>> On Thu, Nov 17, 2016 at 7:05 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>>> > -----Original Message-----                                              
>>> > From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]                    
>>> > Sent: 17 listopada 2016 14:29                                           
>>> > To: Harini Katakam; Rafal Ozieblo                                       
>>> > Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;                  
>>> > linux-kernel@vger.kernel.org                                            
>>> > Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing           
>>> > support for GEM                                                         
>>> >                                                                         
>>> >> Le 17/11/2016 à 13:21, Harini Katakam a écrit :                        
>>> >> > Hi Rafal,                                                            
>>> >> >                                                                      
>>> >> > On Thu, Nov 17, 2016 at 5:20 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>>> >> >> Hello,                                                                   
>>> >> >> I think, there could a bug in your patch.                                
>>> >> >>                                                                          
>>> >> >>> +                                                                       
>>> >> >>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                    
>>> >> >>> +             dmacfg |= GEM_BIT(ADDR64); #endif                         
>>> >> >>                                                                          
>>> >> >> You enable 64 bit addressing (64b dma bus width) always when appropriate architecture config option is enabled.                                                                                         
>>> >> >> But there are some legacy controllers which do not support that feature. According Cadence hardware team:                                                                                               
>>> >> >> "64 bit addressing was added in July 2013. Earlier version do not have it.                     
>>> >> >> This feature was enhanced in release August 2014 to have separate upper address values for transmit and receive."                                                                                       
>>> >> >>                                                                                                
>>> >> >>> /* Bitfields in NSR */                                                                        
>>> >> >>> @@ -474,6 +479,10 @@                                                                          
>>> >> >>>  struct macb_dma_desc {                                                                       
>>> >> >>  >      u32     addr;                                                                          
>>> >> >>>       u32     ctrl;                                                                           
>>> >> >>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                          
>>> >> >>> +     u32     addrh;                                                                          
>>> >> >>> +     u32     resvd;                                                                          
>>> >> >>> +#endif                                                                                       
>>> >> >>>  };                                                                                           
>>> >> >>                                                                                                
>>> >> >> It will not work for legacy hardware. Old descriptor is 2 words wide, the new one is 4 words wide.                                                                                                      
>>> >> >> If you enable CONFIG_ARCH_DMA_ADDR_T_64BIT but hardware doesn't                                
>>> >> >> support it at all, you will miss every second descriptor.                                      
>>> >> >>                                                                                                
>>> >> >                                                                                                 
>>> >> > True, this feature is not available in all of Cadence IP versions.                              
>>> >> > In fact, the IP version Zynq does not support this. But the one in ZynqMP does.                 
>>> >> > So, we enable kernel config for 64 bit DMA addressing for this                                  
>>> >> > SoC and hence the driver picks it up. My assumption was that if                                 
>>> >> > the legacy IP does not support                                                                  
>>> >> > 64 bit addressing, then this DMA option wouldn't be enabled.                                    
>>> >> >                                                                                                 
>>> >> > There is a design config register in Cadence IP which is being                                  
>>> >> > read to check for 64 bit address support - DMA mask is set based on that.                       
>>> >> > But the addition of two descriptor words cannot be based on this runtime check.                 
>>> >> > For this reason, all the static changes were placed under this check.                           
>>> >>                                                                                                   
>>> >> We have quite a bunch of options in this driver to determinate what is the real capacity of the underlying hardware.                                                                                       
>>> >> If HW configuration registers are not appropriate, and it seems they are not, I would advice to simply use the DT compatibility string.                                                                    
>>> >>                                                                                                   
>>> >> Best regards,                                                                                     
>>> >> --                                                                                                
>>> >> Nicolas Ferre                                                                                     
>>> >                                                                                                    
>>> > HW configuration registers are appropriate. The issue is that this code doesn’t use the capability bit to switch between different dma descriptors (2 words vs. 4 words).                                   
>>> > DMA descriptor size is chosen based on kernel configuration, not based on hardware capabilities.   
>>>                                                                                                      
>>> HW configuration register does give appropriate information.                                         
>>> But addition of two address words in the macb descriptor structure is a static change.               
>>>                                                                                                      
>>> +static inline void macb_set_addr(struct macb_dma_desc *desc,                                        
>>> +dma_addr_t                                                                                          
>>> +addr) {                                                                                             
>>> +       desc->addr = (u32)addr;                                                                      
>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                                 
>>> +       desc->addrh = (u32)(addr >> 32); #endif                                                      
>>> +                                                                                                    
>>>                                                                                                      
>>> Even if the #ifdef condition here is changed to HW config check, addr and addrh are different.       
>>> And "addrh" entry has to be present for 64 bit desc case to be handled separately.                   
>>> Can you please tell me how you propose change in DMA descriptor                                      
>>> structure from                                                                                       
>>> 4 to 2 or 2 to 4 words *after* reading the DCFG register?                                            
>>                                                                                                       
>> It is very complex problem. I wrote to you because I faced the same issue. I'm working on PTP implementation for macb. When PTP is enabled there are additional two words in buffer descriptor.                
>> But hardware might not be compatible with PTP. Therefore I have to change DMA descriptor between 2 and 4 words after reading DCFG register (the same as you between 32b and 64b).                              
>> When we consider both PTP and 64 bits, we end up with 4 different descriptors!                        
>                                                                                                        
>Agree                                                                                                   
>                                                                                                        
><snip>                                                                                                  
>> (Below is kind of pseudo code only to show my idea. All defines like                                  
>> 64B or PTP are omitted for simplicity)                                                                
>>                                                                                                       
>> 1. Prepare appropriate structures:                                                                    
>>                                                                                                       
>> struct macb_dma_desc {                                                                                
>>         u32     addr;                                                                                 
>>         u32     ctrl;                                                                                 
>> }                                                                                                     
>>                                                                                                       
>> struct macb_dma_desc_64 {                                                                             
>>         u32 addrh;                                                                                    
>>         u32 resvd;                                                                                    
>> }                                                                                                     
>>                                                                                                       
>> struct macb_dma_desc_ptp {                                                                            
>>         u32 dma_desc_ts_1;                                                                            
>>         u32     dma_desc_ts_2;                                                                        
>> }                                                                                                     
>>                                                                                                       
>> 2. Add hardware support information to macb:                                                          
>>                                                                                                       
>> enum macb_hw_cap {                                                                                    
>>         HW_CAP_NONE,                                                                                  
>>         HW_CAP_64B,                                                                                   
>>         HW_CAP_PTP,                                                                                   
>>         HW_CAP_64B_PTP,                                                                               
>> };                                                                                                    
>>                                                                                                       
>> struct macb {                                                                                         
>> // (...)                                                                                              
>>         macb_hw_cap hw_cap;                                                                           
>>                                                                                                       
>> }                                                                                                     
>>                                                                                                       
>> 3. Set bp->hw_cap on macb_probe()                                                                     
>>                                                                                                       
>                                                                                                        
>hw_cap can alreayd be obtained from config structures based on compatible string.                       
>                                                                                                        
>> 4. Additional function might be helpful:                                                              
>>                                                                                                       
>> static unsigned char macb_dma_desc_get_mul(struct macb *bp) {
>>         switch (bp->hw_cap) {
>>                 case HW_CAP_NONE:
>>                         return 1;
>>                 case HW_CAP_64B:
>>                 case HW_CAP_PTP:
>>                         return 2;
>>                 case HW_CAP_64B_PTP:
>>                         return 3;
>>         }
>> }
>>
>> 5. Change sizeof struct to function:
>> (sizeof(struct macb_dma_desc) change to macb_dma_desc_get_size(bp). It will return sizeof(struct macb_dma_desc) * macb_dma_desc_get_mul(bp).
>> There is a hidden assumption that all three structures have the same size.
>>
>> 6. macb_rx_desc() and macb_tx_desc() will still return struct macb_dma_desc * but descriptor index will be counted in different way, ex.
>>
>> static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned
>> int index) {
>>         index *= macb_dma_desc_get_mul(bp);
>>         return &bp->rx_ring[macb_rx_ring_wrap(bp, index)]; }
>>
>> 7. Two additional functions to dereference PTP and 64b information:
>>
>> static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct
>> macb_dma_desc *desc) {
>>         switch (bp->hw_cap) {
>>                 case HW_CAP_64B:
>>                 case HW_CAP_64B_PTP:
>>                         return (struct macb_dma_desc_64 *)(desc + 1);  // ugly casting
>>                 default:
>>                         return NULL;
>>         }
>> }
>>
>> static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp, struct
>> macb_dma_desc *desc) {
>>         switch (bp->hw_cap) {
>>                 case HW_CAP_PTP:
>>                         return (struct macb_dma_desc_ptp *)(desc + 1);
>>                 case HW_CAP_64B_PTP:
>>                         return (struct macb_dma_desc_ptp *)(desc + 2);
>>                 default:
>>                         return NULL;
>>         }
>> }
>>
>> Whenever you want to reach fields in appropriate descriptor, above function should be used.
>>
>
>Theoretically I agree this will work.
>But we'll have to try to see how this will affect/slow down the desc reading.. especially with PTP.
>
>Regards,
>Harini

It is done very similarly in sdhci driver:
http://lxr.free-electrons.com/source/drivers/mmc/host/sdhci.c

For example, please look at sdhci_adma_write_desc().

If we change my idea to operate directly on void * instead of macb_dma_desc *, it would be even better. (rx_ring, tx_ring and others), ex.:

struct void *rx_ring;
struct void *tx_ring;

static  macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
{
	index *= macb_dma_desc_get_size(bp);
	 return (macb_dma_desc *)&bp->rx_ring[macb_rx_ring_wrap(bp, index)];
}

>> This is only my very first idea. Of course, we can leave it as it is and say, that old hardware is not support either when PTP enabled or 64b enabled.
>
Best regards,
Rafal Ozieblo   |   Firmware System Engineer, 
phone nbr.: +48 32 5085469 

www.cadence.com


^ permalink raw reply

* Re: [PATCH v9 0/8] thunderbolt: Introducing Thunderbolt(TM) Networking
From: Simon Guinot @ 2016-11-18 11:20 UTC (permalink / raw)
  To: Levy, Amir (Jer)
  Cc: gregkh@linuxfoundation.org, andreas.noever@gmail.com,
	bhelgaas@google.com, corbet@lwn.net, linux-kernel@vger.kernel.org,
	linux-pci@vger.kernel.org, netdev@vger.kernel.org,
	linux-doc@vger.kernel.org, mario_limonciello@dell.com,
	thunderbolt-linux, Westerberg, Mika, Winkler, Tomas,
	Zhang, Xiong Y, Jamet, Michael, remi.rerolle@seagate.com
In-Reply-To: <E607265CB020454880711A6F96C05A03BE2199EE@hasmsx108.ger.corp.intel.com>

[-- Attachment #1: Type: text/plain, Size: 4034 bytes --]

On Fri, Nov 18, 2016 at 08:48:36AM +0000, Levy, Amir (Jer) wrote:
> On Tue, Nov 15 2016, 12:59 PM, Simon Guinot wrote:
> > On Wed, Nov 09, 2016 at 03:42:53PM +0000, Levy, Amir (Jer) wrote:
> > > On Wed, Nov 9 2016, 04:36 PM, Simon Guinot wrote:
> > > > Hi Amir,
> > > >
> > > > I have an ASUS "All Series/Z87-DELUXE/QUAD" motherboard with a 
> > > > Thunderbolt 2 "Falcon Ridge" chipset (device ID 156d).
> > > >
> > > > Is the thunderbolt-icm driver supposed to work with this chipset ?
> > > >
> > >
> > > Yes, the thunderbolt-icm supports Falcon Ridge, device ID 156c.
> > > 156d is the bridge -
> > > http://lxr.free-electrons.com/source/include/linux/pci_ids.h#L2619
> > >
> > > > I have installed both a 4.8.6 Linux kernel (patched with your v9
> > > > series) and the thunderbolt-software-daemon (27 october release) 
> > > > inside a Debian system (Jessie).
> > > >
> > > > If I connect the ASUS motherboard with a MacBook Pro (Thunderbolt 
> > > > 2, device ID 156c), I can see that the thunderbolt-icm driver is 
> > > > loaded and that the thunderbolt-software-daemon is well started. 
> > > > But the Ethernet interface is not created.
> > > >
> > > > I have attached to this email the syslog file. There is the logs 
> > > > from both the kernel and the daemon inside. Note that the daemon 
> > > > logs are everything but clear about what could be the issue. Maybe 
> > > > I missed some kind of configuration ? But I failed to find any 
> > > > valuable information about configuring the driver and/or the 
> > > > daemon in
> > the various documentation files.
> > > >
> > > > Please, can you provide some guidance ? I'd really like to test 
> > > > your patch series.
> > >
> > > First, thank you very much for willing to test it.
> > > Thunderbolt Networking support was added during Falcon Ridge, in the
> > latest FR images.
> > > Do you know which Thunderbolt image version you have on your system?
> > > Currently I submitted only Thunderbolt Networking feature in Linux, 
> > > and we plan to add more features like reading the image version and
> > updating the image.
> > > If you don't know the image version, the only thing I can suggest is 
> > > to load windows, install thunderbolt SW and check in the Thunderbolt
> > application the image version.
> > > To know if image update is needed, you can check - 
> > > https://thunderbolttechnology.net/updates
> > 
> > Hi Amir,
> > 
> > From the Windows Thunderbolt software, I can read 13.00 for the 
> > firmware version. And from https://thunderbolttechnology.net/updates, 
> > I can see that there is no update available for my ASUS motherboard.
> > 
> > Am I good to go ?
> > 
> 
> Thunderbolt Networking is supported on both Thunderbolt(tm) 2 and Thunderbolt(tm) 3 systems.  
> Thunderbolt 2 systems must have updated NVM (version 25 or later) in order for the functionality to work properly.  
> If the system does not have the update, please contact the OEM directly for an updated NVM.  
> For best functionality and support, Intel recommends using Thunderbolt 3 systems for all validation and testing.

Maybe it is worth mentioning in the documentation and/or in the Kconfig
help message that a minimal firmware version is needed for Thunderbolt 2
controllers.

It would have saved some time for me :)

> 
> > BTW, it is quite a shame that the Thunderbolt firmware version can't 
> > be read from Linux.
> > 
> 
> This is WIP, once this patch will be upstream, we will be able to focus more
> on aligning Linux with the Thunderbolt features that we have for windows.

Well, I rather see the firmware identification and update as basic
features on the top of which ones you can build a driver. For example in
this case this would allow the ICM driver and/or the userland daemon to
exit with a useful error message rather than just not working without any
explanation.

Next week I'll try the driver with a Thunderbolt 3 controller.

Thanks for your help!

Simon

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply

* Re: [PATCH net-next] cadence: Add hardware PTP support.
From: Nicolas Ferre @ 2016-11-18 11:12 UTC (permalink / raw)
  To: Rafal Ozieblo, Andrei Pistirica, netdev, David Miller
  Cc: Harini Katakam, linux-kernel
In-Reply-To: <1479466028-29914-1-git-send-email-rafalo@cadence.com>

Le 18/11/2016 à 11:47, Rafal Ozieblo a écrit :
> Signed-off-by: Rafal Ozieblo <rafalo@cadence.com>

Note to David: This is more a RFC: we are discussing the addition of
this feature and how to cover all macb revisions and optional features
implemented in actual products.

regards,

> ---
>  Documentation/devicetree/bindings/net/macb.txt |   1 +
>  drivers/net/ethernet/cadence/macb.c            | 742 ++++++++++++++++++++++++-
>  drivers/net/ethernet/cadence/macb.h            | 217 +++++++-
>  3 files changed, 950 insertions(+), 10 deletions(-)

[..]

-- 
Nicolas Ferre

^ permalink raw reply

* [PATCH net-next] cxgb4: Allocate Tx queues dynamically
From: Atul Gupta @ 2016-11-18 11:07 UTC (permalink / raw)
  To: netdev, linux-scsi, target-devel, linux-rdma, linux-crypto
  Cc: davem, nab, jejb, martin.petersen, dledford, herbert, leedom,
	nirranjan, varun, swise, hariprasad, Atul Gupta

From: Hariprasad Shenai <hariprasad@chelsio.com>

Allocate resources dynamically for Upper layer driver's (ULD) like
cxgbit, iw_cxgb4, cxgb4i and chcr. The resources allocated include Tx
queues which are allocated when ULD register with cxgb4 driver and freed
while un-registering. The Tx queues which are shared by ULD shall be
allocated by first registering driver and un-allocated by last
unregistering driver.

Signed-off-by: Atul Gupta <atul.gupta@chelsio.com>
---
 drivers/crypto/chelsio/chcr_algo.c                 |  16 +--
 drivers/crypto/chelsio/chcr_core.c                 |   3 +-
 drivers/infiniband/hw/cxgb4/device.c               |   1 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h         |  19 +++-
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c |  12 --
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |  64 +++++++----
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c     | 114 +++++++++++++++++++
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h     |  17 +++
 drivers/net/ethernet/chelsio/cxgb4/sge.c           | 121 +++++++++++++++------
 drivers/scsi/cxgbi/cxgb4i/cxgb4i.c                 |   1 +
 drivers/target/iscsi/cxgbit/cxgbit_main.c          |   1 +
 11 files changed, 287 insertions(+), 82 deletions(-)

diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c
index e4ddb921d7b3..56b153805462 100644
--- a/drivers/crypto/chelsio/chcr_algo.c
+++ b/drivers/crypto/chelsio/chcr_algo.c
@@ -592,16 +592,18 @@ static int chcr_aes_cbc_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
 
 static int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx)
 {
-	int ret = 0;
-	struct sge_ofld_txq *q;
 	struct adapter *adap = netdev2adap(dev);
+	struct sge_uld_txq_info *txq_info =
+		adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
+	struct sge_uld_txq *txq;
+	int ret = 0;
 
 	local_bh_disable();
-	q = &adap->sge.ofldtxq[idx];
-	spin_lock(&q->sendq.lock);
-	if (q->full)
+	txq = &txq_info->uldtxq[idx];
+	spin_lock(&txq->sendq.lock);
+	if (txq->full)
 		ret = -1;
-	spin_unlock(&q->sendq.lock);
+	spin_unlock(&txq->sendq.lock);
 	local_bh_enable();
 	return ret;
 }
@@ -674,11 +676,11 @@ static int chcr_device_init(struct chcr_context *ctx)
 		}
 		u_ctx = ULD_CTX(ctx);
 		rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan;
-		ctx->dev->tx_channel_id = 0;
 		rxq_idx = ctx->dev->tx_channel_id * rxq_perchan;
 		rxq_idx += id % rxq_perchan;
 		spin_lock(&ctx->dev->lock_chcr_dev);
 		ctx->tx_channel_id = rxq_idx;
+		ctx->dev->tx_channel_id = !ctx->dev->tx_channel_id;
 		spin_unlock(&ctx->dev->lock_chcr_dev);
 	}
 out:
diff --git a/drivers/crypto/chelsio/chcr_core.c b/drivers/crypto/chelsio/chcr_core.c
index fb5f9bbfa09c..4d7f6700fd7e 100644
--- a/drivers/crypto/chelsio/chcr_core.c
+++ b/drivers/crypto/chelsio/chcr_core.c
@@ -42,6 +42,7 @@ static chcr_handler_func work_handlers[NUM_CPL_CMDS] = {
 static struct cxgb4_uld_info chcr_uld_info = {
 	.name = DRV_MODULE_NAME,
 	.nrxq = MAX_ULD_QSETS,
+	.ntxq = MAX_ULD_QSETS,
 	.rxq_size = 1024,
 	.add = chcr_uld_add,
 	.state_change = chcr_uld_state_change,
@@ -126,7 +127,7 @@ static int cpl_fw6_pld_handler(struct chcr_dev *dev,
 
 int chcr_send_wr(struct sk_buff *skb)
 {
-	return cxgb4_ofld_send(skb->dev, skb);
+	return cxgb4_crypto_send(skb->dev, skb);
 }
 
 static void *chcr_uld_add(const struct cxgb4_lld_info *lld)
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 93e3d270a98a..4e5baf4fe15e 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -1481,6 +1481,7 @@ static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...)
 static struct cxgb4_uld_info c4iw_uld_info = {
 	.name = DRV_NAME,
 	.nrxq = MAX_ULD_QSETS,
+	.ntxq = MAX_ULD_QSETS,
 	.rxq_size = 511,
 	.ciq = true,
 	.lro = false,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 2125903043fb..0bce1bf9ca0f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -635,6 +635,7 @@ struct tx_sw_desc;
 
 struct sge_txq {
 	unsigned int  in_use;       /* # of in-use Tx descriptors */
+	unsigned int  q_type;	    /* Q type Eth/Ctrl/Ofld */
 	unsigned int  size;         /* # of descriptors */
 	unsigned int  cidx;         /* SW consumer index */
 	unsigned int  pidx;         /* producer index */
@@ -665,7 +666,7 @@ struct sge_eth_txq {                /* state for an SGE Ethernet Tx queue */
 	unsigned long mapping_err;  /* # of I/O MMU packet mapping errors */
 } ____cacheline_aligned_in_smp;
 
-struct sge_ofld_txq {               /* state for an SGE offload Tx queue */
+struct sge_uld_txq {               /* state for an SGE offload Tx queue */
 	struct sge_txq q;
 	struct adapter *adap;
 	struct sk_buff_head sendq;  /* list of backpressured packets */
@@ -693,14 +694,20 @@ struct sge_uld_rxq_info {
 	u8 uld;			/* uld type */
 };
 
+struct sge_uld_txq_info {
+	struct sge_uld_txq *uldtxq; /* Txq's for ULD */
+	atomic_t users;		/* num users */
+	u16 ntxq;		/* # of egress uld queues */
+};
+
 struct sge {
 	struct sge_eth_txq ethtxq[MAX_ETH_QSETS];
-	struct sge_ofld_txq ofldtxq[MAX_OFLD_QSETS];
 	struct sge_ctrl_txq ctrlq[MAX_CTRL_QUEUES];
 
 	struct sge_eth_rxq ethrxq[MAX_ETH_QSETS];
 	struct sge_rspq fw_evtq ____cacheline_aligned_in_smp;
 	struct sge_uld_rxq_info **uld_rxq_info;
+	struct sge_uld_txq_info **uld_txq_info;
 
 	struct sge_rspq intrq ____cacheline_aligned_in_smp;
 	spinlock_t intrq_lock;
@@ -1298,8 +1305,9 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
 			  unsigned int cmplqid);
 int t4_sge_mod_ctrl_txq(struct adapter *adap, unsigned int eqid,
 			unsigned int cmplqid);
-int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
-			  struct net_device *dev, unsigned int iqid);
+int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
+			 struct net_device *dev, unsigned int iqid,
+			 unsigned int uld_type);
 irqreturn_t t4_sge_intr_msix(int irq, void *cookie);
 int t4_sge_init(struct adapter *adap);
 void t4_sge_start(struct adapter *adap);
@@ -1661,4 +1669,7 @@ int t4_uld_mem_alloc(struct adapter *adap);
 void t4_uld_clean_up(struct adapter *adap);
 void t4_register_netevent_notifier(void);
 void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl);
+void free_tx_desc(struct adapter *adap, struct sge_txq *q,
+		  unsigned int n, bool unmap);
+void free_txq(struct adapter *adap, struct sge_txq *q);
 #endif /* __CXGB4_H__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 20455d082cb8..acc231293e4d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -2512,18 +2512,6 @@ do { \
 		RL("FLLow:", fl.low);
 		RL("FLStarving:", fl.starving);
 
-	} else if (ofld_idx < ofld_entries) {
-		const struct sge_ofld_txq *tx =
-			&adap->sge.ofldtxq[ofld_idx * 4];
-		int n = min(4, adap->sge.ofldqsets - 4 * ofld_idx);
-
-		S("QType:", "OFLD-Txq");
-		T("TxQ ID:", q.cntxt_id);
-		T("TxQ size:", q.size);
-		T("TxQ inuse:", q.in_use);
-		T("TxQ CIDX:", q.cidx);
-		T("TxQ PIDX:", q.pidx);
-
 	} else if (ctrl_idx < ctrl_entries) {
 		const struct sge_ctrl_txq *tx = &adap->sge.ctrlq[ctrl_idx * 4];
 		int n = min(4, adap->params.nports - 4 * ctrl_idx);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index c0cc2ee77be7..449884f8dd67 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -530,15 +530,15 @@ static int fwevtq_handler(struct sge_rspq *q, const __be64 *rsp,
 
 		txq = q->adap->sge.egr_map[qid - q->adap->sge.egr_start];
 		txq->restarts++;
-		if ((u8 *)txq < (u8 *)q->adap->sge.ofldtxq) {
+		if (txq->q_type == CXGB4_TXQ_ETH) {
 			struct sge_eth_txq *eq;
 
 			eq = container_of(txq, struct sge_eth_txq, q);
 			netif_tx_wake_queue(eq->txq);
 		} else {
-			struct sge_ofld_txq *oq;
+			struct sge_uld_txq *oq;
 
-			oq = container_of(txq, struct sge_ofld_txq, q);
+			oq = container_of(txq, struct sge_uld_txq, q);
 			tasklet_schedule(&oq->qresume_tsk);
 		}
 	} else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) {
@@ -885,15 +885,6 @@ static int setup_sge_queues(struct adapter *adap)
 		}
 	}
 
-	j = s->ofldqsets / adap->params.nports; /* iscsi queues per channel */
-	for_each_ofldtxq(s, i) {
-		err = t4_sge_alloc_ofld_txq(adap, &s->ofldtxq[i],
-					    adap->port[i / j],
-					    s->fw_evtq.cntxt_id);
-		if (err)
-			goto freeout;
-	}
-
 	for_each_port(adap, i) {
 		/* Note that cmplqid below is 0 if we don't
 		 * have RDMA queues, and that's the right value.
@@ -1922,8 +1913,18 @@ static void disable_dbs(struct adapter *adap)
 
 	for_each_ethrxq(&adap->sge, i)
 		disable_txq_db(&adap->sge.ethtxq[i].q);
-	for_each_ofldtxq(&adap->sge, i)
-		disable_txq_db(&adap->sge.ofldtxq[i].q);
+	if (is_offload(adap)) {
+		struct sge_uld_txq_info *txq_info =
+			adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+
+		if (txq_info) {
+			for_each_ofldtxq(&adap->sge, i) {
+				struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+				disable_txq_db(&txq->q);
+			}
+		}
+	}
 	for_each_port(adap, i)
 		disable_txq_db(&adap->sge.ctrlq[i].q);
 }
@@ -1934,8 +1935,18 @@ static void enable_dbs(struct adapter *adap)
 
 	for_each_ethrxq(&adap->sge, i)
 		enable_txq_db(adap, &adap->sge.ethtxq[i].q);
-	for_each_ofldtxq(&adap->sge, i)
-		enable_txq_db(adap, &adap->sge.ofldtxq[i].q);
+	if (is_offload(adap)) {
+		struct sge_uld_txq_info *txq_info =
+			adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+
+		if (txq_info) {
+			for_each_ofldtxq(&adap->sge, i) {
+				struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+				enable_txq_db(adap, &txq->q);
+			}
+		}
+	}
 	for_each_port(adap, i)
 		enable_txq_db(adap, &adap->sge.ctrlq[i].q);
 }
@@ -2006,8 +2017,17 @@ static void recover_all_queues(struct adapter *adap)
 
 	for_each_ethrxq(&adap->sge, i)
 		sync_txq_pidx(adap, &adap->sge.ethtxq[i].q);
-	for_each_ofldtxq(&adap->sge, i)
-		sync_txq_pidx(adap, &adap->sge.ofldtxq[i].q);
+	if (is_offload(adap)) {
+		struct sge_uld_txq_info *txq_info =
+			adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+		if (txq_info) {
+			for_each_ofldtxq(&adap->sge, i) {
+				struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+				sync_txq_pidx(adap, &txq->q);
+			}
+		}
+	}
 	for_each_port(adap, i)
 		sync_txq_pidx(adap, &adap->sge.ctrlq[i].q);
 }
@@ -3991,7 +4011,7 @@ static inline bool is_x_10g_port(const struct link_config *lc)
 static void cfg_queues(struct adapter *adap)
 {
 	struct sge *s = &adap->sge;
-	int i, n10g = 0, qidx = 0;
+	int i = 0, n10g = 0, qidx = 0;
 #ifndef CONFIG_CHELSIO_T4_DCB
 	int q10g = 0;
 #endif
@@ -4006,8 +4026,7 @@ static void cfg_queues(struct adapter *adap)
 		adap->params.crypto = 0;
 	}
 
-	for_each_port(adap, i)
-		n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
+	n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
 #ifdef CONFIG_CHELSIO_T4_DCB
 	/* For Data Center Bridging support we need to be able to support up
 	 * to 8 Traffic Priorities; each of which will be assigned to its
@@ -4075,9 +4094,6 @@ static void cfg_queues(struct adapter *adap)
 	for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++)
 		s->ctrlq[i].q.size = 512;
 
-	for (i = 0; i < ARRAY_SIZE(s->ofldtxq); i++)
-		s->ofldtxq[i].q.size = 1024;
-
 	init_rspq(adap, &s->fw_evtq, 0, 1, 1024, 64);
 	init_rspq(adap, &s->intrq, 0, 1, 512, 64);
 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
index 2471ff465d5c..565a6c6bfeaf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
@@ -447,6 +447,106 @@ static void quiesce_rx_uld(struct adapter *adap, unsigned int uld_type)
 		quiesce_rx(adap, &rxq_info->uldrxq[idx].rspq);
 }
 
+static void
+free_sge_txq_uld(struct adapter *adap, struct sge_uld_txq_info *txq_info)
+{
+	int nq = txq_info->ntxq;
+	int i;
+
+	for (i = 0; i < nq; i++) {
+		struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+		if (txq && txq->q.desc) {
+			tasklet_kill(&txq->qresume_tsk);
+			t4_ofld_eq_free(adap, adap->mbox, adap->pf, 0,
+					txq->q.cntxt_id);
+			free_tx_desc(adap, &txq->q, txq->q.in_use, false);
+			kfree(txq->q.sdesc);
+			__skb_queue_purge(&txq->sendq);
+			free_txq(adap, &txq->q);
+		}
+	}
+}
+
+static int
+alloc_sge_txq_uld(struct adapter *adap, struct sge_uld_txq_info *txq_info,
+		  unsigned int uld_type)
+{
+	struct sge *s = &adap->sge;
+	int nq = txq_info->ntxq;
+	int i, j, err;
+
+	j = nq / adap->params.nports;
+	for (i = 0; i < nq; i++) {
+		struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+		txq->q.size = 1024;
+		err = t4_sge_alloc_uld_txq(adap, txq, adap->port[i / j],
+					   s->fw_evtq.cntxt_id, uld_type);
+		if (err)
+			goto freeout;
+	}
+	return 0;
+freeout:
+	free_sge_txq_uld(adap, txq_info);
+	return err;
+}
+
+static void
+release_sge_txq_uld(struct adapter *adap, unsigned int uld_type)
+{
+	struct sge_uld_txq_info *txq_info = NULL;
+	int tx_uld_type = TX_ULD(uld_type);
+
+	txq_info = adap->sge.uld_txq_info[tx_uld_type];
+
+	if (txq_info && atomic_dec_and_test(&txq_info->users)) {
+		free_sge_txq_uld(adap, txq_info);
+		kfree(txq_info->uldtxq);
+		kfree(txq_info);
+		adap->sge.uld_txq_info[tx_uld_type] = NULL;
+	}
+}
+
+static int
+setup_sge_txq_uld(struct adapter *adap, unsigned int uld_type,
+		  const struct cxgb4_uld_info *uld_info)
+{
+	struct sge_uld_txq_info *txq_info = NULL;
+	int tx_uld_type, i;
+
+	tx_uld_type = TX_ULD(uld_type);
+	txq_info = adap->sge.uld_txq_info[tx_uld_type];
+
+	if ((tx_uld_type == CXGB4_TX_OFLD) && txq_info &&
+	    (atomic_inc_return(&txq_info->users) > 1))
+		return 0;
+
+	txq_info = kzalloc(sizeof(*txq_info), GFP_KERNEL);
+	if (!txq_info)
+		return -ENOMEM;
+
+	i = min_t(int, uld_info->ntxq, num_online_cpus());
+	txq_info->ntxq = roundup(i, adap->params.nports);
+
+	txq_info->uldtxq = kcalloc(txq_info->ntxq, sizeof(struct sge_uld_txq),
+				   GFP_KERNEL);
+	if (!txq_info->uldtxq) {
+		kfree(txq_info->uldtxq);
+		return -ENOMEM;
+	}
+
+	if (alloc_sge_txq_uld(adap, txq_info, tx_uld_type)) {
+		kfree(txq_info->uldtxq);
+		kfree(txq_info);
+		return -ENOMEM;
+	}
+
+	atomic_inc(&txq_info->users);
+	adap->sge.uld_txq_info[tx_uld_type] = txq_info;
+	return 0;
+}
+
 static void uld_queue_init(struct adapter *adap, unsigned int uld_type,
 			   struct cxgb4_lld_info *lli)
 {
@@ -472,7 +572,15 @@ int t4_uld_mem_alloc(struct adapter *adap)
 	if (!s->uld_rxq_info)
 		goto err_uld;
 
+	s->uld_txq_info = kzalloc(CXGB4_TX_MAX *
+				  sizeof(struct sge_uld_txq_info *),
+				  GFP_KERNEL);
+	if (!s->uld_txq_info)
+		goto err_uld_rx;
 	return 0;
+
+err_uld_rx:
+	kfree(s->uld_rxq_info);
 err_uld:
 	kfree(adap->uld);
 	return -ENOMEM;
@@ -482,6 +590,7 @@ void t4_uld_mem_free(struct adapter *adap)
 {
 	struct sge *s = &adap->sge;
 
+	kfree(s->uld_txq_info);
 	kfree(s->uld_rxq_info);
 	kfree(adap->uld);
 }
@@ -616,6 +725,9 @@ int cxgb4_register_uld(enum cxgb4_uld type,
 			ret = -EBUSY;
 			goto free_irq;
 		}
+		ret = setup_sge_txq_uld(adap, type, p);
+		if (ret)
+			goto free_irq;
 		adap->uld[type] = *p;
 		uld_attach(adap, type);
 		adap_idx++;
@@ -644,6 +756,7 @@ int cxgb4_register_uld(enum cxgb4_uld type,
 			break;
 		adap->uld[type].handle = NULL;
 		adap->uld[type].add = NULL;
+		release_sge_txq_uld(adap, type);
 		if (adap->flags & FULL_INIT_DONE)
 			quiesce_rx_uld(adap, type);
 		if (adap->flags & USING_MSIX)
@@ -679,6 +792,7 @@ int cxgb4_unregister_uld(enum cxgb4_uld type)
 			continue;
 		adap->uld[type].handle = NULL;
 		adap->uld[type].add = NULL;
+		release_sge_txq_uld(adap, type);
 		if (adap->flags & FULL_INIT_DONE)
 			quiesce_rx_uld(adap, type);
 		if (adap->flags & USING_MSIX)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 2996793b1aaa..4c856605fdfa 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -77,6 +77,8 @@ enum {
 
 /* Special asynchronous notification message */
 #define CXGB4_MSG_AN ((void *)1)
+#define TX_ULD(uld)(((uld) != CXGB4_ULD_CRYPTO) ? CXGB4_TX_OFLD :\
+		      CXGB4_TX_CRYPTO)
 
 struct serv_entry {
 	void *data;
@@ -223,6 +225,19 @@ enum cxgb4_uld {
 	CXGB4_ULD_MAX
 };
 
+enum cxgb4_tx_uld {
+	CXGB4_TX_OFLD,
+	CXGB4_TX_CRYPTO,
+	CXGB4_TX_MAX
+};
+
+enum cxgb4_txq_type {
+	CXGB4_TXQ_ETH,
+	CXGB4_TXQ_ULD,
+	CXGB4_TXQ_CTRL,
+	CXGB4_TXQ_MAX
+};
+
 enum cxgb4_state {
 	CXGB4_STATE_UP,
 	CXGB4_STATE_START_RECOVERY,
@@ -316,6 +331,7 @@ struct cxgb4_uld_info {
 	void *handle;
 	unsigned int nrxq;
 	unsigned int rxq_size;
+	unsigned int ntxq;
 	bool ciq;
 	bool lro;
 	void *(*add)(const struct cxgb4_lld_info *p);
@@ -333,6 +349,7 @@ struct cxgb4_uld_info {
 int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
 int cxgb4_unregister_uld(enum cxgb4_uld type);
 int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
+int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb);
 unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
 unsigned int cxgb4_port_chan(const struct net_device *dev);
 unsigned int cxgb4_port_viid(const struct net_device *dev);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 1e74fd6085df..b7d0753b9242 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -377,8 +377,8 @@ unmap:			dma_unmap_page(dev, be64_to_cpu(p->addr[0]),
  *	Reclaims Tx descriptors from an SGE Tx queue and frees the associated
  *	Tx buffers.  Called with the Tx queue lock held.
  */
-static void free_tx_desc(struct adapter *adap, struct sge_txq *q,
-			 unsigned int n, bool unmap)
+void free_tx_desc(struct adapter *adap, struct sge_txq *q,
+		  unsigned int n, bool unmap)
 {
 	struct tx_sw_desc *d;
 	unsigned int cidx = q->cidx;
@@ -1543,7 +1543,7 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb)
  *	inability to map packets.  A periodic timer attempts to restart
  *	queues so marked.
  */
-static void txq_stop_maperr(struct sge_ofld_txq *q)
+static void txq_stop_maperr(struct sge_uld_txq *q)
 {
 	q->mapping_err++;
 	q->q.stops++;
@@ -1559,7 +1559,7 @@ static void txq_stop_maperr(struct sge_ofld_txq *q)
  *	Stops an offload Tx queue that has become full and modifies the packet
  *	being written to request a wakeup.
  */
-static void ofldtxq_stop(struct sge_ofld_txq *q, struct sk_buff *skb)
+static void ofldtxq_stop(struct sge_uld_txq *q, struct sk_buff *skb)
 {
 	struct fw_wr_hdr *wr = (struct fw_wr_hdr *)skb->data;
 
@@ -1586,7 +1586,7 @@ static void ofldtxq_stop(struct sge_ofld_txq *q, struct sk_buff *skb)
  *	boolean "service_ofldq_running" to make sure that only one instance
  *	is ever running at a time ...
  */
-static void service_ofldq(struct sge_ofld_txq *q)
+static void service_ofldq(struct sge_uld_txq *q)
 {
 	u64 *pos, *before, *end;
 	int credits;
@@ -1706,7 +1706,7 @@ static void service_ofldq(struct sge_ofld_txq *q)
  *
  *	Send an offload packet through an SGE offload queue.
  */
-static int ofld_xmit(struct sge_ofld_txq *q, struct sk_buff *skb)
+static int ofld_xmit(struct sge_uld_txq *q, struct sk_buff *skb)
 {
 	skb->priority = calc_tx_flits_ofld(skb);       /* save for restart */
 	spin_lock(&q->sendq.lock);
@@ -1735,7 +1735,7 @@ static int ofld_xmit(struct sge_ofld_txq *q, struct sk_buff *skb)
  */
 static void restart_ofldq(unsigned long data)
 {
-	struct sge_ofld_txq *q = (struct sge_ofld_txq *)data;
+	struct sge_uld_txq *q = (struct sge_uld_txq *)data;
 
 	spin_lock(&q->sendq.lock);
 	q->full = 0;            /* the queue actually is completely empty now */
@@ -1767,17 +1767,23 @@ static inline unsigned int is_ctrl_pkt(const struct sk_buff *skb)
 	return skb->queue_mapping & 1;
 }
 
-static inline int ofld_send(struct adapter *adap, struct sk_buff *skb)
+static inline int uld_send(struct adapter *adap, struct sk_buff *skb,
+			   unsigned int tx_uld_type)
 {
+	struct sge_uld_txq_info *txq_info;
+	struct sge_uld_txq *txq;
 	unsigned int idx = skb_txq(skb);
 
+	txq_info = adap->sge.uld_txq_info[tx_uld_type];
+	txq = &txq_info->uldtxq[idx];
+
 	if (unlikely(is_ctrl_pkt(skb))) {
 		/* Single ctrl queue is a requirement for LE workaround path */
 		if (adap->tids.nsftids)
 			idx = 0;
 		return ctrl_xmit(&adap->sge.ctrlq[idx], skb);
 	}
-	return ofld_xmit(&adap->sge.ofldtxq[idx], skb);
+	return ofld_xmit(txq, skb);
 }
 
 /**
@@ -1794,7 +1800,7 @@ int t4_ofld_send(struct adapter *adap, struct sk_buff *skb)
 	int ret;
 
 	local_bh_disable();
-	ret = ofld_send(adap, skb);
+	ret = uld_send(adap, skb, CXGB4_TX_OFLD);
 	local_bh_enable();
 	return ret;
 }
@@ -1813,6 +1819,39 @@ int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(cxgb4_ofld_send);
 
+/**
+ *	t4_crypto_send - send crypto packet
+ *	@adap: the adapter
+ *	@skb: the packet
+ *
+ *	Sends crypto packet.  We use the packet queue_mapping to select the
+ *	appropriate Tx queue as follows: bit 0 indicates whether the packet
+ *	should be sent as regular or control, bits 1-15 select the queue.
+ */
+static int t4_crypto_send(struct adapter *adap, struct sk_buff *skb)
+{
+	int ret;
+
+	local_bh_disable();
+	ret = uld_send(adap, skb, CXGB4_TX_CRYPTO);
+	local_bh_enable();
+	return ret;
+}
+
+/**
+ *	cxgb4_crypto_send - send crypto packet
+ *	@dev: the net device
+ *	@skb: the packet
+ *
+ *	Sends crypto packet.  This is an exported version of @t4_crypto_send,
+ *	intended for ULDs.
+ */
+int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb)
+{
+	return t4_crypto_send(netdev2adap(dev), skb);
+}
+EXPORT_SYMBOL(cxgb4_crypto_send);
+
 static inline void copy_frags(struct sk_buff *skb,
 			      const struct pkt_gl *gl, unsigned int offset)
 {
@@ -2479,7 +2518,7 @@ static void sge_tx_timer_cb(unsigned long data)
 	for (i = 0; i < BITS_TO_LONGS(s->egr_sz); i++)
 		for (m = s->txq_maperr[i]; m; m &= m - 1) {
 			unsigned long id = __ffs(m) + i * BITS_PER_LONG;
-			struct sge_ofld_txq *txq = s->egr_map[id];
+			struct sge_uld_txq *txq = s->egr_map[id];
 
 			clear_bit(id, s->txq_maperr);
 			tasklet_schedule(&txq->qresume_tsk);
@@ -2799,6 +2838,7 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
 		return ret;
 	}
 
+	txq->q.q_type = CXGB4_TXQ_ETH;
 	init_txq(adap, &txq->q, FW_EQ_ETH_CMD_EQID_G(ntohl(c.eqid_pkd)));
 	txq->txq = netdevq;
 	txq->tso = txq->tx_cso = txq->vlan_ins = 0;
@@ -2852,6 +2892,7 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
 		return ret;
 	}
 
+	txq->q.q_type = CXGB4_TXQ_CTRL;
 	init_txq(adap, &txq->q, FW_EQ_CTRL_CMD_EQID_G(ntohl(c.cmpliqid_eqid)));
 	txq->adap = adap;
 	skb_queue_head_init(&txq->sendq);
@@ -2872,13 +2913,15 @@ int t4_sge_mod_ctrl_txq(struct adapter *adap, unsigned int eqid,
 	return t4_set_params(adap, adap->mbox, adap->pf, 0, 1, &param, &val);
 }
 
-int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
-			  struct net_device *dev, unsigned int iqid)
+int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
+			 struct net_device *dev, unsigned int iqid,
+			 unsigned int uld_type)
 {
 	int ret, nentries;
 	struct fw_eq_ofld_cmd c;
 	struct sge *s = &adap->sge;
 	struct port_info *pi = netdev_priv(dev);
+	int cmd = FW_EQ_OFLD_CMD;
 
 	/* Add status entries */
 	nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
@@ -2891,7 +2934,9 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
 		return -ENOMEM;
 
 	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST_F |
+	if (unlikely(uld_type == CXGB4_TX_CRYPTO))
+		cmd = FW_EQ_CTRL_CMD;
+	c.op_to_vfn = htonl(FW_CMD_OP_V(cmd) | FW_CMD_REQUEST_F |
 			    FW_CMD_WRITE_F | FW_CMD_EXEC_F |
 			    FW_EQ_OFLD_CMD_PFN_V(adap->pf) |
 			    FW_EQ_OFLD_CMD_VFN_V(0));
@@ -2919,6 +2964,7 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
 		return ret;
 	}
 
+	txq->q.q_type = CXGB4_TXQ_ULD;
 	init_txq(adap, &txq->q, FW_EQ_OFLD_CMD_EQID_G(ntohl(c.eqid_pkd)));
 	txq->adap = adap;
 	skb_queue_head_init(&txq->sendq);
@@ -2928,7 +2974,7 @@ int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
 	return 0;
 }
 
-static void free_txq(struct adapter *adap, struct sge_txq *q)
+void free_txq(struct adapter *adap, struct sge_txq *q)
 {
 	struct sge *s = &adap->sge;
 
@@ -3026,21 +3072,6 @@ void t4_free_sge_resources(struct adapter *adap)
 		}
 	}
 
-	/* clean up offload Tx queues */
-	for (i = 0; i < ARRAY_SIZE(adap->sge.ofldtxq); i++) {
-		struct sge_ofld_txq *q = &adap->sge.ofldtxq[i];
-
-		if (q->q.desc) {
-			tasklet_kill(&q->qresume_tsk);
-			t4_ofld_eq_free(adap, adap->mbox, adap->pf, 0,
-					q->q.cntxt_id);
-			free_tx_desc(adap, &q->q, q->q.in_use, false);
-			kfree(q->q.sdesc);
-			__skb_queue_purge(&q->sendq);
-			free_txq(adap, &q->q);
-		}
-	}
-
 	/* clean up control Tx queues */
 	for (i = 0; i < ARRAY_SIZE(adap->sge.ctrlq); i++) {
 		struct sge_ctrl_txq *cq = &adap->sge.ctrlq[i];
@@ -3093,12 +3124,34 @@ void t4_sge_stop(struct adapter *adap)
 	if (s->tx_timer.function)
 		del_timer_sync(&s->tx_timer);
 
-	for (i = 0; i < ARRAY_SIZE(s->ofldtxq); i++) {
-		struct sge_ofld_txq *q = &s->ofldtxq[i];
+	if (is_offload(adap)) {
+		struct sge_uld_txq_info *txq_info;
+
+		txq_info = adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+		if (txq_info) {
+			struct sge_uld_txq *txq = txq_info->uldtxq;
 
-		if (q->q.desc)
-			tasklet_kill(&q->qresume_tsk);
+			for_each_ofldtxq(&adap->sge, i) {
+				if (txq->q.desc)
+					tasklet_kill(&txq->qresume_tsk);
+			}
+		}
 	}
+
+	if (is_pci_uld(adap)) {
+		struct sge_uld_txq_info *txq_info;
+
+		txq_info = adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
+		if (txq_info) {
+			struct sge_uld_txq *txq = txq_info->uldtxq;
+
+			for_each_ofldtxq(&adap->sge, i) {
+				if (txq->q.desc)
+					tasklet_kill(&txq->qresume_tsk);
+			}
+		}
+	}
+
 	for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++) {
 		struct sge_ctrl_txq *cq = &s->ctrlq[i];
 
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index 0039bebaa9e2..4655a9f9dcea 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -85,6 +85,7 @@ static inline int send_tx_flowc_wr(struct cxgbi_sock *);
 static const struct cxgb4_uld_info cxgb4i_uld_info = {
 	.name = DRV_MODULE_NAME,
 	.nrxq = MAX_ULD_QSETS,
+	.ntxq = MAX_ULD_QSETS,
 	.rxq_size = 1024,
 	.lro = false,
 	.add = t4_uld_add,
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_main.c b/drivers/target/iscsi/cxgbit/cxgbit_main.c
index ad26b9372f10..96eedfc49c94 100644
--- a/drivers/target/iscsi/cxgbit/cxgbit_main.c
+++ b/drivers/target/iscsi/cxgbit/cxgbit_main.c
@@ -653,6 +653,7 @@ static struct iscsit_transport cxgbit_transport = {
 static struct cxgb4_uld_info cxgbit_uld_info = {
 	.name		= DRV_NAME,
 	.nrxq		= MAX_ULD_QSETS,
+	.ntxq		= MAX_ULD_QSETS,
 	.rxq_size	= 1024,
 	.lro		= true,
 	.add		= cxgbit_uld_add,
-- 
2.3.4

^ permalink raw reply related

* Re: [PATCH net-next] bridge: add igmpv3 and mldv2 query support
From: kbuild test robot @ 2016-11-18 10:56 UTC (permalink / raw)
  To: Hangbin Liu
  Cc: kbuild-all, netdev, Hannes Frederic Sowa, Nikolay Aleksandrov,
	linus.luessing, Hangbin Liu
In-Reply-To: <1479454321-31304-1-git-send-email-liuhangbin@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2471 bytes --]

Hi Hangbin,

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Hangbin-Liu/bridge-add-igmpv3-and-mldv2-query-support/20161118-155854
config: powerpc-defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   net/bridge/br_multicast.c: In function 'mld_force_mld_version':
>> net/bridge/br_multicast.c:688:24: error: 'struct net' has no member named 'ipv6'; did you mean 'ipv4'?
     if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
                           ^~
   net/bridge/br_multicast.c:689:28: error: 'struct net' has no member named 'ipv6'; did you mean 'ipv4'?
      return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
                               ^~
   net/bridge/br_multicast.c: In function 'br_multicast_alloc_query':
   net/bridge/br_multicast.c:699:27: error: implicit declaration of function '__in6_dev_get' [-Werror=implicit-function-declaration]
     struct inet6_dev *idev = __in6_dev_get(br->dev);
                              ^~~~~~~~~~~~~
   net/bridge/br_multicast.c:699:27: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
   net/bridge/br_multicast.c:699:20: warning: unused variable 'idev' [-Wunused-variable]
     struct inet6_dev *idev = __in6_dev_get(br->dev);
                       ^~~~
   At top level:
   net/bridge/br_multicast.c:686:12: warning: 'mld_force_mld_version' defined but not used [-Wunused-function]
    static int mld_force_mld_version(const struct inet6_dev *idev)
               ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +688 net/bridge/br_multicast.c

   682		return skb;
   683	}
   684	#endif
   685	
   686	static int mld_force_mld_version(const struct inet6_dev *idev)
   687	{
 > 688		if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
   689			return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
   690		else
   691			return idev->cnf.force_mld_version;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 22647 bytes --]

^ permalink raw reply

* [PATCH net-next] cadence: Add hardware PTP support.
From: Rafal Ozieblo @ 2016-11-18 10:47 UTC (permalink / raw)
  To: Nicolas Ferre, Harini Katakam, Andrei Pistirica, netdev,
	linux-kernel
  Cc: Rafal Ozieblo

Signed-off-by: Rafal Ozieblo <rafalo@cadence.com>
---
 Documentation/devicetree/bindings/net/macb.txt |   1 +
 drivers/net/ethernet/cadence/macb.c            | 742 ++++++++++++++++++++++++-
 drivers/net/ethernet/cadence/macb.h            | 217 +++++++-
 3 files changed, 950 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt
index 1506e94..27966ae 100644
--- a/Documentation/devicetree/bindings/net/macb.txt
+++ b/Documentation/devicetree/bindings/net/macb.txt
@@ -22,6 +22,7 @@ Required properties:
 	Required elements: 'pclk', 'hclk'
 	Optional elements: 'tx_clk'
 	Optional elements: 'rx_clk' applies to cdns,zynqmp-gem
+	Optional elements: 'tsu_clk'
 - clocks: Phandles to input clocks.
 
 Optional properties for PHY child node:
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index e1847ce..8481e4a 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -32,7 +32,10 @@
 #include <linux/of_gpio.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
-
+#include <linux/ptp_clock_kernel.h>
+#include <linux/clocksource.h>
+#include <linux/net_tstamp.h>
+#include <linux/timecounter.h>
 #include "macb.h"
 
 #define MACB_RX_BUFFER_SIZE	128
@@ -665,6 +668,81 @@ static void macb_tx_error_task(struct work_struct *work)
 	spin_unlock_irqrestore(&bp->lock, flags);
 }
 
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+static int macb_hw_timestamp(struct macb *bp, u32 dma_desc_ts_1, u32 dma_desc_ts_2, struct timespec64 *ts)
+{
+	struct timespec64 tsu;
+
+	ts->tv_sec = (MACB_BFEXT(DMA_TS_MSB_SEC, dma_desc_ts_2) << MACB_DMA_TS_LSB_SEC_SIZE) |
+			MACB_BFEXT(DMA_TS_LSB_SEC, dma_desc_ts_1);
+	ts->tv_nsec = MACB_BFEXT(DMA_TS_NSEC, dma_desc_ts_1);
+
+	/* TSU overlaping workaround
+	 * The timestamp only contains lower few bits of seconds,
+	 * so add value from 1588 timer
+	 */
+	macb_ptp_time_get(bp, &tsu);
+
+	/* If the top bit is set in the timestamp,
+	 * but not in 1588 timer, it has rolled over,
+	 * so subtract max size
+	 */
+	if ((ts->tv_sec & (MACB_DMA_TS_SEC_TOP >> 1)) && 
+		!(tsu.tv_sec & (MACB_DMA_TS_SEC_TOP >> 1)))
+		ts->tv_sec -= MACB_DMA_TS_SEC_TOP;
+
+	ts->tv_sec += ((~MACB_DMA_TS_SEC_MASK) & (tsu.tv_sec));
+
+	return 0;
+}
+
+static void macb_tstamp_tx(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc)
+{
+	struct skb_shared_hwtstamps shhwtstamps;
+	struct timespec64 ts;
+
+	if(MACB_BFEXT(DMA_TX_TS_VALID, desc->ctrl)) {
+		macb_hw_timestamp(bp, desc->dma_desc_ts_1, desc->dma_desc_ts_2, &ts);
+		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+		shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+		skb_tstamp_tx(skb, &shhwtstamps);
+	}
+}
+
+static void macb_tx_timestamp_flush(struct work_struct *work)
+{
+	struct macb_queue *queue = container_of(work, struct macb_queue, tx_timestamp_task);
+	struct macb_tx_timestamp *tx_timestamp;
+	unsigned long head = smp_load_acquire(&queue->tx_tstamp_head);
+	unsigned long tail = queue->tx_tstamp_tail;
+
+	while (CIRC_CNT(head, tail, PTP_TS_BUFFER_SIZE)) {
+		tx_timestamp = &queue->tx_timestamps[tail];
+		macb_tstamp_tx(queue->bp, tx_timestamp->skb, &tx_timestamp->desc);
+		/* cleanup */
+		dev_kfree_skb_any(tx_timestamp->skb);
+		smp_store_release(&queue->tx_tstamp_tail, (tail + 1) & (PTP_TS_BUFFER_SIZE - 1));
+		tail = queue->tx_tstamp_tail;
+	}
+}
+
+static int macb_tx_timestamp_add(struct macb_queue *queue, struct sk_buff *skb, struct macb_dma_desc *desc)
+{
+	struct macb_tx_timestamp *tx_timestamp;
+	unsigned long head = queue->tx_tstamp_head;
+	unsigned long tail = ACCESS_ONCE(queue->tx_tstamp_tail);
+
+	if (CIRC_SPACE(head, tail, PTP_TS_BUFFER_SIZE) == 0)
+		return -ENOMEM;
+
+	tx_timestamp = &queue->tx_timestamps[head];
+	tx_timestamp->skb = skb;
+	memcpy(&tx_timestamp->desc, desc, sizeof(tx_timestamp->desc));
+	smp_store_release(&queue->tx_tstamp_head, (head + 1) & (PTP_TS_BUFFER_SIZE - 1));
+	return 0;
+}
+#endif
+
 static void macb_tx_interrupt(struct macb_queue *queue)
 {
 	unsigned int tail;
@@ -712,6 +790,16 @@ static void macb_tx_interrupt(struct macb_queue *queue)
 				netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
 					    macb_tx_ring_wrap(bp, tail),
 					    skb->data);
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+				if (bp->ptp_hw_support)
+					if (macb_tx_timestamp_add(queue, skb, desc) == 0) {
+						 /* skb now belongs to timestamp buffer
+						 * and will be removed later
+						 */
+						tx_skb->skb = NULL;
+						schedule_work(&queue->tx_timestamp_task);
+					}
+#endif
 				bp->stats.tx_packets++;
 				bp->stats.tx_bytes += skb->len;
 			}
@@ -876,6 +964,17 @@ static int gem_rx(struct macb *bp, int budget)
 		bp->stats.rx_packets++;
 		bp->stats.rx_bytes += skb->len;
 
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+		if (bp->ptp_hw_support) {
+			struct timespec64 ts;
+
+			if (MACB_BFEXT(DMA_RX_TS_VALID, desc->addr)) {
+				macb_hw_timestamp(bp, desc->dma_desc_ts_1, desc->dma_desc_ts_2, &ts);
+				skb_hwtstamps(skb)->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+			}
+		}
+#endif
+
 #if defined(DEBUG) && defined(VERBOSE_DEBUG)
 		netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
 			    skb->len, skb->csum);
@@ -1103,6 +1202,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 	struct macb *bp = queue->bp;
 	struct net_device *dev = bp->dev;
 	u32 status, ctrl;
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+	struct timespec64 ts;
+#endif
 
 	status = queue_readl(queue, ISR);
 
@@ -1195,6 +1297,87 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 				queue_writel(queue, ISR, MACB_BIT(HRESP));
 		}
 
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+		if (status & MACB_BIT(PTP_DELAY_REQ_FRAME_RECEIVED)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(PTP_DELAY_REQ_FRAME_RECEIVED));
+			if (macb_ptp_time_frame_rx_get(bp, &ts) != 0) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			}
+			macb_ptp_event(bp, &ts);
+		}
+
+		if (status & MACB_BIT(PTP_SYNC_FRAME_RECEIVED)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(PTP_SYNC_FRAME_RECEIVED));
+			if (macb_ptp_time_frame_rx_get(bp, &ts) != 0) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			}
+			macb_ptp_event(bp, &ts);
+		}
+
+		if (status & MACB_BIT(PTP_DELAY_REQ_FRAME_TRANSMITTED)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(PTP_DELAY_REQ_FRAME_TRANSMITTED));
+			if (macb_ptp_time_frame_tx_get(bp, &ts) != 0) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			}
+			macb_ptp_event(bp, &ts);
+		}
+
+		if (status & MACB_BIT(PTP_SYNC_FRAME_TRANSMITTED)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(PTP_SYNC_FRAME_TRANSMITTED));
+			if (macb_ptp_time_frame_tx_get(bp, &ts) != 0) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			}
+			macb_ptp_event(bp, &ts);
+		}
+
+		if (status & MACB_BIT(PTP_PDELAY_REQ_FRAME_RECEIVED)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(PTP_PDELAY_REQ_FRAME_RECEIVED));
+			if (macb_ptp_time_peer_frame_rx_get(bp, &ts) != 0) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			}
+			macb_ptp_event(bp, &ts);
+		}
+
+		if (status & MACB_BIT(PTP_PDELAY_RESP_FRAME_RECEIVED)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(PTP_PDELAY_RESP_FRAME_RECEIVED));
+			if (macb_ptp_time_peer_frame_rx_get(bp, &ts) != 0) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			}
+			macb_ptp_event(bp, &ts);
+		}
+
+		if (status & MACB_BIT(PTP_PDELAY_REQ_FRAME_TRANSMITTED)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(PTP_PDELAY_REQ_FRAME_TRANSMITTED));
+			if (macb_ptp_time_peer_frame_tx_get(bp, &ts) != 0) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			}
+			macb_ptp_event(bp, &ts);
+		}
+
+		if (status & MACB_BIT(PTP_PDELAY_RESP_FRAME_TRANSMITTED)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(PTP_PDELAY_RESP_FRAME_TRANSMITTED));
+			if (macb_ptp_time_peer_frame_tx_get(bp, &ts) != 0) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 0;
+			}
+			macb_ptp_event(bp, &ts);
+		}
+#endif
 		status = queue_readl(queue, ISR);
 	}
 
@@ -1422,7 +1605,10 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Make newly initialized descriptor visible to hardware */
 	wmb();
 
-	skb_tx_timestamp(skb);
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+	if (!bp->ptp_hw_support)
+#endif
+		skb_tx_timestamp(skb);
 
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 
@@ -1752,6 +1938,9 @@ static void macb_configure_dma(struct macb *bp)
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 		dmacfg |= GEM_BIT(ADDR64);
 #endif
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+		dmacfg |= GEM_BIT(RX_EXTENDED_MODE) | GEM_BIT(TX_EXTENDED_MODE);
+#endif
 		netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
 			   dmacfg);
 		gem_writel(bp, DMACFG, dmacfg);
@@ -1763,7 +1952,7 @@ static void macb_init_hw(struct macb *bp)
 	struct macb_queue *queue;
 	unsigned int q;
 
-	u32 config;
+	u32 config, ier;
 
 	macb_reset_hw(bp);
 	macb_set_hwaddr(bp);
@@ -1808,10 +1997,21 @@ static void macb_init_hw(struct macb *bp)
 #endif
 
 		/* Enable interrupts */
-		queue_writel(queue, IER,
-			     MACB_RX_INT_FLAGS |
-			     MACB_TX_INT_FLAGS |
-			     MACB_BIT(HRESP));
+		ier = MACB_RX_INT_FLAGS |
+			MACB_TX_INT_FLAGS |
+			MACB_BIT(HRESP);
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+		if (bp->ptp_hw_support)
+			ier |= MACB_BIT(PTP_DELAY_REQ_FRAME_TRANSMITTED) |
+				MACB_BIT(PTP_SYNC_FRAME_TRANSMITTED) |
+				MACB_BIT(PTP_PDELAY_REQ_FRAME_TRANSMITTED) |
+				MACB_BIT(PTP_PDELAY_RESP_FRAME_TRANSMITTED) |
+				MACB_BIT(PTP_DELAY_REQ_FRAME_RECEIVED) |
+				MACB_BIT(PTP_SYNC_FRAME_RECEIVED) |
+				MACB_BIT(PTP_PDELAY_REQ_FRAME_RECEIVED) |
+				MACB_BIT(PTP_PDELAY_RESP_FRAME_RECEIVED);
+#endif
+		queue_writel(queue, IER, ier);
 	}
 
 	/* Enable TX and RX */
@@ -2183,6 +2383,34 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 		regs_buff[13] = gem_readl(bp, DMACFG);
 }
 
+int macb_get_ts_info(struct net_device *dev, struct ethtool_ts_info *ts_info)
+{
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+	struct macb *bp = netdev_priv(dev);
+
+	if (bp->ptp_hw_support) {
+		ts_info->phc_index = ptp_clock_index(bp->ptp_clock);
+		ts_info->so_timestamping =
+			SOF_TIMESTAMPING_TX_SOFTWARE |
+			SOF_TIMESTAMPING_RX_SOFTWARE |
+			SOF_TIMESTAMPING_TX_HARDWARE |
+			SOF_TIMESTAMPING_RX_HARDWARE |
+			SOF_TIMESTAMPING_RAW_HARDWARE |
+			SOF_TIMESTAMPING_SOFTWARE;
+		ts_info->tx_types =
+			(1 << HWTSTAMP_TX_ONESTEP_SYNC) |
+			(1 << HWTSTAMP_TX_OFF) |
+			(1 << HWTSTAMP_TX_ON);
+		ts_info->rx_filters =
+			(1 << HWTSTAMP_FILTER_NONE) |
+			(1 << HWTSTAMP_FILTER_ALL);
+		return 0;
+	}
+	else
+#endif
+		return ethtool_op_get_ts_info(dev, ts_info);
+}
+
 static void macb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
 	struct macb *bp = netdev_priv(netdev);
@@ -2283,7 +2511,7 @@ static const struct ethtool_ops gem_ethtool_ops = {
 	.get_regs_len		= macb_get_regs_len,
 	.get_regs		= macb_get_regs,
 	.get_link		= ethtool_op_get_link,
-	.get_ts_info		= ethtool_op_get_ts_info,
+	.get_ts_info		= macb_get_ts_info,
 	.get_ethtool_stats	= gem_get_ethtool_stats,
 	.get_strings		= gem_get_ethtool_strings,
 	.get_sset_count		= gem_get_sset_count,
@@ -2293,6 +2521,100 @@ static const struct ethtool_ops gem_ethtool_ops = {
 	.set_ringparam		= macb_set_ringparam,
 };
 
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+int macb_get_ts(struct net_device *dev, struct ifreq *rq)
+{
+	struct macb *bp = netdev_priv(dev);
+	struct hwtstamp_config *tstamp_config = &bp->tstamp_config;
+
+	if (!bp->ptp_hw_support)
+		return -EFAULT;
+	if (copy_to_user(rq->ifr_data, tstamp_config, sizeof(*tstamp_config)))
+		return -EFAULT;
+	else
+		return 0;
+}
+
+int macb_set_ts(struct net_device *dev, struct ifreq *rq)
+{
+	struct macb *bp = netdev_priv(dev);
+	struct hwtstamp_config *tstamp_config = &bp->tstamp_config;
+
+	struct timespec64 ts;
+	struct incrementspec incr_spec;
+
+	enum macb_bd_control tx_bd_control;
+	enum macb_bd_control rx_bd_control;
+
+	if (!bp->ptp_hw_support)
+		return -EFAULT;
+
+	if (copy_from_user(tstamp_config, rq->ifr_data, sizeof(*tstamp_config)))
+		return -EFAULT;
+
+	switch (tstamp_config->tx_type) {
+	case HWTSTAMP_TX_OFF:
+		break;
+	case HWTSTAMP_TX_ONESTEP_SYNC:
+		if (macb_ptp_set_one_step_sync(bp, 1) != 0)
+			return -ERANGE;
+	case HWTSTAMP_TX_ON:
+		tx_bd_control = TSTAMP_ALL_FRAMES;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (tstamp_config->rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+		break;
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+		rx_bd_control =  TSTAMP_ALL_PTP_FRAMES;
+		tstamp_config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+		break;
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_ALL:
+		rx_bd_control = TSTAMP_ALL_FRAMES;
+		tstamp_config->rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	default:
+		tstamp_config->rx_filter = HWTSTAMP_FILTER_NONE;
+		return -ERANGE;
+	}
+
+	/* 1. get current system time */
+	ts = ns_to_timespec64(ktime_to_ns(ktime_get_real()));
+
+	/* 2. set ptp timer */
+	macb_ptp_time_set(bp, &ts);
+
+	/* 3. set PTP timer increment value to BASE_INCREMENT */
+	incr_spec.sub_ns = bp->tsu_incr.sub_ns;
+	incr_spec.ns = bp->tsu_incr.ns;
+	macb_ptp_increment_set(bp, &incr_spec);
+
+	if (macb_ptp_set_tstamp_mode(bp, tx_bd_control, rx_bd_control) != 0)
+		return -ERANGE;
+
+	if (copy_to_user(rq->ifr_data, tstamp_config, sizeof(*tstamp_config)))
+		return -EFAULT;
+	else
+		return 0;
+}
+#endif
+
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct phy_device *phydev = dev->phydev;
@@ -2303,6 +2625,13 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!phydev)
 		return -ENODEV;
 
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+	if (cmd == SIOCGHWTSTAMP)
+		return macb_get_ts(dev, rq);
+
+	if (cmd == SIOCSHWTSTAMP)
+		return macb_set_ts(dev, rq);
+#endif
 	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
@@ -3147,6 +3476,17 @@ static int macb_probe(struct platform_device *pdev)
 		    macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID),
 		    dev->base_addr, dev->irq, dev->dev_addr);
 
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+	/* Enable PTP */
+	bp->ptp_hw_support = false;
+	if (GEM_BFEXT(TSU, gem_readl(bp, DCFG5))) {
+		err = macb_ptp_init(pdev);
+		if (err)
+			dev_err(&pdev->dev, "Cannot initialize ptp.\n");
+		else
+			bp->ptp_hw_support = true;
+	}
+#endif
 	return 0;
 
 err_out_unregister_mdio:
@@ -3245,6 +3585,392 @@ static int __maybe_unused macb_resume(struct device *dev)
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+int macb_ptp_init(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct macb *bp = netdev_priv(dev);
+	u64 tsu_f, temp;
+	unsigned int q;
+	struct macb_queue *queue;
+
+	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+		queue->tx_tstamp_head = 0;
+		queue->tx_tstamp_tail = 0;
+		INIT_WORK(&queue->tx_timestamp_task, macb_tx_timestamp_flush);
+	}
+
+	snprintf(bp->ptp_clock_info.name, 16, "macb_ptp");
+	bp->ptp_clock_info.max_adj   = (64E6);
+	bp->ptp_clock_info.n_alarm   = 1;
+	bp->ptp_clock_info.n_ext_ts  = 1;
+	bp->ptp_clock_info.n_per_out = 0;
+	bp->ptp_clock_info.n_pins    = 0;
+	bp->ptp_clock_info.pps	     = 1;
+	bp->ptp_clock_info.adjfreq   = macb_ptp_adjfreq;
+	bp->ptp_clock_info.adjtime   = macb_ptp_adjtime;
+	bp->ptp_clock_info.gettime64 = macb_ptp_gettime;
+	bp->ptp_clock_info.settime64 = macb_ptp_settime;
+	bp->ptp_clock_info.enable    = macb_ptp_enable;
+
+	bp->ptp_clock = ptp_clock_register(&bp->ptp_clock_info, &pdev->dev);
+
+	bp->tsu_clk = devm_clk_get(&pdev->dev, "tsu_clk");
+	if (!IS_ERR(bp->tsu_clk)) {
+		tsu_f = clk_get_rate(bp->tsu_clk);
+	}
+	/* try pclk instead */
+	else if (!IS_ERR(bp->pclk)) {
+		bp->tsu_clk = bp->pclk;
+		tsu_f = clk_get_rate(bp->tsu_clk);
+	} else
+		return -ENOTSUPP;
+
+	bp->tsu_incr.ns = div_u64(NSEC_PER_SEC, tsu_f);
+	temp = (NSEC_PER_SEC - ((u64)bp->tsu_incr.ns * tsu_f));
+	temp *= (1 << MACB_SUB_NS_INCR_SIZE);
+	bp->tsu_incr.sub_ns = div_u64(temp, tsu_f);
+
+	return 0;
+}
+
+void macb_ptp_stop(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct macb *bp = netdev_priv(dev);
+
+	if (bp->ptp_clock)
+		ptp_clock_unregister(bp->ptp_clock);
+}
+
+/* Interface of Linux PTP Framework */
+
+int macb_ptp_adjfreq(struct ptp_clock_info *ptp_clock_info, s32 ppb)
+{
+	struct incrementspec incr_spec;
+	struct macb *bp = container_of(ptp_clock_info, struct macb, ptp_clock_info);
+	u64 period, temp;
+	bool neg_adj = false;
+	unsigned long flags;
+
+	if (!ptp_clock_info)
+		return -EINVAL;
+
+	if (ppb < 0) {
+		neg_adj = true;
+		ppb = -ppb;
+	}
+
+	/* Adjustment is relative to base frequency */
+	incr_spec.sub_ns = bp->tsu_incr.sub_ns;
+	incr_spec.ns = bp->tsu_incr.ns;
+
+	/* scaling */
+	period = ((u64) incr_spec.ns << MACB_SUB_NS_INCR_SIZE) + incr_spec.sub_ns;
+	temp = (u64)ppb * period;
+	/* Divide with rounding, equivalent to floating dividing:
+	 * (temp / NSEC_PER_SEC) + 0.5
+	 */
+	temp = div_u64(temp + (NSEC_PER_SEC >> 1), NSEC_PER_SEC);
+
+	period = neg_adj ? (period - temp) : (period + temp);
+
+	incr_spec.ns = (period >> MACB_SUB_NS_INCR_SIZE) & ((1 << MACB_NUM_INCS_SIZE) - 1);
+	incr_spec.sub_ns = period & ((1 << MACB_SUB_NS_INCR_SIZE) - 1);
+
+	spin_lock_irqsave(&bp->lock, flags);
+	macb_ptp_increment_set(bp, &incr_spec);
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+	return 0;
+}
+
+int macb_ptp_adjtime(struct ptp_clock_info *ptp_clock_info, s64 delta)
+{
+
+	u64 ts_nsec;
+	struct timespec64 ts;
+	struct macb *bp = container_of(ptp_clock_info, struct macb, ptp_clock_info);
+
+	if (!ptp_clock_info)
+		return -EINVAL;
+
+	if (delta >= -TSU_NSEC_MAX_VAL && delta <= TSU_NSEC_MAX_VAL) {
+		macb_ptp_time_adjust(bp, (s32)delta);
+	} else {
+		macb_ptp_time_get(bp, &ts);
+
+		ts_nsec = ts.tv_nsec + ts.tv_sec * NSEC_PER_SEC;
+		ts_nsec += delta;
+
+		ts.tv_sec = div_u64(ts_nsec, NSEC_PER_SEC);
+		ts.tv_nsec = ts_nsec - ts.tv_sec * NSEC_PER_SEC;
+
+		macb_ptp_time_set(bp, &ts);
+	}
+
+	return 0;
+}
+
+
+int macb_ptp_gettime(struct ptp_clock_info *ptp_clock_info, struct timespec64 *ts)
+{
+	struct macb *bp = container_of(ptp_clock_info, struct macb, ptp_clock_info);
+
+	if (!ptp_clock_info || !ts)
+		return -EINVAL;
+
+	macb_ptp_time_get(bp, ts);
+	return 0;
+}
+
+int macb_ptp_settime(struct ptp_clock_info *ptp_clock_info, const struct timespec64 *ts)
+{
+	struct macb *bp = container_of(ptp_clock_info, struct macb, ptp_clock_info);
+
+	if (!ptp_clock_info || !ts)
+		return -EINVAL;
+
+	macb_ptp_time_set(bp, ts);
+	return 0;
+}
+
+int macb_ptp_enable(struct ptp_clock_info *ptp_clock_info,
+		    struct ptp_clock_request *request, int on)
+{
+	struct macb *bp = container_of(ptp_clock_info, struct macb, ptp_clock_info);
+	u32 mask;
+
+	if (!ptp_clock_info || !request)
+		return -EINVAL;
+
+	switch (request->type) {
+	case PTP_CLK_REQ_EXTTS:	/* Toggle TSU match interrupt */
+		mask = macb_readl(bp, IMR) | (1 << MACB_TSU_TIMER_COMPARISON_INTERRUPT_OFFSET);
+		if (on)
+			macb_writel(bp, IER, mask);
+		else
+			macb_writel(bp, IDR, mask);
+		break;
+	case PTP_CLK_REQ_PEROUT: /* Toggle Periodic output */
+		return -EOPNOTSUPP;
+		/* break; */
+	case PTP_CLK_REQ_PPS:	/* Toggle TSU periodic (second) interrupt */
+		mask = macb_readl(bp, IMR) | (1 << MACB_TSU_SECONDS_REGISTER_INCREMENT_OFFSET);
+		if (on)
+			macb_writel(bp, IER, mask);
+		else
+			macb_writel(bp, IDR, mask);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+
+/* End of Interface of Linux PTP Framework */
+
+int macb_ptp_increment_get(struct macb *bp, struct incrementspec *incr_spec)
+{
+	u32 sub_ns_reg;
+	u32 ns_reg;
+
+	if (!bp || !incr_spec)
+		return -EINVAL;
+
+	sub_ns_reg = macb_readl(bp, TSU_TIMER_INCR_SUB_NSEC);
+	ns_reg = macb_readl(bp, TSU_TIMER_INCR);
+
+	incr_spec->sub_ns = MACB_BFEXT(SUB_NS_INCR_MSB, sub_ns_reg) << MACB_SUB_NS_INCR_LSB_SIZE | MACB_BFEXT(SUB_NS_INCR_LSB, sub_ns_reg);
+	incr_spec->ns = MACB_BFEXT(NS_INCREMENT, ns_reg);
+
+	return 0;
+}
+
+int macb_ptp_increment_set(struct macb *bp, struct incrementspec *incr_spec)
+{
+	u32 sub_ns_reg;
+	u32 ns_reg;
+
+	if (!bp || !incr_spec)
+		return -EINVAL;
+
+	sub_ns_reg = MACB_BF(SUB_NS_INCR_LSB, incr_spec->sub_ns)
+			| (((incr_spec->sub_ns & ~((1 << MACB_SUB_NS_INCR_LSB_SIZE) - 1)) >> MACB_SUB_NS_INCR_LSB_SIZE));
+	ns_reg = incr_spec->ns;
+
+	/* tsu_timer_incr register must be written after the tsu_timer_incr_sub_ns register
+	 * and the write operation will cause the value written to the tsu_timer_incr_sub_ns
+	 * register to take effect.
+	 */
+	macb_writel(bp, TSU_TIMER_INCR_SUB_NSEC, sub_ns_reg);
+	macb_writel(bp, TSU_TIMER_INCR, ns_reg);
+
+	return 0;
+}
+
+int macb_ptp_time_adjust(struct macb *bp, s32 delta)
+{
+	bool subtract = 0;
+	u32 val = 0;
+
+	if (!bp)
+		return -EINVAL;
+
+	if ((delta < -TSU_NSEC_MAX_VAL) || (delta > TSU_NSEC_MAX_VAL))
+		return -EINVAL;
+
+	if (delta < 0) {
+		subtract = 1;
+		delta = -delta;
+	}
+
+	val = (subtract << MACB_ADD_SUBTRACT_OFFSET) | delta;
+
+	macb_writel(bp, TSU_TIMER_ADJUST, val);
+
+	return 0;
+}
+
+int macb_ptp_time_get(struct macb *bp, struct timespec64 *ts)
+{
+	long first, second;
+	u32 sec, msb_sec;
+
+	if (!bp || !ts)
+		return -EINVAL;
+
+	first = macb_readl(bp, TSU_TMR_NSEC);
+	sec = macb_readl(bp, TSU_TMR_SEC);
+	msb_sec = macb_readl(bp, TSU_TMR_MSB_SEC);
+	second = macb_readl(bp, TSU_TMR_NSEC);
+
+	/* test for nsec rollover */
+	if (first > second) {
+		/* if so, use later read & re-read seconds
+		 * (assume all done within 1s)
+		 */
+		ts->tv_nsec = macb_readl(bp, TSU_TMR_NSEC);
+		sec = macb_readl(bp, TSU_TMR_SEC);
+		msb_sec = macb_readl(bp, TSU_TMR_MSB_SEC);
+	} else
+		ts->tv_nsec = first;
+
+	ts->tv_sec = (((u64)msb_sec << MACB_TIMER_LSB_SEC_SIZE) | sec)
+			& TSU_SEC_MAX_VAL;
+
+	return 0;
+}
+
+int macb_ptp_time_set(struct macb *bp, const struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	macb_writel(bp, TSU_TMR_MSB_SEC, (ts->tv_sec >> MACB_TIMER_LSB_SEC_SIZE)
+			& ((1 << MACB_TIMER_MSB_SEC_SIZE) - 1));
+	/* write lower bits 2nd, for synchronised secs update */
+	macb_writel(bp, TSU_TMR_SEC, ts->tv_sec & (((u64)1 << MACB_TIMER_LSB_SEC_SIZE) - 1));
+	macb_writel(bp, TSU_TMR_NSEC, ts->tv_nsec);
+
+	return 0;
+}
+
+int macb_ptp_time_peer_frame_tx_get(struct macb *bp, struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	ts->tv_sec = (((u64)macb_readl(bp, TSU_PEER_TX_MSB_SEC) << 32) |
+		macb_readl(bp, TSU_PEER_TX_SEC)) & TSU_SEC_MAX_VAL;
+	ts->tv_nsec = macb_readl(bp, TSU_PEER_TX_NSEC);
+
+	return 0;
+}
+
+int macb_ptp_time_peer_frame_rx_get(struct macb *bp, struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	ts->tv_sec = (((u64)macb_readl(bp, TSU_PEER_RX_MSB_SEC) << 32) |
+		macb_readl(bp, TSU_PEER_RX_SEC)) & TSU_SEC_MAX_VAL;
+	ts->tv_nsec = macb_readl(bp, TSU_PEER_RX_NSEC);
+
+	return 0;
+}
+
+int macb_ptp_time_frame_tx_get(struct macb *bp, struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	ts->tv_sec = (((u64)macb_readl(bp, TSU_PTP_TX_MSB_SEC) << 32) |
+		macb_readl(bp, TSU_PTP_TX_SEC)) & TSU_SEC_MAX_VAL;
+	ts->tv_nsec = macb_readl(bp, TSU_PTP_TX_NSEC);
+
+	return 0;
+}
+
+int macb_ptp_time_frame_rx_get(struct macb *bp, struct timespec64 *ts)
+{
+	if (!bp || !ts)
+		return -EINVAL;
+
+	ts->tv_sec = (((u64)macb_readl(bp, TSU_PTP_RX_MSB_SEC) << 32) |
+		      macb_readl(bp, TSU_PTP_RX_SEC)) & TSU_SEC_MAX_VAL;
+	ts->tv_nsec = macb_readl(bp, TSU_PTP_RX_NSEC);
+
+	return 0;
+}
+
+int macb_ptp_event(struct macb *bp, struct timespec64 *ts)
+{
+	struct ptp_clock_event event;
+
+	event.type = PTP_CLOCK_EXTTS;
+	event.index = 0;
+	event.timestamp = ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec;
+
+	ptp_clock_event(bp->ptp_clock, &event);
+
+	return 0;
+}
+
+int macb_ptp_set_one_step_sync(struct macb *bp, u8 enable)
+{
+	u32 reg_val;
+
+	if (!bp)
+		return -EINVAL;
+	if (enable < 0 || enable > 1)
+		return -EINVAL;
+
+	reg_val = macb_readl(bp, NCR);
+
+	if (enable)
+		macb_writel(bp, NCR, reg_val | MACB_BIT(ONE_STEP_SYNC_MODE));
+	else
+		macb_writel(bp, NCR, reg_val & ~MACB_BIT(ONE_STEP_SYNC_MODE));
+
+	return 0;
+}
+
+int macb_ptp_set_tstamp_mode(struct macb *bp,
+			     enum macb_bd_control tx_bd_control,
+			     enum macb_bd_control rx_bd_control)
+{
+	if (!bp)
+		return -EINVAL;
+
+	macb_writel(bp, TX_BD_CONTROL, MACB_BF(TX_BD_TS_MODE, tx_bd_control));
+	macb_writel(bp, RX_BD_CONTROL, MACB_BF(RX_BD_TS_MODE, rx_bd_control));
+
+	return 0;
+}
+#endif
+
 static SIMPLE_DEV_PM_OPS(macb_pm_ops, macb_suspend, macb_resume);
 
 static struct platform_driver macb_driver = {
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 1216950..1381f0a 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -66,8 +66,32 @@
 #define MACB_USRIO		0x00c0
 #define MACB_WOL		0x00c4
 #define MACB_MID		0x00fc
-#define MACB_TBQPH		0x04C8
-#define MACB_RBQPH		0x04D4
+
+#define MACB_TSU_PTP_TX_MSB_SEC		0x00e8	/* PTP Event Frame Transmitted Seconds Register 47:32 */
+#define MACB_TSU_PTP_RX_MSB_SEC		0x00ec	/* PTP Event Frame Received Seconds Register 47:32 */
+#define MACB_TSU_PEER_TX_MSB_SEC	0x00f0	/* PTP Peer Event Frame Transmitted Seconds Register 47:32 */
+#define MACB_TSU_PEER_RX_MSB_SEC	0x00f4	/* PTP Peer Event Frame Received Seconds Register 47:32 */
+#define MACB_TSU_TIMER_INCR_SUB_NSEC	0x01bc	/* Sub-nanoseconds increment */
+#define MACB_TSU_TIMER_INCR		0x01dc	/* Nanoseconds increment */
+#define MACB_TSU_TMR_MSB_SEC		0x01c0	/* Upper second count of Time Stamp Unit */
+#define MACB_TSU_TMR_SEC		0x01d0	/* Lower second count of Time Stamp Unit */
+#define MACB_TSU_TMR_NSEC		0x01d4	/* Nanosecond count of Time Stamp Unit */
+#define MACB_TSU_TIMER_ADJUST		0x01d8	/* Nanosecond Adjust Register */
+#define MACB_TSU_TIMER_INCR_SUB_NSEC	0x01bc	/* Sub-nanosecond Adjust Register */
+#define MACB_TSU_TIMER_INCR		0x01dc	/* Nanosecond Adjust Register */
+#define MACB_TSU_PTP_TX_SEC		0x01e0	/* PTP Event Frame Transmitted Seconds Register 31:0 */
+#define MACB_TSU_PTP_TX_NSEC		0x01e4	/* PTP Event Frame Transmitted Nanoseconds Register */
+#define MACB_TSU_PTP_RX_SEC		0x01e8	/* PTP Event Frame Received Seconds Register 31:0 */
+#define MACB_TSU_PTP_RX_NSEC		0x01ec	/* PTP Event Frame Received Nanoseconds Register */
+#define MACB_TSU_PEER_TX_SEC		0x01f0	/* PTP Peer Event Frame Transmitted Seconds Register 31:0 */
+#define MACB_TSU_PEER_TX_NSEC		0x01f4	/* PTP Peer Event Frame Transmitted Nanoseconds Register */
+#define MACB_TSU_PEER_RX_SEC		0x01f8	/* PTP Peer Event Frame Received Seconds Register 31:0 */
+#define MACB_TSU_PEER_RX_NSEC		0x01fc	/* PTP Peer Event Frame Received Nanoseconds Register */
+
+#define MACB_TX_BD_CONTROL 	0x04cc /* TX Buffer Descriptor control register */
+#define MACB_RX_BD_CONTROL 	0x04d0 /* RX Buffer Descriptor control register */
+#define MACB_TBQPH		0x04c8
+#define MACB_RBQPH		0x04d4
 
 /* GEM register offsets. */
 #define GEM_NCFGR		0x0004 /* Network Config */
@@ -174,6 +198,8 @@
 #define MACB_NCR_TPF_SIZE	1
 #define MACB_TZQ_OFFSET		12 /* Transmit zero quantum pause frame */
 #define MACB_TZQ_SIZE		1
+#define MACB_ONE_STEP_SYNC_MODE_OFFSET 24 /* Enable One Step Synchro Mode */
+#define MACB_ONE_STEP_SYNC_MODE_SIZE 1
 
 /* Bitfields in NCFGR */
 #define MACB_SPD_OFFSET		0 /* Speed */
@@ -252,6 +278,10 @@
 #define GEM_RXBS_SIZE		8
 #define GEM_DDRP_OFFSET		24 /* disc_when_no_ahb */
 #define GEM_DDRP_SIZE		1
+#define GEM_RX_EXTENDED_MODE_OFFSET	28 /* RX extended Buffer Descriptor mode */
+#define GEM_RX_EXTENDED_MODE_SIZE	1
+#define GEM_TX_EXTENDED_MODE_OFFSET	29 /* TX extended Buffer Descriptor mode */
+#define GEM_TX_EXTENDED_MODE_SIZE	1
 #define GEM_ADDR64_OFFSET	30 /* Address bus width - 64b or 32b */
 #define GEM_ADDR64_SIZE		1
 
@@ -319,6 +349,26 @@
 #define MACB_PTZ_SIZE		1
 #define MACB_WOL_OFFSET		14 /* Enable wake-on-lan interrupt */
 #define MACB_WOL_SIZE		1
+#define MACB_PTP_DELAY_REQ_FRAME_RECEIVED_OFFSET	18	/* PTP delay_req frame received */
+#define MACB_PTP_DELAY_REQ_FRAME_RECEIVED_SIZE		1
+#define MACB_PTP_SYNC_FRAME_RECEIVED_OFFSET		19	/* PTP sync frame received */
+#define MACB_PTP_SYNC_FRAME_RECEIVED_SIZE		1
+#define MACB_PTP_DELAY_REQ_FRAME_TRANSMITTED_OFFSET	20	/* PTP delay_req frame transmitted */
+#define MACB_PTP_DELAY_REQ_FRAME_TRANSMITTED_SIZE	1
+#define MACB_PTP_SYNC_FRAME_TRANSMITTED_OFFSET		21	/* PTP sync frame transmitted */
+#define MACB_PTP_SYNC_FRAME_TRANSMITTED_SIZE		1
+#define MACB_PTP_PDELAY_REQ_FRAME_RECEIVED_OFFSET	22	/* PTP pdelay_req frame received */
+#define MACB_PTP_PDELAY_REQ_FRAME_RECEIVED_SIZE		1
+#define MACB_PTP_PDELAY_RESP_FRAME_RECEIVED_OFFSET	23	/* PTP pdelay_resp frame received */
+#define MACB_PTP_PDELAY_RESP_FRAME_RECEIVED_SIZE	1
+#define MACB_PTP_PDELAY_REQ_FRAME_TRANSMITTED_OFFSET	24	/* PTP pdelay_req frame transmitted */
+#define MACB_PTP_PDELAY_REQ_FRAME_TRANSMITTED_SIZE	1
+#define MACB_PTP_PDELAY_RESP_FRAME_TRANSMITTED_OFFSET	25	/* PTP pdelay_resp frame transmitted */
+#define MACB_PTP_PDELAY_RESP_FRAME_TRANSMITTED_SIZE	1
+#define MACB_TSU_SECONDS_REGISTER_INCREMENT_OFFSET	26	/* TSU periodic (second) interrup */
+#define MACB_TSU_SECONDS_REGISTER_INCREMENT_SIZE	1
+#define MACB_TSU_TIMER_COMPARISON_INTERRUPT_OFFSET	29	/* TSU match interrupt */
+#define MACB_TSU_TIMER_COMPARISON_INTERRUPT_SIZE	1
 
 /* Bitfields in MAN */
 #define MACB_DATA_OFFSET	0 /* data */
@@ -382,6 +432,10 @@
 #define GEM_TX_PKT_BUFF_OFFSET			21
 #define GEM_TX_PKT_BUFF_SIZE			1
 
+/* Bitfields in DCFG5. */
+#define GEM_TSU_OFFSET				8
+#define GEM_TSU_SIZE				1
+
 /* Constants for CLK */
 #define MACB_CLK_DIV8				0
 #define MACB_CLK_DIV16				1
@@ -402,6 +456,74 @@
 #define MACB_MAN_READ				2
 #define MACB_MAN_CODE				2
 
+/* Constants for TSU */
+/* MACB_TSU_TIMER_INCR_SUB_NSEC */
+#define MACB_SUB_NS_INCR_MSB_OFFSET	0 /* sub-ns MSB [23:8] which the 1588 timer will be incremented each clock cycle */
+#define MACB_SUB_NS_INCR_MSB_SIZE	16
+#define MACB_SUB_NS_INCR_LSB_OFFSET	24 /* sub-ns MSB [7:0] which the 1588 timer will be incremented each clock cycle */
+#define MACB_SUB_NS_INCR_LSB_SIZE	8
+#define MACB_SUB_NS_INCR_SIZE 		(MACB_SUB_NS_INCR_MSB_SIZE + MACB_SUB_NS_INCR_LSB_SIZE)
+
+/* MACB_TSU_TIMER_INCR */
+#define MACB_NS_INCREMENT_OFFSET	0 /* ns [7:0] which the 1588 timer will be incremented each clock cycle */
+#define MACB_NS_INCREMENT_SIZE		8
+#define MACB_ALT_NS_INCR_OFFSET		8 /* Alternative nanoseconds count */
+#define MACB_ALT_NS_INCR_SIZE		8
+#define MACB_NUM_INCS_OFFSET		16 /* Number of incs before alt inc */
+#define MACB_NUM_INCS_SIZE		8
+
+/* MACB_TSU_TIMER_ADJUST */
+#define MACB_INCREMENT_VALUE_OFFSET	0 /* Timer increment value */
+#define MACB_INCREMENT_VALUE_SIZE	30
+#define MACB_ADD_SUBTRACT_OFFSET	31 /* Write as one to subtract from the 1588 timer */
+#define MACB_ADD_SUBTRACT_SIZE		1
+
+/* MACB_TSU_TIMER_MSB_SEC */
+#define MACB_TIMER_MSB_SEC_OFFSET	0 /* TSU timer value (s). MSB [47:32] of seconds timer count */
+#define MACB_TIMER_MSB_SEC_SIZE		16
+
+/* MACB_TSU_TIMER_SEC */
+#define MACB_TIMER_LSB_SEC_OFFSET	0 /* TSU timer value (s). LSB [31:0] of seconds timer count */
+#define MACB_TIMER_LSB_SEC_SIZE		32
+
+/* MACB_TSU_TIMER_NSEC */
+#define MACB_TIMER_NSEC_OFFSET		0 /* TSU timer value (ns) */
+#define MACB_TIMER_NSEC_SIZE		30
+
+/* Transmit DMA buffer descriptor Word 1 */
+#define MACB_DMA_TX_TS_VALID_OFFSET	23 /* timestamp has been captured in the Buffer Descriptor */
+#define MACB_DMA_TX_TS_VALID_SIZE	1
+
+/* Receive DMA buffer descriptor Word 0 */
+#define MACB_DMA_RX_TS_VALID_OFFSET	2 /* indicates a valid timestamp in the Buffer Descriptor */
+#define MACB_DMA_RX_TS_VALID_SIZE	1
+
+/* DMA buffer descriptor Word 2 (32 bit addressing) or Word 4 (64 bit addressing) */
+#define MACB_DMA_TS_LSB_SEC_OFFSET	30 /* Timestamp seconds[1:0]  */
+#define MACB_DMA_TS_LSB_SEC_SIZE	2
+#define MACB_DMA_TS_NSEC_OFFSET		0 /* Timestamp nanosecs [29:0] */
+#define MACB_DMA_TS_NSEC_SIZE		30
+
+/* DMA buffer descriptor Word 3 (32 bit addressing) or Word 5 (64 bit addressing) */
+
+/* New hardware supports 12 bit precision of timestamp in DMA buffer descriptor.
+ * Old hardware supports only 6 bit precision but it is enough for PTP.
+ * Less accuracy is used always instead of checking hardware version.
+ */
+#define MACB_DMA_TS_MSB_SEC_OFFSET	0 /* Timestamp seconds[5:2] */
+#define MACB_DMA_TS_MSB_SEC_SIZE	4
+#define MACB_DMA_TS_SEC_WIDTH 		(MACB_DMA_TS_MSB_SEC_SIZE + MACB_DMA_TS_LSB_SEC_SIZE)
+#define MACB_DMA_TS_SEC_TOP 		(1 << MACB_DMA_TS_SEC_WIDTH)
+#define MACB_DMA_TS_SEC_MASK 		(MACB_DMA_TS_SEC_TOP - 1)
+
+/* Constants for TX_BD_CONTROL */
+#define MACB_TX_BD_TS_MODE_OFFSET	4 /* TX Descriptor Timestamp Insertion mode */
+#define MACB_TX_BD_TS_MODE_SIZE		2
+
+/* Constants for RX_BD_CONTROL */
+#define MACB_RX_BD_TS_MODE_OFFSET 	4 /* RX Descriptor Timestamp Insertion mode */
+#define MACB_RX_BD_TS_MODE_SIZE 	2
+
 /* Capability mask bits */
 #define MACB_CAPS_ISR_CLEAR_ON_WRITE		0x00000001
 #define MACB_CAPS_USRIO_HAS_CLKEN		0x00000002
@@ -449,6 +571,8 @@
 #define queue_readl(queue, reg)		(queue)->bp->macb_reg_readl((queue)->bp, (queue)->reg)
 #define queue_writel(queue, reg, value)	(queue)->bp->macb_reg_writel((queue)->bp, (queue)->reg, (value))
 
+#define PTP_TS_BUFFER_SIZE		128 /* must be power of 2 */
+
 /* Conditional GEM/MACB macros.  These perform the operation to the correct
  * register dependent on whether the device is a GEM or a MACB.  For registers
  * and bitfields that are common across both devices, use macb_{read,write}l
@@ -483,7 +607,18 @@ struct macb_dma_desc {
 	u32     addrh;
 	u32     resvd;
 #endif
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+	u32	dma_desc_ts_1;
+	u32	dma_desc_ts_2;
+#endif
+};
+
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+struct macb_tx_timestamp {
+	struct sk_buff *skb;
+	struct macb_dma_desc desc;
 };
+#endif
 
 /* DMA descriptor bitfields */
 #define MACB_RX_USED_OFFSET			0
@@ -794,8 +929,22 @@ struct macb_queue {
 	struct macb_tx_skb	*tx_skb;
 	dma_addr_t		tx_ring_dma;
 	struct work_struct	tx_error_task;
+
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+	/* PTP support */
+	struct work_struct 	tx_timestamp_task;
+	unsigned int 		tx_tstamp_head, tx_tstamp_tail;
+	struct macb_tx_timestamp tx_timestamps[PTP_TS_BUFFER_SIZE];
+#endif
 };
 
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+struct incrementspec {
+	u32 sub_ns;
+	u32 ns;
+};
+#endif
+
 struct macb {
 	void __iomem		*regs;
 	bool			native_io;
@@ -860,8 +1009,72 @@ struct macb {
 	unsigned int		jumbo_max_len;
 
 	u32			wol;
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+	/* PTP support */
+	bool ptp_hw_support;
+	struct ptp_clock_info ptp_clock_info;
+	struct ptp_clock *ptp_clock;
+	struct clk *tsu_clk;
+	struct incrementspec tsu_incr;
+	struct hwtstamp_config tstamp_config;
+#endif
+};
+
+#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
+#define MACB_TIMER_SEC_SIZE  (MACB_TIMER_MSB_SEC_SIZE + MACB_TIMER_LSB_SEC_SIZE)
+#define TSU_SEC_MAX_VAL (((u64)1 << MACB_TIMER_SEC_SIZE) - 1)
+#define TSU_NSEC_MAX_VAL ((1 << MACB_TIMER_NSEC_SIZE) - 1)
+
+enum macb_bd_control {
+	TSTAMP_DISABLED,
+	TSTAMP_FRAME_PTP_EVENT_ONLY,
+	TSTAMP_ALL_PTP_FRAMES,
+	TSTAMP_ALL_FRAMES,
 };
 
+int macb_ptp_init(struct platform_device *pdev);
+void macb_ptp_stop(struct platform_device *pdev);
+
+int macb_ptp_verify(struct ptp_clock_info *ptp_clock_info, unsigned int pin,
+		    enum ptp_pin_function func, unsigned int chan);
+
+/* Following functions implement interface functions of Linux PTP
+ * Framework.
+ */
+int macb_ptp_adjfreq(struct ptp_clock_info *ptp_clock_info, s32 ppb);
+int macb_ptp_adjtime(struct ptp_clock_info *ptp_clock_info, s64 delta);
+int macb_ptp_gettime(struct ptp_clock_info *ptp_clock_info,
+		     struct timespec64 *ts);
+int macb_ptp_settime(struct ptp_clock_info *ptp_clock_info,
+		     const struct timespec64 *ts);
+int macb_ptp_enable(struct ptp_clock_info *ptp_clock_info,
+		    struct ptp_clock_request *request, int on);
+
+/* Low level functions used by above interface. */
+int macb_ptp_time_get(struct macb *bp, struct timespec64 *ts);
+int macb_ptp_time_set(struct macb *bp, const struct timespec64 *ts);
+
+int macb_ptp_increment_get(struct macb *bp, struct incrementspec *incr_spec);
+int macb_ptp_increment_set(struct macb *bp, struct incrementspec *incr_spec);
+int macb_ptp_time_adjust(struct macb *bp, s32 delta);
+
+/* Timestamp reading functions */
+int macb_ptp_time_peer_frame_tx_get(struct macb *bp, struct timespec64 *ts);
+int macb_ptp_time_peer_frame_rx_get(struct macb *bp, struct timespec64 *ts);
+int macb_ptp_time_frame_tx_get(struct macb *bp, struct timespec64 *ts);
+int macb_ptp_time_frame_rx_get(struct macb *bp, struct timespec64 *ts);
+
+/* Event reporting functions */
+int macb_ptp_event(struct macb *bp, struct timespec64 *ts);
+
+/* Hardware configuratio functions */
+int macb_ptp_set_one_step_sync(struct macb *bp, u8 enable);
+int macb_ptp_set_tstamp_mode(struct macb *bp,
+			     enum macb_bd_control tx_bd_control,
+			     enum macb_bd_control rx_bd_control);
+
+#endif
+
 static inline bool macb_is_gem(struct macb *bp)
 {
 	return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
-- 
2.4.5

^ permalink raw reply related

* Re: [PATCH net-next] bridge: add igmpv3 and mldv2 query support
From: Nikolay Aleksandrov @ 2016-11-18 10:31 UTC (permalink / raw)
  To: Hangbin Liu, netdev; +Cc: Hannes Frederic Sowa, linus.luessing, roopa
In-Reply-To: <c1c35821-cdba-4a5e-0e53-694d10fb5918@cumulusnetworks.com>

On 18/11/16 11:09, Nikolay Aleksandrov wrote:
> On 18/11/16 11:04, Nikolay Aleksandrov wrote:
>> (+CC Roopa)
>> Hi Hangbin,
>> This patch is not correct, you should not use the net device IGMP config in the bridge.
> * bridge net device, sorry not port
>
>> These packets may never make it to the host and they may not be reflected, even more the
>> host may have very different igmp config for the port net device than the bridge does.
> * again bridge net device, not port
>
>> Also your current implementation switches to V3 only if it is globally set, and that should
>> be controlled on a per-bridge basis, even per-vlan later.
> * it is per-bridge, you use the global net device IGMP config, but it should be in the bridge
> mcast control options, so we can do it per-vlan later and also be able to do the compat parts
> of the RFC and in general, the bridge is configured via its own options not the host net device
> because as I said these packets may never be received locally

Having the host netdev options affect the bridge-specific config is really undesirable and confusing.

>
>> One more thing, if someone does a V2 leave for a group, you can end up sending them V3
>> group-specific query.
>>
>> I have been working on an implementation for IGMPv3/MLDv2 querier for the bridge device, it re-uses
>> most of the current code and allows you to configure it per-bridge (and later per-vlan). The only
>> reason I've not yet sent it to upstream is that we (at Cumulus) are working out the compatibility
>> parts (e.g. RFC3376 sec 7, sec 8) of the RFC since it has some unclear cases.

Err, RFC3376 sec 7.3.1, 7.3.2, and RFC3810 sec 8.3.1, 8.3.2

I really should get coffee.. sorry for the multiple emails :-)

>> But I can rip the compatibility out and send it early for review if you'd like, we can add the
>> compat code later.
>>
>> Cheers,
>>  Nik
>>

^ permalink raw reply

* Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Harini Katakam @ 2016-11-18 10:32 UTC (permalink / raw)
  To: Andrei Pistirica
  Cc: Rafal Ozieblo, Nicolas Ferre, harini.katakam@xilinx.com,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <27516aeb-b8f9-dc38-4d01-d2a5c5cf44dd@microchip.com>

tHi Andrei,

>> Yes, Andre's version of Cadence does not ability to report have RX
>> timestamp.
>> The version I worked with did. This is the old series I sent:
>> https://lkml.org/lkml/2015/9/11/92
>> But right now, i'm working on building on top of Andre's changes.
>
>
> I'm addressing maintainer's feedback on both patches:
> https://patchwork.kernel.org/patch/9310989/
> https://patchwork.kernel.org/patch/9310991/
>
> I've done all suggested updates, except the numerous 64bit divisions in the
> frequency adjustment callback. I've implemented a different algorithm which
> uses 2 64bit division, but I couldn't find a way to use only 1.
>
> Also, I have a version with timecounter/cyclecounter which shows a much
> better accuracy (less than 100ns level). In my opinion this could be a
> better implementation. What is you opinion about this? Did you try it?
>

I did not try timecounter on Cadence IP versions later than r1p06.
Because with sub ns precision in HW timestamp, that works better
than SW cyclecounter.
On older Zynq version, yes timecounter is used and is better.

Regards,
Harini

^ permalink raw reply

* Re: [PATCH net-next] bridge: add igmpv3 and mldv2 query support
From: kbuild test robot @ 2016-11-18 10:16 UTC (permalink / raw)
  To: Hangbin Liu
  Cc: kbuild-all, netdev, Hannes Frederic Sowa, Nikolay Aleksandrov,
	linus.luessing, Hangbin Liu
In-Reply-To: <1479454321-31304-1-git-send-email-liuhangbin@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2634 bytes --]

Hi Hangbin,

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Hangbin-Liu/bridge-add-igmpv3-and-mldv2-query-support/20161118-155854
config: i386-randconfig-r0-201646 (attached as .config)
compiler: gcc-5 (Debian 5.4.1-2) 5.4.1 20160904
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   net/bridge/br_multicast.c: In function 'mld_force_mld_version':
>> net/bridge/br_multicast.c:688:24: error: 'struct net' has no member named 'ipv6'
     if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
                           ^
   net/bridge/br_multicast.c:689:28: error: 'struct net' has no member named 'ipv6'
      return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
                               ^
   net/bridge/br_multicast.c: In function 'br_multicast_alloc_query':
>> net/bridge/br_multicast.c:699:27: error: implicit declaration of function '__in6_dev_get' [-Werror=implicit-function-declaration]
     struct inet6_dev *idev = __in6_dev_get(br->dev);
                              ^
>> net/bridge/br_multicast.c:699:27: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
>> net/bridge/br_multicast.c:699:20: warning: unused variable 'idev' [-Wunused-variable]
     struct inet6_dev *idev = __in6_dev_get(br->dev);
                       ^
   net/bridge/br_multicast.c: At top level:
   net/bridge/br_multicast.c:686:12: warning: 'mld_force_mld_version' defined but not used [-Wunused-function]
    static int mld_force_mld_version(const struct inet6_dev *idev)
               ^
   cc1: some warnings being treated as errors

vim +688 net/bridge/br_multicast.c

   682		return skb;
   683	}
   684	#endif
   685	
   686	static int mld_force_mld_version(const struct inet6_dev *idev)
   687	{
 > 688		if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
 > 689			return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
   690		else
   691			return idev->cnf.force_mld_version;
   692	}
   693	
   694	static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
   695							struct br_ip *addr,
   696							u8 *igmp_type)
   697	{
   698		struct in_device *in_dev = __in_dev_get_rcu(br->dev);
 > 699		struct inet6_dev *idev = __in6_dev_get(br->dev);
   700		switch (addr->proto) {
   701		case htons(ETH_P_IP):
   702			if (IGMP_V3_SEEN(in_dev))

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28193 bytes --]

^ permalink raw reply

* Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Nicolas Ferre @ 2016-11-18 10:14 UTC (permalink / raw)
  To: Rafal Ozieblo, Harini Katakam, Andrei Pistirica
  Cc: harini.katakam@xilinx.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <BN3PR07MB25162D82CEF09B8C7586B799C9B00@BN3PR07MB2516.namprd07.prod.outlook.com>

Le 18/11/2016 à 10:59, Rafal Ozieblo a écrit :
>>                                                     
>> -----Original Message-----                           
>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com] 
>> Sent: 18 listopada 2016 10:44                              
>> To: Rafal Ozieblo                                          
>> Cc: Nicolas Ferre; Andrei Pistirica; harini.katakam@xilinx.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org                                                                                             
>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM                           
>>                                                                                                        
>> Hi Rafal,                                                                                               
>>                                                                                                        
>> On Fri, Nov 18, 2016 at 3:00 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:                              
>>>> -----Original Message-----                                                                            
>>>> From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]                                                  
>>>> Sent: 18 listopada 2016 10:10                                                                         
>>>> To: Rafal Ozieblo; Harini Katakam; Andrei Pistirica                                                   
>>>> Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;                                                
>>>> linux-kernel@vger.kernel.org                                                                          
>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support                                 
>>>> for GEM                                                                                               
>>>>                                                                                                      
>>>> Le 18/11/2016 à 09:59, Rafal Ozieblo a écrit :                                                        
>>>>> Hello,                                                                                              
>>>>>                                                                                                     
>>>>>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com]                                         
>>>>>> Sent: 18 listopada 2016 05:30                                                                      
>>>>>> To: Rafal Ozieblo                                                                                  
>>>>>> Cc: Nicolas Ferre; harini.katakam@xilinx.com;                                                      
>>>>>> netdev@vger.kernel.org; linux-kernel@vger.kernel.org                                               
>>>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing                                      
>>>>>> support for GEM                                                                                    
>>>>>>                                                                                                    
>>>>>> Hi Rafal,                                                                                          
>>>>>>                                                                                                    
>>>>>> On Thu, Nov 17, 2016 at 7:05 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:                         
>>>>>>> -----Original Message-----                                                                        
>>>>>>> From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]                                              
>>>>>>> Sent: 17 listopada 2016 14:29                                                                     
>>>>>>> To: Harini Katakam; Rafal Ozieblo                                                                 
>>>>>>> Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;                                            
>>>>>>> linux-kernel@vger.kernel.org                                                                      
>>>>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing                                     
>>>>>>> support for GEM                                                                                   
>>>>>>>                                                                                                   
>>>>>>>> Le 17/11/2016 à 13:21, Harini Katakam a écrit :                                                  
>>>>>>>>> Hi Rafal,                                                                                       
>>>>>>>>>                                                                                                 
>>>>>>>>> On Thu, Nov 17, 2016 at 5:20 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:                      
>>>>>>>>>> Hello,                                                                                         
>>>>>>>>>> I think, there could a bug in your patch.                                                      
>>>>>>>>>>                                                                                                
>>>>>>>>>>> +                                                                                             
>>>>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                          
>>>>>>>>>>> +             dmacfg |= GEM_BIT(ADDR64); #endif                                               
>>>>>>>>>>                                                                                                
>>>>>>>>>> You enable 64 bit addressing (64b dma bus width) always when appropriate architecture config option is enabled.                                                                                         
>>>>>>>>>> But there are some legacy controllers which do not support that feature. According Cadence hardware team:                                                                                               
>>>>>>>>>> "64 bit addressing was added in July 2013. Earlier version do not have it.                     
>>>>>>>>>> This feature was enhanced in release August 2014 to have separate upper address values for transmit and receive."                                                                                       
>>>>>>>>>>                                                                                                
>>>>>>>>>>> /* Bitfields in NSR */                                                                        
>>>>>>>>>>> @@ -474,6 +479,10 @@                                                                          
>>>>>>>>>>>  struct macb_dma_desc {                                                                       
>>>>>>>>>>  >      u32     addr;                                                                          
>>>>>>>>>>>       u32     ctrl;                                                                           
>>>>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                          
>>>>>>>>>>> +     u32     addrh;                                                                          
>>>>>>>>>>> +     u32     resvd;                                                                          
>>>>>>>>>>> +#endif                                                                                       
>>>>>>>>>>>  };                                                                                           
>>>>>>>>>>                                                                                                
>>>>>>>>>> It will not work for legacy hardware. Old descriptor is 2 words wide, the new one is 4 words wide.                                                                                                      
>>>>>>>>>> If you enable CONFIG_ARCH_DMA_ADDR_T_64BIT but hardware doesn't                                
>>>>>>>>>> support it at all, you will miss every second descriptor.                                      
>>>>>>>>>>                                                                                                
>>>>>>>>>                                                                                                 
>>>>>>>>> True, this feature is not available in all of Cadence IP versions.                              
>>>>>>>>> In fact, the IP version Zynq does not support this. But the one in ZynqMP does.                 
>>>>>>>>> So, we enable kernel config for 64 bit DMA addressing for this                                  
>>>>>>>>> SoC and hence the driver picks it up. My assumption was that if                                 
>>>>>>>>> the legacy IP does not support                                                                  
>>>>>>>>> 64 bit addressing, then this DMA option wouldn't be enabled.                                    
>>>>>>>>>                                                                                                 
>>>>>>>>> There is a design config register in Cadence IP which is being                                  
>>>>>>>>> read to check for 64 bit address support - DMA mask is set based on that.                       
>>>>>>>>> But the addition of two descriptor words cannot be based on this runtime check.                 
>>>>>>>>> For this reason, all the static changes were placed under this check.                           
>>>>>>>>                                                                                                  
>>>>>>>> We have quite a bunch of options in this driver to determinate what is the real capacity of the underlying hardware.                                                                                      
>>>>>>>> If HW configuration registers are not appropriate, and it seems they are not, I would advice to simply use the DT compatibility string.                                                                   
>>>>>>>>                                                                                                  
>>>>>>>> Best regards,                                                                                    
>>>>>>>> --                                                                                               
>>>>>>>> Nicolas Ferre                                                                                    
>>>>>>>                                                                                                   
>>>>>>> HW configuration registers are appropriate. The issue is that this code doesn’t use the capability bit to switch between different dma descriptors (2 words vs. 4 words).                                  
>>>>>>> DMA descriptor size is chosen based on kernel configuration, not based on hardware capabilities.  
>>>>>>                                                                                                    
>>>>>> HW configuration register does give appropriate information.                                       
>>>>>> But addition of two address words in the macb descriptor structure is a static change.             
>>>>>>                                                                                                    
>>>>>> +static inline void macb_set_addr(struct macb_dma_desc *desc,                                      
>>>>>> +dma_addr_t                                                                                        
>>>>>> +addr) {                                                                                           
>>>>>> +       desc->addr = (u32)addr;                                                                    
>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                               
>>>>>> +       desc->addrh = (u32)(addr >> 32); #endif                                                    
>>>>>> +                                                                                                  
>>>>>>                                                                                                    
>>>>>> Even if the #ifdef condition here is changed to HW config check, addr and addrh are different.     
>>>>>> And "addrh" entry has to be present for 64 bit desc case to be handled separately.                 
>>>>>> Can you please tell me how you propose change in DMA descriptor                                    
>>>>>> structure from                                                                                     
>>>>>> 4 to 2 or 2 to 4 words *after* reading the DCFG register?                                          
>>>>>                                                                                                     
>>>>> It is very complex problem. I wrote to you because I faced the same issue. I'm working on PTP implementation for macb. When PTP is enabled there are additional two words in buffer descriptor.              
>>>>
>>>> Moreover, we can use PTP without the 64bits descriptor support (early GEM revisions).
>>>>
>>>> BTW, note that there is an initiative ongoing with Andrei to support
>>>> PTP/1588 on these devices with patches already send: please synchronize with him.
>>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__marc.info_-3Fl-3D
>>>> linux-2Dnetdev-26m-3D147282092309112-26w-3D3&d=DgIDaQ&c=aUq983L2pue2Fq
>>>> KFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtC
>>>> g4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=kr_km0MKQBzpkaOt
>>>> 0fkM-FIajN1-pOylzzTjsXi-vak&e=
>>>> or
>>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.
>>>> org_patch_9310989_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_ha
>>>> XqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3B
>>>> HCHFC6ZsKoZkU3vT8gJ-7fnsE&s=ZbXVD5Lb5zGn7wUKIPYHxagIEKp_vJvrnkRa4qJfmT
>>>> Y&e=
>>>> and
>>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.
>>>> org_patch_9310991_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_ha
>>>> XqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3B
>>>> HCHFC6ZsKoZkU3vT8gJ-7fnsE&s=Z0kRqUqh5Is4TmuaY7A4hnpizfdeq3HrgPhyDAMLuA
>>>> 8&e=
>>>>
>>>> Regards,
>>>> --
>>>> Nicolas Ferre
>>>
>>> Above patch doesn’t use hardware timestamps in descriptors at all. It doesn't use appropriate accuracy.
>>> We have our PTP patch ready, which use timestamps from descriptor. But we have not sent it yet because of compatibility issue.
>>> Of course, we can do it like Harini did:
>>>
>>> struct macb_dma_desc {
>>>         u32     addr;
>>>         u32     ctrl;
>>> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>>         u32     addrh;
>>>         u32     resvd;
>>> #endif
>>> #if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
>>>         u32     dma_desc_ts_1;
>>>         u32     dma_desc_ts_2;
>>> #endif
>>> };
>>>
>>> But in that approach we lose backward compatibility.
>>>
>>> What are your suggestion? Can we send patch like it is or wait for some common solution with backward compatibility?
>>>
>>
>> Yes, Andre's version of Cadence does not ability to report have RX timestamp.
>> The version I worked with did. This is the old series I sent:
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.org_lkml_2015_9_11_92&d=DgIFaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=1A1qxdlwY3kMlJ1JUJJL1EqLzWz4AKtfOxZf_vu8bWo&s=NGpEbbC4bYXUZjJ6n0Ud8F8p3fPz5EhTJ1O9-NKwCkQ&e=
>> But right now, i'm working on building on top of Andre's changes.
>>
>> Regards,
>> Harini
>>
> I can’t see a place where you enable extended descriptor for PTP. Did you add support for extended PTP descriptor?
> "DMA Configuration Register" 0x010:
> 29	tx_bd_extended_mode_en	"Enable TX extended BD mode. See TX BD control register definition for description of feature."
> 28	rx_bd_extended_mode_en	"Enable RX extended BD mode. See RX BD control register definition for description of feature."
> 
> Can I send you our patch for comparison ? 

You mean "send you and everyone else on the mailing-list" right?
Even if the first initiative has a bit or priority, like Harini's one
ported further by Andrei, we are still eager to share code and ideas to
make this support go forward.

I do think that the steps will be to include generic support for PTP
(without 64bits descriptors) and then plug the 64bits descriptor support
which is an newer extension of it (and definitively more robust and
leading to more accurate behavior, I know). Basically like Harini
suggested: "building on top of Andrei's changes".

Best regards,
-- 
Nicolas Ferre

^ permalink raw reply

* RE: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Rafal Ozieblo @ 2016-11-18  9:59 UTC (permalink / raw)
  To: Harini Katakam
  Cc: Nicolas Ferre, Andrei Pistirica, harini.katakam@xilinx.com,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CAFcVECJT=b2jmQAtsTeXEwWad8L2VEVW1GOyTY9XYR5qUq=4Mw@mail.gmail.com>

>                                                     
>-----Original Message-----                           
>From: Harini Katakam [mailto:harinikatakamlinux@gmail.com] 
>Sent: 18 listopada 2016 10:44                              
>To: Rafal Ozieblo                                          
>Cc: Nicolas Ferre; Andrei Pistirica; harini.katakam@xilinx.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org                                                                                             
>Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM                           
>                                                                                                        
>Hi Rafal,                                                                                               
>                                                                                                        
>On Fri, Nov 18, 2016 at 3:00 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:                              
>>>-----Original Message-----                                                                            
>>>From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]                                                  
>>>Sent: 18 listopada 2016 10:10                                                                         
>>>To: Rafal Ozieblo; Harini Katakam; Andrei Pistirica                                                   
>>>Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;                                                
>>>linux-kernel@vger.kernel.org                                                                          
>>>Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support                                 
>>>for GEM                                                                                               
>>>                                                                                                      
>>>Le 18/11/2016 à 09:59, Rafal Ozieblo a écrit :                                                        
>>>> Hello,                                                                                              
>>>>                                                                                                     
>>>>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com]                                         
>>>>> Sent: 18 listopada 2016 05:30                                                                      
>>>>> To: Rafal Ozieblo                                                                                  
>>>>> Cc: Nicolas Ferre; harini.katakam@xilinx.com;                                                      
>>>>> netdev@vger.kernel.org; linux-kernel@vger.kernel.org                                               
>>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing                                      
>>>>> support for GEM                                                                                    
>>>>>                                                                                                    
>>>>> Hi Rafal,                                                                                          
>>>>>                                                                                                    
>>>>> On Thu, Nov 17, 2016 at 7:05 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:                         
>>>>>> -----Original Message-----                                                                        
>>>>>> From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]                                              
>>>>>> Sent: 17 listopada 2016 14:29                                                                     
>>>>>> To: Harini Katakam; Rafal Ozieblo                                                                 
>>>>>> Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;                                            
>>>>>> linux-kernel@vger.kernel.org                                                                      
>>>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing                                     
>>>>>> support for GEM                                                                                   
>>>>>>                                                                                                   
>>>>>>> Le 17/11/2016 à 13:21, Harini Katakam a écrit :                                                  
>>>>>>>> Hi Rafal,                                                                                       
>>>>>>>>                                                                                                 
>>>>>>>> On Thu, Nov 17, 2016 at 5:20 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:                      
>>>>>>>>> Hello,                                                                                         
>>>>>>>>> I think, there could a bug in your patch.                                                      
>>>>>>>>>                                                                                                
>>>>>>>>>> +                                                                                             
>>>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                          
>>>>>>>>>> +             dmacfg |= GEM_BIT(ADDR64); #endif                                               
>>>>>>>>>                                                                                                
>>>>>>>>> You enable 64 bit addressing (64b dma bus width) always when appropriate architecture config option is enabled.                                                                                         
>>>>>>>>> But there are some legacy controllers which do not support that feature. According Cadence hardware team:                                                                                               
>>>>>>>>> "64 bit addressing was added in July 2013. Earlier version do not have it.                     
>>>>>>>>> This feature was enhanced in release August 2014 to have separate upper address values for transmit and receive."                                                                                       
>>>>>>>>>                                                                                                
>>>>>>>>>> /* Bitfields in NSR */                                                                        
>>>>>>>>>> @@ -474,6 +479,10 @@                                                                          
>>>>>>>>>>  struct macb_dma_desc {                                                                       
>>>>>>>>>  >      u32     addr;                                                                          
>>>>>>>>>>       u32     ctrl;                                                                           
>>>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                          
>>>>>>>>>> +     u32     addrh;                                                                          
>>>>>>>>>> +     u32     resvd;                                                                          
>>>>>>>>>> +#endif                                                                                       
>>>>>>>>>>  };                                                                                           
>>>>>>>>>                                                                                                
>>>>>>>>> It will not work for legacy hardware. Old descriptor is 2 words wide, the new one is 4 words wide.                                                                                                      
>>>>>>>>> If you enable CONFIG_ARCH_DMA_ADDR_T_64BIT but hardware doesn't                                
>>>>>>>>> support it at all, you will miss every second descriptor.                                      
>>>>>>>>>                                                                                                
>>>>>>>>                                                                                                 
>>>>>>>> True, this feature is not available in all of Cadence IP versions.                              
>>>>>>>> In fact, the IP version Zynq does not support this. But the one in ZynqMP does.                 
>>>>>>>> So, we enable kernel config for 64 bit DMA addressing for this                                  
>>>>>>>> SoC and hence the driver picks it up. My assumption was that if                                 
>>>>>>>> the legacy IP does not support                                                                  
>>>>>>>> 64 bit addressing, then this DMA option wouldn't be enabled.                                    
>>>>>>>>                                                                                                 
>>>>>>>> There is a design config register in Cadence IP which is being                                  
>>>>>>>> read to check for 64 bit address support - DMA mask is set based on that.                       
>>>>>>>> But the addition of two descriptor words cannot be based on this runtime check.                 
>>>>>>>> For this reason, all the static changes were placed under this check.                           
>>>>>>>                                                                                                  
>>>>>>> We have quite a bunch of options in this driver to determinate what is the real capacity of the underlying hardware.                                                                                      
>>>>>>> If HW configuration registers are not appropriate, and it seems they are not, I would advice to simply use the DT compatibility string.                                                                   
>>>>>>>                                                                                                  
>>>>>>> Best regards,                                                                                    
>>>>>>> --                                                                                               
>>>>>>> Nicolas Ferre                                                                                    
>>>>>>                                                                                                   
>>>>>> HW configuration registers are appropriate. The issue is that this code doesn’t use the capability bit to switch between different dma descriptors (2 words vs. 4 words).                                  
>>>>>> DMA descriptor size is chosen based on kernel configuration, not based on hardware capabilities.  
>>>>>                                                                                                    
>>>>> HW configuration register does give appropriate information.                                       
>>>>> But addition of two address words in the macb descriptor structure is a static change.             
>>>>>                                                                                                    
>>>>> +static inline void macb_set_addr(struct macb_dma_desc *desc,                                      
>>>>> +dma_addr_t                                                                                        
>>>>> +addr) {                                                                                           
>>>>> +       desc->addr = (u32)addr;                                                                    
>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                               
>>>>> +       desc->addrh = (u32)(addr >> 32); #endif                                                    
>>>>> +                                                                                                  
>>>>>                                                                                                    
>>>>> Even if the #ifdef condition here is changed to HW config check, addr and addrh are different.     
>>>>> And "addrh" entry has to be present for 64 bit desc case to be handled separately.                 
>>>>> Can you please tell me how you propose change in DMA descriptor                                    
>>>>> structure from                                                                                     
>>>>> 4 to 2 or 2 to 4 words *after* reading the DCFG register?                                          
>>>>                                                                                                     
>>>> It is very complex problem. I wrote to you because I faced the same issue. I'm working on PTP implementation for macb. When PTP is enabled there are additional two words in buffer descriptor.              
>>>
>>>Moreover, we can use PTP without the 64bits descriptor support (early GEM revisions).
>>>
>>>BTW, note that there is an initiative ongoing with Andrei to support
>>>PTP/1588 on these devices with patches already send: please synchronize with him.
>>>https://urldefense.proofpoint.com/v2/url?u=https-3A__marc.info_-3Fl-3D
>>>linux-2Dnetdev-26m-3D147282092309112-26w-3D3&d=DgIDaQ&c=aUq983L2pue2Fq
>>>KFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtC
>>>g4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=kr_km0MKQBzpkaOt
>>>0fkM-FIajN1-pOylzzTjsXi-vak&e=
>>>or
>>>https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.
>>>org_patch_9310989_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_ha
>>>XqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3B
>>>HCHFC6ZsKoZkU3vT8gJ-7fnsE&s=ZbXVD5Lb5zGn7wUKIPYHxagIEKp_vJvrnkRa4qJfmT
>>>Y&e=
>>>and
>>>https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.
>>>org_patch_9310991_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_ha
>>>XqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3B
>>>HCHFC6ZsKoZkU3vT8gJ-7fnsE&s=Z0kRqUqh5Is4TmuaY7A4hnpizfdeq3HrgPhyDAMLuA
>>>8&e=
>>>
>>>Regards,
>>>--
>>>Nicolas Ferre
>>
>> Above patch doesn’t use hardware timestamps in descriptors at all. It doesn't use appropriate accuracy.
>> We have our PTP patch ready, which use timestamps from descriptor. But we have not sent it yet because of compatibility issue.
>> Of course, we can do it like Harini did:
>>
>> struct macb_dma_desc {
>>         u32     addr;
>>         u32     ctrl;
>> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>         u32     addrh;
>>         u32     resvd;
>> #endif
>> #if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
>>         u32     dma_desc_ts_1;
>>         u32     dma_desc_ts_2;
>> #endif
>> };
>>
>> But in that approach we lose backward compatibility.
>>
>> What are your suggestion? Can we send patch like it is or wait for some common solution with backward compatibility?
>>
>
>Yes, Andre's version of Cadence does not ability to report have RX timestamp.
>The version I worked with did. This is the old series I sent:
>https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.org_lkml_2015_9_11_92&d=DgIFaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=1A1qxdlwY3kMlJ1JUJJL1EqLzWz4AKtfOxZf_vu8bWo&s=NGpEbbC4bYXUZjJ6n0Ud8F8p3fPz5EhTJ1O9-NKwCkQ&e=
>But right now, i'm working on building on top of Andre's changes.
>
>Regards,
>Harini
>
I can’t see a place where you enable extended descriptor for PTP. Did you add support for extended PTP descriptor?
"DMA Configuration Register" 0x010:
29	tx_bd_extended_mode_en	"Enable TX extended BD mode. See TX BD control register definition for description of feature."
28	rx_bd_extended_mode_en	"Enable RX extended BD mode. See RX BD control register definition for description of feature."

Can I send you our patch for comparison ? 

^ permalink raw reply

* Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Harini Katakam @ 2016-11-18  9:58 UTC (permalink / raw)
  To: Rafal Ozieblo
  Cc: Nicolas Ferre, harini.katakam@xilinx.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <BN3PR07MB25166D8301C60C4A35402AB1C9B00@BN3PR07MB2516.namprd07.prod.outlook.com>

Hi Rafal,

On Fri, Nov 18, 2016 at 2:29 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
> Hello,
>
>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com]
>> Sent: 18 listopada 2016 05:30
>> To: Rafal Ozieblo
>> Cc: Nicolas Ferre; harini.katakam@xilinx.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
>>
>> Hi Rafal,
>>
>> On Thu, Nov 17, 2016 at 7:05 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>> > -----Original Message-----
>> > From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]
>> > Sent: 17 listopada 2016 14:29
>> > To: Harini Katakam; Rafal Ozieblo
>> > Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;
>> > linux-kernel@vger.kernel.org
>> > Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support
>> > for GEM
>> >
>> >> Le 17/11/2016 à 13:21, Harini Katakam a écrit :
>> >> > Hi Rafal,
>> >> >
>> >> > On Thu, Nov 17, 2016 at 5:20 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>> >> >> Hello,
>> >> >> I think, there could a bug in your patch.
>> >> >>
>> >> >>> +
>> >> >>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>> >> >>> +             dmacfg |= GEM_BIT(ADDR64); #endif
>> >> >>
>> >> >> You enable 64 bit addressing (64b dma bus width) always when appropriate architecture config option is enabled.
>> >> >> But there are some legacy controllers which do not support that feature. According Cadence hardware team:
>> >> >> "64 bit addressing was added in July 2013. Earlier version do not have it.
>> >> >> This feature was enhanced in release August 2014 to have separate upper address values for transmit and receive."
>> >> >>
>> >> >>> /* Bitfields in NSR */
>> >> >>> @@ -474,6 +479,10 @@
>> >> >>>  struct macb_dma_desc {
>> >> >>  >      u32     addr;
>> >> >>>       u32     ctrl;
>> >> >>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>> >> >>> +     u32     addrh;
>> >> >>> +     u32     resvd;
>> >> >>> +#endif
>> >> >>>  };
>> >> >>
>> >> >> It will not work for legacy hardware. Old descriptor is 2 words wide, the new one is 4 words wide.
>> >> >> If you enable CONFIG_ARCH_DMA_ADDR_T_64BIT but hardware doesn't
>> >> >> support it at all, you will miss every second descriptor.
>> >> >>
>> >> >
>> >> > True, this feature is not available in all of Cadence IP versions.
>> >> > In fact, the IP version Zynq does not support this. But the one in ZynqMP does.
>> >> > So, we enable kernel config for 64 bit DMA addressing for this SoC
>> >> > and hence the driver picks it up. My assumption was that if the
>> >> > legacy IP does not support
>> >> > 64 bit addressing, then this DMA option wouldn't be enabled.
>> >> >
>> >> > There is a design config register in Cadence IP which is being read
>> >> > to check for 64 bit address support - DMA mask is set based on that.
>> >> > But the addition of two descriptor words cannot be based on this runtime check.
>> >> > For this reason, all the static changes were placed under this check.
>> >>
>> >> We have quite a bunch of options in this driver to determinate what is the real capacity of the underlying hardware.
>> >> If HW configuration registers are not appropriate, and it seems they are not, I would advice to simply use the DT compatibility string.
>> >>
>> >> Best regards,
>> >> --
>> >> Nicolas Ferre
>> >
>> > HW configuration registers are appropriate. The issue is that this code doesn’t use the capability bit to switch between different dma descriptors (2 words vs. 4 words).
>> > DMA descriptor size is chosen based on kernel configuration, not based on hardware capabilities.
>>
>> HW configuration register does give appropriate information.
>> But addition of two address words in the macb descriptor structure is a static change.
>>
>> +static inline void macb_set_addr(struct macb_dma_desc *desc, dma_addr_t
>> +addr) {
>> +       desc->addr = (u32)addr;
>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>> +       desc->addrh = (u32)(addr >> 32); #endif
>> +
>>
>> Even if the #ifdef condition here is changed to HW config check, addr and addrh are different.
>> And "addrh" entry has to be present for 64 bit desc case to be handled separately.
>> Can you please tell me how you propose change in DMA descriptor structure from
>> 4 to 2 or 2 to 4 words *after* reading the DCFG register?
>
> It is very complex problem. I wrote to you because I faced the same issue. I'm working on PTP implementation for macb. When PTP is enabled there are additional two words in buffer descriptor.
> But hardware might not be compatible with PTP. Therefore I have to change DMA descriptor between 2 and 4 words after reading DCFG register (the same as you between 32b and 64b).
> When we consider both PTP and 64 bits, we end up with 4 different descriptors!

Agree

<snip>
> (Below is kind of pseudo code only to show my idea. All defines like 64B or PTP are omitted for simplicity)
>
> 1. Prepare appropriate structures:
>
> struct macb_dma_desc {
>         u32     addr;
>         u32     ctrl;
> }
>
> struct macb_dma_desc_64 {
>         u32 addrh;
>         u32 resvd;
> }
>
> struct macb_dma_desc_ptp {
>         u32 dma_desc_ts_1;
>         u32     dma_desc_ts_2;
> }
>
> 2. Add hardware support information to macb:
>
> enum macb_hw_cap {
>         HW_CAP_NONE,
>         HW_CAP_64B,
>         HW_CAP_PTP,
>         HW_CAP_64B_PTP,
> };
>
> struct macb {
> // (...)
>         macb_hw_cap hw_cap;
>
> }
>
> 3. Set bp->hw_cap on macb_probe()
>

hw_cap can alreayd be obtained from config structures
based on compatible string.

> 4. Additional function might be helpful:
>
> static unsigned char macb_dma_desc_get_mul(struct macb *bp)
> {
>         switch (bp->hw_cap) {
>                 case HW_CAP_NONE:
>                         return 1;
>                 case HW_CAP_64B:
>                 case HW_CAP_PTP:
>                         return 2;
>                 case HW_CAP_64B_PTP:
>                         return 3;
>         }
> }
>
> 5. Change sizeof struct to function:
> (sizeof(struct macb_dma_desc) change to macb_dma_desc_get_size(bp). It will return sizeof(struct macb_dma_desc) * macb_dma_desc_get_mul(bp).
> There is a hidden assumption that all three structures have the same size.
>
> 6. macb_rx_desc() and macb_tx_desc() will still return struct macb_dma_desc * but descriptor index will be counted in different way, ex.
>
> static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
> {
>         index *= macb_dma_desc_get_mul(bp);
>         return &bp->rx_ring[macb_rx_ring_wrap(bp, index)];
> }
>
> 7. Two additional functions to dereference PTP and 64b information:
>
> static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
> {
>         switch (bp->hw_cap) {
>                 case HW_CAP_64B:
>                 case HW_CAP_64B_PTP:
>                         return (struct macb_dma_desc_64 *)(desc + 1);  // ugly casting
>                 default:
>                         return NULL;
>         }
> }
>
> static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp, struct macb_dma_desc *desc)
> {
>         switch (bp->hw_cap) {
>                 case HW_CAP_PTP:
>                         return (struct macb_dma_desc_ptp *)(desc + 1);
>                 case HW_CAP_64B_PTP:
>                         return (struct macb_dma_desc_ptp *)(desc + 2);
>                 default:
>                         return NULL;
>         }
> }
>
> Whenever you want to reach fields in appropriate descriptor, above function should be used.
>

Theoretically I agree this will work.
But we'll have to try to see how this will affect/slow down
the desc reading.. especially with PTP.

Regards,
Harini

> This is only my very first idea. Of course, we can leave it as it is and say, that old hardware is not support either when PTP enabled or 64b enabled.

^ permalink raw reply

* Re: [PATCH net-next] bridge: add igmpv3 and mldv2 query support
From: Nikolay Aleksandrov @ 2016-11-18 10:09 UTC (permalink / raw)
  To: Hangbin Liu, netdev; +Cc: Hannes Frederic Sowa, linus.luessing, roopa
In-Reply-To: <9c1e16c2-b716-21e0-fa2c-3e3126607953@cumulusnetworks.com>

On 18/11/16 11:04, Nikolay Aleksandrov wrote:
> On 18/11/16 08:32, Hangbin Liu wrote:
>> Add bridge IGMPv3 and MLDv2 query support. But before we think it is stable
>> enough, only enable it when declare in force_igmp/mld_version.
>>
>> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
>> ---
>>  net/bridge/br_multicast.c | 203 ++++++++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 194 insertions(+), 9 deletions(-)
>>
>
> (+CC Roopa)
> Hi Hangbin,
> This patch is not correct, you should not use the net device IGMP config in the bridge.
* bridge net device, sorry not port

> These packets may never make it to the host and they may not be reflected, even more the
> host may have very different igmp config for the port net device than the bridge does.
* again bridge net device, not port

> Also your current implementation switches to V3 only if it is globally set, and that should
> be controlled on a per-bridge basis, even per-vlan later.
* it is per-bridge, you use the global net device IGMP config, but it should be in the bridge
mcast control options, so we can do it per-vlan later and also be able to do the compat parts
of the RFC and in general, the bridge is configured via its own options not the host net device
because as I said these packets may never be received locally

> One more thing, if someone does a V2 leave for a group, you can end up sending them V3
> group-specific query.
>
> I have been working on an implementation for IGMPv3/MLDv2 querier for the bridge device, it re-uses
> most of the current code and allows you to configure it per-bridge (and later per-vlan). The only
> reason I've not yet sent it to upstream is that we (at Cumulus) are working out the compatibility
> parts (e.g. RFC3376 sec 7, sec 8) of the RFC since it has some unclear cases.
> But I can rip the compatibility out and send it early for review if you'd like, we can add the
> compat code later.
>
> Cheers,
>  Nik
>
>> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
>> index 2136e45..9fb47f3 100644
>> --- a/net/bridge/br_multicast.c
>> +++ b/net/bridge/br_multicast.c
>> @@ -35,6 +35,10 @@
>>
>>  #include "br_private.h"
>>
>> +#define IGMP_V3_SEEN(in_dev) \
>> +    (IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 3 || \
>> +     IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 3)
>> +
>>  static void br_multicast_start_querier(struct net_bridge *br,
>>                         struct bridge_mcast_own_query *query);
>>  static void br_multicast_add_router(struct net_bridge *br,
>> @@ -360,9 +364,8 @@ static int br_mdb_rehash(struct net_bridge_mdb_htable __rcu **mdbp, int max,
>>      return 0;
>>  }
>>
>> -static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
>> -                            __be32 group,
>> -                            u8 *igmp_type)
>> +static struct sk_buff *br_ip4_alloc_query_v2(struct net_bridge *br,
>> +                         __be32 group, u8 *igmp_type)
>>  {
>>      struct sk_buff *skb;
>>      struct igmphdr *ih;
>> @@ -428,10 +431,82 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
>>      return skb;
>>  }
>>
>> +static struct sk_buff *br_ip4_alloc_query_v3(struct net_bridge *br,
>> +                         __be32 group, u8 *igmp_type)
>> +{
>> +    struct sk_buff *skb;
>> +    struct igmpv3_query *ih3;
>> +    struct ethhdr *eth;
>> +    struct iphdr *iph;
>> +
>> +    skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*iph) +
>> +                         sizeof(*ih3) + 4);
>> +    if (!skb)
>> +        goto out;
>> +
>> +    skb->protocol = htons(ETH_P_IP);
>> +
>> +    skb_reset_mac_header(skb);
>> +    eth = eth_hdr(skb);
>> +
>> +    ether_addr_copy(eth->h_source, br->dev->dev_addr);
>> +    eth->h_dest[0] = 1;
>> +    eth->h_dest[1] = 0;
>> +    eth->h_dest[2] = 0x5e;
>> +    eth->h_dest[3] = 0;
>> +    eth->h_dest[4] = 0;
>> +    eth->h_dest[5] = 1;
>> +    eth->h_proto = htons(ETH_P_IP);
>> +    skb_put(skb, sizeof(*eth));
>> +
>> +    skb_set_network_header(skb, skb->len);
>> +    iph = ip_hdr(skb);
>> +
>> +    iph->version = 4;
>> +    iph->ihl = 6;
>> +    iph->tos = 0xc0;
>> +    iph->tot_len = htons(sizeof(*iph) + sizeof(*ih3) + 4);
>> +    iph->id = 0;
>> +    iph->frag_off = htons(IP_DF);
>> +    iph->ttl = 1;
>> +    iph->protocol = IPPROTO_IGMP;
>> +    iph->saddr = br->multicast_query_use_ifaddr ?
>> +             inet_select_addr(br->dev, 0, RT_SCOPE_LINK) : 0;
>> +    iph->daddr = htonl(INADDR_ALLHOSTS_GROUP);
>> +    ((u8 *)&iph[1])[0] = IPOPT_RA;
>> +    ((u8 *)&iph[1])[1] = 4;
>> +    ((u8 *)&iph[1])[2] = 0;
>> +    ((u8 *)&iph[1])[3] = 0;
>> +    ip_send_check(iph);
>> +    skb_put(skb, 24);
>> +
>> +    skb_set_transport_header(skb, skb->len);
>> +    ih3 = igmpv3_query_hdr(skb);
>> +
>> +    *igmp_type = IGMP_HOST_MEMBERSHIP_QUERY;
>> +    ih3->type = IGMP_HOST_MEMBERSHIP_QUERY;
>> +    ih3->code = (group ? br->multicast_last_member_interval :
>> +                br->multicast_query_response_interval) /
>> +           (HZ / IGMP_TIMER_SCALE);
>> +    ih3->csum = 0;
>> +    ih3->group = group;
>> +    ih3->resv = 0;
>> +    ih3->suppress = 0;
>> +    ih3->qrv= 2;
>> +    ih3->qqic = br->multicast_query_interval / HZ;
>> +    ih3->nsrcs = 0;
>> +    ih3->csum = ip_compute_csum((void *)ih3, sizeof(struct igmpv3_query ));
>> +    skb_put(skb, sizeof(*ih3));
>> +
>> +    __skb_pull(skb, sizeof(*eth));
>> +
>> +out:
>> +    return skb;
>> +}
>>  #if IS_ENABLED(CONFIG_IPV6)
>> -static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
>> -                            const struct in6_addr *grp,
>> -                            u8 *igmp_type)
>> +static struct sk_buff *br_ip6_alloc_query_v1(struct net_bridge *br,
>> +                         const struct in6_addr *grp,
>> +                         u8 *igmp_type)
>>  {
>>      struct sk_buff *skb;
>>      struct ipv6hdr *ip6h;
>> @@ -514,19 +589,129 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
>>  out:
>>      return skb;
>>  }
>> +
>> +static struct sk_buff *br_ip6_alloc_query_v2(struct net_bridge *br,
>> +                         const struct in6_addr *grp,
>> +                         u8 *igmp_type)
>> +{
>> +    struct sk_buff *skb;
>> +    struct ipv6hdr *ip6h;
>> +    struct mld2_query *mld2q;
>> +    struct ethhdr *eth;
>> +    u8 *hopopt;
>> +    unsigned long interval;
>> +
>> +    skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*ip6h) +
>> +                         8 + sizeof(*mld2q));
>> +    if (!skb)
>> +        goto out;
>> +
>> +    skb->protocol = htons(ETH_P_IPV6);
>> +
>> +    /* Ethernet header */
>> +    skb_reset_mac_header(skb);
>> +    eth = eth_hdr(skb);
>> +
>> +    ether_addr_copy(eth->h_source, br->dev->dev_addr);
>> +    eth->h_proto = htons(ETH_P_IPV6);
>> +    skb_put(skb, sizeof(*eth));
>> +
>> +    /* IPv6 header + HbH option */
>> +    skb_set_network_header(skb, skb->len);
>> +    ip6h = ipv6_hdr(skb);
>> +
>> +    *(__force __be32 *)ip6h = htonl(0x60000000);
>> +    ip6h->payload_len = htons(8 + sizeof(*mld2q));
>> +    ip6h->nexthdr = IPPROTO_HOPOPTS;
>> +    ip6h->hop_limit = 1;
>> +    ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1));
>> +    if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
>> +                   &ip6h->saddr)) {
>> +        kfree_skb(skb);
>> +        br->has_ipv6_addr = 0;
>> +        return NULL;
>> +    }
>> +
>> +    br->has_ipv6_addr = 1;
>> +    ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
>> +
>> +    hopopt = (u8 *)(ip6h + 1);
>> +    hopopt[0] = IPPROTO_ICMPV6;        /* next hdr */
>> +    hopopt[1] = 0;                /* length of HbH */
>> +    hopopt[2] = IPV6_TLV_ROUTERALERT;    /* Router Alert */
>> +    hopopt[3] = 2;                /* Length of RA Option */
>> +    hopopt[4] = 0;                /* Type = 0x0000 (MLD) */
>> +    hopopt[5] = 0;
>> +    hopopt[6] = IPV6_TLV_PAD1;        /* Pad1 */
>> +    hopopt[7] = IPV6_TLV_PAD1;        /* Pad1 */
>> +
>> +    skb_put(skb, sizeof(*ip6h) + 8);
>> +
>> +    /* ICMPv6 */
>> +    skb_set_transport_header(skb, skb->len);
>> +    mld2q = (struct mld2_query *) icmp6_hdr(skb);
>> +
>> +    interval = ipv6_addr_any(grp) ?
>> +            br->multicast_query_response_interval :
>> +            br->multicast_last_member_interval;
>> +
>> +    *igmp_type = ICMPV6_MGM_QUERY;
>> +    mld2q->mld2q_type = ICMPV6_MGM_QUERY;
>> +    mld2q->mld2q_code = 0;
>> +    mld2q->mld2q_cksum = 0;
>> +    mld2q->mld2q_mrc = htons((u16)jiffies_to_msecs(interval));
>> +    mld2q->mld2q_resv1 = 0;
>> +    mld2q->mld2q_mca = *grp;
>> +    mld2q->mld2q_resv2 = 0;
>> +    mld2q->mld2q_suppress = 0;
>> +    mld2q->mld2q_qrv = 2;
>> +    mld2q->mld2q_qqic = br->multicast_query_interval / HZ;
>> +    mld2q->mld2q_nsrcs = 0;
>> +
>> +    /* checksum */
>> +    mld2q->mld2q_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
>> +                      sizeof(*mld2q), IPPROTO_ICMPV6,
>> +                      csum_partial(mld2q,
>> +                               sizeof(*mld2q), 0));
>> +    skb_put(skb, sizeof(*mld2q));
>> +
>> +    __skb_pull(skb, sizeof(*eth));
>> +
>> +out:
>> +    return skb;
>> +}
>>  #endif
>>
>> +static int mld_force_mld_version(const struct inet6_dev *idev)
>> +{
>> +    if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
>> +        return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
>> +    else
>> +        return idev->cnf.force_mld_version;
>> +}
>> +
>>  static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
>>                          struct br_ip *addr,
>>                          u8 *igmp_type)
>>  {
>> +    struct in_device *in_dev = __in_dev_get_rcu(br->dev);
>> +    struct inet6_dev *idev = __in6_dev_get(br->dev);
>>      switch (addr->proto) {
>>      case htons(ETH_P_IP):
>> -        return br_ip4_multicast_alloc_query(br, addr->u.ip4, igmp_type);
>> +        if (IGMP_V3_SEEN(in_dev))
>> +            return br_ip4_alloc_query_v3(br, addr->u.ip4,
>> +                             igmp_type);
>> +        else
>> +            return br_ip4_alloc_query_v2(br, addr->u.ip4,
>> +                             igmp_type);
>>  #if IS_ENABLED(CONFIG_IPV6)
>>      case htons(ETH_P_IPV6):
>> -        return br_ip6_multicast_alloc_query(br, &addr->u.ip6,
>> -                            igmp_type);
>> +        if (mld_force_mld_version(idev) == 2)
>> +            return br_ip6_alloc_query_v2(br, &addr->u.ip6,
>> +                             igmp_type);
>> +        else
>> +            return br_ip6_alloc_query_v1(br, &addr->u.ip6,
>> +                             igmp_type);
>>  #endif
>>      }
>>      return NULL;
>>
>

^ permalink raw reply

* Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Andrei Pistirica @ 2016-11-18 10:07 UTC (permalink / raw)
  To: Harini Katakam
  Cc: Rafal Ozieblo, Nicolas Ferre, harini.katakam@xilinx.com,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CAFcVECJT=b2jmQAtsTeXEwWad8L2VEVW1GOyTY9XYR5qUq=4Mw@mail.gmail.com>

Hi Harini,

On 18.11.2016 10:43, Harini Katakam wrote:
> Hi Rafal,
>
> On Fri, Nov 18, 2016 at 3:00 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>>> -----Original Message-----
>>> From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]
>>> Sent: 18 listopada 2016 10:10
>>> To: Rafal Ozieblo; Harini Katakam; Andrei Pistirica
>>> Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
>>>
>>> Le 18/11/2016 à 09:59, Rafal Ozieblo a écrit :
>>>> Hello,
>>>>
>>>>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com]
>>>>> Sent: 18 listopada 2016 05:30
>>>>> To: Rafal Ozieblo
>>>>> Cc: Nicolas Ferre; harini.katakam@xilinx.com; netdev@vger.kernel.org;
>>>>> linux-kernel@vger.kernel.org
>>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support
>>>>> for GEM
>>>>>
>>>>> Hi Rafal,
>>>>>
>>>>> On Thu, Nov 17, 2016 at 7:05 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>>>>>> -----Original Message-----
>>>>>> From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]
>>>>>> Sent: 17 listopada 2016 14:29
>>>>>> To: Harini Katakam; Rafal Ozieblo
>>>>>> Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;
>>>>>> linux-kernel@vger.kernel.org
>>>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing
>>>>>> support for GEM
>>>>>>
>>>>>>> Le 17/11/2016 à 13:21, Harini Katakam a écrit :
>>>>>>>> Hi Rafal,
>>>>>>>>
>>>>>>>> On Thu, Nov 17, 2016 at 5:20 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>>>>>>>>> Hello,
>>>>>>>>> I think, there could a bug in your patch.
>>>>>>>>>
>>>>>>>>>> +
>>>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>>>>>>>>> +             dmacfg |= GEM_BIT(ADDR64); #endif
>>>>>>>>>
>>>>>>>>> You enable 64 bit addressing (64b dma bus width) always when appropriate architecture config option is enabled.
>>>>>>>>> But there are some legacy controllers which do not support that feature. According Cadence hardware team:
>>>>>>>>> "64 bit addressing was added in July 2013. Earlier version do not have it.
>>>>>>>>> This feature was enhanced in release August 2014 to have separate upper address values for transmit and receive."
>>>>>>>>>
>>>>>>>>>> /* Bitfields in NSR */
>>>>>>>>>> @@ -474,6 +479,10 @@
>>>>>>>>>>  struct macb_dma_desc {
>>>>>>>>>  >      u32     addr;
>>>>>>>>>>       u32     ctrl;
>>>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>>>>>>>>> +     u32     addrh;
>>>>>>>>>> +     u32     resvd;
>>>>>>>>>> +#endif
>>>>>>>>>>  };
>>>>>>>>>
>>>>>>>>> It will not work for legacy hardware. Old descriptor is 2 words wide, the new one is 4 words wide.
>>>>>>>>> If you enable CONFIG_ARCH_DMA_ADDR_T_64BIT but hardware doesn't
>>>>>>>>> support it at all, you will miss every second descriptor.
>>>>>>>>>
>>>>>>>>
>>>>>>>> True, this feature is not available in all of Cadence IP versions.
>>>>>>>> In fact, the IP version Zynq does not support this. But the one in ZynqMP does.
>>>>>>>> So, we enable kernel config for 64 bit DMA addressing for this SoC
>>>>>>>> and hence the driver picks it up. My assumption was that if the
>>>>>>>> legacy IP does not support
>>>>>>>> 64 bit addressing, then this DMA option wouldn't be enabled.
>>>>>>>>
>>>>>>>> There is a design config register in Cadence IP which is being
>>>>>>>> read to check for 64 bit address support - DMA mask is set based on that.
>>>>>>>> But the addition of two descriptor words cannot be based on this runtime check.
>>>>>>>> For this reason, all the static changes were placed under this check.
>>>>>>>
>>>>>>> We have quite a bunch of options in this driver to determinate what is the real capacity of the underlying hardware.
>>>>>>> If HW configuration registers are not appropriate, and it seems they are not, I would advice to simply use the DT compatibility string.
>>>>>>>
>>>>>>> Best regards,
>>>>>>> --
>>>>>>> Nicolas Ferre
>>>>>>
>>>>>> HW configuration registers are appropriate. The issue is that this code doesn’t use the capability bit to switch between different dma descriptors (2 words vs. 4 words).
>>>>>> DMA descriptor size is chosen based on kernel configuration, not based on hardware capabilities.
>>>>>
>>>>> HW configuration register does give appropriate information.
>>>>> But addition of two address words in the macb descriptor structure is a static change.
>>>>>
>>>>> +static inline void macb_set_addr(struct macb_dma_desc *desc,
>>>>> +dma_addr_t
>>>>> +addr) {
>>>>> +       desc->addr = (u32)addr;
>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>>>> +       desc->addrh = (u32)(addr >> 32); #endif
>>>>> +
>>>>>
>>>>> Even if the #ifdef condition here is changed to HW config check, addr and addrh are different.
>>>>> And "addrh" entry has to be present for 64 bit desc case to be handled separately.
>>>>> Can you please tell me how you propose change in DMA descriptor
>>>>> structure from
>>>>> 4 to 2 or 2 to 4 words *after* reading the DCFG register?
>>>>
>>>> It is very complex problem. I wrote to you because I faced the same issue. I'm working on PTP implementation for macb. When PTP is enabled there are additional two words in buffer descriptor.
>>>
>>> Moreover, we can use PTP without the 64bits descriptor support (early GEM revisions).
>>>
>>> BTW, note that there is an initiative ongoing with Andrei to support
>>> PTP/1588 on these devices with patches already send: please synchronize with him.
>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__marc.info_-3Fl-3Dlinux-2Dnetdev-26m-3D147282092309112-26w-3D3&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=kr_km0MKQBzpkaOt0fkM-FIajN1-pOylzzTjsXi-vak&e=
>>> or
>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_9310989_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=ZbXVD5Lb5zGn7wUKIPYHxagIEKp_vJvrnkRa4qJfmTY&e=
>>> and
>>> https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_9310991_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=Z0kRqUqh5Is4TmuaY7A4hnpizfdeq3HrgPhyDAMLuA8&e=
>>>
>>> Regards,
>>> --
>>> Nicolas Ferre
>>
>> Above patch doesn’t use hardware timestamps in descriptors at all. It doesn't use appropriate accuracy.
>> We have our PTP patch ready, which use timestamps from descriptor. But we have not sent it yet because of compatibility issue.
>> Of course, we can do it like Harini did:
>>
>> struct macb_dma_desc {
>>         u32     addr;
>>         u32     ctrl;
>> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>         u32     addrh;
>>         u32     resvd;
>> #endif
>> #if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
>>         u32     dma_desc_ts_1;
>>         u32     dma_desc_ts_2;
>> #endif
>> };
>>
>> But in that approach we lose backward compatibility.
>>
>> What are your suggestion? Can we send patch like it is or wait for some common solution with backward compatibility?
>>
>
> Yes, Andre's version of Cadence does not ability to report have RX timestamp.
> The version I worked with did. This is the old series I sent:
> https://lkml.org/lkml/2015/9/11/92
> But right now, i'm working on building on top of Andre's changes.

I'm addressing maintainer's feedback on both patches:
https://patchwork.kernel.org/patch/9310989/
https://patchwork.kernel.org/patch/9310991/

I've done all suggested updates, except the numerous 64bit divisions in 
the frequency adjustment callback. I've implemented a different 
algorithm which uses 2 64bit division, but I couldn't find a way to use 
only 1.

Also, I have a version with timecounter/cyclecounter which shows a much 
better accuracy (less than 100ns level). In my opinion this could be a 
better implementation. What is you opinion about this? Did you try it?

Tuesday I can send an updated version of these patches.

>
> Regards,
> Harini
>

Regards,
Andrei

^ permalink raw reply

* Re: [PATCH v9 0/8] thunderbolt: Introducing Thunderbolt(TM) Networking
From: gregkh @ 2016-11-18 10:07 UTC (permalink / raw)
  To: Levy, Amir (Jer)
  Cc: Simon Guinot, andreas.noever@gmail.com, bhelgaas@google.com,
	corbet@lwn.net, linux-kernel@vger.kernel.org,
	linux-pci@vger.kernel.org, netdev@vger.kernel.org,
	linux-doc@vger.kernel.org, mario_limonciello@dell.com,
	thunderbolt-linux, Westerberg, Mika, Winkler, Tomas,
	Zhang, Xiong Y, Jamet, Michael, remi.rerolle@seagate.com
In-Reply-To: <E607265CB020454880711A6F96C05A03BE2199EE@hasmsx108.ger.corp.intel.com>

On Fri, Nov 18, 2016 at 08:48:36AM +0000, Levy, Amir (Jer) wrote:
> > BTW, it is quite a shame that the Thunderbolt firmware version can't 
> > be read from Linux.
> > 
> 
> This is WIP, once this patch will be upstream, we will be able to focus more
> on aligning Linux with the Thunderbolt features that we have for windows.

Why is this patch somehow holding that work back?  You aren't just
sitting around waiting for people to review this and not doing anything
else, right?  Is there some basic building block in these patches that
your firmware download code is going to rely on?

confused,

greg k-h

^ permalink raw reply

* Re: [PATCH net-next] bridge: add igmpv3 and mldv2 query support
From: Nikolay Aleksandrov @ 2016-11-18 10:04 UTC (permalink / raw)
  To: Hangbin Liu, netdev; +Cc: Hannes Frederic Sowa, linus.luessing, roopa
In-Reply-To: <1479454321-31304-1-git-send-email-liuhangbin@gmail.com>

On 18/11/16 08:32, Hangbin Liu wrote:
> Add bridge IGMPv3 and MLDv2 query support. But before we think it is stable
> enough, only enable it when declare in force_igmp/mld_version.
>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> ---
>  net/bridge/br_multicast.c | 203 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 194 insertions(+), 9 deletions(-)
>

(+CC Roopa)
Hi Hangbin,
This patch is not correct, you should not use the port net device IGMP config in the bridge.
These packets may never make it to the host and they may not be reflected, even more the
host may have very different igmp config for the port net device than the bridge does.
Also your current implementation switches to V3 only if it is globally set, and that should
be controlled on a per-bridge basis, even per-vlan later.
One more thing, if someone does a V2 leave for a group, you can end up sending them V3
group-specific query.

I have been working on an implementation for IGMPv3/MLDv2 querier for the bridge device, it re-uses
most of the current code and allows you to configure it per-bridge (and later per-vlan). The only
reason I've not yet sent it to upstream is that we (at Cumulus) are working out the compatibility
parts (e.g. RFC3376 sec 7, sec 8) of the RFC since it has some unclear cases.
But I can rip the compatibility out and send it early for review if you'd like, we can add the
compat code later.

Cheers,
  Nik

> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
> index 2136e45..9fb47f3 100644
> --- a/net/bridge/br_multicast.c
> +++ b/net/bridge/br_multicast.c
> @@ -35,6 +35,10 @@
>
>  #include "br_private.h"
>
> +#define IGMP_V3_SEEN(in_dev) \
> +	(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 3 || \
> +	 IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 3)
> +
>  static void br_multicast_start_querier(struct net_bridge *br,
>  				       struct bridge_mcast_own_query *query);
>  static void br_multicast_add_router(struct net_bridge *br,
> @@ -360,9 +364,8 @@ static int br_mdb_rehash(struct net_bridge_mdb_htable __rcu **mdbp, int max,
>  	return 0;
>  }
>
> -static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
> -						    __be32 group,
> -						    u8 *igmp_type)
> +static struct sk_buff *br_ip4_alloc_query_v2(struct net_bridge *br,
> +					     __be32 group, u8 *igmp_type)
>  {
>  	struct sk_buff *skb;
>  	struct igmphdr *ih;
> @@ -428,10 +431,82 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
>  	return skb;
>  }
>
> +static struct sk_buff *br_ip4_alloc_query_v3(struct net_bridge *br,
> +					     __be32 group, u8 *igmp_type)
> +{
> +	struct sk_buff *skb;
> +	struct igmpv3_query *ih3;
> +	struct ethhdr *eth;
> +	struct iphdr *iph;
> +
> +	skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*iph) +
> +						 sizeof(*ih3) + 4);
> +	if (!skb)
> +		goto out;
> +
> +	skb->protocol = htons(ETH_P_IP);
> +
> +	skb_reset_mac_header(skb);
> +	eth = eth_hdr(skb);
> +
> +	ether_addr_copy(eth->h_source, br->dev->dev_addr);
> +	eth->h_dest[0] = 1;
> +	eth->h_dest[1] = 0;
> +	eth->h_dest[2] = 0x5e;
> +	eth->h_dest[3] = 0;
> +	eth->h_dest[4] = 0;
> +	eth->h_dest[5] = 1;
> +	eth->h_proto = htons(ETH_P_IP);
> +	skb_put(skb, sizeof(*eth));
> +
> +	skb_set_network_header(skb, skb->len);
> +	iph = ip_hdr(skb);
> +
> +	iph->version = 4;
> +	iph->ihl = 6;
> +	iph->tos = 0xc0;
> +	iph->tot_len = htons(sizeof(*iph) + sizeof(*ih3) + 4);
> +	iph->id = 0;
> +	iph->frag_off = htons(IP_DF);
> +	iph->ttl = 1;
> +	iph->protocol = IPPROTO_IGMP;
> +	iph->saddr = br->multicast_query_use_ifaddr ?
> +		     inet_select_addr(br->dev, 0, RT_SCOPE_LINK) : 0;
> +	iph->daddr = htonl(INADDR_ALLHOSTS_GROUP);
> +	((u8 *)&iph[1])[0] = IPOPT_RA;
> +	((u8 *)&iph[1])[1] = 4;
> +	((u8 *)&iph[1])[2] = 0;
> +	((u8 *)&iph[1])[3] = 0;
> +	ip_send_check(iph);
> +	skb_put(skb, 24);
> +
> +	skb_set_transport_header(skb, skb->len);
> +	ih3 = igmpv3_query_hdr(skb);
> +
> +	*igmp_type = IGMP_HOST_MEMBERSHIP_QUERY;
> +	ih3->type = IGMP_HOST_MEMBERSHIP_QUERY;
> +	ih3->code = (group ? br->multicast_last_member_interval :
> +			    br->multicast_query_response_interval) /
> +		   (HZ / IGMP_TIMER_SCALE);
> +	ih3->csum = 0;
> +	ih3->group = group;
> +	ih3->resv = 0;
> +	ih3->suppress = 0;
> +	ih3->qrv= 2;
> +	ih3->qqic = br->multicast_query_interval / HZ;
> +	ih3->nsrcs = 0;
> +	ih3->csum = ip_compute_csum((void *)ih3, sizeof(struct igmpv3_query ));
> +	skb_put(skb, sizeof(*ih3));
> +
> +	__skb_pull(skb, sizeof(*eth));
> +
> +out:
> +	return skb;
> +}
>  #if IS_ENABLED(CONFIG_IPV6)
> -static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
> -						    const struct in6_addr *grp,
> -						    u8 *igmp_type)
> +static struct sk_buff *br_ip6_alloc_query_v1(struct net_bridge *br,
> +					     const struct in6_addr *grp,
> +					     u8 *igmp_type)
>  {
>  	struct sk_buff *skb;
>  	struct ipv6hdr *ip6h;
> @@ -514,19 +589,129 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
>  out:
>  	return skb;
>  }
> +
> +static struct sk_buff *br_ip6_alloc_query_v2(struct net_bridge *br,
> +					     const struct in6_addr *grp,
> +					     u8 *igmp_type)
> +{
> +	struct sk_buff *skb;
> +	struct ipv6hdr *ip6h;
> +	struct mld2_query *mld2q;
> +	struct ethhdr *eth;
> +	u8 *hopopt;
> +	unsigned long interval;
> +
> +	skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*ip6h) +
> +						 8 + sizeof(*mld2q));
> +	if (!skb)
> +		goto out;
> +
> +	skb->protocol = htons(ETH_P_IPV6);
> +
> +	/* Ethernet header */
> +	skb_reset_mac_header(skb);
> +	eth = eth_hdr(skb);
> +
> +	ether_addr_copy(eth->h_source, br->dev->dev_addr);
> +	eth->h_proto = htons(ETH_P_IPV6);
> +	skb_put(skb, sizeof(*eth));
> +
> +	/* IPv6 header + HbH option */
> +	skb_set_network_header(skb, skb->len);
> +	ip6h = ipv6_hdr(skb);
> +
> +	*(__force __be32 *)ip6h = htonl(0x60000000);
> +	ip6h->payload_len = htons(8 + sizeof(*mld2q));
> +	ip6h->nexthdr = IPPROTO_HOPOPTS;
> +	ip6h->hop_limit = 1;
> +	ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1));
> +	if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
> +			       &ip6h->saddr)) {
> +		kfree_skb(skb);
> +		br->has_ipv6_addr = 0;
> +		return NULL;
> +	}
> +
> +	br->has_ipv6_addr = 1;
> +	ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
> +
> +	hopopt = (u8 *)(ip6h + 1);
> +	hopopt[0] = IPPROTO_ICMPV6;		/* next hdr */
> +	hopopt[1] = 0;				/* length of HbH */
> +	hopopt[2] = IPV6_TLV_ROUTERALERT;	/* Router Alert */
> +	hopopt[3] = 2;				/* Length of RA Option */
> +	hopopt[4] = 0;				/* Type = 0x0000 (MLD) */
> +	hopopt[5] = 0;
> +	hopopt[6] = IPV6_TLV_PAD1;		/* Pad1 */
> +	hopopt[7] = IPV6_TLV_PAD1;		/* Pad1 */
> +
> +	skb_put(skb, sizeof(*ip6h) + 8);
> +
> +	/* ICMPv6 */
> +	skb_set_transport_header(skb, skb->len);
> +	mld2q = (struct mld2_query *) icmp6_hdr(skb);
> +
> +	interval = ipv6_addr_any(grp) ?
> +			br->multicast_query_response_interval :
> +			br->multicast_last_member_interval;
> +
> +	*igmp_type = ICMPV6_MGM_QUERY;
> +	mld2q->mld2q_type = ICMPV6_MGM_QUERY;
> +	mld2q->mld2q_code = 0;
> +	mld2q->mld2q_cksum = 0;
> +	mld2q->mld2q_mrc = htons((u16)jiffies_to_msecs(interval));
> +	mld2q->mld2q_resv1 = 0;
> +	mld2q->mld2q_mca = *grp;
> +	mld2q->mld2q_resv2 = 0;
> +	mld2q->mld2q_suppress = 0;
> +	mld2q->mld2q_qrv = 2;
> +	mld2q->mld2q_qqic = br->multicast_query_interval / HZ;
> +	mld2q->mld2q_nsrcs = 0;
> +
> +	/* checksum */
> +	mld2q->mld2q_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
> +					  sizeof(*mld2q), IPPROTO_ICMPV6,
> +					  csum_partial(mld2q,
> +						       sizeof(*mld2q), 0));
> +	skb_put(skb, sizeof(*mld2q));
> +
> +	__skb_pull(skb, sizeof(*eth));
> +
> +out:
> +	return skb;
> +}
>  #endif
>
> +static int mld_force_mld_version(const struct inet6_dev *idev)
> +{
> +	if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
> +		return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
> +	else
> +		return idev->cnf.force_mld_version;
> +}
> +
>  static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
>  						struct br_ip *addr,
>  						u8 *igmp_type)
>  {
> +	struct in_device *in_dev = __in_dev_get_rcu(br->dev);
> +	struct inet6_dev *idev = __in6_dev_get(br->dev);
>  	switch (addr->proto) {
>  	case htons(ETH_P_IP):
> -		return br_ip4_multicast_alloc_query(br, addr->u.ip4, igmp_type);
> +		if (IGMP_V3_SEEN(in_dev))
> +			return br_ip4_alloc_query_v3(br, addr->u.ip4,
> +						     igmp_type);
> +		else
> +			return br_ip4_alloc_query_v2(br, addr->u.ip4,
> +						     igmp_type);
>  #if IS_ENABLED(CONFIG_IPV6)
>  	case htons(ETH_P_IPV6):
> -		return br_ip6_multicast_alloc_query(br, &addr->u.ip6,
> -						    igmp_type);
> +		if (mld_force_mld_version(idev) == 2)
> +			return br_ip6_alloc_query_v2(br, &addr->u.ip6,
> +						     igmp_type);
> +		else
> +			return br_ip6_alloc_query_v1(br, &addr->u.ip6,
> +						     igmp_type);
>  #endif
>  	}
>  	return NULL;
>

^ permalink raw reply

* Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Harini Katakam @ 2016-11-18 10:03 UTC (permalink / raw)
  To: Rafal Ozieblo
  Cc: Nicolas Ferre, Andrei Pistirica, harini.katakam@xilinx.com,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <BN3PR07MB25162D82CEF09B8C7586B799C9B00@BN3PR07MB2516.namprd07.prod.outlook.com>

Hi Rafal,


> I can’t see a place where you enable extended descriptor for PTP. Did you add support for extended PTP descriptor?
Sorry, that was separate patch in the series:
http://lkml.iu.edu/hypermail/linux/kernel/1509.1/02239.html

> "DMA Configuration Register" 0x010:
> 29      tx_bd_extended_mode_en  "Enable TX extended BD mode. See TX BD control register definition for description of feature."
> 28      rx_bd_extended_mode_en  "Enable RX extended BD mode. See RX BD control register definition for description of feature."
>
> Can I send you our patch for comparison ?
Sure, please mail. Also, please mention the Cadence IP version number you use.

Regards,
Harini

^ permalink raw reply

* Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Harini Katakam @ 2016-11-18  9:43 UTC (permalink / raw)
  To: Rafal Ozieblo
  Cc: Nicolas Ferre, Andrei Pistirica, harini.katakam@xilinx.com,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <BN3PR07MB251655CAFDB38CCF0F240BB5C9B00@BN3PR07MB2516.namprd07.prod.outlook.com>

Hi Rafal,

On Fri, Nov 18, 2016 at 3:00 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>>-----Original Message-----
>>From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]
>>Sent: 18 listopada 2016 10:10
>>To: Rafal Ozieblo; Harini Katakam; Andrei Pistirica
>>Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
>>Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
>>
>>Le 18/11/2016 à 09:59, Rafal Ozieblo a écrit :
>>> Hello,
>>>
>>>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com]
>>>> Sent: 18 listopada 2016 05:30
>>>> To: Rafal Ozieblo
>>>> Cc: Nicolas Ferre; harini.katakam@xilinx.com; netdev@vger.kernel.org;
>>>> linux-kernel@vger.kernel.org
>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support
>>>> for GEM
>>>>
>>>> Hi Rafal,
>>>>
>>>> On Thu, Nov 17, 2016 at 7:05 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>>>>> -----Original Message-----
>>>>> From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]
>>>>> Sent: 17 listopada 2016 14:29
>>>>> To: Harini Katakam; Rafal Ozieblo
>>>>> Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;
>>>>> linux-kernel@vger.kernel.org
>>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing
>>>>> support for GEM
>>>>>
>>>>>> Le 17/11/2016 à 13:21, Harini Katakam a écrit :
>>>>>>> Hi Rafal,
>>>>>>>
>>>>>>> On Thu, Nov 17, 2016 at 5:20 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
>>>>>>>> Hello,
>>>>>>>> I think, there could a bug in your patch.
>>>>>>>>
>>>>>>>>> +
>>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>>>>>>>> +             dmacfg |= GEM_BIT(ADDR64); #endif
>>>>>>>>
>>>>>>>> You enable 64 bit addressing (64b dma bus width) always when appropriate architecture config option is enabled.
>>>>>>>> But there are some legacy controllers which do not support that feature. According Cadence hardware team:
>>>>>>>> "64 bit addressing was added in July 2013. Earlier version do not have it.
>>>>>>>> This feature was enhanced in release August 2014 to have separate upper address values for transmit and receive."
>>>>>>>>
>>>>>>>>> /* Bitfields in NSR */
>>>>>>>>> @@ -474,6 +479,10 @@
>>>>>>>>>  struct macb_dma_desc {
>>>>>>>>  >      u32     addr;
>>>>>>>>>       u32     ctrl;
>>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>>>>>>>> +     u32     addrh;
>>>>>>>>> +     u32     resvd;
>>>>>>>>> +#endif
>>>>>>>>>  };
>>>>>>>>
>>>>>>>> It will not work for legacy hardware. Old descriptor is 2 words wide, the new one is 4 words wide.
>>>>>>>> If you enable CONFIG_ARCH_DMA_ADDR_T_64BIT but hardware doesn't
>>>>>>>> support it at all, you will miss every second descriptor.
>>>>>>>>
>>>>>>>
>>>>>>> True, this feature is not available in all of Cadence IP versions.
>>>>>>> In fact, the IP version Zynq does not support this. But the one in ZynqMP does.
>>>>>>> So, we enable kernel config for 64 bit DMA addressing for this SoC
>>>>>>> and hence the driver picks it up. My assumption was that if the
>>>>>>> legacy IP does not support
>>>>>>> 64 bit addressing, then this DMA option wouldn't be enabled.
>>>>>>>
>>>>>>> There is a design config register in Cadence IP which is being
>>>>>>> read to check for 64 bit address support - DMA mask is set based on that.
>>>>>>> But the addition of two descriptor words cannot be based on this runtime check.
>>>>>>> For this reason, all the static changes were placed under this check.
>>>>>>
>>>>>> We have quite a bunch of options in this driver to determinate what is the real capacity of the underlying hardware.
>>>>>> If HW configuration registers are not appropriate, and it seems they are not, I would advice to simply use the DT compatibility string.
>>>>>>
>>>>>> Best regards,
>>>>>> --
>>>>>> Nicolas Ferre
>>>>>
>>>>> HW configuration registers are appropriate. The issue is that this code doesn’t use the capability bit to switch between different dma descriptors (2 words vs. 4 words).
>>>>> DMA descriptor size is chosen based on kernel configuration, not based on hardware capabilities.
>>>>
>>>> HW configuration register does give appropriate information.
>>>> But addition of two address words in the macb descriptor structure is a static change.
>>>>
>>>> +static inline void macb_set_addr(struct macb_dma_desc *desc,
>>>> +dma_addr_t
>>>> +addr) {
>>>> +       desc->addr = (u32)addr;
>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>>>> +       desc->addrh = (u32)(addr >> 32); #endif
>>>> +
>>>>
>>>> Even if the #ifdef condition here is changed to HW config check, addr and addrh are different.
>>>> And "addrh" entry has to be present for 64 bit desc case to be handled separately.
>>>> Can you please tell me how you propose change in DMA descriptor
>>>> structure from
>>>> 4 to 2 or 2 to 4 words *after* reading the DCFG register?
>>>
>>> It is very complex problem. I wrote to you because I faced the same issue. I'm working on PTP implementation for macb. When PTP is enabled there are additional two words in buffer descriptor.
>>
>>Moreover, we can use PTP without the 64bits descriptor support (early GEM revisions).
>>
>>BTW, note that there is an initiative ongoing with Andrei to support
>>PTP/1588 on these devices with patches already send: please synchronize with him.
>>https://urldefense.proofpoint.com/v2/url?u=https-3A__marc.info_-3Fl-3Dlinux-2Dnetdev-26m-3D147282092309112-26w-3D3&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=kr_km0MKQBzpkaOt0fkM-FIajN1-pOylzzTjsXi-vak&e=
>>or
>>https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_9310989_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=ZbXVD5Lb5zGn7wUKIPYHxagIEKp_vJvrnkRa4qJfmTY&e=
>>and
>>https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_9310991_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=Z0kRqUqh5Is4TmuaY7A4hnpizfdeq3HrgPhyDAMLuA8&e=
>>
>>Regards,
>>--
>>Nicolas Ferre
>
> Above patch doesn’t use hardware timestamps in descriptors at all. It doesn't use appropriate accuracy.
> We have our PTP patch ready, which use timestamps from descriptor. But we have not sent it yet because of compatibility issue.
> Of course, we can do it like Harini did:
>
> struct macb_dma_desc {
>         u32     addr;
>         u32     ctrl;
> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
>         u32     addrh;
>         u32     resvd;
> #endif
> #if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
>         u32     dma_desc_ts_1;
>         u32     dma_desc_ts_2;
> #endif
> };
>
> But in that approach we lose backward compatibility.
>
> What are your suggestion? Can we send patch like it is or wait for some common solution with backward compatibility?
>

Yes, Andre's version of Cadence does not ability to report have RX timestamp.
The version I worked with did. This is the old series I sent:
https://lkml.org/lkml/2015/9/11/92
But right now, i'm working on building on top of Andre's changes.

Regards,
Harini

^ permalink raw reply

* [PATCH] netns: fix get_net_ns_by_fd(int pid) typo
From: Stefan Hajnoczi @ 2016-11-18  9:41 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Stefan Hajnoczi

The argument to get_net_ns_by_fd() is a /proc/$PID/ns/net file
descriptor not a pid.  Fix the typo.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/net/net_namespace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index fc4f757..0940598 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -170,7 +170,7 @@ static inline struct net *copy_net_ns(unsigned long flags,
 extern struct list_head net_namespace_list;
 
 struct net *get_net_ns_by_pid(pid_t pid);
-struct net *get_net_ns_by_fd(int pid);
+struct net *get_net_ns_by_fd(int fd);
 
 #ifdef CONFIG_SYSCTL
 void ipx_register_sysctl(void);
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH net v2 7/7] net: ethernet: ti: cpsw: fix fixed-link phy probe deferral
From: Johan Hovold @ 2016-11-18  9:33 UTC (permalink / raw)
  To: David Miller
  Cc: johan, mugunthanvnm, grygorii.strashko, linux-omap, netdev,
	linux-kernel
In-Reply-To: <20161117171920.GD10490@localhost>

On Thu, Nov 17, 2016 at 06:19:20PM +0100, Johan Hovold wrote:
> On Thu, Nov 17, 2016 at 12:04:16PM -0500, David Miller wrote:
> > From: Johan Hovold <johan@kernel.org>
> > Date: Thu, 17 Nov 2016 17:40:04 +0100
> > 
> > > Make sure to propagate errors from of_phy_register_fixed_link() which
> > > can fail with -EPROBE_DEFER.
> > > 
> > > Fixes: 1f71e8c96fc6 ("drivers: net: cpsw: Add support for fixed-link
> > > PHY")
> > > Signed-off-by: Johan Hovold <johan@kernel.org>
> > 
> > Johan, when you update a patch within a series you must post the
> > entire series freshly to the lists, cover posting and all.
> 
> I'm quite sure that is exactly what I did. Did you only get this last
> patch out of the seven?

The full series has made it to the lists:

	https://marc.info/?l=linux-netdev&m=147940433115984&w=2

Perhaps some messages just got held up.

Let me know if you still want me to resend.

Thanks,
Johan

^ permalink raw reply

* RE: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Rafal Ozieblo @ 2016-11-18  8:59 UTC (permalink / raw)
  To: Harini Katakam
  Cc: Nicolas Ferre, harini.katakam@xilinx.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <CAFcVEC+RqUMQF39oe2EuCoisX6dCwRQ3G81zFMqoOHU3HpfPHQ@mail.gmail.com>

Hello,

> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com]
> Sent: 18 listopada 2016 05:30
> To: Rafal Ozieblo
> Cc: Nicolas Ferre; harini.katakam@xilinx.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
>
> Hi Rafal,
>
> On Thu, Nov 17, 2016 at 7:05 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
> > -----Original Message-----
> > From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]
> > Sent: 17 listopada 2016 14:29
> > To: Harini Katakam; Rafal Ozieblo
> > Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;
> > linux-kernel@vger.kernel.org
> > Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support
> > for GEM
> >
> >> Le 17/11/2016 à 13:21, Harini Katakam a écrit :
> >> > Hi Rafal,
> >> >
> >> > On Thu, Nov 17, 2016 at 5:20 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:
> >> >> Hello,
> >> >> I think, there could a bug in your patch.
> >> >>
> >> >>> +
> >> >>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> >> >>> +             dmacfg |= GEM_BIT(ADDR64); #endif
> >> >>
> >> >> You enable 64 bit addressing (64b dma bus width) always when appropriate architecture config option is enabled.
> >> >> But there are some legacy controllers which do not support that feature. According Cadence hardware team:
> >> >> "64 bit addressing was added in July 2013. Earlier version do not have it.
> >> >> This feature was enhanced in release August 2014 to have separate upper address values for transmit and receive."
> >> >>
> >> >>> /* Bitfields in NSR */
> >> >>> @@ -474,6 +479,10 @@
> >> >>>  struct macb_dma_desc {
> >> >>  >      u32     addr;
> >> >>>       u32     ctrl;
> >> >>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> >> >>> +     u32     addrh;
> >> >>> +     u32     resvd;
> >> >>> +#endif
> >> >>>  };
> >> >>
> >> >> It will not work for legacy hardware. Old descriptor is 2 words wide, the new one is 4 words wide.
> >> >> If you enable CONFIG_ARCH_DMA_ADDR_T_64BIT but hardware doesn't
> >> >> support it at all, you will miss every second descriptor.
> >> >>
> >> >
> >> > True, this feature is not available in all of Cadence IP versions.
> >> > In fact, the IP version Zynq does not support this. But the one in ZynqMP does.
> >> > So, we enable kernel config for 64 bit DMA addressing for this SoC
> >> > and hence the driver picks it up. My assumption was that if the
> >> > legacy IP does not support
> >> > 64 bit addressing, then this DMA option wouldn't be enabled.
> >> >
> >> > There is a design config register in Cadence IP which is being read
> >> > to check for 64 bit address support - DMA mask is set based on that.
> >> > But the addition of two descriptor words cannot be based on this runtime check.
> >> > For this reason, all the static changes were placed under this check.
> >>
> >> We have quite a bunch of options in this driver to determinate what is the real capacity of the underlying hardware.
> >> If HW configuration registers are not appropriate, and it seems they are not, I would advice to simply use the DT compatibility string.
> >>
> >> Best regards,
> >> --
> >> Nicolas Ferre
> >
> > HW configuration registers are appropriate. The issue is that this code doesn’t use the capability bit to switch between different dma descriptors (2 words vs. 4 words).
> > DMA descriptor size is chosen based on kernel configuration, not based on hardware capabilities.
>
> HW configuration register does give appropriate information.
> But addition of two address words in the macb descriptor structure is a static change.
>
> +static inline void macb_set_addr(struct macb_dma_desc *desc, dma_addr_t
> +addr) {
> +       desc->addr = (u32)addr;
> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> +       desc->addrh = (u32)(addr >> 32); #endif
> +
>
> Even if the #ifdef condition here is changed to HW config check, addr and addrh are different.
> And "addrh" entry has to be present for 64 bit desc case to be handled separately.
> Can you please tell me how you propose change in DMA descriptor structure from
> 4 to 2 or 2 to 4 words *after* reading the DCFG register?

It is very complex problem. I wrote to you because I faced the same issue. I'm working on PTP implementation for macb. When PTP is enabled there are additional two words in buffer descriptor.
But hardware might not be compatible with PTP. Therefore I have to change DMA descriptor between 2 and 4 words after reading DCFG register (the same as you between 32b and 64b).
When we consider both PTP and 64 bits, we end up with 4 different descriptors!

1. 32b and without PTP support:

struct macb_dma_desc {
	u32	addr;
	u32	ctrl;
}

2. 64b and without PTP support:

struct macb_dma_desc {
	u32	addr;
	u32	ctrl;
	u32 	addrh;
	u32  	resvd;
}

3. 32 and PTP support:

struct macb_dma_desc {
	u32	addr;
	u32	ctrl;
	u32	dma_desc_ts_1;
	u32	dma_desc_ts_2;
};

4. 64b and PTP support:

struct macb_dma_desc {
	u32 	addr;
	u32 	ctrl;
	u32 	addrh;
	u32  	resvd;
	u32 	dma_desc_ts_1;
	u32	dma_desc_ts_2;
};

> Can you please tell me how you propose change in DMA descriptor structure from
> 4 to 2 or 2 to 4 words *after* reading the DCFG register?

I have some ideas but I don’t know whether it is possible to upstream it later on.
IMHO, we need to use the same mechanism in both our cases.

My very first idea to start discussion:
(Below is kind of pseudo code only to show my idea. All defines like 64B or PTP are omitted for simplicity)

1. Prepare appropriate structures:

struct macb_dma_desc {
	u32	addr;
	u32	ctrl;
}

struct macb_dma_desc_64 {
	u32 addrh;
	u32 resvd;
}

struct macb_dma_desc_ptp {
	u32 dma_desc_ts_1;
	u32	dma_desc_ts_2;
}

2. Add hardware support information to macb:

enum macb_hw_cap {
	HW_CAP_NONE,
	HW_CAP_64B,
	HW_CAP_PTP,
	HW_CAP_64B_PTP,
};

struct macb {
// (...)
	macb_hw_cap hw_cap;

}

3. Set bp->hw_cap on macb_probe()

4. Additional function might be helpful:

static unsigned char macb_dma_desc_get_mul(struct macb *bp)
{
	switch (bp->hw_cap) {
		case HW_CAP_NONE:
			return 1;
		case HW_CAP_64B:
		case HW_CAP_PTP:
			return 2;
		case HW_CAP_64B_PTP:
			return 3;
	}
}

5. Change sizeof struct to function:
(sizeof(struct macb_dma_desc) change to macb_dma_desc_get_size(bp). It will return sizeof(struct macb_dma_desc) * macb_dma_desc_get_mul(bp).
There is a hidden assumption that all three structures have the same size.

6. macb_rx_desc() and macb_tx_desc() will still return struct macb_dma_desc * but descriptor index will be counted in different way, ex.

static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
{
	index *= macb_dma_desc_get_mul(bp);
	return &bp->rx_ring[macb_rx_ring_wrap(bp, index)];
}

7. Two additional functions to dereference PTP and 64b information:

static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
{
	switch (bp->hw_cap) {
		case HW_CAP_64B:
		case HW_CAP_64B_PTP:
			return (struct macb_dma_desc_64 *)(desc + 1);  // ugly casting
		default:
			return NULL;
	}
}

static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp, struct macb_dma_desc *desc)
{
	switch (bp->hw_cap) {
		case HW_CAP_PTP:
			return (struct macb_dma_desc_ptp *)(desc + 1);
		case HW_CAP_64B_PTP:
			return (struct macb_dma_desc_ptp *)(desc + 2);
		default:
			return NULL;
	}
}

Whenever you want to reach fields in appropriate descriptor, above function should be used.

This is only my very first idea. Of course, we can leave it as it is and say, that old hardware is not support either when PTP enabled or 64b enabled.

^ permalink raw reply

* RE: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM
From: Rafal Ozieblo @ 2016-11-18  9:30 UTC (permalink / raw)
  To: Nicolas Ferre, Harini Katakam, Andrei Pistirica
  Cc: harini.katakam@xilinx.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <a315b554-8b44-ac82-a104-e382940750bb@atmel.com>

>-----Original Message-----         
>From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com] 
>Sent: 18 listopada 2016 10:10                        
>To: Rafal Ozieblo; Harini Katakam; Andrei Pistirica  
>Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
>Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support for GEM      
>                                                                                   
>Le 18/11/2016 à 09:59, Rafal Ozieblo a écrit :                                     
>> Hello,                                                                           
>>                                                                                  
>>> From: Harini Katakam [mailto:harinikatakamlinux@gmail.com]                      
>>> Sent: 18 listopada 2016 05:30                                                   
>>> To: Rafal Ozieblo                                                               
>>> Cc: Nicolas Ferre; harini.katakam@xilinx.com; netdev@vger.kernel.org;           
>>> linux-kernel@vger.kernel.org                                                    
>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing support           
>>> for GEM                                                                         
>>>                                                                                 
>>> Hi Rafal,                                                                       
>>>                                                                                 
>>> On Thu, Nov 17, 2016 at 7:05 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:      
>>>> -----Original Message-----                                                     
>>>> From: Nicolas Ferre [mailto:nicolas.ferre@atmel.com]                           
>>>> Sent: 17 listopada 2016 14:29                                                  
>>>> To: Harini Katakam; Rafal Ozieblo                                              
>>>> Cc: harini.katakam@xilinx.com; netdev@vger.kernel.org;                         
>>>> linux-kernel@vger.kernel.org                                                   
>>>> Subject: Re: [RFC PATCH 2/2] net: macb: Add 64 bit addressing                  
>>>> support for GEM                                                                
>>>>                                                                                
>>>>> Le 17/11/2016 à 13:21, Harini Katakam a écrit :                               
>>>>>> Hi Rafal,                                                                    
>>>>>>                                                                              
>>>>>> On Thu, Nov 17, 2016 at 5:20 PM, Rafal Ozieblo <rafalo@cadence.com> wrote:   
>>>>>>> Hello,                                                                      
>>>>>>> I think, there could a bug in your patch.                                   
>>>>>>>                                                                             
>>>>>>>> +                                                                          
>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                       
>>>>>>>> +             dmacfg |= GEM_BIT(ADDR64); #endif                            
>>>>>>>                                                                             
>>>>>>> You enable 64 bit addressing (64b dma bus width) always when appropriate architecture config option is enabled.                                                                                           
>>>>>>> But there are some legacy controllers which do not support that feature. According Cadence hardware team:                                                                                                 
>>>>>>> "64 bit addressing was added in July 2013. Earlier version do not have it.                       
>>>>>>> This feature was enhanced in release August 2014 to have separate upper address values for transmit and receive."                                                                                         
>>>>>>>                                                                                                  
>>>>>>>> /* Bitfields in NSR */                                                                          
>>>>>>>> @@ -474,6 +479,10 @@                                                                            
>>>>>>>>  struct macb_dma_desc {                                                                         
>>>>>>>  >      u32     addr;                                                                            
>>>>>>>>       u32     ctrl;                                                                             
>>>>>>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                            
>>>>>>>> +     u32     addrh;                                                                            
>>>>>>>> +     u32     resvd;                                                                            
>>>>>>>> +#endif                                                                                         
>>>>>>>>  };                                                                                             
>>>>>>>                                                                                                  
>>>>>>> It will not work for legacy hardware. Old descriptor is 2 words wide, the new one is 4 words wide.                                                                                                        
>>>>>>> If you enable CONFIG_ARCH_DMA_ADDR_T_64BIT but hardware doesn't                                  
>>>>>>> support it at all, you will miss every second descriptor.                                        
>>>>>>>                                                                                                  
>>>>>>                                                                                                   
>>>>>> True, this feature is not available in all of Cadence IP versions.                                
>>>>>> In fact, the IP version Zynq does not support this. But the one in ZynqMP does.                   
>>>>>> So, we enable kernel config for 64 bit DMA addressing for this SoC                                
>>>>>> and hence the driver picks it up. My assumption was that if the                                   
>>>>>> legacy IP does not support                                                                        
>>>>>> 64 bit addressing, then this DMA option wouldn't be enabled.                                      
>>>>>>                                                                                                   
>>>>>> There is a design config register in Cadence IP which is being                                    
>>>>>> read to check for 64 bit address support - DMA mask is set based on that.                         
>>>>>> But the addition of two descriptor words cannot be based on this runtime check.                   
>>>>>> For this reason, all the static changes were placed under this check.                             
>>>>>                                                                                                    
>>>>> We have quite a bunch of options in this driver to determinate what is the real capacity of the underlying hardware.                                                                                        
>>>>> If HW configuration registers are not appropriate, and it seems they are not, I would advice to simply use the DT compatibility string.                                                                     
>>>>>                                                                                                    
>>>>> Best regards,                                                                                      
>>>>> --                                                                                                 
>>>>> Nicolas Ferre                                                                                      
>>>>                                                                                                     
>>>> HW configuration registers are appropriate. The issue is that this code doesn’t use the capability bit to switch between different dma descriptors (2 words vs. 4 words).                                    
>>>> DMA descriptor size is chosen based on kernel configuration, not based on hardware capabilities.    
>>>                                                                                                      
>>> HW configuration register does give appropriate information.                                         
>>> But addition of two address words in the macb descriptor structure is a static change.               
>>>                                                                                                      
>>> +static inline void macb_set_addr(struct macb_dma_desc *desc,                                        
>>> +dma_addr_t                                                                                          
>>> +addr) {                                                                                             
>>> +       desc->addr = (u32)addr;                                                                      
>>> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT                                                                 
>>> +       desc->addrh = (u32)(addr >> 32); #endif                                                      
>>> +                                                                                                    
>>>                                                                                                      
>>> Even if the #ifdef condition here is changed to HW config check, addr and addrh are different.       
>>> And "addrh" entry has to be present for 64 bit desc case to be handled separately.                   
>>> Can you please tell me how you propose change in DMA descriptor                                      
>>> structure from                                                                                       
>>> 4 to 2 or 2 to 4 words *after* reading the DCFG register?                                            
>>                                                                                                       
>> It is very complex problem. I wrote to you because I faced the same issue. I'm working on PTP implementation for macb. When PTP is enabled there are additional two words in buffer descriptor.                
>                                                                                                        
>Moreover, we can use PTP without the 64bits descriptor support (early GEM revisions).                   
>                                                                                                        
>BTW, note that there is an initiative ongoing with Andrei to support                                    
>PTP/1588 on these devices with patches already send: please synchronize with him.                       
>https://urldefense.proofpoint.com/v2/url?u=https-3A__marc.info_-3Fl-3Dlinux-2Dnetdev-26m-3D147282092309112-26w-3D3&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=kr_km0MKQBzpkaOt0fkM-FIajN1-pOylzzTjsXi-vak&e=    
>or                                                                                                      
>https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_9310989_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=ZbXVD5Lb5zGn7wUKIPYHxagIEKp_vJvrnkRa4qJfmTY&e=                              
>and                                                                                                     
>https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_9310991_&d=DgIDaQ&c=aUq983L2pue2FqKFoP6PGHMJQyoJ7kl3s3GZ-_haXqY&r=MWSZN_jP4BHjuU9UFsrndALGeJqIXzD0WtGCtCg4L5E&m=jUmZzqwn1uRrvcqF3BHCHFC6ZsKoZkU3vT8gJ-7fnsE&s=Z0kRqUqh5Is4TmuaY7A4hnpizfdeq3HrgPhyDAMLuA8&e=                              
>                                                                                                        
>Regards,                                                                                                
>--
>Nicolas Ferre

Above patch doesn’t use hardware timestamps in descriptors at all. It doesn't use appropriate accuracy. 
We have our PTP patch ready, which use timestamps from descriptor. But we have not sent it yet because of compatibility issue.
Of course, we can do it like Harini did:

struct macb_dma_desc {
	u32	addr;
	u32	ctrl;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
	u32     addrh;
	u32     resvd;
#endif
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
	u32	dma_desc_ts_1;
	u32	dma_desc_ts_2;
#endif
};

But in that approach we lose backward compatibility.

What are your suggestion? Can we send patch like it is or wait for some common solution with backward compatibility?

Best regards,

Rafal Ozieblo   |   Firmware System Engineer, 
phone nbr.: +48 32 5085469    
www.cadence.com

^ permalink raw reply

* Re: [PATCH ipsec] xfrm: unbreak xfrm_sk_policy_lookup
From: Steffen Klassert @ 2016-11-18  9:17 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev
In-Reply-To: <1479385306-24731-1-git-send-email-fw@strlen.de>

On Thu, Nov 17, 2016 at 01:21:46PM +0100, Florian Westphal wrote:
> if we succeed grabbing the refcount, then
>   if (err && !xfrm_pol_hold_rcu)
> 
> will evaluate to false so this hits last else branch which then
> sets policy to ERR_PTR(0).
> 
> Fixes: ae33786f73a7ce ("xfrm: policy: only use rcu in xfrm_sk_policy_lookup")
> Reported-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Tested-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Signed-off-by: Florian Westphal <fw@strlen.de>

Applied to the ipsec tree, thanks everyone!

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox