forcedeth: mgmt unit interface changes
Subsystems (2)
PATCH 1/1 forcedeth: mgmt unit interface changes
This patch updates the logic used to communicate with the mgmt unit. It also adds a version check for a newer mgmt unit firmware.
drivers/net/forcedeth.c +78 -16
@@ -157,6 +157,9 @@#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 @@#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 @@#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 @@u32 register_size;int rx_csum;u32 mac_in_use; +int mgmt_version; +int mgmt_sema;void __iomem *base;
@@ -5169,6 +5178,7 @@/* 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;
@@ -5191,8 +5201,10 @@/* 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 ); }
@@ -5200,6 +5212,47 @@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; +int i; + +writel (NVREG_MGMTUNITGETVERSION , base + NvRegMgmtUnitGetVersion); +writel (data_ready ^NVREG_XMITCTL_DATA_START , base + NvRegTransmitterControl); +for (i =0 ; i <1000000 ; i++) { + data_ready2 =readl (base + NvRegTransmitterControl); +if ((data_ready &NVREG_XMITCTL_DATA_READY ) != (data_ready2 &NVREG_XMITCTL_DATA_READY )) +break ; +udelay (50 ); + } + +if (i ==1000000 || (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);
@@ -5771,19 +5824,26 @@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 */ } } }
@@ -5945,6 +6005,8 @@/* restore any phy related changes */ nv_restore_phy (dev); +nv_mgmt_release_sema (dev); +/* free all structures */ free_rings (dev);iounmap (get_hwbase (dev));
Quoted 14 lines · On Fri, 23 Jan 2009 16:01:58 -0500 Ayaz Abdulla <[email protected]> wrote:
drivers/net/forcedeth.c +14
-0+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; +int i; + +writel (NVREG_MGMTUNITGETVERSION , base + NvRegMgmtUnitGetVersion); +writel (data_ready ^NVREG_XMITCTL_DATA_START , base + NvRegTransmitterControl); +for (i =0 ; i <1000000 ; i++) { + data_ready2 =readl (base + NvRegTransmitterControl); +if ((data_ready &NVREG_XMITCTL_DATA_READY ) != (data_ready2 &NVREG_XMITCTL_DATA_READY )) +break ;
drivers/net/forcedeth.c line 5254
Quoted 10 lines
drivers/net/forcedeth.c +10
-0+udelay (50 ); + } + +if (i ==1000000 || (data_ready2 &NVREG_XMITCTL_DATA_ERROR )) +return 0 ; + + np->mgmt_version =readl (base + NvRegMgmtUnitVersion) &NVREG_MGMTUNITVERSION ; + +return 1 ; +}
whee, a 50 second busy-wait.
Unnecessarily, afacit. The sole caller calls this function from ->probe without any locks held?
I'd suggest that we
a) use schedule_timeout_uninterruptible(1) and
b) add a bit of user feedback (printk(".")?) so they don't get bored and hit the reset button (remember those?)
David Miller
maintainerFrom: Andrew Morton <[email protected]>
Date: Tue, 27 Jan 2009 17:27:05 -0800
Quoted 11 lines
whee, a 50 second busy-wait.
Unnecessarily, afacit. The sole caller calls this function from ->probe without any locks held?
I'd suggest that we
a) use
schedule_timeout_uninterruptible(1)andb) add a bit of user feedback (
printk(".")?) so they don't get bored and hit the reset button (remember those?)
Agreed.
Yes, good catch. One extra zero added, should be only upto 5 secs.
I will resend the patch.
-----Original Message-----
From: David Miller [mailto:[email protected]]
Sent: Tuesday, January 27, 2009 5:30 PM
To: [email protected]
Cc: Ayaz Abdulla; [email protected]; [email protected]; [email protected]
Subject: Re: [PATCH] forcedeth: mgmt unit interface changes
From: Andrew Morton <[email protected]>
Date: Tue, 27 Jan 2009 17:27:05 -0800
Quoted 11 lines
whee, a 50 second busy-wait.
Unnecessarily, afacit. The sole caller calls this function from ->probe without any locks held?
I'd suggest that we
a) use
schedule_timeout_uninterruptible(1)andb) add a bit of user feedback (
printk(".")?) so they don't get bored and hit the reset button (remember those?)
Agreed.
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------