* [PATCH] [3/11] pasemi_mac: rework ring management
From: Olof Johansson @ 2007-10-02 21:25 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>
pasemi_mac: rework ring management
Rework ring management, switching to an opaque ring format instead of
the struct-based descriptor+pointer setup, since it will be needed for
SG support.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -63,10 +63,10 @@
NETIF_MSG_RX_ERR | \
NETIF_MSG_TX_ERR)
-#define TX_DESC(mac, num) ((mac)->tx->desc[(num) & (TX_RING_SIZE-1)])
-#define TX_DESC_INFO(mac, num) ((mac)->tx->desc_info[(num) & (TX_RING_SIZE-1)])
-#define RX_DESC(mac, num) ((mac)->rx->desc[(num) & (RX_RING_SIZE-1)])
-#define RX_DESC_INFO(mac, num) ((mac)->rx->desc_info[(num) & (RX_RING_SIZE-1)])
+#define TX_RING(mac, num) ((mac)->tx->ring[(num) & (TX_RING_SIZE-1)])
+#define TX_RING_INFO(mac, num) ((mac)->tx->ring_info[(num) & (TX_RING_SIZE-1)])
+#define RX_RING(mac, num) ((mac)->rx->ring[(num) & (RX_RING_SIZE-1)])
+#define RX_RING_INFO(mac, num) ((mac)->rx->ring_info[(num) & (RX_RING_SIZE-1)])
#define RX_BUFF(mac, num) ((mac)->rx->buffers[(num) & (RX_RING_SIZE-1)])
#define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
@@ -174,22 +174,21 @@ static int pasemi_mac_setup_rx_resources
spin_lock_init(&ring->lock);
ring->size = RX_RING_SIZE;
- ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
+ ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
RX_RING_SIZE, GFP_KERNEL);
- if (!ring->desc_info)
- goto out_desc_info;
+ if (!ring->ring_info)
+ goto out_ring_info;
/* Allocate descriptors */
- ring->desc = dma_alloc_coherent(&mac->dma_pdev->dev,
- RX_RING_SIZE *
- sizeof(struct pas_dma_xct_descr),
+ ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
+ RX_RING_SIZE * sizeof(u64),
&ring->dma, GFP_KERNEL);
- if (!ring->desc)
- goto out_desc;
+ if (!ring->ring)
+ goto out_ring_desc;
- memset(ring->desc, 0, RX_RING_SIZE * sizeof(struct pas_dma_xct_descr));
+ memset(ring->ring, 0, RX_RING_SIZE * sizeof(u64));
ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
RX_RING_SIZE * sizeof(u64),
@@ -203,7 +202,7 @@ static int pasemi_mac_setup_rx_resources
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 >> 2));
+ PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3));
write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id),
PAS_DMA_RXCHAN_CFG_HBU(2));
@@ -229,11 +228,11 @@ static int pasemi_mac_setup_rx_resources
out_buffers:
dma_free_coherent(&mac->dma_pdev->dev,
- RX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
- mac->rx->desc, mac->rx->dma);
-out_desc:
- kfree(ring->desc_info);
-out_desc_info:
+ RX_RING_SIZE * sizeof(u64),
+ mac->rx->ring, mac->rx->dma);
+out_ring_desc:
+ kfree(ring->ring_info);
+out_ring_info:
kfree(ring);
out_ring:
return -ENOMEM;
@@ -254,25 +253,24 @@ static int pasemi_mac_setup_tx_resources
spin_lock_init(&ring->lock);
ring->size = TX_RING_SIZE;
- ring->desc_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
+ ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
TX_RING_SIZE, GFP_KERNEL);
- if (!ring->desc_info)
- goto out_desc_info;
+ if (!ring->ring_info)
+ goto out_ring_info;
/* Allocate descriptors */
- ring->desc = dma_alloc_coherent(&mac->dma_pdev->dev,
- TX_RING_SIZE *
- sizeof(struct pas_dma_xct_descr),
+ ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
+ TX_RING_SIZE * sizeof(u64),
&ring->dma, GFP_KERNEL);
- if (!ring->desc)
- goto out_desc;
+ if (!ring->ring)
+ goto out_ring_desc;
- memset(ring->desc, 0, TX_RING_SIZE * sizeof(struct pas_dma_xct_descr));
+ memset(ring->ring, 0, TX_RING_SIZE * sizeof(u64));
write_dma_reg(mac, PAS_DMA_TXCHAN_BASEL(chan_id),
PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32);
- val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 2);
+ val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 3);
write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
@@ -291,9 +289,9 @@ static int pasemi_mac_setup_tx_resources
return 0;
-out_desc:
- kfree(ring->desc_info);
-out_desc_info:
+out_ring_desc:
+ kfree(ring->ring_info);
+out_ring_info:
kfree(ring);
out_ring:
return -ENOMEM;
@@ -304,31 +302,27 @@ static void pasemi_mac_free_tx_resources
struct pasemi_mac *mac = netdev_priv(dev);
unsigned int i;
struct pasemi_mac_buffer *info;
- struct pas_dma_xct_descr *dp;
- for (i = 0; i < TX_RING_SIZE; i++) {
- info = &TX_DESC_INFO(mac, i);
- dp = &TX_DESC(mac, i);
- if (info->dma) {
- if (info->skb) {
- pci_unmap_single(mac->dma_pdev,
- info->dma,
- info->skb->len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb_any(info->skb);
- }
- info->dma = 0;
- info->skb = NULL;
- dp->mactx = 0;
- dp->ptr = 0;
+ for (i = 0; i < TX_RING_SIZE; i += 2) {
+ info = &TX_RING_INFO(mac, i+1);
+ if (info->dma && info->skb) {
+ pci_unmap_single(mac->dma_pdev,
+ info->dma,
+ info->skb->len,
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(info->skb);
}
+ TX_RING(mac, i) = 0;
+ TX_RING(mac, i+1) = 0;
+ info->dma = 0;
+ info->skb = NULL;
}
dma_free_coherent(&mac->dma_pdev->dev,
- TX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
- mac->tx->desc, mac->tx->dma);
+ TX_RING_SIZE * sizeof(u64),
+ mac->tx->ring, mac->tx->dma);
- kfree(mac->tx->desc_info);
+ kfree(mac->tx->ring_info);
kfree(mac->tx);
mac->tx = NULL;
}
@@ -338,34 +332,31 @@ static void pasemi_mac_free_rx_resources
struct pasemi_mac *mac = netdev_priv(dev);
unsigned int i;
struct pasemi_mac_buffer *info;
- struct pas_dma_xct_descr *dp;
for (i = 0; i < RX_RING_SIZE; i++) {
- info = &RX_DESC_INFO(mac, i);
- dp = &RX_DESC(mac, i);
- if (info->skb) {
- if (info->dma) {
- pci_unmap_single(mac->dma_pdev,
- info->dma,
- info->skb->len,
- PCI_DMA_FROMDEVICE);
- dev_kfree_skb_any(info->skb);
- }
- info->dma = 0;
- info->skb = NULL;
- dp->macrx = 0;
- dp->ptr = 0;
+ info = &RX_RING_INFO(mac, i);
+ if (info->skb && info->dma) {
+ pci_unmap_single(mac->dma_pdev,
+ info->dma,
+ info->skb->len,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb_any(info->skb);
}
+ info->dma = 0;
+ info->skb = NULL;
}
+ for (i = 0; i < RX_RING_SIZE; i++)
+ RX_RING(mac, i) = 0;
+
dma_free_coherent(&mac->dma_pdev->dev,
- RX_RING_SIZE * sizeof(struct pas_dma_xct_descr),
- mac->rx->desc, mac->rx->dma);
+ RX_RING_SIZE * sizeof(u64),
+ mac->rx->ring, mac->rx->dma);
dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
mac->rx->buffers, mac->rx->buf_dma);
- kfree(mac->rx->desc_info);
+ kfree(mac->rx->ring_info);
kfree(mac->rx);
mac->rx = NULL;
}
@@ -373,20 +364,22 @@ static void pasemi_mac_free_rx_resources
static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
{
struct pasemi_mac *mac = netdev_priv(dev);
- unsigned int i;
int start = mac->rx->next_to_fill;
- int count;
+ unsigned int fill, count;
if (limit <= 0)
return;
- i = start;
+ fill = start;
for (count = 0; count < limit; count++) {
- struct pasemi_mac_buffer *info = &RX_DESC_INFO(mac, i);
- u64 *buff = &RX_BUFF(mac, i);
+ struct pasemi_mac_buffer *info = &RX_RING_INFO(mac, fill);
+ u64 *buff = &RX_BUFF(mac, fill);
struct sk_buff *skb;
dma_addr_t dma;
+ /* Entry in use? */
+ WARN_ON(*buff);
+
/* skb might still be in there for recycle on short receives */
if (info->skb)
skb = info->skb;
@@ -407,7 +400,7 @@ static void pasemi_mac_replenish_rx_ring
info->skb = skb;
info->dma = dma;
*buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma);
- i++;
+ fill++;
}
wmb();
@@ -481,7 +474,6 @@ static int pasemi_mac_clean_rx(struct pa
{
unsigned int n;
int count;
- struct pas_dma_xct_descr *dp;
struct pasemi_mac_buffer *info;
struct sk_buff *skb;
unsigned int i, len;
@@ -496,9 +488,7 @@ static int pasemi_mac_clean_rx(struct pa
rmb();
- dp = &RX_DESC(mac, n);
- prefetchw(dp);
- macrx = dp->macrx;
+ macrx = RX_RING(mac, n);
if ((macrx & XCT_MACRX_E) ||
(*mac->rx_status & PAS_STATUS_ERROR))
@@ -516,12 +506,15 @@ static int pasemi_mac_clean_rx(struct pa
* interface ring.
*/
- dma = (dp->ptr & XCT_PTR_ADDR_M);
- for (i = n; i < (n + RX_RING_SIZE); i++) {
- info = &RX_DESC_INFO(mac, i);
+ dma = (RX_RING(mac, n+1) & XCT_PTR_ADDR_M);
+ for (i = mac->rx->next_to_fill;
+ i < (mac->rx->next_to_fill + RX_RING_SIZE);
+ i++) {
+ info = &RX_RING_INFO(mac, i);
if (info->dma == dma)
break;
}
+
prefetchw(info);
skb = info->skb;
@@ -546,6 +539,11 @@ static int pasemi_mac_clean_rx(struct pa
} else
info->skb = NULL;
+ /* Need to zero it out since hardware doesn't, since the
+ * replenish loop uses it to tell when it's done.
+ */
+ RX_BUFF(mac, i) = 0;
+
skb_put(skb, len);
if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
@@ -561,13 +559,13 @@ static int pasemi_mac_clean_rx(struct pa
skb->protocol = eth_type_trans(skb, mac->netdev);
netif_receive_skb(skb);
- dp->ptr = 0;
- dp->macrx = 0;
+ RX_RING(mac, n) = 0;
+ RX_RING(mac, n+1) = 0;
- n++;
+ n += 2;
}
- mac->rx->next_to_clean += limit - count;
+ mac->rx->next_to_clean = n;
pasemi_mac_replenish_rx_ring(mac->netdev, limit-count);
spin_unlock(&mac->rx->lock);
@@ -579,7 +577,6 @@ static int pasemi_mac_clean_tx(struct pa
{
int i;
struct pasemi_mac_buffer *info;
- struct pas_dma_xct_descr *dp;
unsigned int start, count, limit;
unsigned int total_count;
unsigned long flags;
@@ -595,29 +592,28 @@ restart:
count = 0;
- for (i = start; i < limit; i++) {
- dp = &TX_DESC(mac, i);
-
- if ((dp->mactx & XCT_MACTX_E) ||
+ for (i = start; i < limit; i += 2) {
+ u64 mactx = TX_RING(mac, i);
+ if ((mactx & XCT_MACTX_E) ||
(*mac->tx_status & PAS_STATUS_ERROR))
- pasemi_mac_tx_error(mac, dp->mactx);
+ pasemi_mac_tx_error(mac, mactx);
- if (unlikely(dp->mactx & XCT_MACTX_O))
+ if (unlikely(mactx & XCT_MACTX_O))
/* Not yet transmitted */
break;
- info = &TX_DESC_INFO(mac, i);
+ info = &TX_RING_INFO(mac, i+1);
skbs[count] = info->skb;
dmas[count] = info->dma;
- info->skb = NULL;
info->dma = 0;
- dp->mactx = 0;
- dp->ptr = 0;
+ TX_RING(mac, i) = 0;
+ TX_RING(mac, i+1) = 0;
+
count++;
}
- mac->tx->next_to_clean += count;
+ mac->tx->next_to_clean += count * 2;
spin_unlock_irqrestore(&mac->tx->lock, flags);
netif_wake_queue(mac->netdev);
@@ -1001,8 +997,6 @@ static int pasemi_mac_start_tx(struct sk
{
struct pasemi_mac *mac = netdev_priv(dev);
struct pasemi_mac_txring *txring;
- struct pasemi_mac_buffer *info;
- struct pas_dma_xct_descr *dp;
u64 dflags, mactx, ptr;
dma_addr_t map;
unsigned long flags;
@@ -1038,13 +1032,13 @@ static int pasemi_mac_start_tx(struct sk
spin_lock_irqsave(&txring->lock, flags);
- if (RING_AVAIL(txring) <= 1) {
+ if (RING_AVAIL(txring) <= 2) {
spin_unlock_irqrestore(&txring->lock, flags);
pasemi_mac_clean_tx(mac);
pasemi_mac_restart_tx_intr(mac);
spin_lock_irqsave(&txring->lock, flags);
- if (RING_AVAIL(txring) <= 1) {
+ if (RING_AVAIL(txring) <= 2) {
/* Still no room -- stop the queue and wait for tx
* intr when there's room.
*/
@@ -1053,15 +1047,14 @@ static int pasemi_mac_start_tx(struct sk
}
}
- dp = &TX_DESC(mac, txring->next_to_fill);
- info = &TX_DESC_INFO(mac, txring->next_to_fill);
+ TX_RING(mac, txring->next_to_fill) = mactx;
+ TX_RING(mac, txring->next_to_fill+1) = ptr;
+
+ TX_RING_INFO(mac, txring->next_to_fill+1).dma = map;
+ TX_RING_INFO(mac, txring->next_to_fill+1).skb = skb;
- dp->mactx = mactx;
- dp->ptr = ptr;
- info->dma = map;
- info->skb = skb;
+ txring->next_to_fill += 2;
- txring->next_to_fill++;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
Index: k.org/drivers/net/pasemi_mac.h
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.h
+++ k.org/drivers/net/pasemi_mac.h
@@ -28,25 +28,25 @@
struct pasemi_mac_txring {
spinlock_t lock;
- struct pas_dma_xct_descr *desc;
+ u64 *ring;
dma_addr_t dma;
unsigned int size;
unsigned int next_to_fill;
unsigned int next_to_clean;
- struct pasemi_mac_buffer *desc_info;
+ struct pasemi_mac_buffer *ring_info;
char irq_name[10]; /* "eth%d tx" */
};
struct pasemi_mac_rxring {
spinlock_t lock;
- struct pas_dma_xct_descr *desc; /* RX channel descriptor ring */
+ u64 *ring; /* RX channel descriptor ring */
dma_addr_t dma;
u64 *buffers; /* RX interface buffer ring */
dma_addr_t buf_dma;
unsigned int size;
unsigned int next_to_fill;
unsigned int next_to_clean;
- struct pasemi_mac_buffer *desc_info;
+ struct pasemi_mac_buffer *ring_info;
char irq_name[10]; /* "eth%d rx" */
};
@@ -88,7 +88,7 @@ struct pasemi_mac {
char phy_id[BUS_ID_SIZE];
};
-/* Software status descriptor (desc_info) */
+/* Software status descriptor (ring_info) */
struct pasemi_mac_buffer {
struct sk_buff *skb;
dma_addr_t dma;
@@ -101,20 +101,7 @@ struct pasdma_status {
u64 tx_sta[20];
};
-/* descriptor structure */
-struct pas_dma_xct_descr {
- union {
- u64 mactx;
- u64 macrx;
- };
- union {
- u64 ptr;
- u64 rxb;
- };
-};
-
/* MAC CFG register offsets */
-
enum {
PAS_MAC_CFG_PCFG = 0x80,
PAS_MAC_CFG_TXP = 0x98,
^ permalink raw reply
* [patch 11/13] PHYLIB: fix an interrupt loop potential when halting
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, macro, afleming, jgarzik
From: "Maciej W. Rozycki" <macro@linux-mips.org>
Ensure the PHY_HALTED state is not entered with the IRQ asserted as it
could lead to an interrupt loop.
There is a small window in phy_stop(), where the state of the PHY machine
indicates it has been halted, but its interrupt output might still be
unmasked. If an interrupt goes active right at this moment it will loop as
the phy_interrupt() handler exits immediately with IRQ_NONE if the halted
state is seen. It is unsafe to extend the phydev spinlock to cover
phy_interrupt(). It is safe to swap the order of the actions though as all
the competing places to unmask the interrupt output of the PHY, which are
phy_change() and phy_timer() are already covered with the lock as is the
sequence in question.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: Andy Fleming <afleming@freescale.com>
Cc: Jeff Garzik <jgarzik@pobox.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/phy/phy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff -puN drivers/net/phy/phy.c~phylib-fix-an-interrupt-loop-potential-when-halting drivers/net/phy/phy.c
--- a/drivers/net/phy/phy.c~phylib-fix-an-interrupt-loop-potential-when-halting
+++ a/drivers/net/phy/phy.c
@@ -737,8 +737,6 @@ void phy_stop(struct phy_device *phydev)
if (PHY_HALTED == phydev->state)
goto out_unlock;
- phydev->state = PHY_HALTED;
-
if (phydev->irq != PHY_POLL) {
/* Disable PHY Interrupts */
phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
@@ -747,6 +745,8 @@ void phy_stop(struct phy_device *phydev)
phy_clear_interrupt(phydev);
}
+ phydev->state = PHY_HALTED;
+
out_unlock:
spin_unlock_bh(&phydev->lock);
_
^ permalink raw reply
* Re: tcp bw in 2.6
From: Larry McVoy @ 2007-10-02 21:21 UTC (permalink / raw)
To: David Miller; +Cc: torvalds, lm, herbert, wscott, netdev
In-Reply-To: <20071002.133322.52193802.davem@davemloft.net>
> We fixed a lot of bugs in TSO last year.
>
> It would be really great to see numbers with a more recent kernel
> than 2.6.18
More data, sky2 works fine (really really fine, like 79MB/sec) between
Linux dylan.bitmover.com 2.6.18.1 #5 SMP Mon Oct 23 17:36:00 PDT 2006 i686
Linux steele 2.6.20-16-generic #2 SMP Sun Sep 23 18:31:23 UTC 2007 x86_64
So this is looking like a e1000 bug. I'll try to upgrade the kernel on
the ia64 box and see what happens.
--
---
Larry McVoy lm at bitmover.com http://www.bitkeeper.com
^ permalink raw reply
* [patch 12/13] Clean up redundant PHY write line for ULi526x Ethernet driver
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, tie-fei.zang, grundler
From: Roy Zang <tie-fei.zang@freescale.com>
Clean up redundant PHY write line for ULi526x Ethernet Driver.
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
Cc: Jeff Garzik <jeff@garzik.org>
Acked-by: Grant Grundler <grundler@parisc-linux.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/tulip/uli526x.c | 1 -
1 file changed, 1 deletion(-)
diff -puN drivers/net/tulip/uli526x.c~clean-up-redundant-phy-write-line-for-uli526x-ethernet drivers/net/tulip/uli526x.c
--- a/drivers/net/tulip/uli526x.c~clean-up-redundant-phy-write-line-for-uli526x-ethernet
+++ a/drivers/net/tulip/uli526x.c
@@ -1599,7 +1599,6 @@ static void uli526x_process_mode(struct
case ULI526X_100MFD: phy_reg = 0x2100; break;
}
phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
- phy_write(db->ioaddr, db->phy_addr, 0, phy_reg, db->chip_id);
}
}
}
_
^ permalink raw reply
* [PATCH] [2/11] pasemi_mac: fix bug in receive buffer dma mapping
From: Olof Johansson @ 2007-10-02 21:25 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>
pasemi_mac: fix bug in receive buffer dma mapping
skb->len isn't actually set to the size of the allocated skb, so don't
try to use it when figuring out how much to map.
(This hasn't surfaced as a real bug because we effectively disable
translation for the interface, but it still needs fixing for the future)
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -396,7 +396,7 @@ static void pasemi_mac_replenish_rx_ring
if (unlikely(!skb))
break;
- dma = pci_map_single(mac->dma_pdev, skb->data, skb->len,
+ dma = pci_map_single(mac->dma_pdev, skb->data, BUF_SIZE,
PCI_DMA_FROMDEVICE);
if (unlikely(dma_mapping_error(dma))) {
^ permalink raw reply
* [PATCH] [1/11] pasemi_mac: basic error checking
From: Olof Johansson @ 2007-10-02 21:24 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
In-Reply-To: <20071002212421.GA2282@lixom.net>
pasemi_mac: basic error checking
Add some rudimentary error checking to pasemi_mac.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: k.org/drivers/net/pasemi_mac.c
===================================================================
--- k.org.orig/drivers/net/pasemi_mac.c
+++ k.org/drivers/net/pasemi_mac.c
@@ -445,6 +445,38 @@ static void pasemi_mac_restart_tx_intr(s
}
+static inline void pasemi_mac_rx_error(struct pasemi_mac *mac, u64 macrx)
+{
+ unsigned int rcmdsta, ccmdsta;
+
+ if (!netif_msg_rx_err(mac))
+ return;
+
+ rcmdsta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
+ ccmdsta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
+
+ printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n",
+ macrx, *mac->rx_status);
+
+ printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n",
+ rcmdsta, ccmdsta);
+}
+
+static inline void pasemi_mac_tx_error(struct pasemi_mac *mac, u64 mactx)
+{
+ unsigned int cmdsta;
+
+ if (!netif_msg_tx_err(mac))
+ return;
+
+ cmdsta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
+
+ printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\
+ "tx status 0x%016lx\n", mactx, *mac->tx_status);
+
+ printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
+}
+
static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
{
unsigned int n;
@@ -468,10 +500,13 @@ static int pasemi_mac_clean_rx(struct pa
prefetchw(dp);
macrx = dp->macrx;
+ if ((macrx & XCT_MACRX_E) ||
+ (*mac->rx_status & PAS_STATUS_ERROR))
+ pasemi_mac_rx_error(mac, macrx);
+
if (!(macrx & XCT_MACRX_O))
break;
-
info = NULL;
/* We have to scan for our skb since there's no way
@@ -563,6 +598,10 @@ restart:
for (i = start; i < limit; i++) {
dp = &TX_DESC(mac, i);
+ if ((dp->mactx & XCT_MACTX_E) ||
+ (*mac->tx_status & PAS_STATUS_ERROR))
+ pasemi_mac_tx_error(mac, dp->mactx);
+
if (unlikely(dp->mactx & XCT_MACTX_O))
/* Not yet transmitted */
break;
@@ -607,9 +646,6 @@ static irqreturn_t pasemi_mac_rx_intr(in
if (!(*mac->rx_status & PAS_STATUS_CAUSE_M))
return IRQ_NONE;
- if (*mac->rx_status & PAS_STATUS_ERROR)
- printk("rx_status reported error\n");
-
/* Don't reset packet count so it won't fire again but clear
* all others.
*/
@@ -1230,7 +1266,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
dev_err(&mac->pdev->dev, "register_netdev failed with error %d\n",
err);
goto out;
- } else
+ } else if netif_msg_probe(mac)
printk(KERN_INFO "%s: PA Semi %s: intf %d, txch %d, rxch %d, "
"hw addr %s\n",
dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
^ permalink raw reply
* [PATCH] [0/11] pasemi_mac: Patches for 2.6.24
From: Olof Johansson @ 2007-10-02 21:24 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
Hi,
This series of patches go on top of the previous fixes that were sent
out and picked up.
It's a series of mostly feature-related changes, but also a couple
of bugfixes:
[1/11] pasemi_mac: basic error checking
[2/11] pasemi_mac: fix bug in receive buffer dma mapping
[3/11] pasemi_mac: rework ring management
[4/11] pasemi_mac: implement sg support
[5/11] pasemi_mac: workaround for erratum 5971
[6/11] pasemi_mac: add local skb alignment
[7/11] pasemi_mac: further performance tweaks
[8/11] pasemi_mac: update todo list
[9/11] pasemi_mac: clear out old errors on interface open
[10/11] pasemi_mac: use buffer index pointer in clean_rx()
[11/11] pasemi_mac: enable iommu support
Thanks,
-Olof
^ permalink raw reply
* Re: [patch 06/13] Fix a potential NULL pointer dereference in uli526x_interrupt() in drivers/net/tulip/uli526x.c
From: Grant Grundler @ 2007-10-02 21:20 UTC (permalink / raw)
To: akpm; +Cc: jeff, netdev, micah.gruber, grundler, kyle
In-Reply-To: <200710022111.l92LBcIs022492@imap1.linux-foundation.org>
On Tue, Oct 02, 2007 at 02:11:38PM -0700, akpm@linux-foundation.org wrote:
> From: Micah Gruber <micah.gruber@gmail.com>
>
> This patch fixes an apparent potential null dereference bug where we
> dereference dev before a null check. This patch simply remvoes the
> can't-happen test for a null pointer.
>
> Signed-off-by: Micah Gruber <micah.gruber@gmail.com>
> Cc: Grant Grundler <grundler@parisc-linux.org>
Acked-by: Grant Grundler <grundler@parisc-linux.org>
thanks!
grant
> Acked-by: Jeff Garzik <jeff@garzik.org>
> Acked-by: Kyle McMartin <kyle@mcmartin.ca>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
> ---
>
> drivers/net/tulip/uli526x.c | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff -puN drivers/net/tulip/uli526x.c~fix-a-potential-null-pointer-dereference-in-uli526x_interrupt drivers/net/tulip/uli526x.c
> --- a/drivers/net/tulip/uli526x.c~fix-a-potential-null-pointer-dereference-in-uli526x_interrupt
> +++ a/drivers/net/tulip/uli526x.c
> @@ -664,11 +664,6 @@ static irqreturn_t uli526x_interrupt(int
> unsigned long ioaddr = dev->base_addr;
> unsigned long flags;
>
> - if (!dev) {
> - ULI526X_DBUG(1, "uli526x_interrupt() without DEVICE arg", 0);
> - return IRQ_NONE;
> - }
> -
> spin_lock_irqsave(&db->lock, flags);
> outl(0, ioaddr + DCR7);
>
> _
^ permalink raw reply
* Re: [PATCH 2.6.24] tg3: fix ethtool autonegotiate flags
From: Andy Gospodarek @ 2007-10-02 21:16 UTC (permalink / raw)
To: Michael Chan; +Cc: David Miller, jeff, netdev
In-Reply-To: <1191362576.5961.15.camel@dell>
On Tue, Oct 02, 2007 at 03:02:56PM -0700, Michael Chan wrote:
> On Tue, 2007-10-02 at 16:16 -0400, Andy Gospodarek wrote:
> > Adding that flag in tg3_set_settings seemed like the most logical
> > place
> > since the driver works fine on boot. This is just an issue when
> > re-enabling autonegotiation, so we should probably nip it there.
> >
> > Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
>
> We also noticed this issue recently, but didn't pay too much attention
> to it since it was more of a "cosmetic" issue. The driver behaves the
> same since we rely on cmd->autoneg to decide whether to enable autoneg
> or not. Your fix seems reasonable to me. Thanks.
>
> Acked-by: Michael Chan <mchan@broadcom.com>
>
I completely agree that it's cosmetic, it just seems like something
decent to toss in there since it's the kind of thing others will start
complaining about.
^ permalink raw reply
* Re: tcp bw in 2.6
From: David Miller @ 2007-10-02 21:16 UTC (permalink / raw)
To: lm; +Cc: torvalds, herbert, wscott, netdev
In-Reply-To: <20071002164858.GH17418@bitmover.com>
From: lm@bitmover.com (Larry McVoy)
Date: Tue, 2 Oct 2007 09:48:58 -0700
> Isn't this something so straightforward that you would have tests for it?
> This is the basic FTP server loop, doesn't someone have a big machine with
> 10gig cards and test that sending/recving data doesn't regress?
Nobody is really doing this, or they aren't talking about it.
Sometimes the crash fixes and other work completely consumes us. Add
in travel to conferences and real life, and it's no surprise stuff
like this slips through the cracks.
We absolutely depend upon people like you to report when there are
anomalies like this. It's the only thing that scales.
FWIW I have a t1000 Niagara box and an Ultra45 going through a netgear
gigabit switch. I'm getting 85MB/sec in one direction and 10MB/sec in
the other (using bw_tcp from lmbench3). Both are using identical
broadcom tigon3 gigabit chips and identical current kernels so that is
a truly strange result.
I'll investigate, it may be the same thing you're seeing.
^ permalink raw reply
* [patch 10/13] PHYLIB: IRQ event workqueue handling fixes
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, macro, afleming, jgarzik
From: "Maciej W. Rozycki" <macro@linux-mips.org>
Keep track of disable_irq_nosync() invocations and call enable_irq() the
right number of times if work has been cancelled that would include them.
Now that the call to flush_work_keventd() (problematic because of
rtnl_mutex being held) has been replaced by cancel_work_sync() another
issue has arisen and been left unresolved. As the MDIO bus cannot be
accessed from the interrupt context the PHY interrupt handler uses
disable_irq_nosync() to prevent from looping and schedules some work to be
done as a softirq, which, apart from handling the state change of the
originating PHY, is responsible for reenabling the interrupt. Now if the
interrupt line is shared by another device and a call to the softirq
handler has been cancelled, that call to enable_irq() never happens and the
other device cannot use its interrupt anymore as its stuck disabled.
I decided to use a counter rather than a flag because there may be more
than one call to phy_change() cancelled in the queue -- a real one and a
fake one triggered by free_irq() if DEBUG_SHIRQ is used, if nothing else.
Therefore because of its nesting property enable_irq() has to be called the
right number of times to match the number disable_irq_nosync() was called
and restore the original state. This DEBUG_SHIRQ feature is also the
reason why free_irq() has to be called before cancel_work_sync().
While at it I updated the comment about phy_stop_interrupts() being called
from `keventd' -- this is no longer relevant as the use of
cancel_work_sync() makes such an approach unnecessary. OTOH a similar
comment referring to flush_scheduled_work() in phy_stop() still applies as
using cancel_work_sync() there would be dangerous.
Checked with checkpatch.pl and at the run time (with and without
DEBUG_SHIRQ).
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: Andy Fleming <afleming@freescale.com>
Cc: Jeff Garzik <jgarzik@pobox.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/phy/phy.c | 24 +++++++++++++++++++-----
include/linux/phy.h | 3 +++
2 files changed, 22 insertions(+), 5 deletions(-)
diff -puN drivers/net/phy/phy.c~phylib-irq-event-workqueue-handling-fixes drivers/net/phy/phy.c
--- a/drivers/net/phy/phy.c~phylib-irq-event-workqueue-handling-fixes
+++ a/drivers/net/phy/phy.c
@@ -7,7 +7,7 @@
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, Inc.
- * Copyright (c) 2006 Maciej W. Rozycki
+ * Copyright (c) 2006, 2007 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -35,6 +35,7 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
+#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -562,6 +563,7 @@ static irqreturn_t phy_interrupt(int irq
* queue will write the PHY to disable and clear the
* interrupt, and then reenable the irq line. */
disable_irq_nosync(irq);
+ atomic_inc(&phydev->irq_disable);
schedule_work(&phydev->phy_queue);
@@ -632,6 +634,7 @@ int phy_start_interrupts(struct phy_devi
INIT_WORK(&phydev->phy_queue, phy_change);
+ atomic_set(&phydev->irq_disable, 0);
if (request_irq(phydev->irq, phy_interrupt,
IRQF_SHARED,
"phy_interrupt",
@@ -662,13 +665,22 @@ int phy_stop_interrupts(struct phy_devic
if (err)
phy_error(phydev);
+ free_irq(phydev->irq, phydev);
+
/*
- * Finish any pending work; we might have been scheduled to be called
- * from keventd ourselves, but cancel_work_sync() handles that.
+ * Cannot call flush_scheduled_work() here as desired because
+ * of rtnl_lock(), but we do not really care about what would
+ * be done, except from enable_irq(), so cancel any work
+ * possibly pending and take care of the matter below.
*/
cancel_work_sync(&phydev->phy_queue);
-
- free_irq(phydev->irq, phydev);
+ /*
+ * If work indeed has been cancelled, disable_irq() will have
+ * been left unbalanced from phy_interrupt() and enable_irq()
+ * has to be called so that other devices on the line work.
+ */
+ while (atomic_dec_return(&phydev->irq_disable) >= 0)
+ enable_irq(phydev->irq);
return err;
}
@@ -695,6 +707,7 @@ static void phy_change(struct work_struc
phydev->state = PHY_CHANGELINK;
spin_unlock_bh(&phydev->lock);
+ atomic_dec(&phydev->irq_disable);
enable_irq(phydev->irq);
/* Reenable interrupts */
@@ -708,6 +721,7 @@ static void phy_change(struct work_struc
irq_enable_err:
disable_irq(phydev->irq);
+ atomic_inc(&phydev->irq_disable);
phy_err:
phy_error(phydev);
}
diff -puN include/linux/phy.h~phylib-irq-event-workqueue-handling-fixes include/linux/phy.h
--- a/include/linux/phy.h~phylib-irq-event-workqueue-handling-fixes
+++ a/include/linux/phy.h
@@ -25,6 +25,8 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
#define PHY_BASIC_FEATURES (SUPPORTED_10baseT_Half | \
SUPPORTED_10baseT_Full | \
SUPPORTED_100baseT_Half | \
@@ -281,6 +283,7 @@ struct phy_device {
/* Interrupt and Polling infrastructure */
struct work_struct phy_queue;
struct timer_list phy_timer;
+ atomic_t irq_disable;
spinlock_t lock;
_
^ permalink raw reply
* Re: tcp bw in 2.6
From: Wayne Scott @ 2007-10-02 20:42 UTC (permalink / raw)
To: lm; +Cc: jheffner, herbert, torvalds, davem, netdev
In-Reply-To: <20071002201420.GE29944@bitmover.com>
[-- Attachment #1: Type: Text/Plain, Size: 999 bytes --]
From: lm@bitmover.com (Larry McVoy)
> Wayne, Linus asked for tcp dumps from just one side, with the first 100
> packets and then wait 10 seconds or so for the window to open up, and then
> a snap shot of the another 100 packets. Do that for both directions
> and send them to the list. Can you do that? I want to get lunch, I'm
> starving.
OK attached are 4 raw tcpdumps of 1000 packets each. One from the
start and one from steady state.
The slow set was done like this:
on ia64: netcat -l -p8888 > /dev/null
on work: netcat ia64 8888 < /dev/zero
the traces were done of work with slow1 started right before the
netcat on work was exectued. And slow2 started after it acheved
steady state at 18MB/s.
The fast set was done like this:
on work: netcat -l -p8888 > /dev/null
on ia64: netcat ia64 8888 < /dev/zero
the traces were done of work with fast1 started right before the
netcat on ia64 was exectued. And fast2 started after it acheved
steady state at 42MB/s.
-Wayne
[-- Attachment #2: tcpdumps.lm.bz2 --]
[-- Type: Application/Octet-Stream, Size: 60715 bytes --]
^ permalink raw reply
* [patch 06/13] Fix a potential NULL pointer dereference in uli526x_interrupt() in drivers/net/tulip/uli526x.c
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, micah.gruber, grundler, kyle
From: Micah Gruber <micah.gruber@gmail.com>
This patch fixes an apparent potential null dereference bug where we
dereference dev before a null check. This patch simply remvoes the
can't-happen test for a null pointer.
Signed-off-by: Micah Gruber <micah.gruber@gmail.com>
Cc: Grant Grundler <grundler@parisc-linux.org>
Acked-by: Jeff Garzik <jeff@garzik.org>
Acked-by: Kyle McMartin <kyle@mcmartin.ca>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/tulip/uli526x.c | 5 -----
1 file changed, 5 deletions(-)
diff -puN drivers/net/tulip/uli526x.c~fix-a-potential-null-pointer-dereference-in-uli526x_interrupt drivers/net/tulip/uli526x.c
--- a/drivers/net/tulip/uli526x.c~fix-a-potential-null-pointer-dereference-in-uli526x_interrupt
+++ a/drivers/net/tulip/uli526x.c
@@ -664,11 +664,6 @@ static irqreturn_t uli526x_interrupt(int
unsigned long ioaddr = dev->base_addr;
unsigned long flags;
- if (!dev) {
- ULI526X_DBUG(1, "uli526x_interrupt() without DEVICE arg", 0);
- return IRQ_NONE;
- }
-
spin_lock_irqsave(&db->lock, flags);
outl(0, ioaddr + DCR7);
_
^ permalink raw reply
* [patch 07/13] PHYLIB: Spinlock fixes for softirqs
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, macro
From: "Maciej W. Rozycki" <macro@linux-mips.org>
Use spin_lock_bh()/spin_unlock_bh() for the phydev lock throughout as it
is used in phy_timer() that is called as a softirq and all the other
operations may happen in the user context.
There has been a change recently that did such a conversion for some of the
operations on the lock, but some have been left intact. Many of them,
perhaps all, may be called in the user context and I was able to trigger
recursive spinlock acquisition indeed, so I think for the sake of long-term
maintenance it is best to convert them all, even if unnecessarily for one
or two -- better safe than sorry.
Perhaps one in phy_timer() could actually be skipped as only called as a
softirq -- I can send an update if that sounds like a good idea.
Checked with checkpatch.pl and at the runtime.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/phy/phy.c | 24 ++++++++++++------------
drivers/net/phy/phy_device.c | 4 ++--
2 files changed, 14 insertions(+), 14 deletions(-)
diff -puN drivers/net/phy/phy.c~phylib-spinlock-fixes-for-softirqs drivers/net/phy/phy.c
--- a/drivers/net/phy/phy.c~phylib-spinlock-fixes-for-softirqs
+++ a/drivers/net/phy/phy.c
@@ -424,7 +424,7 @@ int phy_start_aneg(struct phy_device *ph
{
int err;
- spin_lock(&phydev->lock);
+ spin_lock_bh(&phydev->lock);
if (AUTONEG_DISABLE == phydev->autoneg)
phy_sanitize_settings(phydev);
@@ -445,7 +445,7 @@ int phy_start_aneg(struct phy_device *ph
}
out_unlock:
- spin_unlock(&phydev->lock);
+ spin_unlock_bh(&phydev->lock);
return err;
}
EXPORT_SYMBOL(phy_start_aneg);
@@ -490,10 +490,10 @@ void phy_stop_machine(struct phy_device
{
del_timer_sync(&phydev->phy_timer);
- spin_lock(&phydev->lock);
+ spin_lock_bh(&phydev->lock);
if (phydev->state > PHY_UP)
phydev->state = PHY_UP;
- spin_unlock(&phydev->lock);
+ spin_unlock_bh(&phydev->lock);
phydev->adjust_state = NULL;
}
@@ -537,9 +537,9 @@ static void phy_force_reduction(struct p
*/
void phy_error(struct phy_device *phydev)
{
- spin_lock(&phydev->lock);
+ spin_lock_bh(&phydev->lock);
phydev->state = PHY_HALTED;
- spin_unlock(&phydev->lock);
+ spin_unlock_bh(&phydev->lock);
}
/**
@@ -690,10 +690,10 @@ static void phy_change(struct work_struc
if (err)
goto phy_err;
- spin_lock(&phydev->lock);
+ spin_lock_bh(&phydev->lock);
if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
phydev->state = PHY_CHANGELINK;
- spin_unlock(&phydev->lock);
+ spin_unlock_bh(&phydev->lock);
enable_irq(phydev->irq);
@@ -718,7 +718,7 @@ phy_err:
*/
void phy_stop(struct phy_device *phydev)
{
- spin_lock(&phydev->lock);
+ spin_lock_bh(&phydev->lock);
if (PHY_HALTED == phydev->state)
goto out_unlock;
@@ -734,7 +734,7 @@ void phy_stop(struct phy_device *phydev)
}
out_unlock:
- spin_unlock(&phydev->lock);
+ spin_unlock_bh(&phydev->lock);
/*
* Cannot call flush_scheduled_work() here as desired because
@@ -782,7 +782,7 @@ static void phy_timer(unsigned long data
int needs_aneg = 0;
int err = 0;
- spin_lock(&phydev->lock);
+ spin_lock_bh(&phydev->lock);
if (phydev->adjust_state)
phydev->adjust_state(phydev->attached_dev);
@@ -948,7 +948,7 @@ static void phy_timer(unsigned long data
break;
}
- spin_unlock(&phydev->lock);
+ spin_unlock_bh(&phydev->lock);
if (needs_aneg)
err = phy_start_aneg(phydev);
diff -puN drivers/net/phy/phy_device.c~phylib-spinlock-fixes-for-softirqs drivers/net/phy/phy_device.c
--- a/drivers/net/phy/phy_device.c~phylib-spinlock-fixes-for-softirqs
+++ a/drivers/net/phy/phy_device.c
@@ -670,9 +670,9 @@ static int phy_remove(struct device *dev
phydev = to_phy_device(dev);
- spin_lock(&phydev->lock);
+ spin_lock_bh(&phydev->lock);
phydev->state = PHY_DOWN;
- spin_unlock(&phydev->lock);
+ spin_unlock_bh(&phydev->lock);
if (phydev->drv->remove)
phydev->drv->remove(phydev);
_
^ permalink raw reply
* [patch 02/13] PCI-X/PCI-Express read control interfaces: use them in e1000
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, peter.oruba, auke-jan.h.kok, bunk, shemminger
From: "Peter Oruba" <peter.oruba@amd.com>
These driver changes incorporate the proposed PCI-X / PCI-Express read byte
count interface. Reading and setting those valuse doesn't take place
"manually", instead wrapping functions are called to allow quirks for some
PCI bridges.
[bunk@stusta.de: e1000: #if 0 two functions]
Signed-off by: Peter Oruba <peter.oruba@amd.com>
Based on work by Stephen Hemminger <shemminger@linux-foundation.org>
Acked-by: Auke Kok <auke-jan.h.kok@intel.com>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/e1000/e1000_hw.c | 25 +++----------------------
drivers/net/e1000/e1000_hw.h | 4 ++--
drivers/net/e1000/e1000_main.c | 18 ++++++++++++++++++
3 files changed, 23 insertions(+), 24 deletions(-)
diff -puN drivers/net/e1000/e1000_hw.c~pci-x-pci-express-read-control-interfaces-e1000 drivers/net/e1000/e1000_hw.c
--- a/drivers/net/e1000/e1000_hw.c~pci-x-pci-express-read-control-interfaces-e1000
+++ a/drivers/net/e1000/e1000_hw.c
@@ -871,10 +871,6 @@ e1000_init_hw(struct e1000_hw *hw)
uint32_t ctrl;
uint32_t i;
int32_t ret_val;
- uint16_t pcix_cmd_word;
- uint16_t pcix_stat_hi_word;
- uint16_t cmd_mmrbc;
- uint16_t stat_mmrbc;
uint32_t mta_size;
uint32_t reg_data;
uint32_t ctrl_ext;
@@ -964,24 +960,9 @@ e1000_init_hw(struct e1000_hw *hw)
break;
default:
/* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
- if (hw->bus_type == e1000_bus_type_pcix) {
- e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word);
- e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI,
- &pcix_stat_hi_word);
- cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >>
- PCIX_COMMAND_MMRBC_SHIFT;
- stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
- PCIX_STATUS_HI_MMRBC_SHIFT;
- if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
- stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
- if (cmd_mmrbc > stat_mmrbc) {
- pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK;
- pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
- e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER,
- &pcix_cmd_word);
- }
- }
- break;
+ if (hw->bus_type == e1000_bus_type_pcix && e1000_pcix_get_mmrbc(hw) > 2048)
+ e1000_pcix_set_mmrbc(hw, 2048);
+ break;
}
/* More time needed for PHY to initialize */
diff -puN drivers/net/e1000/e1000_hw.h~pci-x-pci-express-read-control-interfaces-e1000 drivers/net/e1000/e1000_hw.h
--- a/drivers/net/e1000/e1000_hw.h~pci-x-pci-express-read-control-interfaces-e1000
+++ a/drivers/net/e1000/e1000_hw.h
@@ -421,9 +421,9 @@ void e1000_tbi_adjust_stats(struct e1000
void e1000_get_bus_info(struct e1000_hw *hw);
void e1000_pci_set_mwi(struct e1000_hw *hw);
void e1000_pci_clear_mwi(struct e1000_hw *hw);
-void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
-void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
int32_t e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value);
+void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc);
+int e1000_pcix_get_mmrbc(struct e1000_hw *hw);
/* Port I/O is only supported on 82544 and newer */
void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
diff -puN drivers/net/e1000/e1000_main.c~pci-x-pci-express-read-control-interfaces-e1000 drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c~pci-x-pci-express-read-control-interfaces-e1000
+++ a/drivers/net/e1000/e1000_main.c
@@ -4887,6 +4887,8 @@ e1000_pci_clear_mwi(struct e1000_hw *hw)
pci_clear_mwi(adapter->pdev);
}
+#if 0
+
void
e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
{
@@ -4903,6 +4905,22 @@ e1000_write_pci_cfg(struct e1000_hw *hw,
pci_write_config_word(adapter->pdev, reg, *value);
}
+#endif /* 0 */
+
+int
+e1000_pcix_get_mmrbc(struct e1000_hw *hw)
+{
+ struct e1000_adapter *adapter = hw->back;
+ return pcix_get_mmrbc(adapter->pdev);
+}
+
+void
+e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
+{
+ struct e1000_adapter *adapter = hw->back;
+ pcix_set_mmrbc(adapter->pdev, mmrbc);
+}
+
int32_t
e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
{
_
^ permalink raw reply
* [patch 03/13] drivers/net/cxgb3/xgmac.c: remove dead code
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, bunk
From: Adrian Bunk <bunk@stusta.de>
This patch removes dead code ("tx_xcnt" can never be != 0 at this place)
spotted by the Coverity checker.
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/cxgb3/xgmac.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff -puN drivers/net/cxgb3/xgmac.c~drivers-net-cxgb3-xgmacc-remove-dead-code drivers/net/cxgb3/xgmac.c
--- a/drivers/net/cxgb3/xgmac.c~drivers-net-cxgb3-xgmacc-remove-dead-code
+++ a/drivers/net/cxgb3/xgmac.c
@@ -522,10 +522,7 @@ int t3b2_mac_watchdog_task(struct cmac *
goto rxcheck;
}
- if (((tx_tcnt != mac->tx_tcnt) &&
- (tx_xcnt == 0) && (mac->tx_xcnt == 0)) ||
- ((mac->tx_mcnt == tx_mcnt) &&
- (tx_xcnt != 0) && (mac->tx_xcnt != 0))) {
+ if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) {
if (mac->toggle_cnt > 4) {
status = 2;
goto out;
_
^ permalink raw reply
* [patch 09/13] forcedeth: "no link" is informational
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, eswierk, aabdulla
From: "Ed Swierk" <eswierk@arastra.com>
Log "no link during initialization" at KERN_INFO as it's not an error, and
occurs every time the interface comes up (when the forcedeth-phy-power-down
patch is applied).
Signed-off-by: Ed Swierk <eswierk@arastra.com>
Cc: Ayaz Abdulla <aabdulla@nvidia.com>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/forcedeth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff -puN drivers/net/forcedeth.c~forcedeth-no-link-is-informational drivers/net/forcedeth.c
--- a/drivers/net/forcedeth.c~forcedeth-no-link-is-informational
+++ a/drivers/net/forcedeth.c
@@ -4921,7 +4921,7 @@ static int nv_open(struct net_device *de
if (ret) {
netif_carrier_on(dev);
} else {
- printk("%s: no link during initialization.\n", dev->name);
+ printk(KERN_INFO "%s: no link during initialization.\n", dev->name);
netif_carrier_off(dev);
}
if (oom)
_
^ permalink raw reply
* [patch 08/13] forcedeth: power down phy when interface is down
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, eswierk, aabdulla
From: "Ed Swierk" <eswierk@arastra.com>
Bring the physical link down when the interface is down, by placing the PHY in
power-down state. This mirrors the behavior of other drivers including e1000
and tg3.
Signed-off-by: Ed Swierk <eswierk@arastra.com>
Cc: Ayaz Abdulla <aabdulla@nvidia.com>
Cc: Jeff Garzik <jeff@garzik.org>
On Sat, 29 Sep 2007 01:57:04 -0400 Jeff Garzik <jeff@garzik.org> wrote:
> akpm@linux-foundation.org wrote:
> > From: "Ed Swierk" <eswierk@arastra.com>
> >
> > Bring the physical link down when the interface is down, by placing the PHY in
> > power-down state. This mirrors the behavior of other drivers including e1000
> > and tg3.
> >
> > Signed-off-by: Ed Swierk <eswierk@arastra.com>
> > Cc: Ayaz Abdulla <aabdulla@nvidia.com>
> > Cc: Jeff Garzik <jeff@garzik.org>
> > Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
>
>
> HOLD -- waiting a bit for comment from others, particularly NVIDIA.
>
> I'm not opposed to applying it, the patch looks correct, but I would
> also like see testing results and general "it's ok for this hardware"
> comments.
>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/forcedeth.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff -puN drivers/net/forcedeth.c~forcedeth-power-down-phy-when-interface-is-down drivers/net/forcedeth.c
--- a/drivers/net/forcedeth.c~forcedeth-power-down-phy-when-interface-is-down
+++ a/drivers/net/forcedeth.c
@@ -1313,9 +1313,9 @@ static int phy_init(struct net_device *d
/* some phys clear out pause advertisment on reset, set it back */
mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
- /* restart auto negotiation */
+ /* restart auto negotiation, power down phy */
mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
- mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
+ mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE | BMCR_PDOWN);
if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
return PHY_ERROR;
}
@@ -4791,6 +4791,10 @@ static int nv_open(struct net_device *de
dprintk(KERN_DEBUG "nv_open: begin\n");
+ /* power up phy */
+ mii_rw(dev, np->phyaddr, MII_BMCR,
+ mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN);
+
/* erase previous misconfiguration */
if (np->driver_data & DEV_HAS_POWER_CNTRL)
nv_mac_reset(dev);
@@ -4975,6 +4979,10 @@ static int nv_close(struct net_device *d
nv_start_rx(dev);
}
+ /* power down phy */
+ mii_rw(dev, np->phyaddr, MII_BMCR,
+ mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) | BMCR_PDOWN);
+
/* FIXME: power down nic */
return 0;
_
^ permalink raw reply
* [patch 05/13] skge: remove broken and unused PHY_M_PC_MDI_XMODE macro
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, m.kozlowski, shemminger
From: Mariusz Kozlowski <m.kozlowski@tuxland.pl>
Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl>
Cc: Stephen Hemminger <shemminger@linux-foundation.org>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/skge.h | 2 --
1 file changed, 2 deletions(-)
diff -puN drivers/net/skge.h~skge-remove-broken-and-unused-phy_m_pc_mdi_xmode-macro drivers/net/skge.h
--- a/drivers/net/skge.h~skge-remove-broken-and-unused-phy_m_pc_mdi_xmode-macro
+++ a/drivers/net/skge.h
@@ -1351,8 +1351,6 @@ enum {
PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */
};
-#define PHY_M_PC_MDI_XMODE(x) ((((u16)(x)<<5) & PHY_M_PC_MDIX_MSK)
-
enum {
PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */
PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */
_
^ permalink raw reply
* [patch 01/13] PHY fixed driver: rework release path and update phy_id notation
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, vitb
From: Vitaly Bordug <vitb@kernel.crashing.org>
device_bind_driver() error code returning has been fixed. release()
function has been written, so that to free resources in correct way; the
release path is now clean.
Before the rework, it used to cause
Device 'fixed@100:1' does not have a release() function, it is broken
and must be fixed.
BUG: at drivers/base/core.c:104 device_release()
Call Trace:
[<ffffffff802ec380>] kobject_cleanup+0x53/0x7e
[<ffffffff802ec3ab>] kobject_release+0x0/0x9
[<ffffffff802ecf3f>] kref_put+0x74/0x81
[<ffffffff8035493b>] fixed_mdio_register_device+0x230/0x265
[<ffffffff80564d31>] fixed_init+0x1f/0x35
[<ffffffff802071a4>] init+0x147/0x2fb
[<ffffffff80223b6e>] schedule_tail+0x36/0x92
[<ffffffff8020a678>] child_rip+0xa/0x12
[<ffffffff80311714>] acpi_ds_init_one_object+0x0/0x83
[<ffffffff8020705d>] init+0x0/0x2fb
[<ffffffff8020a66e>] child_rip+0x0/0x12
Also changed the notation of the fixed phy definition on
mdio bus to the form of <speed>+<duplex> to make it able to be used by
gianfar and ucc_geth that define phy_id strictly as "%d:%d" and cleaned up
the whitespace issues.
Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/phy/Kconfig | 14 +
drivers/net/phy/fixed.c | 310 ++++++++++++++++++------------------
include/linux/phy_fixed.h | 38 ++++
3 files changed, 207 insertions(+), 155 deletions(-)
diff -puN drivers/net/phy/Kconfig~phy-fixed-driver-rework-release-path-and-update drivers/net/phy/Kconfig
--- a/drivers/net/phy/Kconfig~phy-fixed-driver-rework-release-path-and-update
+++ a/drivers/net/phy/Kconfig
@@ -76,4 +76,18 @@ config FIXED_MII_100_FDX
bool "Emulation for 100M Fdx fixed PHY behavior"
depends on FIXED_PHY
+config FIXED_MII_1000_FDX
+ bool "Emulation for 1000M Fdx fixed PHY behavior"
+ depends on FIXED_PHY
+
+config FIXED_MII_AMNT
+ int "Number of emulated PHYs to allocate "
+ depends on FIXED_PHY
+ default "1"
+ ---help---
+ Sometimes it is required to have several independent emulated
+ PHYs on the bus (in case of multi-eth but phy-less HW for instance).
+ This control will have specified number allocated for each fixed
+ PHY type enabled.
+
endif # PHYLIB
diff -puN drivers/net/phy/fixed.c~phy-fixed-driver-rework-release-path-and-update drivers/net/phy/fixed.c
--- a/drivers/net/phy/fixed.c~phy-fixed-driver-rework-release-path-and-update
+++ a/drivers/net/phy/fixed.c
@@ -30,53 +30,31 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/phy_fixed.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
-#define MII_REGS_NUM 7
-
-/*
- The idea is to emulate normal phy behavior by responding with
- pre-defined values to mii BMCR read, so that read_status hook could
- take all the needed info.
-*/
-
-struct fixed_phy_status {
- u8 link;
- u16 speed;
- u8 duplex;
-};
-
-/*-----------------------------------------------------------------------------
- * Private information hoder for mii_bus
- *-----------------------------------------------------------------------------*/
-struct fixed_info {
- u16 *regs;
- u8 regs_num;
- struct fixed_phy_status phy_status;
- struct phy_device *phydev; /* pointer to the container */
- /* link & speed cb */
- int(*link_update)(struct net_device*, struct fixed_phy_status*);
-
-};
+/* we need to track the allocated pointers in order to free them on exit */
+static struct fixed_info *fixed_phy_ptrs[CONFIG_FIXED_MII_AMNT*MAX_PHY_AMNT];
/*-----------------------------------------------------------------------------
* If something weird is required to be done with link/speed,
* network driver is able to assign a function to implement this.
* May be useful for PHY's that need to be software-driven.
*-----------------------------------------------------------------------------*/
-int fixed_mdio_set_link_update(struct phy_device* phydev,
- int(*link_update)(struct net_device*, struct fixed_phy_status*))
+int fixed_mdio_set_link_update(struct phy_device *phydev,
+ int (*link_update) (struct net_device *,
+ struct fixed_phy_status *))
{
struct fixed_info *fixed;
- if(link_update == NULL)
+ if (link_update == NULL)
return -EINVAL;
- if(phydev) {
- if(phydev->bus) {
+ if (phydev) {
+ if (phydev->bus) {
fixed = phydev->bus->priv;
fixed->link_update = link_update;
return 0;
@@ -84,54 +62,64 @@ int fixed_mdio_set_link_update(struct ph
}
return -EINVAL;
}
+
EXPORT_SYMBOL(fixed_mdio_set_link_update);
+struct fixed_info *fixed_mdio_get_phydev (int phydev_ind)
+{
+ if (phydev_ind >= MAX_PHY_AMNT)
+ return NULL;
+ return fixed_phy_ptrs[phydev_ind];
+}
+
+EXPORT_SYMBOL(fixed_mdio_get_phydev);
+
/*-----------------------------------------------------------------------------
* This is used for updating internal mii regs from the status
*-----------------------------------------------------------------------------*/
-#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX)
+#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
static int fixed_mdio_update_regs(struct fixed_info *fixed)
{
u16 *regs = fixed->regs;
u16 bmsr = 0;
u16 bmcr = 0;
- if(!regs) {
+ if (!regs) {
printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
return -EINVAL;
}
- if(fixed->phy_status.link)
+ if (fixed->phy_status.link)
bmsr |= BMSR_LSTATUS;
- if(fixed->phy_status.duplex) {
+ if (fixed->phy_status.duplex) {
bmcr |= BMCR_FULLDPLX;
- switch ( fixed->phy_status.speed ) {
+ switch (fixed->phy_status.speed) {
case 100:
bmsr |= BMSR_100FULL;
bmcr |= BMCR_SPEED100;
- break;
+ break;
case 10:
bmsr |= BMSR_10FULL;
- break;
+ break;
}
} else {
- switch ( fixed->phy_status.speed ) {
+ switch (fixed->phy_status.speed) {
case 100:
bmsr |= BMSR_100HALF;
bmcr |= BMCR_SPEED100;
- break;
+ break;
case 10:
bmsr |= BMSR_100HALF;
- break;
+ break;
}
}
- regs[MII_BMCR] = bmcr;
- regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx*/
+ regs[MII_BMCR] = bmcr;
+ regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx */
return 0;
}
@@ -141,29 +129,30 @@ static int fixed_mii_read(struct mii_bus
struct fixed_info *fixed = bus->priv;
/* if user has registered link update callback, use it */
- if(fixed->phydev)
- if(fixed->phydev->attached_dev) {
- if(fixed->link_update) {
+ if (fixed->phydev)
+ if (fixed->phydev->attached_dev) {
+ if (fixed->link_update) {
fixed->link_update(fixed->phydev->attached_dev,
- &fixed->phy_status);
+ &fixed->phy_status);
fixed_mdio_update_regs(fixed);
}
- }
+ }
if ((unsigned int)location >= fixed->regs_num)
return -1;
return fixed->regs[location];
}
-static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location,
+ u16 val)
{
- /* do nothing for now*/
+ /* do nothing for now */
return 0;
}
static int fixed_mii_reset(struct mii_bus *bus)
{
- /*nothing here - no way/need to reset it*/
+ /*nothing here - no way/need to reset it */
return 0;
}
#endif
@@ -171,8 +160,8 @@ static int fixed_mii_reset(struct mii_bu
static int fixed_config_aneg(struct phy_device *phydev)
{
/* :TODO:03/13/2006 09:45:37 PM::
- The full autoneg funcionality can be emulated,
- but no need to have anything here for now
+ The full autoneg funcionality can be emulated,
+ but no need to have anything here for now
*/
return 0;
}
@@ -182,59 +171,79 @@ static int fixed_config_aneg(struct phy_
* match will never return true...
*-----------------------------------------------------------------------------*/
static struct phy_driver fixed_mdio_driver = {
- .name = "Fixed PHY",
- .features = PHY_BASIC_FEATURES,
- .config_aneg = fixed_config_aneg,
- .read_status = genphy_read_status,
- .driver = { .owner = THIS_MODULE,},
+ .name = "Fixed PHY",
+#ifdef CONFIG_FIXED_MII_1000_FDX
+ .features = PHY_GBIT_FEATURES,
+#else
+ .features = PHY_BASIC_FEATURES,
+#endif
+ .config_aneg = fixed_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = { .owner = THIS_MODULE, },
};
+static void fixed_mdio_release(struct device *dev)
+{
+ struct phy_device *phydev = container_of(dev, struct phy_device, dev);
+ struct mii_bus *bus = phydev->bus;
+ struct fixed_info *fixed = bus->priv;
+
+ kfree(phydev);
+ kfree(bus->dev);
+ kfree(bus);
+ kfree(fixed->regs);
+ kfree(fixed);
+}
+
/*-----------------------------------------------------------------------------
* This func is used to create all the necessary stuff, bind
* the fixed phy driver and register all it on the mdio_bus_type.
- * speed is either 10 or 100, duplex is boolean.
+ * speed is either 10 or 100 or 1000, duplex is boolean.
* number is used to create multiple fixed PHYs, so that several devices can
* utilize them simultaneously.
+ *
+ * The device on mdio bus will look like [bus_id]:[phy_id],
+ * bus_id = number
+ * phy_id = speed+duplex.
*-----------------------------------------------------------------------------*/
-#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX)
-static int fixed_mdio_register_device(int number, int speed, int duplex)
+#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
+struct fixed_info *fixed_mdio_register_device(
+ int bus_id, int speed, int duplex, u8 phy_id)
{
struct mii_bus *new_bus;
struct fixed_info *fixed;
struct phy_device *phydev;
- int err = 0;
+ int err;
- struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+ struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
- if (NULL == dev)
- return -ENOMEM;
+ if (dev == NULL)
+ goto err_dev_alloc;
new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
- if (NULL == new_bus) {
- kfree(dev);
- return -ENOMEM;
- }
+ if (new_bus == NULL)
+ goto err_bus_alloc;
+
fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
- if (NULL == fixed) {
- kfree(dev);
- kfree(new_bus);
- return -ENOMEM;
- }
+ if (fixed == NULL)
+ goto err_fixed_alloc;
+
+ fixed->regs = kzalloc(MII_REGS_NUM * sizeof(int), GFP_KERNEL);
+ if (NULL == fixed->regs)
+ goto err_fixed_regs_alloc;
- fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
fixed->regs_num = MII_REGS_NUM;
fixed->phy_status.speed = speed;
fixed->phy_status.duplex = duplex;
fixed->phy_status.link = 1;
- new_bus->name = "Fixed MII Bus",
- new_bus->read = &fixed_mii_read,
- new_bus->write = &fixed_mii_write,
- new_bus->reset = &fixed_mii_reset,
-
- /*set up workspace*/
+ new_bus->name = "Fixed MII Bus";
+ new_bus->read = &fixed_mii_read;
+ new_bus->write = &fixed_mii_write;
+ new_bus->reset = &fixed_mii_reset;
+ /*set up workspace */
fixed_mdio_update_regs(fixed);
new_bus->priv = fixed;
@@ -243,119 +252,110 @@ static int fixed_mdio_register_device(in
/* create phy_device and register it on the mdio bus */
phydev = phy_device_create(new_bus, 0, 0);
+ if (phydev == NULL)
+ goto err_phy_dev_create;
/*
- Put the phydev pointer into the fixed pack so that bus read/write code could
- be able to access for instance attached netdev. Well it doesn't have to do
- so, only in case of utilizing user-specified link-update...
+ * Put the phydev pointer into the fixed pack so that bus read/write
+ * code could be able to access for instance attached netdev. Well it
+ * doesn't have to do so, only in case of utilizing user-specified
+ * link-update...
*/
- fixed->phydev = phydev;
- if(NULL == phydev) {
- err = -ENOMEM;
- goto device_create_fail;
- }
+ fixed->phydev = phydev;
+ phydev->speed = speed;
+ phydev->duplex = duplex;
phydev->irq = PHY_IGNORE_INTERRUPT;
phydev->dev.bus = &mdio_bus_type;
- if(number)
- snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
- "fixed_%d@%d:%d", number, speed, duplex);
- else
- snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
- "fixed@%d:%d", speed, duplex);
- phydev->bus = new_bus;
+ snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+ PHY_ID_FMT, bus_id, phy_id);
- err = device_register(&phydev->dev);
- if(err) {
- printk(KERN_ERR "Phy %s failed to register\n",
- phydev->dev.bus_id);
- goto bus_register_fail;
- }
+ phydev->bus = new_bus;
- /*
- the mdio bus has phy_id match... In order not to do it
- artificially, we are binding the driver here by hand;
- it will be the same for all the fixed phys anyway.
- */
phydev->dev.driver = &fixed_mdio_driver.driver;
-
+ phydev->dev.release = fixed_mdio_release;
err = phydev->dev.driver->probe(&phydev->dev);
- if(err < 0) {
- printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
- goto probe_fail;
+ if (err < 0) {
+ printk(KERN_ERR "Phy %s: problems with fixed driver\n",
+ phydev->dev.bus_id);
+ goto err_out;
}
+ err = device_register(&phydev->dev);
+ if (err) {
+ printk(KERN_ERR "Phy %s failed to register\n",
+ phydev->dev.bus_id);
+ goto err_out;
+ }
+ //phydev->state = PHY_RUNNING; /* make phy go up quick, but in 10Mbit/HDX
+ return fixed;
- err = device_bind_driver(&phydev->dev);
- if (err)
- goto probe_fail;
-
- return 0;
-
-probe_fail:
- device_unregister(&phydev->dev);
-bus_register_fail:
+err_out:
kfree(phydev);
-device_create_fail:
- kfree(dev);
- kfree(new_bus);
+err_phy_dev_create:
+ kfree(fixed->regs);
+err_fixed_regs_alloc:
kfree(fixed);
+err_fixed_alloc:
+ kfree(new_bus);
+err_bus_alloc:
+ kfree(dev);
+err_dev_alloc:
+
+ return NULL;
- return err;
}
#endif
-
MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
MODULE_AUTHOR("Vitaly Bordug");
MODULE_LICENSE("GPL");
static int __init fixed_init(void)
{
-#if 0
- int ret;
- int duplex = 0;
-#endif
-
- /* register on the bus... Not expected to be matched with anything there... */
+ int cnt = 0;
+ int i;
+/* register on the bus... Not expected to be matched
+ * with anything there...
+ *
+ */
phy_driver_register(&fixed_mdio_driver);
- /* So let the fun begin...
- We will create several mdio devices here, and will bound the upper
- driver to them.
-
- Then the external software can lookup the phy bus by searching
- fixed@speed:duplex, e.g. fixed@100:1, to be connected to the
- virtual 100M Fdx phy.
-
- In case several virtual PHYs required, the bus_id will be in form
- fixed_<num>@<speed>:<duplex>, which make it able even to define
- driver-specific link control callback, if for instance PHY is completely
- SW-driven.
-
- */
-
-#ifdef CONFIG_FIXED_MII_DUPLEX
-#if 0
- duplex = 1;
-#endif
+/* We will create several mdio devices here, and will bound the upper
+ * driver to them.
+ *
+ * Then the external software can lookup the phy bus by searching
+ * for 0:101, to be connected to the virtual 100M Fdx phy.
+ *
+ * In case several virtual PHYs required, the bus_id will be in form
+ * [num]:[duplex]+[speed], which make it able even to define
+ * driver-specific link control callback, if for instance PHY is
+ * completely SW-driven.
+ */
+ for (i=1; i <= CONFIG_FIXED_MII_AMNT; i++) {
+#ifdef CONFIG_FIXED_MII_1000_FDX
+ fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(0, 1000, 1, i);
#endif
-
#ifdef CONFIG_FIXED_MII_100_FDX
- fixed_mdio_register_device(0, 100, 1);
+ fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(1, 100, 1, i);
#endif
-
#ifdef CONFIG_FIXED_MII_10_FDX
- fixed_mdio_register_device(0, 10, 1);
+ fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(2, 10, 1, i);
#endif
+ }
+
return 0;
}
static void __exit fixed_exit(void)
{
+ int i;
+
phy_driver_unregister(&fixed_mdio_driver);
- /* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */
+ for (i=0; i < MAX_PHY_AMNT; i++)
+ if ( fixed_phy_ptrs[i] )
+ device_unregister(&fixed_phy_ptrs[i]->phydev->dev);
}
module_init(fixed_init);
diff -puN /dev/null include/linux/phy_fixed.h
--- /dev/null
+++ a/include/linux/phy_fixed.h
@@ -0,0 +1,38 @@
+#ifndef __PHY_FIXED_H
+#define __PHY_FIXED_H
+
+#define MII_REGS_NUM 29
+
+/* max number of virtual phy stuff */
+#define MAX_PHY_AMNT 10
+/*
+ The idea is to emulate normal phy behavior by responding with
+ pre-defined values to mii BMCR read, so that read_status hook could
+ take all the needed info.
+*/
+
+struct fixed_phy_status {
+ u8 link;
+ u16 speed;
+ u8 duplex;
+};
+
+/*-----------------------------------------------------------------------------
+ * Private information hoder for mii_bus
+ *-----------------------------------------------------------------------------*/
+struct fixed_info {
+ u16 *regs;
+ u8 regs_num;
+ struct fixed_phy_status phy_status;
+ struct phy_device *phydev; /* pointer to the container */
+ /* link & speed cb */
+ int (*link_update) (struct net_device *, struct fixed_phy_status *);
+
+};
+
+
+int fixed_mdio_set_link_update(struct phy_device *,
+ int (*link_update) (struct net_device *, struct fixed_phy_status *));
+struct fixed_info *fixed_mdio_get_phydev (int phydev_ind);
+
+#endif /* __PHY_FIXED_H */
_
^ permalink raw reply
* [patch 04/13] Avoid possible NULL pointer deref in 3c359 driver
From: akpm @ 2007-10-02 21:11 UTC (permalink / raw)
To: jeff; +Cc: netdev, akpm, jesper.juhl
From: Jesper Juhl <jesper.juhl@gmail.com>
In xl_freemem(), if dev_if is NULL, the line
struct xl_private *xl_priv =(struct xl_private *)dev->priv;
will cause a NULL pointer dereference.
(akpm: don't try to fix it: just delete the pointless test-for-null)
Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/tokenring/3c359.c | 5 -----
1 file changed, 5 deletions(-)
diff -puN drivers/net/tokenring/3c359.c~avoid-possible-null-pointer-deref-in-3c359-driver drivers/net/tokenring/3c359.c
--- a/drivers/net/tokenring/3c359.c~avoid-possible-null-pointer-deref-in-3c359-driver
+++ a/drivers/net/tokenring/3c359.c
@@ -1045,11 +1045,6 @@ static irqreturn_t xl_interrupt(int irq,
u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
u16 intstatus, macstatus ;
- if (!dev) {
- printk(KERN_WARNING "Device structure dead, aaahhhh !\n") ;
- return IRQ_NONE;
- }
-
intstatus = readw(xl_mmio + MMIO_INTSTATUS) ;
if (!(intstatus & 1)) /* We didn't generate the interrupt */
_
^ permalink raw reply
* Re: [IPv6] Fix ICMPv6 redirect handling with target multicast address
From: Brian Haley @ 2007-10-02 21:06 UTC (permalink / raw)
To: David Stevens
Cc: David Miller, netdev@vger.kernel.org, netdev-owner,
YOSHIFUJI Hideaki
In-Reply-To: <OF939F3A2D.96830882-ON88257368.007068EA-88257368.007161DC@us.ibm.com>
Hi David,
David Stevens wrote:
> ipv6_addr_type() returns a mask, so checking for equality will
> fail to
> match if any other (irrelevant) attributes are set. How about using
> bitwise
> operators for that?
ipv6_addr_type() does return a mask, but there's a lot of code that just
checks for equality since some things are mutually-exclusive - this code
is actually identical to what ip6_route_add() does. I don't
particularly like this duality, but it's there - I'd gladly volunteer to
clean this up everywhere if I didn't think there might be some
performance reason it was done like that.
> Also, the error message is no longer descriptive of the
> failure if it's a link-local multicast, but you could make it "target
> address is not
> link-local unicast.\n" (in both places).
I can do that, thanks.
-Brian
^ permalink raw reply
* [patch 2/3] ipg.c doesn't compile with with CONFIG_HIGHMEM64G
From: akpm @ 2007-10-02 21:04 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, tremyfr, jeff, jesse, sorbica
From: trem <tremyfr@yahoo.fr>
I've tried to compile 2.6.23-rc8-mm2, but it fails on ipg.c with the
error : ERROR: "__udivdi3" [drivers/net/ipg.ko] undefined!
I've instigated a bit, and I've found this code in ipg.c :
static void ipg_nic_txfree(struct net_device *dev)
{
struct ipg_nic_private *sp = netdev_priv(dev);
void __iomem *ioaddr = sp->ioaddr;
const unsigned int curr = ipg_r32(TFD_LIST_PTR_0) -
(sp->txd_map / sizeof(struct ipg_tx)) - 1;
unsigned int released, pending;
sp->txd_map is an u64
because :
dma_addr_t txd_map;
And in asm-i386/types.h, I see :
#ifdef CONFIG_HIGHMEM64G
typedef u64 dma_addr_t;
#else
typedef u32 dma_addr_t;
#endif
I my config, I use CONFIG_HIGHMEM64G
sizeof(struct ipg_tx) is an u32
So the div failed on i386 because of u64 / u32.
[akpm@linux-foundation.org: cleanups]
Cc: Sorbica Shieh <sorbica@icplus.com.tw>
Cc: Jesse Huang <jesse@icplus.com.tw>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/ipg.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff -puN drivers/net/ipg.c~ipgc-doesnt-compile-with-with-config_highmem64g drivers/net/ipg.c
--- a/drivers/net/ipg.c~ipgc-doesnt-compile-with-with-config_highmem64g
+++ a/drivers/net/ipg.c
@@ -25,6 +25,8 @@
#include <linux/mii.h>
#include <linux/mutex.h>
+#include <asm/div64.h>
+
#define IPG_RX_RING_BYTES (sizeof(struct ipg_rx) * IPG_RFDLIST_LENGTH)
#define IPG_TX_RING_BYTES (sizeof(struct ipg_tx) * IPG_TFDLIST_LENGTH)
#define IPG_RESET_MASK \
@@ -836,10 +838,14 @@ static void ipg_nic_txfree(struct net_de
{
struct ipg_nic_private *sp = netdev_priv(dev);
void __iomem *ioaddr = sp->ioaddr;
- const unsigned int curr = ipg_r32(TFD_LIST_PTR_0) -
- (sp->txd_map / sizeof(struct ipg_tx)) - 1;
+ unsigned int curr;
+ u64 txd_map;
unsigned int released, pending;
+ txd_map = (u64)sp->txd_map;
+ curr = ipg_r32(TFD_LIST_PTR_0) -
+ do_div(txd_map, sizeof(struct ipg_tx)) - 1;
+
IPG_DEBUG_MSG("_nic_txfree\n");
pending = sp->tx_current - sp->tx_dirty;
_
^ permalink raw reply
* [patch 3/3] git-net: sctp build fix (not for applying)
From: akpm @ 2007-10-02 21:04 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm
From: Andrew Morton <akpm@linux-foundation.org>
net/sctp/sm_statetable.c:551: error: 'sctp_sf_tabort_8_4_8' undeclared here (not in a function)
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
net/sctp/sm_statetable.c | 2 --
1 file changed, 2 deletions(-)
diff -puN net/sctp/sm_statetable.c~git-net-sctp-hack net/sctp/sm_statetable.c
--- a/net/sctp/sm_statetable.c~git-net-sctp-hack
+++ a/net/sctp/sm_statetable.c
@@ -527,8 +527,6 @@ static const sctp_sm_table_entry_t prsct
/* SCTP_STATE_EMPTY */ \
TYPE_SCTP_FUNC(sctp_sf_ootb), \
/* SCTP_STATE_CLOSED */ \
- TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
- /* SCTP_STATE_COOKIE_WAIT */ \
TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
/* SCTP_STATE_COOKIE_ECHOED */ \
TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
_
^ permalink raw reply
* [patch 1/3] git-net: make it compile (not for applying?)
From: akpm @ 2007-10-02 21:04 UTC (permalink / raw)
To: davem; +Cc: netdev, akpm, shemminger
From: Andrew Morton <akpm@linux-foundation.org>
drivers/net/hamradio/baycom_epp.c: In function 'baycom_probe':
drivers/net/hamradio/baycom_epp.c:1162: error: 'struct net_device' has no member named 'hard_header'
drivers/net/hamradio/baycom_epp.c:1163: error: 'struct net_device' has no member named 'rebuild_header'
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
drivers/net/hamradio/baycom_epp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff -puN drivers/net/hamradio/baycom_epp.c~git-net-more-bustage drivers/net/hamradio/baycom_epp.c
--- a/drivers/net/hamradio/baycom_epp.c~git-net-more-bustage
+++ a/drivers/net/hamradio/baycom_epp.c
@@ -1159,8 +1159,8 @@ static void baycom_probe(struct net_devi
/* Fill in the fields of the device structure */
bc->skb = NULL;
- dev->hard_header = ax25_hard_header;
- dev->rebuild_header = ax25_rebuild_header;
+// dev->hard_header = ax25_hard_header;
+// dev->rebuild_header = ax25_rebuild_header;
dev->set_mac_address = baycom_set_mac_address;
dev->type = ARPHRD_AX25; /* AF_AX25 device */
_
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox