adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN)) e1000_update_mng_vlan(adapter);
/* * If AMT is enabled, let the firmware know that the network * interface is now open */ if (adapter->flags & FLAG_HAS_AMT) e1000_get_hw_control(adapter);
/* * before we allocate an interrupt, we must be ready to handle it. * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt * as soon as we call pci_request_irq, so we have to setup our * clean_rx handler before we do so. */ e1000_configure(adapter);
err = e1000_request_irq(adapter); if (err) goto err_req_irq;
/* * Work around PCIe errata with MSI interrupts causing some chipsets to * ignore e1000e MSI messages, which means we need to test our MSI * interrupt now */ #ifdef CONFIG_E1000E_MSIX if (adapter->int_mode != E1000E_INT_MODE_LEGACY) #endif { err = e1000_test_msi(adapter); if (err) { e_err("Interrupt allocation failed\n"); goto err_req_irq; } }
/* From here on the code is the same as e1000_up() */ clear_bit(__E1000_DOWN, &adapter->state);
发布评论
评论(5)
具体怎么操作的?
只是打开中断?还是做了其它操作?在你操作的时候,网卡处于什么样的状态和工作模式?
正常的中断使能是在e1000_open()
static int e1000_open(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
int err;
/* disallow open during test */
if (test_bit(__E1000_TESTING, &adapter->state))
return -EBUSY;
/* allocate transmit descriptors */
err = e1000_setup_tx_resources(adapter);
if (err)
goto err_setup_tx;
/* allocate receive descriptors */
err = e1000_setup_rx_resources(adapter);
if (err)
goto err_setup_rx;
e1000_power_up_phy(hw);
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN))
e1000_update_mng_vlan(adapter);
/*
* If AMT is enabled, let the firmware know that the network
* interface is now open
*/
if (adapter->flags & FLAG_HAS_AMT)
e1000_get_hw_control(adapter);
/*
* before we allocate an interrupt, we must be ready to handle it.
* Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
* as soon as we call pci_request_irq, so we have to setup our
* clean_rx handler before we do so.
*/
e1000_configure(adapter);
err = e1000_request_irq(adapter);
if (err)
goto err_req_irq;
/*
* Work around PCIe errata with MSI interrupts causing some chipsets to
* ignore e1000e MSI messages, which means we need to test our MSI
* interrupt now
*/
#ifdef CONFIG_E1000E_MSIX
if (adapter->int_mode != E1000E_INT_MODE_LEGACY)
#endif
{
err = e1000_test_msi(adapter);
if (err) {
e_err("Interrupt allocation failed\n");
goto err_req_irq;
}
}
/* From here on the code is the same as e1000_up() */
clear_bit(__E1000_DOWN, &adapter->state);
#ifdef CONFIG_E1000E_NAPI
napi_enable(&adapter->napi);
#endif
// e1000_irq_enable(adapter);
/* fire a link status change interrupt to start the watchdog */
// ew32(ICS, E1000_ICS_LSC);
return 0;
err_req_irq:
e1000_release_hw_control(adapter);
if (!adapter->wol && hw->phy.ops.power_down)
hw->phy.ops.power_down(hw);
e1000_free_rx_resources(adapter);
err_setup_rx:
e1000_free_tx_resources(adapter);
err_setup_tx:
e1000_reset(adapter);
return err;
}
标红的被我注释掉了,我想在用户空间控制网卡中断的开关,所以注册了一个miscdevice设备,利用它的ioctl打开网卡中断
static int mapdevice_ioctl(struct inode * inode, struct file *file,
unsigned int cmd, unsigned long arg){
struct mapdevice_private *priv=global_mapdevice;
struct vortex_private *vp = priv->pci_dev_private;
long ioaddr= priv->dev->base_addr;
int entry, tmp=0;
unsigned char val;
switch (cmd) {
case WAIT_FOR_INTERRUPT:
//Check which timer is on, if on, disable it
switch (using_timer){
/**/
case WAIT_FOR_RTC_TIMER:
spin_lock_irq(&rtc_lock);
CMOS_WRITE(CMOS_READ(RTC_CONTROL)& ~0x40, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
if (rtc_status & 0x02) {
rtc_status &= ~0x02;
del_timer(&rtc_irq_timer);
}
spin_unlock_irq (&rtc_lock);
break;
case WAIT_FOR_LAPIC_TIMER:
break;
}
using_timer=0;
//enable irq and then sleep
//enabling interrupt
e1000_irq_enable(adapter); //到这步,下面有函数定义
wait_event_interruptible(wait_queue, interrupt_arrived);
interrupt_arrived=0;
//Time probe
/*
last_wake_ioctl = get_cycles();
last_end_ioctl = my_rdtsc();
//get_cycles(last_end_ioctl);
if (first_time_ioctl) {
first_wake_ioctl = last_wake_ioctl;
first_time_ioctl=0;
first_end_ioctl=last_end_ioctl;
}
*/
break;
........................
static void e1000_irq_enable(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
#ifdef CONFIG_E1000E_MSIX
if (adapter->msix_entries) {
ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
} else {
ew32(IMS, IMS_ENABLE_MASK); //到这里机器就死了
}
#else
ew32(IMS, IMS_ENABLE_MASK);
#endif /* CONFIG_E1000E_MSIX */
}
你应该搞清楚,内核里面是不是本身已经打开了中断?你在用户空间随意的打开中断,关闭中断,就有可能会出问题
在ioctl中运行的程序,kernel肯定会是打开中断的.
你先把 isr中什么都不执行。
你应该没修改e1000的代码吧