📄 at_main.c
字号:
/**
* at_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
**/
inline void
at_irq_enable(struct at_adapter *adapter)
{
if(0 == atomic_dec_and_test(&adapter->irq_sem)) {
AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK);
}
}
static int
at_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
{
struct pci_dev *pdev = NULL;
DEBUGFUNC("at_notify_reboot !");
switch(event) {
case SYS_DOWN:
case SYS_HALT:
case SYS_POWER_OFF:
while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
if(pci_dev_driver(pdev) == &at_driver)
at_suspend(pdev, 3);
}
}
return NOTIFY_DONE;
}
static int
at_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct at_adapter *adapter = netdev_priv(netdev);
struct at_hw * hw = &adapter->hw;
uint32_t ctrl = 0;
uint32_t wufc = adapter->wol;
DEBUGFUNC("at_suspend !");
netif_device_detach(netdev);
if(netif_running(netdev))
at_down(adapter);
at_read_phy_reg(hw, MII_BMSR, (uint16_t*)&ctrl);
at_read_phy_reg(hw, MII_BMSR, (uint16_t*)&ctrl);
if(ctrl & BMSR_LSTATUS)
wufc &= ~AT_WUFC_LNKC;
// reduce speed to 10/100M
if (wufc) {
at_phy_enter_power_saving(hw);
// if resume, let driver to re- setup link
hw->phy_configured = FALSE;
set_mac_addr(hw);
at_set_multi(netdev);
ctrl = 0;
/* turn on magic packet wol */
if (wufc & AT_WUFC_MAG) {
ctrl = WOL_MAGIC_EN|WOL_MAGIC_PME_EN;
}
// turn on Link change WOL */
if (wufc & AT_WUFC_LNKC) {
ctrl |= (WOL_LINK_CHG_EN|WOL_LINK_CHG_PME_EN);
}
AT_WRITE_REG(hw, REG_WOL_CTRL, ctrl);
/* turn on all-multi mode if wake on multicast is enabled */
ctrl = AT_READ_REG(hw, REG_MAC_CTRL);
ctrl &= ~MAC_CTRL_DBG;
ctrl &= ~MAC_CTRL_PROMIS_EN;
if(wufc & AT_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 & AT_WUFC_BC) {
ctrl |= MAC_CTRL_BC_EN;
} else {
ctrl &= ~MAC_CTRL_BC_EN;
}
// enable RX
ctrl |= MAC_CTRL_RX_EN;
AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl);
pci_enable_wake(pdev, 3, 1);
pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
} else {
AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
pci_enable_wake(pdev, 3, 0);
pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
}
pci_save_state(pdev);
pci_disable_device(pdev);
state = (state > 0) ? 3 : 0;
pci_set_power_state(pdev, state);
return 0;
}
static int
at_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct at_adapter *adapter = netdev_priv(netdev);
uint32_t ret_val;
DEBUGFUNC("at_resume !");
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
ret_val = pci_enable_device(pdev);
pci_enable_wake(pdev, 3, 0);
pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
at_reset(adapter);
if(netif_running(netdev))
at_up(adapter);
netif_device_attach(netdev);
at_via_workaround(adapter);
return 0;
}
/**
* at_sw_init - Initialize general software structures (struct at_adapter)
* @adapter: board private structure to initialize
*
* at_sw_init initializes the Adapter private data structure.
* Fields are initialized based on PCI device information and
* OS network device settings (MTU size).
**/
static int __devinit
at_sw_init(struct at_adapter *adapter)
{
struct at_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
/* PCI config space info */
hw->vendor_id = pdev->vendor;
hw->device_id = pdev->device;
hw->subsystem_vendor_id = pdev->subsystem_vendor;
hw->subsystem_id = pdev->subsystem_device;
pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
hw->max_frame_size = netdev->mtu +
ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
adapter->wol = 0;
adapter->rx_buffer_len = (hw->max_frame_size+7)&~7;
adapter->ict = 50000; // 100ms
adapter->link_speed = SPEED_0; // hardware init
adapter->link_duplex = FULL_DUPLEX; //
hw->phy_configured = FALSE;
hw->preamble_len = 7;
hw->ipgt = 0x60;
hw->min_ifg = 0x50;
hw->ipgr1 = 0x40;
hw->ipgr2 = 0x60;
hw->max_retry = 0xf;
hw->lcol = 0x37;
hw->jam_ipg = 7;
hw->rfd_burst = 8;
hw->rrd_burst = 8;
hw->rfd_fetch_gap = 1;
hw->rx_jumbo_th = adapter->rx_buffer_len / 8;
hw->rx_jumbo_lkah = 1;
hw->rrd_ret_timer = 16;
hw->tpd_burst = 4;
hw->tpd_fetch_th = 16;
hw->txf_burst = 0x100;
hw->tx_jumbo_task_th = (hw->max_frame_size+7)>>3;
hw->tpd_fetch_gap = 1;
hw->rcb_value = at_rcb_128;
hw->dma_ord = at_dma_ord_enh;
hw->dmar_block = at_dma_req_256;
hw->dmaw_block = at_dma_req_256;
hw->cmb_rrd = 4;
hw->cmb_tpd = 4;
hw->cmb_rx_timer = 1; //about 2us
hw->cmb_tx_timer = 1; //about 2us
hw->smb_timer = 100000 ; // about 200ms
atomic_set(&adapter->irq_sem, 0);
spin_lock_init(&adapter->stats_lock);
spin_lock_init(&adapter->tx_lock);
spin_lock_init(&adapter->mb_lock);
return 0;
}
int
at_reset(struct at_adapter *adapter)
{
int ret;
if (AT_SUCCESS != (ret = at_reset_hw(&adapter->hw)))
return ret;
return at_init_hw(&adapter->hw);
}
/**
* at_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
at_open(struct net_device *netdev)
{
struct at_adapter *adapter = netdev_priv(netdev);
int err;
DEBUGFUNC("at_open !");
/* allocate transmit descriptors */
if((err = at_setup_ring_resources(adapter)))
return err;
if((err = at_up(adapter)))
goto err_up;
/* for test only */
/* { uint32_t value;
value = AT_READ_REG(&adapter->hw, 0x12FC);
DEBUGOUT1("reg 0x12fc = 0x%x", value);
value = AT_READ_REG(&adapter->hw, 0x1008);
DEBUGOUT1("reg 0x1008 = 0x%x", value);
}
*/
/**********end ****/
return 0;
err_up:
at_reset(adapter);
return err;
}
/**
* at_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
at_close(struct net_device *netdev)
{
struct at_adapter *adapter = netdev_priv(netdev);
DEBUGFUNC("at_close!");
at_down(adapter);
at_free_ring_resources(adapter);
return 0;
}
/**
* at_setup_mem_resources - allocate Tx / RX descriptor resources
* @adapter: board private structure
*
* Return 0 on success, negative on failure
**/
int32_t
at_setup_ring_resources(struct at_adapter *adapter)
{
struct at_tpd_ring *tpd_ring = &adapter->tpd_ring;
struct at_rfd_ring *rfd_ring = &adapter->rfd_ring;
struct at_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct at_ring_header * ring_header = &adapter->ring_header;
struct pci_dev *pdev = adapter->pdev;
int size;
uint8_t offset = 0;
// DEBUGFUNC("at_setup_ring_resources !");
// DEBUGOUT1("TPD count = %x RFD cont = %x RRD = %x",
// tpd_ring->count, rfd_ring->count, rrd_ring->count);
DEBUGOUT1("sz TPD:%d, sz RFD:%d, sz RRD:%d",
sizeof(tx_packet_desc_t),
sizeof(rx_free_desc_t),
sizeof(rx_return_desc_t));
size = sizeof(struct at_buffer) * (tpd_ring->count+rfd_ring->count);
tpd_ring->buffer_info = kmalloc(size, GFP_KERNEL);
if(!tpd_ring->buffer_info) {
DEBUGOUT1("kmalloc failed , size = D%d", size);
return -ENOMEM;
}
rfd_ring->buffer_info =
(struct at_buffer*)(tpd_ring->buffer_info+tpd_ring->count);
memset(tpd_ring->buffer_info, 0, size);
/* real ring DMA buffer */
ring_header->size = size = sizeof(tx_packet_desc_t ) * tpd_ring->count
+ sizeof(rx_free_desc_t) * rfd_ring->count
+ sizeof(rx_return_desc_t) * rrd_ring->count
+ sizeof(coals_msg_block_t)
+ sizeof(stats_msg_block_t)
+ 40; // 40: for 8 bytes align
ring_header->desc =
pci_alloc_consistent(pdev, ring_header->size, &ring_header->dma);
if(!ring_header->desc) {
kfree(tpd_ring->buffer_info);
DEBUGOUT1("pci_alloc_consistent failed , size = D%d", size);
return -ENOMEM;
}
if (adapter->pci_using_64)
{ // test whether HIDWORD dma buffer is not cross boundary
if ( ((ring_header->dma &0xffffffff00000000ULL)>>32)
!= (((ring_header->dma+size)&0xffffffff00000000ULL)>>32) )
{
kfree(tpd_ring->buffer_info);
pci_free_consistent(
pdev,
ring_header->size,
ring_header->desc,
ring_header->dma);
DEBUGOUT("memory allocated cross 32bit boundary !");
return -ENOMEM;
}
}
// DEBUGOUT("memory allocated successfully !");
memset(ring_header->desc, 0, ring_header->size);
DEBUGOUT1("whole ring dma addr=%x", ring_header->dma);
// init TPD ring
tpd_ring->dma = ring_header->dma;
offset = (tpd_ring->dma & 0x7) ? (8 - (ring_header->dma & 0x7)) : 0;
tpd_ring->dma += offset;
tpd_ring->desc = (uint8_t*) ring_header->desc + offset;
tpd_ring->size = sizeof(tx_packet_desc_t) * tpd_ring->count;
atomic_set(&tpd_ring->next_to_use, 0);
atomic_set(&tpd_ring->next_to_clean, 0);
DEBUGOUT1("tpd ring dma addr=%x", tpd_ring->dma);
// init RFD ring
rfd_ring->dma = tpd_ring->dma + tpd_ring->size;
offset = (rfd_ring->dma & 0x7) ? (8 - (rfd_ring->dma & 0x7)) : 0;
rfd_ring->dma += offset;
rfd_ring->desc = (uint8_t*) tpd_ring->desc + (tpd_ring->size+offset);
rfd_ring->size = sizeof(rx_free_desc_t) * rfd_ring->count;
rfd_ring->next_to_clean = 0;
//rfd_ring->next_to_use = rfd_ring->count - 1;
atomic_set(&rfd_ring->next_to_use, 0);
DEBUGOUT1("rfd ring dma addr=%x", rfd_ring->dma);
// init RRD ring
rrd_ring->dma = rfd_ring->dma + rfd_ring->size;
offset = (rrd_ring->dma & 0x7) ? (8 - (rrd_ring->dma & 0x7)) : 0;
rrd_ring->dma += offset;
rrd_ring->desc = (uint8_t*) rfd_ring->desc + (rfd_ring->size+offset);
rrd_ring->size = sizeof(rx_return_desc_t) * rrd_ring->count;
rrd_ring->next_to_use = 0;
atomic_set(&rrd_ring->next_to_clean, 0);
DEBUGOUT1("rrd ring dma addr=%x", rrd_ring->dma);
// init CMB
adapter->cmb.dma = rrd_ring->dma + rrd_ring->size;
offset = (adapter->cmb.dma & 0x7)? (8-(adapter->cmb.dma & 0x7)) : 0;
adapter->cmb.dma += offset;
adapter->cmb.cmb =
(coals_msg_block_t*)
((uint8_t*)rrd_ring->desc + (rrd_ring->size+offset));
DEBUGOUT1("cmd dma addr=%x", adapter->cmb.dma);
// init SMB
adapter->smb.dma = adapter->cmb.dma + sizeof(coals_msg_block_t);
offset = (adapter->smb.dma&0x7) ? (8-(adapter->smb.dma&0x7)): 0;
adapter->smb.dma += offset;
adapter->smb.smb =
(stats_msg_block_t*)
((uint8_t*)adapter->cmb.cmb + (sizeof(coals_msg_block_t)+offset));
DEBUGOUT1("smb dma addr=%x", adapter->smb.dma);
return AT_SUCCESS;
}
/**
* at_free_ring_resources - Free Tx / RX descriptor Resources
* @adapter: board private structure
*
* Free all transmit software resources
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -