* [patch 06/35] pasemi_mac: Abstract out register access
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
Abstract out the PCI config read/write accesses into reg read/write ones, still
calling the pci accessors on the back end.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: netdev-2.6/drivers/net/pasemi_mac.c
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.c
+++ netdev-2.6/drivers/net/pasemi_mac.c
@@ -81,6 +81,48 @@ MODULE_PARM_DESC(debug, "PA Semi MAC bit
static struct pasdma_status *dma_status;
+static unsigned int read_iob_reg(struct pasemi_mac *mac, unsigned int reg)
+{
+ unsigned int val;
+
+ pci_read_config_dword(mac->iob_pdev, reg, &val);
+ return val;
+}
+
+static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
+ unsigned int val)
+{
+ pci_write_config_dword(mac->iob_pdev, reg, val);
+}
+
+static unsigned int read_mac_reg(struct pasemi_mac *mac, unsigned int reg)
+{
+ unsigned int val;
+
+ pci_read_config_dword(mac->pdev, reg, &val);
+ return val;
+}
+
+static void write_mac_reg(struct pasemi_mac *mac, unsigned int reg,
+ unsigned int val)
+{
+ pci_write_config_dword(mac->pdev, reg, val);
+}
+
+static unsigned int read_dma_reg(struct pasemi_mac *mac, unsigned int reg)
+{
+ unsigned int val;
+
+ pci_read_config_dword(mac->dma_pdev, reg, &val);
+ return val;
+}
+
+static void write_dma_reg(struct pasemi_mac *mac, unsigned int reg,
+ unsigned int val)
+{
+ pci_write_config_dword(mac->dma_pdev, reg, val);
+}
+
static int pasemi_get_mac_addr(struct pasemi_mac *mac)
{
struct pci_dev *pdev = mac->pdev;
@@ -166,22 +208,21 @@ static int pasemi_mac_setup_rx_resources
memset(ring->buffers, 0, RX_RING_SIZE * sizeof(u64));
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXCHAN_BASEL(chan_id),
- PAS_DMA_RXCHAN_BASEL_BRBL(ring->dma));
+ write_dma_reg(mac, PAS_DMA_RXCHAN_BASEL(chan_id), PAS_DMA_RXCHAN_BASEL_BRBL(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 >> 2));
+
+ write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id),
+ PAS_DMA_RXCHAN_CFG_HBU(1));
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXCHAN_BASEU(chan_id),
- PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) |
- PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 2));
-
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXCHAN_CFG(chan_id),
- PAS_DMA_RXCHAN_CFG_HBU(1));
-
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXINT_BASEL(mac->dma_if),
- PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers)));
-
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_RXINT_BASEU(mac->dma_if),
- PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) |
- PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
+ write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if),
+ PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers)));
+
+ write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if),
+ PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) |
+ PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
ring->next_to_fill = 0;
ring->next_to_clean = 0;
@@ -233,18 +274,18 @@ static int pasemi_mac_setup_tx_resources
memset(ring->desc, 0, TX_RING_SIZE * sizeof(struct pas_dma_xct_descr));
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_TXCHAN_BASEL(chan_id),
- PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
+ 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);
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_TXCHAN_BASEU(chan_id), val);
+ write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_TXCHAN_CFG(chan_id),
- PAS_DMA_TXCHAN_CFG_TY_IFACE |
- PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
- PAS_DMA_TXCHAN_CFG_UP |
- PAS_DMA_TXCHAN_CFG_WT(2));
+ write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id),
+ PAS_DMA_TXCHAN_CFG_TY_IFACE |
+ PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
+ PAS_DMA_TXCHAN_CFG_UP |
+ PAS_DMA_TXCHAN_CFG_WT(2));
ring->next_to_use = 0;
ring->next_to_clean = 0;
@@ -383,12 +424,8 @@ static void pasemi_mac_replenish_rx_ring
wmb();
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_RXCHAN_INCR(mac->dma_rxch),
- limit - count);
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_RXINT_INCR(mac->dma_if),
- limit - count);
+ write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), limit - count);
+ write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), limit - count);
mac->rx->next_to_fill += limit - count;
}
@@ -404,9 +441,7 @@ static void pasemi_mac_restart_rx_intr(s
reg = PAS_IOB_DMA_RXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_RXCH_RESET_PINTC;
- pci_write_config_dword(mac->iob_pdev,
- PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch),
- reg);
+ write_iob_reg(mac, PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
}
static void pasemi_mac_restart_tx_intr(struct pasemi_mac *mac)
@@ -418,8 +453,7 @@ static void pasemi_mac_restart_tx_intr(s
reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
- pci_write_config_dword(mac->iob_pdev,
- PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
+ write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
}
@@ -574,8 +608,6 @@ static irqreturn_t pasemi_mac_rx_intr(in
* all others.
*/
- pci_read_config_dword(mac->dma_pdev, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), ®);
-
reg = 0;
if (*mac->rx_status & PAS_STATUS_SOFT)
reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
@@ -586,9 +618,7 @@ static irqreturn_t pasemi_mac_rx_intr(in
netif_rx_schedule(dev);
- pci_write_config_dword(mac->iob_pdev,
- PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
-
+ write_iob_reg(mac, PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
return IRQ_HANDLED;
}
@@ -613,9 +643,7 @@ static irqreturn_t pasemi_mac_tx_intr(in
if (*mac->tx_status & PAS_STATUS_ERROR)
reg |= PAS_IOB_DMA_TXCH_RESET_DINTC;
- pci_write_config_dword(mac->iob_pdev,
- PAS_IOB_DMA_TXCH_RESET(mac->dma_txch),
- reg);
+ write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
return IRQ_HANDLED;
}
@@ -641,7 +669,7 @@ static void pasemi_adjust_link(struct ne
} else
netif_carrier_on(dev);
- pci_read_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, &flags);
+ flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M |
PAS_MAC_CFG_PCFG_TSR_M);
@@ -673,7 +701,7 @@ static void pasemi_adjust_link(struct ne
mac->link = mac->phydev->link;
if (new_flags != flags)
- pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, new_flags);
+ write_mac_reg(mac, PAS_MAC_CFG_PCFG, new_flags);
if (msg && netif_msg_link(mac))
printk(KERN_INFO "%s: Link is up at %d Mbps, %s duplex.\n",
@@ -736,39 +764,37 @@ static int pasemi_mac_open(struct net_de
int ret;
/* enable rx section */
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_COM_RXCMD,
- PAS_DMA_COM_RXCMD_EN);
+ write_dma_reg(mac, PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
/* enable tx section */
- pci_write_config_dword(mac->dma_pdev, PAS_DMA_COM_TXCMD,
- PAS_DMA_COM_TXCMD_EN);
+ write_dma_reg(mac, 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) |
PAS_MAC_CFG_TXP_TIFT(8) | PAS_MAC_CFG_TXP_TIFG(12);
- pci_write_config_dword(mac->pdev, PAS_MAC_CFG_TXP, flags);
+ write_mac_reg(mac, PAS_MAC_CFG_TXP, flags);
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_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
- pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
- PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
+ write_iob_reg(mac, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
+ PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
- pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
- PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
+ write_iob_reg(mac, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
+ PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
/* 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 */
- pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_COM_TIMEOUTCFG,
- PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
+ write_iob_reg(mac, PAS_IOB_DMA_COM_TIMEOUTCFG,
+ PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
- pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, flags);
+ write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
ret = pasemi_mac_setup_rx_resources(dev);
if (ret)
@@ -778,25 +804,22 @@ static int pasemi_mac_open(struct net_de
if (ret)
goto out_tx_resources;
- pci_write_config_dword(mac->pdev, PAS_MAC_IPC_CHNL,
- PAS_MAC_IPC_CHNL_DCHNO(mac->dma_rxch) |
- PAS_MAC_IPC_CHNL_BCH(mac->dma_rxch));
+ write_mac_reg(mac, PAS_MAC_IPC_CHNL,
+ PAS_MAC_IPC_CHNL_DCHNO(mac->dma_rxch) |
+ PAS_MAC_IPC_CHNL_BCH(mac->dma_rxch));
/* enable rx if */
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
- PAS_DMA_RXINT_RCMDSTA_EN);
+ write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
+ PAS_DMA_RXINT_RCMDSTA_EN);
/* enable rx channel */
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
- PAS_DMA_RXCHAN_CCMDSTA_EN |
- PAS_DMA_RXCHAN_CCMDSTA_DU);
+ write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
+ PAS_DMA_RXCHAN_CCMDSTA_EN |
+ PAS_DMA_RXCHAN_CCMDSTA_DU);
/* enable tx channel */
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
- PAS_DMA_TXCHAN_TCMDSTA_EN);
+ write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
+ PAS_DMA_TXCHAN_TCMDSTA_EN);
pasemi_mac_replenish_rx_ring(dev);
@@ -875,20 +898,12 @@ static int pasemi_mac_close(struct net_d
pasemi_mac_clean_rx(mac, RX_RING_SIZE);
/* Disable interface */
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
- PAS_DMA_TXCHAN_TCMDSTA_ST);
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
- PAS_DMA_RXINT_RCMDSTA_ST);
- pci_write_config_dword(mac->dma_pdev,
- 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++) {
- pci_read_config_dword(mac->dma_pdev,
- PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
- &stat);
+ stat = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
break;
cond_resched();
@@ -898,9 +913,7 @@ static int pasemi_mac_close(struct net_d
dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
for (retries = 0; retries < MAX_RETRIES; retries++) {
- pci_read_config_dword(mac->dma_pdev,
- PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
- &stat);
+ stat = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT))
break;
cond_resched();
@@ -910,9 +923,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++) {
- pci_read_config_dword(mac->dma_pdev,
- PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
- &stat);
+ stat = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT))
break;
cond_resched();
@@ -925,12 +936,9 @@ static int pasemi_mac_close(struct net_d
* stopping, since you can't disable when active.
*/
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), 0);
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), 0);
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
+ 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);
free_irq(mac->tx_irq, dev);
free_irq(mac->rx_irq, dev);
@@ -1011,8 +1019,7 @@ static int pasemi_mac_start_tx(struct sk
spin_unlock_irqrestore(&txring->lock, flags);
- pci_write_config_dword(mac->dma_pdev,
- PAS_DMA_TXCHAN_INCR(mac->dma_txch), 1);
+ write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(mac->dma_txch), 1);
return NETDEV_TX_OK;
@@ -1035,7 +1042,7 @@ static void pasemi_mac_set_rx_mode(struc
struct pasemi_mac *mac = netdev_priv(dev);
unsigned int flags;
- pci_read_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, &flags);
+ flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
/* Set promiscuous */
if (dev->flags & IFF_PROMISC)
@@ -1043,7 +1050,7 @@ static void pasemi_mac_set_rx_mode(struc
else
flags &= ~PAS_MAC_CFG_PCFG_PR;
- pci_write_config_dword(mac->pdev, PAS_MAC_CFG_PCFG, flags);
+ write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
}
--
^ permalink raw reply
* [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
Move away from using the pci config access functions for simple register
access. Our device has all of the registers in the config space (hey,
from the hardware point of view it looks reasonable :-), so we need to
somehow get to it. Newer firmwares have it in the device tree such that
we can just get it and ioremap it there (in case it ever moves in future
products). For now, provide a hardcoded fallback for older firmwares.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: netdev-2.6/drivers/net/pasemi_mac.c
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.c
+++ netdev-2.6/drivers/net/pasemi_mac.c
@@ -81,46 +81,47 @@ MODULE_PARM_DESC(debug, "PA Semi MAC bit
static struct pasdma_status *dma_status;
-static unsigned int read_iob_reg(struct pasemi_mac *mac, unsigned int reg)
+static inline unsigned int read_iob_reg(struct pasemi_mac *mac, unsigned int reg)
{
unsigned int val;
- pci_read_config_dword(mac->iob_pdev, reg, &val);
+ val = in_le32(mac->iob_regs+reg);
+
return val;
}
-static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
+static inline void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
unsigned int val)
{
- pci_write_config_dword(mac->iob_pdev, reg, val);
+ out_le32(mac->iob_regs+reg, val);
}
-static unsigned int read_mac_reg(struct pasemi_mac *mac, unsigned int reg)
+static inline unsigned int read_mac_reg(struct pasemi_mac *mac, unsigned int reg)
{
unsigned int val;
- pci_read_config_dword(mac->pdev, reg, &val);
+ val = in_le32(mac->regs+reg);
return val;
}
-static void write_mac_reg(struct pasemi_mac *mac, unsigned int reg,
+static inline void write_mac_reg(struct pasemi_mac *mac, unsigned int reg,
unsigned int val)
{
- pci_write_config_dword(mac->pdev, reg, val);
+ out_le32(mac->regs+reg, val);
}
-static unsigned int read_dma_reg(struct pasemi_mac *mac, unsigned int reg)
+static inline unsigned int read_dma_reg(struct pasemi_mac *mac, unsigned int reg)
{
unsigned int val;
- pci_read_config_dword(mac->dma_pdev, reg, &val);
+ val = in_le32(mac->dma_regs+reg);
return val;
}
-static void write_dma_reg(struct pasemi_mac *mac, unsigned int reg,
+static inline void write_dma_reg(struct pasemi_mac *mac, unsigned int reg,
unsigned int val)
{
- pci_write_config_dword(mac->dma_pdev, reg, val);
+ out_le32(mac->dma_regs+reg, val);
}
static int pasemi_get_mac_addr(struct pasemi_mac *mac)
@@ -585,7 +586,6 @@ static int pasemi_mac_clean_tx(struct pa
}
mac->tx->next_to_clean += count;
spin_unlock_irqrestore(&mac->tx->lock, flags);
-
netif_wake_queue(mac->netdev);
return count;
@@ -1077,6 +1077,73 @@ static int pasemi_mac_poll(struct net_de
}
}
+static inline 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
+ * who 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), 0x1000);
+}
+
+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)
{
@@ -1105,21 +1172,6 @@ pasemi_mac_probe(struct pci_dev *pdev, c
mac->pdev = pdev;
mac->netdev = dev;
- mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
-
- if (!mac->dma_pdev) {
- dev_err(&pdev->dev, "Can't find DMA Controller\n");
- err = -ENODEV;
- goto out_free_netdev;
- }
-
- mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
-
- if (!mac->iob_pdev) {
- dev_err(&pdev->dev, "Can't find I/O Bridge\n");
- err = -ENODEV;
- goto out_put_dma_pdev;
- }
/* These should come out of the device tree eventually */
mac->dma_txch = index;
@@ -1162,12 +1214,9 @@ pasemi_mac_probe(struct pci_dev *pdev, c
dev->poll = pasemi_mac_poll;
dev->features = NETIF_F_HW_CSUM;
- /* The dma status structure is located in the I/O bridge, and
- * is cache coherent.
- */
- if (!dma_status)
- /* XXXOJN This should come from the device tree */
- dma_status = __ioremap(0xfd800000, 0x1000, 0);
+ err = pasemi_mac_map_regs(mac);
+ if (err)
+ goto out;
mac->rx_status = &dma_status->rx_sta[mac->dma_rxch];
mac->tx_status = &dma_status->tx_sta[mac->dma_txch];
@@ -1194,10 +1243,17 @@ pasemi_mac_probe(struct pci_dev *pdev, c
return err;
out:
- pci_dev_put(mac->iob_pdev);
-out_put_dma_pdev:
- pci_dev_put(mac->dma_pdev);
-out_free_netdev:
+ if (mac->iob_pdev)
+ 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:
pci_disable_device(pdev);
@@ -1221,6 +1277,10 @@ 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);
+
pci_set_drvdata(pdev, NULL);
free_netdev(netdev);
}
Index: netdev-2.6/drivers/net/pasemi_mac.h
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.h
+++ netdev-2.6/drivers/net/pasemi_mac.h
@@ -52,6 +52,9 @@ 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;
--
^ permalink raw reply
* [patch 12/35] pasemi_mac: Enable LLTX
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
Enable LLTX on pasemi_mac: we're already doing sufficient locking
in the driver to enable it.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: netdev-2.6/drivers/net/pasemi_mac.c
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.c
+++ netdev-2.6/drivers/net/pasemi_mac.c
@@ -1239,7 +1239,7 @@ pasemi_mac_probe(struct pci_dev *pdev, c
dev->set_multicast_list = pasemi_mac_set_rx_mode;
dev->weight = 64;
dev->poll = pasemi_mac_poll;
- dev->features = NETIF_F_HW_CSUM;
+ dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
err = pasemi_mac_map_regs(mac);
if (err)
--
^ permalink raw reply
* [patch 09/35] pasemi_mac: Simplify memcpy for short receives
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
No need to copy over the skipped align bytes (besides, NET_IP_ALIGN is
0 on ppc64).
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: netdev-2.6/drivers/net/pasemi_mac.c
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.c
+++ netdev-2.6/drivers/net/pasemi_mac.c
@@ -516,9 +516,7 @@ static int pasemi_mac_clean_rx(struct pa
netdev_alloc_skb(mac->netdev, len + NET_IP_ALIGN);
if (new_skb) {
skb_reserve(new_skb, NET_IP_ALIGN);
- memcpy(new_skb->data - NET_IP_ALIGN,
- skb->data - NET_IP_ALIGN,
- len + NET_IP_ALIGN);
+ memcpy(new_skb->data, skb->data, len);
/* save the skb in buffer_info as good */
skb = new_skb;
}
--
^ permalink raw reply
* [patch 08/35] pasemi_mac: Enable L2 caching of packet headers
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
Enable settings to target L2 for the first few cachelines of the packet,
since we'll access them to get to the various headers.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: netdev-2.6/drivers/net/pasemi_mac.c
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.c
+++ netdev-2.6/drivers/net/pasemi_mac.c
@@ -216,7 +216,7 @@ static int pasemi_mac_setup_rx_resources
PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 2));
write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id),
- PAS_DMA_RXCHAN_CFG_HBU(1));
+ PAS_DMA_RXCHAN_CFG_HBU(2));
write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if),
PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers)));
@@ -225,6 +225,9 @@ static int pasemi_mac_setup_rx_resources
PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) |
PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
+ write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if),
+ PAS_DMA_RXINT_CFG_DHL(2));
+
ring->next_to_fill = 0;
ring->next_to_clean = 0;
Index: netdev-2.6/drivers/net/pasemi_mac.h
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.h
+++ netdev-2.6/drivers/net/pasemi_mac.h
@@ -218,6 +218,14 @@ enum {
#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_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_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
--
^ permalink raw reply
* [patch 05/35] pasemi_mac: Clean TX ring in poll
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
Clean the TX ring in the poll call, to avoid sitting on mapped buffers
for a long time. NFS doesn't seem to like it much, for example.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: netdev-2.6/drivers/net/pasemi_mac.c
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.c
+++ netdev-2.6/drivers/net/pasemi_mac.c
@@ -1052,6 +1052,7 @@ static int pasemi_mac_poll(struct net_de
int pkts, limit = min(*budget, dev->quota);
struct pasemi_mac *mac = netdev_priv(dev);
+ pasemi_mac_clean_tx(mac);
pkts = pasemi_mac_clean_rx(mac, limit);
dev->quota -= pkts;
--
^ permalink raw reply
* [patch 11/35] pasemi_mac: Reduce locking when cleaning TX ring
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
Postpone pci unmap and skb free of the transmitted buffers to outside
of the tx ring lock, batching them up 32 at a time.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: netdev-2.6/drivers/net/pasemi_mac.c
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.c
+++ netdev-2.6/drivers/net/pasemi_mac.c
@@ -562,37 +562,56 @@ static int pasemi_mac_clean_tx(struct pa
int i;
struct pasemi_mac_buffer *info;
struct pas_dma_xct_descr *dp;
- int start, count;
+ unsigned int start, count, limit;
+ unsigned int total_count;
int flags;
+ struct sk_buff *skbs[32];
+ dma_addr_t dmas[32];
+ total_count = 0;
+restart:
spin_lock_irqsave(&mac->tx->lock, flags);
start = mac->tx->next_to_clean;
+ limit = min(mac->tx->next_to_use, start+32);
+
count = 0;
- for (i = start; i < mac->tx->next_to_use; i++) {
+ for (i = start; i < limit; i++) {
dp = &TX_DESC(mac, i);
+
if (unlikely(dp->mactx & XCT_MACTX_O))
+ /* Not yet transmitted */
break;
- count++;
-
info = &TX_DESC_INFO(mac, i);
-
- pci_unmap_single(mac->dma_pdev, info->dma,
- info->skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(info->skb);
+ skbs[count] = info->skb;
+ dmas[count] = info->dma;
info->skb = NULL;
info->dma = 0;
dp->mactx = 0;
dp->ptr = 0;
+
+ count++;
}
mac->tx->next_to_clean += count;
spin_unlock_irqrestore(&mac->tx->lock, flags);
netif_wake_queue(mac->netdev);
- return count;
+ for (i = 0; i < count; i++) {
+ pci_unmap_single(mac->dma_pdev, dmas[i],
+ skbs[i]->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(skbs[i]);
+ }
+
+ total_count += count;
+
+ /* If the batch was full, try to clean more */
+ if (count == 32)
+ goto restart;
+
+ return total_count;
}
--
^ permalink raw reply
* [patch 03/35] Change powerpc64 ioaddr_t to u_int
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras
In-Reply-To: <20070705170233.258351000@lixom.net>
ppc64 really needs ioaddr_t to be 32-bit, since I/O addresses really are
MMIO addresses, and remapped at an offset that's well above 16 bits in
some cases.
While the type is exported to userspace, there hasn't been any platforms
with PCMCIA on 64-bit powerpc until now, so changing it won't regress
any existing users.
Signed-off-by: Olof Johansson <olof@lixom.net>
Acked-by: Paul Mackerras <paulus@samba.org>
Index: 2.6.21/include/pcmcia/cs_types.h
===================================================================
--- 2.6.21.orig/include/pcmcia/cs_types.h
+++ 2.6.21/include/pcmcia/cs_types.h
@@ -21,7 +21,7 @@
#include <sys/types.h>
#endif
-#if defined(__arm__) || defined(__mips__)
+#if defined(__arm__) || defined(__mips__) || defined(__powerpc64__)
/* This (ioaddr_t) is exposed to userspace & hence cannot be changed. */
typedef u_int ioaddr_t;
#else
--
^ permalink raw reply
* [patch 04/35] pasemi_mac: Fix TX interrupt threshold
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
It was mistakenly set to interrupt on the second packet instead of first, causing
some interesting latency behaviour.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: netdev-2.6/drivers/net/pasemi_mac.c
===================================================================
--- netdev-2.6.orig/drivers/net/pasemi_mac.c
+++ netdev-2.6/drivers/net/pasemi_mac.c
@@ -755,7 +755,7 @@ static int pasemi_mac_open(struct net_de
flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
- PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
+ PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
--
^ permalink raw reply
* [patch 02/35] PA Semi EDAC driver
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Egor Martovetsky
In-Reply-To: <20070705170233.258351000@lixom.net>
EDAC driver for the memory controllers on PA Semi PA6T-1682M.
Signed-off-by: Egor Martovetsky <egor@pasemi.com>
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: 2.6.21/drivers/edac/pasemi_edac.c
===================================================================
--- /dev/null
+++ 2.6.21/drivers/edac/pasemi_edac.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2006-2007 PA Semi, Inc
+ *
+ * Author: Egor Martovetsky <egor@pasemi.com>
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Driver for the PWRficient onchip memory controllers
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+#define MODULE_NAME "pasemi_edac"
+
+#define MCCFG_MCEN 0x300
+#define MCCFG_MCEN_MMC_EN 0x00000001
+#define MCCFG_ERRCOR 0x388
+#define MCCFG_ERRCOR_RNK_FAIL_DET_EN 0x00000100
+#define MCCFG_ERRCOR_ECC_GEN_EN 0x00000010
+#define MCCFG_ERRCOR_ECC_CRR_EN 0x00000001
+#define MCCFG_SCRUB 0x384
+#define MCCFG_SCRUB_RGLR_SCRB_EN 0x00000001
+#define MCDEBUG_ERRCTL1 0x728
+#define MCDEBUG_ERRCTL1_RFL_LOG_EN 0x00080000
+#define MCDEBUG_ERRCTL1_MBE_LOG_EN 0x00040000
+#define MCDEBUG_ERRCTL1_SBE_LOG_EN 0x00020000
+#define MCDEBUG_ERRSTA 0x730
+#define MCDEBUG_ERRSTA_RFL_STATUS 0x00000004
+#define MCDEBUG_ERRSTA_MBE_STATUS 0x00000002
+#define MCDEBUG_ERRSTA_SBE_STATUS 0x00000001
+#define MCDEBUG_ERRCNT1 0x734
+#define MCDEBUG_ERRCNT1_SBE_CNT_OVRFLO 0x00000080
+#define MCDEBUG_ERRLOG1A 0x738
+#define MCDEBUG_ERRLOG1A_MERR_TYPE_M 0x30000000
+#define MCDEBUG_ERRLOG1A_MERR_TYPE_NONE 0x00000000
+#define MCDEBUG_ERRLOG1A_MERR_TYPE_SBE 0x10000000
+#define MCDEBUG_ERRLOG1A_MERR_TYPE_MBE 0x20000000
+#define MCDEBUG_ERRLOG1A_MERR_TYPE_RFL 0x30000000
+#define MCDEBUG_ERRLOG1A_MERR_BA_M 0x00700000
+#define MCDEBUG_ERRLOG1A_MERR_BA_S 20
+#define MCDEBUG_ERRLOG1A_MERR_CS_M 0x00070000
+#define MCDEBUG_ERRLOG1A_MERR_CS_S 16
+#define MCDEBUG_ERRLOG1A_SYNDROME_M 0x0000ffff
+#define MCDRAM_RANKCFG 0x114
+#define MCDRAM_RANKCFG_EN 0x00000001
+#define MCDRAM_RANKCFG_TYPE_SIZE_M 0x000001c0
+#define MCDRAM_RANKCFG_TYPE_SIZE_S 6
+
+#define PASEMI_EDAC_NR_CSROWS 8
+#define PASEMI_EDAC_NR_CHANS 1
+#define PASEMI_EDAC_ERROR_GRAIN 64
+
+static int last_page_in_mmc = 0;
+static int system_mmc_id = 0;
+
+
+static u32 pasemi_edac_get_error_info(struct mem_ctl_info *mci)
+{
+ struct pci_dev *pdev = to_pci_dev(mci->dev);
+ u32 tmp;
+
+ pci_read_config_dword(pdev, MCDEBUG_ERRSTA,
+ &tmp);
+
+ tmp &= (MCDEBUG_ERRSTA_RFL_STATUS | MCDEBUG_ERRSTA_MBE_STATUS
+ | MCDEBUG_ERRSTA_SBE_STATUS);
+
+ if (tmp) {
+ if (tmp & MCDEBUG_ERRSTA_SBE_STATUS)
+ pci_write_config_dword(pdev, MCDEBUG_ERRCNT1,
+ MCDEBUG_ERRCNT1_SBE_CNT_OVRFLO);
+ pci_write_config_dword(pdev, MCDEBUG_ERRSTA, tmp);
+ }
+
+ return tmp;
+}
+
+static void pasemi_edac_process_error_info(struct mem_ctl_info *mci, u32 errsta)
+{
+ struct pci_dev *pdev = to_pci_dev(mci->dev);
+ u32 errlog1a;
+ u32 cs;
+
+ if (!errsta)
+ return;
+
+ pci_read_config_dword(pdev, MCDEBUG_ERRLOG1A, &errlog1a);
+
+ cs = (errlog1a & MCDEBUG_ERRLOG1A_MERR_CS_M) >>
+ MCDEBUG_ERRLOG1A_MERR_CS_S;
+
+ /* uncorrectable/multi-bit errors */
+ if (errsta & (MCDEBUG_ERRSTA_MBE_STATUS |
+ MCDEBUG_ERRSTA_RFL_STATUS)) {
+ edac_mc_handle_ue(mci, mci->csrows[cs].first_page, 0,
+ cs, mci->ctl_name);
+ }
+
+ /* correctable/single-bit errors */
+ if (errsta & MCDEBUG_ERRSTA_SBE_STATUS) {
+ edac_mc_handle_ce(mci, mci->csrows[cs].first_page, 0,
+ 0, cs, 0, mci->ctl_name);
+ }
+}
+
+static void pasemi_edac_check(struct mem_ctl_info *mci)
+{
+ u32 errsta;
+
+ errsta = pasemi_edac_get_error_info(mci);
+ if (errsta)
+ pasemi_edac_process_error_info(mci, errsta);
+}
+
+static int pasemi_edac_init_csrows(struct mem_ctl_info *mci,
+ struct pci_dev *pdev,
+ enum edac_type edac_mode)
+{
+ struct csrow_info *csrow;
+ u32 rankcfg;
+ int index;
+
+ for (index = 0; index < mci->nr_csrows; index++) {
+ csrow = &mci->csrows[index];
+
+ pci_read_config_dword(pdev,
+ MCDRAM_RANKCFG + (index * 12),
+ &rankcfg);
+
+ if (!(rankcfg & MCDRAM_RANKCFG_EN))
+ continue;
+
+ switch ((rankcfg & MCDRAM_RANKCFG_TYPE_SIZE_M) >>
+ MCDRAM_RANKCFG_TYPE_SIZE_S) {
+ case 0:
+ csrow->nr_pages = 128 << (20 - PAGE_SHIFT);
+ break;
+ case 1:
+ csrow->nr_pages = 256 << (20 - PAGE_SHIFT);
+ break;
+ case 2:
+ case 3:
+ csrow->nr_pages = 512 << (20 - PAGE_SHIFT);
+ break;
+ case 4:
+ csrow->nr_pages = 1024 << (20 - PAGE_SHIFT);
+ break;
+ case 5:
+ csrow->nr_pages = 2048 << (20 - PAGE_SHIFT);
+ break;
+ default:
+ edac_mc_printk(mci, KERN_ERR,
+ "Unrecognized Rank Config\n");
+ return -EINVAL;
+ }
+
+ csrow->first_page = last_page_in_mmc;
+ csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+ last_page_in_mmc += csrow->nr_pages;
+ csrow->page_mask = 0;
+ csrow->grain = PASEMI_EDAC_ERROR_GRAIN;
+ csrow->mtype = MEM_DDR;
+ csrow->dtype = DEV_UNKNOWN;
+ csrow->edac_mode = edac_mode;
+ }
+ return 0;
+}
+
+static int __devinit pasemi_edac_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct mem_ctl_info *mci = NULL;
+ u32 errctl1, errcor, scrub, mcen;
+
+ pci_read_config_dword(pdev, MCCFG_MCEN, &mcen);
+ if (!(mcen & MCCFG_MCEN_MMC_EN))
+ return -ENODEV;
+
+ /*
+ * We should think about enabling other error detection later on
+ */
+
+ pci_read_config_dword(pdev, MCDEBUG_ERRCTL1, &errctl1);
+ errctl1 |= MCDEBUG_ERRCTL1_SBE_LOG_EN |
+ MCDEBUG_ERRCTL1_MBE_LOG_EN |
+ MCDEBUG_ERRCTL1_RFL_LOG_EN;
+ pci_write_config_dword(pdev, MCDEBUG_ERRCTL1, errctl1);
+
+ mci = edac_mc_alloc(0, PASEMI_EDAC_NR_CSROWS, PASEMI_EDAC_NR_CHANS);
+
+ if (mci == NULL)
+ return -ENOMEM;
+
+ pci_read_config_dword(pdev, MCCFG_ERRCOR, &errcor);
+ errcor |= MCCFG_ERRCOR_RNK_FAIL_DET_EN |
+ MCCFG_ERRCOR_ECC_GEN_EN |
+ MCCFG_ERRCOR_ECC_CRR_EN;
+
+ mci->dev = &pdev->dev;
+ mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ mci->edac_cap = (errcor & MCCFG_ERRCOR_ECC_GEN_EN) ?
+ ((errcor & MCCFG_ERRCOR_ECC_CRR_EN) ?
+ (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_EC) :
+ EDAC_FLAG_NONE;
+ mci->mod_name = MODULE_NAME;
+ mci->ctl_name = "PA6T1682M";
+ mci->edac_check = pasemi_edac_check;
+ mci->ctl_page_to_phys = NULL;
+ pci_read_config_dword(pdev, MCCFG_SCRUB, &scrub);
+ mci->scrub_cap = SCRUB_FLAG_HW_PROG | SCRUB_FLAG_HW_SRC;
+ mci->scrub_mode =
+ ((errcor & MCCFG_ERRCOR_ECC_CRR_EN) ? SCRUB_FLAG_HW_SRC : 0) |
+ ((scrub & MCCFG_SCRUB_RGLR_SCRB_EN) ? SCRUB_FLAG_HW_PROG : 0);
+
+ if (pasemi_edac_init_csrows(mci, pdev,
+ (mci->edac_cap & EDAC_FLAG_SECDED) ?
+ EDAC_SECDED :
+ ((mci->edac_cap & EDAC_FLAG_EC) ?
+ EDAC_EC : EDAC_NONE)))
+ goto fail;
+
+ /*
+ * Clear status
+ */
+ pasemi_edac_get_error_info(mci);
+
+ if (edac_mc_add_mc(mci, system_mmc_id++)) {
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ return 0;
+
+fail:
+ edac_mc_free(mci);
+ return -ENODEV;
+}
+
+static void __devexit pasemi_edac_remove(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
+ return;
+
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id pasemi_edac_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa00a) },
+};
+
+MODULE_DEVICE_TABLE(pci, pasemi_edac_pci_tbl);
+
+static struct pci_driver pasemi_edac_driver = {
+ .name = MODULE_NAME,
+ .probe = pasemi_edac_probe,
+ .remove = __devexit_p(pasemi_edac_remove),
+ .id_table = pasemi_edac_pci_tbl,
+};
+
+static int __init pasemi_edac_init(void)
+{
+ return pci_register_driver(&pasemi_edac_driver);
+}
+
+static void __exit pasemi_edac_exit(void)
+{
+ pci_unregister_driver(&pasemi_edac_driver);
+}
+
+module_init(pasemi_edac_init);
+module_exit(pasemi_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
+MODULE_DESCRIPTION("MC support for PA Semi PA6T-1682M memory controller");
Index: 2.6.21/drivers/edac/Kconfig
===================================================================
--- 2.6.21.orig/drivers/edac/Kconfig
+++ 2.6.21/drivers/edac/Kconfig
@@ -10,7 +10,7 @@ menu 'EDAC - error detection and reporti
config EDAC
tristate "EDAC core system error reporting (EXPERIMENTAL)"
- depends on X86 && EXPERIMENTAL
+ depends on (X86 || PPC) && EXPERIMENTAL
help
EDAC is designed to report errors in the core system.
These are low-level errors that are reported in the CPU or
@@ -97,6 +97,13 @@ config EDAC_R82600
Support for error detection and correction on the Radisys
82600 embedded chipset.
+config EDAC_PASEMI
+ tristate "PA Semi PA6T-1682M"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the PA Semi
+ PA6T-1682M processor.
+
choice
prompt "Error detecting method"
depends on EDAC
Index: 2.6.21/drivers/edac/edac_mc.h
===================================================================
--- 2.6.21.orig/drivers/edac/edac_mc.h
+++ 2.6.21/drivers/edac/edac_mc.h
@@ -84,7 +84,7 @@ extern int edac_debug_level;
#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \
PCI_DEVICE_ID_ ## vend ## _ ## dev
-#if defined(CONFIG_X86) && defined(CONFIG_PCI)
+#if (defined(CONFIG_X86) || defined(CONFIG_PPC)) && defined(CONFIG_PCI)
#define dev_name(dev) pci_name(to_pci_dev(dev))
#else
#define dev_name(dev) to_platform_device(dev)->name
@@ -185,7 +185,7 @@ enum scrub_type {
#define SCRUB_FLAG_SW_PROG_SRC BIT(SCRUB_SW_PROG_SRC_CORR)
#define SCRUB_FLAG_SW_TUN BIT(SCRUB_SW_SCRUB_TUNABLE)
#define SCRUB_FLAG_HW_PROG BIT(SCRUB_HW_PROG)
-#define SCRUB_FLAG_HW_SRC BIT(SCRUB_HW_SRC_CORR)
+#define SCRUB_FLAG_HW_SRC BIT(SCRUB_HW_SRC)
#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR)
#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE)
Index: 2.6.21/drivers/edac/Makefile
===================================================================
--- 2.6.21.orig/drivers/edac/Makefile
+++ 2.6.21/drivers/edac/Makefile
@@ -15,4 +15,5 @@ obj-$(CONFIG_EDAC_E752X) += e752x_edac.
obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
obj-$(CONFIG_EDAC_I82860) += i82860_edac.o
obj-$(CONFIG_EDAC_R82600) += r82600_edac.o
+obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o
--
^ permalink raw reply
* [patch 01/35] pasemi: rename platform
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20070705170233.258351000@lixom.net>
Rename the pasemi platform to "pasemi" to be in line with the platforms
directory name.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: mainline/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- mainline.orig/arch/powerpc/platforms/pasemi/setup.c
+++ mainline/arch/powerpc/platforms/pasemi/setup.c
@@ -239,7 +239,7 @@ static int __init pas_probe(void)
return 1;
}
-define_machine(pas) {
+define_machine(pasemi) {
.name = "PA Semi PA6T-1682M",
.probe = pas_probe,
.setup_arch = pas_setup_arch,
--
^ permalink raw reply
* [patch 00/35] PA Semi patch set
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
The following series is a snapshot of the in-progress and out-of-tree
errata workarounds that I'm currently maintaining.
The first patches are mostly copies of stuff that has already been sent
out for upstream merge, followed by some patches that are not yet ready
to be merged (need cleanup, more work). Last are some errata workarounds
for various bugs in the sample-level silicon.
Some of the workarounds are quite ugly and touches various parts of the
kernels in not so pretty ways. No need to tell me about it.
They are also not multiplatform-friendly. Since they are all temporary
it hasn't been a priority.
This is not a request for review or merge, just a FYI to "get the patches
out there".
--
^ permalink raw reply
* PowerPC equivalent to dma_mmap_writecombine()?
From: Timur Tabi @ 2007-07-05 16:41 UTC (permalink / raw)
To: linuxppc-dev
I'm porting a driver from ARM to PowerPC, and I came across this function:
static int at91_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_pcm_runtime *runtime = substream->runtime;
return dma_mmap_writecombine(substream->pcm->card->dev, vma,
runtime->dma_area,
runtime->dma_addr,
runtime->dma_bytes);
}
There are no dma_mmap_x() functions in arch/powerpc. Can someone tell me what the powerpc
equivalent to dma_mmap_writecombine() is?
--
Timur Tabi
Linux Kernel Developer @ Freescale
^ permalink raw reply
* Re: [PATCH 2/2] eHEA: Receive SKB Aggregation, generic LRO helper functions
From: Evgeniy Polyakov @ 2007-07-05 15:45 UTC (permalink / raw)
To: Jan-Bernd Themann
Cc: Thomas Klein, Jeff Garzik, Jan-Bernd Themann, netdev,
linux-kernel, Christoph Hellwig, linux-ppc, Christoph Raisch,
Marcus Eder, Stefan Roscher
In-Reply-To: <200707051624.46887.ossthema@de.ibm.com>
On Thu, Jul 05, 2007 at 04:24:46PM +0200, Jan-Bernd Themann (ossthema@de.ibm.com) wrote:
> > I've couple of comments on the driver, but mainly the fact of decreased
> > CPU usage itself - what was the magnitude of the win with this driver,
> > it looks like because of per-packet receive code path invocation is the
> > place of the latency...
> > Your implementation looks generic enough to be used by any driver, don't
> > you want to push it separately from eHEA driver?
> >
>
> We can try to come up with a generic file with these helperfunctions.
> What do you think about putting them into /net/ipv4/inet_lro.c and
> /include/linux/inet_lro.h ?
The more I think, the more it looks as appropriate to be used by all hardware
drivers with proper API. As far as I recall this is third implementation
in the linux drivers :)
--
Evgeniy Polyakov
^ permalink raw reply
* Re: Patches added to for_paulus (queue'd for 2.6.23)
From: Jon Loeliger @ 2007-07-05 15:48 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev list
In-Reply-To: <790E72AD-637C-4C13-8266-CDD285573DF6@kernel.crashing.org>
On Tue, 2007-07-03 at 04:17, Kumar Gala wrote:
> I'm still working through the back log of patches related to ppc32/
> fsl. If there are patches people want to make sure get into 2.6.23
> let me know.
> Jon Loeliger (1):
> [POWERPC] Replace use of GET_64BIT(prop, i) with of_read_number().
Kumar,
Please also pick this one up too:
From: Jon Loeliger <jdl@freescale.com>
To: linuxppc-dev@ozlabs.org <linuxppc-dev@ozlabs.org>
Cc: pci-ids@ucw.cz
Subject: [PATCH v2 7/9] Add Freescale PCI VENDOR ID.
Date: Mon, 04 Jun 2007 17:30:
Thanks,
jdl
^ permalink raw reply
* Re: [PATCH 2/2] eHEA: Receive SKB Aggregation, generic LRO helper functions
From: Jan-Bernd Themann @ 2007-07-05 14:24 UTC (permalink / raw)
To: Evgeniy Polyakov
Cc: Thomas Klein, Jeff Garzik, Jan-Bernd Themann, netdev,
linux-kernel, Christoph Hellwig, linux-ppc, Christoph Raisch,
Marcus Eder, Stefan Roscher
In-Reply-To: <20070705082056.GA358@2ka.mipt.ru>
Hi,
thanks for your comment.
Jan-Bernd
On Thursday 05 July 2007 10:20, you wrote:
> Hi Jan-Bernd.
>
> [ Dropped spambot/i.e. unrelated mail lists ]
>
> On Thu, Jul 05, 2007 at 09:26:30AM +0200, Jan-Bernd Themann (ossthema@de.ibm.com) wrote:
> > This patch enables the receive side processing to aggregate TCP packets within
> > the HEA device driver. It analyses the packets already received after an
> > interrupt arrived and forwards these as chains of SKBs for the same TCP
> > connection with modified header field. We have seen a lower CPU load and
> > improved throughput for small numbers of parallel TCP connections.
> > As this feature is considered as experimental it is switched off by default
> > and can be activated via a module parameter.
>
> I've couple of comments on the driver, but mainly the fact of decreased
> CPU usage itself - what was the magnitude of the win with this driver,
> it looks like because of per-packet receive code path invocation is the
> place of the latency...
> Your implementation looks generic enough to be used by any driver, don't
> you want to push it separately from eHEA driver?
>
We can try to come up with a generic file with these helperfunctions.
What do you think about putting them into /net/ipv4/inet_lro.c and
/include/linux/inet_lro.h ?
Latency: We didn't measure it so far, but it leads to a significant improvement
concerning the throughput. Our LRO algorithm only handles X packets a time
(depends on MTU and budget), so the upper bound delay is X*processing a single
packet from driver perspective.
>
> > +static int lro_tcp_check(struct iphdr *iph, struct tcphdr *tcph,
> > + int tcp_data_len, struct ehea_lro *lro)
> > +{
> > + if (tcp_data_len == 0)
> > + return -1;
> > +
> > + if (iph->ihl != IPH_LEN_WO_OPTIONS)
> > + return -1;
> > +
> > + if (tcph->cwr || tcph->ece || tcph->urg || !tcph->ack || tcph->psh
> > + || tcph->rst || tcph->syn || tcph->fin)
> > + return -1;
> > +
> > + if (INET_ECN_is_ce(ipv4_get_dsfield(iph)))
> > + return -1;
> > +
> > + if (tcph->doff != TCPH_LEN_WO_OPTIONS
> > + && tcph->doff != TCPH_LEN_W_TIMESTAMP)
> > + return -1;
> > +
> > + /* check tcp options (only timestamp allowed) */
> > + if (tcph->doff == TCPH_LEN_W_TIMESTAMP) {
> > + u32 *topt = (u32 *)(tcph + 1);
> > +
> > + if (*topt != htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
> > + | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
> > + return -1;
> > +
> > + /* timestamp should be in right order */
> > + topt++;
> > + if (lro && (ntohl(lro->tcp_rcv_tsval) > ntohl(*topt)))
> > + return -1;
>
> This should use before/after technique like PAWS in TCP code or there will be a
> problem with wrapper timestamps.
>
good point, will look into this
> > +
> > + /* timestamp reply should not be zero */
> > + topt++;
> > + if (*topt == 0)
> > + return -1;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void update_tcp_ip_header(struct ehea_lro *lro)
> > +{
> > + struct iphdr *iph = lro->iph;
> > + struct tcphdr *tcph = lro->tcph;
> > + u32 *p;
> > +
> > + tcph->ack_seq = lro->tcp_ack;
> > + tcph->window = lro->tcp_window;
> > +
> > + if (lro->tcp_saw_tstamp) {
> > + p = (u32 *)(tcph + 1);
> > + *(p+2) = lro->tcp_rcv_tsecr;
> > + }
> > +
> > + iph->tot_len = htons(lro->ip_tot_len);
> > + iph->check = 0;
> > + iph->check = ip_fast_csum((u8 *)lro->iph, iph->ihl);
> > +}
> > +
> > +static void init_lro_desc(struct ehea_lro *lro, struct ehea_cqe *cqe,
> > + struct sk_buff *skb, struct iphdr *iph,
> > + struct tcphdr *tcph, u32 tcp_data_len)
> > +{
> > + u32 *ptr;
> > +
> > + lro->parent = skb;
> > + lro->iph = iph;
> > + lro->tcph = tcph;
> > + lro->tcp_next_seq = ntohl(tcph->seq) + tcp_data_len;
> > + lro->tcp_ack = ntohl(tcph->ack_seq);
>
> How do you handle misordering or duplicate acks or resends?
>
we just forward these packets and leave it to the network stack to
handle them. As soon as we get a packet which does not match we
just flush the LRO session and the current packet
(forward to stack as separate SKBs)
> > + lro->skb_sg_cnt = 1;
> > + lro->ip_tot_len = ntohs(iph->tot_len);
> > +
> > + if (tcph->doff == 8) {
> > + ptr = (u32 *)(tcph+1);
> > + lro->tcp_saw_tstamp = 1;
> > + lro->tcp_rcv_tsval = *(ptr+1);
> > + lro->tcp_rcv_tsecr = *(ptr+2);
> > + }
> > +
> > + if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) {
> > + lro->vlan_packet = 1;
> > + lro->vlan_tag = cqe->vlan_tag;
> > + }
> > +
> > + lro->active = 1;
> > +}
>
^ permalink raw reply
* [PATCH v3] pcmcia: CompactFlash driver for PA Semi Electra boards
From: Olof Johansson @ 2007-07-05 14:49 UTC (permalink / raw)
To: Christoph Hellwig, linux-kernel, linux-pcmcia, linuxppc-dev,
miltonm
In-Reply-To: <20070625204341.GA8865@lixom.net>
Driver for the CompactFlash slot on the PA Semi Electra eval board. It's
a simple device sitting on localbus, with interrupts and detect/voltage
control over GPIO.
The driver is implemented as an of_platform driver, and adds localbus
as a bus being probed by the of_platform framework.
Signed-off-by: Olof Johansson <olof@lixom.net>
---
On Mon, Jun 25, 2007 at 03:43:41PM -0500, olof wrote:
> The ifdef is needed since for CONFIG_PCMCIA=n builds, the bus notifier
> isn't available. I wanted to do the bus notifier registration explicitly
> before the of_platform bus probe to avoid later surprises due to reordered
> initcalls in case it was split up in it's own initcall.
>
> I could add the code under ifdef as well, but it didn't seem too
> critical. Once the second major board comes along I'll probably move it
> out to a per-board file, there's no real need for it just yet.
Alright, turns out I still need to declare the extern bus type, which would mean
two #ifdefs in one function. Moving it out instead.
I've addressed Milton's comments as well.
Who's maintaining PCMCIA? MAINTAINERS only lists a mailing list, no person. Seems
weird for a component that's marked as maintained.
Index: mainline/drivers/pcmcia/Kconfig
===================================================================
--- mainline.orig/drivers/pcmcia/Kconfig
+++ mainline/drivers/pcmcia/Kconfig
@@ -270,6 +270,13 @@ config AT91_CF
Say Y here to support the CompactFlash controller on AT91 chips.
Or choose M to compile the driver as a module named "at91_cf".
+config ELECTRA_CF
+ bool "Electra CompactFlash Controller"
+ depends on PCMCIA=y && PPC_PASEMI
+ help
+ Say Y here to support the CompactFlash controller on the
+ PA Semi Electra eval board.
+
config PCCARD_NONSTATIC
tristate
Index: mainline/drivers/pcmcia/Makefile
===================================================================
--- mainline.orig/drivers/pcmcia/Makefile
+++ mainline/drivers/pcmcia/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_PCMCIA_VRC4171) += vrc417
obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
obj-$(CONFIG_OMAP_CF) += omap_cf.o
obj-$(CONFIG_AT91_CF) += at91_cf.o
+obj-$(CONFIG_ELECTRA_CF) += electra_cf.o
sa11xx_core-y += soc_common.o sa11xx_base.o
pxa2xx_core-y += soc_common.o pxa2xx_base.o
Index: mainline/drivers/pcmcia/electra_cf.c
===================================================================
--- /dev/null
+++ mainline/drivers/pcmcia/electra_cf.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * Based on drivers/pcmcia/omap_cf.c
+ *
+ * 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 Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+#include <asm/of_platform.h>
+
+static const char driver_name[] = "electra-cf";
+
+struct electra_cf_socket {
+ struct pcmcia_socket socket;
+
+ struct timer_list timer;
+ unsigned present:1;
+ unsigned active:1;
+
+ struct of_device *ofdev;
+ unsigned long mem_phys;
+ void __iomem * mem_base;
+ unsigned long mem_size;
+ void __iomem * io_virt;
+ unsigned int io_base;
+ unsigned int io_size;
+ u_int irq;
+ struct resource iomem;
+ void __iomem * gpio_base;
+ int gpio_detect;
+ int gpio_vsense;
+ int gpio_3v;
+ int gpio_5v;
+};
+
+#define POLL_INTERVAL (2 * HZ)
+
+
+static int electra_cf_present(struct electra_cf_socket *cf)
+{
+ unsigned int gpio;
+
+ gpio = in_le32(cf->gpio_base+0x40);
+ return !(gpio & (1 << cf->gpio_detect));
+}
+
+static int electra_cf_ss_init(struct pcmcia_socket *s)
+{
+ return 0;
+}
+
+/* the timer is primarily to kick this socket's pccardd */
+static void electra_cf_timer(unsigned long _cf)
+{
+ struct electra_cf_socket *cf = (void *) _cf;
+ int present = electra_cf_present(cf);
+
+ if (present != cf->present) {
+ cf->present = present;
+ pcmcia_parse_events(&cf->socket, SS_DETECT);
+ }
+
+ if (cf->active)
+ mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+}
+
+static irqreturn_t electra_cf_irq(int irq, void *_cf)
+{
+ electra_cf_timer((unsigned long)_cf);
+ return IRQ_HANDLED;
+}
+
+static int electra_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+ struct electra_cf_socket *cf;
+
+ if (!sp)
+ return -EINVAL;
+
+ cf = container_of(s, struct electra_cf_socket, socket);
+
+ /* NOTE CF is always 3VCARD */
+ if (electra_cf_present(cf)) {
+ struct electra_cf_socket *cf;
+
+ *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
+ cf = container_of(s, struct electra_cf_socket, socket);
+ s->pci_irq = cf->irq;
+ } else
+ *sp = 0;
+ return 0;
+}
+
+static int electra_cf_set_socket(struct pcmcia_socket *sock,
+ struct socket_state_t *s)
+{
+ unsigned int gpio;
+ unsigned int vcc;
+ struct electra_cf_socket *cf;
+
+ cf = container_of(sock, struct electra_cf_socket, socket);
+
+ /* "reset" means no power in our case */
+ vcc = (s->flags & SS_RESET) ? 0 : s->Vcc;
+
+ switch (vcc) {
+ case 0:
+ gpio = 0;
+ break;
+ case 33:
+ gpio = (1 << cf->gpio_3v);
+ break;
+ default:
+ /* CF is 3.3V only */
+ return -EINVAL;
+ }
+
+ gpio |= 1 << (cf->gpio_3v + 16); /* enwr */
+ gpio |= 1 << (cf->gpio_5v + 16); /* enwr */
+ out_le32(cf->gpio_base+0x90, gpio);
+
+ pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+ driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+ return 0;
+}
+
+static int electra_cf_set_io_map(struct pcmcia_socket *s,
+ struct pccard_io_map *io)
+{
+ return 0;
+}
+
+static int electra_cf_set_mem_map(struct pcmcia_socket *s,
+ struct pccard_mem_map *map)
+{
+ struct electra_cf_socket *cf;
+
+ if (map->card_start)
+ return -EINVAL;
+ cf = container_of(s, struct electra_cf_socket, socket);
+ map->static_start = cf->mem_phys;
+ map->flags &= MAP_ACTIVE|MAP_ATTRIB;
+ if (!(map->flags & MAP_ATTRIB))
+ map->static_start += 0x800;
+ return 0;
+}
+
+static struct pccard_operations electra_cf_ops = {
+ .init = electra_cf_ss_init,
+ .get_status = electra_cf_get_status,
+ .set_socket = electra_cf_set_socket,
+ .set_io_map = electra_cf_set_io_map,
+ .set_mem_map = electra_cf_set_mem_map,
+};
+
+static int __devinit electra_cf_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device *device = &ofdev->dev;
+ struct device_node *np = ofdev->node;
+ struct electra_cf_socket *cf;
+ struct resource mem, io;
+ int status;
+ const unsigned int *prop;
+ int err;
+
+ err = of_address_to_resource(np, 0, &mem);
+ if (err)
+ return -EINVAL;
+
+ err = of_address_to_resource(np, 1, &io);
+ if (err)
+ return -EINVAL;
+
+ cf = kzalloc(sizeof *cf, GFP_KERNEL);
+ if (!cf)
+ return -ENOMEM;
+
+ init_timer(&cf->timer);
+ cf->timer.function = electra_cf_timer;
+ cf->timer.data = (unsigned long) cf;
+ cf->irq = NO_IRQ;
+
+ cf->ofdev = ofdev;
+ cf->mem_phys = mem.start;
+ cf->mem_base = ioremap(mem.start, mem.end - mem.start);
+ cf->io_size = PAGE_ALIGN(io.end - io.start);
+
+ cf->io_virt = reserve_phb_iospace(cf->io_size);
+
+ cf->gpio_base = ioremap(0xfc103000, 0x1000);
+ dev_set_drvdata(device, cf);
+
+ if (!cf->mem_base || !cf->io_virt || !cf->gpio_base) {
+ dev_err(device, "can't ioremap ranges\n");
+ status = -ENOMEM;
+ goto fail1;
+ }
+
+ __ioremap_explicit(io.start, (unsigned long)cf->io_virt, cf->io_size,
+ _PAGE_NO_CACHE | _PAGE_GUARDED);
+
+ cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END;
+
+ cf->iomem.start = (unsigned long)cf->mem_base;
+ cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start);
+ cf->iomem.flags = IORESOURCE_MEM;
+
+ cf->irq = irq_of_parse_and_map(np, 0);
+
+ status = request_irq(cf->irq, electra_cf_irq, IRQF_SHARED,
+ driver_name, cf);
+ if (status < 0) {
+ dev_err(device, "request_irq failed\n");
+ goto fail1;
+ }
+
+ cf->socket.pci_irq = cf->irq;
+
+ prop = of_get_property(np, "card-detect-gpio", NULL);
+ if (!prop)
+ goto fail1;
+ cf->gpio_detect = *prop;
+
+ prop = of_get_property(np, "card-vsense-gpio", NULL);
+ if (!prop)
+ goto fail1;
+ cf->gpio_vsense = *prop;
+
+ prop = of_get_property(np, "card-3v-gpio", NULL);
+ if (!prop)
+ goto fail1;
+ cf->gpio_3v = *prop;
+
+ prop = of_get_property(np, "card-5v-gpio", NULL);
+ if (!prop)
+ goto fail1;
+ cf->gpio_5v = *prop;
+
+ cf->socket.io_offset = cf->io_base;
+
+ /* reserve chip-select regions */
+ if (!request_mem_region(mem.start, mem.end + 1 - mem.start,
+ driver_name)) {
+ status = -ENXIO;
+ dev_err(device, "Can't claim memory region\n");
+ goto fail1;
+ }
+
+ if (!request_region(cf->io_base, cf->io_size, driver_name)) {
+ status = -ENXIO;
+ dev_err(device, "Can't claim I/O region\n");
+ goto fail2;
+ }
+
+ cf->socket.owner = THIS_MODULE;
+ cf->socket.dev.parent = &ofdev->dev;
+ cf->socket.ops = &electra_cf_ops;
+ cf->socket.resource_ops = &pccard_static_ops;
+ cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP |
+ SS_CAP_MEM_ALIGN;
+ cf->socket.map_size = 0x800;
+
+ status = pcmcia_register_socket(&cf->socket);
+ if (status < 0) {
+ dev_err(device, "pcmcia_register_socket failed\n");
+ goto fail3;
+ }
+
+ dev_info(device, "at mem 0x%lx io 0x%lx irq %d\n",
+ mem.start, io.start, cf->irq);
+
+ cf->active = 1;
+ electra_cf_timer((unsigned long)cf);
+ return 0;
+
+fail3:
+ release_mem_region(io.start, io.end + 1 - io.start);
+fail2:
+ release_mem_region(mem.start, mem.end + 1 - mem.start);
+fail1:
+ if (cf->irq != NO_IRQ)
+ free_irq(cf->irq, cf);
+
+ /* XXX No way to undo the ioremap_explicit at this time */
+ if (cf->mem_base)
+ iounmap(cf->mem_base);
+ if (cf->gpio_base)
+ iounmap(cf->gpio_base);
+ device_init_wakeup(&ofdev->dev, 0);
+ kfree(cf);
+ return status;
+
+}
+
+static int __devexit electra_cf_remove(struct of_device *ofdev)
+{
+ struct device *device = &ofdev->dev;
+ struct electra_cf_socket *cf;
+
+ cf = dev_get_drvdata(device);
+
+ cf->active = 0;
+ pcmcia_unregister_socket(&cf->socket);
+ free_irq(cf->irq, cf);
+ del_timer_sync(&cf->timer);
+
+ iounmap(cf->mem_base);
+ iounmap(cf->gpio_base);
+ release_mem_region(cf->mem_phys, cf->mem_size);
+ release_region(cf->io_base, cf->io_size);
+
+ kfree(cf);
+
+ return 0;
+}
+
+static struct of_device_id electra_cf_match[] =
+{
+ {
+ .compatible = "electra-cf",
+ },
+ {},
+};
+
+static struct of_platform_driver electra_cf_driver =
+{
+ .name = (char *)driver_name,
+ .match_table = electra_cf_match,
+ .probe = electra_cf_probe,
+ .remove = electra_cf_remove,
+};
+
+static int __init electra_cf_init(void)
+{
+ return of_register_platform_driver(&electra_cf_driver);
+}
+module_init(electra_cf_init);
+
+static void __exit electra_cf_exit(void)
+{
+ of_unregister_platform_driver(&electra_cf_driver);
+}
+module_exit(electra_cf_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi Electra CF driver");
+
Index: mainline/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- mainline.orig/arch/powerpc/platforms/pasemi/setup.c
+++ mainline/arch/powerpc/platforms/pasemi/setup.c
@@ -37,6 +37,10 @@
#include <asm/time.h>
#include <asm/of_platform.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
#include "pasemi.h"
static void __iomem *reset_reg;
@@ -204,7 +208,57 @@ static void __init pas_init_early(void)
iommu_init_early_pasemi();
}
+#ifdef CONFIG_PCMCIA
+static int pcmcia_notify(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct device *dev = data;
+ struct device *parent;
+ struct pcmcia_device *pdev = to_pcmcia_dev(dev);
+
+ /* We are only intereted in device addition */
+ if (action != BUS_NOTIFY_ADD_DEVICE)
+ return 0;
+
+ parent = pdev->socket->dev.parent;
+
+ /* We know electra_cf devices will always have of_node set, since
+ * electra_cf is an of_platform driver.
+ */
+ if (!parent->archdata.of_node)
+ return 0;
+
+ if (!of_device_is_compatible(parent->archdata.of_node, "electra-cf"))
+ return 0;
+
+ /* We use the direct ops for localbus */
+ dev->archdata.dma_ops = &dma_direct_ops;
+
+ return 0;
+}
+
+static struct notifier_block pcmcia_notifier = {
+ .notifier_call = pcmcia_notify,
+};
+
+static inline void pasemi_pcmcia_init(void)
+{
+ extern struct bus_type pcmcia_bus_type;
+
+ bus_register_notifier(&pcmcia_bus_type, &pcmcia_notifier);
+}
+
+#else
+
+static inline void pasemi_pcmcia_init(void)
+{
+}
+
+#endif
+
+
static struct of_device_id pasemi_bus_ids[] = {
+ { .type = "localbus", },
{ .type = "sdc", },
{},
};
@@ -214,6 +268,8 @@ static int __init pasemi_publish_devices
if (!machine_is(pasemi))
return 0;
+ pasemi_pcmcia_init();
+
/* Publish OF platform devices for SDC and other non-PCI devices */
of_platform_bus_probe(NULL, pasemi_bus_ids, NULL);
^ permalink raw reply
* [PATCH] [2.6.23] pasemi: rename platform
From: Olof Johansson @ 2007-07-05 14:49 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
Rename the pasemi platform to "pasemi" to be in line with the platforms
directory name.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: mainline/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- mainline.orig/arch/powerpc/platforms/pasemi/setup.c
+++ mainline/arch/powerpc/platforms/pasemi/setup.c
@@ -239,7 +239,7 @@ static int __init pas_probe(void)
return 1;
}
-define_machine(pas) {
+define_machine(pasemi) {
.name = "PA Semi PA6T-1682M",
.probe = pas_probe,
.setup_arch = pas_setup_arch,
^ permalink raw reply
* Re: [PATCH v2] pcmcia: CompactFlash driver for PA Semi Electra boards
From: Olof Johansson @ 2007-07-05 14:37 UTC (permalink / raw)
To: Milton Miller; +Cc: ppcdev, Christoph Hellwig
In-Reply-To: <3d37f1da59dc2a063a06bbd6092ed96a@bga.com>
On Wed, Jun 27, 2007 at 06:20:38AM -0500, Milton Miller wrote:
> If CONFIG_PCMCIA=m then your notifier is not registered. The modprobe
> of your of_driver loads ds.ko, registers the bus, then registers your
> driver. When the socket driver tries to dma, the BUG in dma_64 for no
> archdata.dma_ops triggers.
>
> It seems like we need
>
> (1) a notifier that a bus is registered, run before allowing any
> devices, so that platforms can register bus notifiers by bus name
> before the devices and drivers are registered.
>
> (2) a powerpc64 generic pcmcia bus notifier that copys the dma ops from
> the parent socket.
>
> (3) something to set the dma_ops to direct_dma_ops on the of device.
>
> If we don't want (3) to be in the driver (as Christoph previosly
> mentioned), then it needs to be a seperate bus that reuses the of
> matching. This would be similar to how ibmebus is setup. If I
> remember the discussion, ibmebus is to provide the alternate dma ops
> and steals match etc code from the of_platform bus type.
>
>
> Oh, is this why you have depends on PCMCIA=y ?
Yes.
-Olof
^ permalink raw reply
* Re: [PATCH] pcmcia: CompactFlash driver for PA Semi Electra boards
From: Olof Johansson @ 2007-07-05 14:36 UTC (permalink / raw)
To: Milton Miller; +Cc: ppcdev
In-Reply-To: <024cbfe00dde1c97bb249b925f55ebee@bga.com>
On Wed, Jun 27, 2007 at 06:20:27AM -0500, Milton Miller wrote:
> get_property is now a #define for of_get_property. I think the use of
> get_property is being deprecated.
Yeah, it's a pita. I've moved these over now.
> If of_get_property fails to find the property, then you will
> dereference a NULL pointer in a probe function and will leave the
> bus_type locked.
Fixed.
> >+ /* XXX No way to undo the io reservation at this time */
>
> What io reservation is this comment referring to?
ioremap_explicit. I've updated the comment.
> Where is the request_irq undone?
Fixed.
> >+static int __devexit electra_cf_remove(struct of_device *ofdev)
> >+{
> >+ struct device *device = &ofdev->dev;
> >+ struct electra_cf_socket *cf;
> >+
> >+ cf = dev_get_drvdata(device);
> >+
> >+ cf->active = 0;
> >+ pcmcia_unregister_socket(&cf->socket);
> >+ free_irq(cf->irq, cf);
> >+ del_timer_sync(&cf->timer);
> >+
> >+ iounmap(cf->mem_base);
> >+ iounmap(cf->gpio_base);
> >+ release_mem_region(cf->mem_phys, cf->mem_size);
> >+ release_region(cf->io_base, cf->io_size);
> >+
> >
>
> irq_request?
Huh?
-Olof
^ permalink raw reply
* Re: MPC8540 DMA transfer
From: Clemens Koller @ 2007-07-05 13:58 UTC (permalink / raw)
To: Ansari; +Cc: linuxppc-embedded
In-Reply-To: <000501c7be46$368236c0$9503a8c0@Ansari>
Hello, Ansari!
Ansari schrieb:
> Hello Koller,
>
> Is there any support for dma transter in linux 2.4.x kernel . Whether u
> have any source code for tht ?????. I think u have attached a dma driver
> code for 2.6.x kernel . But i need it for 2.4 kernel. ( Processor :
> MPC8540 / MPC8560 )
There are no new features going into kernel 2.4.x. Development has stopped
long time ago. Have a look at the available code and backport it to 2.4 (YMMV).
But you propably want to move to the latest 2.6. The MPC8540 is supported
very well.
If you want to have new features implemented, use the latest 2.6.x tree from
Linus. Don't ride dead horses!
Regards,
--
Clemens Koller
__________________________________
R&D Imaging Devices
Anagramm GmbH
Rupert-Mayer-Straße 45/1
Linhof Werksgelände
D-81379 München
Tel.089-741518-50
Fax 089-741518-19
http://www.anagramm-technology.com
^ permalink raw reply
* Re: OF devices and non OF devices
From: John Rigby @ 2007-07-05 13:28 UTC (permalink / raw)
To: Kári Davíðsson; +Cc: linuxppc-embedded
In-Reply-To: <DD39B5C3F4963040ADC9768BE7E430CB020D3DE8@is-hdq-exchange.marel.net>
[-- Attachment #1: Type: text/plain, Size: 4788 bytes --]
kd,
Ok, obviously It doesn't work the way I thought. Hopefully someone who does
understand this will comment.
John
On 7/4/07, Kári Davíðsson <kari.davidsson@marel.is> wrote:
>
> John, thank you for your answare.
>
> Enabling CONFIG_FSL_SOC only enabled the execution of the init function
> (fsl_i2c_init())
> of the fsl-i2c driver (i2c-mpc.c). The .probe function of the driver was
> never called
> until I converted the driver to the OF model and added the .match_table to
> the driver structure.
>
> Then I get the .probe function (fsl_i2c_probe()) called and the i2c bus
> set up.
>
> Similar thing happens for the i2c device PCF8563 i.e., the init functin of
> the driver (pcf8563_init())
> is called the driver is registered with the kernel, but the .probe
> (pcf8563_probe()) is never called.
>
> The driver pcf8563 has _NO_ exported structures or functions so I
> basically have no handle on it
> that I can utilize in board specific setup.
>
> The way I suspect this is supposed to work is that from the board settup
> files I would do
> rtc_dev = platform_device_register_simple("pcf8563", -1, NULL, 0);
> which should later trigger the calling of the pcf8563_probe() function.
>
> This is doing things in the same way as the fsl i2c code, i.e.
> i2c_dev = platform_device_register_simple("i2c", i, r, 2);
> which by the way does not work untill I have converted the fsl_i2c (
> i2c-mpc.c) driver to the OF structure.
>
> So still the method of gluing together the OF drivers and non OF drivers
> eludes me.
>
> rg
> kd
>
> P.S. I did check the 2.6.21-RC7-git3 and found that the i2c-mpc.c and the
> rtc-pcf85763.c are basically the same
> as what I am working with in 2.6.20+
> ________________________________
>
> From: John Rigby [mailto:jcrigby@gmail.com]
> Sent: 3. júlí 2007 16:31
> To: Kári Davíðsson
> Cc: linuxppc-embedded@ozlabs.org
> Subject: Re: OF devices and non OF devices
>
>
> One place to find binding between OF devices and non OF devices is in
> arch/powerpc/sysdev/fsl_soc.c
> The typical pattern is:
> if of_find_compatible_node "of-device-name"
> platform_device_register_simple ""platform-device-name"
> platform_device_add_data ...
>
>
>
> On 7/3/07, Kári Davíðsson <kari.davidsson@marel.is> wrote:
>
> Hi,
>
> I am attempting to get some non OF devices working for an mpc 5200
> board, in particular
> PCF8563 RTC.
>
> This device has an non OF device interface which I believe is
> correct. After all it should work
> on non OF platforms.
>
> I have managed to get the board to run the i2c initialization (and
> probe) for the fsl-mpc i2c driver by
> converting the fsl-mpc i2c driver to OF driver (I found some patch
> here that I based this work on).
>
>
> fsl-i2c is one of the devices handled by fsl_soc.c so you shouldn't need
> to change anything to
> make it work in the latest kernel. CONFIG_FSL_SOC was only added to
> lite5200_defconfig recently so
> that may explain why it's not on in your kernel.
>
>
>
> Since the PCF8563 driver is not OF driver only its initaliziation
> code is run but the .probe function
> of the driver is never run. Basically (as far as I can understand)
> the .probe is never run because the
> driver is not an OF driver.
>
> I could convert the PCF8563 driver to OF driver and make it work
> for our puposes but I feel this is
> 1) Wrong
> 2) therefore wasted work.
>
>
> Since the driver must run on non OF platforms then it should not be
> converted. You just need to add a platform_device_register somewhere.
> I don't think fsl_soc.c is the right place since it is not part of an
> freescale SOC.
> You could probably put it in a board specific startup routine.
>
>
>
> What seems to elude me is some glue that glues together the OF
> part of the driver space to the non OF part
> of the driver space.
>
> Any hints or pointers on where to find this glue?
>
> Regards,
> kd
>
> P.S. Kernel is post 2.6.20.
>
> --
> Kári Davíðsson | kari.davidsson@marel.is
> Hugbúnaðargerð | www.marel.com
> Tel: 563-8156 Fax: +354 563 8001
> Iceland
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
[-- Attachment #2: Type: text/html, Size: 7029 bytes --]
^ permalink raw reply
* Re: [PATCH] pseries: don't die if unknown/missing interrupt controller property
From: Olof Johansson @ 2007-07-05 13:37 UTC (permalink / raw)
To: Sonny Rao; +Cc: linuxppc-dev, paulus, miltonm
In-Reply-To: <20070702004937.GA15712@kevlar.boston.burdell.org>
On Sun, Jul 01, 2007 at 08:49:37PM -0400, Sonny Rao wrote:
> The pseries platform does not have a default function for init_IRQ and
> does not install one if it doesn't find or doesn't recognize an
> interrupt controller in the device tree. Currently, the kernel dies
> when it tries to call the NULL init_IRQ() function. Clean that up.
Doesn't it make more sense to make init_IRQ() check that the pointer is
set instead? That'll work for more platforms than just pseries.
-Olof
^ permalink raw reply
* [PATCH] arch/powerpc/kernel/sysfs.c: move NUMA exports
From: Johannes Berg @ 2007-07-05 9:35 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev list
With !CONFIG_NUMA, these are static inlines in the header file so don't
generate exports for them then.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
arch/powerpc/kernel/sysfs.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- wireless-dev.orig/arch/powerpc/kernel/sysfs.c 2007-07-05 11:33:33.135640003 +0200
+++ wireless-dev/arch/powerpc/kernel/sysfs.c 2007-07-05 11:34:04.125640003 +0200
@@ -442,12 +442,14 @@ int sysfs_add_device_to_node(struct sys_
return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
kobject_name(&dev->kobj));
}
+EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
{
struct node *node = &node_devices[nid];
sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
}
+EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
#else
static void register_nodes(void)
@@ -457,9 +459,6 @@ static void register_nodes(void)
#endif
-EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
-EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
-
/* Only valid if CPU is present. */
static ssize_t show_physical_id(struct sys_device *dev, char *buf)
{
^ permalink raw reply
* Re: powerpc stacktrace and lockdep support
From: Johannes Berg @ 2007-07-04 22:40 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linuxppc-dev
In-Reply-To: <20070630085808.GA15386@lst.de>
[-- Attachment #1: Type: text/plain, Size: 820 bytes --]
On Sat, 2007-06-30 at 10:58 +0200, Christoph Hellwig wrote:
> On Thu, Jun 28, 2007 at 06:20:42PM +0200, Johannes Berg wrote:
> > This one doesn't break 32-bit build by simply disabling irqtrace for
> > 32-bit.
>
> This looks really cool to me. I'd love to see this in 2.6.23.
Hmm. Looks like I just found a case where I forgot to trace in some
place:
[ 241.629380] hardirqs last enabled at (1319): [<c0000000000b3718>] .get_page_from_freelist+0x298/0x620
[ 241.629714] hardirqs last disabled at (1320): [<c000000000033690>] .native_hpte_invalidate+0x60/0x320
[ 241.629732] softirqs last enabled at (1282): [<c000000000059e28>] .__do_softirq+0x198/0x1e0
[ 241.629748] softirqs last disabled at (1273): [<c00000000000c7e4>] .do_softirq+0xd4/0xe0
I'll look into it when I get around.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]
^ 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