* [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library
@ 2007-11-29 2:54 Olof Johansson
2007-11-29 2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
` (12 more replies)
0 siblings, 13 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:54 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
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
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
@ 2007-11-29 2:54 ` Olof Johansson
2007-12-01 21:54 ` Jeff Garzik
2007-11-29 2:56 ` [PATCH] [2/12] pasemi_mac: Move register definitions to include/asm-powerpc Olof Johansson
` (11 subsequent siblings)
12 siblings, 1 reply; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:54 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 277 ++++++++++++++++++++++++-----------------------
drivers/net/pasemi_mac.h | 19 +--
2 files changed, 157 insertions(+), 139 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -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_resources
memset(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_resources
if (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_ring
write_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(s
unsigned 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 pa
int 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 pa
BUG_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 pa
netif_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(in
struct 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(in
static 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_de
write_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_de
if (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_de
write_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_de
return 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_d
printk(KERN_DEBUG "pasemi_mac: ccmdsta error: 0x%08x\n", sta);
sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
- if (sta & (PAS_DMA_TXCHAN_TCMDSTA_SZ |
- PAS_DMA_TXCHAN_TCMDSTA_DB |
- PAS_DMA_TXCHAN_TCMDSTA_DE |
- PAS_DMA_TXCHAN_TCMDSTA_DA))
+ 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_d
write_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 sk
spin_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_s
struct 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, c
if (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;
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -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 2
u32 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;
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [2/12] pasemi_mac: Move register definitions to include/asm-powerpc
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
2007-11-29 2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
@ 2007-11-29 2:56 ` Olof Johansson
2007-11-29 2:56 ` [PATCH] [3/12] pasemi: DMA engine management library Olof Johansson
` (10 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:56 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
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(-)
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- /dev/null
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -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 */
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -35,6 +35,7 @@
#include <asm/irq.h>
#include <asm/firmware.h>
+#include <asm/pasemi_dma.h>
#include "pasemi_mac.h"
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -96,11 +96,8 @@ struct pasemi_mac_buffer {
};
-/* status register layout in IOB region, at 0xfb800000 */
-struct pasdma_status {
- u64 rx_sta[64];
- u64 tx_sta[20];
-};
+/* PCI register offsets and formats */
+
/* MAC CFG register offsets */
enum {
@@ -174,333 +171,4 @@ enum {
#define PAS_MAC_IPC_CHNL_BCH(x) (((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
PAS_MAC_IPC_CHNL_BCH_M)
-/* 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_PTR_LEN_S) & XCT_PTR_LEN_M)
-#define XCT_RXB_ADDR_M 0x00000fffffffffffull
-#define XCT_RXB_ADDR_S 0
-#define XCT_RXB_ADDR(x) ((((long)(x)) << XCT_PTR_ADDR_S) & XCT_PTR_ADDR_M)
-
-
#endif /* PASEMI_MAC_H */
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [3/12] pasemi: DMA engine management library
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
2007-11-29 2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
2007-11-29 2:56 ` [PATCH] [2/12] pasemi_mac: Move register definitions to include/asm-powerpc Olof Johansson
@ 2007-11-29 2:56 ` Olof Johansson
2007-11-29 2:56 ` [PATCH] [4/12] pasemi_mac: Convert to new dma library Olof Johansson
` (9 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:56 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi: 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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
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(-)
Index: k.org/arch/powerpc/platforms/pasemi/Makefile
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/Makefile
+++ k.org/arch/powerpc/platforms/pasemi/Makefile
@@ -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
Index: k.org/arch/powerpc/platforms/pasemi/dma_lib.c
===================================================================
--- /dev/null
+++ k.org/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * Common functions for DMA access on PA Semi PWRficient
+ *
+ * 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
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/of.h>
+
+#include <asm/pasemi_dma.h>
+
+#define MAX_TXCH 64
+#define MAX_RXCH 64
+
+static struct pasdma_status *dma_status;
+
+static void __iomem *iob_regs;
+static void __iomem *mac_regs[6];
+static void __iomem *dma_regs;
+
+static int base_hw_irq;
+
+static int num_txch, num_rxch;
+
+static struct pci_dev *dma_pdev;
+
+/* Bitmaps to handle allocation of channels */
+
+static DECLARE_BITMAP(txch_free, MAX_TXCH);
+static DECLARE_BITMAP(rxch_free, MAX_RXCH);
+
+/* pasemi_read_iob_reg - read IOB register
+ * @reg: Register to read (offset into PCI CFG space)
+ */
+unsigned int pasemi_read_iob_reg(unsigned int reg)
+{
+ return in_le32(iob_regs+reg);
+}
+EXPORT_SYMBOL(pasemi_read_iob_reg);
+
+/* pasemi_write_iob_reg - write IOB register
+ * @reg: Register to write to (offset into PCI CFG space)
+ * @val: Value to write
+ */
+void pasemi_write_iob_reg(unsigned int reg, unsigned int val)
+{
+ out_le32(iob_regs+reg, val);
+}
+EXPORT_SYMBOL(pasemi_write_iob_reg);
+
+/* pasemi_read_mac_reg - read MAC register
+ * @intf: MAC interface
+ * @reg: Register to read (offset into PCI CFG space)
+ */
+unsigned int pasemi_read_mac_reg(int intf, unsigned int reg)
+{
+ return in_le32(mac_regs[intf]+reg);
+}
+EXPORT_SYMBOL(pasemi_read_mac_reg);
+
+/* pasemi_write_mac_reg - write MAC register
+ * @intf: MAC interface
+ * @reg: Register to write to (offset into PCI CFG space)
+ * @val: Value to write
+ */
+void pasemi_write_mac_reg(int intf, unsigned int reg, unsigned int val)
+{
+ out_le32(mac_regs[intf]+reg, val);
+}
+EXPORT_SYMBOL(pasemi_write_mac_reg);
+
+/* pasemi_read_dma_reg - read DMA register
+ * @reg: Register to read (offset into PCI CFG space)
+ */
+unsigned int pasemi_read_dma_reg(unsigned int reg)
+{
+ return in_le32(dma_regs+reg);
+}
+EXPORT_SYMBOL(pasemi_read_dma_reg);
+
+/* pasemi_write_dma_reg - write DMA register
+ * @reg: Register to write to (offset into PCI CFG space)
+ * @val: Value to write
+ */
+void pasemi_write_dma_reg(unsigned int reg, unsigned int val)
+{
+ out_le32(dma_regs+reg, val);
+}
+EXPORT_SYMBOL(pasemi_write_dma_reg);
+
+static int pasemi_alloc_tx_chan(enum pasemi_dmachan_type type)
+{
+ int bit;
+ int start, limit;
+
+ switch (type & (TXCHAN_EVT0|TXCHAN_EVT1)) {
+ case TXCHAN_EVT0:
+ start = 0;
+ limit = 10;
+ break;
+ case TXCHAN_EVT1:
+ start = 10;
+ limit = MAX_TXCH;
+ break;
+ default:
+ start = 0;
+ limit = MAX_TXCH;
+ break;
+ }
+retry:
+ bit = find_next_bit(txch_free, MAX_TXCH, start);
+ if (bit >= limit)
+ return -ENOSPC;
+ if (!test_and_clear_bit(bit, txch_free))
+ goto retry;
+
+ return bit;
+}
+
+static void pasemi_free_tx_chan(int chan)
+{
+ BUG_ON(test_bit(chan, txch_free));
+ set_bit(chan, txch_free);
+}
+
+static int pasemi_alloc_rx_chan(void)
+{
+ int bit;
+retry:
+ bit = find_first_bit(rxch_free, MAX_RXCH);
+ if (bit >= MAX_TXCH)
+ return -ENOSPC;
+ if (!test_and_clear_bit(bit, rxch_free))
+ goto retry;
+
+ return bit;
+}
+
+static void pasemi_free_rx_chan(int chan)
+{
+ BUG_ON(test_bit(chan, rxch_free));
+ set_bit(chan, rxch_free);
+}
+
+/* pasemi_dma_alloc_chan - Allocate a DMA channel
+ * @type: Type of channel to allocate
+ * @total_size: Total size of structure to allocate (to allow for more
+ * room behind the structure to be used by the client)
+ * @offset: Offset in bytes from start of the total structure to the beginning
+ * of struct pasemi_dmachan. Needed when struct pasemi_dmachan is
+ * not the first member of the client structure.
+ *
+ * pasemi_dma_alloc_chan allocates a DMA channel for use by a client. The
+ * type argument specifies whether it's a RX or TX channel, and in the case
+ * of TX channels which group it needs to belong to (if any).
+ *
+ * Returns a pointer to the total structure allocated on success, NULL
+ * on failure.
+ */
+void *pasemi_dma_alloc_chan(enum pasemi_dmachan_type type,
+ int total_size, int offset)
+{
+ void *buf;
+ struct pasemi_dmachan *chan;
+ int chno;
+
+ BUG_ON(total_size < sizeof(struct pasemi_dmachan));
+
+ buf = kzalloc(total_size, GFP_KERNEL);
+
+ if (!buf)
+ return NULL;
+ chan = buf + offset;
+
+ chan->priv = buf;
+
+ switch (type & (TXCHAN|RXCHAN)) {
+ case RXCHAN:
+ chno = pasemi_alloc_rx_chan();
+ chan->chno = chno;
+ chan->irq = irq_create_mapping(NULL,
+ base_hw_irq + num_txch + chno);
+ chan->status = &dma_status->rx_sta[chno];
+ break;
+ case TXCHAN:
+ chno = pasemi_alloc_tx_chan(type);
+ chan->chno = chno;
+ chan->irq = irq_create_mapping(NULL, base_hw_irq + chno);
+ chan->status = &dma_status->tx_sta[chno];
+ break;
+ }
+
+ chan->chan_type = type;
+
+ return chan;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_chan);
+
+/* pasemi_dma_free_chan - Free a previously allocated channel
+ * @chan: Channel to free
+ *
+ * Frees a previously allocated channel. It will also deallocate any
+ * descriptor ring associated with the channel, if allocated.
+ */
+void pasemi_dma_free_chan(struct pasemi_dmachan *chan)
+{
+ if (chan->ring_virt)
+ pasemi_dma_free_ring(chan);
+
+ switch (chan->chan_type & (RXCHAN|TXCHAN)) {
+ case RXCHAN:
+ pasemi_free_rx_chan(chan->chno);
+ break;
+ case TXCHAN:
+ pasemi_free_tx_chan(chan->chno);
+ break;
+ }
+
+ kfree(chan->priv);
+}
+EXPORT_SYMBOL(pasemi_dma_free_chan);
+
+/* pasemi_dma_alloc_ring - Allocate descriptor ring for a channel
+ * @chan: Channel for which to allocate
+ * @ring_size: Ring size in 64-bit (8-byte) words
+ *
+ * Allocate a descriptor ring for a channel. Returns 0 on success, errno
+ * on failure. The passed in struct pasemi_dmachan is updated with the
+ * virtual and DMA addresses of the ring.
+ */
+int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size)
+{
+ BUG_ON(chan->ring_virt);
+
+ chan->ring_size = ring_size;
+
+ chan->ring_virt = dma_alloc_coherent(&dma_pdev->dev,
+ ring_size * sizeof(u64),
+ &chan->ring_dma, GFP_KERNEL);
+
+ if (!chan->ring_virt)
+ return -ENOMEM;
+
+ memset(chan->ring_virt, 0, ring_size * sizeof(u64));
+
+ return 0;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_ring);
+
+/* pasemi_dma_free_ring - Free an allocated descriptor ring for a channel
+ * @chan: Channel for which to free the descriptor ring
+ *
+ * Frees a previously allocated descriptor ring for a channel.
+ */
+void pasemi_dma_free_ring(struct pasemi_dmachan *chan)
+{
+ BUG_ON(!chan->ring_virt);
+
+ dma_free_coherent(&dma_pdev->dev, chan->ring_size * sizeof(u64),
+ chan->ring_virt, chan->ring_dma);
+ chan->ring_virt = NULL;
+ chan->ring_size = 0;
+ chan->ring_dma = 0;
+}
+EXPORT_SYMBOL(pasemi_dma_free_ring);
+
+/* pasemi_dma_start_chan - Start a DMA channel
+ * @chan: Channel to start
+ * @cmdsta: Additional CCMDSTA/TCMDSTA bits to write
+ *
+ * Enables (starts) a DMA channel with optional additional arguments.
+ */
+void pasemi_dma_start_chan(const struct pasemi_dmachan *chan, const u32 cmdsta)
+{
+ if (chan->chan_type == RXCHAN)
+ pasemi_write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno),
+ cmdsta | PAS_DMA_RXCHAN_CCMDSTA_EN);
+ else
+ pasemi_write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno),
+ cmdsta | PAS_DMA_TXCHAN_TCMDSTA_EN);
+}
+EXPORT_SYMBOL(pasemi_dma_start_chan);
+
+/* pasemi_dma_stop_chan - Stop a DMA channel
+ * @chan: Channel to stop
+ *
+ * Stops (disables) a DMA channel. This is done by setting the ST bit in the
+ * CMDSTA register and waiting on the ACT (active) bit to clear, then
+ * finally disabling the whole channel.
+ *
+ * This function will only try for a short while for the channel to stop, if
+ * it doesn't it will return failure.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+#define MAX_RETRIES 5000
+int pasemi_dma_stop_chan(const struct pasemi_dmachan *chan)
+{
+ int reg, retries;
+ u32 sta;
+
+ if (chan->chan_type == RXCHAN) {
+ reg = PAS_DMA_RXCHAN_CCMDSTA(chan->chno);
+ pasemi_write_dma_reg(reg, PAS_DMA_RXCHAN_CCMDSTA_ST);
+ for (retries = 0; retries < MAX_RETRIES; retries++) {
+ sta = pasemi_read_dma_reg(reg);
+ if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)) {
+ pasemi_write_dma_reg(reg, 0);
+ return 1;
+ }
+ cond_resched();
+ }
+ } else {
+ reg = PAS_DMA_TXCHAN_TCMDSTA(chan->chno);
+ pasemi_write_dma_reg(reg, PAS_DMA_TXCHAN_TCMDSTA_ST);
+ for (retries = 0; retries < MAX_RETRIES; retries++) {
+ sta = pasemi_read_dma_reg(reg);
+ if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)) {
+ pasemi_write_dma_reg(reg, 0);
+ return 1;
+ }
+ cond_resched();
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(pasemi_dma_stop_chan);
+
+/* pasemi_dma_alloc_buf - Allocate a buffer to use for DMA
+ * @chan: Channel to allocate for
+ * @size: Size of buffer in bytes
+ * @handle: DMA handle
+ *
+ * Allocate a buffer to be used by the DMA engine for read/write,
+ * similar to dma_alloc_coherent().
+ *
+ * Returns the virtual address of the buffer, or NULL in case of failure.
+ */
+void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
+ dma_addr_t *handle)
+{
+ return dma_alloc_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_buf);
+
+/* pasemi_dma_free_buf - Free a buffer used for DMA
+ * @chan: Channel the buffer was allocated for
+ * @size: Size of buffer in bytes
+ * @handle: DMA handle
+ *
+ * Frees a previously allocated buffer.
+ */
+void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
+ dma_addr_t *handle)
+{
+ dma_free_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
+}
+EXPORT_SYMBOL(pasemi_dma_free_buf);
+
+static void *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);
+}
+
+/* pasemi_dma_init - Initialize the PA Semi DMA library
+ *
+ * This function initializes the DMA library. It must be called before
+ * any other function in the library.
+ *
+ * Returns 0 on success, errno on failure.
+ */
+int pasemi_dma_init(void)
+{
+ static spinlock_t init_lock = SPIN_LOCK_UNLOCKED;
+ struct pci_dev *iob_pdev;
+ struct pci_dev *pdev;
+ struct resource res;
+ struct device_node *dn;
+ int i, intf, err = 0;
+ u32 tmp;
+
+ if (!machine_is(pasemi))
+ return -ENODEV;
+
+ spin_lock(&init_lock);
+
+ /* Make sure we haven't already initialized */
+ if (dma_pdev)
+ goto out;
+
+ iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
+ if (!iob_pdev) {
+ BUG();
+ printk(KERN_WARNING "Can't find I/O Bridge\n");
+ err = -ENODEV;
+ goto out;
+ }
+ iob_regs = map_onedev(iob_pdev, 0);
+
+ dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
+ if (!dma_pdev) {
+ BUG();
+ printk(KERN_WARNING "Can't find DMA controller\n");
+ err = -ENODEV;
+ goto out;
+ }
+ dma_regs = map_onedev(dma_pdev, 0);
+ base_hw_irq = virq_to_hw(dma_pdev->irq);
+
+ pci_read_config_dword(dma_pdev, PAS_DMA_CAP_TXCH, &tmp);
+ num_txch = (tmp & PAS_DMA_CAP_TXCH_TCHN_M) >> PAS_DMA_CAP_TXCH_TCHN_S;
+
+ pci_read_config_dword(dma_pdev, PAS_DMA_CAP_RXCH, &tmp);
+ num_rxch = (tmp & PAS_DMA_CAP_RXCH_RCHN_M) >> PAS_DMA_CAP_RXCH_RCHN_S;
+
+ intf = 0;
+ for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, NULL);
+ pdev;
+ pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, pdev))
+ mac_regs[intf++] = map_onedev(pdev, 0);
+
+ pci_dev_put(pdev);
+
+ for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, NULL);
+ pdev;
+ pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, pdev))
+ mac_regs[intf++] = map_onedev(pdev, 0);
+
+ pci_dev_put(pdev);
+
+ dn = pci_device_to_OF_node(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);
+ pci_dev_put(iob_pdev);
+
+ for (i = 0; i < MAX_TXCH; i++)
+ __set_bit(i, txch_free);
+
+ for (i = 0; i < MAX_RXCH; i++)
+ __set_bit(i, rxch_free);
+
+ printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
+ "(%d tx, %d rx channels)\n", num_txch, num_rxch);
+
+out:
+ spin_unlock(&init_lock);
+ return err;
+}
Index: k.org/arch/powerpc/platforms/pasemi/pasemi.h
===================================================================
--- k.org.orig/arch/powerpc/platforms/pasemi/pasemi.h
+++ k.org/arch/powerpc/platforms/pasemi/pasemi.h
@@ -9,6 +9,7 @@ extern void __devinit pas_pci_dma_dev_se
extern 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);
Index: k.org/include/asm-powerpc/pasemi_dma.h
===================================================================
--- k.org.orig/include/asm-powerpc/pasemi_dma.h
+++ k.org/include/asm-powerpc/pasemi_dma.h
@@ -33,11 +33,27 @@ struct pasdma_status {
* device. Use the normal PCI config access functions for them.
*/
enum {
+ PAS_DMA_CAP_TXCH = 0x44, /* Transmit Channel Info */
+ PAS_DMA_CAP_RXCH = 0x48, /* Transmit Channel Info */
+ PAS_DMA_CAP_IFI = 0x4c, /* Interface Info */
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_CAP_TXCH_TCHN_M 0x00ff0000 /* # of TX channels */
+#define PAS_DMA_CAP_TXCH_TCHN_S 16
+
+#define PAS_DMA_CAP_RXCH_RCHN_M 0x00ff0000 /* # of RX channels */
+#define PAS_DMA_CAP_RXCH_RCHN_S 16
+
+#define PAS_DMA_CAP_IFI_IOFF_M 0xff000000 /* Cfg reg for intf pointers */
+#define PAS_DMA_CAP_IFI_IOFF_S 24
+#define PAS_DMA_CAP_IFI_NIN_M 0x00ff0000 /* # of interfaces */
+#define PAS_DMA_CAP_IFI_NIN_S 16
+
#define PAS_DMA_COM_TXCMD_EN 0x00000001 /* enable */
#define PAS_DMA_COM_TXSTA_ACT 0x00000001 /* active */
#define PAS_DMA_COM_RXCMD_EN 0x00000001 /* enable */
@@ -388,4 +404,64 @@ enum {
CTRL_CMD_REG_M)
+
+/* Prototypes for the shared DMA functions in the platform code. */
+
+/* DMA TX Channel type. Right now only limitations used are event types 0/1,
+ * for event-triggered DMA transactions.
+ */
+
+enum pasemi_dmachan_type {
+ RXCHAN = 0, /* Any RX chan */
+ TXCHAN = 1, /* Any TX chan */
+ TXCHAN_EVT0 = 0x1001, /* TX chan in event class 0 (chan 0-9) */
+ TXCHAN_EVT1 = 0x2001, /* TX chan in event class 1 (chan 10-19) */
+};
+
+struct pasemi_dmachan {
+ int chno; /* Channel number */
+ enum pasemi_dmachan_type chan_type; /* TX / RX */
+ u64 *status; /* Ptr to cacheable status */
+ int irq; /* IRQ used by channel */
+ unsigned int ring_size; /* size of allocated ring */
+ dma_addr_t ring_dma; /* DMA address for ring */
+ u64 *ring_virt; /* Virt address for ring */
+ void *priv; /* Ptr to start of client struct */
+};
+
+/* Read/write the different registers in the I/O Bridge, Ethernet
+ * and DMA Controller
+ */
+extern unsigned int pasemi_read_iob_reg(unsigned int reg);
+extern void pasemi_write_iob_reg(unsigned int reg, unsigned int val);
+
+extern unsigned int pasemi_read_mac_reg(int intf, unsigned int reg);
+extern void pasemi_write_mac_reg(int intf, unsigned int reg, unsigned int val);
+
+extern unsigned int pasemi_read_dma_reg(unsigned int reg);
+extern void pasemi_write_dma_reg(unsigned int reg, unsigned int val);
+
+/* Channel management routines */
+
+extern void *pasemi_dma_alloc_chan(enum pasemi_dmachan_type type,
+ int total_size, int offset);
+extern void pasemi_dma_free_chan(struct pasemi_dmachan *chan);
+
+extern void pasemi_dma_start_chan(const struct pasemi_dmachan *chan,
+ const u32 cmdsta);
+extern int pasemi_dma_stop_chan(const struct pasemi_dmachan *chan);
+
+/* Common routines to allocate rings and buffers */
+
+extern int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size);
+extern void pasemi_dma_free_ring(struct pasemi_dmachan *chan);
+
+extern void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
+ dma_addr_t *handle);
+extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
+ dma_addr_t *handle);
+
+/* Initialize the library, must be called before any other functions */
+extern int pasemi_dma_init(void);
+
#endif /* ASM_PASEMI_DMA_H */
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [4/12] pasemi_mac: Convert to new dma library
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (2 preceding siblings ...)
2007-11-29 2:56 ` [PATCH] [3/12] pasemi: DMA engine management library Olof Johansson
@ 2007-11-29 2:56 ` Olof Johansson
2007-11-29 2:56 ` [PATCH] [5/12] pasemi_mac: performance tweaks Olof Johansson
` (8 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:56 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 480 ++++++++++++++++++++---------------------------
drivers/net/pasemi_mac.h | 16 -
2 files changed, 210 insertions(+), 286 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -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 DEFA
module_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_ring
return 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 net
if (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_resources
for (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_ring
wmb();
- 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(s
unsigned 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(s
static 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(in
static 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_de
write_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_de
netif_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_de
return 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_d
struct 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_d
netif_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_d
pasemi_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_d
dev_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 sk
spin_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_s
return 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);
}
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -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;
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [5/12] pasemi_mac: performance tweaks
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (3 preceding siblings ...)
2007-11-29 2:56 ` [PATCH] [4/12] pasemi_mac: Convert to new dma library Olof Johansson
@ 2007-11-29 2:56 ` Olof Johansson
2007-11-29 2:56 ` [PATCH] [6/12] pasemi_mac: Fix TX cleaning Olof Johansson
` (7 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:56 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 114 ++++++++++++++++++++++++++++-------------------
1 file changed, 68 insertions(+), 46 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -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 r
pasemi_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 r
pasemi_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 pa
static 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(struc
return (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_resources
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(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_resources
PAS_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(s
write_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(s
printk(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 pa
for (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(in
static 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 sk
unsigned 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 sk
spin_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 sk
if (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, c
netif_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) {
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [6/12] pasemi_mac: Fix TX cleaning
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (4 preceding siblings ...)
2007-11-29 2:56 ` [PATCH] [5/12] pasemi_mac: performance tweaks Olof Johansson
@ 2007-11-29 2:56 ` Olof Johansson
2007-11-29 2:57 ` [PATCH] [7/12] pasemi_mac: Improve RX interrupt mitigation Olof Johansson
` (6 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:56 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 41 +++++++++++++++++++++++++++++++++--------
drivers/net/pasemi_mac.h | 1 +
2 files changed, 34 insertions(+), 8 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -805,27 +805,43 @@ static irqreturn_t pasemi_mac_rx_intr(in
return 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_de
if (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_d
phy_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_s
netif_rx_complete(dev, napi);
pasemi_mac_restart_rx_intr(mac);
+ pasemi_mac_restart_tx_intr(mac);
}
return pkts;
}
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -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 {
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [7/12] pasemi_mac: Improve RX interrupt mitigation
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (5 preceding siblings ...)
2007-11-29 2:56 ` [PATCH] [6/12] pasemi_mac: Fix TX cleaning Olof Johansson
@ 2007-11-29 2:57 ` Olof Johansson
2007-11-29 2:57 ` [PATCH] [8/12] pasemi_mac: Software-based LRO support Olof Johansson
` (5 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:57 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -504,15 +504,19 @@ static void pasemi_mac_replenish_rx_ring
static 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_de
write_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_de
if (!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));
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [8/12] pasemi_mac: Software-based LRO support
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (6 preceding siblings ...)
2007-11-29 2:57 ` [PATCH] [7/12] pasemi_mac: Improve RX interrupt mitigation Olof Johansson
@ 2007-11-29 2:57 ` Olof Johansson
2007-11-29 2:57 ` [PATCH] [9/12] pasemi_mac: SKB unmap optimization Olof Johansson
` (4 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:57 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_mac: Software-based LRO support
Implement LRO for pasemi_mac. Pretty straightforward.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/Kconfig | 1
drivers/net/pasemi_mac.c | 53 +++++++++++++++++++++++++++++++++++++++++++----
drivers/net/pasemi_mac.h | 5 ++++
3 files changed, 55 insertions(+), 4 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -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 pa
return -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 pa
return 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 pa
skb_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");
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -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;
Index: k.org/drivers/net/Kconfig
===================================================================
--- k.org.orig/drivers/net/Kconfig
+++ k.org/drivers/net/Kconfig
@@ -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.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [9/12] pasemi_mac: SKB unmap optimization
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (7 preceding siblings ...)
2007-11-29 2:57 ` [PATCH] [8/12] pasemi_mac: Software-based LRO support Olof Johansson
@ 2007-11-29 2:57 ` Olof Johansson
2007-11-29 2:57 ` [PATCH] [10/12] pasemi_mac: Remove SKB copy/recycle logic Olof Johansson
` (3 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:57 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 39 +++++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 14 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -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_resources
unsigned 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_resources
for (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 pa
unsigned 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++) {
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [10/12] pasemi_mac: Remove SKB copy/recycle logic
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (8 preceding siblings ...)
2007-11-29 2:57 ` [PATCH] [9/12] pasemi_mac: SKB unmap optimization Olof Johansson
@ 2007-11-29 2:57 ` Olof Johansson
2007-11-29 2:58 ` [PATCH] [11/12] pasemi_mac: Print warning when not attaching to a PHY Olof Johansson
` (2 subsequent siblings)
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:57 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 25 +++----------------------
1 file changed, 3 insertions(+), 22 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -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)) {
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [11/12] pasemi_mac: Print warning when not attaching to a PHY
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (9 preceding siblings ...)
2007-11-29 2:57 ` [PATCH] [10/12] pasemi_mac: Remove SKB copy/recycle logic Olof Johansson
@ 2007-11-29 2:58 ` Olof Johansson
2007-11-29 2:58 ` [PATCH] [12/12] pasemi_mac: Don't enable RX/TX without a link (if possible) Olof Johansson
2007-11-29 2:59 ` [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:58 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -1064,11 +1064,12 @@ static int pasemi_mac_open(struct net_de
write_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);
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] [12/12] pasemi_mac: Don't enable RX/TX without a link (if possible)
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (10 preceding siblings ...)
2007-11-29 2:58 ` [PATCH] [11/12] pasemi_mac: Print warning when not attaching to a PHY Olof Johansson
@ 2007-11-29 2:58 ` Olof Johansson
2007-11-29 2:59 ` [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:58 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
pasemi_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.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
drivers/net/pasemi_mac.c | 41 +++++++++++++++++++++++++++++++++--------
1 file changed, 33 insertions(+), 8 deletions(-)
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -874,6 +874,24 @@ static irqreturn_t pasemi_mac_tx_intr(in
return 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 ne
printk(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_de
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;
+ 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_de
write_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);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
` (11 preceding siblings ...)
2007-11-29 2:58 ` [PATCH] [12/12] pasemi_mac: Don't enable RX/TX without a link (if possible) Olof Johansson
@ 2007-11-29 2:59 ` Olof Johansson
12 siblings, 0 replies; 15+ messages in thread
From: Olof Johansson @ 2007-11-29 2:59 UTC (permalink / raw)
To: jgarzik; +Cc: linuxppc-dev, netdev
On Wed, Nov 28, 2007 at 08:54:10PM -0600, Olof Johansson wrote:
> 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)
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup
2007-11-29 2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
@ 2007-12-01 21:54 ` Jeff Garzik
0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2007-12-01 21:54 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev, netdev
Olof Johansson wrote:
> 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.
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
applied 1-12
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2007-12-01 21:54 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-29 2:54 [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
2007-11-29 2:54 ` [PATCH] [1/12] pasemi_mac: RX/TX ring management cleanup Olof Johansson
2007-12-01 21:54 ` Jeff Garzik
2007-11-29 2:56 ` [PATCH] [2/12] pasemi_mac: Move register definitions to include/asm-powerpc Olof Johansson
2007-11-29 2:56 ` [PATCH] [3/12] pasemi: DMA engine management library Olof Johansson
2007-11-29 2:56 ` [PATCH] [4/12] pasemi_mac: Convert to new dma library Olof Johansson
2007-11-29 2:56 ` [PATCH] [5/12] pasemi_mac: performance tweaks Olof Johansson
2007-11-29 2:56 ` [PATCH] [6/12] pasemi_mac: Fix TX cleaning Olof Johansson
2007-11-29 2:57 ` [PATCH] [7/12] pasemi_mac: Improve RX interrupt mitigation Olof Johansson
2007-11-29 2:57 ` [PATCH] [8/12] pasemi_mac: Software-based LRO support Olof Johansson
2007-11-29 2:57 ` [PATCH] [9/12] pasemi_mac: SKB unmap optimization Olof Johansson
2007-11-29 2:57 ` [PATCH] [10/12] pasemi_mac: Remove SKB copy/recycle logic Olof Johansson
2007-11-29 2:58 ` [PATCH] [11/12] pasemi_mac: Print warning when not attaching to a PHY Olof Johansson
2007-11-29 2:58 ` [PATCH] [12/12] pasemi_mac: Don't enable RX/TX without a link (if possible) Olof Johansson
2007-11-29 2:59 ` [PATCH] [0/12] pasemi_mac updates for 2.6.25 + DMA channel management library Olof Johansson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.