pasemi_mac updates for 2.6.25 + DMA channel management library
Subsystems (3)
cover pasemi_mac updates for 2.6.25 + DMA channel management library
Hi,
The following series contains driver updates for 2.6.25, together with a couple of patches that introduces a library for abstracting DMA channel allocation and access.
While the DMA stuff (patches 5 and 6) isn't really netdev material, the driver updates depend on them, and it'd just be easier to merge them up the netdev path.
The patches are:
1/12: pasemi_mac: RX/TX ring management cleanup
2/12: pasemi_mac: Remove SKB copy/recycle logic
3/12: pasemi_mac: Print warning when not attaching to a PHY 4/12: pasemi_mac: Don't enable RX/TX without a link (if possible) 5/12: pasemi_mac: Move register definitions to include/asm-powerpc 6/12: pasemi: DMA engine management library
7/12: pasemi_mac: Convert to new dma library
8/12: pasemi_mac: performance tweaks
9/12: pasemi_mac: Fix TX cleaning
10/12: pasemi_mac: Improve RX interrupt mitigation l1/12: pasemi_mac: Software-based LRO support
12/12: pasemi_mac: SKB unmap optimization
-Olof
PATCH 1/12 pasemi_mac: RX/TX ring management cleanup
pasemi_mac: RX/TX ring management cleanup
Prepare a bit for supporting multiple TX queues by cleaning up some of the ring management and shuffle things around a bit.
--- drivers/net/pasemi_mac.c | 277 ++++++++++++++++++++++++----------------------- drivers/net/pasemi_mac.h | 19 +-- 2 files changed, 157 insertions(+), 139 deletions(-)
drivers/net/pasemi_mac.c +147 -130
@@ -68,11 +68,11 @@ NETIF_MSG_RX_ERR | \ NETIF_MSG_TX_ERR) -#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 TX_DESC (tx, num) ((tx)->ring[(num) & (TX_RING_SIZE-1)]) +#define TX_DESC_INFO (tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)]) +#define RX_DESC (rx, num) ((rx)->ring[(num) & (RX_RING_SIZE-1)]) +#define RX_DESC_INFO (rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)]) +#define RX_BUFF (rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)])#define RING_USED (ring) (((ring)->next_to_fill - (ring)->next_to_clean) \ & ((ring)->size - 1))
@@ -127,6 +127,16 @@ static void write_dma_reg(struct pasemi_out_le32 (mac->dma_regs+reg, val); } +static struct pasemi_mac_rxring *rx_ring (struct pasemi_mac *mac) +{ +return mac->rx; +} + +static struct pasemi_mac_txring *tx_ring (struct pasemi_mac *mac) +{ +return mac->tx; +} +static int pasemi_get_mac_addr (struct pasemi_mac *mac) {struct pci_dev *pdev = mac->pdev;
@@ -269,8 +279,8 @@ static int pasemi_mac_setup_rx_resources ring->next_to_fill =0 ; ring->next_to_clean =0 ; -snprintf (ring->irq_name,sizeof (ring->irq_name), -"%s rx" , dev->name); + ring->status = &dma_status->rx_sta[mac->dma_rxch]; + ring->mac = mac; mac->rx = ring;return 0 ;
@@ -278,7 +288,7 @@ static int pasemi_mac_setup_rx_resources out_buffers:dma_free_coherent (&mac->dma_pdev->dev,RX_RING_SIZE *sizeof (u64), - mac->rx->ring, mac->rx->dma); +rx_ring (mac)->ring,rx_ring (mac)->dma); out_ring_desc:kfree (ring->ring_info); out_ring_info:
@@ -287,12 +297,11 @@ out_ring:return -ENOMEM ; } - -static int pasemi_mac_setup_tx_resources (struct net_device *dev) +static struct pasemi_mac_txring * +pasemi_mac_setup_tx_resources (struct net_device *dev,int txch) {struct pasemi_mac *mac =netdev_priv (dev);u32 val; -int chan_id = mac->dma_txch;struct pasemi_mac_txring *ring;unsigned int cfg;
@@ -317,12 +326,12 @@ static int pasemi_mac_setup_tx_resourcesmemset (ring->ring,0 ,TX_RING_SIZE *sizeof (u64)); -write_dma_reg (mac,PAS_DMA_TXCHAN_BASEL (chan_id), +write_dma_reg (mac,PAS_DMA_TXCHAN_BASEL (txch),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 >>3 ); -write_dma_reg (mac,PAS_DMA_TXCHAN_BASEU (chan_id), val); +write_dma_reg (mac,PAS_DMA_TXCHAN_BASEU (txch), val); cfg =PAS_DMA_TXCHAN_CFG_TY_IFACE | PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
@@ -332,71 +341,70 @@ static int pasemi_mac_setup_tx_resourcesif (translation_enabled ()) cfg |=PAS_DMA_TXCHAN_CFG_TRD |PAS_DMA_TXCHAN_CFG_TRR ; -write_dma_reg (mac,PAS_DMA_TXCHAN_CFG (chan_id), cfg); +write_dma_reg (mac,PAS_DMA_TXCHAN_CFG (txch), cfg); ring->next_to_fill =0 ; ring->next_to_clean =0 ; + ring->status = &dma_status->tx_sta[txch]; + ring->chan = txch; + ring->mac = mac; -snprintf (ring->irq_name,sizeof (ring->irq_name), -"%s tx" , dev->name); - mac->tx = ring; - -return 0 ; +return ring; out_ring_desc:kfree (ring->ring_info); out_ring_info:kfree (ring); out_ring: -return -ENOMEM ; +return NULL ; } -static void pasemi_mac_free_tx_resources (struct net_device *dev) +static void pasemi_mac_free_tx_resources (struct pasemi_mac *mac) { -struct pasemi_mac *mac =netdev_priv (dev); +struct pasemi_mac_txring *txring =tx_ring (mac);unsigned int i, j;struct pasemi_mac_buffer *info;dma_addr_t dmas[MAX_SKB_FRAGS +1 ];int freed;int start, limit; - start = mac->tx->next_to_clean; - limit = mac->tx->next_to_fill; + start = txring->next_to_clean; + limit = txring->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 ); + info = &txring->ring_info[(i+1 ) & (TX_RING_SIZE -1 )];if (info->dma && info->skb) {for (j =0 ; j <=skb_shinfo (info->skb)->nr_frags; j++) - dmas[j] =TX_RING_INFO (mac, i+1 +j).dma; + dmas[j] = txring->ring_info[(i+1 +j) & + (TX_RING_SIZE -1 )].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 ; + txring->ring[i] =0 ;dma_free_coherent (&mac->dma_pdev->dev,TX_RING_SIZE *sizeof (u64), - mac->tx->ring, mac->tx->dma); + txring->ring, txring->dma); -kfree (mac->tx->ring_info); -kfree (mac->tx); - mac->tx =NULL ; +kfree (txring->ring_info); +kfree (txring); } -static void pasemi_mac_free_rx_resources (struct net_device *dev) +static void pasemi_mac_free_rx_resources (struct pasemi_mac *mac) { -struct pasemi_mac *mac =netdev_priv (dev); +struct pasemi_mac_rxring *rx =rx_ring (mac);unsigned int i;struct pasemi_mac_buffer *info;for (i =0 ; i <RX_RING_SIZE ; i++) { - info = &RX_RING_INFO (mac, i); + info = &RX_DESC_INFO (rx, i);if (info->skb && info->dma) { pci_unmap_single(mac->dma_pdev, info->dma,
@@ -409,32 +417,33 @@ static void pasemi_mac_free_rx_resources }for (i =0 ; i <RX_RING_SIZE ; i++) -RX_RING (mac, i) =0 ; +RX_DESC (rx, i) =0 ;dma_free_coherent (&mac->dma_pdev->dev,RX_RING_SIZE *sizeof (u64), - mac->rx->ring, mac->rx->dma); +rx_ring (mac)->ring,rx_ring (mac)->dma);dma_free_coherent (&mac->dma_pdev->dev,RX_RING_SIZE *sizeof (u64), - mac->rx->buffers, mac->rx->buf_dma); +rx_ring (mac)->buffers,rx_ring (mac)->buf_dma); -kfree (mac->rx->ring_info); -kfree (mac->rx); +kfree (rx_ring (mac)->ring_info); +kfree (rx_ring (mac)); mac->rx =NULL ; }static void pasemi_mac_replenish_rx_ring (struct net_device *dev,int limit) {struct pasemi_mac *mac =netdev_priv (dev); +struct pasemi_mac_rxring *rx =rx_ring (mac);int fill, count;if (limit <=0 )return ; - fill = mac->rx->next_to_fill; + fill =rx_ring (mac)->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); +struct pasemi_mac_buffer *info = &RX_DESC_INFO (rx, fill); +u64 *buff = &RX_BUFF (rx, fill);struct sk_buff *skb;dma_addr_t dma;
@@ -471,7 +480,7 @@ static void pasemi_mac_replenish_rx_ringwrite_dma_reg (mac,PAS_DMA_RXINT_INCR (mac->dma_if), count); - mac->rx->next_to_fill = (mac->rx->next_to_fill + count) & +rx_ring (mac)->next_to_fill = (rx_ring (mac)->next_to_fill + count) & (RX_RING_SIZE -1 ); }
@@ -482,7 +491,7 @@ static void pasemi_mac_restart_rx_intr(s* ack the packet count interrupt we got in rx_intr. */ - pcnt = *mac->rx_status &PAS_STATUS_PCNT_M ; + pcnt = *rx_ring (mac)->status &PAS_STATUS_PCNT_M ; reg =PAS_IOB_DMA_RXCH_RESET_PCNT (pcnt) |PAS_IOB_DMA_RXCH_RESET_PINTC ;
@@ -494,11 +503,11 @@ static void pasemi_mac_restart_tx_intr(sunsigned int reg, pcnt;/* Re-enable packet count interrupts */ - pcnt = *mac->tx_status &PAS_STATUS_PCNT_M ; + pcnt = *tx_ring (mac)->status &PAS_STATUS_PCNT_M ; reg =PAS_IOB_DMA_TXCH_RESET_PCNT (pcnt) |PAS_IOB_DMA_TXCH_RESET_PINTC ; -write_iob_reg (mac,PAS_IOB_DMA_TXCH_RESET (mac->dma_txch), reg); +write_iob_reg (mac,PAS_IOB_DMA_TXCH_RESET (tx_ring (mac)->chan), reg); }
@@ -513,7 +522,7 @@ static inline void pasemi_mac_rx_error(s 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); + macrx, *rx_ring (mac)->status);printk (KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n" , rcmdsta, ccmdsta);
@@ -529,13 +538,14 @@ static inline void pasemi_mac_tx_error(s 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); +"tx status 0x%016lx\n" , mactx, *tx_ring (mac)->status);printk (KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n" , cmdsta); } -static int pasemi_mac_clean_rx (struct pasemi_mac *mac,int limit) +static int pasemi_mac_clean_rx (struct pasemi_mac_rxring *rx,int limit) { +struct pasemi_mac *mac = rx->mac;unsigned int n;int count;struct pasemi_mac_buffer *info;
@@ -546,17 +556,17 @@ static int pasemi_mac_clean_rx(struct paint buf_index;u64 eval; -spin_lock (&mac->rx->lock); +spin_lock (&rx->lock); - n = mac->rx->next_to_clean; + n = rx->next_to_clean; -prefetch (&RX_RING (mac, n)); +prefetch (&RX_DESC (rx, n));for (count =0 ; count < limit; count++) { - macrx =RX_RING (mac, n); + macrx =RX_DESC (rx, n);if ((macrx &XCT_MACRX_E ) || - (*mac->rx_status &PAS_STATUS_ERROR )) + (*rx_ring (mac)->status &PAS_STATUS_ERROR ))pasemi_mac_rx_error (mac, macrx);if (!(macrx &XCT_MACRX_O ))
@@ -566,12 +576,12 @@ static int pasemi_mac_clean_rx(struct paBUG_ON (!(macrx &XCT_MACRX_RR_8BRES )); - eval = (RX_RING (mac, n+1 ) &XCT_RXRES_8B_EVAL_M ) >> + eval = (RX_DESC (rx, 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); + dma = (RX_DESC (rx, n+2 ) &XCT_PTR_ADDR_M ); + info = &RX_DESC_INFO (rx, buf_index); skb = info->skb;
@@ -624,13 +634,13 @@ static int pasemi_mac_clean_rx(struct panetif_receive_skb (skb); next: -RX_RING (mac, n) =0 ; -RX_RING (mac, n+1 ) =0 ; +RX_DESC (rx, n) =0 ; +RX_DESC (rx, 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, buf_index) =0 ; +RX_BUFF (rx, buf_index) =0 ; n +=4 ; }
@@ -641,7 +651,7 @@ next: n &= (RX_RING_SIZE -1 ); } - mac->rx->next_to_clean = n; +rx_ring (mac)->next_to_clean = n;/* Increase is in number of 16-byte entries, and since each descriptor * with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with
@@ -651,7 +661,7 @@ next:pasemi_mac_replenish_rx_ring (mac->netdev, count); -spin_unlock (&mac->rx->lock); +spin_unlock (&rx_ring (mac)->lock);return count; }
@@ -659,8 +669,9 @@ next:/* 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) +static int pasemi_mac_clean_tx (struct pasemi_mac_txring *txring) { +struct pasemi_mac *mac = txring->mac;int i, j;unsigned int start, descr_count, buf_count, batch_limit;unsigned int ring_limit;
@@ -672,10 +683,10 @@ static int pasemi_mac_clean_tx(struct pa total_count =0 ; batch_limit =TX_CLEAN_BATCHSIZE ; restart: -spin_lock_irqsave (&mac->tx->lock, flags); +spin_lock_irqsave (&txring->lock, flags); - start = mac->tx->next_to_clean; - ring_limit = mac->tx->next_to_fill; + start = txring->next_to_clean; + ring_limit = txring->next_to_fill;/* Compensate for when fill has wrapped but clean has not */ if (start > ring_limit)
@@ -687,26 +698,26 @@ restart:for (i = start; descr_count < batch_limit && i < ring_limit; i += buf_count) { -u64 mactx =TX_RING (mac, i); +u64 mactx =TX_DESC (txring, i);struct sk_buff *skb;if ((mactx &XCT_MACTX_E ) || - (*mac->tx_status &PAS_STATUS_ERROR )) + (*tx_ring (mac)->status &PAS_STATUS_ERROR ))pasemi_mac_tx_error (mac, mactx);if (unlikely (mactx &XCT_MACTX_O ))/* Not yet transmitted */ break ; - skb =TX_RING_INFO (mac, i+1 ).skb; + skb =TX_DESC_INFO (txring, i+1 ).skb; skbs[descr_count] = skb; 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; + dmas[descr_count][j] =TX_DESC_INFO (txring, i+1 +j).dma; -TX_RING (mac, i) =0 ; -TX_RING (mac, i+1 ) =0 ; +TX_DESC (txring, i) =0 ; +TX_DESC (txring, i+1 ) =0 ;/* Since we always fill with an even number of entries, make * sure we skip any unused one at the end as well.
@@ -715,9 +726,9 @@ restart: buf_count++; descr_count++; } - mac->tx->next_to_clean = i & (TX_RING_SIZE -1 ); + txring->next_to_clean = i & (TX_RING_SIZE -1 ); -spin_unlock_irqrestore (&mac->tx->lock, flags); +spin_unlock_irqrestore (&txring->lock, flags);netif_wake_queue (mac->netdev);for (i =0 ; i < descr_count; i++)
@@ -739,7 +750,7 @@ static irqreturn_t pasemi_mac_rx_intr(instruct pasemi_mac *mac =netdev_priv (dev);unsigned int reg; -if (!(*mac->rx_status &PAS_STATUS_CAUSE_M )) +if (!(*rx_ring (mac)->status &PAS_STATUS_CAUSE_M ))return IRQ_NONE ;/* Don't reset packet count so it won't fire again but clear
@@ -747,11 +758,11 @@ static irqreturn_t pasemi_mac_rx_intr(in*/ reg =0 ; -if (*mac->rx_status &PAS_STATUS_SOFT ) +if (*rx_ring (mac)->status &PAS_STATUS_SOFT ) reg |=PAS_IOB_DMA_RXCH_RESET_SINTC ; -if (*mac->rx_status &PAS_STATUS_ERROR ) +if (*rx_ring (mac)->status &PAS_STATUS_ERROR ) reg |=PAS_IOB_DMA_RXCH_RESET_DINTC ; -if (*mac->rx_status &PAS_STATUS_TIMER ) +if (*rx_ring (mac)->status &PAS_STATUS_TIMER ) reg |=PAS_IOB_DMA_RXCH_RESET_TINTC ;netif_rx_schedule (dev, &mac->napi);
@@ -763,25 +774,25 @@ static irqreturn_t pasemi_mac_rx_intr(instatic irqreturn_t pasemi_mac_tx_intr (int irq,void *data) { -struct net_device *dev = data; -struct pasemi_mac *mac =netdev_priv (dev); +struct pasemi_mac_txring *txring = data; +struct pasemi_mac *mac = txring->mac;unsigned int reg, pcnt; -if (!(*mac->tx_status &PAS_STATUS_CAUSE_M )) +if (!(*txring->status &PAS_STATUS_CAUSE_M ))return IRQ_NONE ; -pasemi_mac_clean_tx (mac); +pasemi_mac_clean_tx (txring); - pcnt = *mac->tx_status &PAS_STATUS_PCNT_M ; + pcnt = *txring->status &PAS_STATUS_PCNT_M ; reg =PAS_IOB_DMA_TXCH_RESET_PCNT (pcnt) |PAS_IOB_DMA_TXCH_RESET_PINTC ; -if (*mac->tx_status &PAS_STATUS_SOFT ) +if (*txring->status &PAS_STATUS_SOFT ) reg |=PAS_IOB_DMA_TXCH_RESET_SINTC ; -if (*mac->tx_status &PAS_STATUS_ERROR ) +if (*txring->status &PAS_STATUS_ERROR ) reg |=PAS_IOB_DMA_TXCH_RESET_DINTC ; -write_iob_reg (mac,PAS_IOB_DMA_TXCH_RESET (mac->dma_txch), reg); +write_iob_reg (mac,PAS_IOB_DMA_TXCH_RESET (txring->chan), reg);return IRQ_HANDLED ; }
@@ -919,10 +930,6 @@ static int pasemi_mac_open(struct net_dewrite_iob_reg (mac,PAS_IOB_DMA_TXCH_CFG (mac->dma_txch),PAS_IOB_DMA_TXCH_CFG_CNTTH (128 )); -/* Clear out any residual packet count state from firmware */ -pasemi_mac_restart_rx_intr (mac); -pasemi_mac_restart_tx_intr (mac); -/* 0xffffff is max value, about 16ms */ write_iob_reg (mac,PAS_IOB_DMA_COM_TIMEOUTCFG ,PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT (0xffffff ));
@@ -931,9 +938,10 @@ static int pasemi_mac_open(struct net_deif (ret) goto out_rx_resources; - ret =pasemi_mac_setup_tx_resources (dev); -if (ret) - goto out_tx_resources; + mac->tx =pasemi_mac_setup_tx_resources (dev, mac->dma_txch); + +if (!mac->tx) + goto out_tx_ring; write_mac_reg(mac, PAS_MAC_IPC_CHNL, PAS_MAC_IPC_CHNL_DCHNO(mac->dma_rxch) |
@@ -967,6 +975,10 @@ static int pasemi_mac_open(struct net_dewrite_dma_reg (mac,PAS_DMA_RXCHAN_INCR (mac->dma_rxch),RX_RING_SIZE >>1 ); +/* Clear out any residual packet count state from firmware */ +pasemi_mac_restart_rx_intr (mac); +pasemi_mac_restart_tx_intr (mac); + flags =PAS_MAC_CFG_PCFG_S1 |PAS_MAC_CFG_PCFG_PE |PAS_MAC_CFG_PCFG_PR |PAS_MAC_CFG_PCFG_CE ;
@@ -997,18 +1009,25 @@ static int pasemi_mac_open(struct net_de base_irq =virq_to_hw (mac->dma_pdev->irq); mac->tx_irq =irq_create_mapping (NULL , base_irq + mac->dma_txch); - mac->rx_irq =irq_create_mapping (NULL , base_irq +20 + mac->dma_txch); + +snprintf (mac->tx_irq_name,sizeof (mac->tx_irq_name),"%s tx" , + dev->name); ret =request_irq (mac->tx_irq, &pasemi_mac_tx_intr,IRQF_DISABLED , - mac->tx->irq_name, dev); + mac->tx_irq_name, mac->tx);if (ret) {dev_err (&mac->pdev->dev,"request_irq of irq %d failed: %d\n" , base_irq + mac->dma_txch, ret); goto out_tx_int; } + mac->rx_irq =irq_create_mapping (NULL , base_irq +20 + mac->dma_rxch); + +snprintf (mac->rx_irq_name,sizeof (mac->rx_irq_name),"%s rx" , + dev->name); + ret =request_irq (mac->rx_irq, &pasemi_mac_rx_intr,IRQF_DISABLED , - mac->rx->irq_name, dev); + mac->rx_irq_name, dev);if (ret) {dev_err (&mac->pdev->dev,"request_irq of irq %d failed: %d\n" , base_irq +20 + mac->dma_rxch, ret);
@@ -1021,13 +1040,14 @@ static int pasemi_mac_open(struct net_dereturn 0 ; out_rx_int: -free_irq (mac->tx_irq, dev); +free_irq (mac->tx_irq, mac->tx); out_tx_int:napi_disable (&mac->napi);netif_stop_queue (dev); -pasemi_mac_free_tx_resources (dev); -out_tx_resources: -pasemi_mac_free_rx_resources (dev); +out_tx_ring: +if (mac->tx) +pasemi_mac_free_tx_resources (mac); +pasemi_mac_free_rx_resources (mac); out_rx_resources:return ret;
@@ -1063,20 +1083,21 @@ static int pasemi_mac_close(struct net_dprintk (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 )) +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 ); +pasemi_mac_clean_tx (tx_ring (mac)); +pasemi_mac_clean_rx (rx_ring (mac),RX_RING_SIZE );/* Disable interface */ -write_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch),PAS_DMA_TXCHAN_TCMDSTA_ST ); -write_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if),PAS_DMA_RXINT_RCMDSTA_ST ); -write_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch),PAS_DMA_RXCHAN_CCMDSTA_ST ); +write_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch), +PAS_DMA_TXCHAN_TCMDSTA_ST ); +write_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if), +PAS_DMA_RXINT_RCMDSTA_ST ); +write_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch), +PAS_DMA_RXCHAN_CCMDSTA_ST );for (retries =0 ; retries <MAX_RETRIES ; retries++) { sta =read_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch));
@@ -1086,7 +1107,8 @@ static int pasemi_mac_close(struct net_d }if (sta &PAS_DMA_TXCHAN_TCMDSTA_ACT ) -dev_err (&mac->dma_pdev->dev,"Failed to stop tx channel\n" ); +dev_err (&mac->dma_pdev->dev,"Failed to stop tx channel %d\n" , + mac->dma_txch);for (retries =0 ; retries <MAX_RETRIES ; retries++) { sta =read_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch));
@@ -1116,12 +1138,12 @@ static int pasemi_mac_close(struct net_dwrite_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch),0 );write_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if),0 ); -free_irq (mac->tx_irq, dev); -free_irq (mac->rx_irq, dev); +free_irq (mac->tx_irq, mac->tx); +free_irq (mac->rx_irq, mac->rx);/* Free resources */ -pasemi_mac_free_rx_resources (dev); -pasemi_mac_free_tx_resources (dev); +pasemi_mac_free_rx_resources (mac); +pasemi_mac_free_tx_resources (mac);return 0 ; }
@@ -1178,7 +1200,7 @@ static int pasemi_mac_start_tx(struct sk mactx = dflags |XCT_MACTX_LLEN (skb->len); - txring = mac->tx; + txring =tx_ring (mac);spin_lock_irqsave (&txring->lock, flags);
@@ -1192,13 +1214,13 @@ static int pasemi_mac_start_tx(struct sk goto out_err; } -TX_RING (mac, txring->next_to_fill) = mactx; +TX_DESC (txring, txring->next_to_fill) = mactx; txring->next_to_fill++; -TX_RING_INFO (mac, txring->next_to_fill).skb = skb; +TX_DESC_INFO (txring, 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]; +TX_DESC (txring, txring->next_to_fill+i) = +XCT_PTR_LEN (map_size[i]) |XCT_PTR_ADDR (map[i]); +TX_DESC_INFO (txring, txring->next_to_fill+i).dma = map[i]; }/* We have to add an even number of 8-byte entries to the ring
@@ -1216,7 +1238,7 @@ static int pasemi_mac_start_tx(struct skspin_unlock_irqrestore (&txring->lock, flags); -write_dma_reg (mac,PAS_DMA_TXCHAN_INCR (mac->dma_txch), (nfrags+2 ) >>1 ); +write_dma_reg (mac,PAS_DMA_TXCHAN_INCR (txring->chan), (nfrags+2 ) >>1 );return NETDEV_TX_OK ;
@@ -1253,8 +1275,8 @@ static int pasemi_mac_poll(struct napi_sstruct net_device *dev = mac->netdev;int pkts; -pasemi_mac_clean_tx (mac); - pkts =pasemi_mac_clean_rx (mac, budget); +pasemi_mac_clean_tx (tx_ring (mac)); + pkts =pasemi_mac_clean_rx (rx_ring (mac), budget);if (pkts < budget) {/* all done, no more packets present */ netif_rx_complete (dev, napi);
@@ -1405,9 +1427,6 @@ pasemi_mac_probe(struct pci_dev *pdev, cif (err) goto out; - mac->rx_status = &dma_status->rx_sta[mac->dma_rxch]; - mac->tx_status = &dma_status->tx_sta[mac->dma_txch]; - mac->msg_enable =netif_msg_init (debug,DEFAULT_MSG_ENABLE );/* Enable most messages by default */
@@ -1420,11 +1439,9 @@ pasemi_mac_probe(struct pci_dev *pdev, c err); goto out; } else if netif_msg_probe(mac) -printk (KERN_INFO "%s: PA Semi %s: intf %d, txch %d, rxch %d, " -"hw addr %s\n" , +printk (KERN_INFO "%s: PA Semi %s: intf %d, hw addr %s\n" , dev->name, mac->type ==MAC_TYPE_GMAC ?"GMAC" :"XAUI" , - mac->dma_if, mac->dma_txch, mac->dma_rxch, -print_mac (mac_buf, dev->dev_addr)); + mac->dma_if,print_mac (mac_buf, dev->dev_addr));return err;
drivers/net/pasemi_mac.h +10 -9
@@ -28,17 +28,20 @@struct pasemi_mac_txring {spinlock_t lock; +u64 *status;/* Ptr to cacheable status area */ u64 *ring;dma_addr_t dma;unsigned int size;unsigned int next_to_fill;unsigned int next_to_clean;struct pasemi_mac_buffer *ring_info; -char irq_name[10 ];/* "eth%d tx" */ +int chan; +struct pasemi_mac *mac;/* Needed in intr handler */ };struct pasemi_mac_rxring {spinlock_t lock; +u64 *status;/* Ptr to cacheable status area */ u64 *ring;/* RX channel descriptor ring */ dma_addr_t dma;u64 *buffers;/* RX interface buffer ring */
@@ -47,7 +50,7 @@ struct pasemi_mac_rxring {unsigned int next_to_fill;unsigned int next_to_clean;struct pasemi_mac_buffer *ring_info; -char irq_name[10 ];/* "eth%d rx" */ +struct pasemi_mac *mac;/* Needed in intr handler */ };struct pasemi_mac {
@@ -61,16 +64,12 @@ struct pasemi_mac {struct phy_device *phydev;struct napi_struct napi; -/* Pointer to the cacheable per-channel status registers */ -u64 *rx_status; -u64 *tx_status; -u8 type;#define MAC_TYPE_GMAC 1#define MAC_TYPE_XAUI 2u32 dma_txch; -u32 dma_if;u32 dma_rxch; +u32 dma_if;u8 mac_addr[6 ];
@@ -78,8 +77,10 @@ struct pasemi_mac {struct pasemi_mac_txring *tx;struct pasemi_mac_rxring *rx; -unsigned long tx_irq; -unsigned long rx_irq; +unsigned int tx_irq; +unsigned int rx_irq; +char tx_irq_name[10 ];/* "eth%d tx" */ +char rx_irq_name[10 ];/* "eth%d rx" */ int link;int speed;int duplex;
Re: [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup
Quoted 6 lines · Olof Johansson
pasemi_mac: RX/TX ring management cleanupPrepare a bit for supporting multiple TX queues by cleaning up some of the ring management and shuffle things around a bit.
Signed-off-by Olof Johansson <[email protected]>
applied 1-12
PATCH 2/12 pasemi_mac: Move register definitions to include/asm-powerpc
In reply to Olof Johanssonpasemi_mac: Move register definitions to include/asm-powerpc
Move the common register formats and descriptor layouts from drivers/net/pasemi_mac.h to include/asm-poewrpc/pasemi_dma.h
Previously only the ethernet driver was using them, but other drivers are coming up that will also use them, so it makes sense to share the constants.
--- drivers/net/pasemi_mac.c | 1 drivers/net/pasemi_mac.h | 336 --------------------------------- include/asm-powerpc/pasemi_dma.h | 391 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 394 insertions(+), 334 deletions(-)
include/asm-powerpc/pasemi_dma.h new file +391 -0
@@ -0,0 +1,391 @@ +/* +* Copyright (C) 2006 PA Semi, Inc +* +* Hardware register layout and descriptor formats for the on-board +* DMA engine on PA Semi PWRficient. Used by ethernet, function and security +* drivers. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef ASM_PASEMI_DMA_H +#define ASM_PASEMI_DMA_H + +/* status register layout in IOB region, at 0xfb800000 */ +struct pasdma_status { +u64 rx_sta[64 ];/* RX channel status */ +u64 tx_sta[20 ];/* TX channel status */ +}; + + +/* All these registers live in the PCI configuration space for the DMA PCI +* device. Use the normal PCI config access functions for them. +*/ +enum { +PAS_DMA_COM_TXCMD =0x100 ,/* Transmit Command Register */ +PAS_DMA_COM_TXSTA =0x104 ,/* Transmit Status Register */ +PAS_DMA_COM_RXCMD =0x108 ,/* Receive Command Register */ +PAS_DMA_COM_RXSTA =0x10c ,/* Receive Status Register */ +}; +#define PAS_DMA_COM_TXCMD_EN 0x00000001/* enable */ +#define PAS_DMA_COM_TXSTA_ACT 0x00000001/* active */ +#define PAS_DMA_COM_RXCMD_EN 0x00000001/* enable */ +#define PAS_DMA_COM_RXSTA_ACT 0x00000001/* active */ + + +/* Per-interface and per-channel registers */ +#define _PAS_DMA_RXINT_STRIDE 0x20 +#define PAS_DMA_RXINT_RCMDSTA (i) (0x200+(i)*_PAS_DMA_RXINT_STRIDE) +#define PAS_DMA_RXINT_RCMDSTA_EN 0x00000001 +#define PAS_DMA_RXINT_RCMDSTA_ST 0x00000002 +#define PAS_DMA_RXINT_RCMDSTA_MBT 0x00000008 +#define PAS_DMA_RXINT_RCMDSTA_MDR 0x00000010 +#define PAS_DMA_RXINT_RCMDSTA_MOO 0x00000020 +#define PAS_DMA_RXINT_RCMDSTA_MBP 0x00000040 +#define PAS_DMA_RXINT_RCMDSTA_BT 0x00000800 +#define PAS_DMA_RXINT_RCMDSTA_DR 0x00001000 +#define PAS_DMA_RXINT_RCMDSTA_OO 0x00002000 +#define PAS_DMA_RXINT_RCMDSTA_BP 0x00004000 +#define PAS_DMA_RXINT_RCMDSTA_TB 0x00008000 +#define PAS_DMA_RXINT_RCMDSTA_ACT 0x00010000 +#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_ITR 0x00400000 +#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 + +#define PAS_DMA_RXINT_INCR (i) (0x210+(i)*_PAS_DMA_RXINT_STRIDE) +#define PAS_DMA_RXINT_INCR_INCR_M 0x0000ffff +#define PAS_DMA_RXINT_INCR_INCR_S 0 +#define PAS_DMA_RXINT_INCR_INCR (x) ((x) & 0x0000ffff) +#define PAS_DMA_RXINT_BASEL (i) (0x218+(i)*_PAS_DMA_RXINT_STRIDE) +#define PAS_DMA_RXINT_BASEL_BRBL (x) ((x) & ~0x3f) +#define PAS_DMA_RXINT_BASEU (i) (0x21c+(i)*_PAS_DMA_RXINT_STRIDE) +#define PAS_DMA_RXINT_BASEU_BRBH (x) ((x) & 0xfff) +#define PAS_DMA_RXINT_BASEU_SIZ_M 0x3fff0000/* # of cache lines worth of buffer ring */ +#define PAS_DMA_RXINT_BASEU_SIZ_S 16/* 0 = 16K */ +#define PAS_DMA_RXINT_BASEU_SIZ (x) (((x) << PAS_DMA_RXINT_BASEU_SIZ_S) & \ + PAS_DMA_RXINT_BASEU_SIZ_M) + + +#define _PAS_DMA_TXCHAN_STRIDE 0x20/* Size per channel */ +#define _PAS_DMA_TXCHAN_TCMDSTA 0x300/* Command / Status */ +#define _PAS_DMA_TXCHAN_CFG 0x304/* Configuration */ +#define _PAS_DMA_TXCHAN_DSCRBU 0x308/* Descriptor BU Allocation */ +#define _PAS_DMA_TXCHAN_INCR 0x310/* Descriptor increment */ +#define _PAS_DMA_TXCHAN_CNT 0x314/* Descriptor count/offset */ +#define _PAS_DMA_TXCHAN_BASEL 0x318/* Descriptor ring base (low) */ +#define _PAS_DMA_TXCHAN_BASEU 0x31c/* (high) */ +#define PAS_DMA_TXCHAN_TCMDSTA (c) (0x300+(c)*_PAS_DMA_TXCHAN_STRIDE) +#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 +#define PAS_DMA_TXCHAN_CFG_TATTR_S 2 +#define PAS_DMA_TXCHAN_CFG_TATTR (x) (((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \ + PAS_DMA_TXCHAN_CFG_TATTR_M) +#define PAS_DMA_TXCHAN_CFG_WT_M 0x000001c0 +#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_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 +#define PAS_DMA_TXCHAN_BASEL_BRBL_S 0 +#define PAS_DMA_TXCHAN_BASEL_BRBL (x) (((x) << PAS_DMA_TXCHAN_BASEL_BRBL_S) & \ + PAS_DMA_TXCHAN_BASEL_BRBL_M) +#define PAS_DMA_TXCHAN_BASEU (c) (0x31c+(c)*_PAS_DMA_TXCHAN_STRIDE) +#define PAS_DMA_TXCHAN_BASEU_BRBH_M 0x00000fff +#define PAS_DMA_TXCHAN_BASEU_BRBH_S 0 +#define PAS_DMA_TXCHAN_BASEU_BRBH (x) (((x) << PAS_DMA_TXCHAN_BASEU_BRBH_S) & \ + PAS_DMA_TXCHAN_BASEU_BRBH_M) +/* # of cache lines worth of buffer ring */ +#define PAS_DMA_TXCHAN_BASEU_SIZ_M 0x3fff0000 +#define PAS_DMA_TXCHAN_BASEU_SIZ_S 16/* 0 = 16K */ +#define PAS_DMA_TXCHAN_BASEU_SIZ (x) (((x) << PAS_DMA_TXCHAN_BASEU_SIZ_S) & \ + PAS_DMA_TXCHAN_BASEU_SIZ_M) + +#define _PAS_DMA_RXCHAN_STRIDE 0x20/* Size per channel */ +#define _PAS_DMA_RXCHAN_CCMDSTA 0x800/* Command / Status */ +#define _PAS_DMA_RXCHAN_CFG 0x804/* Configuration */ +#define _PAS_DMA_RXCHAN_INCR 0x810/* Descriptor increment */ +#define _PAS_DMA_RXCHAN_CNT 0x814/* Descriptor count/offset */ +#define _PAS_DMA_RXCHAN_BASEL 0x818/* Descriptor ring base (low) */ +#define _PAS_DMA_RXCHAN_BASEU 0x81c/* (high) */ +#define PAS_DMA_RXCHAN_CCMDSTA (c) (0x800+(c)*_PAS_DMA_RXCHAN_STRIDE) +#define PAS_DMA_RXCHAN_CCMDSTA_EN 0x00000001/* Enabled */ +#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_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) & \ + PAS_DMA_RXCHAN_CFG_HBU_M) +#define PAS_DMA_RXCHAN_INCR (c) (0x810+(c)*_PAS_DMA_RXCHAN_STRIDE) +#define PAS_DMA_RXCHAN_BASEL (c) (0x818+(c)*_PAS_DMA_RXCHAN_STRIDE) +#define PAS_DMA_RXCHAN_BASEL_BRBL_M 0xffffffc0 +#define PAS_DMA_RXCHAN_BASEL_BRBL_S 0 +#define PAS_DMA_RXCHAN_BASEL_BRBL (x) (((x) << PAS_DMA_RXCHAN_BASEL_BRBL_S) & \ + PAS_DMA_RXCHAN_BASEL_BRBL_M) +#define PAS_DMA_RXCHAN_BASEU (c) (0x81c+(c)*_PAS_DMA_RXCHAN_STRIDE) +#define PAS_DMA_RXCHAN_BASEU_BRBH_M 0x00000fff +#define PAS_DMA_RXCHAN_BASEU_BRBH_S 0 +#define PAS_DMA_RXCHAN_BASEU_BRBH (x) (((x) << PAS_DMA_RXCHAN_BASEU_BRBH_S) & \ + PAS_DMA_RXCHAN_BASEU_BRBH_M) +/* # of cache lines worth of buffer ring */ +#define PAS_DMA_RXCHAN_BASEU_SIZ_M 0x3fff0000 +#define PAS_DMA_RXCHAN_BASEU_SIZ_S 16/* 0 = 16K */ +#define PAS_DMA_RXCHAN_BASEU_SIZ (x) (((x) << PAS_DMA_RXCHAN_BASEU_SIZ_S) & \ + PAS_DMA_RXCHAN_BASEU_SIZ_M) + +#define PAS_STATUS_PCNT_M 0x000000000000ffffull +#define PAS_STATUS_PCNT_S 0 +#define PAS_STATUS_DCNT_M 0x00000000ffff0000ull +#define PAS_STATUS_DCNT_S 16 +#define PAS_STATUS_BPCNT_M 0x0000ffff00000000ull +#define PAS_STATUS_BPCNT_S 32 +#define PAS_STATUS_CAUSE_M 0xf000000000000000ull +#define PAS_STATUS_TIMER 0x1000000000000000ull +#define PAS_STATUS_ERROR 0x2000000000000000ull +#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 +#define PAS_IOB_DMA_RXCH_CFG_CNTTH (x) (((x) << PAS_IOB_DMA_RXCH_CFG_CNTTH_S) & \ + PAS_IOB_DMA_RXCH_CFG_CNTTH_M) +#define PAS_IOB_DMA_TXCH_CFG (i) (0x1200 + (i)*4) +#define PAS_IOB_DMA_TXCH_CFG_CNTTH_M 0x00000fff +#define PAS_IOB_DMA_TXCH_CFG_CNTTH_S 0 +#define PAS_IOB_DMA_TXCH_CFG_CNTTH (x) (((x) << PAS_IOB_DMA_TXCH_CFG_CNTTH_S) & \ + PAS_IOB_DMA_TXCH_CFG_CNTTH_M) +#define PAS_IOB_DMA_RXCH_STAT (i) (0x1300 + (i)*4) +#define PAS_IOB_DMA_RXCH_STAT_INTGEN 0x00001000 +#define PAS_IOB_DMA_RXCH_STAT_CNTDEL_M 0x00000fff +#define PAS_IOB_DMA_RXCH_STAT_CNTDEL_S 0 +#define PAS_IOB_DMA_RXCH_STAT_CNTDEL (x) (((x) << PAS_IOB_DMA_RXCH_STAT_CNTDEL_S) &\ + PAS_IOB_DMA_RXCH_STAT_CNTDEL_M) +#define PAS_IOB_DMA_TXCH_STAT (i) (0x1400 + (i)*4) +#define PAS_IOB_DMA_TXCH_STAT_INTGEN 0x00001000 +#define PAS_IOB_DMA_TXCH_STAT_CNTDEL_M 0x00000fff +#define PAS_IOB_DMA_TXCH_STAT_CNTDEL_S 0 +#define PAS_IOB_DMA_TXCH_STAT_CNTDEL (x) (((x) << PAS_IOB_DMA_TXCH_STAT_CNTDEL_S) &\ + PAS_IOB_DMA_TXCH_STAT_CNTDEL_M) +#define PAS_IOB_DMA_RXCH_RESET (i) (0x1500 + (i)*4) +#define PAS_IOB_DMA_RXCH_RESET_PCNT_M 0xffff0000 +#define PAS_IOB_DMA_RXCH_RESET_PCNT_S 16 +#define PAS_IOB_DMA_RXCH_RESET_PCNT (x) (((x) << PAS_IOB_DMA_RXCH_RESET_PCNT_S) & \ + PAS_IOB_DMA_RXCH_RESET_PCNT_M) +#define PAS_IOB_DMA_RXCH_RESET_PCNTRST 0x00000020 +#define PAS_IOB_DMA_RXCH_RESET_DCNTRST 0x00000010 +#define PAS_IOB_DMA_RXCH_RESET_TINTC 0x00000008 +#define PAS_IOB_DMA_RXCH_RESET_DINTC 0x00000004 +#define PAS_IOB_DMA_RXCH_RESET_SINTC 0x00000002 +#define PAS_IOB_DMA_RXCH_RESET_PINTC 0x00000001 +#define PAS_IOB_DMA_TXCH_RESET (i) (0x1600 + (i)*4) +#define PAS_IOB_DMA_TXCH_RESET_PCNT_M 0xffff0000 +#define PAS_IOB_DMA_TXCH_RESET_PCNT_S 16 +#define PAS_IOB_DMA_TXCH_RESET_PCNT (x) (((x) << PAS_IOB_DMA_TXCH_RESET_PCNT_S) & \ + PAS_IOB_DMA_TXCH_RESET_PCNT_M) +#define PAS_IOB_DMA_TXCH_RESET_PCNTRST 0x00000020 +#define PAS_IOB_DMA_TXCH_RESET_DCNTRST 0x00000010 +#define PAS_IOB_DMA_TXCH_RESET_TINTC 0x00000008 +#define PAS_IOB_DMA_TXCH_RESET_DINTC 0x00000004 +#define PAS_IOB_DMA_TXCH_RESET_SINTC 0x00000002 +#define PAS_IOB_DMA_TXCH_RESET_PINTC 0x00000001 + +#define PAS_IOB_DMA_COM_TIMEOUTCFG 0x1700 +#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M 0x00ffffff +#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S 0 +#define PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT (x) (((x) << PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_S) & \ + PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT_M) + +/* Transmit descriptor fields */ +#define XCT_MACTX_T 0x8000000000000000ull +#define XCT_MACTX_ST 0x4000000000000000ull +#define XCT_MACTX_NORES 0x0000000000000000ull +#define XCT_MACTX_8BRES 0x1000000000000000ull +#define XCT_MACTX_24BRES 0x2000000000000000ull +#define XCT_MACTX_40BRES 0x3000000000000000ull +#define XCT_MACTX_I 0x0800000000000000ull +#define XCT_MACTX_O 0x0400000000000000ull +#define XCT_MACTX_E 0x0200000000000000ull +#define XCT_MACTX_VLAN_M 0x0180000000000000ull +#define XCT_MACTX_VLAN_NOP 0x0000000000000000ull +#define XCT_MACTX_VLAN_REMOVE 0x0080000000000000ull +#define XCT_MACTX_VLAN_INSERT 0x0100000000000000ull +#define XCT_MACTX_VLAN_REPLACE 0x0180000000000000ull +#define XCT_MACTX_CRC_M 0x0060000000000000ull +#define XCT_MACTX_CRC_NOP 0x0000000000000000ull +#define XCT_MACTX_CRC_INSERT 0x0020000000000000ull +#define XCT_MACTX_CRC_PAD 0x0040000000000000ull +#define XCT_MACTX_CRC_REPLACE 0x0060000000000000ull +#define XCT_MACTX_SS 0x0010000000000000ull +#define XCT_MACTX_LLEN_M 0x00007fff00000000ull +#define XCT_MACTX_LLEN_S 32ull +#define XCT_MACTX_LLEN (x) ((((long)(x)) << XCT_MACTX_LLEN_S) & \ + XCT_MACTX_LLEN_M) +#define XCT_MACTX_IPH_M 0x00000000f8000000ull +#define XCT_MACTX_IPH_S 27ull +#define XCT_MACTX_IPH (x) ((((long)(x)) << XCT_MACTX_IPH_S) & \ + XCT_MACTX_IPH_M) +#define XCT_MACTX_IPO_M 0x0000000007c00000ull +#define XCT_MACTX_IPO_S 22ull +#define XCT_MACTX_IPO (x) ((((long)(x)) << XCT_MACTX_IPO_S) & \ + XCT_MACTX_IPO_M) +#define XCT_MACTX_CSUM_M 0x0000000000000060ull +#define XCT_MACTX_CSUM_NOP 0x0000000000000000ull +#define XCT_MACTX_CSUM_TCP 0x0000000000000040ull +#define XCT_MACTX_CSUM_UDP 0x0000000000000060ull +#define XCT_MACTX_V6 0x0000000000000010ull +#define XCT_MACTX_C 0x0000000000000004ull +#define XCT_MACTX_AL2 0x0000000000000002ull + +/* Receive descriptor fields */ +#define XCT_MACRX_T 0x8000000000000000ull +#define XCT_MACRX_ST 0x4000000000000000ull +#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 +#define XCT_MACRX_PF 0x0080000000000000ull +#define XCT_MACRX_OB 0x0040000000000000ull +#define XCT_MACRX_OD 0x0020000000000000ull +#define XCT_MACRX_FS 0x0010000000000000ull +#define XCT_MACRX_NB_M 0x000fc00000000000ull +#define XCT_MACRX_NB_S 46ULL +#define XCT_MACRX_NB (x) ((((long)(x)) << XCT_MACRX_NB_S) & \ + XCT_MACRX_NB_M) +#define XCT_MACRX_LLEN_M 0x00003fff00000000ull +#define XCT_MACRX_LLEN_S 32ULL +#define XCT_MACRX_LLEN (x) ((((long)(x)) << XCT_MACRX_LLEN_S) & \ + XCT_MACRX_LLEN_M) +#define XCT_MACRX_CRC 0x0000000080000000ull +#define XCT_MACRX_LEN_M 0x0000000060000000ull +#define XCT_MACRX_LEN_TOOSHORT 0x0000000020000000ull +#define XCT_MACRX_LEN_BELOWMIN 0x0000000040000000ull +#define XCT_MACRX_LEN_TRUNC 0x0000000060000000ull +#define XCT_MACRX_CAST_M 0x0000000018000000ull +#define XCT_MACRX_CAST_UNI 0x0000000000000000ull +#define XCT_MACRX_CAST_MULTI 0x0000000008000000ull +#define XCT_MACRX_CAST_BROAD 0x0000000010000000ull +#define XCT_MACRX_CAST_PAUSE 0x0000000018000000ull +#define XCT_MACRX_VLC_M 0x0000000006000000ull +#define XCT_MACRX_FM 0x0000000001000000ull +#define XCT_MACRX_HTY_M 0x0000000000c00000ull +#define XCT_MACRX_HTY_IPV4_OK 0x0000000000000000ull +#define XCT_MACRX_HTY_IPV6 0x0000000000400000ull +#define XCT_MACRX_HTY_IPV4_BAD 0x0000000000800000ull +#define XCT_MACRX_HTY_NONIP 0x0000000000c00000ull +#define XCT_MACRX_IPP_M 0x00000000003f0000ull +#define XCT_MACRX_IPP_S 16 +#define XCT_MACRX_CSUM_M 0x000000000000ffffull +#define XCT_MACRX_CSUM_S 0 + +#define XCT_PTR_T 0x8000000000000000ull +#define XCT_PTR_LEN_M 0x7ffff00000000000ull +#define XCT_PTR_LEN_S 44 +#define XCT_PTR_LEN (x) ((((long)(x)) << XCT_PTR_LEN_S) & \ + XCT_PTR_LEN_M) +#define XCT_PTR_ADDR_M 0x00000fffffffffffull +#define XCT_PTR_ADDR_S 0 +#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 +#define XCT_RXB_LEN (x) ((((long)(x)) << XCT_RXB_LEN_S) & \ + XCT_RXB_LEN_M) +#define XCT_RXB_ADDR_M 0x00000fffffffffffull +#define XCT_RXB_ADDR_S 0 +#define XCT_RXB_ADDR (x) ((((long)(x)) << XCT_RXB_ADDR_S) & \ + XCT_RXB_ADDR_M) + +/* Copy descriptor fields */ +#define XCT_COPY_T 0x8000000000000000ull +#define XCT_COPY_ST 0x4000000000000000ull +#define XCT_COPY_RR_M 0x3000000000000000ull +#define XCT_COPY_RR_NORES 0x0000000000000000ull +#define XCT_COPY_RR_8BRES 0x1000000000000000ull +#define XCT_COPY_RR_24BRES 0x2000000000000000ull +#define XCT_COPY_RR_40BRES 0x3000000000000000ull +#define XCT_COPY_I 0x0800000000000000ull +#define XCT_COPY_O 0x0400000000000000ull +#define XCT_COPY_E 0x0200000000000000ull +#define XCT_COPY_STY_ZERO 0x01c0000000000000ull +#define XCT_COPY_DTY_PREF 0x0038000000000000ull +#define XCT_COPY_LLEN_M 0x0007ffff00000000ull +#define XCT_COPY_LLEN_S 32 +#define XCT_COPY_LLEN (x) ((((long)(x)) << XCT_COPY_LLEN_S) & \ + XCT_COPY_LLEN_M) +#define XCT_COPY_SE 0x0000000000000001ull + +/* Control descriptor fields */ +#define CTRL_CMD_T 0x8000000000000000ull +#define CTRL_CMD_META_EVT 0x2000000000000000ull +#define CTRL_CMD_O 0x0400000000000000ull +#define CTRL_CMD_REG_M 0x000000000000000full +#define CTRL_CMD_REG_S 0 +#define CTRL_CMD_REG (x) ((((long)(x)) << CTRL_CMD_REG_S) & \ + CTRL_CMD_REG_M) + + +#endif /* ASM_PASEMI_DMA_H */
drivers/net/pasemi_mac.c +1 -0
@@ -35,6 +35,7 @@#include <asm/irq.h> #include <asm/firmware.h> +#include <asm/pasemi_dma.h> #include "pasemi_mac.h"
drivers/net/pasemi_mac.h +2 -334
346 lines not on this page · raw message
PATCH 3/12 pasemi: DMA engine management library
In reply to Olof Johanssonpasemi: DMA engine management library
Introduce a DMA management library to manage the various DMA resources on the PA Semi SoCs. Since several drivers need to allocate these shared resources, provide some abstractions as well as allocation/free functions for channels, etc.
--- arch/powerpc/platforms/pasemi/Makefile | 2 arch/powerpc/platforms/pasemi/dma_lib.c | 487 ++++++++++++++++++++++++++++++++ arch/powerpc/platforms/pasemi/pasemi.h | 1 include/asm-powerpc/pasemi_dma.h | 76 ++++ 4 files changed, 565 insertions(+), 1 deletion(-)
arch/powerpc/platforms/pasemi/Makefile +1 -1
@@ -1,4 +1,4 @@ -obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o +obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o dma_lib.o obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
arch/powerpc/platforms/pasemi/dma_lib.c new file +487 -0
487 lines not on this page · raw message
arch/powerpc/platforms/pasemi/pasemi.h +1 -0
@@ -9,6 +9,7 @@ extern void __devinit pas_pci_dma_dev_seextern void __iomem *pasemi_pci_getcfgaddr (struct pci_dev *dev,int offset);extern void __init alloc_iobmap_l2 (void ); +extern void __init pasemi_map_registers (void );/* Power savings modes, implemented in asm */ extern void idle_spin (void );
include/asm-powerpc/pasemi_dma.h +76 -0
91 lines not on this page · raw message
PATCH 4/12 pasemi_mac: Convert to new dma library
In reply to Olof Johanssonpasemi_mac: Convert to new dma library
Convert the pasemi_mac driver to the new platform global DMA manaagement library. This also does a couple of other minor cleanups w.r.t. channel management.
--- drivers/net/pasemi_mac.c | 480 ++++++++++++++++++++--------------------------- drivers/net/pasemi_mac.h | 16 - 2 files changed, 210 insertions(+), 286 deletions(-)
drivers/net/pasemi_mac.c +208 -272
@@ -69,9 +69,9 @@ NETIF_MSG_RX_ERR | \ NETIF_MSG_TX_ERR) -#define TX_DESC (tx, num) ((tx)->ring[(num) & (TX_RING_SIZE-1)]) +#define TX_DESC (tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])#define TX_DESC_INFO (tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)]) -#define RX_DESC (rx, num) ((rx)->ring[(num) & (RX_RING_SIZE-1)]) +#define RX_DESC (rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])#define RX_DESC_INFO (rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])#define RX_BUFF (rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
@@ -89,8 +89,6 @@ static int debug = -1; /* -1 == use DEFAmodule_param (debug, int,0 );MODULE_PARM_DESC (debug,"PA Semi MAC bitmapped debugging message enable value" ); -static struct pasdma_status *dma_status; -static int translation_enabled (void ) {#if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE )
@@ -100,32 +98,30 @@ static int translation_enabled(void)#endif } -static void write_iob_reg (struct pasemi_mac *mac,unsigned int reg, -unsigned int val) +static void write_iob_reg (unsigned int reg,unsigned int val) { -out_le32 (mac->iob_regs+reg, val); +pasemi_write_iob_reg (reg, val); }static unsigned int read_mac_reg (struct pasemi_mac *mac,unsigned int reg) { -return in_le32 (mac->regs+reg); +return pasemi_read_mac_reg (mac->dma_if, reg); }static void write_mac_reg (struct pasemi_mac *mac,unsigned int reg,unsigned int val) { -out_le32 (mac->regs+reg, val); +pasemi_write_mac_reg (mac->dma_if, reg, val); } -static unsigned int read_dma_reg (struct pasemi_mac *mac,unsigned int reg) +static unsigned int read_dma_reg (unsigned int reg) { -return in_le32 (mac->dma_regs+reg); +return pasemi_read_dma_reg (reg); } -static void write_dma_reg (struct pasemi_mac *mac,unsigned int reg, -unsigned int val) +static void write_dma_reg (unsigned int reg,unsigned int val) { -out_le32 (mac->dma_regs+reg, val); +pasemi_write_dma_reg (reg, val); }static struct pasemi_mac_rxring *rx_ring (struct pasemi_mac *mac)
@@ -138,6 +134,34 @@ static struct pasemi_mac_txring *tx_ringreturn mac->tx; } +static int mac_to_intf (struct pasemi_mac *mac) +{ +struct pci_dev *pdev = mac->pdev; +u32 tmp; +int nintf, off, i, j; +int devfn = pdev->devfn; + + tmp =read_dma_reg (PAS_DMA_CAP_IFI ); + nintf = (tmp &PAS_DMA_CAP_IFI_NIN_M ) >>PAS_DMA_CAP_IFI_NIN_S ; + off = (tmp &PAS_DMA_CAP_IFI_IOFF_M ) >>PAS_DMA_CAP_IFI_IOFF_S ; + +/* IOFF contains the offset to the registers containing the +* DMA interface-to-MAC-pci-id mappings, and NIN contains number +* of total interfaces. Each register contains 4 devfns. +* Just do a linear search until we find the devfn of the MAC +* we're trying to look up. +*/ + +for (i =0 ; i < (nintf+3 )/4 ; i++) { + tmp =read_dma_reg (off+4 *i); +for (j =0 ; j <4 ; j++) { +if (((tmp >> (8 *j)) &0xff ) == devfn) +return i*4 + j; + } + } +return -1 ; +} +static int pasemi_get_mac_addr (struct pasemi_mac *mac) {struct pci_dev *pdev = mac->pdev;
@@ -213,13 +237,17 @@ static int pasemi_mac_setup_rx_resources {struct pasemi_mac_rxring *ring;struct pasemi_mac *mac =netdev_priv (dev); -int chan_id = mac->dma_rxch; +int chno;unsigned int cfg; - ring =kzalloc (sizeof (*ring),GFP_KERNEL ); + ring =pasemi_dma_alloc_chan (RXCHAN ,sizeof (struct pasemi_mac_rxring ), + offsetof(struct pasemi_mac_rxring , chan)); -if (!ring) - goto out_ring; +if (!ring) { +dev_err (&mac->pdev->dev,"Can't allocate RX channel\n" ); + goto out_chan; + } + chno = ring->chan.chno;spin_lock_init (&ring->lock);
@@ -231,84 +259,80 @@ static int pasemi_mac_setup_rx_resources goto out_ring_info;/* Allocate descriptors */ - ring->ring =dma_alloc_coherent (&mac->dma_pdev->dev, -RX_RING_SIZE *sizeof (u64), - &ring->dma,GFP_KERNEL ); - -if (!ring->ring) +if (pasemi_dma_alloc_ring (&ring->chan,RX_RING_SIZE )) goto out_ring_desc; -memset (ring->ring,0 ,RX_RING_SIZE *sizeof (u64)); - ring->buffers =dma_alloc_coherent (&mac->dma_pdev->dev,RX_RING_SIZE *sizeof (u64), &ring->buf_dma,GFP_KERNEL );if (!ring->buffers) - goto out_buffers; + goto out_ring_desc;memset (ring->buffers,0 ,RX_RING_SIZE *sizeof (u64)); -write_dma_reg (mac,PAS_DMA_RXCHAN_BASEL (chan_id),PAS_DMA_RXCHAN_BASEL_BRBL (ring->dma)); +write_dma_reg (PAS_DMA_RXCHAN_BASEL (chno), +PAS_DMA_RXCHAN_BASEL_BRBL (ring->chan.ring_dma)); -write_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 >>3 )); +write_dma_reg (PAS_DMA_RXCHAN_BASEU (chno), +PAS_DMA_RXCHAN_BASEU_BRBH (ring->chan.ring_dma >>32 ) | +PAS_DMA_RXCHAN_BASEU_SIZ (RX_RING_SIZE >>3 )); - cfg =PAS_DMA_RXCHAN_CFG_HBU (2 ); + cfg =PAS_DMA_RXCHAN_CFG_HBU (1 );if (translation_enabled ()) cfg |=PAS_DMA_RXCHAN_CFG_CTR ; -write_dma_reg (mac,PAS_DMA_RXCHAN_CFG (chan_id), cfg); +write_dma_reg (PAS_DMA_RXCHAN_CFG (chno), cfg); -write_dma_reg (mac,PAS_DMA_RXINT_BASEL (mac->dma_if), -PAS_DMA_RXINT_BASEL_BRBL (ring->buf_dma)); +write_dma_reg (PAS_DMA_RXINT_BASEL (mac->dma_if), +PAS_DMA_RXINT_BASEL_BRBL (ring->buf_dma)); -write_dma_reg (mac,PAS_DMA_RXINT_BASEU (mac->dma_if), -PAS_DMA_RXINT_BASEU_BRBH (ring->buf_dma >>32 ) | -PAS_DMA_RXINT_BASEU_SIZ (RX_RING_SIZE >>3 )); +write_dma_reg (PAS_DMA_RXINT_BASEU (mac->dma_if), +PAS_DMA_RXINT_BASEU_BRBH (ring->buf_dma >>32 ) | +PAS_DMA_RXINT_BASEU_SIZ (RX_RING_SIZE >>3 )); - cfg =PAS_DMA_RXINT_CFG_DHL (3 ) |PAS_DMA_RXINT_CFG_L2 | + cfg =PAS_DMA_RXINT_CFG_DHL (1 ) |PAS_DMA_RXINT_CFG_L2 |PAS_DMA_RXINT_CFG_LW |PAS_DMA_RXINT_CFG_RBP |PAS_DMA_RXINT_CFG_HEN ;if (translation_enabled ()) cfg |=PAS_DMA_RXINT_CFG_ITRR |PAS_DMA_RXINT_CFG_ITR ; -write_dma_reg (mac,PAS_DMA_RXINT_CFG (mac->dma_if), cfg); +write_dma_reg (PAS_DMA_RXINT_CFG (mac->dma_if), cfg); ring->next_to_fill =0 ; ring->next_to_clean =0 ; - - ring->status = &dma_status->rx_sta[mac->dma_rxch]; ring->mac = mac; mac->rx = ring;return 0 ; -out_buffers: -dma_free_coherent (&mac->dma_pdev->dev, -RX_RING_SIZE *sizeof (u64), -rx_ring (mac)->ring,rx_ring (mac)->dma); out_ring_desc:kfree (ring->ring_info); out_ring_info: -kfree (ring); -out_ring: +pasemi_dma_free_chan (&ring->chan); +out_chan:return -ENOMEM ; }static struct pasemi_mac_txring * -pasemi_mac_setup_tx_resources (struct net_device *dev,int txch) +pasemi_mac_setup_tx_resources (struct net_device *dev) {struct pasemi_mac *mac =netdev_priv (dev);u32 val;struct pasemi_mac_txring *ring;unsigned int cfg; +int chno; - ring =kzalloc (sizeof (*ring),GFP_KERNEL ); -if (!ring) - goto out_ring; + ring =pasemi_dma_alloc_chan (TXCHAN ,sizeof (struct pasemi_mac_txring ), + offsetof(struct pasemi_mac_txring , chan)); + +if (!ring) { +dev_err (&mac->pdev->dev,"Can't allocate TX channel\n" ); + goto out_chan; + } + + chno = ring->chan.chno;spin_lock_init (&ring->lock);
@@ -319,20 +343,15 @@ pasemi_mac_setup_tx_resources(struct net goto out_ring_info;/* Allocate descriptors */ - ring->ring =dma_alloc_coherent (&mac->dma_pdev->dev, -TX_RING_SIZE *sizeof (u64), - &ring->dma,GFP_KERNEL ); -if (!ring->ring) +if (pasemi_dma_alloc_ring (&ring->chan,TX_RING_SIZE )) goto out_ring_desc; -memset (ring->ring,0 ,TX_RING_SIZE *sizeof (u64)); - -write_dma_reg (mac,PAS_DMA_TXCHAN_BASEL (txch), -PAS_DMA_TXCHAN_BASEL_BRBL (ring->dma)); - val =PAS_DMA_TXCHAN_BASEU_BRBH (ring->dma >>32 ); +write_dma_reg (PAS_DMA_TXCHAN_BASEL (chno), +PAS_DMA_TXCHAN_BASEL_BRBL (ring->chan.ring_dma)); + val =PAS_DMA_TXCHAN_BASEU_BRBH (ring->chan.ring_dma >>32 ); val |=PAS_DMA_TXCHAN_BASEU_SIZ (TX_RING_SIZE >>3 ); -write_dma_reg (mac,PAS_DMA_TXCHAN_BASEU (txch), val); +write_dma_reg (PAS_DMA_TXCHAN_BASEU (chno), val); cfg =PAS_DMA_TXCHAN_CFG_TY_IFACE | PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
@@ -342,12 +361,10 @@ pasemi_mac_setup_tx_resources(struct netif (translation_enabled ()) cfg |=PAS_DMA_TXCHAN_CFG_TRD |PAS_DMA_TXCHAN_CFG_TRR ; -write_dma_reg (mac,PAS_DMA_TXCHAN_CFG (txch), cfg); +write_dma_reg (PAS_DMA_TXCHAN_CFG (chno), cfg); ring->next_to_fill =0 ; ring->next_to_clean =0 ; - ring->status = &dma_status->tx_sta[txch]; - ring->chan = txch; ring->mac = mac;return ring;
@@ -355,8 +372,8 @@ pasemi_mac_setup_tx_resources(struct net out_ring_desc:kfree (ring->ring_info); out_ring_info: -kfree (ring); -out_ring: +pasemi_dma_free_chan (&ring->chan); +out_chan:return NULL ; }
@@ -387,15 +404,9 @@ static void pasemi_mac_free_tx_resources freed =2 ; } -for (i =0 ; i <TX_RING_SIZE ; i++) - txring->ring[i] =0 ; - -dma_free_coherent (&mac->dma_pdev->dev, -TX_RING_SIZE *sizeof (u64), - txring->ring, txring->dma); -kfree (txring->ring_info); -kfree (txring); +pasemi_dma_free_chan (&txring->chan); + }static void pasemi_mac_free_rx_resources (struct pasemi_mac *mac)
@@ -420,15 +431,11 @@ static void pasemi_mac_free_rx_resourcesfor (i =0 ; i <RX_RING_SIZE ; i++)RX_DESC (rx, i) =0 ; -dma_free_coherent (&mac->dma_pdev->dev, -RX_RING_SIZE *sizeof (u64), -rx_ring (mac)->ring,rx_ring (mac)->dma); -dma_free_coherent (&mac->dma_pdev->dev,RX_RING_SIZE *sizeof (u64),rx_ring (mac)->buffers,rx_ring (mac)->buf_dma);kfree (rx_ring (mac)->ring_info); -kfree (rx_ring (mac)); +pasemi_dma_free_chan (&rx_ring (mac)->chan); mac->rx =NULL ; }
@@ -479,7 +486,7 @@ static void pasemi_mac_replenish_rx_ringwmb (); -write_dma_reg (mac,PAS_DMA_RXINT_INCR (mac->dma_if), count); +write_dma_reg (PAS_DMA_RXINT_INCR (mac->dma_if), count);rx_ring (mac)->next_to_fill = (rx_ring (mac)->next_to_fill + count) & (RX_RING_SIZE -1 );
@@ -492,11 +499,11 @@ static void pasemi_mac_restart_rx_intr(s* ack the packet count interrupt we got in rx_intr. */ - pcnt = *rx_ring (mac)->status &PAS_STATUS_PCNT_M ; + pcnt = *rx_ring (mac)->chan.status &PAS_STATUS_PCNT_M ; reg =PAS_IOB_DMA_RXCH_RESET_PCNT (pcnt) |PAS_IOB_DMA_RXCH_RESET_PINTC ; -write_iob_reg (mac,PAS_IOB_DMA_RXCH_RESET (mac->dma_rxch), reg); +write_iob_reg (PAS_IOB_DMA_RXCH_RESET (mac->rx->chan.chno), reg); }static void pasemi_mac_restart_tx_intr (struct pasemi_mac *mac)
@@ -504,26 +511,27 @@ static void pasemi_mac_restart_tx_intr(sunsigned int reg, pcnt;/* Re-enable packet count interrupts */ - pcnt = *tx_ring (mac)->status &PAS_STATUS_PCNT_M ; + pcnt = *tx_ring (mac)->chan.status &PAS_STATUS_PCNT_M ; reg =PAS_IOB_DMA_TXCH_RESET_PCNT (pcnt) |PAS_IOB_DMA_TXCH_RESET_PINTC ; -write_iob_reg (mac,PAS_IOB_DMA_TXCH_RESET (tx_ring (mac)->chan), reg); +write_iob_reg (PAS_IOB_DMA_TXCH_RESET (tx_ring (mac)->chan.chno), reg); }static inline void pasemi_mac_rx_error (struct pasemi_mac *mac,u64 macrx) {unsigned int rcmdsta, ccmdsta; +struct pasemi_dmachan *chan = &rx_ring (mac)->chan;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)); + rcmdsta =read_dma_reg (PAS_DMA_RXINT_RCMDSTA (mac->dma_if)); + ccmdsta =read_dma_reg (PAS_DMA_RXCHAN_CCMDSTA (chan->chno));printk (KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n" , - macrx, *rx_ring (mac)->status); + macrx, *chan->status);printk (KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n" , rcmdsta, ccmdsta);
@@ -532,20 +540,22 @@ static inline void pasemi_mac_rx_error(sstatic inline void pasemi_mac_tx_error (struct pasemi_mac *mac,u64 mactx) {unsigned int cmdsta; +struct pasemi_dmachan *chan = &tx_ring (mac)->chan;if (!netif_msg_tx_err (mac))return ; - cmdsta =read_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch)); + cmdsta =read_dma_reg (PAS_DMA_TXCHAN_TCMDSTA (chan->chno));printk (KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, " \ -"tx status 0x%016lx\n" , mactx, *tx_ring (mac)->status); +"tx status 0x%016lx\n" , mactx, *chan->status);printk (KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n" , cmdsta); }static int pasemi_mac_clean_rx (struct pasemi_mac_rxring *rx,int limit) { +struct pasemi_dmachan *chan = &rx->chan;struct pasemi_mac *mac = rx->mac;unsigned int n;int count;
@@ -567,7 +577,7 @@ static int pasemi_mac_clean_rx(struct pa macrx =RX_DESC (rx, n);if ((macrx &XCT_MACRX_E ) || - (*rx_ring (mac)->status &PAS_STATUS_ERROR )) + (*chan->status &PAS_STATUS_ERROR ))pasemi_mac_rx_error (mac, macrx);if (!(macrx &XCT_MACRX_O ))
@@ -648,7 +658,7 @@ next:if (n >RX_RING_SIZE ) {/* Errata 5971 workaround: L2 target of headers */ -write_iob_reg (mac,PAS_IOB_COM_PKTHDRCNT ,0 ); +write_iob_reg (PAS_IOB_COM_PKTHDRCNT ,0 ); n &= (RX_RING_SIZE -1 ); }
@@ -658,7 +668,7 @@ next:* 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 ); +write_dma_reg (PAS_DMA_RXCHAN_INCR (mac->rx->chan.chno), count <<1 );pasemi_mac_replenish_rx_ring (mac->netdev, count);
@@ -672,6 +682,7 @@ next:static int pasemi_mac_clean_tx (struct pasemi_mac_txring *txring) { +struct pasemi_dmachan *chan = &txring->chan;struct pasemi_mac *mac = txring->mac;int i, j;unsigned int start, descr_count, buf_count, batch_limit;
@@ -703,7 +714,7 @@ restart:struct sk_buff *skb;if ((mactx &XCT_MACTX_E ) || - (*tx_ring (mac)->status &PAS_STATUS_ERROR )) + (*chan->status &PAS_STATUS_ERROR ))pasemi_mac_tx_error (mac, mactx);if (unlikely (mactx &XCT_MACTX_O ))
@@ -747,11 +758,13 @@ restart:static irqreturn_t pasemi_mac_rx_intr (int irq,void *data) { -struct net_device *dev = data; -struct pasemi_mac *mac =netdev_priv (dev); +struct pasemi_mac_rxring *rxring = data; +struct pasemi_mac *mac = rxring->mac; +struct net_device *dev = mac->netdev; +struct pasemi_dmachan *chan = &rxring->chan;unsigned int reg; -if (!(*rx_ring (mac)->status &PAS_STATUS_CAUSE_M )) +if (!(*chan->status &PAS_STATUS_CAUSE_M ))return IRQ_NONE ;/* Don't reset packet count so it won't fire again but clear
@@ -759,16 +772,16 @@ static irqreturn_t pasemi_mac_rx_intr(in*/ reg =0 ; -if (*rx_ring (mac)->status &PAS_STATUS_SOFT ) +if (*chan->status &PAS_STATUS_SOFT ) reg |=PAS_IOB_DMA_RXCH_RESET_SINTC ; -if (*rx_ring (mac)->status &PAS_STATUS_ERROR ) +if (*chan->status &PAS_STATUS_ERROR ) reg |=PAS_IOB_DMA_RXCH_RESET_DINTC ; -if (*rx_ring (mac)->status &PAS_STATUS_TIMER ) +if (*chan->status &PAS_STATUS_TIMER ) reg |=PAS_IOB_DMA_RXCH_RESET_TINTC ;netif_rx_schedule (dev, &mac->napi); -write_iob_reg (mac,PAS_IOB_DMA_RXCH_RESET (mac->dma_rxch), reg); +write_iob_reg (PAS_IOB_DMA_RXCH_RESET (chan->chno), reg);return IRQ_HANDLED ; }
@@ -776,24 +789,24 @@ static irqreturn_t pasemi_mac_rx_intr(instatic irqreturn_t pasemi_mac_tx_intr (int irq,void *data) {struct pasemi_mac_txring *txring = data; -struct pasemi_mac *mac = txring->mac; +struct pasemi_dmachan *chan = &txring->chan;unsigned int reg, pcnt; -if (!(*txring->status &PAS_STATUS_CAUSE_M )) +if (!(*chan->status &PAS_STATUS_CAUSE_M ))return IRQ_NONE ;pasemi_mac_clean_tx (txring); - pcnt = *txring->status &PAS_STATUS_PCNT_M ; + pcnt = *chan->status &PAS_STATUS_PCNT_M ; reg =PAS_IOB_DMA_TXCH_RESET_PCNT (pcnt) |PAS_IOB_DMA_TXCH_RESET_PINTC ; -if (*txring->status &PAS_STATUS_SOFT ) +if (*chan->status &PAS_STATUS_SOFT ) reg |=PAS_IOB_DMA_TXCH_RESET_SINTC ; -if (*txring->status &PAS_STATUS_ERROR ) +if (*chan->status &PAS_STATUS_ERROR ) reg |=PAS_IOB_DMA_TXCH_RESET_DINTC ; -write_iob_reg (mac,PAS_IOB_DMA_TXCH_RESET (txring->chan), reg); +write_iob_reg (PAS_IOB_DMA_TXCH_RESET (chan->chno), reg);return IRQ_HANDLED ; }
@@ -909,15 +922,14 @@ err:static int pasemi_mac_open (struct net_device *dev) {struct pasemi_mac *mac =netdev_priv (dev); -int base_irq;unsigned int flags;int ret;/* enable rx section */ -write_dma_reg (mac,PAS_DMA_COM_RXCMD ,PAS_DMA_COM_RXCMD_EN ); +write_dma_reg (PAS_DMA_COM_RXCMD ,PAS_DMA_COM_RXCMD_EN );/* enable tx section */ -write_dma_reg (mac,PAS_DMA_COM_TXCMD ,PAS_DMA_COM_TXCMD_EN ); +write_dma_reg (PAS_DMA_COM_TXCMD ,PAS_DMA_COM_TXCMD_EN ); flags =PAS_MAC_CFG_TXP_FCE |PAS_MAC_CFG_TXP_FPC (3 ) | PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
@@ -925,56 +937,53 @@ static int pasemi_mac_open(struct net_dewrite_mac_reg (mac,PAS_MAC_CFG_TXP , flags); -write_iob_reg (mac,PAS_IOB_DMA_RXCH_CFG (mac->dma_rxch), -PAS_IOB_DMA_RXCH_CFG_CNTTH (0 )); - -write_iob_reg (mac,PAS_IOB_DMA_TXCH_CFG (mac->dma_txch), -PAS_IOB_DMA_TXCH_CFG_CNTTH (128 )); -/* 0xffffff is max value, about 16ms */ -write_iob_reg (mac,PAS_IOB_DMA_COM_TIMEOUTCFG , -PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT (0xffffff )); +write_iob_reg (PAS_IOB_DMA_COM_TIMEOUTCFG , +PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT (0xffffff )); ret =pasemi_mac_setup_rx_resources (dev);if (ret) goto out_rx_resources; - mac->tx =pasemi_mac_setup_tx_resources (dev, mac->dma_txch); + mac->tx =pasemi_mac_setup_tx_resources (dev);if (!mac->tx) goto out_tx_ring; +write_iob_reg (PAS_IOB_DMA_RXCH_CFG (mac->rx->chan.chno), +PAS_IOB_DMA_RXCH_CFG_CNTTH (0 )); + +write_iob_reg (PAS_IOB_DMA_TXCH_CFG (mac->tx->chan.chno), +PAS_IOB_DMA_TXCH_CFG_CNTTH (128 )); +write_mac_reg (mac,PAS_MAC_IPC_CHNL , -PAS_MAC_IPC_CHNL_DCHNO (mac->dma_rxch) | -PAS_MAC_IPC_CHNL_BCH (mac->dma_rxch)); +PAS_MAC_IPC_CHNL_DCHNO (mac->rx->chan.chno) | +PAS_MAC_IPC_CHNL_BCH (mac->rx->chan.chno));/* enable rx if */ -write_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if), -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 ); +write_dma_reg (PAS_DMA_RXINT_RCMDSTA (mac->dma_if), +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_OD | -PAS_DMA_RXCHAN_CCMDSTA_FD | -PAS_DMA_RXCHAN_CCMDSTA_DT ); +pasemi_dma_start_chan (&rx_ring (mac)->chan,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_SZ | -PAS_DMA_TXCHAN_TCMDSTA_DB | -PAS_DMA_TXCHAN_TCMDSTA_DE | -PAS_DMA_TXCHAN_TCMDSTA_DA ); +pasemi_dma_start_chan (&tx_ring (mac)->chan,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 ); -write_dma_reg (mac,PAS_DMA_RXCHAN_INCR (mac->dma_rxch),RX_RING_SIZE >>1 ); +write_dma_reg (PAS_DMA_RXCHAN_INCR (rx_ring (mac)->chan.chno), +RX_RING_SIZE >>1 );/* Clear out any residual packet count state from firmware */ pasemi_mac_restart_rx_intr (mac);
@@ -1001,37 +1010,25 @@ static int pasemi_mac_open(struct net_denetif_start_queue (dev);napi_enable (&mac->napi); -/* Interrupts are a bit different for our DMA controller: While -* it's got one a regular PCI device header, the interrupt there -* is really the base of the range it's using. Each tx and rx -* channel has it's own interrupt source. -*/ - - base_irq =virq_to_hw (mac->dma_pdev->irq); - - mac->tx_irq =irq_create_mapping (NULL , base_irq + mac->dma_txch); -snprintf (mac->tx_irq_name,sizeof (mac->tx_irq_name),"%s tx" , dev->name); - ret =request_irq (mac->tx_irq, &pasemi_mac_tx_intr,IRQF_DISABLED , + ret =request_irq (mac->tx->chan.irq, &pasemi_mac_tx_intr,IRQF_DISABLED , mac->tx_irq_name, mac->tx);if (ret) {dev_err (&mac->pdev->dev,"request_irq of irq %d failed: %d\n" , - base_irq + mac->dma_txch, ret); + mac->tx->chan.irq, ret); goto out_tx_int; } - mac->rx_irq =irq_create_mapping (NULL , base_irq +20 + mac->dma_rxch); -snprintf (mac->rx_irq_name,sizeof (mac->rx_irq_name),"%s rx" , dev->name); - ret =request_irq (mac->rx_irq, &pasemi_mac_rx_intr,IRQF_DISABLED , - mac->rx_irq_name, dev); + ret =request_irq (mac->rx->chan.irq, &pasemi_mac_rx_intr,IRQF_DISABLED , + mac->rx_irq_name, mac->rx);if (ret) {dev_err (&mac->pdev->dev,"request_irq of irq %d failed: %d\n" , - base_irq +20 + mac->dma_rxch, ret); + mac->rx->chan.irq, ret); goto out_rx_int; }
@@ -1041,7 +1038,7 @@ static int pasemi_mac_open(struct net_dereturn 0 ; out_rx_int: -free_irq (mac->tx_irq, mac->tx); +free_irq (mac->tx->chan.irq, mac->tx); out_tx_int:napi_disable (&mac->napi);netif_stop_queue (dev);
@@ -1061,6 +1058,10 @@ static int pasemi_mac_close(struct net_dstruct pasemi_mac *mac =netdev_priv (dev);unsigned int sta;int retries; +int rxch, txch; + + rxch =rx_ring (mac)->chan.chno; + txch =tx_ring (mac)->chan.chno;if (mac->phydev) {phy_stop (mac->phydev);
@@ -1070,20 +1071,20 @@ 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)); + sta =read_dma_reg (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)); + sta =read_dma_reg (PAS_DMA_RXCHAN_CCMDSTA (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)); + sta =read_dma_reg (PAS_DMA_TXCHAN_TCMDSTA (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);
@@ -1093,26 +1094,25 @@ static int pasemi_mac_close(struct net_dpasemi_mac_clean_rx (rx_ring (mac),RX_RING_SIZE );/* Disable interface */ -write_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch), +write_dma_reg (PAS_DMA_TXCHAN_TCMDSTA (txch),PAS_DMA_TXCHAN_TCMDSTA_ST ); -write_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if), +write_dma_reg (PAS_DMA_RXINT_RCMDSTA (mac->dma_if),PAS_DMA_RXINT_RCMDSTA_ST ); -write_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch), +write_dma_reg (PAS_DMA_RXCHAN_CCMDSTA (rxch),PAS_DMA_RXCHAN_CCMDSTA_ST );for (retries =0 ; retries <MAX_RETRIES ; retries++) { - sta =read_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch)); + sta =read_dma_reg (PAS_DMA_TXCHAN_TCMDSTA (rxch));if (!(sta &PAS_DMA_TXCHAN_TCMDSTA_ACT ))break ;cond_resched (); }if (sta &PAS_DMA_TXCHAN_TCMDSTA_ACT ) -dev_err (&mac->dma_pdev->dev,"Failed to stop tx channel %d\n" , - mac->dma_txch); +dev_err (&mac->dma_pdev->dev,"Failed to stop tx channel\n" );for (retries =0 ; retries <MAX_RETRIES ; retries++) { - sta =read_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch)); + sta =read_dma_reg (PAS_DMA_RXCHAN_CCMDSTA (rxch));if (!(sta &PAS_DMA_RXCHAN_CCMDSTA_ACT ))break ;cond_resched ();
@@ -1122,7 +1122,7 @@ static int pasemi_mac_close(struct net_ddev_err (&mac->dma_pdev->dev,"Failed to stop rx channel\n" );for (retries =0 ; retries <MAX_RETRIES ; retries++) { - sta =read_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if)); + sta =read_dma_reg (PAS_DMA_RXINT_RCMDSTA (mac->dma_if));if (!(sta &PAS_DMA_RXINT_RCMDSTA_ACT ))break ;cond_resched ();
@@ -1135,12 +1135,12 @@ static int pasemi_mac_close(struct net_d* stopping, since you can't disable when active. */ -write_dma_reg (mac,PAS_DMA_TXCHAN_TCMDSTA (mac->dma_txch),0 ); -write_dma_reg (mac,PAS_DMA_RXCHAN_CCMDSTA (mac->dma_rxch),0 ); -write_dma_reg (mac,PAS_DMA_RXINT_RCMDSTA (mac->dma_if),0 ); +write_dma_reg (PAS_DMA_TXCHAN_TCMDSTA (txch),0 ); +write_dma_reg (PAS_DMA_RXCHAN_CCMDSTA (rxch),0 ); +write_dma_reg (PAS_DMA_RXINT_RCMDSTA (mac->dma_if),0 ); -free_irq (mac->tx_irq, mac->tx); -free_irq (mac->rx_irq, mac->rx); +free_irq (mac->tx->chan.irq, mac->tx); +free_irq (mac->rx->chan.irq, mac->rx);/* Free resources */ pasemi_mac_free_rx_resources (mac);
@@ -1239,7 +1239,7 @@ static int pasemi_mac_start_tx(struct skspin_unlock_irqrestore (&txring->lock, flags); -write_dma_reg (mac,PAS_DMA_TXCHAN_INCR (txring->chan), (nfrags+2 ) >>1 ); +write_dma_reg (PAS_DMA_TXCHAN_INCR (txring->chan.chno), (nfrags+2 ) >>1 );return NETDEV_TX_OK ;
@@ -1287,77 +1287,9 @@ static int pasemi_mac_poll(struct napi_sreturn pkts; } -static void __iomem *__devinit map_onedev (struct pci_dev *p,int index) -{ -struct device_node *dn; -void __iomem *ret; - - dn =pci_device_to_OF_node (p); -if (!dn) - goto fallback; - - ret =of_iomap (dn, index); -if (!ret) - goto fallback; - -return ret; -fallback: -/* This is hardcoded and ugly, but we have some firmware versions -* that don't provide the register space in the device tree. Luckily -* they are at well-known locations so we can just do the math here. -*/ -return ioremap (0xe0000000 + (p->devfn <<12 ),0x2000 ); -} - -static int __devinit pasemi_mac_map_regs (struct pasemi_mac *mac) -{ -struct resource res; -struct device_node *dn; -int err; - - mac->dma_pdev =pci_get_device (PCI_VENDOR_ID_PASEMI ,0xa007 ,NULL ); -if (!mac->dma_pdev) { -dev_err (&mac->pdev->dev,"Can't find DMA Controller\n" ); -return -ENODEV ; - } - - mac->iob_pdev =pci_get_device (PCI_VENDOR_ID_PASEMI ,0xa001 ,NULL ); -if (!mac->iob_pdev) { -dev_err (&mac->pdev->dev,"Can't find I/O Bridge\n" ); -return -ENODEV ; - } - - mac->regs =map_onedev (mac->pdev,0 ); - mac->dma_regs =map_onedev (mac->dma_pdev,0 ); - mac->iob_regs =map_onedev (mac->iob_pdev,0 ); - -if (!mac->regs || !mac->dma_regs || !mac->iob_regs) { -dev_err (&mac->pdev->dev,"Can't map registers\n" ); -return -ENODEV ; - } - -/* The dma status structure is located in the I/O bridge, and -* is cache coherent. -*/ -if (!dma_status) { - dn =pci_device_to_OF_node (mac->iob_pdev); -if (dn) - err =of_address_to_resource (dn,1 , &res); -if (!dn || err) { -/* Fallback for old firmware */ - res.start =0xfd800000 ; - res.end = res.start +0x1000 ; - } - dma_status =__ioremap (res.start, res.end-res.start,0 ); - } - -return 0 ; -} -static int __devinit pasemi_mac_probe (struct pci_dev *pdev,const struct pci_device_id *ent) { -static int index =0 ;struct net_device *dev;struct pasemi_mac *mac;int err;
@@ -1387,18 +1319,33 @@ pasemi_mac_probe(struct pci_dev *pdev, c 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; - mac->dma_rxch = index; + mac->dma_pdev =pci_get_device (PCI_VENDOR_ID_PASEMI ,0xa007 ,NULL ); +if (!mac->dma_pdev) { +dev_err (&mac->pdev->dev,"Can't find DMA Controller\n" ); + err = -ENODEV ; + goto out; + } -/* We probe GMAC before XAUI, but the DMA interfaces are -* in XAUI, GMAC order. -*/ -if (index <4 ) - mac->dma_if = index +2 ; -else - mac->dma_if = index -4 ; - index++; + mac->iob_pdev =pci_get_device (PCI_VENDOR_ID_PASEMI ,0xa001 ,NULL ); +if (!mac->iob_pdev) { +dev_err (&mac->pdev->dev,"Can't find I/O Bridge\n" ); + err = -ENODEV ; + goto out; + } + +/* get mac addr from device tree */ +if (pasemi_get_mac_addr (mac) || !is_valid_ether_addr (mac->mac_addr)) { + err = -ENODEV ; + goto out; + } +memcpy (dev->dev_addr, mac->mac_addr,sizeof (mac->mac_addr)); + + mac->dma_if =mac_to_intf (mac); +if (mac->dma_if <0 ) { +dev_err (&mac->pdev->dev,"Can't map DMA interface\n" ); + err = -ENODEV ; + goto out; + }switch (pdev->device) {case 0xa005 :
@@ -1412,19 +1359,11 @@ pasemi_mac_probe(struct pci_dev *pdev, c goto out; } -/* get mac addr from device tree */ -if (pasemi_get_mac_addr (mac) || !is_valid_ether_addr (mac->mac_addr)) { - err = -ENODEV ; - goto out; - } -memcpy (dev->dev_addr, mac->mac_addr,sizeof (mac->mac_addr)); - dev->open = pasemi_mac_open; dev->stop = pasemi_mac_close; dev->hard_start_xmit = pasemi_mac_start_tx; dev->set_multicast_list = pasemi_mac_set_rx_mode; - err =pasemi_mac_map_regs (mac);if (err) goto out;
@@ -1451,12 +1390,6 @@ out:pci_dev_put (mac->iob_pdev);if (mac->dma_pdev)pci_dev_put (mac->dma_pdev); -if (mac->dma_regs) -iounmap (mac->dma_regs); -if (mac->iob_regs) -iounmap (mac->iob_regs); -if (mac->regs) -iounmap (mac->regs);free_netdev (dev); out_disable_device:
@@ -1481,9 +1414,8 @@ static void __devexit pasemi_mac_remove(pci_dev_put (mac->dma_pdev);pci_dev_put (mac->iob_pdev); -iounmap (mac->regs); -iounmap (mac->dma_regs); -iounmap (mac->iob_regs); +pasemi_dma_free_chan (&mac->tx->chan); +pasemi_dma_free_chan (&mac->rx->chan);pci_set_drvdata (pdev,NULL );free_netdev (netdev);
@@ -1507,12 +1439,16 @@ static struct pci_driver pasemi_mac_driv static void __exit pasemi_mac_cleanup_module(void) {pci_unregister_driver (&pasemi_mac_driver); -__iounmap (dma_status); - dma_status =NULL ; }int pasemi_mac_init_module (void ) { +int err; + + err =pasemi_dma_init (); +if (err) +return err; +return pci_register_driver (&pasemi_mac_driver); }
drivers/net/pasemi_mac.h +2 -14
@@ -27,23 +27,18 @@#include <linux/phy.h> struct pasemi_mac_txring { +struct pasemi_dmachan chan;/* Must be first */ spinlock_t lock; -u64 *status;/* Ptr to cacheable status area */ -u64 *ring; -dma_addr_t dma;unsigned int size;unsigned int next_to_fill;unsigned int next_to_clean;struct pasemi_mac_buffer *ring_info; -int chan;struct pasemi_mac *mac;/* Needed in intr handler */ };struct pasemi_mac_rxring { +struct pasemi_dmachan chan;/* Must be first */ spinlock_t lock; -u64 *status;/* Ptr to cacheable status area */ -u64 *ring;/* RX channel descriptor ring */ -dma_addr_t dma;u64 *buffers;/* RX interface buffer ring */ dma_addr_t buf_dma;unsigned int size;
@@ -55,9 +50,6 @@ struct pasemi_mac_rxring {struct pasemi_mac {struct net_device *netdev; -void __iomem *regs; -void __iomem *dma_regs; -void __iomem *iob_regs;struct pci_dev *pdev;struct pci_dev *dma_pdev;struct pci_dev *iob_pdev;
@@ -67,8 +59,6 @@ struct pasemi_mac {u8 type;#define MAC_TYPE_GMAC 1#define MAC_TYPE_XAUI 2 -u32 dma_txch; -u32 dma_rxch;u32 dma_if;u8 mac_addr[6 ];
@@ -77,8 +67,6 @@ struct pasemi_mac {struct pasemi_mac_txring *tx;struct pasemi_mac_rxring *rx; -unsigned int tx_irq; -unsigned int rx_irq;char tx_irq_name[10 ];/* "eth%d tx" */ char rx_irq_name[10 ];/* "eth%d rx" */ int link;
PATCH 5/12 pasemi_mac: performance tweaks
In reply to Olof Johanssonpasemi_mac: performance tweaks
* Seems like we do better with a smaller RX ring, probably because chances of still having the SKB cached are better
* Const-ify variables to get better code generation and fewer reloads
* Move prefetching around a little, and try to prefetch the whole SKB
* Set NETIF_F_HIGHDMA
* Misc other minor tweaks
--- drivers/net/pasemi_mac.c | 114 ++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 46 deletions(-)
drivers/net/pasemi_mac.c +68 -46
@@ -56,7 +56,7 @@/* Must be a power of two */ -#define RX_RING_SIZE 4096 +#define RX_RING_SIZE 1024#define TX_RING_SIZE 4096#define DEFAULT_MSG_ENABLE \
@@ -103,12 +103,12 @@ static void write_iob_reg(unsigned int rpasemi_write_iob_reg (reg, val); } -static unsigned int read_mac_reg (struct pasemi_mac *mac,unsigned int reg) +static unsigned int read_mac_reg (const struct pasemi_mac *mac,unsigned int reg) {return pasemi_read_mac_reg (mac->dma_if, reg); } -static void write_mac_reg (struct pasemi_mac *mac,unsigned int reg, +static void write_mac_reg (const struct pasemi_mac *mac,unsigned int reg,unsigned int val) {pasemi_write_mac_reg (mac->dma_if, reg, val);
@@ -124,16 +124,26 @@ static void write_dma_reg(unsigned int rpasemi_write_dma_reg (reg, val); } -static struct pasemi_mac_rxring *rx_ring (struct pasemi_mac *mac) +static struct pasemi_mac_rxring *rx_ring (const struct pasemi_mac *mac) {return mac->rx; } -static struct pasemi_mac_txring *tx_ring (struct pasemi_mac *mac) +static struct pasemi_mac_txring *tx_ring (const struct pasemi_mac *mac) {return mac->tx; } +static inline void prefetch_skb (const struct sk_buff *skb) +{ +const void *d = skb; + +prefetch (d); +prefetch (d+64 ); +prefetch (d+128 ); +prefetch (d+192 ); +} +static int mac_to_intf (struct pasemi_mac *mac) {struct pci_dev *pdev = mac->pdev;
@@ -211,19 +221,18 @@ static int pasemi_get_mac_addr(struct pastatic int pasemi_mac_unmap_tx_skb (struct pasemi_mac *mac,struct sk_buff *skb, -dma_addr_t *dmas) +const dma_addr_t *dmas) {int f;int nfrags =skb_shinfo (skb)->nr_frags; +struct pci_dev *pdev = mac->dma_pdev; -pci_unmap_single (mac->dma_pdev, dmas[0 ],skb_headlen (skb), -PCI_DMA_TODEVICE ); +pci_unmap_single (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 ); +pci_unmap_page (pdev, dmas[f+1 ], frag->size,PCI_DMA_TODEVICE ); }dev_kfree_skb_irq (skb);
@@ -233,7 +242,7 @@ static int pasemi_mac_unmap_tx_skb(strucreturn (nfrags +3 ) & ~1 ; } -static int pasemi_mac_setup_rx_resources (struct net_device *dev) +static int pasemi_mac_setup_rx_resources (const struct net_device *dev) {struct pasemi_mac_rxring *ring;struct pasemi_mac *mac =netdev_priv (dev);
@@ -277,7 +286,7 @@ static int pasemi_mac_setup_rx_resourcesPAS_DMA_RXCHAN_BASEU_BRBH (ring->chan.ring_dma >>32 ) | PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3)); - cfg =PAS_DMA_RXCHAN_CFG_HBU (1 ); + cfg =PAS_DMA_RXCHAN_CFG_HBU (2 );if (translation_enabled ()) cfg |=PAS_DMA_RXCHAN_CFG_CTR ;
@@ -291,7 +300,7 @@ static int pasemi_mac_setup_rx_resourcesPAS_DMA_RXINT_BASEU_BRBH (ring->buf_dma >>32 ) | PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3)); - cfg =PAS_DMA_RXINT_CFG_DHL (1 ) |PAS_DMA_RXINT_CFG_L2 | + cfg =PAS_DMA_RXINT_CFG_DHL (2 ) |PAS_DMA_RXINT_CFG_L2 |PAS_DMA_RXINT_CFG_LW |PAS_DMA_RXINT_CFG_RBP |PAS_DMA_RXINT_CFG_HEN ;
@@ -316,7 +325,7 @@ out_chan: }static struct pasemi_mac_txring * -pasemi_mac_setup_tx_resources (struct net_device *dev) +pasemi_mac_setup_tx_resources (const struct net_device *dev) {struct pasemi_mac *mac =netdev_priv (dev);u32 val;
@@ -439,9 +448,10 @@ static void pasemi_mac_free_rx_resources mac->rx =NULL ; } -static void pasemi_mac_replenish_rx_ring (struct net_device *dev,int limit) +static void pasemi_mac_replenish_rx_ring (const struct net_device *dev, +const int limit) { -struct pasemi_mac *mac =netdev_priv (dev); +const struct pasemi_mac *mac =netdev_priv (dev);struct pasemi_mac_rxring *rx =rx_ring (mac);int fill, count;
@@ -492,7 +502,7 @@ static void pasemi_mac_replenish_rx_ring (RX_RING_SIZE -1 ); } -static void pasemi_mac_restart_rx_intr (struct pasemi_mac *mac) +static void pasemi_mac_restart_rx_intr (const struct pasemi_mac *mac) {unsigned int reg, pcnt;/* Re-enable packet count interrupts: finally
@@ -506,7 +516,7 @@ static void pasemi_mac_restart_rx_intr(swrite_iob_reg (PAS_IOB_DMA_RXCH_RESET (mac->rx->chan.chno), reg); } -static void pasemi_mac_restart_tx_intr (struct pasemi_mac *mac) +static void pasemi_mac_restart_tx_intr (const struct pasemi_mac *mac) {unsigned int reg, pcnt;
@@ -519,7 +529,8 @@ static void pasemi_mac_restart_tx_intr(s } -static inline void pasemi_mac_rx_error (struct pasemi_mac *mac,u64 macrx) +static inline void pasemi_mac_rx_error (const struct pasemi_mac *mac, +const u64 macrx) {unsigned int rcmdsta, ccmdsta;struct pasemi_dmachan *chan = &rx_ring (mac)->chan;
@@ -537,7 +548,8 @@ static inline void pasemi_mac_rx_error(s rcmdsta, ccmdsta); } -static inline void pasemi_mac_tx_error (struct pasemi_mac *mac,u64 mactx) +static inline void pasemi_mac_tx_error (const struct pasemi_mac *mac, +const u64 mactx) {unsigned int cmdsta;struct pasemi_dmachan *chan = &tx_ring (mac)->chan;
@@ -553,19 +565,22 @@ static inline void pasemi_mac_tx_error(sprintk (KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n" , cmdsta); } -static int pasemi_mac_clean_rx (struct pasemi_mac_rxring *rx,int limit) +static int pasemi_mac_clean_rx (struct pasemi_mac_rxring *rx, +const int limit) { -struct pasemi_dmachan *chan = &rx->chan; +const struct pasemi_dmachan *chan = &rx->chan;struct pasemi_mac *mac = rx->mac; +struct pci_dev *pdev = mac->dma_pdev;unsigned int n; -int count; +int count, buf_index, tot_bytes, packets;struct pasemi_mac_buffer *info;struct sk_buff *skb;unsigned int len; -u64 macrx; +u64 macrx, eval;dma_addr_t dma; -int buf_index; -u64 eval; + + tot_bytes =0 ; + packets =0 ;spin_lock (&rx->lock);
@@ -575,6 +590,7 @@ static int pasemi_mac_clean_rx(struct pafor (count =0 ; count < limit; count++) { macrx =RX_DESC (rx, n); +prefetch (&RX_DESC (rx, n+4 ));if ((macrx &XCT_MACRX_E ) || (*chan->status &PAS_STATUS_ERROR ))
@@ -596,12 +612,12 @@ static int pasemi_mac_clean_rx(struct pa skb = info->skb; -prefetch (skb); -prefetch (&skb->data_len); +prefetch_skb (skb); len = (macrx &XCT_MACRX_LLEN_M ) >>XCT_MACRX_LLEN_S ; -pci_unmap_single (mac->dma_pdev, dma, len,PCI_DMA_FROMDEVICE ); +pci_unmap_single (pdev, dma,BUF_SIZE -LOCAL_SKB_ALIGN , +PCI_DMA_FROMDEVICE );if (macrx &XCT_MACRX_CRC ) {/* CRC error flagged */
@@ -628,9 +644,6 @@ static int pasemi_mac_clean_rx(struct pa info->dma =0 ; -/* Don't include CRC */ -skb_put (skb, len-4 ); -if (likely ((macrx &XCT_MACRX_HTY_M ) ==XCT_MACRX_HTY_IPV4_OK )) { skb->ip_summed =CHECKSUM_UNNECESSARY ; skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
@@ -638,8 +651,11 @@ static int pasemi_mac_clean_rx(struct pa }else skb->ip_summed =CHECKSUM_NONE ; - mac->netdev->stats.rx_bytes += len; - mac->netdev->stats.rx_packets++; + packets++; + tot_bytes += len; + +/* Don't include CRC */ +skb_put (skb, len-4 ); skb->protocol =eth_type_trans (skb, mac->netdev);netif_receive_skb (skb);
@@ -672,6 +688,9 @@ next:pasemi_mac_replenish_rx_ring (mac->netdev, count); + mac->netdev->stats.rx_bytes += tot_bytes; + mac->netdev->stats.rx_packets += packets; +spin_unlock (&rx_ring (mac)->lock);return count;
@@ -758,10 +777,10 @@ restart:static irqreturn_t pasemi_mac_rx_intr (int irq,void *data) { -struct pasemi_mac_rxring *rxring = data; +const struct pasemi_mac_rxring *rxring = data;struct pasemi_mac *mac = rxring->mac;struct net_device *dev = mac->netdev; -struct pasemi_dmachan *chan = &rxring->chan; +const struct pasemi_dmachan *chan = &rxring->chan;unsigned int reg;if (!(*chan->status &PAS_STATUS_CAUSE_M ))
@@ -789,7 +808,7 @@ static irqreturn_t pasemi_mac_rx_intr(instatic irqreturn_t pasemi_mac_tx_intr (int irq,void *data) {struct pasemi_mac_txring *txring = data; -struct pasemi_dmachan *chan = &txring->chan; +const struct pasemi_dmachan *chan = &txring->chan;unsigned int reg, pcnt;if (!(*chan->status &PAS_STATUS_CAUSE_M ))
@@ -1158,6 +1177,7 @@ static int pasemi_mac_start_tx(struct skunsigned int map_size[MAX_SKB_FRAGS +1 ];unsigned long flags;int i, nfrags; +int fill; dflags =XCT_MACTX_O |XCT_MACTX_ST |XCT_MACTX_CRC_PAD ;
@@ -1205,6 +1225,8 @@ static int pasemi_mac_start_tx(struct skspin_lock_irqsave (&txring->lock, flags); + fill = txring->next_to_fill; +/* 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
@@ -1215,13 +1237,13 @@ static int pasemi_mac_start_tx(struct sk goto out_err; } -TX_DESC (txring, txring->next_to_fill) = mactx; - txring->next_to_fill++; -TX_DESC_INFO (txring, txring->next_to_fill).skb = skb; +TX_DESC (txring, fill) = mactx; + fill++; +TX_DESC_INFO (txring, fill).skb = skb;for (i =0 ; i <= nfrags; i++) { -TX_DESC (txring, txring->next_to_fill+i) = +TX_DESC (txring, fill+i) =XCT_PTR_LEN (map_size[i]) |XCT_PTR_ADDR (map[i]); -TX_DESC_INFO (txring, txring->next_to_fill+i).dma = map[i]; +TX_DESC_INFO (txring, fill+i).dma = map[i]; }/* We have to add an even number of 8-byte entries to the ring
@@ -1231,8 +1253,7 @@ static int pasemi_mac_start_tx(struct skif (nfrags &1 ) nfrags++; - txring->next_to_fill = (txring->next_to_fill + nfrags +1 ) & - (TX_RING_SIZE -1 ); + txring->next_to_fill = (fill + nfrags +1 ) & (TX_RING_SIZE -1 ); dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len;
@@ -1255,7 +1276,7 @@ out_err_nolock:static void pasemi_mac_set_rx_mode (struct net_device *dev) { -struct pasemi_mac *mac =netdev_priv (dev); +const struct pasemi_mac *mac =netdev_priv (dev);unsigned int flags; flags =read_mac_reg (mac,PAS_MAC_CFG_PCFG );
@@ -1317,7 +1338,8 @@ 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 |NETIF_F_SG ; + dev->features =NETIF_F_HW_CSUM |NETIF_F_LLTX |NETIF_F_SG | +NETIF_F_HIGHDMA ; mac->dma_pdev =pci_get_device (PCI_VENDOR_ID_PASEMI ,0xa007 ,NULL );if (!mac->dma_pdev) {
PATCH 6/12 pasemi_mac: Fix TX cleaning
In reply to Olof Johanssonpasemi_mac: Fix TX cleaning
This is a bit awkward. We don't have a timer-delayed interrupt on TX complete, but we have a count threshold. So set that reasonably high (32 packets), and schedule the NAPI poll when it goes off. Also bump a regular timer that will take care of rotting packets for the last 1..31 ones in case we don't trigger a TX interrupt (and there's no RX activity that would otherwise trigger the poll).
The longer-term fix is to separate TX from RX NAPI and do two separate poll loops.
--- drivers/net/pasemi_mac.c | 41 +++++++++++++++++++++++++++++++++-------- drivers/net/pasemi_mac.h | 1 + 2 files changed, 34 insertions(+), 8 deletions(-)
drivers/net/pasemi_mac.c +33 -8
@@ -805,27 +805,43 @@ static irqreturn_t pasemi_mac_rx_intr(inreturn IRQ_HANDLED ; } +#define TX_CLEAN_INTERVAL HZ + +static void pasemi_mac_tx_timer (unsigned long data) +{ +struct pasemi_mac_txring *txring = (struct pasemi_mac_txring *)data; +struct pasemi_mac *mac = txring->mac; + +pasemi_mac_clean_tx (txring); + +mod_timer (&txring->clean_timer, jiffies +TX_CLEAN_INTERVAL ); + +pasemi_mac_restart_tx_intr (mac); +} +static irqreturn_t pasemi_mac_tx_intr (int irq,void *data) {struct pasemi_mac_txring *txring = data;const struct pasemi_dmachan *chan = &txring->chan; -unsigned int reg, pcnt; +struct pasemi_mac *mac = txring->mac; +unsigned int reg;if (!(*chan->status &PAS_STATUS_CAUSE_M ))return IRQ_NONE ; -pasemi_mac_clean_tx (txring); - - pcnt = *chan->status &PAS_STATUS_PCNT_M ; - - reg =PAS_IOB_DMA_TXCH_RESET_PCNT (pcnt) |PAS_IOB_DMA_TXCH_RESET_PINTC ; + reg =0 ;if (*chan->status &PAS_STATUS_SOFT ) reg |=PAS_IOB_DMA_TXCH_RESET_SINTC ;if (*chan->status &PAS_STATUS_ERROR ) reg |=PAS_IOB_DMA_TXCH_RESET_DINTC ; -write_iob_reg (PAS_IOB_DMA_TXCH_RESET (chan->chno), reg); +mod_timer (&txring->clean_timer, jiffies + (TX_CLEAN_INTERVAL )*2 ); + +netif_rx_schedule (mac->netdev, &mac->napi); + +if (reg) +write_iob_reg (PAS_IOB_DMA_TXCH_RESET (chan->chno), reg);return IRQ_HANDLED ; }
@@ -973,7 +989,7 @@ static int pasemi_mac_open(struct net_de PAS_IOB_DMA_RXCH_CFG_CNTTH(0));write_iob_reg (PAS_IOB_DMA_TXCH_CFG (mac->tx->chan.chno), -PAS_IOB_DMA_TXCH_CFG_CNTTH (128 )); +PAS_IOB_DMA_TXCH_CFG_CNTTH (32 )); write_mac_reg(mac, PAS_MAC_IPC_CHNL, PAS_MAC_IPC_CHNL_DCHNO(mac->rx->chan.chno) |
@@ -1054,6 +1070,12 @@ static int pasemi_mac_open(struct net_deif (mac->phydev)phy_start (mac->phydev); +init_timer (&mac->tx->clean_timer); + mac->tx->clean_timer.function = pasemi_mac_tx_timer; + mac->tx->clean_timer.data = (unsigned long )mac->tx; + mac->tx->clean_timer.expires = jiffies+HZ ; +add_timer (&mac->tx->clean_timer); +return 0 ; out_rx_int:
@@ -1087,6 +1109,8 @@ static int pasemi_mac_close(struct net_dphy_disconnect (mac->phydev); } +del_timer_sync (&mac->tx->clean_timer); +netif_stop_queue (dev);napi_disable (&mac->napi);
@@ -1304,6 +1328,7 @@ static int pasemi_mac_poll(struct napi_snetif_rx_complete (dev, napi);pasemi_mac_restart_rx_intr (mac); +pasemi_mac_restart_tx_intr (mac); }return pkts; }
drivers/net/pasemi_mac.h +1 -0
@@ -34,6 +34,7 @@ struct pasemi_mac_txring {unsigned int next_to_clean;struct pasemi_mac_buffer *ring_info;struct pasemi_mac *mac;/* Needed in intr handler */ +struct timer_list clean_timer; };struct pasemi_mac_rxring {
PATCH 7/12 pasemi_mac: Improve RX interrupt mitigation
In reply to Olof Johanssonpasemi_mac: Improve RX interrupt mitigation
Currently the receive side interrupts will go off on the reception of a packet, NAPI will poll the ring and keep polling as long as there's a decent amount of packets to receive.
This is less than optimal, especially for LRO where it's better if we have a more substantial amount of packets to process at once, to get the real LRO benefits.
So, set the count threshold to a higher value and use the timeout feature that will give us an interrupt even if not enough packets have come in to set off the count threshold.
FIXME: It'd be real nice to have ethtool support for users to tune this at runtime.
--- drivers/net/pasemi_mac.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/net/pasemi_mac.c +10 -8
@@ -504,15 +504,19 @@ static void pasemi_mac_replenish_rx_ringstatic void pasemi_mac_restart_rx_intr (const struct pasemi_mac *mac) { +struct pasemi_mac_rxring *rx =rx_ring (mac);unsigned int reg, pcnt;/* Re-enable packet count interrupts: finally * ack the packet count interrupt we got in rx_intr. */ - pcnt = *rx_ring (mac)->chan.status &PAS_STATUS_PCNT_M ; + pcnt = *rx->chan.status &PAS_STATUS_PCNT_M ; reg =PAS_IOB_DMA_RXCH_RESET_PCNT (pcnt) |PAS_IOB_DMA_RXCH_RESET_PINTC ; +if (*rx->chan.status &PAS_STATUS_TIMER ) + reg |=PAS_IOB_DMA_RXCH_RESET_TINTC ; +write_iob_reg (PAS_IOB_DMA_RXCH_RESET (mac->rx->chan.chno), reg); }
@@ -795,8 +799,6 @@ static irqreturn_t pasemi_mac_rx_intr(in reg |=PAS_IOB_DMA_RXCH_RESET_SINTC ;if (*chan->status &PAS_STATUS_ERROR ) reg |=PAS_IOB_DMA_RXCH_RESET_DINTC ; -if (*chan->status &PAS_STATUS_TIMER ) - reg |=PAS_IOB_DMA_RXCH_RESET_TINTC ;netif_rx_schedule (dev, &mac->napi);
@@ -972,10 +974,6 @@ static int pasemi_mac_open(struct net_dewrite_mac_reg (mac,PAS_MAC_CFG_TXP , flags); -/* 0xffffff is max value, about 16ms */ -write_iob_reg (PAS_IOB_DMA_COM_TIMEOUTCFG , -PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT (0xffffff )); - ret =pasemi_mac_setup_rx_resources (dev);if (ret) goto out_rx_resources;
@@ -985,8 +983,12 @@ static int pasemi_mac_open(struct net_deif (!mac->tx) goto out_tx_ring; +/* 0x3ff with 33MHz clock is about 31us */ +write_iob_reg (PAS_IOB_DMA_COM_TIMEOUTCFG , +PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT (0x3ff )); +write_iob_reg (PAS_IOB_DMA_RXCH_CFG (mac->rx->chan.chno), -PAS_IOB_DMA_RXCH_CFG_CNTTH (0 )); +PAS_IOB_DMA_RXCH_CFG_CNTTH (128 ));write_iob_reg (PAS_IOB_DMA_TXCH_CFG (mac->tx->chan.chno),PAS_IOB_DMA_TXCH_CFG_CNTTH (32 ));
PATCH 8/12 pasemi_mac: Software-based LRO support
In reply to Olof Johanssonpasemi_mac: Software-based LRO support
Implement LRO for pasemi_mac. Pretty straightforward.
--- drivers/net/Kconfig | 1 drivers/net/pasemi_mac.c | 53 +++++++++++++++++++++++++++++++++++++++++++---- drivers/net/pasemi_mac.h | 5 ++++ 3 files changed, 55 insertions(+), 4 deletions(-)
drivers/net/pasemi_mac.c +49 -4
@@ -32,6 +32,7 @@#include <linux/ip.h> #include <linux/tcp.h> #include <net/checksum.h> +#include <linux/inet_lro.h> #include <asm/irq.h> #include <asm/firmware.h>
@@ -56,9 +57,11 @@/* Must be a power of two */ -#define RX_RING_SIZE 1024 +#define RX_RING_SIZE 2048#define TX_RING_SIZE 4096 +#define LRO_MAX_AGGR 64 +#define DEFAULT_MSG_ENABLE \ (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \
@@ -206,7 +209,6 @@ static int pasemi_get_mac_addr(struct pareturn -ENOENT ; } -if (sscanf (maddr,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx" , &addr[0 ], &addr[1 ], &addr[2 ], &addr[3 ], &addr[4 ], &addr[5 ]) !=6 ) { dev_warn(&pdev->dev,
@@ -219,6 +221,37 @@ static int pasemi_get_mac_addr(struct pareturn 0 ; } +static int get_skb_hdr (struct sk_buff *skb,void **iphdr, +void **tcph,u64 *hdr_flags,void *data) +{ +u64 macrx = (u64 ) data; +unsigned int ip_len; +struct iphdr *iph; + +/* IPv4 header checksum failed */ +if ((macrx &XCT_MACRX_HTY_M ) !=XCT_MACRX_HTY_IPV4_OK ) +return -1 ; + +/* non tcp packet */ +skb_reset_network_header (skb); + iph =ip_hdr (skb); +if (iph->protocol !=IPPROTO_TCP ) +return -1 ; + + ip_len =ip_hdrlen (skb); +skb_set_transport_header (skb, ip_len); + *tcph =tcp_hdr (skb); + +/* check if ip header and tcp header are complete */ +if (iph->tot_len < ip_len +tcp_hdrlen (skb)) +return -1 ; + + *hdr_flags =LRO_IPV4 |LRO_TCP ; + *iphdr = iph; + +return 0 ; +} +static int pasemi_mac_unmap_tx_skb (struct pasemi_mac *mac,struct sk_buff *skb,const dma_addr_t *dmas)
@@ -662,7 +695,7 @@ static int pasemi_mac_clean_rx(struct paskb_put (skb, len-4 ); skb->protocol =eth_type_trans (skb, mac->netdev); -netif_receive_skb (skb); +lro_receive_skb (&mac->lro_mgr, skb, (void *)macrx); next:RX_DESC (rx, n) =0 ;
@@ -684,6 +717,8 @@ next:rx_ring (mac)->next_to_clean = n; +lro_flush_all (&mac->lro_mgr); +/* 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.
@@ -988,7 +1023,7 @@ static int pasemi_mac_open(struct net_de PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));write_iob_reg (PAS_IOB_DMA_RXCH_CFG (mac->rx->chan.chno), -PAS_IOB_DMA_RXCH_CFG_CNTTH (128 )); +PAS_IOB_DMA_RXCH_CFG_CNTTH (256 ));write_iob_reg (PAS_IOB_DMA_TXCH_CFG (mac->tx->chan.chno),PAS_IOB_DMA_TXCH_CFG_CNTTH (32 ));
@@ -1368,6 +1403,16 @@ pasemi_mac_probe(struct pci_dev *pdev, c dev->features =NETIF_F_HW_CSUM |NETIF_F_LLTX |NETIF_F_SG |NETIF_F_HIGHDMA ; + mac->lro_mgr.max_aggr =LRO_MAX_AGGR ; + mac->lro_mgr.max_desc =MAX_LRO_DESCRIPTORS ; + mac->lro_mgr.lro_arr = mac->lro_desc; + mac->lro_mgr.get_skb_header = get_skb_hdr; + mac->lro_mgr.features =LRO_F_NAPI |LRO_F_EXTRACT_VLAN_ID ; + mac->lro_mgr.dev = mac->netdev; + mac->lro_mgr.ip_summed =CHECKSUM_UNNECESSARY ; + mac->lro_mgr.ip_summed_aggr =CHECKSUM_UNNECESSARY ; + + mac->dma_pdev =pci_get_device (PCI_VENDOR_ID_PASEMI ,0xa007 ,NULL );if (!mac->dma_pdev) {dev_err (&mac->pdev->dev,"Can't find DMA Controller\n" );
drivers/net/pasemi_mac.h +5 -0
@@ -26,6 +26,8 @@#include <linux/spinlock.h> #include <linux/phy.h> +#define MAX_LRO_DESCRIPTORS 8 +struct pasemi_mac_txring {struct pasemi_dmachan chan;/* Must be first */ spinlock_t lock;
@@ -64,7 +66,10 @@ struct pasemi_mac {u8 mac_addr[6 ]; +struct net_lro_mgr lro_mgr; +struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS ];struct timer_list rxtimer; +unsigned int lro_max_aggr;struct pasemi_mac_txring *tx;struct pasemi_mac_rxring *rx;
drivers/net/Kconfig +1 -0
@@ -2566,6 +2566,7 @@ config PASEMI_MAC tristate "PA Semi 1/10Gbit MAC" depends on PPC64 && PCI select PHYLIB + select INET_LRO help This driver supports the on-chip 1/10Gbit Ethernet controller on PA Semi's PWRficient line of chips.
PATCH 9/12 pasemi_mac: SKB unmap optimization
In reply to Olof Johanssonpasemi_mac: SKB unmap optimization
Avoid touching skb_shinfo() in the unmap path, since it turns out to normally cause cache misses and delays. instead, save number of fragments in the TX_RING_INFO structures since that's all that's needed anyway.
--- drivers/net/pasemi_mac.c | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-)
drivers/net/pasemi_mac.c +25 -14
@@ -253,11 +253,11 @@ static int get_skb_hdr(struct sk_buff *s }static int pasemi_mac_unmap_tx_skb (struct pasemi_mac *mac, +const int nfrags,struct sk_buff *skb,const dma_addr_t *dmas) {int f; -int nfrags =skb_shinfo (skb)->nr_frags;struct pci_dev *pdev = mac->dma_pdev;pci_unmap_single (pdev, dmas[0 ],skb_headlen (skb),PCI_DMA_TODEVICE );
@@ -425,7 +425,7 @@ static void pasemi_mac_free_tx_resourcesunsigned int i, j;struct pasemi_mac_buffer *info;dma_addr_t dmas[MAX_SKB_FRAGS +1 ]; -int freed; +int freed, nfrags;int start, limit; start = txring->next_to_clean;
@@ -438,10 +438,12 @@ static void pasemi_mac_free_tx_resourcesfor (i = start; i < limit; i += freed) { info = &txring->ring_info[(i+1 ) & (TX_RING_SIZE -1 )];if (info->dma && info->skb) { -for (j =0 ; j <=skb_shinfo (info->skb)->nr_frags; j++) + nfrags =skb_shinfo (info->skb)->nr_frags; +for (j =0 ; j <= nfrags; j++) dmas[j] = txring->ring_info[(i+1 +j) & (TX_RING_SIZE -1 )].dma; - freed =pasemi_mac_unmap_tx_skb (mac, info->skb, dmas); + freed =pasemi_mac_unmap_tx_skb (mac, nfrags, + info->skb, dmas); }else freed =2 ; }
@@ -749,6 +751,8 @@ static int pasemi_mac_clean_tx(struct paunsigned long flags;struct sk_buff *skbs[TX_CLEAN_BATCHSIZE ];dma_addr_t dmas[TX_CLEAN_BATCHSIZE ][MAX_SKB_FRAGS +1 ]; +int nf[TX_CLEAN_BATCHSIZE ]; +int nr_frags; total_count =0 ; batch_limit =TX_CLEAN_BATCHSIZE ;
@@ -758,6 +762,8 @@ restart: start = txring->next_to_clean; ring_limit = txring->next_to_fill; +prefetch (&TX_DESC_INFO (txring, start+1 ).skb); +/* Compensate for when fill has wrapped but clean has not */ if (start > ring_limit) ring_limit +=TX_RING_SIZE ;
@@ -771,6 +777,9 @@ restart:u64 mactx =TX_DESC (txring, i);struct sk_buff *skb; + skb =TX_DESC_INFO (txring, i+1 ).skb; + nr_frags =TX_DESC_INFO (txring, i).dma; +if ((mactx &XCT_MACTX_E ) || (*chan->status &PAS_STATUS_ERROR ))pasemi_mac_tx_error (mac, mactx);
@@ -779,21 +788,22 @@ restart:/* Not yet transmitted */ break ; - skb =TX_DESC_INFO (txring, i+1 ).skb; - skbs[descr_count] = skb; + buf_count =2 + nr_frags; +/* 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++; - buf_count =2 +skb_shinfo (skb)->nr_frags; -for (j =0 ; j <=skb_shinfo (skb)->nr_frags; j++) +for (j =0 ; j <= nr_frags; j++) dmas[descr_count][j] =TX_DESC_INFO (txring, i+1 +j).dma; + skbs[descr_count] = skb; + nf[descr_count] = nr_frags; +TX_DESC (txring, i) =0 ;TX_DESC (txring, i+1 ) =0 ; -/* 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++; } txring->next_to_clean = i & (TX_RING_SIZE -1 );
@@ -802,7 +812,7 @@ restart:netif_wake_queue (mac->netdev);for (i =0 ; i < descr_count; i++) -pasemi_mac_unmap_tx_skb (mac, skbs[i], dmas[i]); +pasemi_mac_unmap_tx_skb (mac, nf[i], skbs[i], dmas[i]); total_count += descr_count;
@@ -1299,6 +1309,7 @@ static int pasemi_mac_start_tx(struct sk }TX_DESC (txring, fill) = mactx; +TX_DESC_INFO (txring, fill).dma = nfrags; fill++;TX_DESC_INFO (txring, fill).skb = skb;for (i =0 ; i <= nfrags; i++) {
PATCH 10/12 pasemi_mac: Remove SKB copy/recycle logic
In reply to Olof Johanssonpasemi_mac: Remove SKB copy/recycle logic
It doesn't really buy us much, since copying is about as expensive as the allocation in the first place. Just remove it for now.
--- drivers/net/pasemi_mac.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-)
drivers/net/pasemi_mac.c +3 -22
@@ -503,13 +503,8 @@ static void pasemi_mac_replenish_rx_ring/* Entry in use? */ WARN_ON (*buff); -/* skb might still be in there for recycle on short receives */ -if (info->skb) - skb = info->skb; -else { - skb =dev_alloc_skb (BUF_SIZE ); -skb_reserve (skb,LOCAL_SKB_ALIGN ); - } + skb =dev_alloc_skb (BUF_SIZE ); +skb_reserve (skb,LOCAL_SKB_ALIGN );if (unlikely (!skb))break ;
@@ -666,21 +661,7 @@ static int pasemi_mac_clean_rx(struct pa goto next; } -if (len <256 ) { -struct sk_buff *new_skb; - - new_skb =netdev_alloc_skb (mac->netdev, - len +LOCAL_SKB_ALIGN ); -if (new_skb) { -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; - } -/* else just continue with the old one */ - }else - info->skb =NULL ; - + info->skb =NULL ; info->dma =0 ;if (likely ((macrx &XCT_MACRX_HTY_M ) ==XCT_MACRX_HTY_IPV4_OK )) {
PATCH 11/12 pasemi_mac: Print warning when not attaching to a PHY
In reply to Olof Johanssonpasemi_mac: Print warning when not attaching to a PHY
Print a warning on the console when not connecting to a phy for an interface. It turns out to be a pretty common problem when someone gets the MDIO info wrong in their device tree, resulting in the macs running at a fixed 1Gbit FD.
--- drivers/net/pasemi_mac.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/net/pasemi_mac.c +5 -4
@@ -1064,11 +1064,12 @@ static int pasemi_mac_open(struct net_dewrite_mac_reg (mac,PAS_MAC_CFG_PCFG , flags); ret =pasemi_mac_phy_init (dev); -/* Some configs don't have PHYs (XAUI etc), so don't complain about -* failed init due to -ENODEV. +/* Warn for missing PHY on SGMII (1Gig) ports. */ -if (ret && ret != -ENODEV ) -dev_warn (&mac->pdev->dev,"phy init failed: %d\n" , ret); +if (ret && mac->type ==MAC_TYPE_GMAC ) { +dev_warn (&mac->pdev->dev,"PHY init failed: %d.\n" , ret); +dev_warn (&mac->pdev->dev,"Defaulting to 1Gbit full duplex\n" ); + }netif_start_queue (dev);napi_enable (&mac->napi);
PATCH 12/12 pasemi_mac: Don't enable RX/TX without a link (if possible)
In reply to Olof Johanssonpasemi_mac: Don't enable RX/TX without a link (if possible)
Don't enable RX/TX of packets until we have a link, since there's a chance we'll just get RX frame errors, etc.
The case where we don't have a PHY we can't do much about: Just enable it and deal with errors as they come in.
--- drivers/net/pasemi_mac.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-)
drivers/net/pasemi_mac.c +33 -8
@@ -874,6 +874,24 @@ static irqreturn_t pasemi_mac_tx_intr(inreturn IRQ_HANDLED ; } +static void pasemi_mac_intf_disable (struct pasemi_mac *mac) +{ +unsigned int flags; + + flags =read_mac_reg (mac,PAS_MAC_CFG_PCFG ); + flags &= ~PAS_MAC_CFG_PCFG_PE ; +write_mac_reg (mac,PAS_MAC_CFG_PCFG , flags); +} + +static void pasemi_mac_intf_enable (struct pasemi_mac *mac) +{ +unsigned int flags; + + flags =read_mac_reg (mac,PAS_MAC_CFG_PCFG ); + flags |=PAS_MAC_CFG_PCFG_PE ; +write_mac_reg (mac,PAS_MAC_CFG_PCFG , flags); +} +static void pasemi_adjust_link (struct net_device *dev) {struct pasemi_mac *mac =netdev_priv (dev);
@@ -889,11 +907,14 @@ static void pasemi_adjust_link(struct neprintk (KERN_INFO "%s: Link is down.\n" , dev->name);netif_carrier_off (dev); +pasemi_mac_intf_disable (mac); mac->link =0 ;return ; - }else + }else { +pasemi_mac_intf_enable (mac);netif_carrier_on (dev); + } flags =read_mac_reg (mac,PAS_MAC_CFG_PCFG ); new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M |
@@ -1052,8 +1073,7 @@ static int pasemi_mac_open(struct net_depasemi_mac_restart_rx_intr (mac);pasemi_mac_restart_tx_intr (mac); - flags =PAS_MAC_CFG_PCFG_S1 |PAS_MAC_CFG_PCFG_PE | -PAS_MAC_CFG_PCFG_PR |PAS_MAC_CFG_PCFG_CE ; + flags =PAS_MAC_CFG_PCFG_S1 |PAS_MAC_CFG_PCFG_PR |PAS_MAC_CFG_PCFG_CE ;if (mac->type ==MAC_TYPE_GMAC ) flags |=PAS_MAC_CFG_PCFG_TSR_1G |PAS_MAC_CFG_PCFG_SPD_1G ;
@@ -1064,11 +1084,16 @@ static int pasemi_mac_open(struct net_dewrite_mac_reg (mac,PAS_MAC_CFG_PCFG , flags); ret =pasemi_mac_phy_init (dev); -/* Warn for missing PHY on SGMII (1Gig) ports. -*/ -if (ret && mac->type ==MAC_TYPE_GMAC ) { -dev_warn (&mac->pdev->dev,"PHY init failed: %d.\n" , ret); -dev_warn (&mac->pdev->dev,"Defaulting to 1Gbit full duplex\n" ); +if (ret) { +/* Since we won't get link notification, just enable RX */ +pasemi_mac_intf_enable (mac); +if (mac->type ==MAC_TYPE_GMAC ) { +/* Warn for missing PHY on SGMII (1Gig) ports */ +dev_warn (&mac->pdev->dev, +"PHY init failed: %d.\n" , ret); +dev_warn (&mac->pdev->dev, +"Defaulting to 1Gbit full duplex\n" ); + } }netif_start_queue (dev);
Quoted 1 line · Olof Johansson
The patches are:
[...]
I got the order wrong above, the actual one is:
1/12 pasemi_mac: RX/TX ring management cleanup
2/12 pasemi_mac: Move register definitions to include/asm-powerpc 3/12 pasemi: DMA engine management library
4/12 pasemi_mac: Convert to new dma library
5/12 pasemi_mac: performance tweaks
6/12 pasemi_mac: Fix TX cleaning
7/12 pasemi_mac: Improve RX interrupt mitigation
8/12 pasemi_mac: Software-based LRO support
9/12 pasemi_mac: SKB unmap optimization
10/12 pasemi_mac: Remove SKB copy/recycle logic
11/12 pasemi_mac: Print warning when not attaching to a PHY 12/12 pasemi_mac: Don't enable RX/TX without a link (if possible)