예제 #1
0
static void smc_tx(struct net_device *dev)
{
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;
	unsigned int saved_packet, packet_no, tx_status, pkt_len;

	DBG(3, "%s: %s\n", dev->name, __func__);

	
	packet_no = SMC_GET_TXFIFO(lp);
	if (unlikely(packet_no & TXFIFO_TEMPTY)) {
		PRINTK("%s: smc_tx with nothing on FIFO.\n", dev->name);
		return;
	}

	
	saved_packet = SMC_GET_PN(lp);
	SMC_SET_PN(lp, packet_no);

	
	SMC_SET_PTR(lp, PTR_AUTOINC | PTR_READ);
	SMC_GET_PKT_HDR(lp, tx_status, pkt_len);
	DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
		dev->name, tx_status, packet_no);

	if (!(tx_status & ES_TX_SUC))
		dev->stats.tx_errors++;

	if (tx_status & ES_LOSTCARR)
		dev->stats.tx_carrier_errors++;

	if (tx_status & (ES_LATCOL | ES_16COL)) {
		PRINTK("%s: %s occurred on last xmit\n", dev->name,
		       (tx_status & ES_LATCOL) ?
			"late collision" : "too many collisions");
		dev->stats.tx_window_errors++;
		if (!(dev->stats.tx_window_errors & 63) && net_ratelimit()) {
			printk(KERN_INFO "%s: unexpectedly large number of "
			       "bad collisions. Please check duplex "
			       "setting.\n", dev->name);
		}
	}

	
	SMC_WAIT_MMU_BUSY(lp);
	SMC_SET_MMU_CMD(lp, MC_FREEPKT);

	
	SMC_WAIT_MMU_BUSY(lp);
	SMC_SET_PN(lp, saved_packet);

	
	SMC_SELECT_BANK(lp, 0);
	SMC_SET_TCR(lp, lp->tcr_cur_mode);
	SMC_SELECT_BANK(lp, 2);
}
예제 #2
0
static void smc_hardware_send_pkt(unsigned long data)
{
	struct net_device *dev = (struct net_device *)data;
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;
	struct sk_buff *skb;
	unsigned int packet_no, len;
	unsigned char *buf;
	unsigned long flags;

	DBG(3, "%s: %s\n", dev->name, __func__);

	if (!smc_special_trylock(&lp->lock, flags)) {
		netif_stop_queue(dev);
		tasklet_schedule(&lp->tx_task);
		return;
	}

	skb = lp->pending_tx_skb;
	if (unlikely(!skb)) {
		smc_special_unlock(&lp->lock, flags);
		return;
	}
	lp->pending_tx_skb = NULL;

	packet_no = SMC_GET_AR(lp);
	if (unlikely(packet_no & AR_FAILED)) {
		printk("%s: Memory allocation failed.\n", dev->name);
		dev->stats.tx_errors++;
		dev->stats.tx_fifo_errors++;
		smc_special_unlock(&lp->lock, flags);
		goto done;
	}

	
	SMC_SET_PN(lp, packet_no);
	SMC_SET_PTR(lp, PTR_AUTOINC);

	buf = skb->data;
	len = skb->len;
	DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n",
		dev->name, packet_no, len, len, buf);
	PRINT_PKT(buf, len);

	
	SMC_PUT_PKT_HDR(lp, 0, len + 6);

	
	SMC_PUSH_DATA(lp, buf, len & ~1);

	
	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));

	
	if (THROTTLE_TX_PKTS)
		netif_stop_queue(dev);

	
	SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
	smc_special_unlock(&lp->lock, flags);

	dev->trans_start = jiffies;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += len;

	SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT);

done:	if (!THROTTLE_TX_PKTS)
		netif_wake_queue(dev);

	dev_kfree_skb(skb);
}
예제 #3
0
/*
 * This is called to actually send a packet to the chip.
 */
static void smc_hardware_send_pkt(unsigned long data)
{
	struct net_device *dev = (struct net_device *)data;
	struct smc_local *lp = netdev_priv(dev);
	void __iomem *ioaddr = lp->base;
	struct sk_buff *skb;
	unsigned int packet_no, len;
	unsigned char *buf;
	unsigned long flags;

	DBG(3, "%s: %s\n", dev->name, __func__);

	if (!smc_special_trylock(&lp->lock, flags)) {
		netif_stop_queue(dev);
		tasklet_schedule(&lp->tx_task);
		return;
	}

	skb = lp->pending_tx_skb;
	if (unlikely(!skb)) {
		smc_special_unlock(&lp->lock, flags);
		return;
	}
	lp->pending_tx_skb = NULL;

	packet_no = SMC_GET_AR(lp);
	if (unlikely(packet_no & AR_FAILED)) {
		printk("%s: Memory allocation failed.\n", dev->name);
		dev->stats.tx_errors++;
		dev->stats.tx_fifo_errors++;
		smc_special_unlock(&lp->lock, flags);
		goto done;
	}

	/* point to the beginning of the packet */
	SMC_SET_PN(lp, packet_no);
	SMC_SET_PTR(lp, PTR_AUTOINC);

	buf = skb->data;
	len = skb->len;
	DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n",
		dev->name, packet_no, len, len, buf);
	PRINT_PKT(buf, len);

	/*
	 * Send the packet length (+6 for status words, length, and ctl.
	 * The card will pad to 64 bytes with zeroes if packet is too small.
	 */
	SMC_PUT_PKT_HDR(lp, 0, len + 6);

	/* send the actual data */
	SMC_PUSH_DATA(lp, buf, len & ~1);

	/* Send final ctl word with the last byte if there is one */
	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp));

	/*
	 * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
	 * have the effect of having at most one packet queued for TX
	 * in the chip's memory at all time.
	 *
	 * If THROTTLE_TX_PKTS is not set then the queue is stopped only
	 * when memory allocation (MC_ALLOC) does not succeed right away.
	 */
	if (THROTTLE_TX_PKTS)
		netif_stop_queue(dev);

	/* queue the packet for TX */
	SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
	smc_special_unlock(&lp->lock, flags);

	dev->trans_start = jiffies;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += len;

	SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT);

done:	if (!THROTTLE_TX_PKTS)
		netif_wake_queue(dev);

	dev_kfree_skb(skb);
}