mbox series

[v7,0/3] AX88796C SPI Ethernet Adapter

Message ID 20201124120330.32445-1-l.stelmach@samsung.com
Headers show
Series AX88796C SPI Ethernet Adapter | expand

Message

Łukasz Stelmach Nov. 24, 2020, 12:03 p.m. UTC
This is a driver for AX88796C Ethernet Adapter connected in SPI mode as
found on ARTIK5 evaluation board. The driver has been ported from a
v3.10.9 vendor kernel for ARTIK5 board.

Changes in v7:
  - removed duplicate code
  - moved a constant buffer definition away from a header file

Changes in v6:
  - fixed typos in Kconfig
  - checked argument value in ax88796c_set_tunable
  - updated tags in commit messages

Changes in v5:
  - coding style (local variable declarations)
  - added spi0 node in the DT binding example and removed
    interrupt-parent
  - removed comp module parameter
  - added CONFIG_SPI_AX88796C_COMPRESSION option to set the initial
    state of SPI compression
  - introduced new ethtool tunable "spi-compression" to controll SPI
    transfer compression
  - removed unused fields in struct ax88796c_device
  - switched from using buffers allocated on stack for SPI transfers
    to DMA safe ones embedded in struct ax_spi and allocated with
    kmalloc()

Changes in v4:
  - fixed compilation problems in asix,ax88796c.yaml and in
  ax88796c_main.c introduced in v3

Changes in v3:
  - modify vendor-prefixes.yaml in a separate patch
  - fix several problems in the dt binding
    - removed unnecessary descriptions and properties
    - changed the order of entries
    - fixed problems with missing defines in the example
  - change (1 << N) to BIT(N), left a few (0 << N)
  - replace ax88796c_get_link(), ax88796c_get_link_ksettings(),
    ax88796c_set_link_ksettings(), ax88796c_nway_reset(),
    ax88796c_set_mac_address() with appropriate kernel functions.
  - disable PHY auto-polling in MAC and use PHYLIB to track the state
    of PHY and configure MAC
  - propagate return values instead of returning constants in several
    places
  - add WARN_ON() for unlocked mutex
  - remove local work queue and use the system_wq
  - replace phy_connect_direct() with phy_connect() and move
    devm_register_netdev() to the end of ax88796c_probe()
    (Unlike phy_connect_direct() phy_connect() does not crash if the
    network device isn't registered yet.)
  - remove error messages on ENOMEM
  - move free_irq() to the end of ax88796c_close() to avoid race
    condition
  - implement flow-control

Changes in v2:
  - use phylib
  - added DT bindings
  - moved #includes to *.c files
  - used mutex instead of a semaphore for locking
  - renamed some constants
  - added error propagation for several functions
  - used ethtool for dumping registers
  - added control over checksum offloading
  - remove vendor specific PM
  - removed macaddr module parameter and added support for reading a MAC
    address from platform data (e.g. DT)
  - removed dependency on SPI from NET_VENDOR_ASIX
  - added an entry in the MAINTAINERS file
  - simplified logging with appropriate netif_* and netdev_* helpers
  - lots of style fixes

Łukasz Stelmach (3):
  dt-bindings: vendor-prefixes: Add asix prefix
  dt-bindings: net: Add bindings for AX88796C SPI Ethernet Adapter
  net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver

 .../bindings/net/asix,ax88796c.yaml           |   73 ++
 .../devicetree/bindings/vendor-prefixes.yaml  |    2 +
 MAINTAINERS                                   |    6 +
 drivers/net/ethernet/Kconfig                  |    1 +
 drivers/net/ethernet/Makefile                 |    1 +
 drivers/net/ethernet/asix/Kconfig             |   35 +
 drivers/net/ethernet/asix/Makefile            |    6 +
 drivers/net/ethernet/asix/ax88796c_ioctl.c    |  221 ++++
 drivers/net/ethernet/asix/ax88796c_ioctl.h    |   26 +
 drivers/net/ethernet/asix/ax88796c_main.c     | 1132 +++++++++++++++++
 drivers/net/ethernet/asix/ax88796c_main.h     |  561 ++++++++
 drivers/net/ethernet/asix/ax88796c_spi.c      |  112 ++
 drivers/net/ethernet/asix/ax88796c_spi.h      |   69 +
 include/uapi/linux/ethtool.h                  |    1 +
 net/ethtool/common.c                          |    1 +
 15 files changed, 2247 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/asix,ax88796c.yaml
 create mode 100644 drivers/net/ethernet/asix/Kconfig
 create mode 100644 drivers/net/ethernet/asix/Makefile
 create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.c
 create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.h
 create mode 100644 drivers/net/ethernet/asix/ax88796c_main.c
 create mode 100644 drivers/net/ethernet/asix/ax88796c_main.h
 create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.c
 create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.h

Comments

Krzysztof Kozlowski Nov. 24, 2020, 12:17 p.m. UTC | #1
On Tue, Nov 24, 2020 at 01:03:30PM +0100, Łukasz Stelmach wrote:
> ASIX AX88796[1] is a versatile ethernet adapter chip, that can be
> connected to a CPU with a 8/16-bit bus or with an SPI. This driver
> supports SPI connection.
> 
> The driver has been ported from the vendor kernel for ARTIK5[2]
> boards. Several changes were made to adapt it to the current kernel
> which include:
> 
> + updated DT configuration,
> + clock configuration moved to DT,
> + new timer, ethtool and gpio APIs,
> + dev_* instead of pr_* and custom printk() wrappers,
> + removed awkward vendor power managemtn.
> + introduced ethtool tunable to control SPI compression
> 
> [1] https://www.asix.com.tw/products.php?op=pItemdetail&PItemID=104;65;86&PLine=65
> [2] https://git.tizen.org/cgit/profile/common/platform/kernel/linux-3.10-artik/
> 
> The other ax88796 driver is for NE2000 compatible AX88796L chip. These
> chips are not compatible. Hence, two separate drivers are required.
> 
> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
> ---
>  MAINTAINERS                                |    6 +
>  drivers/net/ethernet/Kconfig               |    1 +
>  drivers/net/ethernet/Makefile              |    1 +
>  drivers/net/ethernet/asix/Kconfig          |   35 +
>  drivers/net/ethernet/asix/Makefile         |    6 +
>  drivers/net/ethernet/asix/ax88796c_ioctl.c |  221 ++++
>  drivers/net/ethernet/asix/ax88796c_ioctl.h |   26 +
>  drivers/net/ethernet/asix/ax88796c_main.c  | 1132 ++++++++++++++++++++
>  drivers/net/ethernet/asix/ax88796c_main.h  |  561 ++++++++++
>  drivers/net/ethernet/asix/ax88796c_spi.c   |  112 ++
>  drivers/net/ethernet/asix/ax88796c_spi.h   |   69 ++
>  include/uapi/linux/ethtool.h               |    1 +
>  net/ethtool/common.c                       |    1 +
>  13 files changed, 2172 insertions(+)
>  create mode 100644 drivers/net/ethernet/asix/Kconfig
>  create mode 100644 drivers/net/ethernet/asix/Makefile
>  create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.c
>  create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.h
>  create mode 100644 drivers/net/ethernet/asix/ax88796c_main.c
>  create mode 100644 drivers/net/ethernet/asix/ax88796c_main.h
>  create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.c
>  create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 14b8ec0bb58b..930dc859d4f7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2812,6 +2812,12 @@ S:	Maintained
>  F:	Documentation/hwmon/asc7621.rst
>  F:	drivers/hwmon/asc7621.c
>  
> +ASIX AX88796C SPI ETHERNET ADAPTER
> +M:	Łukasz Stelmach <l.stelmach@samsung.com>
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/net/asix,ax99706c-spi.yaml

Wrong file name.

Best regards,
Krzysztof


> +F:	drivers/net/ethernet/asix/ax88796c_*
> +
Łukasz Stelmach Nov. 24, 2020, 2:29 p.m. UTC | #2
It was <2020-11-24 wto 13:17>, when Krzysztof Kozlowski wrote:
> On Tue, Nov 24, 2020 at 01:03:30PM +0100, Łukasz Stelmach wrote:
>> ASIX AX88796[1] is a versatile ethernet adapter chip, that can be
>> connected to a CPU with a 8/16-bit bus or with an SPI. This driver
>> supports SPI connection.
>> 
>> The driver has been ported from the vendor kernel for ARTIK5[2]
>> boards. Several changes were made to adapt it to the current kernel
>> which include:
>> 
>> + updated DT configuration,
>> + clock configuration moved to DT,
>> + new timer, ethtool and gpio APIs,
>> + dev_* instead of pr_* and custom printk() wrappers,
>> + removed awkward vendor power managemtn.
>> + introduced ethtool tunable to control SPI compression
>> 
>> [1]
>> https://protect2.fireeye.com/v1/url?k=400e2614-1f951ecd-400fad5b-0cc47a3356b2-10d6caf77ede1dd5&q=1&e=8ef355b1-1777-4137-878d-2b11d6ef0003&u=https%3A%2F%2Fwww.asix.com.tw%2Fproducts.php%3Fop%3DpItemdetail%26PItemID%3D104%3B65%3B86%26PLine%3D65
>> [2]
>> https://protect2.fireeye.com/v1/url?k=519692a9-0e0daa70-519719e6-0cc47a3356b2-b5daaace05887741&q=1&e=8ef355b1-1777-4137-878d-2b11d6ef0003&u=https%3A%2F%2Fgit.tizen.org%2Fcgit%2Fprofile%2Fcommon%2Fplatform%2Fkernel%2Flinux-3.10-artik%2F
>> 
>> The other ax88796 driver is for NE2000 compatible AX88796L chip. These
>> chips are not compatible. Hence, two separate drivers are required.
>> 
>> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
>> ---
>>  MAINTAINERS                                |    6 +
>>  drivers/net/ethernet/Kconfig               |    1 +
>>  drivers/net/ethernet/Makefile              |    1 +
>>  drivers/net/ethernet/asix/Kconfig          |   35 +
>>  drivers/net/ethernet/asix/Makefile         |    6 +
>>  drivers/net/ethernet/asix/ax88796c_ioctl.c |  221 ++++
>>  drivers/net/ethernet/asix/ax88796c_ioctl.h |   26 +
>>  drivers/net/ethernet/asix/ax88796c_main.c  | 1132 ++++++++++++++++++++
>>  drivers/net/ethernet/asix/ax88796c_main.h  |  561 ++++++++++
>>  drivers/net/ethernet/asix/ax88796c_spi.c   |  112 ++
>>  drivers/net/ethernet/asix/ax88796c_spi.h   |   69 ++
>>  include/uapi/linux/ethtool.h               |    1 +
>>  net/ethtool/common.c                       |    1 +
>>  13 files changed, 2172 insertions(+)
>>  create mode 100644 drivers/net/ethernet/asix/Kconfig
>>  create mode 100644 drivers/net/ethernet/asix/Makefile
>>  create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.c
>>  create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.h
>>  create mode 100644 drivers/net/ethernet/asix/ax88796c_main.c
>>  create mode 100644 drivers/net/ethernet/asix/ax88796c_main.h
>>  create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.c
>>  create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.h
>> 
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 14b8ec0bb58b..930dc859d4f7 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -2812,6 +2812,12 @@ S:	Maintained
>>  F:	Documentation/hwmon/asc7621.rst
>>  F:	drivers/hwmon/asc7621.c
>>  
>> +ASIX AX88796C SPI ETHERNET ADAPTER
>> +M:	Łukasz Stelmach <l.stelmach@samsung.com>
>> +S:	Maintained
>> +F:	Documentation/devicetree/bindings/net/asix,ax99706c-spi.yaml
>
> Wrong file name.

Fixed. Thanks.
Andrew Lunn Nov. 24, 2020, 10:33 p.m. UTC | #3
On Tue, Nov 24, 2020 at 01:03:30PM +0100, Łukasz Stelmach wrote:
> ASIX AX88796[1] is a versatile ethernet adapter chip, that can be
> connected to a CPU with a 8/16-bit bus or with an SPI. This driver
> supports SPI connection.
> 
> The driver has been ported from the vendor kernel for ARTIK5[2]
> boards. Several changes were made to adapt it to the current kernel
> which include:
> 
> + updated DT configuration,
> + clock configuration moved to DT,
> + new timer, ethtool and gpio APIs,
> + dev_* instead of pr_* and custom printk() wrappers,
> + removed awkward vendor power managemtn.
> + introduced ethtool tunable to control SPI compression
> 
> [1] https://www.asix.com.tw/products.php?op=pItemdetail&PItemID=104;65;86&PLine=65
> [2] https://git.tizen.org/cgit/profile/common/platform/kernel/linux-3.10-artik/
> 
> The other ax88796 driver is for NE2000 compatible AX88796L chip. These
> chips are not compatible. Hence, two separate drivers are required.
> 
> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew
Jakub Kicinski Nov. 25, 2020, 9:26 p.m. UTC | #4
On Tue, 24 Nov 2020 13:03:30 +0100 Łukasz Stelmach wrote:
> +static int
> +ax88796c_start_xmit(struct sk_buff *skb, struct net_device *ndev)
> +{
> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> +
> +	skb_queue_tail(&ax_local->tx_wait_q, skb);
> +	if (skb_queue_len(&ax_local->tx_wait_q) > TX_QUEUE_HIGH_WATER) {
> +		netif_err(ax_local, tx_queued, ndev,
> +			  "Too many TX packets in queue %d\n",
> +			  skb_queue_len(&ax_local->tx_wait_q));

This will probably happen under heavy traffic. No need to print errors,
it's normal to back pressure.

> +		netif_stop_queue(ndev);
> +	}
> +
> +	set_bit(EVENT_TX, &ax_local->flags);
> +	schedule_work(&ax_local->ax_work);
> +
> +	return NETDEV_TX_OK;
> +}
> +
> +static void
> +ax88796c_skb_return(struct ax88796c_device *ax_local, struct sk_buff *skb,
> +		    struct rx_header *rxhdr)
> +{
> +	struct net_device *ndev = ax_local->ndev;
> +	int status;
> +
> +	do {
> +		if (!(ndev->features & NETIF_F_RXCSUM))
> +			break;
> +
> +		/* checksum error bit is set */
> +		if ((rxhdr->flags & RX_HDR3_L3_ERR) ||
> +		    (rxhdr->flags & RX_HDR3_L4_ERR))
> +			break;
> +
> +		/* Other types may be indicated by more than one bit. */
> +		if ((rxhdr->flags & RX_HDR3_L4_TYPE_TCP) ||
> +		    (rxhdr->flags & RX_HDR3_L4_TYPE_UDP))
> +			skb->ip_summed = CHECKSUM_UNNECESSARY;
> +	} while (0);
> +
> +	ax_local->stats.rx_packets++;
> +	ax_local->stats.rx_bytes += skb->len;
> +	skb->dev = ndev;
> +
> +	skb->truesize = skb->len + sizeof(struct sk_buff);
> +	skb->protocol = eth_type_trans(skb, ax_local->ndev);
> +
> +	netif_info(ax_local, rx_status, ndev, "< rx, len %zu, type 0x%x\n",
> +		   skb->len + sizeof(struct ethhdr), skb->protocol);
> +
> +	status = netif_rx(skb);

If I'm reading things right this is in process context, so netif_rx_ni()

> +	if (status != NET_RX_SUCCESS)
> +		netif_info(ax_local, rx_err, ndev,
> +			   "netif_rx status %d\n", status);

Again, it's inadvisable to put per packet prints without any rate
limiting in the data path.
Jakub Kicinski Nov. 25, 2020, 9:27 p.m. UTC | #5
On Tue, 24 Nov 2020 13:03:30 +0100 Łukasz Stelmach wrote:
> ASIX AX88796[1] is a versatile ethernet adapter chip, that can be
> connected to a CPU with a 8/16-bit bus or with an SPI. This driver
> supports SPI connection.
> 
> The driver has been ported from the vendor kernel for ARTIK5[2]
> boards. Several changes were made to adapt it to the current kernel
> which include:
> 
> + updated DT configuration,
> + clock configuration moved to DT,
> + new timer, ethtool and gpio APIs,
> + dev_* instead of pr_* and custom printk() wrappers,
> + removed awkward vendor power managemtn.
> + introduced ethtool tunable to control SPI compression
> 
> [1] https://www.asix.com.tw/products.php?op=pItemdetail&PItemID=104;65;86&PLine=65
> [2] https://git.tizen.org/cgit/profile/common/platform/kernel/linux-3.10-artik/
> 
> The other ax88796 driver is for NE2000 compatible AX88796L chip. These
> chips are not compatible. Hence, two separate drivers are required.
> 
> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>

drivers/net/ethernet/asix/ax88796c_main.c: In function ‘ax88796c_probe’:
drivers/net/ethernet/asix/ax88796c_main.c:966:32: warning: conversion from ‘long unsigned int’ to ‘u32’ {aka ‘unsigned int’} changes value from ‘18446744073709486079’ to ‘4294901759’ [-Woverflow]
  966 |  ax_local->mdiobus->phy_mask = ~BIT(AX88796C_PHY_ID);
      |                                ^
Łukasz Stelmach Dec. 2, 2020, 10:46 a.m. UTC | #6
It was <2020-11-25 śro 13:26>, when Jakub Kicinski wrote:
> On Tue, 24 Nov 2020 13:03:30 +0100 Łukasz Stelmach wrote:
>> +static int
>> +ax88796c_start_xmit(struct sk_buff *skb, struct net_device *ndev)
>> +{
>> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>> +
>> +	skb_queue_tail(&ax_local->tx_wait_q, skb);
>> +	if (skb_queue_len(&ax_local->tx_wait_q) > TX_QUEUE_HIGH_WATER) {
>> +		netif_err(ax_local, tx_queued, ndev,
>> +			  "Too many TX packets in queue %d\n",
>> +			  skb_queue_len(&ax_local->tx_wait_q));
>
> This will probably happen under heavy traffic. No need to print errors,
> it's normal to back pressure.
>

Removed.

>> +		netif_stop_queue(ndev);
>> +	}
>> +
>> +	set_bit(EVENT_TX, &ax_local->flags);
>> +	schedule_work(&ax_local->ax_work);
>> +
>> +	return NETDEV_TX_OK;
>> +}
>> +
>> +static void
>> +ax88796c_skb_return(struct ax88796c_device *ax_local, struct sk_buff *skb,
>> +		    struct rx_header *rxhdr)
>> +{
>> +	struct net_device *ndev = ax_local->ndev;
>> +	int status;
>> +
>> +	do {
>> +		if (!(ndev->features & NETIF_F_RXCSUM))
>> +			break;
>> +
>> +		/* checksum error bit is set */
>> +		if ((rxhdr->flags & RX_HDR3_L3_ERR) ||
>> +		    (rxhdr->flags & RX_HDR3_L4_ERR))
>> +			break;
>> +
>> +		/* Other types may be indicated by more than one bit. */
>> +		if ((rxhdr->flags & RX_HDR3_L4_TYPE_TCP) ||
>> +		    (rxhdr->flags & RX_HDR3_L4_TYPE_UDP))
>> +			skb->ip_summed = CHECKSUM_UNNECESSARY;
>> +	} while (0);
>> +
>> +	ax_local->stats.rx_packets++;
>> +	ax_local->stats.rx_bytes += skb->len;
>> +	skb->dev = ndev;
>> +
>> +	skb->truesize = skb->len + sizeof(struct sk_buff);
>> +	skb->protocol = eth_type_trans(skb, ax_local->ndev);
>> +
>> +	netif_info(ax_local, rx_status, ndev, "< rx, len %zu, type 0x%x\n",
>> +		   skb->len + sizeof(struct ethhdr), skb->protocol);
>> +
>> +	status = netif_rx(skb);
>
> If I'm reading things right this is in process context, so netif_rx_ni()
>

Is it? The stack looks as follows

    ax88796c_skb_return()
    ax88796c_rx_fixup()
    ax88796c_receive()
    ax88796c_process_isr()
    ax88796c_work()

and ax88796c_work() is a scheduled in the system_wq.

>> +	if (status != NET_RX_SUCCESS)
>> +		netif_info(ax_local, rx_err, ndev,
>> +			   "netif_rx status %d\n", status);
>
> Again, it's inadvisable to put per packet prints without any rate
> limiting in the data path.

Even if limmited by the msglvl flag, which is off by default?
Jakub Kicinski Dec. 2, 2020, 5:18 p.m. UTC | #7
On Wed, 02 Dec 2020 11:46:28 +0100 Lukasz Stelmach wrote:
> >> +	status = netif_rx(skb);  
> >
> > If I'm reading things right this is in process context, so netif_rx_ni()
> >  
> 
> Is it? The stack looks as follows
> 
>     ax88796c_skb_return()
>     ax88796c_rx_fixup()
>     ax88796c_receive()
>     ax88796c_process_isr()
>     ax88796c_work()
> 
> and ax88796c_work() is a scheduled in the system_wq.

Are you asking if work queue gets run in process context? It does.

> >> +	if (status != NET_RX_SUCCESS)
> >> +		netif_info(ax_local, rx_err, ndev,
> >> +			   "netif_rx status %d\n", status);  
> >
> > Again, it's inadvisable to put per packet prints without any rate
> > limiting in the data path.  
> 
> Even if limmited by the msglvl flag, which is off by default?

I'd err on the side of caution, but up to you.
Łukasz Stelmach Dec. 2, 2020, 8:07 p.m. UTC | #8
It was <2020-12-02 śro 09:18>, when Jakub Kicinski wrote:
> On Wed, 02 Dec 2020 11:46:28 +0100 Lukasz Stelmach wrote:
>> >> +	status = netif_rx(skb);  
>> >
>> > If I'm reading things right this is in process context, so netif_rx_ni()
>> >  
>> 
>> Is it? The stack looks as follows
>> 
>>     ax88796c_skb_return()
>>     ax88796c_rx_fixup()
>>     ax88796c_receive()
>>     ax88796c_process_isr()
>>     ax88796c_work()
>> 
>> and ax88796c_work() is a scheduled in the system_wq.
>
> Are you asking if work queue gets run in process context? It does.
>

Thanks. Changed.

>> >> +	if (status != NET_RX_SUCCESS)
>> >> +		netif_info(ax_local, rx_err, ndev,
>> >> +			   "netif_rx status %d\n", status);  
>> >
>> > Again, it's inadvisable to put per packet prints without any rate
>> > limiting in the data path.  
>> 
>> Even if limmited by the msglvl flag, which is off by default?
>
> I'd err on the side of caution, but up to you.
>

It isn't very common, but a few drivers do this.

Thank you.