diff mbox series

[net-next,08/18] ravb: Add R-Car common features

Message ID 20210722141351.13668-9-biju.das.jz@bp.renesas.com (mailing list archive)
State Superseded
Delegated to: Geert Uytterhoeven
Headers show
Series Add Gigabit Ethernet driver support | expand

Commit Message

Biju Das July 22, 2021, 2:13 p.m. UTC
The below features are supported by both R-Car Gen2 and Gen3.

1) magic packet detection
2) multiple TSRQ support
3) extended descriptor in rx
4) No half duplex support
5) override mtu change

Add features bits to support the same.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 drivers/net/ethernet/renesas/ravb_main.c | 110 +++++++++++++++--------
 1 file changed, 71 insertions(+), 39 deletions(-)

Comments

Sergei Shtylyov July 27, 2021, 8:48 p.m. UTC | #1
Hello!

On 7/22/21 5:13 PM, Biju Das wrote:

> The below features are supported by both R-Car Gen2 and Gen3.
> 
> 1) magic packet detection
> 2) multiple TSRQ support
> 3) extended descriptor in rx

   I think this one should better be called timestamping...

> 4) No half duplex support

   Couldn't we avoid the "negative" features?

> 5) override mtu change

   Hm, I'd vote for the individual patches covering only single feature...

> Add features bits to support the same.
> 
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
>  drivers/net/ethernet/renesas/ravb_main.c | 110 +++++++++++++++--------
>  1 file changed, 71 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
> index b3c99f974632..4ef2565534d2 100644
> --- a/drivers/net/ethernet/renesas/ravb_main.c
> +++ b/drivers/net/ethernet/renesas/ravb_main.c
[...]
> @@ -680,11 +694,14 @@ static void ravb_rcv_snd_enable(struct net_device *ndev)
>  /* function for waiting dma process finished */
>  static int ravb_stop_dma(struct net_device *ndev)
>  {
> +	struct ravb_private *priv = netdev_priv(ndev);
> +	const struct ravb_drv_data *info = priv->info;
>  	int error;
>  
>  	/* Wait for stopping the hardware TX process */
> -	error = ravb_wait(ndev, TCCR,
> -			  TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 0);
> +	if (info->features & RAVB_MULTI_TSRQ)
> +		error = ravb_wait(ndev, TCCR,
> +				  TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 0);
>  	if (error)

   What if the above *if* skips the ravb_wait() call -- didn't you get a complaint from gcc
about the unnintialized variable?

[...]
> @@ -808,11 +826,14 @@ static bool ravb_queue_interrupt(struct net_device *ndev, int q)
>  
>  static bool ravb_timestamp_interrupt(struct net_device *ndev)
>  {
> +	struct ravb_private *priv = netdev_priv(ndev);
> +	const struct ravb_drv_data *info = priv->info;
>  	u32 tis = ravb_read(ndev, TIS);
>  
>  	if (tis & TIS_TFUF) {
>  		ravb_write(ndev, ~(TIS_TFUF | TIS_RESERVED), TIS);
> -		ravb_get_tx_tstamp(ndev);
> +		if (info->features & RAVB_EX_RX_DESC)

   Yeah, definitely a bad feature name...

> +			ravb_get_tx_tstamp(ndev);
>  		return true;
>  	}
>  	return false;
[...]
> @@ -1069,15 +1091,17 @@ static int ravb_phy_init(struct net_device *ndev)
>  		netdev_info(ndev, "limited PHY to 100Mbit/s\n");
>  	}
>  
> -	/* 10BASE, Pause and Asym Pause is not supported */
> -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
> -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
> -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
> -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
> +	if (info->features & RAVB_NO_HALF_DUPLEX) {
> +		/* 10BASE, Pause and Asym Pause is not supported */
> +		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
> +		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
> +		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
> +		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
>  
> -	/* Half Duplex is not supported */
> -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
> -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
> +		/* Half Duplex is not supported */
> +		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
> +		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);

    Mhm? Some of the half-duplex modes sre unsupported still?

[...]
> @@ -1314,8 +1338,9 @@ static void ravb_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
>  static int ravb_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
>  {
>  	struct ravb_private *priv = netdev_priv(ndev);
> +	const struct ravb_drv_data *info = priv->info;
>  
> -	if (wol->wolopts & ~WAKE_MAGIC)
> +	if ((wol->wolopts & ~WAKE_MAGIC) || (!(info->features & RAVB_MAGIC)))

   Parens about !x not needed. And I think the second operand should come first instead...

>  		return -EOPNOTSUPP;
>  
>  	priv->wol_enabled = !!(wol->wolopts & WAKE_MAGIC);
[...]
> @@ -1595,28 +1621,30 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
>  	desc->dptr = cpu_to_le32(dma_addr);
>  
>  	/* TX timestamp required */
> -	if (q == RAVB_NC) {
> -		ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC);
> -		if (!ts_skb) {
> -			if (num_tx_desc > 1) {
> -				desc--;
> -				dma_unmap_single(ndev->dev.parent, dma_addr,
> -						 len, DMA_TO_DEVICE);
> +	if (info->features & RAVB_EX_RX_DESC) {

   Definitely a bad name...

[...]
> @@ -2205,8 +2235,10 @@ static int ravb_probe(struct platform_device *pdev)
>  	}
>  	clk_prepare_enable(priv->refclk);
>  
> -	ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
> -	ndev->min_mtu = ETH_MIN_MTU;
> +	if (info->features & RAVB_OVERRIDE_MTU_CHANGE) {

   Why? :-/ Could you tell me more details?

> +		ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
> +		ndev->min_mtu = ETH_MIN_MTU;
> +	}
>  
>  	priv->num_tx_desc = info->num_tx_desc;
>  

MBR, Sergei
Biju Das July 28, 2021, 10:13 a.m. UTC | #2
Hi Sergei,

Thanks for the feedback.

> Subject: Re: [PATCH net-next 08/18] ravb: Add R-Car common features
> 
> Hello!
> 
> On 7/22/21 5:13 PM, Biju Das wrote:
> 
> > The below features are supported by both R-Car Gen2 and Gen3.
> >
> > 1) magic packet detection
> > 2) multiple TSRQ support
> > 3) extended descriptor in rx
> 
>    I think this one should better be called timestamping...

OK. Will change it to timestamp.

> 
> > 4) No half duplex support
> 
>    Couldn't we avoid the "negative" features?

10 Mbps/Half duplex(As per the comment below) is not supported in R-Car. May be it should be a "positive" feature for
RZ/G2L. probably we need to add this as part of RZ/G2L feature.

> 
> > 5) override mtu change
> 
>    Hm, I'd vote for the individual patches covering only single feature...

OK. That will make patches again simpler.

> 
> > Add features bits to support the same.
> >
> > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> > Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > ---
> >  drivers/net/ethernet/renesas/ravb_main.c | 110
> > +++++++++++++++--------
> >  1 file changed, 71 insertions(+), 39 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/renesas/ravb_main.c
> > b/drivers/net/ethernet/renesas/ravb_main.c
> > index b3c99f974632..4ef2565534d2 100644
> > --- a/drivers/net/ethernet/renesas/ravb_main.c
> > +++ b/drivers/net/ethernet/renesas/ravb_main.c
> [...]
> > @@ -680,11 +694,14 @@ static void ravb_rcv_snd_enable(struct
> > net_device *ndev)
> >  /* function for waiting dma process finished */  static int
> > ravb_stop_dma(struct net_device *ndev)  {
> > +	struct ravb_private *priv = netdev_priv(ndev);
> > +	const struct ravb_drv_data *info = priv->info;
> >  	int error;
> >
> >  	/* Wait for stopping the hardware TX process */
> > -	error = ravb_wait(ndev, TCCR,
> > -			  TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 0);
> > +	if (info->features & RAVB_MULTI_TSRQ)
> > +		error = ravb_wait(ndev, TCCR,
> > +				  TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 |
> TCCR_TSRQ3, 0);
> >  	if (error)
> 
>    What if the above *if* skips the ravb_wait() call -- didn't you get a
> complaint from gcc about the unnintialized variable?

Good catch will initialize with error = 0 and later patch when we add RZ/G2L, will remove this unnecessary initialization.

> 
> [...]
> > @@ -808,11 +826,14 @@ static bool ravb_queue_interrupt(struct
> > net_device *ndev, int q)
> >
> >  static bool ravb_timestamp_interrupt(struct net_device *ndev)  {
> > +	struct ravb_private *priv = netdev_priv(ndev);
> > +	const struct ravb_drv_data *info = priv->info;
> >  	u32 tis = ravb_read(ndev, TIS);
> >
> >  	if (tis & TIS_TFUF) {
> >  		ravb_write(ndev, ~(TIS_TFUF | TIS_RESERVED), TIS);
> > -		ravb_get_tx_tstamp(ndev);
> > +		if (info->features & RAVB_EX_RX_DESC)
> 
>    Yeah, definitely a bad feature name...
OK. AS you suggested, will change the macro RAVB_EX_RX_DESC to ravb_timestamp feature bit like sh_eth.

> 
> > +			ravb_get_tx_tstamp(ndev);
> >  		return true;
> >  	}
> >  	return false;
> [...]
> > @@ -1069,15 +1091,17 @@ static int ravb_phy_init(struct net_device
> *ndev)
> >  		netdev_info(ndev, "limited PHY to 100Mbit/s\n");
> >  	}
> >
> > -	/* 10BASE, Pause and Asym Pause is not supported */
> > -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
> > -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
> > -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
> > -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
> > +	if (info->features & RAVB_NO_HALF_DUPLEX) {
> > +		/* 10BASE, Pause and Asym Pause is not supported */
> > +		phy_remove_link_mode(phydev,
> ETHTOOL_LINK_MODE_10baseT_Half_BIT);
> > +		phy_remove_link_mode(phydev,
> ETHTOOL_LINK_MODE_10baseT_Full_BIT);
> > +		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
> > +		phy_remove_link_mode(phydev,
> ETHTOOL_LINK_MODE_Asym_Pause_BIT);
> >
> > -	/* Half Duplex is not supported */
> > -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
> > -	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
> > +		/* Half Duplex is not supported */
> > +		phy_remove_link_mode(phydev,
> ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
> > +		phy_remove_link_mode(phydev,
> ETHTOOL_LINK_MODE_100baseT_Half_BIT);
> 
>     Mhm? Some of the half-duplex modes sre unsupported still?
> 
> [...]
> > @@ -1314,8 +1338,9 @@ static void ravb_get_wol(struct net_device
> > *ndev, struct ethtool_wolinfo *wol)  static int ravb_set_wol(struct
> > net_device *ndev, struct ethtool_wolinfo *wol)  {
> >  	struct ravb_private *priv = netdev_priv(ndev);
> > +	const struct ravb_drv_data *info = priv->info;
> >
> > -	if (wol->wolopts & ~WAKE_MAGIC)
> > +	if ((wol->wolopts & ~WAKE_MAGIC) || (!(info->features &
> > +RAVB_MAGIC)))
> 
>    Parens about !x not needed. And I think the second operand should come
> first instead...

OK.

> 
> >  		return -EOPNOTSUPP;
> >
> >  	priv->wol_enabled = !!(wol->wolopts & WAKE_MAGIC);
> [...]
> > @@ -1595,28 +1621,30 @@ static netdev_tx_t ravb_start_xmit(struct
> sk_buff *skb, struct net_device *ndev)
> >  	desc->dptr = cpu_to_le32(dma_addr);
> >
> >  	/* TX timestamp required */
> > -	if (q == RAVB_NC) {
> > -		ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC);
> > -		if (!ts_skb) {
> > -			if (num_tx_desc > 1) {
> > -				desc--;
> > -				dma_unmap_single(ndev->dev.parent, dma_addr,
> > -						 len, DMA_TO_DEVICE);
> > +	if (info->features & RAVB_EX_RX_DESC) {
> 
>    Definitely a bad name...

OK.

> 
> [...]
> > @@ -2205,8 +2235,10 @@ static int ravb_probe(struct platform_device
> *pdev)
> >  	}
> >  	clk_prepare_enable(priv->refclk);
> >
> > -	ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
> > -	ndev->min_mtu = ETH_MIN_MTU;
> > +	if (info->features & RAVB_OVERRIDE_MTU_CHANGE) {
> 
>    Why? :-/ Could you tell me more details?

RX buff size = 2048 for R-Car where as it is 8K for RZ/G2L.
So Do you think we should use the same max_mtu for RZ/G2L as well?

Please let us know your recommendation here in this case?  The original bsp code used default "eth_mtu_change"
which is now deprecated.

Regards,
Biju

> 
> > +		ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
> > +		ndev->min_mtu = ETH_MIN_MTU;
> > +	}
> >
> >  	priv->num_tx_desc = info->num_tx_desc;
> >
> 
> MBR, Sergei
Andrew Lunn July 28, 2021, 1:45 p.m. UTC | #3
> > > @@ -2205,8 +2235,10 @@ static int ravb_probe(struct platform_device
> > *pdev)
> > >  	}
> > >  	clk_prepare_enable(priv->refclk);
> > >
> > > -	ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
> > > -	ndev->min_mtu = ETH_MIN_MTU;
> > > +	if (info->features & RAVB_OVERRIDE_MTU_CHANGE) {
> > 
> >    Why? :-/ Could you tell me more details?
> 
> RX buff size = 2048 for R-Car where as it is 8K for RZ/G2L.

RAVB_OVERRIDE_MTU_CHANGE is not the most descriptive name. You are not
overriding, you are setting the correct value for the hardware
variant.

Maybe name the feature RAVB_8K_BUFFERS or RAVB_2K_BUFFERS.

Also, putting more details in the commit message will help, and lots
of small patches, each patch doing one thing. It is much better to
have 40 simple, well documented, obviously correct patches, than 20
hard to understand patches. But please do submit them in small
batches, no more than 15 at once.

	 Andrew
Biju Das July 29, 2021, 3:10 p.m. UTC | #4
Hi Andrew,

Thanks for the feedback.

> Subject: Re: [PATCH net-next 08/18] ravb: Add R-Car common features
> 
> > > > @@ -2205,8 +2235,10 @@ static int ravb_probe(struct
> > > > platform_device
> > > *pdev)
> > > >  	}
> > > >  	clk_prepare_enable(priv->refclk);
> > > >
> > > > -	ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
> > > > -	ndev->min_mtu = ETH_MIN_MTU;
> > > > +	if (info->features & RAVB_OVERRIDE_MTU_CHANGE) {
> > >
> > >    Why? :-/ Could you tell me more details?
> >
> > RX buff size = 2048 for R-Car where as it is 8K for RZ/G2L.
> 
> RAVB_OVERRIDE_MTU_CHANGE is not the most descriptive name. You are not
> overriding, you are setting the correct value for the hardware variant.

Thanks for correcting me.

> Maybe name the feature RAVB_8K_BUFFERS or RAVB_2K_BUFFERS.

OK.

> 
> Also, putting more details in the commit message will help, and lots of
> small patches, each patch doing one thing. 

Agreed. Will send smaller patches with more details on commit message.

It is much better to have 40
> simple, well documented, obviously correct patches, than 20 hard to
> understand patches. But please do submit them in small batches, no more
> than 15 at once.

OK. 

Cheers,
Biju
diff mbox series

Patch

diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index b3c99f974632..4ef2565534d2 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -45,16 +45,30 @@ 
 #define RAVB_MULTI_IRQS			BIT(2)
 #define RAVB_INTERNAL_DELAY		BIT(3)
 #define RAVB_TX_DROP_COUNTER		BIT(4)
+#define RAVB_MAGIC			BIT(5)
+#define RAVB_MULTI_TSRQ			BIT(6)
+#define RAVB_NO_HALF_DUPLEX		BIT(7)
+#define RAVB_OVERRIDE_MTU_CHANGE	BIT(8)
+#define RAVB_EX_RX_DESC			BIT(9)
 
 #define RAVB_PTP	(RAVB_PTP_CONFIG_ACTIVE | RAVB_PTP_CONFIG_INACTIVE)
+#define RAVB_RCAR_COMMON \
+		(RAVB_MAGIC			| \
+		 RAVB_MULTI_TSRQ		| \
+		 RAVB_NO_HALF_DUPLEX		| \
+		 RAVB_OVERRIDE_MTU_CHANGE	| \
+		 RAVB_EX_RX_DESC)
 
 #define RAVB_RCAR_GEN3_FEATURES \
 		(RAVB_PTP_CONFIG_ACTIVE		| \
 		 RAVB_MULTI_IRQS		| \
 		 RAVB_INTERNAL_DELAY		| \
-		 RAVB_TX_DROP_COUNTER)
+		 RAVB_TX_DROP_COUNTER		| \
+		 RAVB_RCAR_COMMON)
 
-#define RAVB_RCAR_GEN2_FEATURES	RAVB_PTP_CONFIG_INACTIVE
+#define RAVB_RCAR_GEN2_FEATURES \
+		(RAVB_PTP_CONFIG_INACTIVE	| \
+		 RAVB_RCAR_COMMON)
 
 static const char *ravb_rx_irqs[NUM_RX_QUEUE] = {
 	"ch0", /* RAVB_BE */
@@ -680,11 +694,14 @@  static void ravb_rcv_snd_enable(struct net_device *ndev)
 /* function for waiting dma process finished */
 static int ravb_stop_dma(struct net_device *ndev)
 {
+	struct ravb_private *priv = netdev_priv(ndev);
+	const struct ravb_drv_data *info = priv->info;
 	int error;
 
 	/* Wait for stopping the hardware TX process */
-	error = ravb_wait(ndev, TCCR,
-			  TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 0);
+	if (info->features & RAVB_MULTI_TSRQ)
+		error = ravb_wait(ndev, TCCR,
+				  TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 0);
 	if (error)
 		return error;
 
@@ -709,12 +726,13 @@  static int ravb_stop_dma(struct net_device *ndev)
 static void ravb_emac_interrupt_unlocked(struct net_device *ndev)
 {
 	struct ravb_private *priv = netdev_priv(ndev);
+	const struct ravb_drv_data *info = priv->info;
 	u32 ecsr, psr;
 
 	ecsr = ravb_read(ndev, ECSR);
 	ravb_write(ndev, ecsr, ECSR);	/* clear interrupt */
 
-	if (ecsr & ECSR_MPD)
+	if ((info->features & RAVB_MAGIC) && (ecsr & ECSR_MPD))
 		pm_wakeup_event(&priv->pdev->dev, 0);
 	if (ecsr & ECSR_ICD)
 		ndev->stats.tx_carrier_errors++;
@@ -808,11 +826,14 @@  static bool ravb_queue_interrupt(struct net_device *ndev, int q)
 
 static bool ravb_timestamp_interrupt(struct net_device *ndev)
 {
+	struct ravb_private *priv = netdev_priv(ndev);
+	const struct ravb_drv_data *info = priv->info;
 	u32 tis = ravb_read(ndev, TIS);
 
 	if (tis & TIS_TFUF) {
 		ravb_write(ndev, ~(TIS_TFUF | TIS_RESERVED), TIS);
-		ravb_get_tx_tstamp(ndev);
+		if (info->features & RAVB_EX_RX_DESC)
+			ravb_get_tx_tstamp(ndev);
 		return true;
 	}
 	return false;
@@ -1024,6 +1045,7 @@  static int ravb_phy_init(struct net_device *ndev)
 {
 	struct device_node *np = ndev->dev.parent->of_node;
 	struct ravb_private *priv = netdev_priv(ndev);
+	const struct ravb_drv_data *info = priv->info;
 	struct phy_device *phydev;
 	struct device_node *pn;
 	phy_interface_t iface;
@@ -1069,15 +1091,17 @@  static int ravb_phy_init(struct net_device *ndev)
 		netdev_info(ndev, "limited PHY to 100Mbit/s\n");
 	}
 
-	/* 10BASE, Pause and Asym Pause is not supported */
-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
+	if (info->features & RAVB_NO_HALF_DUPLEX) {
+		/* 10BASE, Pause and Asym Pause is not supported */
+		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
+		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
+		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
+		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
 
-	/* Half Duplex is not supported */
-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
+		/* Half Duplex is not supported */
+		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
+	}
 
 	phy_attached_info(phydev);
 
@@ -1314,8 +1338,9 @@  static void ravb_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
 static int ravb_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
 {
 	struct ravb_private *priv = netdev_priv(ndev);
+	const struct ravb_drv_data *info = priv->info;
 
-	if (wol->wolopts & ~WAKE_MAGIC)
+	if ((wol->wolopts & ~WAKE_MAGIC) || (!(info->features & RAVB_MAGIC)))
 		return -EOPNOTSUPP;
 
 	priv->wol_enabled = !!(wol->wolopts & WAKE_MAGIC);
@@ -1519,6 +1544,7 @@  static void ravb_tx_timeout_work(struct work_struct *work)
 static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
 	struct ravb_private *priv = netdev_priv(ndev);
+	const struct ravb_drv_data *info = priv->info;
 	int num_tx_desc = priv->num_tx_desc;
 	u16 q = skb_get_queue_mapping(skb);
 	struct ravb_tstamp_skb *ts_skb;
@@ -1595,28 +1621,30 @@  static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	desc->dptr = cpu_to_le32(dma_addr);
 
 	/* TX timestamp required */
-	if (q == RAVB_NC) {
-		ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC);
-		if (!ts_skb) {
-			if (num_tx_desc > 1) {
-				desc--;
-				dma_unmap_single(ndev->dev.parent, dma_addr,
-						 len, DMA_TO_DEVICE);
+	if (info->features & RAVB_EX_RX_DESC) {
+		if (q == RAVB_NC) {
+			ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC);
+			if (!ts_skb) {
+				if (num_tx_desc > 1) {
+					desc--;
+					dma_unmap_single(ndev->dev.parent, dma_addr,
+							 len, DMA_TO_DEVICE);
+				}
+				goto unmap;
 			}
-			goto unmap;
+			ts_skb->skb = skb_get(skb);
+			ts_skb->tag = priv->ts_skb_tag++;
+			priv->ts_skb_tag &= 0x3ff;
+			list_add_tail(&ts_skb->list, &priv->ts_skb_list);
+
+			/* TAG and timestamp required flag */
+			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+			desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR;
+			desc->ds_tagl |= cpu_to_le16(ts_skb->tag << 12);
 		}
-		ts_skb->skb = skb_get(skb);
-		ts_skb->tag = priv->ts_skb_tag++;
-		priv->ts_skb_tag &= 0x3ff;
-		list_add_tail(&ts_skb->list, &priv->ts_skb_list);
 
-		/* TAG and timestamp required flag */
-		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
-		desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR;
-		desc->ds_tagl |= cpu_to_le16(ts_skb->tag << 12);
+		skb_tx_timestamp(skb);
 	}
-
-	skb_tx_timestamp(skb);
 	/* Descriptor type must be set after all the above writes */
 	dma_wmb();
 	if (num_tx_desc > 1) {
@@ -1727,10 +1755,12 @@  static int ravb_close(struct net_device *ndev)
 			   "device will be stopped after h/w processes are done.\n");
 
 	/* Clear the timestamp list */
-	list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
-		list_del(&ts_skb->list);
-		kfree_skb(ts_skb->skb);
-		kfree(ts_skb);
+	if (info->features & RAVB_EX_RX_DESC) {
+		list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
+			list_del(&ts_skb->list);
+			kfree_skb(ts_skb->skb);
+			kfree(ts_skb);
+		}
 	}
 
 	/* PHY disconnect */
@@ -2205,8 +2235,10 @@  static int ravb_probe(struct platform_device *pdev)
 	}
 	clk_prepare_enable(priv->refclk);
 
-	ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
-	ndev->min_mtu = ETH_MIN_MTU;
+	if (info->features & RAVB_OVERRIDE_MTU_CHANGE) {
+		ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
+		ndev->min_mtu = ETH_MIN_MTU;
+	}
 
 	priv->num_tx_desc = info->num_tx_desc;