static int eth_close(struct net_device *dev) { struct port *port = netdev_priv(dev); struct msg msg; int buffs = RX_DESCS; /* allocated RX buffers */ int i; ports_open--; qmgr_disable_irq(port->plat->rxq); napi_disable(&port->napi); netif_stop_queue(dev); while (queue_get_desc(RXFREE_QUEUE(port->id), port, 0) >= 0) buffs--; memset(&msg, 0, sizeof(msg)); msg.cmd = NPE_SETLOOPBACK_MODE; msg.eth_id = port->id; msg.byte3 = 1; if (npe_send_recv_message(port->npe, &msg, "ETH_ENABLE_LOOPBACK")) printk(KERN_CRIT "%s: unable to enable loopback\n", dev->name); i = 0; do { /* drain RX buffers */ while (queue_get_desc(port->plat->rxq, port, 0) >= 0) buffs--; if (!buffs) break; if (qmgr_stat_empty(TX_QUEUE(port->id))) { /* we have to inject some packet */ struct desc *desc; u32 phys; int n = queue_get_desc(port->plat->txreadyq, port, 1); BUG_ON(n < 0); desc = tx_desc_ptr(port, n); phys = tx_desc_phys(port, n); desc->buf_len = desc->pkt_len = 1; wmb(); queue_put_desc(TX_QUEUE(port->id), phys, desc); } udelay(1); } while (++i < MAX_CLOSE_WAIT); if (buffs) printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)" " left in NPE\n", dev->name, buffs); #if DEBUG_CLOSE if (!buffs) printk(KERN_DEBUG "Draining RX queue took %i cycles\n", i); #endif buffs = TX_DESCS; while (queue_get_desc(TX_QUEUE(port->id), port, 1) >= 0) buffs--; /* cancel TX */ i = 0; do { while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0) buffs--; if (!buffs) break; } while (++i < MAX_CLOSE_WAIT); if (buffs) printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) " "left in NPE\n", dev->name, buffs); #if DEBUG_CLOSE if (!buffs) printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i); #endif msg.byte3 = 0; if (npe_send_recv_message(port->npe, &msg, "ETH_DISABLE_LOOPBACK")) printk(KERN_CRIT "%s: unable to disable loopback\n", dev->name); phy_stop(port->phydev); if (!ports_open) qmgr_disable_irq(TXDONE_QUEUE); destroy_queues(port); release_queues(port); return 0; }
static int eth_open(struct net_device *dev) { struct port *port = netdev_priv(dev); struct npe *npe = port->npe; struct msg msg; int i, err; if (!npe_running(npe)) { err = npe_load_firmware(npe, npe_name(npe), &dev->dev); if (err) return err; if (npe_recv_message(npe, &msg, "ETH_GET_STATUS")) { printk(KERN_ERR "%s: %s not responding\n", dev->name, npe_name(npe)); return -EIO; } port->firmware[0] = msg.byte4; port->firmware[1] = msg.byte5; port->firmware[2] = msg.byte6; port->firmware[3] = msg.byte7; } memset(&msg, 0, sizeof(msg)); msg.cmd = NPE_VLAN_SETRXQOSENTRY; msg.eth_id = port->id; msg.byte5 = port->plat->rxq | 0x80; msg.byte7 = port->plat->rxq << 4; for (i = 0; i < 8; i++) { msg.byte3 = i; if (npe_send_recv_message(port->npe, &msg, "ETH_SET_RXQ")) return -EIO; } msg.cmd = NPE_EDB_SETPORTADDRESS; msg.eth_id = PHYSICAL_ID(port->id); msg.byte2 = dev->dev_addr[0]; msg.byte3 = dev->dev_addr[1]; msg.byte4 = dev->dev_addr[2]; msg.byte5 = dev->dev_addr[3]; msg.byte6 = dev->dev_addr[4]; msg.byte7 = dev->dev_addr[5]; if (npe_send_recv_message(port->npe, &msg, "ETH_SET_MAC")) return -EIO; memset(&msg, 0, sizeof(msg)); msg.cmd = NPE_FW_SETFIREWALLMODE; msg.eth_id = port->id; if (npe_send_recv_message(port->npe, &msg, "ETH_SET_FIREWALL_MODE")) return -EIO; if ((err = request_queues(port)) != 0) return err; if ((err = init_queues(port)) != 0) { destroy_queues(port); release_queues(port); return err; } port->speed = 0; /* force "link up" message */ phy_start(port->phydev); for (i = 0; i < ETH_ALEN; i++) __raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]); __raw_writel(0x08, &port->regs->random_seed); __raw_writel(0x12, &port->regs->partial_empty_threshold); __raw_writel(0x30, &port->regs->partial_full_threshold); __raw_writel(0x08, &port->regs->tx_start_bytes); __raw_writel(0x15, &port->regs->tx_deferral); __raw_writel(0x08, &port->regs->tx_2part_deferral[0]); __raw_writel(0x07, &port->regs->tx_2part_deferral[1]); __raw_writel(0x80, &port->regs->slot_time); __raw_writel(0x01, &port->regs->int_clock_threshold); /* Populate queues with buffers, no failure after this point */ for (i = 0; i < TX_DESCS; i++) queue_put_desc(port->plat->txreadyq, tx_desc_phys(port, i), tx_desc_ptr(port, i)); for (i = 0; i < RX_DESCS; i++) queue_put_desc(RXFREE_QUEUE(port->id), rx_desc_phys(port, i), rx_desc_ptr(port, i)); __raw_writel(TX_CNTRL1_RETRIES, &port->regs->tx_control[1]); __raw_writel(DEFAULT_TX_CNTRL0, &port->regs->tx_control[0]); __raw_writel(0, &port->regs->rx_control[1]); __raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]); napi_enable(&port->napi); eth_set_mcast_list(dev); netif_start_queue(dev); qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY, eth_rx_irq, dev); if (!ports_open) { qmgr_set_irq(TXDONE_QUEUE, QUEUE_IRQ_SRC_NOT_EMPTY, eth_txdone_irq, NULL); qmgr_enable_irq(TXDONE_QUEUE); } ports_open++; /* we may already have RX data, enables IRQ */ napi_schedule(&port->napi); return 0; }
static void queue_out_deinit(struct module *m) { struct queue_out_priv *priv = get_priv(m); release_queues(priv->port, m, PACKET_DIR_OUT, &priv->qid, 1); }