Skip to content

Commit cac1c52

Browse files
Ayaz Abdulladavem330
authored andcommitted
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: Ayaz Abdulla <aabdulla@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 1f0fa15 commit cac1c52

File tree

1 file changed

+82
-16
lines changed

1 file changed

+82
-16
lines changed

drivers/net/forcedeth.c

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ enum {
157157
#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000
158158
#define NVREG_XMITCTL_HOST_LOADED 0x00004000
159159
#define NVREG_XMITCTL_TX_PATH_EN 0x01000000
160+
#define NVREG_XMITCTL_DATA_START 0x00100000
161+
#define NVREG_XMITCTL_DATA_READY 0x00010000
162+
#define NVREG_XMITCTL_DATA_ERROR 0x00020000
160163
NvRegTransmitterStatus = 0x088,
161164
#define NVREG_XMITSTAT_BUSY 0x01
162165

@@ -289,8 +292,10 @@ enum {
289292
#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04
290293
#define NVREG_WAKEUPFLAGS_ENABLE 0x1111
291294

292-
NvRegPatternCRC = 0x204,
293-
NvRegPatternMask = 0x208,
295+
NvRegMgmtUnitGetVersion = 0x204,
296+
#define NVREG_MGMTUNITGETVERSION 0x01
297+
NvRegMgmtUnitVersion = 0x208,
298+
#define NVREG_MGMTUNITVERSION 0x08
294299
NvRegPowerCap = 0x268,
295300
#define NVREG_POWERCAP_D3SUPP (1<<30)
296301
#define NVREG_POWERCAP_D2SUPP (1<<26)
@@ -303,6 +308,8 @@ enum {
303308
#define NVREG_POWERSTATE_D1 0x0001
304309
#define NVREG_POWERSTATE_D2 0x0002
305310
#define NVREG_POWERSTATE_D3 0x0003
311+
NvRegMgmtUnitControl = 0x278,
312+
#define NVREG_MGMTUNITCONTROL_INUSE 0x20000
306313
NvRegTxCnt = 0x280,
307314
NvRegTxZeroReXmt = 0x284,
308315
NvRegTxOneReXmt = 0x288,
@@ -758,6 +765,8 @@ struct fe_priv {
758765
u32 register_size;
759766
int rx_csum;
760767
u32 mac_in_use;
768+
int mgmt_version;
769+
int mgmt_sema;
761770

762771
void __iomem *base;
763772

@@ -5182,6 +5191,7 @@ static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
51825191
/* The mgmt unit and driver use a semaphore to access the phy during init */
51835192
static int nv_mgmt_acquire_sema(struct net_device *dev)
51845193
{
5194+
struct fe_priv *np = netdev_priv(dev);
51855195
u8 __iomem *base = get_hwbase(dev);
51865196
int i;
51875197
u32 tx_ctrl, mgmt_sema;
@@ -5204,15 +5214,62 @@ static int nv_mgmt_acquire_sema(struct net_device *dev)
52045214
/* verify that semaphore was acquired */
52055215
tx_ctrl = readl(base + NvRegTransmitterControl);
52065216
if (((tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK) == NVREG_XMITCTL_HOST_SEMA_ACQ) &&
5207-
((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE))
5217+
((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) {
5218+
np->mgmt_sema = 1;
52085219
return 1;
5220+
}
52095221
else
52105222
udelay(50);
52115223
}
52125224

52135225
return 0;
52145226
}
52155227

5228+
static void nv_mgmt_release_sema(struct net_device *dev)
5229+
{
5230+
struct fe_priv *np = netdev_priv(dev);
5231+
u8 __iomem *base = get_hwbase(dev);
5232+
u32 tx_ctrl;
5233+
5234+
if (np->driver_data & DEV_HAS_MGMT_UNIT) {
5235+
if (np->mgmt_sema) {
5236+
tx_ctrl = readl(base + NvRegTransmitterControl);
5237+
tx_ctrl &= ~NVREG_XMITCTL_HOST_SEMA_ACQ;
5238+
writel(tx_ctrl, base + NvRegTransmitterControl);
5239+
}
5240+
}
5241+
}
5242+
5243+
5244+
static int nv_mgmt_get_version(struct net_device *dev)
5245+
{
5246+
struct fe_priv *np = netdev_priv(dev);
5247+
u8 __iomem *base = get_hwbase(dev);
5248+
u32 data_ready = readl(base + NvRegTransmitterControl);
5249+
u32 data_ready2 = 0;
5250+
unsigned long start;
5251+
int ready = 0;
5252+
5253+
writel(NVREG_MGMTUNITGETVERSION, base + NvRegMgmtUnitGetVersion);
5254+
writel(data_ready ^ NVREG_XMITCTL_DATA_START, base + NvRegTransmitterControl);
5255+
start = jiffies;
5256+
while (time_before(jiffies, start + 5*HZ)) {
5257+
data_ready2 = readl(base + NvRegTransmitterControl);
5258+
if ((data_ready & NVREG_XMITCTL_DATA_READY) != (data_ready2 & NVREG_XMITCTL_DATA_READY)) {
5259+
ready = 1;
5260+
break;
5261+
}
5262+
schedule_timeout_uninterruptible(1);
5263+
}
5264+
5265+
if (!ready || (data_ready2 & NVREG_XMITCTL_DATA_ERROR))
5266+
return 0;
5267+
5268+
np->mgmt_version = readl(base + NvRegMgmtUnitVersion) & NVREG_MGMTUNITVERSION;
5269+
5270+
return 1;
5271+
}
5272+
52165273
static int nv_open(struct net_device *dev)
52175274
{
52185275
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
57845841

57855842
if (id->driver_data & DEV_HAS_MGMT_UNIT) {
57865843
/* management unit running on the mac? */
5787-
if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) {
5788-
np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST;
5789-
dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use);
5790-
if (nv_mgmt_acquire_sema(dev)) {
5791-
/* management unit setup the phy already? */
5792-
if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
5793-
NVREG_XMITCTL_SYNC_PHY_INIT) {
5794-
/* phy is inited by mgmt unit */
5795-
phyinitialized = 1;
5796-
dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev));
5797-
} else {
5798-
/* we need to init the phy */
5799-
}
5844+
if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST) &&
5845+
(readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) &&
5846+
nv_mgmt_acquire_sema(dev) &&
5847+
nv_mgmt_get_version(dev)) {
5848+
np->mac_in_use = 1;
5849+
if (np->mgmt_version > 0) {
5850+
np->mac_in_use = readl(base + NvRegMgmtUnitControl) & NVREG_MGMTUNITCONTROL_INUSE;
5851+
}
5852+
dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n",
5853+
pci_name(pci_dev), np->mac_in_use);
5854+
/* management unit setup the phy already? */
5855+
if (np->mac_in_use &&
5856+
((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) ==
5857+
NVREG_XMITCTL_SYNC_PHY_INIT)) {
5858+
/* phy is inited by mgmt unit */
5859+
phyinitialized = 1;
5860+
dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n",
5861+
pci_name(pci_dev));
5862+
} else {
5863+
/* we need to init the phy */
58005864
}
58015865
}
58025866
}
@@ -5958,6 +6022,8 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
59586022
/* restore any phy related changes */
59596023
nv_restore_phy(dev);
59606024

6025+
nv_mgmt_release_sema(dev);
6026+
59616027
/* free all structures */
59626028
free_rings(dev);
59636029
iounmap(get_hwbase(dev));

0 commit comments

Comments
 (0)