mbox series

[v4,0/5] AX88796C SPI Ethernet Adapter

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

Message

Łukasz Stelmach Oct. 28, 2020, 9:40 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 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 (5):
  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
  ARM: dts: exynos: Add Ethernet to Artik 5 board
  ARM: defconfig: Enable ax88796c driver

 .../bindings/net/asix,ax88796c.yaml           |   69 +
 .../devicetree/bindings/vendor-prefixes.yaml  |    2 +
 MAINTAINERS                                   |    6 +
 arch/arm/boot/dts/exynos3250-artik5-eval.dts  |   29 +
 arch/arm/configs/exynos_defconfig             |    2 +
 arch/arm/configs/multi_v7_defconfig           |    2 +
 drivers/net/ethernet/Kconfig                  |    1 +
 drivers/net/ethernet/Makefile                 |    1 +
 drivers/net/ethernet/asix/Kconfig             |   22 +
 drivers/net/ethernet/asix/Makefile            |    6 +
 drivers/net/ethernet/asix/ax88796c_ioctl.c    |  197 +++
 drivers/net/ethernet/asix/ax88796c_ioctl.h    |   26 +
 drivers/net/ethernet/asix/ax88796c_main.c     | 1144 +++++++++++++++++
 drivers/net/ethernet/asix/ax88796c_main.h     |  578 +++++++++
 drivers/net/ethernet/asix/ax88796c_spi.c      |  111 ++
 drivers/net/ethernet/asix/ax88796c_spi.h      |   69 +
 16 files changed, 2265 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

Andrew Lunn Oct. 29, 2020, 12:31 a.m. UTC | #1
> +static void
> +ax88796c_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *_p)
> +{
> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> +	u16 *p = _p;
> +	int offset, i;

You missed a reverse christmass tree fix here.

> +static int comp;
> +static int msg_enable = NETIF_MSG_PROBE |
> +			NETIF_MSG_LINK |
> +			/* NETIF_MSG_TIMER | */
> +			/* NETIF_MSG_IFDOWN | */
> +			/* NETIF_MSG_IFUP | */
> +			NETIF_MSG_RX_ERR |
> +			NETIF_MSG_TX_ERR |
> +			/* NETIF_MSG_TX_QUEUED | */
> +			/* NETIF_MSG_INTR | */
> +			/* NETIF_MSG_TX_DONE | */
> +			/* NETIF_MSG_RX_STATUS | */
> +			/* NETIF_MSG_PKTDATA | */
> +			/* NETIF_MSG_HW | */
> +			/* NETIF_MSG_WOL | */
> +			0;

You should probably delete anything which is commented out.

> +
> +static char *no_regs_list = "80018001,e1918001,8001a001,fc0d0000";
> +unsigned long ax88796c_no_regs_mask[AX88796C_REGDUMP_LEN / (sizeof(unsigned long) * 8)];
> +
> +module_param(comp, int, 0444);
> +MODULE_PARM_DESC(comp, "0=Non-Compression Mode, 1=Compression Mode");

I think you need to find a different way to configure this. How much
does compression bring you anyway?

> +module_param(msg_enable, int, 0444);
> +MODULE_PARM_DESC(msg_enable, "Message mask (see linux/netdevice.h for bitmap)");

I know a lot of drivers have msg_enable, but DaveM is generally
against module parameters. So i would remove this.


> +static void ax88796c_set_hw_multicast(struct net_device *ndev)
> +{
> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> +	u16 rx_ctl = RXCR_AB;
> +	int mc_count = netdev_mc_count(ndev);

reverse christmass tree.

> +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);
> +	struct sk_buff *skb, *tx_skb;
> +	struct tx_pkt_info *info;
> +	struct skb_data *entry;
> +	int headroom;
> +	int tailroom;
> +	u8 need_pages;
> +	u16 tol_len, pkt_len;
> +	u8 padlen, seq_num;
> +	u8 spi_len = ax_local->ax_spi.comp ? 1 : 4;

reverse christmass tree.

> +static int ax88796c_receive(struct net_device *ndev)
> +{
> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> +	struct sk_buff *skb;
> +	struct skb_data *entry;
> +	u16 w_count, pkt_len;
> +	u8 pkt_cnt;

Reverse christmass tree

> +
> +static int ax88796c_process_isr(struct ax88796c_device *ax_local)
> +{
> +	u16 isr;
> +	u8 done = 0;
> +	struct net_device *ndev = ax_local->ndev;

...

> +static irqreturn_t ax88796c_interrupt(int irq, void *dev_instance)
> +{
> +	struct net_device *ndev = dev_instance;
> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);

...

> +static int
> +ax88796c_open(struct net_device *ndev)
> +{
> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
> +	int ret;
> +	unsigned long irq_flag = IRQF_SHARED;
> +	int fc = AX_FC_NONE;

...


> +static int ax88796c_probe(struct spi_device *spi)
> +{
> +	struct net_device *ndev;
> +	struct ax88796c_device *ax_local;
> +	char phy_id[MII_BUS_ID_SIZE + 3];
> +	int ret;
> +	u16 temp;

...

The mdio/phy/ethtool code looks O.K. now. I've not really looked at
any of the frame transfer code, so i cannot comment on that.

    Andrew
Łukasz Stelmach Oct. 29, 2020, 1:09 p.m. UTC | #2
It was <2020-10-29 czw 01:31>, when Andrew Lunn wrote:
>> +static void
>> +ax88796c_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *_p)
>> +{
>> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>> +	u16 *p = _p;
>> +	int offset, i;
>
> You missed a reverse christmass tree fix here.
>

Done.

>> +static int comp;
>> +static int msg_enable = NETIF_MSG_PROBE |
>> +			NETIF_MSG_LINK |
>> +			/* NETIF_MSG_TIMER | */
>> +			/* NETIF_MSG_IFDOWN | */
>> +			/* NETIF_MSG_IFUP | */
>> +			NETIF_MSG_RX_ERR |
>> +			NETIF_MSG_TX_ERR |
>> +			/* NETIF_MSG_TX_QUEUED | */
>> +			/* NETIF_MSG_INTR | */
>> +			/* NETIF_MSG_TX_DONE | */
>> +			/* NETIF_MSG_RX_STATUS | */
>> +			/* NETIF_MSG_PKTDATA | */
>> +			/* NETIF_MSG_HW | */
>> +			/* NETIF_MSG_WOL | */
>> +			0;
>
> You should probably delete anything which is commented out.
>

Done.

>> +
>> +static char *no_regs_list = "80018001,e1918001,8001a001,fc0d0000";
>> +unsigned long ax88796c_no_regs_mask[AX88796C_REGDUMP_LEN / (sizeof(unsigned long) * 8)];
>> +
>> +module_param(comp, int, 0444);
>> +MODULE_PARM_DESC(comp, "0=Non-Compression Mode, 1=Compression Mode");
>
> I think you need to find a different way to configure this. How much
> does compression bring you anyway?
>

Anything between almost 0 for large transfers, to 50 for tiniest. ~5%
for ~500 byte transfers. Considering the chip is rather for small
devices, that won't transfer large amounts of data, I'd rather keep some
way to control it.

>> +module_param(msg_enable, int, 0444);
>> +MODULE_PARM_DESC(msg_enable, "Message mask (see linux/netdevice.h for bitmap)");
>
> I know a lot of drivers have msg_enable, but DaveM is generally
> against module parameters. So i would remove this.
>

These two parameters have something in common: no(?) other way to pass
the information at the right time. Compression might be tuned in
runtime, if there is an interface (via ethtool?) for setting custom
knobs? Ther is such interface for msg_level level but it can be used
before a device is probed and userland is running. Hence, there is no
way to control msg_level during boot. I can remove those parameters, but
I really would like to be able to control these parameter, especially
msg_level during boot. If there is any other way, do let me know.

>> +static void ax88796c_set_hw_multicast(struct net_device *ndev)
>> +{
>> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>> +	u16 rx_ctl = RXCR_AB;
>> +	int mc_count = netdev_mc_count(ndev);
>
> reverse christmass tree.
>

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);
>> +	struct sk_buff *skb, *tx_skb;
>> +	struct tx_pkt_info *info;
>> +	struct skb_data *entry;
>> +	int headroom;
>> +	int tailroom;
>> +	u8 need_pages;
>> +	u16 tol_len, pkt_len;
>> +	u8 padlen, seq_num;
>> +	u8 spi_len = ax_local->ax_spi.comp ? 1 : 4;
>
> reverse christmass tree.
>

Done.

>> +static int ax88796c_receive(struct net_device *ndev)
>> +{
>> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>> +	struct sk_buff *skb;
>> +	struct skb_data *entry;
>> +	u16 w_count, pkt_len;
>> +	u8 pkt_cnt;
>
> Reverse christmass tree
>

Done.

>> +
>> +static int ax88796c_process_isr(struct ax88796c_device *ax_local)
>> +{
>> +	u16 isr;
>> +	u8 done = 0;
>> +	struct net_device *ndev = ax_local->ndev;
>
> ...
>

Done.

>> +static irqreturn_t ax88796c_interrupt(int irq, void *dev_instance)
>> +{
>> +	struct net_device *ndev = dev_instance;
>> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>
> ...
>

Done.

>> +static int
>> +ax88796c_open(struct net_device *ndev)
>> +{
>> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>> +	int ret;
>> +	unsigned long irq_flag = IRQF_SHARED;
>> +	int fc = AX_FC_NONE;
>
> ...
>

Done.

>> +static int ax88796c_probe(struct spi_device *spi)
>> +{
>> +	struct net_device *ndev;
>> +	struct ax88796c_device *ax_local;
>> +	char phy_id[MII_BUS_ID_SIZE + 3];
>> +	int ret;
>> +	u16 temp;
>
> ...
>

Done.

> The mdio/phy/ethtool code looks O.K. now. I've not really looked at
> any of the frame transfer code, so i cannot comment on that.
>
>     Andrew
>
>

Thanks.
Marc Kleine-Budde Oct. 29, 2020, 5:27 p.m. UTC | #3
On 10/28/20 10:40 PM, Ł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.
> 
> [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          |   22 +
>  drivers/net/ethernet/asix/Makefile         |    6 +
>  drivers/net/ethernet/asix/ax88796c_ioctl.c |  197 ++++
>  drivers/net/ethernet/asix/ax88796c_ioctl.h |   26 +
>  drivers/net/ethernet/asix/ax88796c_main.c  | 1144 ++++++++++++++++++++
>  drivers/net/ethernet/asix/ax88796c_main.h  |  578 ++++++++++
>  drivers/net/ethernet/asix/ax88796c_spi.c   |  111 ++
>  drivers/net/ethernet/asix/ax88796c_spi.h   |   69 ++
>  11 files changed, 2161 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

[...]

> +enum watchdog_state {
> +	chk_link = 0,
> +	chk_cable,
> +	ax_nop,
> +};
> +
> +struct ax88796c_device {
> +	struct resource		*addr_res;   /* resources found */
> +	struct resource		*addr_req;   /* resources requested */
> +	struct resource		*irq_res;
> +
> +	struct spi_device	*spi;
> +	struct net_device	*ndev;
> +	struct net_device_stats	stats;
> +
> +	struct timer_list	watchdog;
> +	enum watchdog_state	w_state;
> +	size_t			w_ticks;

are these used?

> +
> +	struct work_struct	ax_work;
> +
> +	struct mutex		spi_lock; /* device access */
> +
> +	struct sk_buff_head	tx_wait_q;
> +
> +	struct axspi_data	ax_spi;
> +
> +	struct mii_bus		*mdiobus;
> +	struct phy_device	*phydev;
> +
> +	int			msg_enable;
> +
> +	u16			seq_num;
> +
> +	u8			multi_filter[AX_MCAST_FILTER_SIZE];
> +
> +	int			link;
> +	int			speed;
> +	int			duplex;
> +	int			pause;
> +	int			asym_pause;
> +	int			flowctrl;
> +		#define AX_FC_NONE		0
> +		#define AX_FC_RX		BIT(0)
> +		#define AX_FC_TX		BIT(1)
> +		#define AX_FC_ANEG		BIT(2)
> +
> +	unsigned long		capabilities;
> +		#define AX_CAP_DMA		BIT(0)
> +		#define AX_CAP_COMP		BIT(1)
> +		#define AX_CAP_BIDIR		BIT(2)
> +
> +	u8			plat_endian;
> +		#define PLAT_LITTLE_ENDIAN	0
> +		#define PLAT_BIG_ENDIAN		1
> +
> +	unsigned long		flags;
> +		#define EVENT_INTR		BIT(0)
> +		#define EVENT_TX		BIT(1)
> +		#define EVENT_SET_MULTI		BIT(2)
> +
> +};
> +
> +#define to_ax88796c_device(ndev) ((struct ax88796c_device *)netdev_priv(ndev))
> +
> +enum skb_state {
> +	illegal = 0,
> +	tx_done,
> +	rx_done,
> +	rx_err,
> +};
> +
> +struct skb_data {
> +	enum skb_state state;
> +	struct net_device *ndev;
> +	struct sk_buff *skb;
> +	size_t len;
> +	dma_addr_t phy_addr;

unused?

[...]

> diff --git a/drivers/net/ethernet/asix/ax88796c_spi.c b/drivers/net/ethernet/asix/ax88796c_spi.c
> new file mode 100644
> index 000000000000..1a20bbeb4dc1
> --- /dev/null
> +++ b/drivers/net/ethernet/asix/ax88796c_spi.c
> @@ -0,0 +1,111 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2010 ASIX Electronics Corporation
> + * Copyright (c) 2020 Samsung Electronics Co., Ltd.
> + *
> + * ASIX AX88796C SPI Fast Ethernet Linux driver
> + */
> +
> +#define pr_fmt(fmt)	"ax88796c: " fmt
> +
> +#include <linux/string.h>
> +#include <linux/spi/spi.h>
> +
> +#include "ax88796c_spi.h"
> +
> +/* driver bus management functions */
> +int axspi_wakeup(const struct axspi_data *ax_spi)
> +{
> +	u8 tx_buf;
> +	int ret;
> +
> +	tx_buf = AX_SPICMD_EXIT_PWD;	/* OP */
> +	ret = spi_write(ax_spi->spi, &tx_buf, 1);

spi_write() needs a DMA safe buffer.

> +	if (ret)
> +		dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
> +	return ret;
> +}
> +
> +int axspi_read_status(const struct axspi_data *ax_spi, struct spi_status *status)
> +{
> +	u8 tx_buf;
> +	int ret;
> +
> +	/* OP */
> +	tx_buf = AX_SPICMD_READ_STATUS;
> +	ret = spi_write_then_read(ax_spi->spi, &tx_buf, 1, (u8 *)&status, 3);
> +	if (ret)
> +		dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
> +	else
> +		le16_to_cpus(&status->isr);
> +
> +	return ret;
> +}
> +
> +int axspi_read_rxq(struct axspi_data *ax_spi, void *data, int len)
> +{
> +	struct spi_transfer *xfer = ax_spi->spi_rx_xfer;
> +	int ret;
> +
> +	memcpy(ax_spi->cmd_buf, rx_cmd_buf, 5);
> +
> +	xfer->tx_buf = ax_spi->cmd_buf;
> +	xfer->rx_buf = NULL;
> +	xfer->len = ax_spi->comp ? 2 : 5;
> +	xfer->bits_per_word = 8;
> +	spi_message_add_tail(xfer, &ax_spi->rx_msg);
> +
> +	xfer++;
> +	xfer->rx_buf = data;
> +	xfer->tx_buf = NULL;
> +	xfer->len = len;
> +	xfer->bits_per_word = 8;
> +	spi_message_add_tail(xfer, &ax_spi->rx_msg);
> +	ret = spi_sync(ax_spi->spi, &ax_spi->rx_msg);
> +	if (ret)
> +		dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
> +
> +	return ret;
> +}
> +
> +int axspi_write_txq(const struct axspi_data *ax_spi, void *data, int len)
> +{
> +	return spi_write(ax_spi->spi, data, len);
> +}
> +
> +u16 axspi_read_reg(const struct axspi_data *ax_spi, u8 reg)
> +{
> +	u8 tx_buf[4];
> +	u16 rx_buf = 0;
> +	int ret;
> +	int len = ax_spi->comp ? 3 : 4;
> +
> +	tx_buf[0] = 0x03;	/* OP code read register */
> +	tx_buf[1] = reg;	/* register address */
> +	tx_buf[2] = 0xFF;	/* dumy cycle */
> +	tx_buf[3] = 0xFF;	/* dumy cycle */
> +	ret = spi_write_then_read(ax_spi->spi, tx_buf, len, (u8 *)&rx_buf, 2);
> +	if (ret)
> +		dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
> +	else
> +		le16_to_cpus(&rx_buf);
> +
> +	return rx_buf;
> +}
> +
> +int axspi_write_reg(const struct axspi_data *ax_spi, u8 reg, u16 value)
> +{
> +	u8 tx_buf[4];
> +	int ret;
> +
> +	tx_buf[0] = AX_SPICMD_WRITE_REG;	/* OP code read register */
> +	tx_buf[1] = reg;			/* register address */
> +	tx_buf[2] = value;
> +	tx_buf[3] = value >> 8;
> +
> +	ret = spi_write(ax_spi->spi, tx_buf, 4);

I think you need DMA safe mem for spi_write().

Marc
Łukasz Stelmach Oct. 29, 2020, 8:31 p.m. UTC | #4
It was <2020-10-29 czw 01:31>, when Andrew Lunn wrote:
>
> Reverse christmass tree
>
>> +
>> +static int ax88796c_process_isr(struct ax88796c_device *ax_local)
>> +{
>> +	u16 isr;
>> +	u8 done = 0;
>> +	struct net_device *ndev = ax_local->ndev;
>
> ...
>
>> +static irqreturn_t ax88796c_interrupt(int irq, void *dev_instance)
>> +{
>> +	struct net_device *ndev = dev_instance;
>> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
>
> ...
>

Doesn't work here - dependency. What next?
Andrew Lunn Oct. 29, 2020, 9:06 p.m. UTC | #5
> >> +static irqreturn_t ax88796c_interrupt(int irq, void *dev_instance)
> >> +{
> >> +	struct net_device *ndev = dev_instance;
> >> +	struct ax88796c_device *ax_local = to_ax88796c_device(ndev);

Do the assignment later.

   Andrew
Łukasz Stelmach Oct. 29, 2020, 11:01 p.m. UTC | #6
It was <2020-10-29 czw 18:27>, when Marc Kleine-Budde wrote:
> On 10/28/20 10:40 PM, Ł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.
>> 
>> [1]
>> https://protect2.fireeye.com/v1/url?k=9aaa9891-c7611faf-9aab13de-0cc47a31309a-7f8f6d6347765df4&q=1&e=78d1d40c-ff31-47e7-91fd-0c29963c1913&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=407e4fb6-1db5c888-407fc4f9-0cc47a31309a-aaf46a5c37be27ea&q=1&e=78d1d40c-ff31-47e7-91fd-0c29963c1913&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          |   22 +
>>  drivers/net/ethernet/asix/Makefile         |    6 +
>>  drivers/net/ethernet/asix/ax88796c_ioctl.c |  197 ++++
>>  drivers/net/ethernet/asix/ax88796c_ioctl.h |   26 +
>>  drivers/net/ethernet/asix/ax88796c_main.c  | 1144 ++++++++++++++++++++
>>  drivers/net/ethernet/asix/ax88796c_main.h  |  578 ++++++++++
>>  drivers/net/ethernet/asix/ax88796c_spi.c   |  111 ++
>>  drivers/net/ethernet/asix/ax88796c_spi.h   |   69 ++
>>  11 files changed, 2161 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
>
> [...]
>
>> +enum watchdog_state {
>> +	chk_link = 0,
>> +	chk_cable,
>> +	ax_nop,
>> +};
>> +
>> +struct ax88796c_device {
>> +	struct resource		*addr_res;   /* resources found */
>> +	struct resource		*addr_req;   /* resources requested */
>> +	struct resource		*irq_res;
>> +
>> +	struct spi_device	*spi;
>> +	struct net_device	*ndev;
>> +	struct net_device_stats	stats;
>> +
>> +	struct timer_list	watchdog;
>> +	enum watchdog_state	w_state;
>> +	size_t			w_ticks;
>
> are these used?
>

Nope. Removed. Thanks.

>> +
>> +	struct work_struct	ax_work;
>> +
>> +	struct mutex		spi_lock; /* device access */
>> +
>> +	struct sk_buff_head	tx_wait_q;
>> +
>> +	struct axspi_data	ax_spi;
>> +
>> +	struct mii_bus		*mdiobus;
>> +	struct phy_device	*phydev;
>> +
>> +	int			msg_enable;
>> +
>> +	u16			seq_num;
>> +
>> +	u8			multi_filter[AX_MCAST_FILTER_SIZE];
>> +
>> +	int			link;
>> +	int			speed;
>> +	int			duplex;
>> +	int			pause;
>> +	int			asym_pause;
>> +	int			flowctrl;
>> +		#define AX_FC_NONE		0
>> +		#define AX_FC_RX		BIT(0)
>> +		#define AX_FC_TX		BIT(1)
>> +		#define AX_FC_ANEG		BIT(2)
>> +
>> +	unsigned long		capabilities;
>> +		#define AX_CAP_DMA		BIT(0)
>> +		#define AX_CAP_COMP		BIT(1)
>> +		#define AX_CAP_BIDIR		BIT(2)
>> +
>> +	u8			plat_endian;
>> +		#define PLAT_LITTLE_ENDIAN	0
>> +		#define PLAT_BIG_ENDIAN		1
>> +
>> +	unsigned long		flags;
>> +		#define EVENT_INTR		BIT(0)
>> +		#define EVENT_TX		BIT(1)
>> +		#define EVENT_SET_MULTI		BIT(2)
>> +
>> +};
>> +
>> +#define to_ax88796c_device(ndev) ((struct ax88796c_device *)netdev_priv(ndev))
>> +
>> +enum skb_state {
>> +	illegal = 0,
>> +	tx_done,
>> +	rx_done,
>> +	rx_err,
>> +};
>> +
>> +struct skb_data {
>> +	enum skb_state state;
>> +	struct net_device *ndev;
>> +	struct sk_buff *skb;
>> +	size_t len;
>> +	dma_addr_t phy_addr;
>
> unused?
>
> [...]
>

Ditto.

>> diff --git a/drivers/net/ethernet/asix/ax88796c_spi.c b/drivers/net/ethernet/asix/ax88796c_spi.c
>> new file mode 100644
>> index 000000000000..1a20bbeb4dc1
>> --- /dev/null
>> +++ b/drivers/net/ethernet/asix/ax88796c_spi.c
>> @@ -0,0 +1,111 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2010 ASIX Electronics Corporation
>> + * Copyright (c) 2020 Samsung Electronics Co., Ltd.
>> + *
>> + * ASIX AX88796C SPI Fast Ethernet Linux driver
>> + */
>> +
>> +#define pr_fmt(fmt)	"ax88796c: " fmt
>> +
>> +#include <linux/string.h>
>> +#include <linux/spi/spi.h>
>> +
>> +#include "ax88796c_spi.h"
>> +
>> +/* driver bus management functions */
>> +int axspi_wakeup(const struct axspi_data *ax_spi)
>> +{
>> +	u8 tx_buf;
>> +	int ret;
>> +
>> +	tx_buf = AX_SPICMD_EXIT_PWD;	/* OP */
>> +	ret = spi_write(ax_spi->spi, &tx_buf, 1);
>
> spi_write() needs a DMA safe buffer.
>

Done.

>> +	if (ret)
>> +		dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
>> +	return ret;
>> +}
>> +
>> +int axspi_read_status(const struct axspi_data *ax_spi, struct spi_status *status)
>> +{
>> +	u8 tx_buf;
>> +	int ret;
>> +
>> +	/* OP */
>> +	tx_buf = AX_SPICMD_READ_STATUS;
>> +	ret = spi_write_then_read(ax_spi->spi, &tx_buf, 1, (u8 *)&status, 3);
>> +	if (ret)
>> +		dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
>> +	else
>> +		le16_to_cpus(&status->isr);
>> +
>> +	return ret;
>> +}
>> +
>> +int axspi_read_rxq(struct axspi_data *ax_spi, void *data, int len)
>> +{
>> +	struct spi_transfer *xfer = ax_spi->spi_rx_xfer;
>> +	int ret;
>> +
>> +	memcpy(ax_spi->cmd_buf, rx_cmd_buf, 5);
>> +
>> +	xfer->tx_buf = ax_spi->cmd_buf;
>> +	xfer->rx_buf = NULL;
>> +	xfer->len = ax_spi->comp ? 2 : 5;
>> +	xfer->bits_per_word = 8;
>> +	spi_message_add_tail(xfer, &ax_spi->rx_msg);
>> +
>> +	xfer++;
>> +	xfer->rx_buf = data;
>> +	xfer->tx_buf = NULL;
>> +	xfer->len = len;
>> +	xfer->bits_per_word = 8;
>> +	spi_message_add_tail(xfer, &ax_spi->rx_msg);
>> +	ret = spi_sync(ax_spi->spi, &ax_spi->rx_msg);
>> +	if (ret)
>> +		dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
>> +
>> +	return ret;
>> +}
>> +
>> +int axspi_write_txq(const struct axspi_data *ax_spi, void *data, int len)
>> +{
>> +	return spi_write(ax_spi->spi, data, len);
>> +}
>> +
>> +u16 axspi_read_reg(const struct axspi_data *ax_spi, u8 reg)
>> +{
>> +	u8 tx_buf[4];
>> +	u16 rx_buf = 0;
>> +	int ret;
>> +	int len = ax_spi->comp ? 3 : 4;
>> +
>> +	tx_buf[0] = 0x03;	/* OP code read register */
>> +	tx_buf[1] = reg;	/* register address */
>> +	tx_buf[2] = 0xFF;	/* dumy cycle */
>> +	tx_buf[3] = 0xFF;	/* dumy cycle */
>> +	ret = spi_write_then_read(ax_spi->spi, tx_buf, len, (u8 *)&rx_buf, 2);
>> +	if (ret)
>> +		dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
>> +	else
>> +		le16_to_cpus(&rx_buf);
>> +
>> +	return rx_buf;
>> +}
>> +
>> +int axspi_write_reg(const struct axspi_data *ax_spi, u8 reg, u16 value)
>> +{
>> +	u8 tx_buf[4];
>> +	int ret;
>> +
>> +	tx_buf[0] = AX_SPICMD_WRITE_REG;	/* OP code read register */
>> +	tx_buf[1] = reg;			/* register address */
>> +	tx_buf[2] = value;
>> +	tx_buf[3] = value >> 8;
>> +
>> +	ret = spi_write(ax_spi->spi, tx_buf, 4);
>
> I think you need DMA safe mem for spi_write().

"Moved" the bufferers to axspi_data struct.

Thank you.