|
@@ -157,6 +157,9 @@ enum {
|
|
|
#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000
|
|
|
#define NVREG_XMITCTL_HOST_LOADED 0x00004000
|
|
|
#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,
|
|
|
#define NVREG_XMITSTAT_BUSY 0x01
|
|
|
|
|
@@ -289,8 +292,10 @@ enum {
|
|
|
#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04
|
|
|
#define NVREG_WAKEUPFLAGS_ENABLE 0x1111
|
|
|
|
|
|
- NvRegPatternCRC = 0x204,
|
|
|
- NvRegPatternMask = 0x208,
|
|
|
+ NvRegMgmtUnitGetVersion = 0x204,
|
|
|
+#define NVREG_MGMTUNITGETVERSION 0x01
|
|
|
+ NvRegMgmtUnitVersion = 0x208,
|
|
|
+#define NVREG_MGMTUNITVERSION 0x08
|
|
|
NvRegPowerCap = 0x268,
|
|
|
#define NVREG_POWERCAP_D3SUPP (1<<30)
|
|
|
#define NVREG_POWERCAP_D2SUPP (1<<26)
|
|
@@ -303,6 +308,8 @@ enum {
|
|
|
#define NVREG_POWERSTATE_D1 0x0001
|
|
|
#define NVREG_POWERSTATE_D2 0x0002
|
|
|
#define NVREG_POWERSTATE_D3 0x0003
|
|
|
+ NvRegMgmtUnitControl = 0x278,
|
|
|
+#define NVREG_MGMTUNITCONTROL_INUSE 0x20000
|
|
|
NvRegTxCnt = 0x280,
|
|
|
NvRegTxZeroReXmt = 0x284,
|
|
|
NvRegTxOneReXmt = 0x288,
|
|
@@ -758,6 +765,8 @@ struct fe_priv {
|
|
|
u32 register_size;
|
|
|
int rx_csum;
|
|
|
u32 mac_in_use;
|
|
|
+ int mgmt_version;
|
|
|
+ int mgmt_sema;
|
|
|
|
|
|
void __iomem *base;
|
|
|
|
|
@@ -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 */
|
|
|
static int nv_mgmt_acquire_sema(struct net_device *dev)
|
|
|
{
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
|
int i;
|
|
|
u32 tx_ctrl, mgmt_sema;
|
|
@@ -5204,8 +5214,10 @@ static int nv_mgmt_acquire_sema(struct net_device *dev)
|
|
|
/* verify that semaphore was acquired */
|
|
|
tx_ctrl = readl(base + NvRegTransmitterControl);
|
|
|
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;
|
|
|
+ }
|
|
|
else
|
|
|
udelay(50);
|
|
|
}
|
|
@@ -5213,6 +5225,51 @@ static int nv_mgmt_acquire_sema(struct net_device *dev)
|
|
|
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)
|
|
|
{
|
|
|
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
|
|
|
|
|
|
if (id->driver_data & DEV_HAS_MGMT_UNIT) {
|
|
|
/* management unit running on the mac? */
|
|
|
- if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) {
|
|
|
- np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
|
|
|
- dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use);
|
|
|
- if (nv_mgmt_acquire_sema(dev)) {
|
|
|
- /* management unit setup the phy already? */
|
|
|
- if ((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 */
|
|
|
- }
|
|
|
+ if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST) &&
|
|
|
+ (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) &&
|
|
|
+ nv_mgmt_acquire_sema(dev) &&
|
|
|
+ nv_mgmt_get_version(dev)) {
|
|
|
+ np->mac_in_use = 1;
|
|
|
+ if (np->mgmt_version > 0) {
|
|
|
+ np->mac_in_use = readl(base + NvRegMgmtUnitControl) & NVREG_MGMTUNITCONTROL_INUSE;
|
|
|
+ }
|
|
|
+ dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n",
|
|
|
+ pci_name(pci_dev), np->mac_in_use);
|
|
|
+ /* management unit setup the phy already? */
|
|
|
+ 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)
|
|
|
/* restore any phy related changes */
|
|
|
nv_restore_phy(dev);
|
|
|
|
|
|
+ nv_mgmt_release_sema(dev);
|
|
|
+
|
|
|
/* free all structures */
|
|
|
free_rings(dev);
|
|
|
iounmap(get_hwbase(dev));
|