aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/forcedeth.c
diff options
context:
space:
mode:
authorAyaz Abdulla <aabdulla@nvidia.com>2009-02-07 03:23:57 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-07 03:23:57 -0500
commitcac1c52c3621b46e3be49cf7887a7cfa393890de (patch)
tree5dc05a67babb5eefcab00f0f9235fef5ec57099d /drivers/net/forcedeth.c
parent1f0fa15432e49547c3fa915644c7e0c0975809e7 (diff)
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>
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r--drivers/net/forcedeth.c98
1 files changed, 82 insertions, 16 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 7825be7586f3..da7c9ee069b5 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -157,6 +157,9 @@ enum {
157#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000 157#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000
158#define NVREG_XMITCTL_HOST_LOADED 0x00004000 158#define NVREG_XMITCTL_HOST_LOADED 0x00004000
159#define NVREG_XMITCTL_TX_PATH_EN 0x01000000 159#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
160 NvRegTransmitterStatus = 0x088, 163 NvRegTransmitterStatus = 0x088,
161#define NVREG_XMITSTAT_BUSY 0x01 164#define NVREG_XMITSTAT_BUSY 0x01
162 165
@@ -289,8 +292,10 @@ enum {
289#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04 292#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04
290#define NVREG_WAKEUPFLAGS_ENABLE 0x1111 293#define NVREG_WAKEUPFLAGS_ENABLE 0x1111
291 294
292 NvRegPatternCRC = 0x204, 295 NvRegMgmtUnitGetVersion = 0x204,
293 NvRegPatternMask = 0x208, 296#define NVREG_MGMTUNITGETVERSION 0x01
297 NvRegMgmtUnitVersion = 0x208,
298#define NVREG_MGMTUNITVERSION 0x08
294 NvRegPowerCap = 0x268, 299 NvRegPowerCap = 0x268,
295#define NVREG_POWERCAP_D3SUPP (1<<30) 300#define NVREG_POWERCAP_D3SUPP (1<<30)
296#define NVREG_POWERCAP_D2SUPP (1<<26) 301#define NVREG_POWERCAP_D2SUPP (1<<26)
@@ -303,6 +308,8 @@ enum {
303#define NVREG_POWERSTATE_D1 0x0001 308#define NVREG_POWERSTATE_D1 0x0001
304#define NVREG_POWERSTATE_D2 0x0002 309#define NVREG_POWERSTATE_D2 0x0002
305#define NVREG_POWERSTATE_D3 0x0003 310#define NVREG_POWERSTATE_D3 0x0003
311 NvRegMgmtUnitControl = 0x278,
312#define NVREG_MGMTUNITCONTROL_INUSE 0x20000
306 NvRegTxCnt = 0x280, 313 NvRegTxCnt = 0x280,
307 NvRegTxZeroReXmt = 0x284, 314 NvRegTxZeroReXmt = 0x284,
308 NvRegTxOneReXmt = 0x288, 315 NvRegTxOneReXmt = 0x288,
@@ -758,6 +765,8 @@ struct fe_priv {
758 u32 register_size; 765 u32 register_size;
759 int rx_csum; 766 int rx_csum;
760 u32 mac_in_use; 767 u32 mac_in_use;
768 int mgmt_version;
769 int mgmt_sema;
761 770
762 void __iomem *base; 771 void __iomem *base;
763 772
@@ -5182,6 +5191,7 @@ static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
5182/* The mgmt unit and driver use a semaphore to access the phy during init */ 5191/* The mgmt unit and driver use a semaphore to access the phy during init */
5183static int nv_mgmt_acquire_sema(struct net_device *dev) 5192static int nv_mgmt_acquire_sema(struct net_device *dev)
5184{ 5193{
5194 struct fe_priv *np = netdev_priv(dev);
5185 u8 __iomem *base = get_hwbase(dev); 5195 u8 __iomem *base = get_hwbase(dev);
5186 int i; 5196 int i;
5187 u32 tx_ctrl, mgmt_sema; 5197 u32 tx_ctrl, mgmt_sema;
@@ -5204,8 +5214,10 @@ static int nv_mgmt_acquire_sema(struct net_device *dev)
5204 /* verify that semaphore was acquired */ 5214 /* verify that semaphore was acquired */
5205 tx_ctrl = readl(base + NvRegTransmitterControl); 5215 tx_ctrl = readl(base + NvRegTransmitterControl);
5206 if (((tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK) == NVREG_XMITCTL_HOST_SEMA_ACQ) && 5216 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;
5208 return 1; 5219 return 1;
5220 }
5209 else 5221 else
5210 udelay(50); 5222 udelay(50);
5211 } 5223 }
@@ -5213,6 +5225,51 @@ static int nv_mgmt_acquire_sema(struct net_device *dev)
5213 return 0; 5225 return 0;
5214} 5226}
5215 5227
5228static 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
5244static 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
5216static int nv_open(struct net_device *dev) 5273static int nv_open(struct net_device *dev)
5217{ 5274{
5218 struct fe_priv *np = netdev_priv(dev); 5275 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 5841
5785 if (id->driver_data & DEV_HAS_MGMT_UNIT) { 5842 if (id->driver_data & DEV_HAS_MGMT_UNIT) {
5786 /* management unit running on the mac? */ 5843 /* management unit running on the mac? */
5787 if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) { 5844 if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST) &&
5788 np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST; 5845 (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_PHY_INIT) &&
5789 dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n", pci_name(pci_dev), np->mac_in_use); 5846 nv_mgmt_acquire_sema(dev) &&
5790 if (nv_mgmt_acquire_sema(dev)) { 5847 nv_mgmt_get_version(dev)) {
5791 /* management unit setup the phy already? */ 5848 np->mac_in_use = 1;
5792 if ((readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK) == 5849 if (np->mgmt_version > 0) {
5793 NVREG_XMITCTL_SYNC_PHY_INIT) { 5850 np->mac_in_use = readl(base + NvRegMgmtUnitControl) & NVREG_MGMTUNITCONTROL_INUSE;
5794 /* phy is inited by mgmt unit */ 5851 }
5795 phyinitialized = 1; 5852 dprintk(KERN_INFO "%s: mgmt unit is running. mac in use %x.\n",
5796 dprintk(KERN_INFO "%s: Phy already initialized by mgmt unit.\n", pci_name(pci_dev)); 5853 pci_name(pci_dev), np->mac_in_use);
5797 } else { 5854 /* management unit setup the phy already? */
5798 /* we need to init the phy */ 5855 if (np->mac_in_use &&
5799 } 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 */
5800 } 5864 }
5801 } 5865 }
5802 } 5866 }
@@ -5958,6 +6022,8 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
5958 /* restore any phy related changes */ 6022 /* restore any phy related changes */
5959 nv_restore_phy(dev); 6023 nv_restore_phy(dev);
5960 6024
6025 nv_mgmt_release_sema(dev);
6026
5961 /* free all structures */ 6027 /* free all structures */
5962 free_rings(dev); 6028 free_rings(dev);
5963 iounmap(get_hwbase(dev)); 6029 iounmap(get_hwbase(dev));