pasemi_mac: Patches for 2.6.24
Subsystems (3)
cover pasemi_mac: Patches for 2.6.24
Hi,
This series of patches go on top of the previous fixes that were sent out and picked up.
It's a series of mostly feature-related changes, but also a couple of bugfixes:
[1/11] pasemi_mac: basic error checking
[2/11] pasemi_mac: fix bug in receive buffer dma mapping [3/11] pasemi_mac: rework ring management
[4/11] pasemi_mac: implement sg support
[5/11] pasemi_mac: workaround for erratum 5971 [6/11] pasemi_mac: add local skb alignment
[7/11] pasemi_mac: further performance tweaks [8/11] pasemi_mac: update todo list
[9/11] pasemi_mac: clear out old errors on interface open [10/11] pasemi_mac: use buffer index pointer in clean_rx() [11/11] pasemi_mac: enable iommu support
Thanks,
-Olof
PATCH 1/11 pasemi_mac: basic error checking
pasemi_mac: basic error checking
Add some rudimentary error checking to pasemi_mac.
drivers/net/pasemi_mac.c +41 -5
@@ -445,6 +445,38 @@ static void pasemi_mac_restart_tx_intr(s } +static inline void pasemi_mac_rx_error (struct pasemi_mac *mac,u64 macrx) +{ +unsigned int rcmdsta, ccmdsta; + +if (!netif_msg_rx_err (mac)) +return ; + + rcmdsta =read_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if)); + ccmdsta =read_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch)); + +printk (KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n" , + macrx, *mac->rx_status); + +printk (KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n" , + rcmdsta, ccmdsta); +} + +static inline void pasemi_mac_tx_error (struct pasemi_mac *mac,u64 mactx) +{ +unsigned int cmdsta; + +if (!netif_msg_tx_err (mac)) +return ; + + cmdsta =read_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch)); + +printk (KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, " \ +"tx status 0x%016lx\n" , mactx, *mac->tx_status); + +printk (KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n" , cmdsta); +} +static int pasemi_mac_clean_rx (struct pasemi_mac *mac,int limit) {unsigned int n;
@@ -468,10 +500,13 @@ static int pasemi_mac_clean_rx(struct paprefetchw (dp); macrx = dp->macrx; +if ((macrx &XCT_MACRX_E ) || + (*mac->rx_status &PAS_STATUS_ERROR )) +pasemi_mac_rx_error (mac, macrx); +if (!(macrx &XCT_MACRX_O ))break ; - info =NULL ;/* We have to scan for our skb since there's no way
@@ -563,6 +598,10 @@ restart:for (i = start; i < limit; i++) { dp = &TX_DESC (mac, i); +if ((dp->mactx &XCT_MACTX_E ) || + (*mac->tx_status &PAS_STATUS_ERROR )) +pasemi_mac_tx_error (mac, dp->mactx); +if (unlikely (dp->mactx &XCT_MACTX_O ))/* Not yet transmitted */ break ;
@@ -607,9 +646,6 @@ static irqreturn_t pasemi_mac_rx_intr(inif (!(*mac->rx_status &PAS_STATUS_CAUSE_M ))return IRQ_NONE ; -if (*mac->rx_status &PAS_STATUS_ERROR ) -printk ("rx_status reported error\n" ); -/* Don't reset packet count so it won't fire again but clear * all others. */
@@ -1230,7 +1266,7 @@ pasemi_mac_probe(struct pci_dev *pdev, cdev_err (&mac->pdev->dev,"register_netdev failed with error %d\n" , err); goto out; - }else + } else if netif_msg_probe(mac) printk(KERN_INFO "%s: PA Semi %s: intf %d, txch %d, rxch %d, " "hw addr %s\n", dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
Re: [PATCH] [1/11] pasemi_mac: basic error checking
Quoted 5 lines · Olof Johansson
pasemi_mac: basic error checkingAdd some rudimentary error checking to
pasemi_mac.Signed-off-by Olof Johansson <[email protected]>
applied 1-10
PATCH 2/11 pasemi_mac: fix bug in receive buffer dma mapping
In reply to Olof Johanssonpasemi_mac: fix bug in receive buffer dma mapping
skb->len isn't actually set to the size of the allocated skb, so don't try to use it when figuring out how much to map.
(This hasn't surfaced as a real bug because we effectively disable translation for the interface, but it still needs fixing for the future)
drivers/net/pasemi_mac.c +1 -1
@@ -396,7 +396,7 @@ static void pasemi_mac_replenish_rx_ringif (unlikely (!skb))break ; - dma =pci_map_single (mac->dma_pdev, skb->data, skb->len, + dma =pci_map_single (mac->dma_pdev, skb->data,BUF_SIZE ,PCI_DMA_FROMDEVICE );if (unlikely (dma_mapping_error (dma))) {
PATCH 3/11 pasemi_mac: rework ring management
In reply to Olof Johanssonpasemi_mac: rework ring management
Rework ring management, switching to an opaque ring format instead of the struct-based descriptor+pointer setup, since it will be needed for SG support.
drivers/net/pasemi_mac.c +102 -109
@@ -63,10 +63,10 @@ NETIF_MSG_RX_ERR | \ NETIF_MSG_TX_ERR) -#define TX_DESC (mac, num) ((mac)->tx->desc[(num) & (TX_RING_SIZE-1)]) -#define TX_DESC_INFO (mac, num) ((mac)->tx->desc_info[(num) & (TX_RING_SIZE-1)]) -#define RX_DESC (mac, num) ((mac)->rx->desc[(num) & (RX_RING_SIZE-1)]) -#define RX_DESC_INFO (mac, num) ((mac)->rx->desc_info[(num) & (RX_RING_SIZE-1)]) +#define TX_RING (mac, num) ((mac)->tx->ring[(num) & (TX_RING_SIZE-1)]) +#define TX_RING_INFO (mac, num) ((mac)->tx->ring_info[(num) & (TX_RING_SIZE-1)]) +#define RX_RING (mac, num) ((mac)->rx->ring[(num) & (RX_RING_SIZE-1)]) +#define RX_RING_INFO (mac, num) ((mac)->rx->ring_info[(num) & (RX_RING_SIZE-1)])#define RX_BUFF (mac, num) ((mac)->rx->buffers[(num) & (RX_RING_SIZE-1)])#define RING_USED (ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
@@ -174,22 +174,21 @@ static int pasemi_mac_setup_rx_resourcesspin_lock_init (&ring->lock); ring->size =RX_RING_SIZE ; - ring->desc_info =kzalloc (sizeof (struct pasemi_mac_buffer ) * + ring->ring_info =kzalloc (sizeof (struct pasemi_mac_buffer ) *RX_RING_SIZE ,GFP_KERNEL ); -if (!ring->desc_info) - goto out_desc_info; +if (!ring->ring_info) + goto out_ring_info;/* Allocate descriptors */ - ring->desc =dma_alloc_coherent (&mac->dma_pdev->dev, -RX_RING_SIZE * -sizeof (struct pas_dma_xct_descr ), + ring->ring =dma_alloc_coherent (&mac->dma_pdev->dev, +RX_RING_SIZE *sizeof (u64), &ring->dma,GFP_KERNEL ); -if (!ring->desc) - goto out_desc; +if (!ring->ring) + goto out_ring_desc; -memset (ring->desc,0 ,RX_RING_SIZE *sizeof (struct pas_dma_xct_descr )); +memset (ring->ring,0 ,RX_RING_SIZE *sizeof (u64)); ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
@@ -203,7 +202,7 @@ static int pasemi_mac_setup_rx_resourceswrite_dma_reg (mac,PAS_DMA_RXCHAN_BASEU (chan_id),PAS_DMA_RXCHAN_BASEU_BRBH (ring->dma >>32 ) | -PAS_DMA_RXCHAN_BASEU_SIZ (RX_RING_SIZE >>2 )); +PAS_DMA_RXCHAN_BASEU_SIZ (RX_RING_SIZE >>3 ));write_dma_reg (mac,PAS_DMA_RXCHAN_CFG (chan_id),PAS_DMA_RXCHAN_CFG_HBU (2 ));
@@ -229,11 +228,11 @@ static int pasemi_mac_setup_rx_resources out_buffers:dma_free_coherent (&mac->dma_pdev->dev, -RX_RING_SIZE *sizeof (struct pas_dma_xct_descr ), - mac->rx->desc, mac->rx->dma); -out_desc: -kfree (ring->desc_info); -out_desc_info: +RX_RING_SIZE *sizeof (u64), + mac->rx->ring, mac->rx->dma); +out_ring_desc: +kfree (ring->ring_info); +out_ring_info:kfree (ring); out_ring:return -ENOMEM ;
@@ -254,25 +253,24 @@ static int pasemi_mac_setup_tx_resourcesspin_lock_init (&ring->lock); ring->size =TX_RING_SIZE ; - ring->desc_info =kzalloc (sizeof (struct pasemi_mac_buffer ) * + ring->ring_info =kzalloc (sizeof (struct pasemi_mac_buffer ) *TX_RING_SIZE ,GFP_KERNEL ); -if (!ring->desc_info) - goto out_desc_info; +if (!ring->ring_info) + goto out_ring_info;/* Allocate descriptors */ - ring->desc =dma_alloc_coherent (&mac->dma_pdev->dev, -TX_RING_SIZE * -sizeof (struct pas_dma_xct_descr ), + ring->ring =dma_alloc_coherent (&mac->dma_pdev->dev, +TX_RING_SIZE *sizeof (u64), &ring->dma,GFP_KERNEL ); -if (!ring->desc) - goto out_desc; +if (!ring->ring) + goto out_ring_desc; -memset (ring->desc,0 ,TX_RING_SIZE *sizeof (struct pas_dma_xct_descr )); +memset (ring->ring,0 ,TX_RING_SIZE *sizeof (u64));write_dma_reg (mac,PAS_DMA_TXCHAN_BASEL (chan_id),PAS_DMA_TXCHAN_BASEL_BRBL (ring->dma)); val =PAS_DMA_TXCHAN_BASEU_BRBH (ring->dma >>32 ); - val |=PAS_DMA_TXCHAN_BASEU_SIZ (TX_RING_SIZE >>2 ); + val |=PAS_DMA_TXCHAN_BASEU_SIZ (TX_RING_SIZE >>3 );write_dma_reg (mac,PAS_DMA_TXCHAN_BASEU (chan_id), val);
@@ -291,9 +289,9 @@ static int pasemi_mac_setup_tx_resourcesreturn 0 ; -out_desc: -kfree (ring->desc_info); -out_desc_info: +out_ring_desc: +kfree (ring->ring_info); +out_ring_info:kfree (ring); out_ring:return -ENOMEM ;
@@ -304,31 +302,27 @@ static void pasemi_mac_free_tx_resourcesstruct pasemi_mac *mac =netdev_priv (dev);unsigned int i;struct pasemi_mac_buffer *info; -struct pas_dma_xct_descr *dp; -for (i =0 ; i <TX_RING_SIZE ; i++) { - info = &TX_DESC_INFO (mac, i); - dp = &TX_DESC (mac, i); -if (info->dma) { -if (info->skb) { -pci_unmap_single (mac->dma_pdev, - info->dma, - info->skb->len, -PCI_DMA_TODEVICE ); -dev_kfree_skb_any (info->skb); - } - info->dma =0 ; - info->skb =NULL ; - dp->mactx =0 ; - dp->ptr =0 ; +for (i =0 ; i <TX_RING_SIZE ; i +=2 ) { + info = &TX_RING_INFO (mac, i+1 ); +if (info->dma && info->skb) { +pci_unmap_single (mac->dma_pdev, + info->dma, + info->skb->len, +PCI_DMA_TODEVICE ); +dev_kfree_skb_any (info->skb); } +TX_RING (mac, i) =0 ; +TX_RING (mac, i+1 ) =0 ; + info->dma =0 ; + info->skb =NULL ; }dma_free_coherent (&mac->dma_pdev->dev, -TX_RING_SIZE *sizeof (struct pas_dma_xct_descr ), - mac->tx->desc, mac->tx->dma); +TX_RING_SIZE *sizeof (u64), + mac->tx->ring, mac->tx->dma); -kfree (mac->tx->desc_info); +kfree (mac->tx->ring_info);kfree (mac->tx); mac->tx =NULL ; }
@@ -338,34 +332,31 @@ static void pasemi_mac_free_rx_resourcesstruct pasemi_mac *mac =netdev_priv (dev);unsigned int i;struct pasemi_mac_buffer *info; -struct pas_dma_xct_descr *dp;for (i =0 ; i <RX_RING_SIZE ; i++) { - info = &RX_DESC_INFO (mac, i); - dp = &RX_DESC (mac, i); -if (info->skb) { -if (info->dma) { -pci_unmap_single (mac->dma_pdev, - info->dma, - info->skb->len, -PCI_DMA_FROMDEVICE ); -dev_kfree_skb_any (info->skb); - } - info->dma =0 ; - info->skb =NULL ; - dp->macrx =0 ; - dp->ptr =0 ; + info = &RX_RING_INFO (mac, i); +if (info->skb && info->dma) { +pci_unmap_single (mac->dma_pdev, + info->dma, + info->skb->len, +PCI_DMA_FROMDEVICE ); +dev_kfree_skb_any (info->skb); } + info->dma =0 ; + info->skb =NULL ; } +for (i =0 ; i <RX_RING_SIZE ; i++) +RX_RING (mac, i) =0 ; +dma_free_coherent (&mac->dma_pdev->dev, -RX_RING_SIZE *sizeof (struct pas_dma_xct_descr ), - mac->rx->desc, mac->rx->dma); +RX_RING_SIZE *sizeof (u64), + mac->rx->ring, mac->rx->dma);dma_free_coherent (&mac->dma_pdev->dev,RX_RING_SIZE *sizeof (u64), mac->rx->buffers, mac->rx->buf_dma); -kfree (mac->rx->desc_info); +kfree (mac->rx->ring_info);kfree (mac->rx); mac->rx =NULL ; }
@@ -373,20 +364,22 @@ static void pasemi_mac_free_rx_resourcesstatic void pasemi_mac_replenish_rx_ring (struct net_device *dev,int limit) {struct pasemi_mac *mac =netdev_priv (dev); -unsigned int i;int start = mac->rx->next_to_fill; -int count; +unsigned int fill, count;if (limit <=0 )return ; - i = start; + fill = start;for (count =0 ; count < limit; count++) { -struct pasemi_mac_buffer *info = &RX_DESC_INFO (mac, i); -u64 *buff = &RX_BUFF (mac, i); +struct pasemi_mac_buffer *info = &RX_RING_INFO (mac, fill); +u64 *buff = &RX_BUFF (mac, fill);struct sk_buff *skb;dma_addr_t dma; +/* Entry in use? */ +WARN_ON (*buff); +/* skb might still be in there for recycle on short receives */ if (info->skb) skb = info->skb;
@@ -407,7 +400,7 @@ static void pasemi_mac_replenish_rx_ring info->skb = skb; info->dma = dma; *buff =XCT_RXB_LEN (BUF_SIZE ) |XCT_RXB_ADDR (dma); - i++; + fill++; }wmb ();
@@ -481,7 +474,6 @@ static int pasemi_mac_clean_rx(struct pa {unsigned int n;int count; -struct pas_dma_xct_descr *dp;struct pasemi_mac_buffer *info;struct sk_buff *skb;unsigned int i, len;
@@ -496,9 +488,7 @@ static int pasemi_mac_clean_rx(struct parmb (); - dp = &RX_DESC (mac, n); -prefetchw (dp); - macrx = dp->macrx; + macrx =RX_RING (mac, n);if ((macrx &XCT_MACRX_E ) || (*mac->rx_status &PAS_STATUS_ERROR ))
@@ -516,12 +506,15 @@ static int pasemi_mac_clean_rx(struct pa* interface ring. */ - dma = (dp->ptr &XCT_PTR_ADDR_M ); -for (i = n; i < (n +RX_RING_SIZE ); i++) { - info = &RX_DESC_INFO (mac, i); + dma = (RX_RING (mac, n+1 ) &XCT_PTR_ADDR_M ); +for (i = mac->rx->next_to_fill; + i < (mac->rx->next_to_fill +RX_RING_SIZE ); + i++) { + info = &RX_RING_INFO (mac, i);if (info->dma == dma)break ; } +prefetchw (info); skb = info->skb;
@@ -546,6 +539,11 @@ static int pasemi_mac_clean_rx(struct pa }else info->skb =NULL ; +/* Need to zero it out since hardware doesn't, since the +* replenish loop uses it to tell when it's done. +*/ +RX_BUFF (mac, i) =0 ; +skb_put (skb, len);if (likely ((macrx &XCT_MACRX_HTY_M ) ==XCT_MACRX_HTY_IPV4_OK )) {
@@ -561,13 +559,13 @@ static int pasemi_mac_clean_rx(struct pa skb->protocol =eth_type_trans (skb, mac->netdev);netif_receive_skb (skb); - dp->ptr =0 ; - dp->macrx =0 ; +RX_RING (mac, n) =0 ; +RX_RING (mac, n+1 ) =0 ; - n++; + n +=2 ; } - mac->rx->next_to_clean += limit - count; + mac->rx->next_to_clean = n;pasemi_mac_replenish_rx_ring (mac->netdev, limit-count);spin_unlock (&mac->rx->lock);
@@ -579,7 +577,6 @@ static int pasemi_mac_clean_tx(struct pa {int i;struct pasemi_mac_buffer *info; -struct pas_dma_xct_descr *dp;unsigned int start, count, limit;unsigned int total_count;unsigned long flags;
@@ -595,29 +592,28 @@ restart: count =0 ; -for (i = start; i < limit; i++) { - dp = &TX_DESC (mac, i); - -if ((dp->mactx &XCT_MACTX_E ) || +for (i = start; i < limit; i +=2 ) { +u64 mactx =TX_RING (mac, i); +if ((mactx &XCT_MACTX_E ) || (*mac->tx_status &PAS_STATUS_ERROR )) -pasemi_mac_tx_error (mac, dp->mactx); +pasemi_mac_tx_error (mac, mactx); -if (unlikely (dp->mactx &XCT_MACTX_O )) +if (unlikely (mactx &XCT_MACTX_O ))/* Not yet transmitted */ break ; - info = &TX_DESC_INFO (mac, i); + info = &TX_RING_INFO (mac, i+1 ); skbs[count] = info->skb; dmas[count] = info->dma; - info->skb =NULL ; info->dma =0 ; - dp->mactx =0 ; - dp->ptr =0 ; +TX_RING (mac, i) =0 ; +TX_RING (mac, i+1 ) =0 ; + count++; } - mac->tx->next_to_clean += count; + mac->tx->next_to_clean += count *2 ;spin_unlock_irqrestore (&mac->tx->lock, flags);netif_wake_queue (mac->netdev);
@@ -1001,8 +997,6 @@ static int pasemi_mac_start_tx(struct sk {struct pasemi_mac *mac =netdev_priv (dev);struct pasemi_mac_txring *txring; -struct pasemi_mac_buffer *info; -struct pas_dma_xct_descr *dp;u64 dflags, mactx, ptr;dma_addr_t map;unsigned long flags;
@@ -1038,13 +1032,13 @@ static int pasemi_mac_start_tx(struct skspin_lock_irqsave (&txring->lock, flags); -if (RING_AVAIL (txring) <=1 ) { +if (RING_AVAIL (txring) <=2 ) {spin_unlock_irqrestore (&txring->lock, flags);pasemi_mac_clean_tx (mac);pasemi_mac_restart_tx_intr (mac);spin_lock_irqsave (&txring->lock, flags); -if (RING_AVAIL (txring) <=1 ) { +if (RING_AVAIL (txring) <=2 ) {/* Still no room -- stop the queue and wait for tx * intr when there's room. */
@@ -1053,15 +1047,14 @@ static int pasemi_mac_start_tx(struct sk } } - dp = &TX_DESC (mac, txring->next_to_fill); - info = &TX_DESC_INFO (mac, txring->next_to_fill); +TX_RING (mac, txring->next_to_fill) = mactx; +TX_RING (mac, txring->next_to_fill+1 ) = ptr; + +TX_RING_INFO (mac, txring->next_to_fill+1 ).dma = map; +TX_RING_INFO (mac, txring->next_to_fill+1 ).skb = skb; - dp->mactx = mactx; - dp->ptr = ptr; - info->dma = map; - info->skb = skb; + txring->next_to_fill +=2 ; - txring->next_to_fill++; dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len;
drivers/net/pasemi_mac.h +5 -18
@@ -28,25 +28,25 @@struct pasemi_mac_txring {spinlock_t lock; -struct pas_dma_xct_descr *desc; +u64 *ring;dma_addr_t dma;unsigned int size;unsigned int next_to_fill;unsigned int next_to_clean; -struct pasemi_mac_buffer *desc_info; +struct pasemi_mac_buffer *ring_info;char irq_name[10 ];/* "eth%d tx" */ };struct pasemi_mac_rxring {spinlock_t lock; -struct pas_dma_xct_descr *desc;/* RX channel descriptor ring */ +u64 *ring;/* RX channel descriptor ring */ dma_addr_t dma;u64 *buffers;/* RX interface buffer ring */ dma_addr_t buf_dma;unsigned int size;unsigned int next_to_fill;unsigned int next_to_clean; -struct pasemi_mac_buffer *desc_info; +struct pasemi_mac_buffer *ring_info;char irq_name[10 ];/* "eth%d rx" */ };
@@ -88,7 +88,7 @@ struct pasemi_mac {char phy_id[BUS_ID_SIZE ]; }; -/* Software status descriptor (desc_info) */ +/* Software status descriptor (ring_info) */ struct pasemi_mac_buffer {struct sk_buff *skb;dma_addr_t dma;
@@ -101,20 +101,7 @@ struct pasdma_status {u64 tx_sta[20 ]; }; -/* descriptor structure */ -struct pas_dma_xct_descr { -union { -u64 mactx; -u64 macrx; - }; -union { -u64 ptr; -u64 rxb; - }; -}; -/* MAC CFG register offsets */ -enum {PAS_MAC_CFG_PCFG =0x80 ,PAS_MAC_CFG_TXP =0x98 ,
PATCH 4/11 pasemi_mac: implement sg support
In reply to Olof Johanssonpasemi_mac: implement sg support
Implement SG support for pasemi_mac
drivers/net/pasemi_mac.c +117 -46
@@ -160,6 +160,30 @@ static int pasemi_get_mac_addr(struct pareturn 0 ; } +static int pasemi_mac_unmap_tx_skb (struct pasemi_mac *mac, +struct sk_buff *skb, +dma_addr_t *dmas) +{ +int f; +int nfrags =skb_shinfo (skb)->nr_frags; + +pci_unmap_single (mac->dma_pdev, dmas[0 ],skb_headlen (skb), +PCI_DMA_TODEVICE ); + +for (f =0 ; f < nfrags; f++) { +skb_frag_t *frag = &skb_shinfo (skb)->frags[f]; + +pci_unmap_page (mac->dma_pdev, dmas[f+1 ], frag->size, +PCI_DMA_TODEVICE ); + } +dev_kfree_skb_irq (skb); + +/* Freed descriptor slot + main SKB ptr + nfrags additional ptrs, +* aligned up to a power of 2 +*/ +return (nfrags +3 ) & ~1 ; +} +static int pasemi_mac_setup_rx_resources (struct net_device *dev) {struct pasemi_mac_rxring *ring;
@@ -300,24 +324,24 @@ out_ring:static void pasemi_mac_free_tx_resources (struct net_device *dev) {struct pasemi_mac *mac =netdev_priv (dev); -unsigned int i; +unsigned int i, j;struct pasemi_mac_buffer *info; +dma_addr_t dmas[MAX_SKB_FRAGS +1 ]; +int freed; -for (i =0 ; i <TX_RING_SIZE ; i +=2 ) { +for (i =0 ; i <TX_RING_SIZE ; i += freed) { info = &TX_RING_INFO (mac, i+1 );if (info->dma && info->skb) { -pci_unmap_single (mac->dma_pdev, - info->dma, - info->skb->len, -PCI_DMA_TODEVICE ); -dev_kfree_skb_any (info->skb); - } -TX_RING (mac, i) =0 ; -TX_RING (mac, i+1 ) =0 ; - info->dma =0 ; - info->skb =NULL ; +for (j =0 ; j <=skb_shinfo (info->skb)->nr_frags; j++) + dmas[j] =TX_RING_INFO (mac, i+1 +j).dma; + freed =pasemi_mac_unmap_tx_skb (mac, info->skb, dmas); + }else + freed =2 ; } +for (i =0 ; i <TX_RING_SIZE ; i++) +TX_RING (mac, i) =0 ; +dma_free_coherent (&mac->dma_pdev->dev,TX_RING_SIZE *sizeof (u64), mac->tx->ring, mac->tx->dma);
@@ -573,27 +597,34 @@ static int pasemi_mac_clean_rx(struct pareturn count; } +/* Can't make this too large or we blow the kernel stack limits */ +#define TX_CLEAN_BATCHSIZE (128/MAX_SKB_FRAGS) +static int pasemi_mac_clean_tx (struct pasemi_mac *mac) { -int i; +int i, j;struct pasemi_mac_buffer *info; -unsigned int start, count, limit; +unsigned int start, descr_count, buf_count, limit;unsigned int total_count;unsigned long flags; -struct sk_buff *skbs[32 ]; -dma_addr_t dmas[32 ]; +struct sk_buff *skbs[TX_CLEAN_BATCHSIZE ]; +dma_addr_t dmas[TX_CLEAN_BATCHSIZE ][MAX_SKB_FRAGS +1 ]; total_count =0 ; + limit =TX_CLEAN_BATCHSIZE ; restart:spin_lock_irqsave (&mac->tx->lock, flags); start = mac->tx->next_to_clean; - limit =min (mac->tx->next_to_fill, start+32 ); - count =0 ; + buf_count =0 ; + descr_count =0 ; -for (i = start; i < limit; i +=2 ) { +for (i = start; + descr_count < limit && i < mac->tx->next_to_fill; + i += buf_count) {u64 mactx =TX_RING (mac, i); +if ((mactx &XCT_MACTX_E ) || (*mac->tx_status &PAS_STATUS_ERROR ))pasemi_mac_tx_error (mac, mactx);
@@ -603,30 +634,38 @@ restart:break ; info = &TX_RING_INFO (mac, i+1 ); - skbs[count] = info->skb; - dmas[count] = info->dma; + skbs[descr_count] = info->skb; + + buf_count =2 +skb_shinfo (info->skb)->nr_frags; +for (j =0 ; j <=skb_shinfo (info->skb)->nr_frags; j++) + dmas[descr_count][j] =TX_RING_INFO (mac, i+1 +j).dma; + info->dma =0 ;TX_RING (mac, i) =0 ;TX_RING (mac, i+1 ) =0 ; +TX_RING_INFO (mac, i+1 ).skb =0 ; +TX_RING_INFO (mac, i+1 ).dma =0 ; - - count++; +/* Since we always fill with an even number of entries, make +* sure we skip any unused one at the end as well. +*/ +if (buf_count &1 ) + buf_count++; + descr_count++; } - mac->tx->next_to_clean += count *2 ; + mac->tx->next_to_clean = i; +spin_unlock_irqrestore (&mac->tx->lock, flags);netif_wake_queue (mac->netdev); -for (i =0 ; i < count; i++) { -pci_unmap_single (mac->dma_pdev, dmas[i], - skbs[i]->len,PCI_DMA_TODEVICE ); -dev_kfree_skb_irq (skbs[i]); - } +for (i =0 ; i < descr_count; i++) +pasemi_mac_unmap_tx_skb (mac, skbs[i], dmas[i]); - total_count += count; + total_count += descr_count;/* If the batch was full, try to clean more */ -if (count ==32 ) +if (descr_count == limit) goto restart;return total_count;
@@ -997,9 +1036,11 @@ static int pasemi_mac_start_tx(struct sk {struct pasemi_mac *mac =netdev_priv (dev);struct pasemi_mac_txring *txring; -u64 dflags, mactx, ptr; -dma_addr_t map; +u64 dflags, mactx; +dma_addr_t map[MAX_SKB_FRAGS +1 ]; +unsigned int map_size[MAX_SKB_FRAGS +1 ];unsigned long flags; +int i, nfrags; dflags =XCT_MACTX_O |XCT_MACTX_ST |XCT_MACTX_SS |XCT_MACTX_CRC_PAD ;
@@ -1020,25 +1061,40 @@ static int pasemi_mac_start_tx(struct sk } } - map =pci_map_single (mac->dma_pdev, skb->data, skb->len,PCI_DMA_TODEVICE ); + nfrags =skb_shinfo (skb)->nr_frags; -if (dma_mapping_error (map)) -return NETDEV_TX_BUSY ; + map[0 ] =pci_map_single (mac->dma_pdev, skb->data,skb_headlen (skb), +PCI_DMA_TODEVICE ); + map_size[0 ] =skb_headlen (skb); +if (dma_mapping_error (map[0 ])) + goto out_err_nolock; + +for (i =0 ; i < nfrags; i++) { +skb_frag_t *frag = &skb_shinfo (skb)->frags[i]; + + map[i+1 ] =pci_map_page (mac->dma_pdev, frag->page, + frag->page_offset, frag->size, +PCI_DMA_TODEVICE ); + map_size[i+1 ] = frag->size; +if (dma_mapping_error (map[i+1 ])) { + nfrags = i; + goto out_err_nolock; + } + } mactx = dflags |XCT_MACTX_LLEN (skb->len); - ptr =XCT_PTR_LEN (skb->len) |XCT_PTR_ADDR (map); txring = mac->tx;spin_lock_irqsave (&txring->lock, flags); -if (RING_AVAIL (txring) <=2 ) { +if (RING_AVAIL (txring) <= nfrags+3 ) {spin_unlock_irqrestore (&txring->lock, flags);pasemi_mac_clean_tx (mac);pasemi_mac_restart_tx_intr (mac);spin_lock_irqsave (&txring->lock, flags); -if (RING_AVAIL (txring) <=2 ) { +if (RING_AVAIL (txring) <= nfrags+3 ) {/* Still no room -- stop the queue and wait for tx * intr when there's room. */
@@ -1048,25 +1104,40 @@ static int pasemi_mac_start_tx(struct sk }TX_RING (mac, txring->next_to_fill) = mactx; -TX_RING (mac, txring->next_to_fill+1 ) = ptr; + txring->next_to_fill++; +TX_RING_INFO (mac, txring->next_to_fill).skb = skb; +for (i =0 ; i <= nfrags; i++) { +TX_RING (mac, txring->next_to_fill+i) = +XCT_PTR_LEN (map_size[i]) |XCT_PTR_ADDR (map[i]); +TX_RING_INFO (mac, txring->next_to_fill+i).dma = map[i]; + } + +/* We have to add an even number of 8-byte entries to the ring +* even if the last one is unused. That means always an odd number +* of pointers + one mactx descriptor. +*/ +if (nfrags &1 ) + nfrags++; -TX_RING_INFO (mac, txring->next_to_fill+1 ).dma = map; -TX_RING_INFO (mac, txring->next_to_fill+1 ).skb = skb; + txring->next_to_fill += nfrags +1 ; - txring->next_to_fill +=2 ; dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len;spin_unlock_irqrestore (&txring->lock, flags); -write_dma_reg (mac,PAS_DMA_TXCHAN_INCR (mac->dma_txch),1 ); +write_dma_reg (mac,PAS_DMA_TXCHAN_INCR (mac->dma_txch), (nfrags+2 ) >>1 );return NETDEV_TX_OK ; out_err:spin_unlock_irqrestore (&txring->lock, flags); -pci_unmap_single (mac->dma_pdev, map, skb->len,PCI_DMA_TODEVICE ); +out_err_nolock: +while (nfrags--) +pci_unmap_single (mac->dma_pdev, map[nfrags], map_size[nfrags], +PCI_DMA_TODEVICE ); +return NETDEV_TX_BUSY ; }
@@ -1202,7 +1273,7 @@ pasemi_mac_probe(struct pci_dev *pdev, cnetif_napi_add (dev, &mac->napi, pasemi_mac_poll,64 ); - dev->features =NETIF_F_HW_CSUM |NETIF_F_LLTX ; + dev->features =NETIF_F_HW_CSUM |NETIF_F_LLTX |NETIF_F_SG ;/* These should come out of the device tree eventually */ mac->dma_txch = index;
PATCH 5/11 pasemi_mac: workaround for erratum 5971
In reply to Olof Johanssonpasemi_mac: workaround for erratum 5971
Implement workarounds for erratum 5971, where L2 hints aren't considered properly unless the way hint is enabled on the interface. Since L2 isn't setup to dedicate a way to headers, we need to reset the packet count by hand so it won't run out of credits.
drivers/net/pasemi_mac.c +8 -1
@@ -239,7 +239,9 @@ static int pasemi_mac_setup_rx_resources PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));write_dma_reg (mac,PAS_DMA_RXINT_CFG (mac->dma_if), -PAS_DMA_RXINT_CFG_DHL (2 )); +PAS_DMA_RXINT_CFG_DHL (3 ) | +PAS_DMA_RXINT_CFG_L2 | +PAS_DMA_RXINT_CFG_LW ); ring->next_to_fill =0 ; ring->next_to_clean =0 ;
@@ -589,6 +591,11 @@ static int pasemi_mac_clean_rx(struct pa n +=2 ; } +if (n >RX_RING_SIZE ) { +/* Errata 5971 workaround: L2 target of headers */ +write_iob_reg (mac,PAS_IOB_COM_PKTHDRCNT ,0 ); + n &= (RX_RING_SIZE -1 ); + } mac->rx->next_to_clean = n;pasemi_mac_replenish_rx_ring (mac->netdev, limit-count);
drivers/net/pasemi_mac.h +8 -0
@@ -210,6 +210,8 @@ enum {#define PAS_DMA_RXINT_CFG_DHL_S 24#define PAS_DMA_RXINT_CFG_DHL (x) (((x) << PAS_DMA_RXINT_CFG_DHL_S) & \ PAS_DMA_RXINT_CFG_DHL_M) +#define PAS_DMA_RXINT_CFG_LW 0x00200000 +#define PAS_DMA_RXINT_CFG_L2 0x00100000#define PAS_DMA_RXINT_CFG_WIF 0x00000002#define PAS_DMA_RXINT_CFG_WIL 0x00000001
@@ -315,6 +317,12 @@ enum {#define PAS_STATUS_SOFT 0x4000000000000000ull#define PAS_STATUS_INT 0x8000000000000000ull +#define PAS_IOB_COM_PKTHDRCNT 0x120 +#define PAS_IOB_COM_PKTHDRCNT_PKTHDR1_M 0x0fff0000 +#define PAS_IOB_COM_PKTHDRCNT_PKTHDR1_S 16 +#define PAS_IOB_COM_PKTHDRCNT_PKTHDR0_M 0x00000fff +#define PAS_IOB_COM_PKTHDRCNT_PKTHDR0_S 0 +#define PAS_IOB_DMA_RXCH_CFG (i) (0x1100 + (i)*4)#define PAS_IOB_DMA_RXCH_CFG_CNTTH_M 0x00000fff#define PAS_IOB_DMA_RXCH_CFG_CNTTH_S 0
PATCH 6/11 pasemi_mac: add local skb alignment
In reply to Olof Johanssonpasemi_mac: add local skb alignment
Add local SKB alignment to pasemi_mac, since ppc64 in general has it at 0 because of design flaws in some of the IBM server bridge chips. However, for PWRficient doing the unaligned copies is more expensive than doing unaligned DMA so make sure the data is aligned instead.
drivers/net/pasemi_mac.c +16 -5
@@ -37,6 +37,12 @@#include "pasemi_mac.h" +/* We have our own align, since ppc64 in general has it at 0 because +* of design flaws in some of the server bridge chips. However, for +* PWRficient doing the unaligned copies is more expensive than doing +* unaligned DMA, so make sure the data is aligned instead. +*/ +#define LOCAL_SKB_ALIGN 2/* TODO list *
@@ -409,13 +415,16 @@ static void pasemi_mac_replenish_rx_ring/* skb might still be in there for recycle on short receives */ if (info->skb) skb = info->skb; -else +else { skb =dev_alloc_skb (BUF_SIZE ); +skb_reserve (skb,LOCAL_SKB_ALIGN ); + }if (unlikely (!skb))break ; - dma =pci_map_single (mac->dma_pdev, skb->data,BUF_SIZE , + dma =pci_map_single (mac->dma_pdev, skb->data, +BUF_SIZE -LOCAL_SKB_ALIGN ,PCI_DMA_FROMDEVICE );if (unlikely (dma_mapping_error (dma))) {
@@ -553,10 +562,12 @@ static int pasemi_mac_clean_rx(struct pa len = (macrx &XCT_MACRX_LLEN_M ) >>XCT_MACRX_LLEN_S ;if (len <256 ) { -struct sk_buff *new_skb = -netdev_alloc_skb (mac->netdev, len +NET_IP_ALIGN ); +struct sk_buff *new_skb; + + new_skb =netdev_alloc_skb (mac->netdev, + len +LOCAL_SKB_ALIGN );if (new_skb) { -skb_reserve (new_skb,NET_IP_ALIGN ); +skb_reserve (new_skb,LOCAL_SKB_ALIGN );memcpy (new_skb->data, skb->data, len);/* save the skb in buffer_info as good */ skb = new_skb;
PATCH 7/11 pasemi_mac: further performance tweaks
In reply to Olof Johanssonpasemi_mac: further performance tweaks
Misc driver tweaks for pasemi_mac:
* Increase ring size (really needed mostly on 10G)
* Take out an unneeded barrier
* Move around a few prefetches and reorder a few calls
* Don't try to clean on full tx buffer, just let things take their course and stop the queue directly
* Avoid filling on the same line as the interface is working on to reduce cache line bouncing
* Avoid unneeded clearing of software state (and make the interface shutdown code handle it)
* Fix up some of the tx ring wrap logic.
drivers/net/pasemi_mac.c +47 -45
@@ -56,8 +56,8 @@/* Must be a power of two */ -#define RX_RING_SIZE 512 -#define TX_RING_SIZE 512 +#define RX_RING_SIZE 4096 +#define TX_RING_SIZE 4096#define DEFAULT_MSG_ENABLE \ (NETIF_MSG_DRV | \
@@ -336,8 +336,16 @@ static void pasemi_mac_free_tx_resourcesstruct pasemi_mac_buffer *info;dma_addr_t dmas[MAX_SKB_FRAGS +1 ];int freed; +int start, limit; -for (i =0 ; i <TX_RING_SIZE ; i += freed) { + start = mac->tx->next_to_clean; + limit = mac->tx->next_to_fill; + +/* Compensate for when fill has wrapped and clean has not */ +if (start > limit) + limit +=TX_RING_SIZE ; + +for (i = start; i < limit; i += freed) { info = &TX_RING_INFO (mac, i+1 );if (info->dma && info->skb) {for (j =0 ; j <=skb_shinfo (info->skb)->nr_frags; j++)
@@ -520,9 +528,6 @@ static int pasemi_mac_clean_rx(struct pa n = mac->rx->next_to_clean;for (count = limit; count; count--) { - -rmb (); - macrx =RX_RING (mac, n); if ((macrx & XCT_MACRX_E) ||
@@ -550,14 +555,10 @@ static int pasemi_mac_clean_rx(struct pabreak ; } -prefetchw (info); - skb = info->skb; -prefetchw (skb); - info->dma =0 ; -pci_unmap_single (mac->dma_pdev, dma, skb->len, -PCI_DMA_FROMDEVICE ); +prefetch (skb); +prefetch (&skb->data_len); len = (macrx &XCT_MACRX_LLEN_M ) >>XCT_MACRX_LLEN_S ;
@@ -576,10 +577,9 @@ static int pasemi_mac_clean_rx(struct pa }else info->skb =NULL ; -/* Need to zero it out since hardware doesn't, since the -* replenish loop uses it to tell when it's done. -*/ -RX_BUFF (mac, i) =0 ; +pci_unmap_single (mac->dma_pdev, dma, len,PCI_DMA_FROMDEVICE ); + + info->dma =0 ;skb_put (skb, len);
@@ -599,6 +599,11 @@ static int pasemi_mac_clean_rx(struct paRX_RING (mac, n) =0 ;RX_RING (mac, n+1 ) =0 ; +/* Need to zero it out since hardware doesn't, since the +* replenish loop uses it to tell when it's done. +*/ +RX_BUFF (mac, i) =0 ; + n +=2 ; }
@@ -621,27 +626,33 @@ static int pasemi_mac_clean_rx(struct pastatic int pasemi_mac_clean_tx (struct pasemi_mac *mac) {int i, j; -struct pasemi_mac_buffer *info; -unsigned int start, descr_count, buf_count, limit; +unsigned int start, descr_count, buf_count, batch_limit; +unsigned int ring_limit;unsigned int total_count;unsigned long flags;struct sk_buff *skbs[TX_CLEAN_BATCHSIZE ];dma_addr_t dmas[TX_CLEAN_BATCHSIZE ][MAX_SKB_FRAGS +1 ]; total_count =0 ; - limit =TX_CLEAN_BATCHSIZE ; + batch_limit =TX_CLEAN_BATCHSIZE ; restart:spin_lock_irqsave (&mac->tx->lock, flags); start = mac->tx->next_to_clean; + ring_limit = mac->tx->next_to_fill; + +/* Compensate for when fill has wrapped but clean has not */ +if (start > ring_limit) + ring_limit +=TX_RING_SIZE ; buf_count =0 ; descr_count =0 ;for (i = start; - descr_count < limit && i < mac->tx->next_to_fill; + descr_count < batch_limit && i < ring_limit; i += buf_count) {u64 mactx =TX_RING (mac, i); +struct sk_buff *skb;if ((mactx &XCT_MACTX_E ) || (*mac->tx_status &PAS_STATUS_ERROR ))
@@ -651,19 +662,15 @@ restart:/* Not yet transmitted */ break ; - info = &TX_RING_INFO (mac, i+1 ); - skbs[descr_count] = info->skb; + skb =TX_RING_INFO (mac, i+1 ).skb; + skbs[descr_count] = skb; - buf_count =2 +skb_shinfo (info->skb)->nr_frags; -for (j =0 ; j <=skb_shinfo (info->skb)->nr_frags; j++) + buf_count =2 +skb_shinfo (skb)->nr_frags; +for (j =0 ; j <=skb_shinfo (skb)->nr_frags; j++) dmas[descr_count][j] =TX_RING_INFO (mac, i+1 +j).dma; - - info->dma =0 ;TX_RING (mac, i) =0 ;TX_RING (mac, i+1 ) =0 ; -TX_RING_INFO (mac, i+1 ).skb =0 ; -TX_RING_INFO (mac, i+1 ).dma =0 ;/* Since we always fill with an even number of entries, make * sure we skip any unused one at the end as well.
@@ -672,7 +679,7 @@ restart: buf_count++; descr_count++; } - mac->tx->next_to_clean = i; + mac->tx->next_to_clean = i & (TX_RING_SIZE -1 );spin_unlock_irqrestore (&mac->tx->lock, flags);netif_wake_queue (mac->netdev);
@@ -683,7 +690,7 @@ restart: total_count += descr_count;/* If the batch was full, try to clean more */ -if (descr_count == limit) +if (descr_count == batch_limit) goto restart;return total_count;
@@ -1106,19 +1113,14 @@ static int pasemi_mac_start_tx(struct skspin_lock_irqsave (&txring->lock, flags); -if (RING_AVAIL (txring) <= nfrags+3 ) { -spin_unlock_irqrestore (&txring->lock, flags); -pasemi_mac_clean_tx (mac); -pasemi_mac_restart_tx_intr (mac); -spin_lock_irqsave (&txring->lock, flags); - -if (RING_AVAIL (txring) <= nfrags+3 ) { -/* Still no room -- stop the queue and wait for tx -* intr when there's room. -*/ -netif_stop_queue (dev); - goto out_err; - } +/* Avoid stepping on the same cache line that the DMA controller +* is currently about to send, so leave at least 8 words available. +* Total free space needed is mactx + fragments + 8 +*/ +if (RING_AVAIL (txring) < nfrags +10 ) { +/* no room -- stop the queue and wait for tx intr */ +netif_stop_queue (dev); + goto out_err; }TX_RING (mac, txring->next_to_fill) = mactx;
@@ -1137,8 +1139,8 @@ static int pasemi_mac_start_tx(struct skif (nfrags &1 ) nfrags++; - txring->next_to_fill += nfrags +1 ; - + txring->next_to_fill = (txring->next_to_fill + nfrags +1 ) & + (TX_RING_SIZE -1 ); dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len;
PATCH 8/11 pasemi_mac: update todo list
In reply to Olof Johanssonpasemi_mac: update todo list
Remove some stale todo items that have been taken care of. Add a couple of upcoming ones.
drivers/net/pasemi_mac.c +2 -4
@@ -46,12 +46,10 @@/* TODO list * -* - Get rid of pci_{read,write}_config(), map registers with ioremap -* for performance -* - PHY support * - Multicast support * - Large MTU support -* - Other performance improvements +* - SW LRO +* - Multiqueue RX/TX */
PATCH 9/11 pasemi_mac: clear out old errors on interface open
In reply to Olof Johanssonpasemi_mac: clear out old errors on interface open
Clear out any pending errors when an interface is brought up. Since the bits are sticky, they might be from interface shutdown time after firmware has used it, etc.
drivers/net/pasemi_mac.c +44 -13
@@ -903,16 +903,27 @@ static int pasemi_mac_open(struct net_de/* enable rx if */ write_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if), -PAS_DMA_RXINT_RCMDSTA_EN ); +PAS_DMA_RXINT_RCMDSTA_EN | +PAS_DMA_RXINT_RCMDSTA_DROPS_M | +PAS_DMA_RXINT_RCMDSTA_BP | +PAS_DMA_RXINT_RCMDSTA_OO | +PAS_DMA_RXINT_RCMDSTA_BT );/* enable rx channel */ write_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch),PAS_DMA_RXCHAN_CCMDSTA_EN | -PAS_DMA_RXCHAN_CCMDSTA_DU ); +PAS_DMA_RXCHAN_CCMDSTA_DU | +PAS_DMA_RXCHAN_CCMDSTA_OD | +PAS_DMA_RXCHAN_CCMDSTA_FD | +PAS_DMA_RXCHAN_CCMDSTA_DT );/* enable tx channel */ write_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch), -PAS_DMA_TXCHAN_TCMDSTA_EN ); +PAS_DMA_TXCHAN_TCMDSTA_EN | +PAS_DMA_TXCHAN_TCMDSTA_SZ | +PAS_DMA_TXCHAN_TCMDSTA_DB | +PAS_DMA_TXCHAN_TCMDSTA_DE | +PAS_DMA_TXCHAN_TCMDSTA_DA );pasemi_mac_replenish_rx_ring (dev,RX_RING_SIZE );
@@ -987,7 +998,7 @@ out_rx_resources:static int pasemi_mac_close (struct net_device *dev) {struct pasemi_mac *mac =netdev_priv (dev); -unsigned int stat; +unsigned int sta;int retries;if (mac->phydev) {
@@ -998,6 +1009,26 @@ static int pasemi_mac_close(struct net_dnetif_stop_queue (dev);napi_disable (&mac->napi); + sta =read_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if)); +if (sta & (PAS_DMA_RXINT_RCMDSTA_BP | +PAS_DMA_RXINT_RCMDSTA_OO | +PAS_DMA_RXINT_RCMDSTA_BT )) +printk (KERN_DEBUG "pasemi_mac: rcmdsta error: 0x%08x\n" , sta); + + sta =read_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch)); +if (sta & (PAS_DMA_RXCHAN_CCMDSTA_DU | +PAS_DMA_RXCHAN_CCMDSTA_OD | +PAS_DMA_RXCHAN_CCMDSTA_FD | +PAS_DMA_RXCHAN_CCMDSTA_DT )) +printk (KERN_DEBUG "pasemi_mac: ccmdsta error: 0x%08x\n" , sta); + + sta =read_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch)); +if (sta & (PAS_DMA_TXCHAN_TCMDSTA_SZ | +PAS_DMA_TXCHAN_TCMDSTA_DB | +PAS_DMA_TXCHAN_TCMDSTA_DE | +PAS_DMA_TXCHAN_TCMDSTA_DA )) +printk (KERN_DEBUG "pasemi_mac: tcmdsta error: 0x%08x\n" , sta); +/* Clean out any pending buffers */ pasemi_mac_clean_tx (mac);pasemi_mac_clean_rx (mac,RX_RING_SIZE );
@@ -1008,33 +1039,33 @@ static int pasemi_mac_close(struct net_dwrite_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch),PAS_DMA_RXCHAN_CCMDSTA_ST );for (retries =0 ; retries <MAX_RETRIES ; retries++) { - stat =read_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch)); -if (!(stat &PAS_DMA_TXCHAN_TCMDSTA_ACT )) + sta =read_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch)); +if (!(sta &PAS_DMA_TXCHAN_TCMDSTA_ACT ))break ;cond_resched (); } -if (stat &PAS_DMA_TXCHAN_TCMDSTA_ACT ) +if (sta &PAS_DMA_TXCHAN_TCMDSTA_ACT )dev_err (&mac->dma_pdev->dev,"Failed to stop tx channel\n" );for (retries =0 ; retries <MAX_RETRIES ; retries++) { - stat =read_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch)); -if (!(stat &PAS_DMA_RXCHAN_CCMDSTA_ACT )) + sta =read_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch)); +if (!(sta &PAS_DMA_RXCHAN_CCMDSTA_ACT ))break ;cond_resched (); } -if (stat &PAS_DMA_RXCHAN_CCMDSTA_ACT ) +if (sta &PAS_DMA_RXCHAN_CCMDSTA_ACT )dev_err (&mac->dma_pdev->dev,"Failed to stop rx channel\n" );for (retries =0 ; retries <MAX_RETRIES ; retries++) { - stat =read_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if)); -if (!(stat &PAS_DMA_RXINT_RCMDSTA_ACT )) + sta =read_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if)); +if (!(sta &PAS_DMA_RXINT_RCMDSTA_ACT ))break ;cond_resched (); } -if (stat &PAS_DMA_RXINT_RCMDSTA_ACT ) +if (sta &PAS_DMA_RXINT_RCMDSTA_ACT )dev_err (&mac->dma_pdev->dev,"Failed to stop rx interface\n" );/* Then, disable the channel. This must be done separately from
drivers/net/pasemi_mac.h +7 -0
@@ -241,6 +241,10 @@ enum {#define PAS_DMA_TXCHAN_TCMDSTA_EN 0x00000001/* Enabled */ #define PAS_DMA_TXCHAN_TCMDSTA_ST 0x00000002/* Stop interface */ #define PAS_DMA_TXCHAN_TCMDSTA_ACT 0x00010000/* Active */ +#define PAS_DMA_TXCHAN_TCMDSTA_SZ 0x00000800 +#define PAS_DMA_TXCHAN_TCMDSTA_DB 0x00000400 +#define PAS_DMA_TXCHAN_TCMDSTA_DE 0x00000200 +#define PAS_DMA_TXCHAN_TCMDSTA_DA 0x00000100#define PAS_DMA_TXCHAN_CFG (c) (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)#define PAS_DMA_TXCHAN_CFG_TY_IFACE 0x00000000/* Type = interface */ #define PAS_DMA_TXCHAN_CFG_TATTR_M 0x0000003c
@@ -283,6 +287,9 @@ enum {#define PAS_DMA_RXCHAN_CCMDSTA_ST 0x00000002/* Stop interface */ #define PAS_DMA_RXCHAN_CCMDSTA_ACT 0x00010000/* Active */ #define PAS_DMA_RXCHAN_CCMDSTA_DU 0x00020000 +#define PAS_DMA_RXCHAN_CCMDSTA_OD 0x00002000 +#define PAS_DMA_RXCHAN_CCMDSTA_FD 0x00001000 +#define PAS_DMA_RXCHAN_CCMDSTA_DT 0x00000800#define PAS_DMA_RXCHAN_CFG (c) (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE)#define PAS_DMA_RXCHAN_CFG_HBU_M 0x00000380#define PAS_DMA_RXCHAN_CFG_HBU_S 7
Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
Quoted 7 lines · Olof Johansson
pasemi_mac: clear out old errors on interface openClear out any pending errors when an interface is brought up. Since the bits are sticky, they might be from interface shutdown time after firmware has used it, etc.
Signed-off-by Olof Johansson <[email protected]>
In general, interface-open should completely reset and initialize the hardware. does pasemi_mac not do that?
Jeff
Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
Quoted 10 lines · Jeff Garzik
Quoted 6 lines · Olof Johansson
pasemi_mac: clear out old errors on interface open
Clear out any pending errors when an interface is brought up. Since the bits
are sticky, they might be from interface shutdown time after firmware has used it, etc.Signed-off-by Olof Johansson <[email protected]>In general, interface-open should completely reset and initialize the hardware. does
pasemi_macnot do that?
There's no explicit way to reset just one interface besides disabling it (which we do at close, and re-enable at open). It seems that some of the error bits are sticky across disable/enable, which is why this was needed. Also, they're RW1C, so writing 0 doesn't remove them (need to write 1 to clear).
The only other dependency from firmware at this time is the setting of mac addresses, something that will be taken care of once we allow override of them via ethtool, since we'd need to program them from the driver then no matter what. Right now we assume that firmware has programmed it.
-Olof
Re: [PATCH] [9/11] pasemi_mac: clear out old errors on interface open
Quoted 7 lines · Olof Johansson
Quoted 6 lines · Jeff Garzik
Quoted 5 lines · Olof Johansson
pasemi_mac: clear out old errors on interface open
Clear out any pending errors when an interface is brought up. Since the bits are sticky, they might be from interface shutdown time after firmware has used it, etc.Signed-off-by Olof Johansson <[email protected]>
Quoted 7 lines
Quoted 1 line
In general, interface-open should completely reset and initialize the hardware. does
pasemi_macnot do that?There's no explicit way to reset just one interface besides disabling it (which we do at close, and re-enable at open). It seems that some of the error bits are sticky across disable/enable, which is why this was needed. Also, they're RW1C, so writing 0 doesn't remove them (need to write 1 to clear).
OK just making sure, thanks.
Quoted 4 lines
The only other dependency from firmware at this time is the setting of mac addresses, something that will be taken care of once we allow override of them via ethtool, since we'd need to program them from the driver then no matter what. Right now we assume that firmware has programmed it.
Standard procedure for this is
* upon module-load, obtain the MAC address from <whatever canonical source>
* upon interface-up, program dev->dev_addr[] into chip's RX filter (aka MAC address) registers
That permits the admin to override the MAC address via ifconfig. (ethtool doesn't support that, but you basically had the right idea)
Jeff
PATCH 10/11 pasemi_mac: use buffer index pointer in clean_rx()
In reply to Olof Johanssonpasemi_mac: use buffer index pointer in clean_rx()
Use the new features in B0 for buffer ring index on the receive side. This means we no longer have to search in the ring for where the buffer came from.
Also cleanup the RX cleaning side a little, while I was at it.
Note: Pre-B0 hardware is no longer supported, and needs a pile of other workarounds that are not being submitted for mainline inclusion. So the fact that this breaks old hardware is not a problem at this time.
drivers/net/pasemi_mac.c +33 -27
@@ -243,9 +243,9 @@ static int pasemi_mac_setup_rx_resources PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));write_dma_reg (mac,PAS_DMA_RXINT_CFG (mac->dma_if), -PAS_DMA_RXINT_CFG_DHL (3 ) | -PAS_DMA_RXINT_CFG_L2 | -PAS_DMA_RXINT_CFG_LW ); +PAS_DMA_RXINT_CFG_DHL (3 ) |PAS_DMA_RXINT_CFG_L2 | +PAS_DMA_RXINT_CFG_LW |PAS_DMA_RXINT_CFG_RBP | +PAS_DMA_RXINT_CFG_HEN ); ring->next_to_fill =0 ; ring->next_to_clean =0 ;
@@ -402,13 +402,12 @@ static void pasemi_mac_free_rx_resourcesstatic void pasemi_mac_replenish_rx_ring (struct net_device *dev,int limit) {struct pasemi_mac *mac =netdev_priv (dev); -int start = mac->rx->next_to_fill; -unsigned int fill, count; +int fill, count;if (limit <=0 )return ; - fill = start; + fill = mac->rx->next_to_fill;for (count =0 ; count < limit; count++) {struct pasemi_mac_buffer *info = &RX_RING_INFO (mac, fill);u64 *buff = &RX_BUFF (mac, fill);
@@ -446,10 +445,10 @@ static void pasemi_mac_replenish_rx_ringwmb (); -write_dma_reg (mac,PAS_DMA_RXCHAN_INCR (mac->dma_rxch), count);write_dma_reg (mac,PAS_DMA_RXINT_INCR (mac->dma_if), count); - mac->rx->next_to_fill += count; + mac->rx->next_to_fill = (mac->rx->next_to_fill + count) & + (RX_RING_SIZE -1 ); }static void pasemi_mac_restart_rx_intr (struct pasemi_mac *mac)
@@ -517,15 +516,19 @@ static int pasemi_mac_clean_rx(struct paint count;struct pasemi_mac_buffer *info;struct sk_buff *skb; -unsigned int i, len; +unsigned int len;u64 macrx;dma_addr_t dma; +int buf_index; +u64 eval;spin_lock (&mac->rx->lock); n = mac->rx->next_to_clean; -for (count = limit; count; count--) { +prefetch (RX_RING (mac, n)); + +for (count =0 ; count < limit; count++) { macrx =RX_RING (mac, n); if ((macrx & XCT_MACRX_E) ||
@@ -537,21 +540,14 @@ static int pasemi_mac_clean_rx(struct pa info =NULL ; -/* We have to scan for our skb since there's no way -* to back-map them from the descriptor, and if we -* have several receive channels then they might not -* show up in the same order as they were put on the -* interface ring. -*/ +BUG_ON (!(macrx &XCT_MACRX_RR_8BRES )); - dma = (RX_RING (mac, n+1 ) &XCT_PTR_ADDR_M ); -for (i = mac->rx->next_to_fill; - i < (mac->rx->next_to_fill +RX_RING_SIZE ); - i++) { - info = &RX_RING_INFO (mac, i); -if (info->dma == dma) -break ; - } + eval = (RX_RING (mac, n+1 ) &XCT_RXRES_8B_EVAL_M ) >> +XCT_RXRES_8B_EVAL_S ; + buf_index = eval-1 ; + + dma = (RX_RING (mac, n+2 ) &XCT_PTR_ADDR_M ); + info = &RX_RING_INFO (mac, buf_index); skb = info->skb;
@@ -600,9 +596,9 @@ static int pasemi_mac_clean_rx(struct pa/* Need to zero it out since hardware doesn't, since the * replenish loop uses it to tell when it's done. */ -RX_BUFF (mac, i) =0 ; +RX_BUFF (mac, buf_index) =0 ; - n +=2 ; + n +=4 ; }if (n >RX_RING_SIZE ) {
@@ -610,8 +606,16 @@ static int pasemi_mac_clean_rx(struct pawrite_iob_reg (mac,PAS_IOB_COM_PKTHDRCNT ,0 ); n &= (RX_RING_SIZE -1 ); } + mac->rx->next_to_clean = n; -pasemi_mac_replenish_rx_ring (mac->netdev, limit-count); + +/* Increase is in number of 16-byte entries, and since each descriptor +* with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with +* count*2. +*/ +write_dma_reg (mac,PAS_DMA_RXCHAN_INCR (mac->dma_rxch), count <<1 ); + +pasemi_mac_replenish_rx_ring (mac->netdev, count);spin_unlock (&mac->rx->lock);
@@ -927,6 +931,8 @@ static int pasemi_mac_open(struct net_depasemi_mac_replenish_rx_ring (dev,RX_RING_SIZE ); +write_dma_reg (mac,PAS_DMA_RXCHAN_INCR (mac->dma_rxch),RX_RING_SIZE >>1 ); + flags =PAS_MAC_CFG_PCFG_S1 |PAS_MAC_CFG_PCFG_PE |PAS_MAC_CFG_PCFG_PR |PAS_MAC_CFG_PCFG_CE ;
drivers/net/pasemi_mac.h +17 -4
@@ -206,12 +206,15 @@ enum {#define PAS_DMA_RXINT_RCMDSTA_DROPS_M 0xfffe0000#define PAS_DMA_RXINT_RCMDSTA_DROPS_S 17#define PAS_DMA_RXINT_CFG (i) (0x204+(i)*_PAS_DMA_RXINT_STRIDE) +#define PAS_DMA_RXINT_CFG_RBP 0x80000000 +#define PAS_DMA_RXINT_CFG_ITRR 0x40000000#define PAS_DMA_RXINT_CFG_DHL_M 0x07000000#define PAS_DMA_RXINT_CFG_DHL_S 24#define PAS_DMA_RXINT_CFG_DHL (x) (((x) << PAS_DMA_RXINT_CFG_DHL_S) & \ PAS_DMA_RXINT_CFG_DHL_M)#define PAS_DMA_RXINT_CFG_LW 0x00200000#define PAS_DMA_RXINT_CFG_L2 0x00100000 +#define PAS_DMA_RXINT_CFG_HEN 0x00080000#define PAS_DMA_RXINT_CFG_WIF 0x00000002#define PAS_DMA_RXINT_CFG_WIL 0x00000001
@@ -425,10 +428,9 @@ enum {/* Receive descriptor fields */ #define XCT_MACRX_T 0x8000000000000000ull#define XCT_MACRX_ST 0x4000000000000000ull -#define XCT_MACRX_NORES 0x0000000000000000ull -#define XCT_MACRX_8BRES 0x1000000000000000ull -#define XCT_MACRX_24BRES 0x2000000000000000ull -#define XCT_MACRX_40BRES 0x3000000000000000ull +#define XCT_MACRX_RR_M 0x3000000000000000ull +#define XCT_MACRX_RR_NORES 0x0000000000000000ull +#define XCT_MACRX_RR_8BRES 0x1000000000000000ull#define XCT_MACRX_O 0x0400000000000000ull#define XCT_MACRX_E 0x0200000000000000ull#define XCT_MACRX_FF 0x0100000000000000ull
@@ -476,6 +478,17 @@ enum {#define XCT_PTR_ADDR (x) ((((long)(x)) << XCT_PTR_ADDR_S) & \ XCT_PTR_ADDR_M) +/* Receive interface 8byte result fields */ +#define XCT_RXRES_8B_L4O_M 0xff00000000000000ull +#define XCT_RXRES_8B_L4O_S 56 +#define XCT_RXRES_8B_RULE_M 0x00ffff0000000000ull +#define XCT_RXRES_8B_RULE_S 40 +#define XCT_RXRES_8B_EVAL_M 0x000000ffff000000ull +#define XCT_RXRES_8B_EVAL_S 24 +#define XCT_RXRES_8B_HTYPE_M 0x0000000000f00000ull +#define XCT_RXRES_8B_HASH_M 0x00000000000fffffull +#define XCT_RXRES_8B_HASH_S 0 +/* Receive interface buffer fields */ #define XCT_RXB_LEN_M 0x0ffff00000000000ull#define XCT_RXB_LEN_S 44
PATCH 11/11 pasemi_mac: enable iommu support
In reply to Olof Johanssonpasemi_mac: use buffer index pointer in clean_rx()
Use the new features in B0 for buffer ring index on the receive side. This means we no longer have to search in the ring for where the buffer came from.
Also cleanup the RX cleaning side a little, while I was at it.
Note: Pre-B0 hardware is no longer supported, and needs a pile of other workarounds that are not being submitted for mainline inclusion. So the fact that this breaks old hardware is not a problem at this time.
drivers/net/pasemi_mac.c +33 -27
@@ -243,9 +243,9 @@ static int pasemi_mac_setup_rx_resources PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));write_dma_reg (mac,PAS_DMA_RXINT_CFG (mac->dma_if), -PAS_DMA_RXINT_CFG_DHL (3 ) | -PAS_DMA_RXINT_CFG_L2 | -PAS_DMA_RXINT_CFG_LW ); +PAS_DMA_RXINT_CFG_DHL (3 ) |PAS_DMA_RXINT_CFG_L2 | +PAS_DMA_RXINT_CFG_LW |PAS_DMA_RXINT_CFG_RBP | +PAS_DMA_RXINT_CFG_HEN ); ring->next_to_fill =0 ; ring->next_to_clean =0 ;
@@ -402,13 +402,12 @@ static void pasemi_mac_free_rx_resourcesstatic void pasemi_mac_replenish_rx_ring (struct net_device *dev,int limit) {struct pasemi_mac *mac =netdev_priv (dev); -int start = mac->rx->next_to_fill; -unsigned int fill, count; +int fill, count;if (limit <=0 )return ; - fill = start; + fill = mac->rx->next_to_fill;for (count =0 ; count < limit; count++) {struct pasemi_mac_buffer *info = &RX_RING_INFO (mac, fill);u64 *buff = &RX_BUFF (mac, fill);
@@ -446,10 +445,10 @@ static void pasemi_mac_replenish_rx_ringwmb (); -write_dma_reg (mac,PAS_DMA_RXCHAN_INCR (mac->dma_rxch), count);write_dma_reg (mac,PAS_DMA_RXINT_INCR (mac->dma_if), count); - mac->rx->next_to_fill += count; + mac->rx->next_to_fill = (mac->rx->next_to_fill + count) & + (RX_RING_SIZE -1 ); }static void pasemi_mac_restart_rx_intr (struct pasemi_mac *mac)
@@ -517,15 +516,19 @@ static int pasemi_mac_clean_rx(struct paint count;struct pasemi_mac_buffer *info;struct sk_buff *skb; -unsigned int i, len; +unsigned int len;u64 macrx;dma_addr_t dma; +int buf_index; +u64 eval;spin_lock (&mac->rx->lock); n = mac->rx->next_to_clean; -for (count = limit; count; count--) { +prefetch (RX_RING (mac, n)); + +for (count =0 ; count < limit; count++) { macrx =RX_RING (mac, n); if ((macrx & XCT_MACRX_E) ||
@@ -537,21 +540,14 @@ static int pasemi_mac_clean_rx(struct pa info =NULL ; -/* We have to scan for our skb since there's no way -* to back-map them from the descriptor, and if we -* have several receive channels then they might not -* show up in the same order as they were put on the -* interface ring. -*/ +BUG_ON (!(macrx &XCT_MACRX_RR_8BRES )); - dma = (RX_RING (mac, n+1 ) &XCT_PTR_ADDR_M ); -for (i = mac->rx->next_to_fill; - i < (mac->rx->next_to_fill +RX_RING_SIZE ); - i++) { - info = &RX_RING_INFO (mac, i); -if (info->dma == dma) -break ; - } + eval = (RX_RING (mac, n+1 ) &XCT_RXRES_8B_EVAL_M ) >> +XCT_RXRES_8B_EVAL_S ; + buf_index = eval-1 ; + + dma = (RX_RING (mac, n+2 ) &XCT_PTR_ADDR_M ); + info = &RX_RING_INFO (mac, buf_index); skb = info->skb;
@@ -600,9 +596,9 @@ static int pasemi_mac_clean_rx(struct pa/* Need to zero it out since hardware doesn't, since the * replenish loop uses it to tell when it's done. */ -RX_BUFF (mac, i) =0 ; +RX_BUFF (mac, buf_index) =0 ; - n +=2 ; + n +=4 ; }if (n >RX_RING_SIZE ) {
@@ -610,8 +606,16 @@ static int pasemi_mac_clean_rx(struct pawrite_iob_reg (mac,PAS_IOB_COM_PKTHDRCNT ,0 ); n &= (RX_RING_SIZE -1 ); } + mac->rx->next_to_clean = n; -pasemi_mac_replenish_rx_ring (mac->netdev, limit-count); + +/* Increase is in number of 16-byte entries, and since each descriptor +* with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with +* count*2. +*/ +write_dma_reg (mac,PAS_DMA_RXCHAN_INCR (mac->dma_rxch), count <<1 ); + +pasemi_mac_replenish_rx_ring (mac->netdev, count);spin_unlock (&mac->rx->lock);
@@ -927,6 +931,8 @@ static int pasemi_mac_open(struct net_depasemi_mac_replenish_rx_ring (dev,RX_RING_SIZE ); +write_dma_reg (mac,PAS_DMA_RXCHAN_INCR (mac->dma_rxch),RX_RING_SIZE >>1 ); + flags =PAS_MAC_CFG_PCFG_S1 |PAS_MAC_CFG_PCFG_PE |PAS_MAC_CFG_PCFG_PR |PAS_MAC_CFG_PCFG_CE ;
drivers/net/pasemi_mac.h +17 -4
@@ -206,12 +206,15 @@ enum {#define PAS_DMA_RXINT_RCMDSTA_DROPS_M 0xfffe0000#define PAS_DMA_RXINT_RCMDSTA_DROPS_S 17#define PAS_DMA_RXINT_CFG (i) (0x204+(i)*_PAS_DMA_RXINT_STRIDE) +#define PAS_DMA_RXINT_CFG_RBP 0x80000000 +#define PAS_DMA_RXINT_CFG_ITRR 0x40000000#define PAS_DMA_RXINT_CFG_DHL_M 0x07000000#define PAS_DMA_RXINT_CFG_DHL_S 24#define PAS_DMA_RXINT_CFG_DHL (x) (((x) << PAS_DMA_RXINT_CFG_DHL_S) & \ PAS_DMA_RXINT_CFG_DHL_M)#define PAS_DMA_RXINT_CFG_LW 0x00200000#define PAS_DMA_RXINT_CFG_L2 0x00100000 +#define PAS_DMA_RXINT_CFG_HEN 0x00080000#define PAS_DMA_RXINT_CFG_WIF 0x00000002#define PAS_DMA_RXINT_CFG_WIL 0x00000001
@@ -425,10 +428,9 @@ enum {/* Receive descriptor fields */ #define XCT_MACRX_T 0x8000000000000000ull#define XCT_MACRX_ST 0x4000000000000000ull -#define XCT_MACRX_NORES 0x0000000000000000ull -#define XCT_MACRX_8BRES 0x1000000000000000ull -#define XCT_MACRX_24BRES 0x2000000000000000ull -#define XCT_MACRX_40BRES 0x3000000000000000ull +#define XCT_MACRX_RR_M 0x3000000000000000ull +#define XCT_MACRX_RR_NORES 0x0000000000000000ull +#define XCT_MACRX_RR_8BRES 0x1000000000000000ull#define XCT_MACRX_O 0x0400000000000000ull#define XCT_MACRX_E 0x0200000000000000ull#define XCT_MACRX_FF 0x0100000000000000ull
@@ -476,6 +478,17 @@ enum {#define XCT_PTR_ADDR (x) ((((long)(x)) << XCT_PTR_ADDR_S) & \ XCT_PTR_ADDR_M) +/* Receive interface 8byte result fields */ +#define XCT_RXRES_8B_L4O_M 0xff00000000000000ull +#define XCT_RXRES_8B_L4O_S 56 +#define XCT_RXRES_8B_RULE_M 0x00ffff0000000000ull +#define XCT_RXRES_8B_RULE_S 40 +#define XCT_RXRES_8B_EVAL_M 0x000000ffff000000ull +#define XCT_RXRES_8B_EVAL_S 24 +#define XCT_RXRES_8B_HTYPE_M 0x0000000000f00000ull +#define XCT_RXRES_8B_HASH_M 0x00000000000fffffull +#define XCT_RXRES_8B_HASH_S 0 +/* Receive interface buffer fields */ #define XCT_RXB_LEN_M 0x0ffff00000000000ull#define XCT_RXB_LEN_S 44
Re: [PATCH] [11/11] pasemi_mac: enable iommu support
Quoted 6 lines · Olof Johansson
pasemi_mac: use buffer index pointer inclean_rx()Use the new features in B0 for buffer ring index on the receive side. This means we no longer have to search in the ring for where the buffer came from.
Quoted 7 lines
Also cleanup the RX cleaning side a little, while I was at it.
Note: Pre-B0 hardware is no longer supported, and needs a pile of other workarounds that are not being submitted for mainline inclusion. So the fact that this breaks old hardware is not a problem at this time.
Signed-off-by Olof Johansson <[email protected]>
You sent patch #10 against as patch #11 :)
PATCH RESEND 11/11 pasemi_mac: enable iommu support
pasemi_mac: enable iommu support
Enable IOMMU support for pasemi_mac, but avoid using it on non-partitioned systems for performance reasons.
The user can override this by selecting the PPC_PASEMI_IOMMU_DMA_FORCE configuration option.
---
Quoted 1 line · Jeff Garzik
You sent patch #10 against as patch #11 :)
Oops! Here's the real copy.
-Olof
arch/powerpc/platforms/pasemi/iommu.c +10 -5
@@ -25,6 +25,7 @@#include <asm/iommu.h> #include <asm/machdep.h> #include <asm/abs_addr.h> +#include <asm/firmware.h> #define IOBMAP_PAGE_SHIFT 12
@@ -175,13 +176,17 @@ static void pci_dma_dev_setup_pasemi(str {pr_debug ("pci_dma_dev_setup, dev %p (%s)\n" , dev,pci_name (dev)); -/* DMA device is untranslated, but all other PCI-e goes through -* the IOMMU +#if !defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE ) +/* For non-LPAR environment, don't translate anything for the DMA +* engine. The exception to this is if the user has enabled +* CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE at build time. */ -if (dev->vendor ==0x1959 && dev->device ==0xa007 ) +if (dev->vendor ==0x1959 && dev->device ==0xa007 && + !firmware_has_feature (FW_FEATURE_LPAR )) dev->dev.archdata.dma_ops = &dma_direct_ops; -else - dev->dev.archdata.dma_data = &iommu_table_iobmap; +#endif + + dev->dev.archdata.dma_data = &iommu_table_iobmap; }static void pci_dma_bus_setup_null (struct pci_bus *b) { }
drivers/net/pasemi_mac.c +37 -13
92 lines not on this page · raw message
drivers/net/pasemi_mac.h +6 -2
@@ -212,6 +212,7 @@ enum {#define PAS_DMA_RXINT_CFG_DHL_S 24#define PAS_DMA_RXINT_CFG_DHL (x) (((x) << PAS_DMA_RXINT_CFG_DHL_S) & \ PAS_DMA_RXINT_CFG_DHL_M) +#define PAS_DMA_RXINT_CFG_ITR 0x00400000#define PAS_DMA_RXINT_CFG_LW 0x00200000#define PAS_DMA_RXINT_CFG_L2 0x00100000#define PAS_DMA_RXINT_CFG_HEN 0x00080000
@@ -258,9 +259,11 @@ enum {#define PAS_DMA_TXCHAN_CFG_WT_S 6#define PAS_DMA_TXCHAN_CFG_WT (x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \ PAS_DMA_TXCHAN_CFG_WT_M) -#define PAS_DMA_TXCHAN_CFG_CF 0x00001000/* Clean first line */ -#define PAS_DMA_TXCHAN_CFG_CL 0x00002000/* Clean last line */ +#define PAS_DMA_TXCHAN_CFG_TRD 0x00010000/* translate data */ +#define PAS_DMA_TXCHAN_CFG_TRR 0x00008000/* translate rings */ #define PAS_DMA_TXCHAN_CFG_UP 0x00004000/* update tx descr when sent */ +#define PAS_DMA_TXCHAN_CFG_CL 0x00002000/* Clean last line */ +#define PAS_DMA_TXCHAN_CFG_CF 0x00001000/* Clean first line */ #define PAS_DMA_TXCHAN_INCR (c) (0x310+(c)*_PAS_DMA_TXCHAN_STRIDE)#define PAS_DMA_TXCHAN_BASEL (c) (0x318+(c)*_PAS_DMA_TXCHAN_STRIDE)#define PAS_DMA_TXCHAN_BASEL_BRBL_M 0xffffffc0
@@ -294,6 +297,7 @@ enum {#define PAS_DMA_RXCHAN_CCMDSTA_FD 0x00001000#define PAS_DMA_RXCHAN_CCMDSTA_DT 0x00000800#define PAS_DMA_RXCHAN_CFG (c) (0x804+(c)*_PAS_DMA_RXCHAN_STRIDE) +#define PAS_DMA_RXCHAN_CFG_CTR 0x00000400#define PAS_DMA_RXCHAN_CFG_HBU_M 0x00000380#define PAS_DMA_RXCHAN_CFG_HBU_S 7#define PAS_DMA_RXCHAN_CFG_HBU (x) (((x) << PAS_DMA_RXCHAN_CFG_HBU_S) & \
arch/powerpc/platforms/pasemi/Kconfig +10 -0
@@ -19,6 +19,16 @@ config PPC_PASEMI_IOMMU help IOMMU support for PA6T-1682M +config PPC_PASEMI_IOMMU_DMA_FORCE + bool "Force DMA engine to use IOMMU" + depends on PPC_PASEMI_IOMMU + help + This option forces the use of the IOMMU also for the + DMA engine. Otherwise the kernel will use it only when + running under a hypervisor. + + If in doubt, say "N". + config PPC_PASEMI_MDIO depends on PHYLIB tristate "MDIO support via GPIO"
Jeff Garzik
AppliedRe: [PATCH RESEND] [11/11] pasemi_mac: enable iommu support
Quoted 9 lines · Olof Johansson
pasemi_mac: enable iommu supportEnable IOMMU support for
pasemi_mac, but avoid using it on non-partitioned systems for performance reasons.The user can override this by selecting the
PPC_PASEMI_IOMMU_DMA_FORCEconfiguration option.Signed-off-by Olof Johansson <[email protected]>
applied