Re: [PATCH v10 3/3] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver

2021-01-20 Thread Jakub Kicinski
On Wed, 20 Jan 2021 20:30:14 +0100 Lukasz Stelmach wrote:
> > You need to use 64 bit stats, like struct rtnl_link_stats64.
> > On a 32bit system at 100Mbps ulong can wrap in minutes.
> >  
> 
> Let me see. At first glance
> 
> git grep -l ndo_get_stats\\\> drivers/net/ethernet/  | xargs grep -li 
> SPEED_100\\\>
> 
> quite a number of Fast Ethernet drivers use net_device_stats. Let me
> calculate.
> 
> - bytes
>   100Mbps is ~10MiB/s
>   sending 4GiB at 10MiB/s takes 27 minutes
> 
> - packets
>   minimum frame size is 84 bytes (840 bits on the wire) on 100Mbps means
>   119048 pps at this speed it takse 10 hours to transmit 2^32 packets
> 
> Anyway, I switched to rtnl_link_stats64. Tell me, is it OK to just
> memcpy() in .ndo_get_stats64?

Yup, you can just memcpy() your local copy over the one you get as an
argument of ndo_get_stats64

> >> +  struct work_struct  ax_work;  
> >
> > I don't see you ever canceling / flushing this work.
> > You should do that at least on driver remove if not close.  
> 
> Done.
> 
> Does it mean most drivers do it wrong?
> 
> git grep INIT_WORK drivers/net/ethernet/ | \
> sed -e 's/\(^[^:]*\):[^>]*->\([^,]*\),.*/\1\2/' | \
> while read file var; do \
> grep -H $var $file;
> done | grep INIT_WORK\\\|cancel_work

Some may use flush, but I wouldn't be surprised if there were bugs like
this out there.


Re: [PATCH v10 3/3] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver

2021-01-20 Thread Andrew Lunn
On Wed, Jan 20, 2021 at 08:30:14PM +0100, Lukasz Stelmach wrote:
> It was <2021-01-15 pią 17:27>, when Jakub Kicinski wrote:
> > On Wed, 13 Jan 2021 19:40:28 +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
> >> 
> 
> [...]
> 
> >> 
> >> 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 
> >> Reviewed-by: Andrew Lunn 
> >
> >> +static u32 ax88796c_get_priv_flags(struct net_device *ndev)
> >> +{
> >> +  struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> >> +
> >> +return ax_local->priv_flags;
> >
> > stray indent
> >
> >> +}
> 
> Done.
> 
> >> +#define MAX(x,y) ((x) > (y) ? (x) : (y))
> >
> > Please use the standard linux max / max_t macros.
> 
> Done.
> 
> >> +static struct sk_buff *
> >> +ax88796c_tx_fixup(struct net_device *ndev, struct sk_buff_head *q)
> >> +{
> >> +  struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> >> +  u8 spi_len = ax_local->ax_spi.comp ? 1 : 4;
> >> +  struct sk_buff *skb;
> >> +  struct tx_pkt_info *info;
> >> +  struct skb_data *entry;
> >> +  u16 pkt_len;
> >> +  u8 padlen, seq_num;
> >> +  u8 need_pages;
> >> +  int headroom;
> >> +  int tailroom;
> >> +
> >> +  if (skb_queue_empty(q))
> >> +  return NULL;
> >> +
> >> +  skb = skb_peek(q);
> >> +  pkt_len = skb->len;
> >> +  need_pages = (pkt_len + TX_OVERHEAD + 127) >> 7;
> >> +  if (ax88796c_check_free_pages(ax_local, need_pages) != 0)
> >> +  return NULL;
> >> +
> >> +  headroom = skb_headroom(skb);
> >> +  tailroom = skb_tailroom(skb);
> >> +  padlen = round_up(pkt_len, 4) - pkt_len;
> >> +  seq_num = ++ax_local->seq_num & 0x1F;
> >> +
> >> +  info = (struct tx_pkt_info *)skb->cb;
> >> +  info->pkt_len = pkt_len;
> >> +
> >> +  if (skb_cloned(skb) ||
> >> +  (headroom < (TX_OVERHEAD + spi_len)) ||
> >> +  (tailroom < (padlen + TX_EOP_SIZE))) {
> >> +  size_t h = MAX((TX_OVERHEAD + spi_len) - headroom,0);
> >> +  size_t t = MAX((padlen + TX_EOP_SIZE) - tailroom,0);
> >> +
> >> +  if (pskb_expand_head(skb, h, t, GFP_KERNEL))
> >> +  return NULL;
> >> +  }
> >> +
> >> +  info->seq_num = seq_num;
> >> +  ax88796c_proc_tx_hdr(info, skb->ip_summed);
> >> +
> >> +  /* SOP and SEG header */
> >> +  memcpy(skb_push(skb, TX_OVERHEAD), >sop, TX_OVERHEAD);
> >
> > why use skb->cb to store info? why not declare it on the stack?
> >
> 
> Done.
> 
> >> +  /* Write SPI TXQ header */
> >> +  memcpy(skb_push(skb, spi_len), ax88796c_tx_cmd_buf, spi_len);
> >> +
> >> +  /* Make 32-bit alignment */
> >> +  skb_put(skb, padlen);
> >> +
> >> +  /* EOP header */
> >> +  memcpy(skb_put(skb, TX_EOP_SIZE), >eop, TX_EOP_SIZE);
> >> +
> >> +  skb_unlink(skb, q);
> >> +
> >> +  entry = (struct skb_data *)skb->cb;
> >> +  memset(entry, 0, sizeof(*entry));
> >> +  entry->len = pkt_len;
> >> +
> >> +  if (netif_msg_pktdata(ax_local)) {
> >> +  char pfx[IFNAMSIZ + 7];
> >> +
> >> +  snprintf(pfx, sizeof(pfx), "%s: ", ndev->name);
> >> +
> >> +  netdev_info(ndev, "TX packet len %d, total len %d, seq %d\n",
> >> +  pkt_len, skb->len, seq_num);
> >> +
> >> +  netdev_info(ndev, "  SPI Header:\n");
> >> +  print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
> >> + skb->data, 4, 0);
> >> +
> >> +  netdev_info(ndev, "  TX SOP:\n");
> >> +  print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
> >> + skb->data + 4, TX_OVERHEAD, 0);
> >> +
> >> +  netdev_info(ndev, "  TX packet:\n");
> >> +  print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
> >> + skb->data + 4 + TX_OVERHEAD,
> >> + skb->len - TX_EOP_SIZE - 4 - TX_OVERHEAD, 0);
> >> +
> >> +  netdev_info(ndev, "  TX EOP:\n");
> >> +  print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
> >> + skb->data + skb->len - 4, 4, 0);
> >> +  }
> >> +
> >> +  return skb;
> >> +}
> >> +
> >> +static int ax88796c_hard_xmit(struct ax88796c_device *ax_local)
> >> +{
> >> +  struct sk_buff *tx_skb;
> >> +  struct skb_data *entry;
> >> +
> >> +  WARN_ON(!mutex_is_locked(_local->spi_lock));
> >> +
> >> +  tx_skb = ax88796c_tx_fixup(ax_local->ndev, 

Re: [PATCH v10 3/3] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver

2021-01-20 Thread Lukasz Stelmach
It was <2021-01-15 pią 17:27>, when Jakub Kicinski wrote:
> On Wed, 13 Jan 2021 19:40:28 +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
>> 

[...]

>> 
>> 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 
>> Reviewed-by: Andrew Lunn 
>
>> +static u32 ax88796c_get_priv_flags(struct net_device *ndev)
>> +{
>> +struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>> +
>> +return ax_local->priv_flags;
>
> stray indent
>
>> +}

Done.

>> +#define MAX(x,y) ((x) > (y) ? (x) : (y))
>
> Please use the standard linux max / max_t macros.

Done.

>> +static struct sk_buff *
>> +ax88796c_tx_fixup(struct net_device *ndev, struct sk_buff_head *q)
>> +{
>> +struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>> +u8 spi_len = ax_local->ax_spi.comp ? 1 : 4;
>> +struct sk_buff *skb;
>> +struct tx_pkt_info *info;
>> +struct skb_data *entry;
>> +u16 pkt_len;
>> +u8 padlen, seq_num;
>> +u8 need_pages;
>> +int headroom;
>> +int tailroom;
>> +
>> +if (skb_queue_empty(q))
>> +return NULL;
>> +
>> +skb = skb_peek(q);
>> +pkt_len = skb->len;
>> +need_pages = (pkt_len + TX_OVERHEAD + 127) >> 7;
>> +if (ax88796c_check_free_pages(ax_local, need_pages) != 0)
>> +return NULL;
>> +
>> +headroom = skb_headroom(skb);
>> +tailroom = skb_tailroom(skb);
>> +padlen = round_up(pkt_len, 4) - pkt_len;
>> +seq_num = ++ax_local->seq_num & 0x1F;
>> +
>> +info = (struct tx_pkt_info *)skb->cb;
>> +info->pkt_len = pkt_len;
>> +
>> +if (skb_cloned(skb) ||
>> +(headroom < (TX_OVERHEAD + spi_len)) ||
>> +(tailroom < (padlen + TX_EOP_SIZE))) {
>> +size_t h = MAX((TX_OVERHEAD + spi_len) - headroom,0);
>> +size_t t = MAX((padlen + TX_EOP_SIZE) - tailroom,0);
>> +
>> +if (pskb_expand_head(skb, h, t, GFP_KERNEL))
>> +return NULL;
>> +}
>> +
>> +info->seq_num = seq_num;
>> +ax88796c_proc_tx_hdr(info, skb->ip_summed);
>> +
>> +/* SOP and SEG header */
>> +memcpy(skb_push(skb, TX_OVERHEAD), >sop, TX_OVERHEAD);
>
> why use skb->cb to store info? why not declare it on the stack?
>

Done.

>> +/* Write SPI TXQ header */
>> +memcpy(skb_push(skb, spi_len), ax88796c_tx_cmd_buf, spi_len);
>> +
>> +/* Make 32-bit alignment */
>> +skb_put(skb, padlen);
>> +
>> +/* EOP header */
>> +memcpy(skb_put(skb, TX_EOP_SIZE), >eop, TX_EOP_SIZE);
>> +
>> +skb_unlink(skb, q);
>> +
>> +entry = (struct skb_data *)skb->cb;
>> +memset(entry, 0, sizeof(*entry));
>> +entry->len = pkt_len;
>> +
>> +if (netif_msg_pktdata(ax_local)) {
>> +char pfx[IFNAMSIZ + 7];
>> +
>> +snprintf(pfx, sizeof(pfx), "%s: ", ndev->name);
>> +
>> +netdev_info(ndev, "TX packet len %d, total len %d, seq %d\n",
>> +pkt_len, skb->len, seq_num);
>> +
>> +netdev_info(ndev, "  SPI Header:\n");
>> +print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
>> +   skb->data, 4, 0);
>> +
>> +netdev_info(ndev, "  TX SOP:\n");
>> +print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
>> +   skb->data + 4, TX_OVERHEAD, 0);
>> +
>> +netdev_info(ndev, "  TX packet:\n");
>> +print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
>> +   skb->data + 4 + TX_OVERHEAD,
>> +   skb->len - TX_EOP_SIZE - 4 - TX_OVERHEAD, 0);
>> +
>> +netdev_info(ndev, "  TX EOP:\n");
>> +print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
>> +   skb->data + skb->len - 4, 4, 0);
>> +}
>> +
>> +return skb;
>> +}
>> +
>> +static int ax88796c_hard_xmit(struct ax88796c_device *ax_local)
>> +{
>> +struct sk_buff *tx_skb;
>> +struct skb_data *entry;
>> +
>> +WARN_ON(!mutex_is_locked(_local->spi_lock));
>> +
>> +tx_skb = ax88796c_tx_fixup(ax_local->ndev, _local->tx_wait_q);
>> +
>> +if (!tx_skb)
>> +return 0;
>
> tx_dropped++ ?
>

Done.

>> +entry = (struct skb_data *)tx_skb->cb;
>> +
>> +AX_WRITE(_local->ax_spi,
>> + (TSNR_TXB_START | 

Re: [PATCH v10 3/3] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver

2021-01-15 Thread Jakub Kicinski
On Wed, 13 Jan 2021 19:40:28 +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=104;65;86=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 
> Reviewed-by: Andrew Lunn 

> +static u32 ax88796c_get_priv_flags(struct net_device *ndev)
> +{
> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> +
> +return ax_local->priv_flags;

stray indent

> +}

> +#define MAX(x,y) ((x) > (y) ? (x) : (y))

Please use the standard linux max / max_t macros.

> +static struct sk_buff *
> +ax88796c_tx_fixup(struct net_device *ndev, struct sk_buff_head *q)
> +{
> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> + u8 spi_len = ax_local->ax_spi.comp ? 1 : 4;
> + struct sk_buff *skb;
> + struct tx_pkt_info *info;
> + struct skb_data *entry;
> + u16 pkt_len;
> + u8 padlen, seq_num;
> + u8 need_pages;
> + int headroom;
> + int tailroom;
> +
> + if (skb_queue_empty(q))
> + return NULL;
> +
> + skb = skb_peek(q);
> + pkt_len = skb->len;
> + need_pages = (pkt_len + TX_OVERHEAD + 127) >> 7;
> + if (ax88796c_check_free_pages(ax_local, need_pages) != 0)
> + return NULL;
> +
> + headroom = skb_headroom(skb);
> + tailroom = skb_tailroom(skb);
> + padlen = round_up(pkt_len, 4) - pkt_len;
> + seq_num = ++ax_local->seq_num & 0x1F;
> +
> + info = (struct tx_pkt_info *)skb->cb;
> + info->pkt_len = pkt_len;
> +
> + if (skb_cloned(skb) ||
> + (headroom < (TX_OVERHEAD + spi_len)) ||
> + (tailroom < (padlen + TX_EOP_SIZE))) {
> + size_t h = MAX((TX_OVERHEAD + spi_len) - headroom,0);
> + size_t t = MAX((padlen + TX_EOP_SIZE) - tailroom,0);
> +
> + if (pskb_expand_head(skb, h, t, GFP_KERNEL))
> + return NULL;
> + }
> +
> + info->seq_num = seq_num;
> + ax88796c_proc_tx_hdr(info, skb->ip_summed);
> +
> + /* SOP and SEG header */
> + memcpy(skb_push(skb, TX_OVERHEAD), >sop, TX_OVERHEAD);

why use skb->cb to store info? why not declare it on the stack?

> + /* Write SPI TXQ header */
> + memcpy(skb_push(skb, spi_len), ax88796c_tx_cmd_buf, spi_len);
> +
> + /* Make 32-bit alignment */
> + skb_put(skb, padlen);
> +
> + /* EOP header */
> + memcpy(skb_put(skb, TX_EOP_SIZE), >eop, TX_EOP_SIZE);
> +
> + skb_unlink(skb, q);
> +
> + entry = (struct skb_data *)skb->cb;
> + memset(entry, 0, sizeof(*entry));
> + entry->len = pkt_len;
> +
> + if (netif_msg_pktdata(ax_local)) {
> + char pfx[IFNAMSIZ + 7];
> +
> + snprintf(pfx, sizeof(pfx), "%s: ", ndev->name);
> +
> + netdev_info(ndev, "TX packet len %d, total len %d, seq %d\n",
> + pkt_len, skb->len, seq_num);
> +
> + netdev_info(ndev, "  SPI Header:\n");
> + print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
> +skb->data, 4, 0);
> +
> + netdev_info(ndev, "  TX SOP:\n");
> + print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
> +skb->data + 4, TX_OVERHEAD, 0);
> +
> + netdev_info(ndev, "  TX packet:\n");
> + print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
> +skb->data + 4 + TX_OVERHEAD,
> +skb->len - TX_EOP_SIZE - 4 - TX_OVERHEAD, 0);
> +
> + netdev_info(ndev, "  TX EOP:\n");
> + print_hex_dump(KERN_INFO, pfx, DUMP_PREFIX_OFFSET, 16, 1,
> +skb->data + skb->len - 4, 4, 0);
> + }
> +
> + return skb;
> +}
> +
> +static int ax88796c_hard_xmit(struct ax88796c_device *ax_local)
> +{
> + struct sk_buff *tx_skb;
> + struct skb_data *entry;
> +
> + WARN_ON(!mutex_is_locked(_local->spi_lock));
> +
> + tx_skb = ax88796c_tx_fixup(ax_local->ndev, _local->tx_wait_q);
> +
> + if (!tx_skb)
> + return 0;

tx_dropped++ ?

> + entry = (struct skb_data *)tx_skb->cb;
> +
> + AX_WRITE(_local->ax_spi,
> +  (TSNR_TXB_START | TSNR_PKT_CNT(1)), 

[PATCH v10 3/3] net: ax88796c: ASIX AX88796C SPI Ethernet Adapter Driver

2021-01-13 Thread Łukasz Stelmach
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=104;65;86=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 
Reviewed-by: Andrew Lunn 
---
 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 |  239 +
 drivers/net/ethernet/asix/ax88796c_ioctl.h |   26 +
 drivers/net/ethernet/asix/ax88796c_main.c  | 1103 
 drivers/net/ethernet/asix/ax88796c_main.h  |  558 ++
 drivers/net/ethernet/asix/ax88796c_spi.c   |  115 ++
 drivers/net/ethernet/asix/ax88796c_spi.h   |   69 ++
 11 files changed, 2159 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..29088970a9cc 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 
+S: Maintained
+F: Documentation/devicetree/bindings/net/asix,ax88796c.yaml
+F: drivers/net/ethernet/asix/ax88796c_*
+
 ASPEED PINCTRL DRIVERS
 M: Andrew Jeffery 
 L: linux-asp...@lists.ozlabs.org (moderated for non-subscribers)
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index de50e8b9e656..f3b218e45ea5 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -32,6 +32,7 @@ source "drivers/net/ethernet/apm/Kconfig"
 source "drivers/net/ethernet/apple/Kconfig"
 source "drivers/net/ethernet/aquantia/Kconfig"
 source "drivers/net/ethernet/arc/Kconfig"
+source "drivers/net/ethernet/asix/Kconfig"
 source "drivers/net/ethernet/atheros/Kconfig"
 source "drivers/net/ethernet/aurora/Kconfig"
 source "drivers/net/ethernet/broadcom/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index f8f38dcb5f8a..9eb368d93607 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_NET_XGENE) += apm/
 obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
 obj-$(CONFIG_NET_VENDOR_AQUANTIA) += aquantia/
 obj-$(CONFIG_NET_VENDOR_ARC) += arc/
+obj-$(CONFIG_NET_VENDOR_ASIX) += asix/
 obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
 obj-$(CONFIG_NET_VENDOR_AURORA) += aurora/
 obj-$(CONFIG_NET_VENDOR_CADENCE) += cadence/
diff --git a/drivers/net/ethernet/asix/Kconfig 
b/drivers/net/ethernet/asix/Kconfig
new file mode 100644
index ..eed02453314c
--- /dev/null
+++ b/drivers/net/ethernet/asix/Kconfig
@@ -0,0 +1,35 @@
+#
+# Asix network device configuration
+#
+
+config NET_VENDOR_ASIX
+   bool "Asix devices"
+   default y
+   help
+ If you have a network (Ethernet, non-USB, not NE2000 compatible)
+ interface based on a chip from ASIX, say Y.
+
+if NET_VENDOR_ASIX
+
+config SPI_AX88796C
+   tristate "Asix AX88796C-SPI support"
+   select PHYLIB
+   depends on SPI
+   depends on GPIOLIB
+   help
+ Say Y here if you intend to use ASIX AX88796C attached in SPI mode.
+
+config SPI_AX88796C_COMPRESSION
+   bool "SPI transfer compression"
+   default n
+   depends on SPI_AX88796C
+   help
+ Say Y here to enable SPI transfer compression. It saves up
+ to 24 dummy cycles during each transfer which may noticeably
+ speed up short transfers. This sets the default value that is
+ inherited by network interfaces during probe. It can be
+ changed at run time via spi-compression ethtool tunable.
+
+ If unsure say N.
+
+endif # NET_VENDOR_ASIX
diff --git