|
@@ -605,36 +605,87 @@ adjust_head:
|
|
static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
|
|
static int bfin_mac_hard_start_xmit(struct sk_buff *skb,
|
|
struct net_device *dev)
|
|
struct net_device *dev)
|
|
{
|
|
{
|
|
- unsigned int data;
|
|
|
|
|
|
+ u16 *data;
|
|
|
|
|
|
current_tx_ptr->skb = skb;
|
|
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);
|
|
|
|
-
|
|
|
|
|
|
+ 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 {
|
|
} 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);
|
|
|
|
|
|
+ /*
|
|
|
|
+ * 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 */
|
|
/* enable this packet's dma */
|