Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions doc/hal.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
What the heck? An Atheros HAL? Here?
====================================

The aim of this work is to migrate the driver away from a very Linux-centric
take on things and more towards something that can be easily leveraged
on multiple platforms.

This was one of the HAL design goals back for the Wireless device support.
Yes, another goal was _binary_ interface and object sharing - we don't
have to worry about this. We are doing well if we're able to compile
and use shared parts of the driver across multiple platforms.

At a very top level, the ethernet driver has a very small set of
interfaces to the kernel:

* probe/attach;
* suspend/resume (if required);
* interrupt registration and callback, ithread, or appropriate;
* a datapath (TX and RX);
* a control path (up/down, ioctl(), etc);
* some statistics path (eg ethtool statistics).

Each of these modules have both machine dependent and independent parts.

The aim of this "HAL-ification" of alx is to isolate out the hardware
interface stuff into separate files and make those files compilable
on multiple platforms. To that end, there are a few "requirements" for
portable driver code. This list isn't exhaustive and will grow/change
over time:

* The types being used by those shared routines must be generic and
not assume a specific compiler or environment. Notably, 'bool',
'u8/u16/u32' can't be used;

* Care must be taken when assuming packed structures - as different
compilers allow for different kinds of packing;

* Same deal with inlining things;

* You -must not assume- that atomics and locking primitives are
available in the hardware code. Anything that requires synchronisation
or ordering must be done by the upper layer driver and OS dependent
code;

* You can't use OS specific defines, typedefs, etc in the code.
This does mean that you may end up defining HAL_ typedefs and
enums for things that exist in UNIX, then write functions which
simply map the OS type to the HAL_ type.

In addition, some non-HAL code may be shared. For example, code
which maintains the TX and RX descriptor arrays. Here, we may
wish to use locks, atomics and other primitives. However we can't
assume that we can use those primitives across multiple operating
systems - each OS has a set of what's allowed and what's not allowed.
For example, Windows/MacOSX doesn't allow locks in the interrupt path
whereas Linux/FreeBSD interrupt threads allow locks.

For now, this work will just focus on separating out the hardware code
enough to get the device to probe/attach. Once that's done, the rest
of the driver can be broken up into pieces that make sense to share
across operating systems, with whatever the relevant caveats are.
139 changes: 56 additions & 83 deletions src/alx.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef _ALX_H_
#define _ALX_H_

#if 0
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
Expand All @@ -29,6 +30,8 @@
#include <linux/ethtool.h>
#include <linux/crc32.h>
#include <linux/mdio.h>
#endif

#include "alx_hw.h"

/* specific error info */
Expand Down Expand Up @@ -444,8 +447,8 @@ struct alx_hw_stats {
*/
struct alx_ring_header {
void *desc; /* virt addr */
dma_addr_t dma; /* phy addr */
u32 size; /* length in bytes */
A_DMA_ADDR dma; /* phy addr */
A_UINT32 size; /* length in bytes */
};

/*
Expand All @@ -456,7 +459,7 @@ struct alx_buffer {
struct sk_buff *skb; /* socket buffer */
DEFINE_DMA_UNMAP_ADDR(dma); /* DMA address */
DEFINE_DMA_UNMAP_LEN(size); /* buffer size */
u16 flags; /* information of this buffer */
A_UINT16 flags; /* information of this buffer */
};
#define ALX_BUF_TX_FIRSTFRAG 0x1

Expand All @@ -465,18 +468,18 @@ struct alx_rx_queue {
struct net_device *netdev;
struct device *dev; /* device pointer for dma operation */
struct rrd_desc *rrd_hdr; /* rrd ring virtual addr */
dma_addr_t rrd_dma; /* rrd ring physical addr */
A_DMA_ADDR rrd_dma; /* rrd ring physical addr */
struct rfd_desc *rfd_hdr; /* rfd ring virtual addr */
dma_addr_t rfd_dma; /* rfd ring physical addr */
A_DMA_ADDR rfd_dma; /* rfd ring physical addr */
struct alx_buffer *bf_info; /* info for rx-skbs */

u16 count; /* number of ring elements */
u16 pidx; /* rfd producer index */
u16 cidx; /* rfd consumer index */
u16 rrd_cidx;
u16 p_reg; /* register saving producer index */
u16 c_reg; /* register saving consumer index */
u16 qidx; /* queue index */
A_UINT16 count; /* number of ring elements */
A_UINT16 pidx; /* rfd producer index */
A_UINT16 cidx; /* rfd consumer index */
A_UINT16 rrd_cidx;
A_UINT16 p_reg; /* register saving producer index */
A_UINT16 c_reg; /* register saving consumer index */
A_UINT16 qidx; /* queue index */
unsigned long flag;

struct sk_buff_head list;
Expand All @@ -488,14 +491,14 @@ struct alx_tx_queue {
struct net_device *netdev;
struct device *dev; /* device pointer for dma operation */
struct tpd_desc *tpd_hdr; /* tpd ring virtual addr */
dma_addr_t tpd_dma; /* tpd ring physical addr */
A_DMA_ADDR tpd_dma; /* tpd ring physical addr */
struct alx_buffer *bf_info; /* info for tx-skbs pending on HW */
u16 count; /* number of ring elements */
u16 pidx; /* producer index */
atomic_t cidx; /* consumer index */
u16 p_reg; /* register saving producer index */
u16 c_reg; /* register saving consumer index */
u16 qidx; /* queue index */
A_UINT16 count; /* number of ring elements */
A_UINT16 pidx; /* producer index */
A_ATOMIC cidx; /* consumer index */
A_UINT16 p_reg; /* register saving producer index */
A_UINT16 c_reg; /* register saving consumer index */
A_UINT16 qidx; /* queue index */
};

#define ALX_TX_WAKEUP_THRESH(_tq) ((_tq)->count / 4)
Expand All @@ -507,7 +510,7 @@ struct alx_napi {
struct alx_rx_queue *rxq;
struct alx_tx_queue *txq;
int vec_idx;
u32 vec_mask;
A_UINT32 vec_mask;
char irq_lbl[IFNAMSIZ];
};

Expand Down Expand Up @@ -540,15 +543,15 @@ enum ALX_FLAGS {
*board specific private data structure
*/
struct alx_adapter {
u8 __iomem *hw_addr; /* memory mapped PCI base address */
A_UINT8 __iomem *hw_addr; /* memory mapped PCI base address */

u8 mac_addr[ETH_ALEN]; /* current mac address */
u8 perm_addr[ETH_ALEN]; /* permanent mac address */
A_UINT8 mac_addr[ETH_ALEN]; /* current mac address */
A_UINT8 perm_addr[ETH_ALEN]; /* permanent mac address */

struct net_device *netdev;
struct pci_dev *pdev;

u16 bd_number; /* board number;*/
A_UINT16 bd_number; /* board number;*/

unsigned int nr_vec; /* totally msix vectors */
struct msix_entry *msix_ent; /* msix entries */
Expand All @@ -563,53 +566,53 @@ struct alx_adapter {
int nr_txq; /* number of napi for TX-Q */
int nr_rxq; /* number of napi for RX-Q */
int nr_napi; /* total napi for TX-Q/RX-Q */
u16 mtu; /* MTU */
u16 imt; /* interrupt moderation timer */
u8 dma_chnl; /* number of DMA channels */
u8 max_dma_chnl;
u32 rx_ctrl; /* main rx control */
u32 mc_hash[2]; /* multicast addr hash table */

u8 rss_key[40]; /* RSS hash algorithm key */
u32 rss_idt[32]; /* RSS indirection table */
u16 rss_idt_size; /* RSS indirection table size */
u8 rss_hash_type; /* RSS hash type */

u32 wrr[ALX_MAX_TX_QUEUES]; /* weight round robin
A_UINT16 mtu; /* MTU */
A_UINT16 imt; /* interrupt moderation timer */
A_UINT8 dma_chnl; /* number of DMA channels */
A_UINT8 max_dma_chnl;
A_UINT32 rx_ctrl; /* main rx control */
A_UINT32 mc_hash[2]; /* multicast addr hash table */

A_UINT8 rss_key[40]; /* RSS hash algorithm key */
A_UINT32 rss_idt[32]; /* RSS indirection table */
A_UINT16 rss_idt_size; /* RSS indirection table size */
A_UINT8 rss_hash_type; /* RSS hash type */

A_UINT32 wrr[ALX_MAX_TX_QUEUES]; /* weight round robin
* for multiple-tx-Q */
u32 wrr_ctrl; /* prioirty control */
A_UINT32 wrr_ctrl; /* prioirty control */

u32 imask; /* interrupt mask for ALX_IMR */
u32 smb_timer; /* statistic counts refresh
A_UINT32 imask; /* interrupt mask for ALX_IMR */
A_UINT32 smb_timer; /* statistic counts refresh
* timeout, million-seconds */
spinlock_t smb_lock; /* lock for updating stats */
A_SPINLOCK smb_lock; /* lock for updating stats */

bool link_up; /* link up flag */
u16 link_speed; /* current link speed */
u8 link_duplex; /* current link duplex */
HAL_BOOL link_up; /* link up flag */
A_UINT16 link_speed; /* current link speed */
A_UINT8 link_duplex; /* current link duplex */

u32 adv_cfg; /* auto-neg advertisement
A_UINT32 adv_cfg; /* auto-neg advertisement
* or force mode config
*/
u8 flowctrl; /* flow control */
A_UINT8 flowctrl; /* flow control */

struct work_struct task; /* any delayed work */
struct net_device_stats net_stats; /* statistics counters */
struct alx_hw_stats hw_stats; /* statistics counters,
* same order with hw
*/
u32 sleep_ctrl; /* control used when sleep */
atomic_t irq_sem; /* interrupt sync */
u16 msg_enable; /* msg level */
A_UINT32 sleep_ctrl; /* control used when sleep */
A_ATOMIC irq_sem; /* interrupt sync */
A_UINT16 msg_enable; /* msg level */

DECLARE_BITMAP(flags, ALX_FLAG_NUMBER_OF_FLAGS);

spinlock_t mdio_lock; /* used for MII bus access */
A_SPINLOCK mdio_lock; /* used for MII bus access */
struct mdio_if_info mdio;
u16 phy_id[2];
A_UINT16 phy_id[2];

bool lnk_patch; /* PHY link patch flag */
bool hib_patch; /* PHY hibernation patch flag */
HAL_BOOL lnk_patch; /* PHY link patch flag */
HAL_BOOL hib_patch; /* PHY hibernation patch flag */
};

#define ALX_VID(_a) ((_a)->pdev->vendor)
Expand All @@ -626,36 +629,6 @@ struct alx_adapter {
#define ALX_FLAG_CLEAR(_adpt, _FLAG) (\
clear_bit(ALX_FLAG_##_FLAG, (_adpt)->flags))


/* write to 8bit register via pci memory space */
#define ALX_MEM_W8(s, reg, val) (writeb((val), ((s)->hw_addr + reg)))

/* read from 8bit register via pci memory space */
#define ALX_MEM_R8(s, reg, pdat) (\
*(u8 *)(pdat) = readb((s)->hw_addr + reg))

/* write to 16bit register via pci memory space */
#define ALX_MEM_W16(s, reg, val) (writew((val), ((s)->hw_addr + reg)))

/* read from 16bit register via pci memory space */
#define ALX_MEM_R16(s, reg, pdat) (\
*(u16 *)(pdat) = readw((s)->hw_addr + reg))

/* write to 32bit register via pci memory space */
#define ALX_MEM_W32(s, reg, val) (writel((val), ((s)->hw_addr + reg)))

/* read from 32bit register via pci memory space */
#define ALX_MEM_R32(s, reg, pdat) (\
*(u32 *)(pdat) = readl((s)->hw_addr + reg))

/* read from 16bit register via pci config space */
#define ALX_CFG_R16(s, reg, pdat) (\
pci_read_config_word((s)->pdev, (reg), (pdat)))

/* write to 16bit register via pci config space */
#define ALX_CFG_W16(s, reg, val) (\
pci_write_config_word((s)->pdev, (reg), (val)))

/* flush regs */
#define ALX_MEM_FLUSH(s) (readl((s)->hw_addr))

Expand Down
22 changes: 12 additions & 10 deletions src/alx_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include <linux/pci.h>
#include <linux/ethtool.h>

#include "ah_osdep.h"

#include "alx.h"

static int alx_get_settings(struct net_device *netdev,
Expand Down Expand Up @@ -58,7 +60,7 @@ static int alx_set_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
{
struct alx_adapter *adpt = netdev_priv(netdev);
u32 adv_cfg;
A_UINT32 adv_cfg;
int err = 0;

while (test_and_set_bit(ALX_FLAG_RESETING, adpt->flags))
Expand Down Expand Up @@ -137,8 +139,8 @@ static int alx_set_pauseparam(struct net_device *netdev,
{
struct alx_adapter *adpt = netdev_priv(netdev);
int err = 0;
bool reconfig_phy = false;
u8 fc = 0;
HAL_BOOL reconfig_phy = AH_FALSE;
A_UINT8 fc = 0;

if (pause->tx_pause)
fc |= ALX_FC_TX;
Expand All @@ -153,10 +155,10 @@ static int alx_set_pauseparam(struct net_device *netdev,
/* restart auto-neg for auto-mode */
if (adpt->adv_cfg & ADVERTISED_Autoneg) {
if (!((fc ^ adpt->flowctrl) & ALX_FC_ANEG))
reconfig_phy = true; /* auto/force change */
reconfig_phy = AH_RUE; /* auto/force change */
if (fc & adpt->flowctrl & ALX_FC_ANEG &&
(fc ^ adpt->flowctrl) & (ALX_FC_RX | ALX_FC_TX))
reconfig_phy = true;
reconfig_phy = AH_TRUE;
}

if (reconfig_phy) {
Expand All @@ -180,21 +182,21 @@ static int alx_set_pauseparam(struct net_device *netdev,
return err;
}

static u32 alx_get_msglevel(struct net_device *netdev)
static A_UINT32 alx_get_msglevel(struct net_device *netdev)
{
struct alx_adapter *adpt = netdev_priv(netdev);

return adpt->msg_enable;
}

static void alx_set_msglevel(struct net_device *netdev, u32 data)
static void alx_set_msglevel(struct net_device *netdev, A_UINT32 data)
{
struct alx_adapter *adpt = netdev_priv(netdev);

adpt->msg_enable = data;
}

static const u32 hw_regs[] = {
static const A_UINT32 hw_regs[] = {
ALX_DEV_CAP, ALX_DEV_CTRL, ALX_LNK_CAP, ALX_LNK_CTRL,
ALX_UE_SVRT, ALX_EFLD, ALX_SLD, ALX_PPHY_MISC1,
ALX_PPHY_MISC2, ALX_PDLL_TRNS1,
Expand Down Expand Up @@ -237,7 +239,7 @@ static void alx_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *buff)
{
struct alx_adapter *adpt = netdev_priv(netdev);
u32 *p = buff;
A_UINT32 *p = buff;
int i;

regs->version = (ALX_DID(adpt) << 16) | (ALX_REVID(adpt) << 8) | 1;
Expand All @@ -248,7 +250,7 @@ static void alx_get_regs(struct net_device *netdev,
ALX_MEM_R32(adpt, hw_regs[i], p);

/* last one for PHY Link Status */
alx_read_phy_reg(adpt, MII_BMSR, (u16 *)p);
alx_read_phy_reg(adpt, MII_BMSR, (A_UINT16 *)p);
}

static void alx_get_drvinfo(struct net_device *netdev,
Expand Down
Loading