Пример #1
0
static int bfin_EMAC_send(struct eth_device *dev, void *packet, int length)
{
	int i;
	int result = 0;
	unsigned int *buf;
	buf = (unsigned int *)packet;

	if (length <= 0) {
		printf("Ethernet: bad packet size: %d\n", length);
		goto out;
	}

	if (bfin_read_DMA2_IRQ_STATUS() & DMA_ERR) {
		printf("Ethernet: tx DMA error\n");
		goto out;
	}

	for (i = 0; (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN); ++i) {
		if (i > TOUT_LOOP) {
			puts("Ethernet: tx time out\n");
			goto out;
		}
	}
	txbuf[txIdx]->FrmData->NoBytes = length;
	memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length);
	txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData;
	bfin_write_DMA2_NEXT_DESC_PTR(txbuf[txIdx]->Dma);
	bfin_write_DMA2_CONFIG(txdmacfg.data);
	bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);

	for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) {
		if (i > TOUT_LOOP) {
			puts("Ethernet: tx error\n");
			goto out;
		}
	}
	result = txbuf[txIdx]->StatusWord;
	txbuf[txIdx]->StatusWord = 0;
	if ((txIdx + 1) >= TX_BUF_CNT)
		txIdx = 0;
	else
		txIdx++;
 out:
	debug("BFIN EMAC send: length = %d\n", length);
	return result;
}
Пример #2
0
static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
				struct net_device *dev)
{
	unsigned int data;

	current_tx_ptr->skb = skb;

	/*
	 * Is skb->data always 16-bit aligned?
	 * Do we need to memcpy((char *)(tail->packet + 2), skb->data, len)?
	 */
	if ((((unsigned int)(skb->data)) & 0x02) == 2) {
		/* move skb->data to current_tx_ptr payload */
		data = (unsigned int)(skb->data) - 2;
		*((unsigned short *)data) = (unsigned short)(skb->len);
		current_tx_ptr->desc_a.start_addr = (unsigned long)data;
		/* this is important! */
		blackfin_dcache_flush_range(data, (data + (skb->len)) + 2);

	} else {
		*((unsigned short *)(current_tx_ptr->packet)) =
		    (unsigned short)(skb->len);
		memcpy((char *)(current_tx_ptr->packet + 2), skb->data,
		       (skb->len));
		current_tx_ptr->desc_a.start_addr =
		    (unsigned long)current_tx_ptr->packet;
		if (current_tx_ptr->status.status_word != 0)
			current_tx_ptr->status.status_word = 0;
		blackfin_dcache_flush_range((unsigned int)current_tx_ptr->
					    packet,
					    (unsigned int)(current_tx_ptr->
							   packet + skb->len) +
					    2);
	}

	/* enable this packet's dma */
	current_tx_ptr->desc_a.config |= DMAEN;

	/* tx dma is running, just return */
	if (bfin_read_DMA2_IRQ_STATUS() & 0x08)
		goto out;

	/* tx dma is not running */
	bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
	/* dma enabled, read from memory, size is 6 */
	bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config);
	/* Turn on the EMAC tx */
	bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);

out:
	adjust_tx_list();
	current_tx_ptr = current_tx_ptr->next;
	dev->trans_start = jiffies;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += (skb->len);
	return 0;
}
Пример #3
0
static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
				struct net_device *dev)
{
	u16 *data;
	u32 data_align = (unsigned long)(skb->data) & 0x3;
	current_tx_ptr->skb = skb;

	if (data_align == 0x2) {
		/* move skb->data to current_tx_ptr payload */
		data = (u16 *)(skb->data) - 1;
				*data = (u16)(skb->len);
		current_tx_ptr->desc_a.start_addr = (u32)data;
		/* this is important! */
		blackfin_dcache_flush_range((u32)data,
				(u32)((u8 *)data + skb->len + 4));
	} else {
		*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
		memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
			skb->len);
		current_tx_ptr->desc_a.start_addr =
			(u32)current_tx_ptr->packet;
		if (current_tx_ptr->status.status_word != 0)
			current_tx_ptr->status.status_word = 0;
		blackfin_dcache_flush_range(
			(u32)current_tx_ptr->packet,
			(u32)(current_tx_ptr->packet + skb->len + 2));
	}

	/* make sure the internal data buffers in the core are drained
	 * so that the DMA descriptors are completely written when the
	 * DMA engine goes to fetch them below
	 */
	SSYNC();

	/* enable this packet's dma */
	current_tx_ptr->desc_a.config |= DMAEN;

	/* tx dma is running, just return */
	if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)
		goto out;

	/* tx dma is not running */
	bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
	/* dma enabled, read from memory, size is 6 */
	bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config);
	/* Turn on the EMAC tx */
	bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);

out:
	adjust_tx_list();
	current_tx_ptr = current_tx_ptr->next;
	dev->trans_start = jiffies;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += (skb->len);
	return NETDEV_TX_OK;
}
Пример #4
0
static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
				struct net_device *dev)
{
	u16 *data;
	u32 data_align = (unsigned long)(skb->data) & 0x3;
	current_tx_ptr->skb = skb;

	if (data_align == 0x2) {
		
		data = (u16 *)(skb->data) - 1;
				*data = (u16)(skb->len);
		current_tx_ptr->desc_a.start_addr = (u32)data;
		
		blackfin_dcache_flush_range((u32)data,
				(u32)((u8 *)data + skb->len + 4));
	} else {
		*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
		memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
			skb->len);
		current_tx_ptr->desc_a.start_addr =
			(u32)current_tx_ptr->packet;
		if (current_tx_ptr->status.status_word != 0)
			current_tx_ptr->status.status_word = 0;
		blackfin_dcache_flush_range(
			(u32)current_tx_ptr->packet,
			(u32)(current_tx_ptr->packet + skb->len + 2));
	}

	
	SSYNC();

	
	current_tx_ptr->desc_a.config |= DMAEN;

	
	if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)
		goto out;

	
	bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
	
	bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config);
	
	bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);

out:
	adjust_tx_list();
	current_tx_ptr = current_tx_ptr->next;
	dev->trans_start = jiffies;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += (skb->len);
	return NETDEV_TX_OK;
}
Пример #5
0
static void adjust_tx_list(void)
{
	int timeout_cnt = MAX_TIMEOUT_CNT;

	if (tx_list_head->status.status_word != 0
	    && current_tx_ptr != tx_list_head) {
		goto adjust_head;	/* released something, just return; */
	}

	/*
	 * if nothing released, check wait condition
	 * current's next can not be the head,
	 * otherwise the dma will not stop as we want
	 */
	if (current_tx_ptr->next->next == tx_list_head) {
		while (tx_list_head->status.status_word == 0) {
			udelay(10);
			if (tx_list_head->status.status_word != 0
			    || !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) {
				goto adjust_head;
			}
			if (timeout_cnt-- < 0) {
				printk(KERN_ERR DRV_NAME
				": wait for adjust tx list head timeout\n");
				break;
			}
		}
		if (tx_list_head->status.status_word != 0) {
			goto adjust_head;
		}
	}

	return;

adjust_head:
	do {
		tx_list_head->desc_a.config &= ~DMAEN;
		tx_list_head->status.status_word = 0;
		if (tx_list_head->skb) {
			dev_kfree_skb(tx_list_head->skb);
			tx_list_head->skb = NULL;
		} else {
			printk(KERN_ERR DRV_NAME
			       ": no sk_buff in a transmitted frame!\n");
		}
		tx_list_head = tx_list_head->next;
	} while (tx_list_head->status.status_word != 0
		 && current_tx_ptr != tx_list_head);
	return;

}
Пример #6
0
static void adjust_tx_list(void)
{
	int timeout_cnt = MAX_TIMEOUT_CNT;

	if (tx_list_head->status.status_word != 0
	    && current_tx_ptr != tx_list_head) {
		goto adjust_head;	
	}

	
	if (current_tx_ptr->next->next == tx_list_head) {
		while (tx_list_head->status.status_word == 0) {
			udelay(10);
			if (tx_list_head->status.status_word != 0
			    || !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) {
				goto adjust_head;
			}
			if (timeout_cnt-- < 0) {
				printk(KERN_ERR DRV_NAME
				": wait for adjust tx list head timeout\n");
				break;
			}
		}
		if (tx_list_head->status.status_word != 0) {
			goto adjust_head;
		}
	}

	return;

adjust_head:
	do {
		tx_list_head->desc_a.config &= ~DMAEN;
		tx_list_head->status.status_word = 0;
		if (tx_list_head->skb) {
			dev_kfree_skb(tx_list_head->skb);
			tx_list_head->skb = NULL;
		} else {
			printk(KERN_ERR DRV_NAME
			       ": no sk_buff in a transmitted frame!\n");
		}
		tx_list_head = tx_list_head->next;
	} while (tx_list_head->status.status_word != 0
		 && current_tx_ptr != tx_list_head);
	return;

}
static void tx_reclaim_skb(struct bfin_mac_local *lp)
{
	int timeout_cnt = MAX_TIMEOUT_CNT;

	if (tx_list_head->status.status_word != 0)
		_tx_reclaim_skb();

	if (current_tx_ptr->next == tx_list_head) {
		while (tx_list_head->status.status_word == 0) {
			
			udelay(10);
			
			if (!(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN))
				break;
			if (timeout_cnt-- < 0)
				break;
		}

		if (timeout_cnt >= 0)
			_tx_reclaim_skb();
		else
			netif_stop_queue(lp->ndev);
	}

	if (current_tx_ptr->next != tx_list_head &&
		netif_queue_stopped(lp->ndev))
		netif_wake_queue(lp->ndev);

	if (tx_list_head != current_tx_ptr) {
		
		if (netif_queue_stopped(lp->ndev))
			lp->tx_reclaim_timer.expires =
				jiffies + (TX_RECLAIM_JIFFIES >> 4);
		else
			lp->tx_reclaim_timer.expires =
				jiffies + TX_RECLAIM_JIFFIES;

		mod_timer(&lp->tx_reclaim_timer,
			lp->tx_reclaim_timer.expires);
	}
Пример #8
0
static void tx_reclaim_skb(struct bfin_mac_local *lp)
{
	int timeout_cnt = MAX_TIMEOUT_CNT;

	if (tx_list_head->status.status_word != 0)
		_tx_reclaim_skb();

	if (current_tx_ptr->next == tx_list_head) {
		while (tx_list_head->status.status_word == 0) {
			/* slow down polling to avoid too many queue stop. */
			udelay(10);
			/* reclaim skb if DMA is not running. */
			if (!(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN))
				break;
			if (timeout_cnt-- < 0)
				break;
		}

		if (timeout_cnt >= 0)
			_tx_reclaim_skb();
		else
			netif_stop_queue(lp->ndev);
	}

	if (current_tx_ptr->next != tx_list_head &&
		netif_queue_stopped(lp->ndev))
		netif_wake_queue(lp->ndev);

	if (tx_list_head != current_tx_ptr) {
		/* shorten the timer interval if tx queue is stopped */
		if (netif_queue_stopped(lp->ndev))
			lp->tx_reclaim_timer.expires =
				jiffies + (TX_RECLAIM_JIFFIES >> 4);
		else
			lp->tx_reclaim_timer.expires =
				jiffies + TX_RECLAIM_JIFFIES;

		mod_timer(&lp->tx_reclaim_timer,
			lp->tx_reclaim_timer.expires);
	}
Пример #9
0
static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
				struct net_device *dev)
{
	u16 *data;
	u32 data_align = (unsigned long)(skb->data) & 0x3;
	union skb_shared_tx *shtx = skb_tx(skb);

	current_tx_ptr->skb = skb;

	if (data_align == 0x2) {
		/* move skb->data to current_tx_ptr payload */
		data = (u16 *)(skb->data) - 1;
		*data = (u16)(skb->len);
		/*
		 * When transmitting an Ethernet packet, the PTP_TSYNC module requires
		 * a DMA_Length_Word field associated with the packet. The lower 12 bits
		 * of this field are the length of the packet payload in bytes and the higher
		 * 4 bits are the timestamping enable field.
		 */
		if (shtx->hardware)
			*data |= 0x1000;

		current_tx_ptr->desc_a.start_addr = (u32)data;
		/* this is important! */
		blackfin_dcache_flush_range((u32)data,
				(u32)((u8 *)data + skb->len + 4));
	} else {
		*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
		/* enable timestamping for the sent packet */
		if (shtx->hardware)
			*((u16 *)(current_tx_ptr->packet)) |= 0x1000;
		memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
			skb->len);
		current_tx_ptr->desc_a.start_addr =
			(u32)current_tx_ptr->packet;
		if (current_tx_ptr->status.status_word != 0)
			current_tx_ptr->status.status_word = 0;
		blackfin_dcache_flush_range(
			(u32)current_tx_ptr->packet,
			(u32)(current_tx_ptr->packet + skb->len + 2));
	}

	/* make sure the internal data buffers in the core are drained
	 * so that the DMA descriptors are completely written when the
	 * DMA engine goes to fetch them below
	 */
	SSYNC();

	/* enable this packet's dma */
	current_tx_ptr->desc_a.config |= DMAEN;

	/* tx dma is running, just return */
	if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)
		goto out;

	/* tx dma is not running */
	bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
	/* dma enabled, read from memory, size is 6 */
	bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config);
	/* Turn on the EMAC tx */
	bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);

out:
	adjust_tx_list();

	bfin_tx_hwtstamp(dev, skb);

	current_tx_ptr = current_tx_ptr->next;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += (skb->len);
	return NETDEV_TX_OK;
}
Пример #10
0
static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
				struct net_device *dev)
{
	u16 *data;

	current_tx_ptr->skb = skb;

	if (ANOMALY_05000285) {
		/*
		 * TXDWA feature is not avaible to older revision < 0.3 silicon
		 * of BF537
		 *
		 * Only if data buffer is ODD WORD alignment, we do not
		 * need to memcpy
		 */
		u32 data_align = (u32)(skb->data) & 0x3;
		if (data_align == 0x2) {
			/* move skb->data to current_tx_ptr payload */
			data = (u16 *)(skb->data) - 1;
			*data = (u16)(skb->len);
			current_tx_ptr->desc_a.start_addr = (u32)data;
			/* this is important! */
			blackfin_dcache_flush_range((u32)data,
					(u32)((u8 *)data + skb->len + 4));
		} else {
			*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
			memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
				skb->len);
			current_tx_ptr->desc_a.start_addr =
				(u32)current_tx_ptr->packet;
			if (current_tx_ptr->status.status_word != 0)
				current_tx_ptr->status.status_word = 0;
			blackfin_dcache_flush_range(
				(u32)current_tx_ptr->packet,
				(u32)(current_tx_ptr->packet + skb->len + 2));
		}
	} else {
		/*
		 * TXDWA feature is avaible to revision < 0.3 silicon of
		 * BF537 and always avaible to BF52x
		 */
		u32 data_align = (u32)(skb->data) & 0x3;
		if (data_align == 0x0) {
			u16 sysctl = bfin_read_EMAC_SYSCTL();
			sysctl |= TXDWA;
			bfin_write_EMAC_SYSCTL(sysctl);

			/* move skb->data to current_tx_ptr payload */
			data = (u16 *)(skb->data) - 2;
			*data = (u16)(skb->len);
			current_tx_ptr->desc_a.start_addr = (u32)data;
			/* this is important! */
			blackfin_dcache_flush_range(
					(u32)data,
					(u32)((u8 *)data + skb->len + 4));
		} else if (data_align == 0x2) {
			u16 sysctl = bfin_read_EMAC_SYSCTL();
			sysctl &= ~TXDWA;
			bfin_write_EMAC_SYSCTL(sysctl);

			/* move skb->data to current_tx_ptr payload */
			data = (u16 *)(skb->data) - 1;
			*data = (u16)(skb->len);
			current_tx_ptr->desc_a.start_addr = (u32)data;
			/* this is important! */
			blackfin_dcache_flush_range(
					(u32)data,
					(u32)((u8 *)data + skb->len + 4));
		} else {
			u16 sysctl = bfin_read_EMAC_SYSCTL();
			sysctl &= ~TXDWA;
			bfin_write_EMAC_SYSCTL(sysctl);

			*((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len);
			memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data,
				skb->len);
			current_tx_ptr->desc_a.start_addr =
				(u32)current_tx_ptr->packet;
			if (current_tx_ptr->status.status_word != 0)
				current_tx_ptr->status.status_word = 0;
			blackfin_dcache_flush_range(
				(u32)current_tx_ptr->packet,
				(u32)(current_tx_ptr->packet + skb->len + 2));
		}
	}

	/* enable this packet's dma */
	current_tx_ptr->desc_a.config |= DMAEN;

	/* tx dma is running, just return */
	if (bfin_read_DMA2_IRQ_STATUS() & 0x08)
		goto out;

	/* tx dma is not running */
	bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a));
	/* dma enabled, read from memory, size is 6 */
	bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config);
	/* Turn on the EMAC tx */
	bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE);

out:
	adjust_tx_list();
	current_tx_ptr = current_tx_ptr->next;
	dev->trans_start = jiffies;
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += (skb->len);
	return 0;
}