Commit cac1c52c authored by Ayaz Abdulla's avatar Ayaz Abdulla Committed by David S. Miller

forcedeth: mgmt unit interface

This patch updates the logic used to communicate with the mgmt unit. It
also adds a version check for a newer mgmt unit firmware.

* Fixed udelay to schedule_timeout_uninterruptible
Signed-off-by: default avatarAyaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1f0fa154
...@@ -157,6 +157,9 @@ enum { ...@@ -157,6 +157,9 @@ enum {
#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000 #define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000
#define NVREG_XMITCTL_HOST_LOADED 0x00004000 #define NVREG_XMITCTL_HOST_LOADED 0x00004000
#define NVREG_XMITCTL_TX_PATH_EN 0x01000000 #define NVREG_XMITCTL_TX_PATH_EN 0x01000000
#define NVREG_XMITCTL_DATA_START 0x00100000
#define NVREG_XMITCTL_DATA_READY 0x00010000
#define NVREG_XMITCTL_DATA_ERROR 0x00020000
NvRegTransmitterStatus = 0x088, NvRegTransmitterStatus = 0x088,
#define NVREG_XMITSTAT_BUSY 0x01 #define NVREG_XMITSTAT_BUSY 0x01
...@@ -289,8 +292,10 @@ enum { ...@@ -289,8 +292,10 @@ enum {
#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04 #define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04
#define NVREG_WAKEUPFLAGS_ENABLE 0x1111 #define NVREG_WAKEUPFLAGS_ENABLE 0x1111
NvRegPatternCRC = 0x204, NvRegMgmtUnitGetVersion = 0x204,
NvRegPatternMask = 0x208, #define NVREG_MGMTUNITGETVERSION 0x01
NvRegMgmtUnitVersion = 0x208,
#define NVREG_MGMTUNITVERSION 0x08
NvRegPowerCap = 0x268, NvRegPowerCap = 0x268,
#define NVREG_POWERCAP_D3SUPP (1<<30) #define NVREG_POWERCAP_D3SUPP (1<<30)
#define NVREG_POWERCAP_D2SUPP (1<<26) #define NVREG_POWERCAP_D2SUPP (1<<26)
...@@ -303,6 +308,8 @@ enum { ...@@ -303,6 +308,8 @@ enum {
#define NVREG_POWERSTATE_D1 0x0001 #define NVREG_POWERSTATE_D1 0x0001
#define NVREG_POWERSTATE_D2 0x0002 #define NVREG_POWERSTATE_D2 0x0002
#define NVREG_POWERSTATE_D3 0x0003 #define NVREG_POWERSTATE_D3 0x0003
NvRegMgmtUnitControl = 0x278,
#define NVREG_MGMTUNITCONTROL_INUSE 0x20000
NvRegTxCnt = 0x280, NvRegTxCnt = 0x280,
NvRegTxZeroReXmt = 0x284, NvRegTxZeroReXmt = 0x284,
NvRegTxOneReXmt = 0x288, NvRegTxOneReXmt = 0x288,
...@@ -758,6 +765,8 @@ struct fe_priv { ...@@ -758,6 +765,8 @@ struct fe_priv {
u32 register_size; u32 register_size;
int rx_csum; int rx_csum;
u32 mac_in_use; u32 mac_in_use;
int mgmt_version;
int mgmt_sema;
void __iomem *base; void __iomem *base;
...@@ -5182,6 +5191,7 @@ static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) ...@@ -5182,6 +5191,7 @@ static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
/* The mgmt unit and driver use a semaphore to access the phy during init */ /* The mgmt unit and driver use a semaphore to access the phy during init */
static int nv_mgmt_acquire_sema(struct net_device *dev) static int nv_mgmt_acquire_sema(struct net_device *dev)
{ {
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev); u8 __iomem *base = get_hwbase(dev);
int i; int i;
u32 tx_ctrl, mgmt_sema; u32 tx_ctrl, mgmt_sema;
...@@ -5204,8 +5214,10 @@ static int nv_mgmt_acquire_sema(struct net_device *dev) ...@@ -5204,8 +5214,10 @@ static int nv_mgmt_acquire_sema(struct net_device *dev)
/* verify that semaphore was acquired */ /* verify that semaphore was acquired */
tx_ctrl = readl(base + NvRegTransmitterControl); tx_ctrl = readl(base + NvRegTransmitterControl);
if (((tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK) == NVREG_XMITCTL_HOST_SEMA_ACQ) && if (((tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK) == NVREG_XMITCTL_HOST_SEMA_ACQ) &&
((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) ((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) {
np->mgmt_sema = 1;
return 1; return 1;
}
else else
udelay(50); udelay(50);
} }
...@@ -5213,6 +5225,51 @@ static int nv_mgmt_acquire_sema(struct net_device *dev) ...@@ -5213,6 +5225,51 @@ static int nv_mgmt_acquire_sema(struct net_device *dev)
return 0; return 0;
} }
static void nv_mgmt_release_sema(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 tx_ctrl;
if (np->driver_data & DEV_HAS_MGMT_UNIT) {
if (np->mgmt_sema) {
tx_ctrl = readl(base + NvRegTransmitterControl);
tx_ctrl &= ~NVREG_XMITCTL_HOST_SEMA_ACQ;
writel(tx_ctrl, base + NvRegTransmitterControl);
}
}
}
static int nv_mgmt_get_version(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base = get_hwbase(dev);
u32 data_ready = readl(base + NvRegTransmitterControl);
u32 data_ready2 = 0;
unsigned long start;
int ready = 0;
writel(NVREG_MGMTUNITGETVERSION, base + NvRegMgmtUnitGetVersion);
writel(data_ready ^ NVREG_XMITCTL_DATA_START, base + NvRegTransmitterControl);
start = jiffies;
while (time_before(jiffies, start + 5*HZ)) {
data_ready2 = readl(base + NvRegTransmitterControl);
if ((data_ready & NVREG_XMITCTL_DATA_READY) != (data_ready2 & NVREG_XMITCTL_DATA_READY)) {
ready = 1;
break;
}
schedule_timeout_uninterruptible(1);
}
if (!ready || (data_ready2 & NVREG_XMITCTL_DATA_ERROR))
return 0;
np->mgmt_version = readl(base + NvRegMgmtUnitVersion) & NVREG_MGMTUNITVERSION;
return 1;
}
static int nv_open(struct net_device *dev) static int nv_open(struct net_device *dev)
{ {
struct fe_priv *np = netdev_priv(dev); struct fe_priv *np = netdev_priv(dev);
...@@ -5784,19 +5841,26 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -5784,19 +5841,26 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (id->driver_data & DEV_HAS_MGMT_UNIT) { if (id->driver_data & DEV_HAS_MGMT_UNIT) {
/* management unit running on the mac? */ /* management unit running on the mac? */
if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) { if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST) &&
np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST; (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) &&
dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use); nv_mgmt_acquire_sema(dev) &&
if (nv_mgmt_acquire_sema(dev)) { nv_mgmt_get_version(dev)) {
/* management unit setup the phy already? */ np->mac_in_use = 1;
if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == if (np->mgmt_version > 0) {
NVREG_XMITCTL_SYNC_PHY_INIT) { np->mac_in_use = readl(base + NvRegMgmtUnitControl) & NVREG_MGMTUNITCONTROL_INUSE;
/* phy is inited by mgmt unit */ }
phyinitialized = 1; dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n",
dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev)); pci_name(pci_dev), np->mac_in_use);
} else { /* management unit setup the phy already? */
/* we need to init the phy */ if (np->mac_in_use &&
} ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
NVREG_XMITCTL_SYNC_PHY_INIT)) {
/* phy is inited by mgmt unit */
phyinitialized = 1;
dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n",
pci_name(pci_dev));
} else {
/* we need to init the phy */
} }
} }
} }
...@@ -5958,6 +6022,8 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) ...@@ -5958,6 +6022,8 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
/* restore any phy related changes */ /* restore any phy related changes */
nv_restore_phy(dev); nv_restore_phy(dev);
nv_mgmt_release_sema(dev);
/* free all structures */ /* free all structures */
free_rings(dev); free_rings(dev);
iounmap(get_hwbase(dev)); iounmap(get_hwbase(dev));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment