📄 at_main.c
字号:
/* Zero out the descriptor ring */
memset(tpd_ring->desc, 0, tpd_ring->size);
atomic_set(&tpd_ring->next_to_use, 0);
atomic_set(&tpd_ring->next_to_clean, 0);
}
/**
* at_clean_rx_ring - Free RFD Buffers
* @adapter: board private structure
**/
static void
at_clean_rx_ring(struct at_adapter *adapter)
{
struct at_rfd_ring *rfd_ring = &adapter->rfd_ring;
struct at_rrd_ring *rrd_ring = &adapter->rrd_ring;
struct at_buffer *buffer_info;
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
unsigned int i;
// DEBUGFUNC("at_clean_rx_ring !");
/* Free all the Rx ring sk_buffs */
for(i = 0; i < rfd_ring->count; i++) {
buffer_info = &rfd_ring->buffer_info[i];
if(buffer_info->dma) {
pci_unmap_page(pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_FROMDEVICE);
buffer_info->dma = 0;
}
if(buffer_info->skb) {
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
}
}
size = sizeof(struct at_buffer) * rfd_ring->count;
memset(rfd_ring->buffer_info, 0, size);
/* Zero out the descriptor ring */
memset(rfd_ring->desc, 0, rfd_ring->size);
rfd_ring->next_to_clean = 0;
atomic_set(&rfd_ring->next_to_use, 0);
rrd_ring->next_to_use = 0;
atomic_set(&rrd_ring->next_to_clean, 0);
}
/**
* at_get_stats - Get System Network Statistics
* @netdev: network interface device structure
*
* Returns the address of the device statistics structure.
* The statistics are actually updated from the timer callback.
**/
static struct net_device_stats *
at_get_stats(struct net_device *netdev)
{
struct at_adapter *adapter = netdev_priv(netdev);
// DEBUGFUNC("at_get_stats");
return &adapter->net_stats;
}
/**
* at_ioctl -
* @netdev:
* @ifreq:
* @cmd:
**/
static int
at_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
// DEBUGFUNC("at_ioctl !");
switch (cmd) {
#ifdef SIOCGMIIPHY
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSMIIREG:
return at_mii_ioctl(netdev, ifr, cmd);
#endif
/*
#ifdef ETHTOOL_OPS_COMPAT
case SIOCETHTOOL:
return at_ethtool_ioctl(ifr);
#endif
*/
//michael add 2005-11-1
case SIOCETHTOOL:
return at_ethtool_ioctl(netdev,ifr);
#ifdef SIOCDEVPRIVATE
case SIOCDEVPRIVATE:
return at_priv_ioctl(netdev, ifr);
#endif
default:
return -EOPNOTSUPP;
}
}
#ifdef SIOCGMIIPHY
/**
* at_mii_ioctl -
* @netdev:
* @ifreq:
* @cmd:
**/
static int
at_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
struct at_adapter *adapter = netdev_priv(netdev);
struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
unsigned long flags;
// DEBUGFUNC("at_mii_ioctl !");
switch (cmd) {
case SIOCGMIIPHY:
data->phy_id = 0;
break;
case SIOCGMIIREG:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&adapter->stats_lock, flags);
if (at_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, &data->val_out)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
case SIOCSMIIREG:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (data->reg_num & ~(0x1F))
return -EFAULT;
spin_lock_irqsave(&adapter->stats_lock, flags);
DEBUGOUT1("<at_mii_ioctl> write %x %x",
data->reg_num,
data->val_in);
if (at_write_phy_reg(&adapter->hw, data->reg_num, data->val_in)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
// ......
spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
default:
return -EOPNOTSUPP;
}
return AT_SUCCESS;
}
#endif
/**
* at_tx_timeout - Respond to a Tx Hang
* @netdev: network interface device structure
**/
static void
at_tx_timeout(struct net_device *netdev)
{
struct at_adapter *adapter = netdev_priv(netdev);
DEBUGFUNC("at_tx_timeout !");
/* Do the reset outside of interrupt context */
schedule_work(&adapter->tx_timeout_task);
}
/*
* 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.
*/
static void
at_tx_timeout_task(struct net_device *netdev)
{
struct at_adapter *adapter = netdev_priv(netdev);
//struct at_hw* hw = &adapter->hw;
//uint32_t val1, val2;
DEBUGFUNC("at_tx_timeout_task !");
netif_device_detach(netdev);
/******* disp debug info **********
val1 = AT_READ_REG(hw, 0x15f0);
DEBUGOUT1("<15f0> = 0x%x", val1);
val1 = AT_READ_REG(hw, 0x1540);
val2 = AT_READ_REG(hw, 0x1544);
DEBUGOUT1("<1540> = 0x%x <1544> = 0x%x", val1, val2);
val1 = AT_READ_REG(hw, 0x1548);
val2 = AT_READ_REG(hw, 0x154c);
DEBUGOUT1("<1548> = 0x%x <154c> = 0x%x", val1, val2);
val1 = AT_READ_REG(hw, 0x1550);
val2 = AT_READ_REG(hw, 0x1554);
DEBUGOUT1("<1550> = 0x%x <1554> = 0x%x", val1, val2);
val1 = AT_READ_REG(hw, 0x1558);
val2 = AT_READ_REG(hw, 0x155c);
DEBUGOUT1("<1558> = 0x%x <155c> = 0x%x", val1, val2);
DEBUGOUT1("tpd next to clean %d, tpd next to use %d",
(uint16_t) atomic_read(&adapter->tpd_ring.next_to_clean),
(uint16_t) atomic_read(&adapter->tpd_ring.next_to_use));
DEBUGOUT1("rfd ring: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
*((uint32_t*)(adapter->rfd_ring.desc) + 0),
*((uint32_t*)(adapter->rfd_ring.desc) + 1),
*((uint32_t*)(adapter->rfd_ring.desc) + 2),
*((uint32_t*)(adapter->rfd_ring.desc) + 3),
*((uint32_t*)(adapter->rfd_ring.desc) + 4),
*((uint32_t*)(adapter->rfd_ring.desc) + 5));
DEBUGOUT1("rfd ring: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
*((uint32_t*)(adapter->rfd_ring.desc) + 6),
*((uint32_t*)(adapter->rfd_ring.desc) + 7),
*((uint32_t*)(adapter->rfd_ring.desc) + 8),
*((uint32_t*)(adapter->rfd_ring.desc) + 9),
*((uint32_t*)(adapter->rfd_ring.desc) + 10),
*((uint32_t*)(adapter->rfd_ring.desc) + 11));
DEBUGOUT1("rfd ring: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
*((uint32_t*)(adapter->rfd_ring.desc) + 12),
*((uint32_t*)(adapter->rfd_ring.desc) + 13),
*((uint32_t*)(adapter->rfd_ring.desc) + 14),
*((uint32_t*)(adapter->rfd_ring.desc) + 15),
*((uint32_t*)(adapter->rfd_ring.desc) + 16),
*((uint32_t*)(adapter->rfd_ring.desc) + 17));
DEBUGOUT1("rfd ring: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
*((uint32_t*)(adapter->rfd_ring.desc) + 18),
*((uint32_t*)(adapter->rfd_ring.desc) + 19),
*((uint32_t*)(adapter->rfd_ring.desc) + 20),
*((uint32_t*)(adapter->rfd_ring.desc) + 21),
*((uint32_t*)(adapter->rfd_ring.desc) + 22),
*((uint32_t*)(adapter->rfd_ring.desc) + 23));
*/
at_down(adapter);
at_up(adapter);
netif_device_attach(netdev);
}
/**
* at_link_chg_task - deal with link change event Out of interrupt context
* @netdev: network interface device structure
**/
static void
at_link_chg_task(struct net_device* netdev)
{
struct at_adapter * adapter = netdev_priv(netdev);
unsigned long flags;
DEBUGFUNC("at_link_chg_task !");
spin_lock_irqsave(&adapter->stats_lock, flags);
at_check_link(adapter);
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
static void
at_check_for_link(struct at_adapter* adapter)
{
struct net_device *netdev = adapter->netdev;
uint16_t phy_data = 0;
DEBUGFUNC("at_check_for_link!");
spin_lock(&adapter->stats_lock);
adapter->phy_timer_pending = FALSE;
at_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
at_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
spin_unlock(&adapter->stats_lock);
DEBUGOUT1("MII_BMSR=%x <at_check_for_link>", phy_data);
// notify upper layer link down ASAP
if (!(phy_data&BMSR_LSTATUS)) { // Link Down
if (netif_carrier_ok(netdev)) { // old link state: Up
printk(KERN_INFO
"%s: %s NIC Link is Down\n",
at_driver_name,
netdev->name );
adapter->link_speed = SPEED_0;
netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
}
schedule_work(&adapter->link_chg_task);
}
static inline void
at_clear_phy_int(struct at_adapter* adapter)
{
uint16_t phy_data;
spin_lock(&adapter->stats_lock);
at_read_phy_reg(&adapter->hw, 19, &phy_data);
spin_unlock(&adapter->stats_lock);
}
/**
* at_intr - Interrupt Handler
* @irq: interrupt number
* @data: pointer to a network interface device structure
* @pt_regs: CPU registers structure
**/
static irqreturn_t
at_intr(int irq, void *data, struct pt_regs *regs)
{
struct at_adapter *adapter = ((struct net_device*)data)->priv;
uint32_t status;
uint8_t update_rx;
int max_ints = 10;
if (0 == (status = adapter->cmb.cmb->int_stats))
return IRQ_NONE;
update_rx = 0;
do {
// clear CMB interrupt status at once
adapter->cmb.cmb->int_stats = 0;
if (status & ISR_GPHY) { // clear phy status
at_clear_phy_int(adapter);
}
// clear ISR status, and Enable CMB DMA/Disable Interrupt
AT_WRITE_REG(&adapter->hw, REG_ISR, status|ISR_DIS_INT);
// check if SMB intr
if (status & ISR_SMB)
{
at_inc_smb(adapter);
}
// check if PCIE PHY Link down
if (status&ISR_PHY_LINKDOWN)
{
DEBUGOUT1("pcie phy linkdown %x", status);
if(netif_running(adapter->netdev)) { // reset MAC
AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
schedule_work(&adapter->pcie_dma_to_rst_task);
return IRQ_HANDLED;
}
}
// check if DMA read/write error ?
if (status&(ISR_DMAR_TO_RST|ISR_DMAW_TO_RST))
{
DEBUGOUT1("PCIE DMA RW error (status = 0x%x) !", status);
//AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST);
AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
schedule_work(&adapter->pcie_dma_to_rst_task);
return IRQ_HANDLED;
}
// link event
if (status&ISR_GPHY)
{
adapter->soft_stats.tx_carrier_errors++;
at_check_for_link(adapter);
}
// transmit event
if (status&ISR_CMB_TX) {
at_intr_tx(adapter);
}
// rx exception
if ( status&(ISR_RXF_OV|
ISR_RFD_UNRUN|
ISR_RRD_OV|
ISR_HOST_RFD_UNRUN|
ISR_HOST_RRD_OV|
ISR_CMB_RX)) {
if (status&(ISR_RXF_OV|
ISR_RFD_UNRUN|
ISR_RRD_OV|
ISR_HOST_RFD_UNRUN|
ISR_HOST_RRD_OV)) {
DEBUGOUT1(KERN_INFO
"Receive Exception ! status = 0x%x", status);
}
at_intr_rx(adapter);
}
if (--max_ints < 0)
break;
} while ((status = adapter->cmb.cmb->int_stats));
// re-enable Interrupt
AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_SMB|ISR_DIS_DMA);
return IRQ_HANDLED;
}
static void
at_intr_tx(struct at_adapter* adapter)
{
struct at_tpd_ring *tpd_ring = &adapter->tpd_ring;
struct at_buffer* buffer_info;
uint16_t sw_tpd_next_to_clean;
uint16_t cmb_tpd_next_to_clean;
uint8_t update = 0;
sw_tpd_next_to_clean = (uint16_t)atomic_read(&tpd_ring->next_to_clean);
cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
tx_packet_desc_t* tpd;
update = 1;
tpd = AT_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
buffer_info = &tpd_ring->buffer_info[sw_tpd_next_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -