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>
This commit is contained in:
		
							parent
							
								
									1f0fa15432
								
							
						
					
					
						commit
						cac1c52c36
					
				| @ -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)); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user