⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atl1_main.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				dev_printk(KERN_DEBUG, &adapter->pdev->dev,					"rx exception, ISR = 0x%x\n", status);			atl1_intr_rx(adapter);		}		if (--max_ints < 0)			break;	} while ((status = adapter->cmb.cmb->int_stats));	/* re-enable Interrupt */	iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR);	return IRQ_HANDLED;}/* * atl1_watchdog - Timer Call-back * @data: pointer to netdev cast into an unsigned long */static void atl1_watchdog(unsigned long data){	struct atl1_adapter *adapter = (struct atl1_adapter *)data;	/* Reset the timer */	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);}/* * atl1_phy_config - Timer Call-back * @data: pointer to netdev cast into an unsigned long */static void atl1_phy_config(unsigned long data){	struct atl1_adapter *adapter = (struct atl1_adapter *)data;	struct atl1_hw *hw = &adapter->hw;	unsigned long flags;	spin_lock_irqsave(&adapter->lock, flags);	adapter->phy_timer_pending = false;	atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);	atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg);	atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN);	spin_unlock_irqrestore(&adapter->lock, flags);}/* * atl1_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure */static void atl1_tx_timeout(struct net_device *netdev){	struct atl1_adapter *adapter = netdev_priv(netdev);	/* Do the reset outside of interrupt context */	schedule_work(&adapter->tx_timeout_task);}/* * Orphaned vendor comment left intact here: * <vendor comment> * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT * will assert. We do soft reset <0x1400=1> according * with the SPEC. BUT, it seemes that PCIE or DMA * state-machine will not be reset. DMAR_TO_INT will * assert again and again. * </vendor comment> */static void atl1_tx_timeout_task(struct work_struct *work){	struct atl1_adapter *adapter =		container_of(work, struct atl1_adapter, tx_timeout_task);	struct net_device *netdev = adapter->netdev;	netif_device_detach(netdev);	atl1_down(adapter);	atl1_up(adapter);	netif_device_attach(netdev);}/* * atl1_link_chg_task - deal with link change event Out of interrupt context */static void atl1_link_chg_task(struct work_struct *work){	struct atl1_adapter *adapter =               container_of(work, struct atl1_adapter, link_chg_task);	unsigned long flags;	spin_lock_irqsave(&adapter->lock, flags);	atl1_check_link(adapter);	spin_unlock_irqrestore(&adapter->lock, flags);}static void atl1_vlan_rx_register(struct net_device *netdev,	struct vlan_group *grp){	struct atl1_adapter *adapter = netdev_priv(netdev);	unsigned long flags;	u32 ctrl;	spin_lock_irqsave(&adapter->lock, flags);	/* atl1_irq_disable(adapter); */	adapter->vlgrp = grp;	if (grp) {		/* enable VLAN tag insert/strip */		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);		ctrl |= MAC_CTRL_RMV_VLAN;		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);	} else {		/* disable VLAN tag insert/strip */		ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL);		ctrl &= ~MAC_CTRL_RMV_VLAN;		iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL);	}	/* atl1_irq_enable(adapter); */	spin_unlock_irqrestore(&adapter->lock, flags);}static void atl1_restore_vlan(struct atl1_adapter *adapter){	atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);}int atl1_reset(struct atl1_adapter *adapter){	int ret;	ret = atl1_reset_hw(&adapter->hw);	if (ret != ATL1_SUCCESS)		return ret;	return atl1_init_hw(&adapter->hw);}s32 atl1_up(struct atl1_adapter *adapter){	struct net_device *netdev = adapter->netdev;	int err;	int irq_flags = IRQF_SAMPLE_RANDOM;	/* hardware has been reset, we need to reload some things */	atl1_set_multi(netdev);	atl1_init_ring_ptrs(adapter);	atl1_restore_vlan(adapter);	err = atl1_alloc_rx_buffers(adapter);	if (unlikely(!err))		/* no RX BUFFER allocated */		return -ENOMEM;	if (unlikely(atl1_configure(adapter))) {		err = -EIO;		goto err_up;	}	err = pci_enable_msi(adapter->pdev);	if (err) {		dev_info(&adapter->pdev->dev,			"Unable to enable MSI: %d\n", err);		irq_flags |= IRQF_SHARED;	}	err = request_irq(adapter->pdev->irq, &atl1_intr, irq_flags,			netdev->name, netdev);	if (unlikely(err))		goto err_up;	mod_timer(&adapter->watchdog_timer, jiffies);	atl1_irq_enable(adapter);	atl1_check_link(adapter);	return 0;err_up:	pci_disable_msi(adapter->pdev);	/* free rx_buffers */	atl1_clean_rx_ring(adapter);	return err;}void atl1_down(struct atl1_adapter *adapter){	struct net_device *netdev = adapter->netdev;	del_timer_sync(&adapter->watchdog_timer);	del_timer_sync(&adapter->phy_config_timer);	adapter->phy_timer_pending = false;	atl1_irq_disable(adapter);	free_irq(adapter->pdev->irq, netdev);	pci_disable_msi(adapter->pdev);	atl1_reset_hw(&adapter->hw);	adapter->cmb.cmb->int_stats = 0;	adapter->link_speed = SPEED_0;	adapter->link_duplex = -1;	netif_carrier_off(netdev);	netif_stop_queue(netdev);	atl1_clean_tx_ring(adapter);	atl1_clean_rx_ring(adapter);}/* * atl1_open - Called when a network interface is made active * @netdev: network interface device structure * * Returns 0 on success, negative value on failure * * The open entry point is called when a network interface is made * active by the system (IFF_UP).  At this point all resources needed * for transmit and receive operations are allocated, the interrupt * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. */static int atl1_open(struct net_device *netdev){	struct atl1_adapter *adapter = netdev_priv(netdev);	int err;	/* allocate transmit descriptors */	err = atl1_setup_ring_resources(adapter);	if (err)		return err;	err = atl1_up(adapter);	if (err)		goto err_up;	return 0;err_up:	atl1_reset(adapter);	return err;}/* * atl1_close - Disables a network interface * @netdev: network interface device structure * * Returns 0, this is not allowed to fail * * The close entry point is called when an interface is de-activated * by the OS.  The hardware is still under the drivers control, but * needs to be disabled.  A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. */static int atl1_close(struct net_device *netdev){	struct atl1_adapter *adapter = netdev_priv(netdev);	atl1_down(adapter);	atl1_free_ring_resources(adapter);	return 0;}#ifdef CONFIG_PMstatic int atl1_suspend(struct pci_dev *pdev, pm_message_t state){	struct net_device *netdev = pci_get_drvdata(pdev);	struct atl1_adapter *adapter = netdev_priv(netdev);	struct atl1_hw *hw = &adapter->hw;	u32 ctrl = 0;	u32 wufc = adapter->wol;	netif_device_detach(netdev);	if (netif_running(netdev))		atl1_down(adapter);	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);	if (ctrl & BMSR_LSTATUS)		wufc &= ~ATL1_WUFC_LNKC;	/* reduce speed to 10/100M */	if (wufc) {		atl1_phy_enter_power_saving(hw);		/* if resume, let driver to re- setup link */		hw->phy_configured = false;		atl1_set_mac_addr(hw);		atl1_set_multi(netdev);		ctrl = 0;		/* turn on magic packet wol */		if (wufc & ATL1_WUFC_MAG)			ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;		/* turn on Link change WOL */		if (wufc & ATL1_WUFC_LNKC)			ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);		/* turn on all-multi mode if wake on multicast is enabled */		ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL);		ctrl &= ~MAC_CTRL_DBG;		ctrl &= ~MAC_CTRL_PROMIS_EN;		if (wufc & ATL1_WUFC_MC)			ctrl |= MAC_CTRL_MC_ALL_EN;		else			ctrl &= ~MAC_CTRL_MC_ALL_EN;		/* turn on broadcast mode if wake on-BC is enabled */		if (wufc & ATL1_WUFC_BC)			ctrl |= MAC_CTRL_BC_EN;		else			ctrl &= ~MAC_CTRL_BC_EN;		/* enable RX */		ctrl |= MAC_CTRL_RX_EN;		iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);		pci_enable_wake(pdev, PCI_D3hot, 1);		pci_enable_wake(pdev, PCI_D3cold, 1);	} else {		iowrite32(0, hw->hw_addr + REG_WOL_CTRL);		pci_enable_wake(pdev, PCI_D3hot, 0);		pci_enable_wake(pdev, PCI_D3cold, 0);	}	pci_save_state(pdev);	pci_disable_device(pdev);	pci_set_power_state(pdev, PCI_D3hot);	return 0;}static int atl1_resume(struct pci_dev *pdev){	struct net_device *netdev = pci_get_drvdata(pdev);	struct atl1_adapter *adapter = netdev_priv(netdev);	u32 ret_val;	pci_set_power_state(pdev, 0);	pci_restore_state(pdev);	ret_val = pci_enable_device(pdev);	pci_enable_wake(pdev, PCI_D3hot, 0);	pci_enable_wake(pdev, PCI_D3cold, 0);	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);	atl1_reset(adapter);	if (netif_running(netdev))		atl1_up(adapter);	netif_device_attach(netdev);	atl1_via_workaround(adapter);	return 0;}#else#define atl1_suspend NULL#define atl1_resume NULL#endif#ifdef CONFIG_NET_POLL_CONTROLLERstatic void atl1_poll_controller(struct net_device *netdev){	disable_irq(netdev->irq);	atl1_intr(netdev->irq, netdev);	enable_irq(netdev->irq);}#endif/* * atl1_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in atl1_pci_tbl * * Returns 0 on success, negative on failure * * atl1_probe initializes an adapter identified by a pci_dev structure. * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. */static int __devinit atl1_probe(struct pci_dev *pdev,	const struct pci_device_id *ent){	struct net_device *netdev;	struct atl1_adapter *adapter;	static int cards_found = 0;	int err;	err = pci_enable_device(pdev);	if (err)		return err;	/*	 * The atl1 chip can DMA to 64-bit addresses, but it uses a single	 * shared register for the high 32 bits, so only a single, aligned,	 * 4 GB physical address range can be used at a time.	 *	 * Supporting 64-bit DMA on this hardware is more trouble than it's	 * worth.  It is far easier to limit to 32-bit DMA than update	 * various kernel subsystems to support the mechanics required by a	 * fixed-high-32-bit system.	 */	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);	if (err) {		dev_err(&pdev->dev, "no usable DMA configuration\n");		goto err_dma;	}	/* Mark all PCI regions associated with PCI device	 * pdev as being reserved by owner atl1_driver_name	 */	err = pci_request_regions(pdev, atl1_driver_name);	if (err)		goto err_request_regions;	/* Enables bus-mastering on the device and calls	 * pcibios_set_master to do the needed arch specific settings	 */	pci_set_master(pdev);	netdev = alloc_etherdev(sizeof(struct atl1_adapter));	if (!netdev) {		err = -ENOMEM;		goto err_alloc_etherdev;	}	SET_NETDEV_DEV(netdev, &pdev->dev);	pci_set_drvdata(pdev, netdev);	adapter = netdev_priv(netdev);	adapter->netdev = netdev;	adapter->pdev = pdev;	adapter->hw.back = adapter;	adapter->hw.hw_addr = pci_iomap(pdev, 0, 0);	if (!adapter->hw.hw_addr) {		err = -EIO;		goto err_pci_iomap;	}	/* get device revision number */	adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr +		(REG_MASTER_CTRL + 2));	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);	/* set default ring resource counts */	adapter->rfd_ring.count = adapter->rrd_ring.count = ATL1_DEFAULT_RFD;	adapter->tpd_ring.count = ATL1_DEFAULT_TPD;	adapter->mii.dev = netdev;	adapter->mii.mdio_read = mdio_read;	adapter->mii.mdio_write = mdio_write;	adapter->mii.phy_id_mask = 0x1f;	adapter->mii.reg_num_mask = 0x1f;	netdev->open = &atl1_open;	netdev->stop = &atl1_close;	netdev->hard_start_xmit = &atl1_xmit_frame;	netdev->get_stats = &atl1_get_stats;	netdev->set_multicast_list = &atl1_set_multi;	netdev->set_mac_address = &atl1_set_mac;	netdev->change_mtu = &atl1_change_mtu;	netdev->do_ioctl = &atl1_ioctl;	netdev->tx_timeout = &atl1_tx_timeout;	netdev->watchdog_timeo = 5 * HZ;#ifdef CONFIG_N

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -