* [patch 00/35] PA Semi patch set
@ 2007-07-05 17:02 Olof Johansson
2007-07-05 17:02 ` [patch 01/35] pasemi: rename platform Olof Johansson
` (34 more replies)
0 siblings, 35 replies; 46+ messages in thread
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 [flat|nested] 46+ messages in thread
* [patch 01/35] pasemi: rename platform
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-08 23:52 ` Stephen Rothwell
2007-07-05 17:02 ` [patch 02/35] PA Semi EDAC driver Olof Johansson
` (33 subsequent siblings)
34 siblings, 1 reply; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: 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 [flat|nested] 46+ messages in thread
* [patch 02/35] PA Semi EDAC driver
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
2007-07-05 17:02 ` [patch 01/35] pasemi: rename platform Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 03/35] Change powerpc64 ioaddr_t to u_int Olof Johansson
` (32 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Egor Martovetsky
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 [flat|nested] 46+ messages in thread
* [patch 03/35] Change powerpc64 ioaddr_t to u_int
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
2007-07-05 17:02 ` [patch 01/35] pasemi: rename platform Olof Johansson
2007-07-05 17:02 ` [patch 02/35] PA Semi EDAC driver Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 04/35] pasemi_mac: Fix TX interrupt threshold Olof Johansson
` (31 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Paul Mackerras
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 [flat|nested] 46+ messages in thread
* [patch 04/35] pasemi_mac: Fix TX interrupt threshold
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (2 preceding siblings ...)
2007-07-05 17:02 ` [patch 03/35] Change powerpc64 ioaddr_t to u_int Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 05/35] pasemi_mac: Clean TX ring in poll Olof Johansson
` (30 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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 [flat|nested] 46+ messages in thread
* [patch 05/35] pasemi_mac: Clean TX ring in poll
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (3 preceding siblings ...)
2007-07-05 17:02 ` [patch 04/35] pasemi_mac: Fix TX interrupt threshold Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 06/35] pasemi_mac: Abstract out register access Olof Johansson
` (29 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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 [flat|nested] 46+ messages in thread
* [patch 06/35] pasemi_mac: Abstract out register access
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (4 preceding siblings ...)
2007-07-05 17:02 ` [patch 05/35] pasemi_mac: Clean TX ring in poll Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes Olof Johansson
` (28 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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 [flat|nested] 46+ messages in thread
* [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (5 preceding siblings ...)
2007-07-05 17:02 ` [patch 06/35] pasemi_mac: Abstract out register access Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-26 21:25 ` Marian Balakowicz
2007-07-05 17:02 ` [patch 08/35] pasemi_mac: Enable L2 caching of packet headers Olof Johansson
` (27 subsequent siblings)
34 siblings, 1 reply; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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 [flat|nested] 46+ messages in thread
* [patch 08/35] pasemi_mac: Enable L2 caching of packet headers
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (6 preceding siblings ...)
2007-07-05 17:02 ` [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 09/35] pasemi_mac: Simplify memcpy for short receives Olof Johansson
` (26 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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 [flat|nested] 46+ messages in thread
* [patch 09/35] pasemi_mac: Simplify memcpy for short receives
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (7 preceding siblings ...)
2007-07-05 17:02 ` [patch 08/35] pasemi_mac: Enable L2 caching of packet headers Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 10/35] pasemi_mac: Minor performance tweaks Olof Johansson
` (25 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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 [flat|nested] 46+ messages in thread
* [patch 10/35] pasemi_mac: Minor performance tweaks
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (8 preceding siblings ...)
2007-07-05 17:02 ` [patch 09/35] pasemi_mac: Simplify memcpy for short receives Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 11/35] pasemi_mac: Reduce locking when cleaning TX ring Olof Johansson
` (24 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Various minor performance tweaks, do some explicit prefetching of packet
data, etc.
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
@@ -481,6 +481,7 @@ static int pasemi_mac_clean_rx(struct pa
rmb();
dp = &RX_DESC(mac, n);
+ prefetchw(dp);
macrx = dp->macrx;
if (!(macrx & XCT_MACRX_O))
@@ -502,8 +503,10 @@ static int pasemi_mac_clean_rx(struct pa
if (info->dma == dma)
break;
}
+ prefetchw(info);
skb = info->skb;
+ prefetchw(skb);
info->dma = 0;
pci_unmap_single(mac->dma_pdev, dma, skb->len,
@@ -526,9 +529,7 @@ static int pasemi_mac_clean_rx(struct pa
skb_put(skb, len);
- skb->protocol = eth_type_trans(skb, mac->netdev);
-
- if ((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK) {
+ if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
XCT_MACRX_CSUM_S;
@@ -538,6 +539,7 @@ static int pasemi_mac_clean_rx(struct pa
mac->stats.rx_bytes += len;
mac->stats.rx_packets++;
+ skb->protocol = eth_type_trans(skb, mac->netdev);
netif_receive_skb(skb);
dp->ptr = 0;
@@ -569,7 +571,7 @@ static int pasemi_mac_clean_tx(struct pa
for (i = start; i < mac->tx->next_to_use; i++) {
dp = &TX_DESC(mac, i);
- if (!dp || (dp->mactx & XCT_MACTX_O))
+ if (unlikely(dp->mactx & XCT_MACTX_O))
break;
count++;
@@ -957,7 +959,7 @@ static int pasemi_mac_start_tx(struct sk
struct pasemi_mac_txring *txring;
struct pasemi_mac_buffer *info;
struct pas_dma_xct_descr *dp;
- u64 dflags;
+ u64 dflags, mactx, ptr;
dma_addr_t map;
int flags;
@@ -985,6 +987,9 @@ static int pasemi_mac_start_tx(struct sk
if (dma_mapping_error(map))
return NETDEV_TX_BUSY;
+ mactx = dflags | XCT_MACTX_LLEN(skb->len);
+ ptr = XCT_PTR_LEN(skb->len) | XCT_PTR_ADDR(map);
+
txring = mac->tx;
spin_lock_irqsave(&txring->lock, flags);
@@ -1005,12 +1010,11 @@ static int pasemi_mac_start_tx(struct sk
}
}
-
dp = &TX_DESC(mac, txring->next_to_use);
info = &TX_DESC_INFO(mac, txring->next_to_use);
- dp->mactx = dflags | XCT_MACTX_LLEN(skb->len);
- dp->ptr = XCT_PTR_LEN(skb->len) | XCT_PTR_ADDR(map);
+ dp->mactx = mactx;
+ dp->ptr = ptr;
info->dma = map;
info->skb = skb;
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 11/35] pasemi_mac: Reduce locking when cleaning TX ring
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (9 preceding siblings ...)
2007-07-05 17:02 ` [patch 10/35] pasemi_mac: Minor performance tweaks Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 12/35] pasemi_mac: Enable LLTX Olof Johansson
` (23 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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 [flat|nested] 46+ messages in thread
* [patch 12/35] pasemi_mac: Enable LLTX
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (10 preceding siblings ...)
2007-07-05 17:02 ` [patch 11/35] pasemi_mac: Reduce locking when cleaning TX ring Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 13/35] Cleanup marvell phy driver init Olof Johansson
` (22 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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 [flat|nested] 46+ messages in thread
* [patch 13/35] Cleanup marvell phy driver init
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (11 preceding siblings ...)
2007-07-05 17:02 ` [patch 12/35] pasemi_mac: Enable LLTX Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 14/35] Add 88E1112 PHY ID to the marvell driver Olof Johansson
` (21 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Simplify the marvell driver init a bit: Make the supported devices an
array instead of explicitly registering each structure. This makes it
considerably easier to add new devices down the road.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: mainline/drivers/net/phy/marvell.c
===================================================================
--- mainline.orig/drivers/net/phy/marvell.c
+++ mainline/drivers/net/phy/marvell.c
@@ -238,77 +238,71 @@ static int m88e1145_config_init(struct p
return 0;
}
-static struct phy_driver m88e1101_driver = {
- .phy_id = 0x01410c60,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1101",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1111_driver = {
- .phy_id = 0x01410cc0,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1111",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .config_init = &m88e1111_config_init,
- .driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1145_driver = {
- .phy_id = 0x01410cd0,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1145",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_init = &m88e1145_config_init,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
+static struct phy_driver marvell_drivers[] = {
+ {
+ .phy_id = 0x01410c60,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1101",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = 0x01410cc0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1111",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1111_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = 0x01410cd0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1145",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1145_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ }
};
static int __init marvell_init(void)
{
int ret;
+ int i;
- ret = phy_driver_register(&m88e1101_driver);
- if (ret)
- return ret;
-
- ret = phy_driver_register(&m88e1111_driver);
- if (ret)
- goto err1111;
-
- ret = phy_driver_register(&m88e1145_driver);
- if (ret)
- goto err1145;
+ for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
+ ret = phy_driver_register(&marvell_drivers[i]);
- return 0;
+ if (ret) {
+ while (i-- > 0)
+ phy_driver_unregister(&marvell_drivers[i]);
+ return ret;
+ }
+ }
-err1145:
- phy_driver_unregister(&m88e1111_driver);
-err1111:
- phy_driver_unregister(&m88e1101_driver);
- return ret;
+ return 0;
}
static void __exit marvell_exit(void)
{
- phy_driver_unregister(&m88e1101_driver);
- phy_driver_unregister(&m88e1111_driver);
- phy_driver_unregister(&m88e1145_driver);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
+ phy_driver_unregister(&marvell_drivers[i]);
}
module_init(marvell_init);
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 14/35] Add 88E1112 PHY ID to the marvell driver.
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (12 preceding siblings ...)
2007-07-05 17:02 ` [patch 13/35] Cleanup marvell phy driver init Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 15/35] Export HID registers via sysfs Olof Johansson
` (20 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Add 88E1112 PHY ID to the marvell driver.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: mainline/drivers/net/phy/marvell.c
===================================================================
--- mainline.orig/drivers/net/phy/marvell.c
+++ mainline/drivers/net/phy/marvell.c
@@ -252,6 +252,19 @@ static struct phy_driver marvell_drivers
.driver = {.owner = THIS_MODULE,},
},
{
+ .phy_id = 0x01410c90,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1112",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1111_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
.phy_id = 0x01410cc0,
.phy_id_mask = 0xfffffff0,
.name = "Marvell 88E1111",
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 15/35] Export HID registers via sysfs
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (13 preceding siblings ...)
2007-07-05 17:02 ` [patch 14/35] Add 88E1112 PHY ID to the marvell driver Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 16/35] Electra ide platform glue Olof Johansson
` (19 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Export some of the HID registers via sysfs. Useful when debugging.
Index: 2.6.21/arch/powerpc/kernel/sysfs.c
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/sysfs.c
+++ 2.6.21/arch/powerpc/kernel/sysfs.c
@@ -197,6 +197,17 @@ SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3
SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4);
SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5);
+SYSFS_PMCSETUP(hid0, SPRN_HID0);
+SYSFS_PMCSETUP(hid1, SPRN_HID1);
+SYSFS_PMCSETUP(hid4, SPRN_HID4);
+SYSFS_PMCSETUP(hid5, SPRN_HID5);
+SYSFS_PMCSETUP(ima0, SPRN_PA6T_IMA0);
+SYSFS_PMCSETUP(ima1, SPRN_PA6T_IMA1);
+SYSFS_PMCSETUP(ima2, SPRN_PA6T_IMA2);
+SYSFS_PMCSETUP(imaat, SPRN_PA6T_IMAAT);
+SYSFS_PMCSETUP(btcr, SPRN_PA6T_BTCR);
+SYSFS_PMCSETUP(pccr, SPRN_PA6T_PCCR);
+SYSFS_PMCSETUP(rpccr, SPRN_PA6T_RPCCR);
static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
static SYSDEV_ATTR(spurr, 0600, show_spurr, NULL);
@@ -228,6 +239,16 @@ static struct sysdev_attribute pa6t_attr
_SYSDEV_ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3),
_SYSDEV_ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4),
_SYSDEV_ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5),
+ _SYSDEV_ATTR(hid0, 0600, show_hid0, store_hid0),
+ _SYSDEV_ATTR(hid1, 0600, show_hid1, store_hid1),
+ _SYSDEV_ATTR(hid4, 0600, show_hid4, store_hid4),
+ _SYSDEV_ATTR(hid5, 0600, show_hid5, store_hid5),
+ _SYSDEV_ATTR(ima0, 0600, show_ima0, store_ima0),
+ _SYSDEV_ATTR(ima1, 0600, show_ima1, store_ima1),
+ _SYSDEV_ATTR(ima2, 0600, show_ima2, store_ima2),
+ _SYSDEV_ATTR(imaat, 0600, show_imaat, store_imaat),
+ _SYSDEV_ATTR(btcr, 0600, show_btcr, store_btcr),
+ _SYSDEV_ATTR(pccr, 0600, show_pccr, store_pccr),
};
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 16/35] Electra ide platform glue
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (14 preceding siblings ...)
2007-07-05 17:02 ` [patch 15/35] Export HID registers via sysfs Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 17/35] CF driver for PA Semi Electra Olof Johansson
` (18 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Glue code to hook up the pata_platform on the PA Semi Electra eval board.
CFE sets up device tree entries for the IDE interface, with device type
'ide' and compatible field 'electra-ide'.
We unfortunately need to modify the resources before calling the generic
platform driver, since the device tree only has one register window in
it and the driver expects two. Adding this as an of_platform driver
instead doesn't give us any benefit, it just adds one more layer of
register/probe functions.
Since CONFIG_PATA_PLATFORM depends on CONFIG_EMBEDDED, add that as a
default for PPC_PASEMI.
Signed-off-by: Olof Johansson <olof@lixom.net>
Index: 2.6.21/arch/powerpc/platforms/pasemi/Makefile
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/Makefile
+++ 2.6.21/arch/powerpc/platforms/pasemi/Makefile
@@ -1,3 +1,4 @@
obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o
obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o
+obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o
Index: 2.6.21/arch/powerpc/platforms/pasemi/electra_ide.c
===================================================================
--- /dev/null
+++ 2.6.21/arch/powerpc/platforms/pasemi/electra_ide.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 PA Semi, Inc
+ *
+ * Maintained by: Olof Johansson <olof@lixom.net>
+ *
+ * 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/platform_device.h>
+
+#include <asm/prom.h>
+#include <asm/system.h>
+
+/* The electra IDE interface is incredibly simple: Just a device on the localbus
+ * with interrupts hooked up to one of the GPIOs. The device tree contains the
+ * address window and interrupt mappings already, and the pata_platform driver handles
+ * the rest. We just need to hook the two up.
+ */
+
+#define MAX_IFS 4 /* really, we have only one */
+
+static struct platform_device *pdevs[MAX_IFS];
+
+static int __devinit electra_ide_init(void)
+{
+ struct device_node *np;
+ struct resource r[3];
+ int ret = 0;
+ int i;
+
+ np = of_find_compatible_node(NULL, "ide", "electra-ide");
+ i = 0;
+
+ while (np && i < MAX_IFS) {
+ memset(r, 0, sizeof(r));
+
+ /* pata_platform wants two address ranges: one for the base registers,
+ * another for the control (altstatus). It's located at offset 0x3f6 in
+ * the window, but the device tree only has one large register window
+ * that covers both ranges. So we need to split it up by hand here:
+ */
+
+ ret = of_address_to_resource(np, 0, &r[0]);
+ if (ret)
+ goto out;
+ ret = of_address_to_resource(np, 0, &r[1]);
+ if (ret)
+ goto out;
+
+ r[1].start += 0x3f6;
+ r[0].end = r[1].start-1;
+
+ r[2].start = irq_of_parse_and_map(np, 0);
+ r[2].end = irq_of_parse_and_map(np, 0);
+ r[2].flags = IORESOURCE_IRQ;
+
+ pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n",
+ r[0].start, r[1].start, r[2].start);
+ pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3);
+ if (IS_ERR(pdevs[i])) {
+ ret = PTR_ERR(pdevs[i]);
+ pdevs[i] = NULL;
+ goto out;
+ }
+ np = of_find_compatible_node(np, "ide", "electra-ide");
+ }
+out:
+ return ret;
+}
+module_init(electra_ide_init);
+
+static void __devexit electra_ide_exit(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_IFS; i++)
+ if (pdevs[i])
+ platform_device_unregister(pdevs[i]);
+}
+module_exit(electra_ide_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
+MODULE_DESCRIPTION("PA Semi Electra IDE driver");
Index: 2.6.21/arch/powerpc/platforms/pasemi/Kconfig
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/Kconfig
+++ 2.6.21/arch/powerpc/platforms/pasemi/Kconfig
@@ -6,6 +6,7 @@ config PPC_PASEMI
select PPC_UDBG_16550
select GENERIC_TBSYNC
select PPC_NATIVE
+ select EMBEDDED
help
This option enables support for PA Semi's PWRficient line
of SoC processors, including PA6T-1682M
@@ -26,4 +27,13 @@ config PPC_PASEMI_MDIO
help
Driver for MDIO via GPIO on PWRficient platforms
+config ELECTRA_IDE
+ tristate "Electra IDE driver"
+ default y
+ depends on PPC_PASEMI && ATA
+ select PATA_PLATFORM
+ help
+ This includes driver support for the Electra on-board IDE
+ interface.
+
endmenu
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 17/35] CF driver for PA Semi Electra
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (15 preceding siblings ...)
2007-07-05 17:02 ` [patch 16/35] Electra ide platform glue Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 18/35] Spread IRQs among cpus by default Olof Johansson
` (17 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
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>
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);
@@ -239,7 +295,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 [flat|nested] 46+ messages in thread
* [patch 18/35] Spread IRQs among cpus by default
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (16 preceding siblings ...)
2007-07-05 17:02 ` [patch 17/35] CF driver for PA Semi Electra Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 19/35] Improve machine check output Olof Johansson
` (16 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Spread IRQs between the two cores on our openpic. Without this,
they get delivered to cpu 0 as long as it's available.
This needs a bit more cleanup -- it needs a flag so it can coexist
with other implementations.
Index: 2.6.21/arch/powerpc/sysdev/mpic.c
===================================================================
--- 2.6.21.orig/arch/powerpc/sysdev/mpic.c
+++ 2.6.21/arch/powerpc/sysdev/mpic.c
@@ -1191,6 +1191,11 @@ void __init mpic_init(struct mpic *mpic)
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
| MPIC_GREG_GCONF_8259_PTHROU_DIS);
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+ mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+ | 0x10000000);
+
+
/* Set current processor priority to 0 */
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
}
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 19/35] Improve machine check output
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (17 preceding siblings ...)
2007-07-05 17:02 ` [patch 18/35] Spread IRQs among cpus by default Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 20/35] Remove idle_spin function pointer Olof Johansson
` (15 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
The name says it all. Try to provide more good info on machine checks.
Index: 2.6.21/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/setup.c
+++ 2.6.21/arch/powerpc/platforms/pasemi/setup.c
@@ -40,6 +40,7 @@
#include "pasemi.h"
static void __iomem *reset_reg;
+void __iomem *mem_errsta0, *mem_errsta1;
DEFINE_SPINLOCK(lbi_lock);
@@ -102,6 +103,9 @@ void __init pas_setup_arch(void)
reset_reg = ioremap(0xfc101100, 4);
pasemi_idle_init();
+
+ mem_errsta0 = ioremap(0xe0020730, 4);
+ mem_errsta1 = ioremap(0xe0028730, 4);
}
static __init void pas_init_IRQ(void)
@@ -164,6 +168,8 @@ static int pas_machine_check_handler(str
{
int cpu = smp_processor_id();
unsigned long srr0, srr1, dsisr;
+ int dump_slb = 0;
+ int dump_memsta = 0;
srr0 = regs->nip;
srr1 = regs->msr;
@@ -177,25 +183,57 @@ static int pas_machine_check_handler(str
printk(KERN_ERR "Signalled by SDC\n");
if (srr1 & 0x100000) {
printk(KERN_ERR "Load/Store detected error:\n");
- if (dsisr & 0x8000)
+ if (dsisr & 0x8000) {
printk(KERN_ERR "D-cache ECC double-bit error or bus error\n");
+ dump_memsta = 1;
+ }
if (dsisr & 0x4000)
printk(KERN_ERR "LSU snoop response error\n");
- if (dsisr & 0x2000)
+ if (dsisr & 0x2000) {
printk(KERN_ERR "MMU SLB multi-hit or invalid B field\n");
+ dump_slb = 1;
+ }
if (dsisr & 0x1000)
printk(KERN_ERR "Recoverable Duptags\n");
- if (dsisr & 0x800)
+ if (dsisr & 0x800) {
printk(KERN_ERR "Recoverable D-cache parity error count overflow\n");
+ dump_memsta = 1;
+ }
if (dsisr & 0x400)
printk(KERN_ERR "TLB parity error count overflow\n");
}
if (srr1 & 0x80000)
printk(KERN_ERR "Bus Error\n");
- if (srr1 & 0x40000)
+ if (srr1 & 0x40000) {
printk(KERN_ERR "I-side SLB multiple hit\n");
- if (srr1 & 0x20000)
+ dump_slb = 1;
+ }
+ if (srr1 & 0x20000) {
printk(KERN_ERR "I-cache parity error hit\n");
+ dump_memsta = 1;
+ }
+
+ if (dump_memsta) {
+ unsigned int errsta;
+ errsta = in_le32(mem_errsta0);
+ printk("mc0_mcdebug_errsta: 0x%08x (MER %d SER %d)\n",
+ errsta, !!(errsta & 0x2), !!(errsta & 0x1));
+ errsta = in_le32(mem_errsta1);
+ printk("mc1_mcdebug_errsta: 0x%08x (MER %d SER %d)\n",
+ errsta, !!(errsta & 0x2), !!(errsta & 0x1));
+ }
+
+ if (dump_slb) {
+ unsigned long slb_e, slb_v;
+ int i;
+ printk("slb contents:\n");
+ for (i = 0; i < SLB_NUM_ENTRIES; i++) {
+ asm volatile("slbmfee %0,%1" : "=r" (slb_e) : "r" (i));
+ asm volatile("slbmfev %0,%1" : "=r" (slb_v) : "r" (i));
+
+ printk("%02d %016lx %016lx\n", i, slb_e, slb_v);
+ }
+ }
/* SRR1[62] is from MSR[62] if recoverable, so pass that back */
return !!(srr1 & 0x2);
Index: 2.6.21/arch/powerpc/kernel/traps.c
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/traps.c
+++ 2.6.21/arch/powerpc/kernel/traps.c
@@ -378,6 +378,7 @@ void machine_check_exception(struct pt_r
if (check_io_access(regs))
return;
+#if defined(CONFIG_PPC32)
#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
if (reason & ESR_IMCP) {
printk("Instruction");
@@ -494,6 +495,7 @@ void machine_check_exception(struct pt_r
printk("Unknown values in msr\n");
}
#endif /* CONFIG_4xx */
+#endif /* CONFIG_PPC32 */
/*
* Optional platform-provided routine to print out
Index: 2.6.21/include/asm-powerpc/reg.h
===================================================================
--- 2.6.21.orig/include/asm-powerpc/reg.h
+++ 2.6.21/include/asm-powerpc/reg.h
@@ -532,6 +532,20 @@
#define SPRN_PA6T_PMC4 791
#define SPRN_PA6T_PMC5 792
+#define SPRN_PA6T_IER 0x3d5 /* Icache Error Register */
+#define SPRN_PA6T_DER 0x3d6 /* Dcache Error Register */
+#define SPRN_PA6T_BAR 0x35e /* BIU Error Address Register */
+#define SPRN_PA6T_MER 0x351 /* MMU Error Register */
+
+#define SPRN_PA6T_PCCR 1019
+#define SPRN_PA6T_RPCCR 1021
+#define SPRN_PA6T_IMAAT 979
+#define SPRN_PA6T_IMA0 880
+#define SPRN_PA6T_IMA1 881
+#define SPRN_PA6T_IMA2 882
+#define SPRN_PA6T_BTCR 978
+
+
#else /* 32-bit */
#define SPRN_MMCR0 952 /* Monitor Mode Control Register 0 */
#define MMCR0_FC 0x80000000UL /* freeze counters */
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 20/35] Remove idle_spin function pointer
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (18 preceding siblings ...)
2007-07-05 17:02 ` [patch 19/35] Improve machine check output Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 21/35] Use MSR_PMM to disable profiling of the idle loop Olof Johansson
` (14 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Remove idle_spin function pointer, since it just seems to make the idle
loop run hotter by doing bl/blr.
Index: 2.6.21/arch/powerpc/platforms/pasemi/idle.c
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/idle.c
+++ 2.6.21/arch/powerpc/platforms/pasemi/idle.c
@@ -34,7 +34,7 @@ struct sleep_mode {
};
static struct sleep_mode modes[] = {
- { .name = "spin", .entry = &idle_spin },
+ { .name = "spin", .entry = NULL },
{ .name = "doze", .entry = &idle_doze },
};
Index: 2.6.21/arch/powerpc/platforms/pasemi/powersave.S
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/powersave.S
+++ 2.6.21/arch/powerpc/platforms/pasemi/powersave.S
@@ -49,9 +49,6 @@ _doze:
b .
-_GLOBAL(idle_spin)
- blr
-
_GLOBAL(idle_doze)
LOAD_REG_ADDR(r3, _doze)
b sleep_common
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 21/35] Use MSR_PMM to disable profiling of the idle loop
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (19 preceding siblings ...)
2007-07-05 17:02 ` [patch 20/35] Remove idle_spin function pointer Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 22/35] Work around errata 4111 Olof Johansson
` (13 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Use MSR_PMM to disable performance monitor counting while in idle,
instead of using the CTRL register like on the IBM implementation.
This needs further cleanup. It should be possible to switch over the
default behaviour to MSR_PMM on IBM hardware too.
Index: 2.6.21/arch/powerpc/kernel/process.c
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/process.c
+++ 2.6.21/arch/powerpc/kernel/process.c
@@ -972,13 +972,18 @@ void ppc64_runlatch_on(void)
{
unsigned long ctrl;
- if (cpu_has_feature(CPU_FTR_CTRL) && !test_thread_flag(TIF_RUNLATCH)) {
+// if (cpu_has_feature(CPU_FTR_CTRL) && !test_thread_flag(TIF_RUNLATCH)) {
+ if (!test_thread_flag(TIF_RUNLATCH)) {
HMT_medium();
ctrl = mfspr(SPRN_CTRLF);
ctrl |= CTRL_RUNLATCH;
mtspr(SPRN_CTRLT, ctrl);
+ ctrl = mfmsr();
+ ctrl &= ~MSR_PMM;
+ mtmsrd(ctrl);
+
set_thread_flag(TIF_RUNLATCH);
}
}
@@ -987,7 +992,8 @@ void ppc64_runlatch_off(void)
{
unsigned long ctrl;
- if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) {
+// if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) {
+ if (test_thread_flag(TIF_RUNLATCH)) {
HMT_medium();
clear_thread_flag(TIF_RUNLATCH);
@@ -995,6 +1001,10 @@ void ppc64_runlatch_off(void)
ctrl = mfspr(SPRN_CTRLF);
ctrl &= ~CTRL_RUNLATCH;
mtspr(SPRN_CTRLT, ctrl);
+
+ ctrl = mfmsr();
+ ctrl |= MSR_PMM;
+ mtmsrd(ctrl);
}
}
#endif
Index: 2.6.21/arch/powerpc/oprofile/op_model_pa6t.c
===================================================================
--- 2.6.21.orig/arch/powerpc/oprofile/op_model_pa6t.c
+++ 2.6.21/arch/powerpc/oprofile/op_model_pa6t.c
@@ -109,6 +109,8 @@ static void pa6t_reg_setup(struct op_cou
pr_debug("turned off counter %u\n", pmc);
}
+ sys->mmcr0 |= PA6T_MMCR0_FCM1;
+
if (sys->enable_kernel)
sys->mmcr0 |= PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN;
else
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 22/35] Work around errata 4111
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (20 preceding siblings ...)
2007-07-05 17:02 ` [patch 21/35] Use MSR_PMM to disable profiling of the idle loop Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 23/35] Work around UART erratas Olof Johansson
` (12 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Workaround for errata 4111: IPI registers of the OpenPIC don't read back
right.
Also, reading back regular irq setup registers is broken, so keep a
software copy.
Index: mainline/arch/powerpc/sysdev/mpic.c
===================================================================
--- mainline.orig/arch/powerpc/sysdev/mpic.c
+++ mainline/arch/powerpc/sysdev/mpic.c
@@ -187,6 +187,9 @@ static inline void _mpic_write(enum mpic
static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
{
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ return mpic->ipi_reg_shadow[ipi];
+#else
enum mpic_reg_type type = mpic->reg_type;
unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
(ipi * MPIC_INFO(GREG_IPI_STRIDE));
@@ -194,6 +197,7 @@ static inline u32 _mpic_ipi_read(struct
if ((mpic->flags & MPIC_BROKEN_IPI) && type == mpic_access_mmio_le)
type = mpic_access_mmio_be;
return _mpic_read(type, &mpic->gregs, offset);
+#endif
}
static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
@@ -202,6 +206,9 @@ static inline void _mpic_ipi_write(struc
(ipi * MPIC_INFO(GREG_IPI_STRIDE));
_mpic_write(mpic->reg_type, &mpic->gregs, offset, value);
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ mpic->ipi_reg_shadow[ipi] = value;
+#endif
}
static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
@@ -213,6 +220,13 @@ static inline u32 _mpic_cpu_read(struct
return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg);
}
+static inline void _mpic_cpu0_write(struct mpic *mpic, unsigned int reg, u32 value)
+{
+ unsigned int cpu = 0;
+
+ _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value);
+}
+
static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
{
unsigned int cpu = 0;
@@ -228,8 +242,13 @@ static inline u32 _mpic_irq_read(struct
unsigned int isu = src_no >> mpic->isu_shift;
unsigned int idx = src_no & mpic->isu_mask;
- return _mpic_read(mpic->reg_type, &mpic->isus[isu],
- reg + (idx * MPIC_INFO(IRQ_STRIDE)));
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ if (reg == 0)
+ return mpic->isu_reg0_shadow[idx];
+ else
+#endif
+ return _mpic_read(mpic->reg_type, &mpic->isus[isu],
+ reg + (idx * MPIC_INFO(IRQ_STRIDE)));
}
static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
@@ -240,6 +259,11 @@ static inline void _mpic_irq_write(struc
_mpic_write(mpic->reg_type, &mpic->isus[isu],
reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
+
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ if (reg == 0)
+ mpic->isu_reg0_shadow[idx] = value;
+#endif
}
#define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r))
@@ -1157,6 +1181,8 @@ void __init mpic_assign_isu(struct mpic
MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
if ((isu_first + mpic->isu_size) > mpic->num_sources)
mpic->num_sources = isu_first + mpic->isu_size;
+
+ printk("num_sources %d\n", mpic->num_sources);
}
void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
@@ -1394,7 +1420,7 @@ void mpic_send_ipi(unsigned int ipi_no,
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
#endif
- mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
+ _mpic_cpu0_write(mpic, MPIC_INFO(CPU_IPI_DISPATCH_0) +
ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
}
Index: mainline/include/asm-powerpc/mpic.h
===================================================================
--- mainline.orig/include/asm-powerpc/mpic.h
+++ mainline/include/asm-powerpc/mpic.h
@@ -306,6 +306,11 @@ struct mpic
unsigned long *hwirq_bitmap;
#endif
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ u32 ipi_reg_shadow[4];
+ u32 isu_reg0_shadow[MPIC_MAX_IRQ_SOURCES];
+#endif
+
/* link */
struct mpic *next;
Index: mainline/arch/powerpc/platforms/Kconfig
===================================================================
--- mainline.orig/arch/powerpc/platforms/Kconfig
+++ mainline/arch/powerpc/platforms/Kconfig
@@ -121,6 +121,11 @@ config MPIC_U3_HT_IRQS
depends on PPC_MAPLE
default y
+config MPIC_BROKEN_REGREAD
+ bool
+ depends on PPC_PASEMI
+ default y
+
config IBMVIO
depends on PPC_PSERIES || PPC_ISERIES
bool
Index: mainline/arch/powerpc/platforms/pasemi/Kconfig
===================================================================
--- mainline.orig/arch/powerpc/platforms/pasemi/Kconfig
+++ mainline/arch/powerpc/platforms/pasemi/Kconfig
@@ -6,6 +6,7 @@ config PPC_PASEMI
select PPC_UDBG_16550
select PPC_NATIVE
select EMBEDDED
+ select MPIC_BROKEN_REGREAD
help
This option enables support for PA Semi's PWRficient line
of SoC processors, including PA6T-1682M
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 23/35] Work around UART erratas
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (21 preceding siblings ...)
2007-07-05 17:02 ` [patch 22/35] Work around errata 4111 Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 24/35] Work around errata 4628 Olof Johansson
` (11 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Support for, and workarounds for various problems with our UART.
This needs further cleanup at some point.
Index: mainline/arch/powerpc/kernel/udbg_16550.c
===================================================================
--- mainline.orig/arch/powerpc/kernel/udbg_16550.c
+++ mainline/arch/powerpc/kernel/udbg_16550.c
@@ -86,9 +86,9 @@ void udbg_init_uart(void __iomem *compor
unsigned int dll, base_bauds;
if (clock == 0)
- clock = 1843200;
+ clock = 133333333;
if (speed == 0)
- speed = 9600;
+ speed = 115200;
base_bauds = clock / 16;
dll = base_bauds / speed;
@@ -143,7 +143,7 @@ unsigned int udbg_probe_uart_speed(void
/* sanity check */
if (speed < 0 || speed > (clock / 16))
- speed = 9600;
+ speed = 115200;
return speed;
}
Index: mainline/include/asm-powerpc/serial.h
===================================================================
--- mainline.orig/include/asm-powerpc/serial.h
+++ mainline/include/asm-powerpc/serial.h
@@ -13,7 +13,7 @@
*/
/* Default baud base if not found in device-tree */
-#define BASE_BAUD ( 1843200 / 16 )
+#define BASE_BAUD ( 133333333 / 16 )
#ifdef CONFIG_PPC_UDBG_16550
extern void find_legacy_serial_ports(void);
Index: mainline/drivers/serial/8250.c
===================================================================
--- mainline.orig/drivers/serial/8250.c
+++ mainline/drivers/serial/8250.c
@@ -173,7 +173,7 @@ static const struct serial8250_config ua
.name = "16550A",
.fifo_size = 16,
.tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
.flags = UART_CAP_FIFO,
},
[PORT_CIRRUS] = {
@@ -1242,7 +1242,7 @@ static void serial8250_start_tx(struct u
if ((up->port.type == PORT_RM9000) ?
(lsr & UART_LSR_THRE &&
(iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
- (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT))
+ (lsr & UART_LSR_TEMT && !(iir & UART_IIR_NO_INT)))
transmit_chars(up);
}
}
@@ -1465,7 +1465,7 @@ static irqreturn_t serial8250_interrupt(
up = list_entry(l, struct uart_8250_port, list);
iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT)) {
+ if ((iir & UART_IIR_NO_INT)) {
serial8250_handle_port(up);
handled = 1;
@@ -1583,7 +1583,7 @@ static void serial8250_timeout(unsigned
unsigned int iir;
iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT))
+ if ((iir & UART_IIR_NO_INT))
serial8250_handle_port(up);
mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
}
@@ -1610,14 +1610,14 @@ static void serial8250_backup_timeout(un
* the "Diva" UART used on the management processor on many HP
* ia64 and parisc boxes.
*/
- if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+ if (!(iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
(!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
(serial_in(up, UART_LSR) & UART_LSR_THRE)) {
- iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
- iir |= UART_IIR_THRI;
+ iir &= ~UART_IIR_ID;
+ iir |= UART_IIR_THRI | UART_IIR_NO_INT;
}
- if (!(iir & UART_IIR_NO_INT))
+ if ((iir & UART_IIR_NO_INT))
serial8250_handle_port(up);
if (is_real_interrupt(up->port.irq))
@@ -1826,7 +1826,7 @@ static int serial8250_startup(struct uar
* If the interrupt is not reasserted, setup a timer to
* kick the UART on a regular basis.
*/
- if (iir & UART_IIR_NO_INT) {
+ if (!(iir & UART_IIR_NO_INT)) {
pr_debug("ttyS%d - using backup timer\n", port->line);
up->timer.function = serial8250_backup_timeout;
up->timer.data = (unsigned long)up;
@@ -1876,7 +1876,7 @@ static int serial8250_startup(struct uar
iir = serial_in(up, UART_IIR);
serial_outp(up, UART_IER, 0);
- if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+ if (lsr & UART_LSR_TEMT && !(iir & UART_IIR_NO_INT)) {
if (!(up->bugs & UART_BUG_TXEN)) {
up->bugs |= UART_BUG_TXEN;
pr_debug("ttyS%d - enabling bad tx status workarounds\n",
Index: mainline/drivers/serial/8250_pci.c
===================================================================
--- mainline.orig/drivers/serial/8250_pci.c
+++ mainline/drivers/serial/8250_pci.c
@@ -984,6 +984,7 @@ enum pci_board_num_t {
pbn_exar_XR17C152,
pbn_exar_XR17C154,
pbn_exar_XR17C158,
+ pbn_pasemi_1682M,
};
/*
@@ -1511,6 +1512,14 @@ static struct pciserial_board pci_boards
.base_baud = 921600,
.uart_offset = 0x200,
},
+ /*
+ * PA Semi PWRficient PA6T-1682M on-chip UART
+ */
+ [pbn_pasemi_1682M] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 8333333,
+ },
};
/*
@@ -2402,6 +2411,13 @@ static struct pci_device_id serial_pci_t
PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8,
0, 0, pbn_b2_8_921600 },
/*
+ * PA Semi PA6T-1682M on-chip UART
+ */
+ { PCI_VENDOR_ID_PASEMI, 0xa004,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_pasemi_1682M },
+
+ /*
* These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
*/
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 24/35] Work around errata 4628
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (22 preceding siblings ...)
2007-07-05 17:02 ` [patch 23/35] Work around UART erratas Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 25/35] Work around errata 4025 Olof Johansson
` (10 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Errata 4628 causes lockups during table walks that are recovered from
when a ptesync is received. So, issue a ptesync every timer interrupt,
and for CPUs that have not yet spun up, at regular intervals. This seems
sufficient to avoid hitting it.
Index: 2.6.21/arch/powerpc/kernel/head_64.S
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/head_64.S
+++ 2.6.21/arch/powerpc/kernel/head_64.S
@@ -123,10 +123,22 @@ _GLOBAL(__secondary_hold)
std r24,__secondary_hold_acknowledge@l(0)
sync
+#ifdef CONFIG_SMP
/* All secondary cpus wait here until told to start. */
100: ld r4,__secondary_hold_spinloop@l(0)
cmpdi 0,r4,1
bne 100b
+#else
+ lis r3, 0x40
+ mtctr r3
+100: bdnz .
+ ptesync
+ ptesync
+ lis r3, 0x40
+ mtctr r3
+ b 100b
+
+#endif
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)
@@ -1582,16 +1594,32 @@ _GLOBAL(generic_secondary_smp_init)
2: mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */
/* From now on, r24 is expected to be logical cpuid */
mr r24,r5
+
+ lis r23, 0x40
+ mtctr r23
+
3: HMT_LOW
lbz r23,PACAPROCSTART(r13) /* Test if this processor should */
- /* start. */
- sync
#ifndef CONFIG_SMP
b 3b /* Never go on non-SMP */
#else
cmpwi 0,r23,0
- beq 3b /* Loop until told to go */
+ bne 5f /* Loop until told to go */
+ /* start. */
+ isync
+
+4: bdnz 3b
+ ptesync
+ isync
+ sync
+ ptesync
+ lis r23, 0x40
+ mtctr r23
+ b 3b
+
+5:
+
/* See if we need to call a cpu state restore handler */
LOAD_REG_IMMEDIATE(r23, cur_cpu_spec)
Index: 2.6.21/arch/powerpc/kernel/time.c
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/time.c
+++ 2.6.21/arch/powerpc/kernel/time.c
@@ -619,6 +619,8 @@ void timer_interrupt(struct pt_regs * re
unsigned long ticks;
u64 tb_next_jiffy;
+ asm("ptesync");
+
#ifdef CONFIG_PPC32
if (atomic_read(&ppc_n_lost_interrupts) != 0)
do_IRQ(regs);
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 25/35] Work around errata 4025
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (23 preceding siblings ...)
2007-07-05 17:02 ` [patch 24/35] Work around errata 4628 Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:02 ` [patch 26/35] Work around errata 4713 Olof Johansson
` (9 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Errata 4025 workaround: A SLB load can in some cases be corrupted. As a workaround,
insert an instruction with sync side effects after the load (in this case it's the
mtmsrd).
Index: 2.6.21/arch/powerpc/kernel/entry_64.S
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/entry_64.S
+++ 2.6.21/arch/powerpc/kernel/entry_64.S
@@ -395,6 +395,8 @@ BEGIN_FTR_SECTION
slbie r6
slbie r6 /* Workaround POWER5 < DD2.1 issue */
slbmte r7,r0
+ mfmsr r7 /* PA6T Ax workaround */
+ mtmsrd r7
isync
2:
Index: 2.6.21/arch/powerpc/mm/slb.c
===================================================================
--- 2.6.21.orig/arch/powerpc/mm/slb.c
+++ 2.6.21/arch/powerpc/mm/slb.c
@@ -79,7 +79,7 @@ static inline void create_shadowed_slbe(
slb_shadow_update(mk_esid_data(ea, entry), mk_vsid_data(ea, flags),
entry);
- asm volatile("slbmte %0,%1" :
+ asm volatile("slbmte %0,%1 ; mfmsr %0 ; mtmsrd %0" :
: "r" (mk_vsid_data(ea, flags)),
"r" (mk_esid_data(ea, entry))
: "memory" );
@@ -113,8 +113,14 @@ void slb_flush_and_rebolt(void)
"slbia\n"
/* Slot 1 - first VMALLOC segment */
"slbmte %0,%1\n"
+ /* PA6T Ax workaround */
+ "mfmsr %0\n"
+ "mtmsrd %0\n"
/* Slot 2 - kernel stack */
"slbmte %2,%3\n"
+ /* PA6T Ax workaround */
+ "mfmsr %0\n"
+ "mtmsrd %0\n"
"isync"
:: "r"(mk_vsid_data(VMALLOC_START, vflags)),
"r"(mk_esid_data(VMALLOC_START, 1)),
Index: 2.6.21/arch/powerpc/mm/slb_low.S
===================================================================
--- 2.6.21.orig/arch/powerpc/mm/slb_low.S
+++ 2.6.21/arch/powerpc/mm/slb_low.S
@@ -221,6 +221,8 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISER
* we enter with and the rfid we exit with are context synchronizing.
*/
slbmte r11,r10
+ mfmsr r3
+ mtmsrd r3
/* we're done for kernel addresses */
crclr 4*cr0+eq /* set result to "success" */
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 26/35] Work around errata 4713
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (24 preceding siblings ...)
2007-07-05 17:02 ` [patch 25/35] Work around errata 4025 Olof Johansson
@ 2007-07-05 17:02 ` Olof Johansson
2007-07-05 17:03 ` [patch 27/35] Work around errata 4290 Olof Johansson
` (8 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:02 UTC (permalink / raw)
To: linuxppc-dev
Workaround for errata 4713: Concurrent access to some of the devices
in the SOC will result in a bus hang.
To avoid this, we introduce the lbi_lock, and grab it in the drivers
in question. Not a pretty solution, but adequate for now.
Index: mainline/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- mainline.orig/arch/powerpc/platforms/pasemi/setup.c
+++ mainline/arch/powerpc/platforms/pasemi/setup.c
@@ -42,6 +42,8 @@
static void __iomem *reset_reg;
void __iomem *mem_errsta0, *mem_errsta1;
+DEFINE_SPINLOCK(lbi_lock);
+
static void pas_restart(char *cmd)
{
printk("Restarting...\n");
Index: mainline/drivers/i2c/busses/i2c-pasemi.c
===================================================================
--- mainline.orig/drivers/i2c/busses/i2c-pasemi.c
+++ mainline/drivers/i2c/busses/i2c-pasemi.c
@@ -59,17 +59,24 @@ struct pasemi_smbus {
#define CLK_100K_DIV 84
#define CLK_400K_DIV 21
+extern spinlock_t lbi_lock;
+
static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
{
+ int flags;
dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n",
smbus->base + reg, val);
+ spin_lock_irqsave(&lbi_lock, flags);
outl(val, smbus->base + reg);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
static inline int reg_read(struct pasemi_smbus *smbus, int reg)
{
- int ret;
+ int ret, flags;
+ spin_lock_irqsave(&lbi_lock, flags);
ret = inl(smbus->base + reg);
+ spin_unlock_irqrestore(&lbi_lock, flags);
dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n",
smbus->base + reg, ret);
return ret;
Index: mainline/drivers/serial/8250.c
===================================================================
--- mainline.orig/drivers/serial/8250.c
+++ mainline/drivers/serial/8250.c
@@ -342,39 +342,51 @@ static inline int map_8250_out_reg(struc
#endif
+extern spinlock_t lbi_lock;
+
static unsigned int serial_in(struct uart_8250_port *up, int offset)
{
unsigned int tmp;
+ int ret, flags;
offset = map_8250_in_reg(up, offset) << up->port.regshift;
+ spin_lock_irqsave(&lbi_lock, flags);
switch (up->port.iotype) {
case UPIO_HUB6:
outb(up->port.hub6 - 1 + offset, up->port.iobase);
- return inb(up->port.iobase + 1);
+ ret = inb(up->port.iobase + 1);
+ break;
case UPIO_MEM:
case UPIO_DWAPB:
- return readb(up->port.membase + offset);
+ ret = readb(up->port.membase + offset);
+ break;
case UPIO_RM9000:
case UPIO_MEM32:
- return readl(up->port.membase + offset);
+ ret = readl(up->port.membase + offset);
+ break;
#ifdef CONFIG_SERIAL_8250_AU1X00
case UPIO_AU:
- return __raw_readl(up->port.membase + offset);
+ ret = __raw_readl(up->port.membase + offset);
+ break;
#endif
case UPIO_TSI:
if (offset == UART_IIR) {
tmp = readl(up->port.membase + (UART_IIR & ~3));
- return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+ ret = (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
} else
- return readb(up->port.membase + offset);
+ ret = readb(up->port.membase + offset);
+ break;
default:
- return inb(up->port.iobase + offset);
+ ret = inb(up->port.iobase + offset);
+ break;
}
+ spin_unlock_irqrestore(&lbi_lock, flags);
+ return ret;
}
static void
@@ -382,8 +394,10 @@ serial_out(struct uart_8250_port *up, in
{
/* Save the offset before it's remapped */
int save_offset = offset;
+ int flags;
offset = map_8250_out_reg(up, offset) << up->port.regshift;
+ spin_lock_irqsave(&lbi_lock, flags);
switch (up->port.iotype) {
case UPIO_HUB6:
outb(up->port.hub6 - 1 + offset, up->port.iobase);
@@ -424,6 +438,7 @@ serial_out(struct uart_8250_port *up, in
default:
outb(value, up->port.iobase + offset);
}
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
static void
@@ -1239,10 +1254,7 @@ static void serial8250_start_tx(struct u
unsigned char lsr, iir;
lsr = serial_in(up, UART_LSR);
iir = serial_in(up, UART_IIR) & 0x0f;
- if ((up->port.type == PORT_RM9000) ?
- (lsr & UART_LSR_THRE &&
- (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) :
- (lsr & UART_LSR_TEMT && !(iir & UART_IIR_NO_INT)))
+ if (lsr & UART_LSR_TEMT && !(iir & UART_IIR_NO_INT))
transmit_chars(up);
}
}
@@ -1879,7 +1891,7 @@ static int serial8250_startup(struct uar
if (lsr & UART_LSR_TEMT && !(iir & UART_IIR_NO_INT)) {
if (!(up->bugs & UART_BUG_TXEN)) {
up->bugs |= UART_BUG_TXEN;
- pr_debug("ttyS%d - enabling bad tx status workarounds\n",
+ printk("ttyS%d - enabling bad tx status workarounds\n",
port->line);
}
} else {
Index: mainline/arch/powerpc/kernel/iomap.c
===================================================================
--- mainline.orig/arch/powerpc/kernel/iomap.c
+++ mainline/arch/powerpc/kernel/iomap.c
@@ -8,29 +8,51 @@
#include <linux/mm.h>
#include <asm/io.h>
+extern spinlock_t lbi_lock;
+
/*
* Here comes the ppc64 implementation of the IOMAP
* interfaces.
*/
unsigned int ioread8(void __iomem *addr)
{
- return readb(addr);
+ int ret, flags;
+ spin_lock_irqsave(&lbi_lock, flags);
+ ret = readb(addr);
+ spin_unlock_irqrestore(&lbi_lock, flags);
+ return ret;
}
unsigned int ioread16(void __iomem *addr)
{
- return readw(addr);
+ int ret, flags;
+ spin_lock_irqsave(&lbi_lock, flags);
+ ret = readw(addr);
+ spin_unlock_irqrestore(&lbi_lock, flags);
+ return ret;
}
unsigned int ioread16be(void __iomem *addr)
{
- return in_be16(addr);
+ int ret, flags;
+ spin_lock_irqsave(&lbi_lock, flags);
+ ret = in_be16(addr);
+ spin_unlock_irqrestore(&lbi_lock, flags);
+ return ret;
}
unsigned int ioread32(void __iomem *addr)
{
- return readl(addr);
+ int ret, flags;
+ spin_lock_irqsave(&lbi_lock, flags);
+ ret = readl(addr);
+ spin_unlock_irqrestore(&lbi_lock, flags);
+ return ret;
}
unsigned int ioread32be(void __iomem *addr)
{
- return in_be32(addr);
+ int ret, flags;
+ spin_lock_irqsave(&lbi_lock, flags);
+ ret = in_be32(addr);
+ spin_unlock_irqrestore(&lbi_lock, flags);
+ return ret;
}
EXPORT_SYMBOL(ioread8);
EXPORT_SYMBOL(ioread16);
@@ -40,23 +62,38 @@ EXPORT_SYMBOL(ioread32be);
void iowrite8(u8 val, void __iomem *addr)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
writeb(val, addr);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
void iowrite16(u16 val, void __iomem *addr)
{
+ int ret, flags;
+ spin_lock_irqsave(&lbi_lock, flags);
writew(val, addr);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
void iowrite16be(u16 val, void __iomem *addr)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
out_be16(addr, val);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
void iowrite32(u32 val, void __iomem *addr)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
writel(val, addr);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
void iowrite32be(u32 val, void __iomem *addr)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
out_be32(addr, val);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
EXPORT_SYMBOL(iowrite8);
EXPORT_SYMBOL(iowrite16);
@@ -74,15 +111,24 @@ EXPORT_SYMBOL(iowrite32be);
*/
void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
_insb((u8 __iomem *) addr, dst, count);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
_insw_ns((u16 __iomem *) addr, dst, count);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
_insl_ns((u32 __iomem *) addr, dst, count);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
EXPORT_SYMBOL(ioread8_rep);
EXPORT_SYMBOL(ioread16_rep);
@@ -90,15 +136,24 @@ EXPORT_SYMBOL(ioread32_rep);
void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
_outsb((u8 __iomem *) addr, src, count);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
_outsw_ns((u16 __iomem *) addr, src, count);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
{
+ int flags;
+ spin_lock_irqsave(&lbi_lock, flags);
_outsl_ns((u32 __iomem *) addr, src, count);
+ spin_unlock_irqrestore(&lbi_lock, flags);
}
EXPORT_SYMBOL(iowrite8_rep);
EXPORT_SYMBOL(iowrite16_rep);
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 27/35] Work around errata 4290
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (25 preceding siblings ...)
2007-07-05 17:02 ` [patch 26/35] Work around errata 4713 Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
2007-07-05 18:50 ` Gabriel Paubert
2007-07-05 17:03 ` [patch 28/35] Work around errata 4712 Olof Johansson
` (7 subsequent siblings)
34 siblings, 1 reply; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Workaround for errata 4290: The decrementer ticks at half the expected rate
so load it with half the value it would otherwise be loaded with.
Index: 2.6.21/include/asm-powerpc/time.h
===================================================================
--- 2.6.21.orig/include/asm-powerpc/time.h
+++ 2.6.21/include/asm-powerpc/time.h
@@ -173,6 +173,13 @@ static inline unsigned int get_dec(void)
static inline void set_dec(int val)
{
+#ifdef CONFIG_PPC_PASEMI
+ /* PA6T rev Ax have decrementer ticking at 1/2 tb rate */
+ val >>= 2;
+ if (!val)
+ val = 1;
+#endif
+
#if defined(CONFIG_40x)
return; /* Have to let it auto-reload */
#elif defined(CONFIG_8xx_CPU6)
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 28/35] Work around errata 4712
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (26 preceding siblings ...)
2007-07-05 17:03 ` [patch 27/35] Work around errata 4290 Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
2007-07-05 17:03 ` [patch 29/35] Work around errata 4910 Olof Johansson
` (6 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Workaround for errata 4712; on an SMP system the PIC can get stuck
trying to read the next available interrupt from INTACK in case there's
only a spurious available. The workaround is to program timers to cause
interrupts every now and then, which recovers from the lockup.
Index: mainline/arch/powerpc/sysdev/mpic.c
===================================================================
--- mainline.orig/arch/powerpc/sysdev/mpic.c
+++ mainline/arch/powerpc/sysdev/mpic.c
@@ -1602,3 +1602,37 @@ static int mpic_init_sys(void)
}
device_initcall(mpic_init_sys);
+
+
+static irqreturn_t intr_4712(int irq, void *data)
+{
+ return IRQ_HANDLED;
+}
+
+static int do_4712_workaround(void)
+{
+ struct mpic *mpic = mpic_primary;
+ int irq, ret;
+
+ /* HACK: setup timers 4 and 5: 2Hz for now, hold off for 1 sec */
+ /* Steal vectors 250 and 251, nothing uses them */
+
+ irq = irq_create_mapping(NULL, 250);
+ ret = request_irq(irq, &intr_4712, IRQF_DISABLED, "4712 workaround cpu0", NULL);
+ irq = irq_create_mapping(NULL, 251);
+ ret = request_irq(irq, &intr_4712, IRQF_DISABLED, "4712 workaround cpu1", NULL);
+
+ mpic_write(mpic->tmregs, 0 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_DESTINATION), 1);
+ mpic_write(mpic->tmregs, 0 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_VECTOR_PRI), (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 250);
+ mpic_write(mpic->tmregs, 0 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_BASE_CNT), 8333333/4);
+ mpic_write(mpic->tmregs, 0 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_CURRENT_CNT), 8333333);
+
+ mpic_write(mpic->tmregs, 3 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_DESTINATION), 2);
+ mpic_write(mpic->tmregs, 3 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_VECTOR_PRI), (10 << MPIC_VECPRI_PRIORITY_SHIFT) | 251);
+ mpic_write(mpic->tmregs, 3 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_BASE_CNT), 8333333/4);
+ mpic_write(mpic->tmregs, 3 * MPIC_INFO(TIMER_STRIDE) + MPIC_INFO(TIMER_CURRENT_CNT), 8333333);
+
+ return 0;
+}
+late_initcall(do_4712_workaround);
+
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 29/35] Work around errata 4910
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (27 preceding siblings ...)
2007-07-05 17:03 ` [patch 28/35] Work around errata 4712 Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
2007-07-05 17:03 ` [patch 30/35] Disable PURR on pa6t Olof Johansson
` (5 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Don't allow unguarded mappings in PCI-express space. This is resolves
problems with frame buffers having garbage on them due to failing
write merges.
Index: 2.6.21/arch/powerpc/mm/hash_native_64.c
===================================================================
--- 2.6.21.orig/arch/powerpc/mm/hash_native_64.c
+++ 2.6.21/arch/powerpc/mm/hash_native_64.c
@@ -152,6 +152,10 @@ static long native_hpte_insert(unsigned
if (i == HPTES_PER_GROUP)
return -1;
+ /* Workaround for bug 4910: No non-guarded access over IOB */
+ if (pa >= 0x80000000 && pa < 0x100000000)
+ rflags |= _PAGE_GUARDED;
+
hpte_v = hpte_encode_v(va, psize) | vflags | HPTE_V_VALID;
hpte_r = hpte_encode_r(pa, psize) | rflags;
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 30/35] Disable PURR on pa6t
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (28 preceding siblings ...)
2007-07-05 17:03 ` [patch 29/35] Work around errata 4910 Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
2007-07-05 17:03 ` [patch 31/35] Work around errata 4161 Olof Johansson
` (4 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Our PURR ticks at the wrong rate (same as the decrementer). Since it
doesn't really have any value-add besides on partitioned and multithreaded
systems, refrain from using it at the moment.
Index: 2.6.21/include/asm-powerpc/cputable.h
===================================================================
--- 2.6.21.orig/include/asm-powerpc/cputable.h
+++ 2.6.21/include/asm-powerpc/cputable.h
@@ -356,7 +356,7 @@ extern void do_feature_fixups(unsigned l
#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
- CPU_FTR_PURR | CPU_FTR_REAL_LE)
+ CPU_FTR_REAL_LE)
#define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2)
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 31/35] Work around errata 4161
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (29 preceding siblings ...)
2007-07-05 17:03 ` [patch 30/35] Disable PURR on pa6t Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
2007-07-05 17:03 ` [patch 32/35] Dont reset openpic on init Olof Johansson
` (3 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Errata 4161: Concurring ptesyncs on both cores might lock up the
cores. Most ptesyncs are already under tlbie_lock, so use that in the only
other remaining location (the timer interrupt ones we've added ourselves).
Index: 2.6.21/arch/powerpc/kernel/time.c
===================================================================
--- 2.6.21.orig/arch/powerpc/kernel/time.c
+++ 2.6.21/arch/powerpc/kernel/time.c
@@ -618,8 +618,11 @@ void timer_interrupt(struct pt_regs * re
int cpu = smp_processor_id();
unsigned long ticks;
u64 tb_next_jiffy;
+ extern spinlock_t native_tlbie_lock;
+ spin_lock(&native_tlbie_lock);
asm("ptesync");
+ spin_unlock(&native_tlbie_lock);
#ifdef CONFIG_PPC32
if (atomic_read(&ppc_n_lost_interrupts) != 0)
Index: 2.6.21/arch/powerpc/mm/hash_native_64.c
===================================================================
--- 2.6.21.orig/arch/powerpc/mm/hash_native_64.c
+++ 2.6.21/arch/powerpc/mm/hash_native_64.c
@@ -35,7 +35,7 @@
#define HPTE_LOCK_BIT 3
-static DEFINE_SPINLOCK(native_tlbie_lock);
+DEFINE_SPINLOCK(native_tlbie_lock);
static inline void __tlbie(unsigned long va, unsigned int psize)
{
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 32/35] Dont reset openpic on init
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (30 preceding siblings ...)
2007-07-05 17:03 ` [patch 31/35] Work around errata 4161 Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
2007-07-05 17:03 ` [patch 33/35] Work around errata 5667 Olof Johansson
` (2 subsequent siblings)
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Take out the MPIC_WANTS_RESET again, since it turns out it causes loss
of interrupt grant tokens during some circumstances on Ax.
Index: 2.6.21/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/setup.c
+++ 2.6.21/arch/powerpc/platforms/pasemi/setup.c
@@ -156,7 +156,7 @@ static __init void pas_init_IRQ(void)
printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
mpic = mpic_alloc(mpic_node, openpic_addr,
- MPIC_PRIMARY|MPIC_LARGE_VECTORS|MPIC_WANTS_RESET,
+ MPIC_PRIMARY|MPIC_LARGE_VECTORS,
0, 0, " PAS-OPIC ");
BUG_ON(!mpic);
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 33/35] Work around errata 5667
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (31 preceding siblings ...)
2007-07-05 17:03 ` [patch 32/35] Dont reset openpic on init Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
2007-07-05 17:03 ` [patch 34/35] Work around errata 4505 Olof Johansson
2007-07-05 17:03 ` [patch 35/35] Work around errata 5652 Olof Johansson
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Always keep a page mapped at EA 0. Right now it is shared among all
processes, as long as noone does a NULL pointer deref and uses the data
there, there should be no security implications. Still, this is better
not used in any kind of environment where users can't be trusted.
Index: mainline/arch/powerpc/kernel/process.c
===================================================================
--- mainline.orig/arch/powerpc/kernel/process.c
+++ mainline/arch/powerpc/kernel/process.c
@@ -330,6 +330,14 @@ struct task_struct *__switch_to(struct t
calculate_steal_time();
last = _switch(old_thread, new_thread);
+ /* current is still really us, just a different us :-) */
+ if (current->mm) {
+#ifdef CONFIG_PPC_HAS_HASH_64K
+ __hash_page_64K(0, _PAGE_USER|_PAGE_RW, get_vsid(current->mm->context.id, 0), ¤t->zero_pte.pte, 0x300, 1);
+#else
+ __hash_page_4K(0, _PAGE_USER|_PAGE_RW, get_vsid(current->mm->context.id, 0), ¤t->zero_pte, 0x300, 1);
+#endif
+ }
local_irq_restore(flags);
Index: mainline/kernel/fork.c
===================================================================
--- mainline.orig/kernel/fork.c
+++ mainline/kernel/fork.c
@@ -104,8 +104,12 @@ struct kmem_cache *vm_area_cachep;
/* SLAB cache for mm_struct structures (tsk->mm) */
static struct kmem_cache *mm_cachep;
+static struct page *zero_page;
+
void free_task(struct task_struct *tsk)
{
+ if (tsk->mm)
+ flush_hash_page(get_vsid(tsk->mm->context.id, 0) << 28, tsk->zero_pte, MMU_PAGE_4K, 0);
free_thread_info(tsk->stack);
rt_mutex_debug_task_free(tsk);
free_task_struct(tsk);
@@ -156,6 +160,8 @@ void __init fork_init(unsigned long memp
init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
init_task.signal->rlim[RLIMIT_SIGPENDING] =
init_task.signal->rlim[RLIMIT_NPROC];
+
+ zero_page = alloc_page(GFP_KERNEL);
}
static struct task_struct *dup_task_struct(struct task_struct *orig)
@@ -182,6 +188,11 @@ static struct task_struct *dup_task_stru
#ifdef CONFIG_CC_STACKPROTECTOR
tsk->stack_canary = get_random_int();
#endif
+#ifdef CONFIG_PPC_64K_PAGES
+ tsk->zero_pte.pte = mk_pte(zero_page,_PAGE_BASE|_PAGE_RW|_PAGE_USER|_PAGE_EXEC);
+#else
+ tsk->zero_pte = mk_pte(zero_page,_PAGE_BASE|_PAGE_RW|_PAGE_USER|_PAGE_EXEC);
+#endif
/* One for us, one for whoever does the "release_task()" (usually parent) */
atomic_set(&tsk->usage,2);
Index: mainline/include/linux/sched.h
===================================================================
--- mainline.orig/include/linux/sched.h
+++ mainline/include/linux/sched.h
@@ -863,6 +863,7 @@ struct task_struct {
struct list_head ptrace_list;
struct mm_struct *mm, *active_mm;
+ real_pte_t zero_pte;
/* task state */
struct linux_binfmt *binfmt;
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 34/35] Work around errata 4505
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (32 preceding siblings ...)
2007-07-05 17:03 ` [patch 33/35] Work around errata 5667 Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
2007-07-05 17:03 ` [patch 35/35] Work around errata 5652 Olof Johansson
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Workaround for Errata 4504: PMC0 doesn't seem to set SIARLOG when
an exception occurs. Instead, log the PC for when we took the actual
exception.
Index: 2.6.21/arch/powerpc/oprofile/op_model_pa6t.c
===================================================================
--- 2.6.21.orig/arch/powerpc/oprofile/op_model_pa6t.c
+++ 2.6.21/arch/powerpc/oprofile/op_model_pa6t.c
@@ -215,6 +215,9 @@ static void pa6t_handle_interrupt(struct
if (oprofile_running && ctr[i].enabled) {
if (mmcr0 & PA6T_MMCR0_SIARLOG)
oprofile_add_ext_sample(pc, regs, i, is_kernel);
+ else if (i < 2)
+ /* PMC0/1 might not set SIARLOG, just log PC at time of fault */
+ oprofile_add_ext_sample(regs->nip, regs, i, is_kernel);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0UL);
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* [patch 35/35] Work around errata 5652
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
` (33 preceding siblings ...)
2007-07-05 17:03 ` [patch 34/35] Work around errata 4505 Olof Johansson
@ 2007-07-05 17:03 ` Olof Johansson
34 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 17:03 UTC (permalink / raw)
To: linuxppc-dev
Due to errata 5652 we might sometimes end up with duplicate SLB entries.
This causes a machine check, so detect it (and print debug info), but
recover instead of killing the process and/or crashing the machine.
Index: 2.6.21/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- 2.6.21.orig/arch/powerpc/platforms/pasemi/setup.c
+++ 2.6.21/arch/powerpc/platforms/pasemi/setup.c
@@ -36,6 +36,7 @@
#include <asm/smp.h>
#include <asm/time.h>
#include <asm/of_platform.h>
+#include <asm/mmu-hash64.h>
#include "pasemi.h"
@@ -176,7 +177,7 @@ static int pas_machine_check_handler(str
{
int cpu = smp_processor_id();
unsigned long srr0, srr1, dsisr;
- int dump_slb = 0;
+ int dump_slb = 0, flush_slb = 0;
int dump_memsta = 0;
srr0 = regs->nip;
@@ -200,6 +201,7 @@ static int pas_machine_check_handler(str
if (dsisr & 0x2000) {
printk(KERN_ERR "MMU SLB multi-hit or invalid B field\n");
dump_slb = 1;
+ flush_slb = 1;
}
if (dsisr & 0x1000)
printk(KERN_ERR "Recoverable Duptags\n");
@@ -215,6 +217,7 @@ static int pas_machine_check_handler(str
if (srr1 & 0x40000) {
printk(KERN_ERR "I-side SLB multiple hit\n");
dump_slb = 1;
+ flush_slb = 1;
}
if (srr1 & 0x20000) {
printk(KERN_ERR "I-cache parity error hit\n");
@@ -243,6 +246,10 @@ static int pas_machine_check_handler(str
}
}
+ if (flush_slb)
+ /* We really can recover from this. flush, rebolt and go. */
+ slb_flush_and_rebolt();
+
/* SRR1[62] is from MSR[62] if recoverable, so pass that back */
return !!(srr1 & 0x2);
}
--
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 27/35] Work around errata 4290
2007-07-05 17:03 ` [patch 27/35] Work around errata 4290 Olof Johansson
@ 2007-07-05 18:50 ` Gabriel Paubert
2007-07-05 19:26 ` Olof Johansson
0 siblings, 1 reply; 46+ messages in thread
From: Gabriel Paubert @ 2007-07-05 18:50 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev
On Thu, Jul 05, 2007 at 12:03:00PM -0500, Olof Johansson wrote:
> Workaround for errata 4290: The decrementer ticks at half the expected rate
> so load it with half the value it would otherwise be loaded with.
>
>
> Index: 2.6.21/include/asm-powerpc/time.h
> ===================================================================
> --- 2.6.21.orig/include/asm-powerpc/time.h
> +++ 2.6.21/include/asm-powerpc/time.h
> @@ -173,6 +173,13 @@ static inline unsigned int get_dec(void)
>
> static inline void set_dec(int val)
> {
> +#ifdef CONFIG_PPC_PASEMI
> + /* PA6T rev Ax have decrementer ticking at 1/2 tb rate */
> + val >>= 2;
Comment does not match code: looks like a divide by 4 to me!
> + if (!val)
> + val = 1;
> +#endif
> +
> #if defined(CONFIG_40x)
> return; /* Have to let it auto-reload */
> #elif defined(CONFIG_8xx_CPU6)
Gabriel
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 27/35] Work around errata 4290
2007-07-05 18:50 ` Gabriel Paubert
@ 2007-07-05 19:26 ` Olof Johansson
0 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-05 19:26 UTC (permalink / raw)
To: Gabriel Paubert; +Cc: linuxppc-dev
On Thu, Jul 05, 2007 at 08:50:21PM +0200, Gabriel Paubert wrote:
> On Thu, Jul 05, 2007 at 12:03:00PM -0500, Olof Johansson wrote:
> > Workaround for errata 4290: The decrementer ticks at half the expected rate
> > so load it with half the value it would otherwise be loaded with.
> >
> >
> > Index: 2.6.21/include/asm-powerpc/time.h
> > ===================================================================
> > --- 2.6.21.orig/include/asm-powerpc/time.h
> > +++ 2.6.21/include/asm-powerpc/time.h
> > @@ -173,6 +173,13 @@ static inline unsigned int get_dec(void)
> >
> > static inline void set_dec(int val)
> > {
> > +#ifdef CONFIG_PPC_PASEMI
> > + /* PA6T rev Ax have decrementer ticking at 1/2 tb rate */
> > + val >>= 2;
>
> Comment does not match code: looks like a divide by 4 to me!
You're right. Thanks for catching it.
Never caught it because the timer code behaves just fine anyway, but
it'll waste power by waking up twice as often when idle.
-Olof
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 01/35] pasemi: rename platform
2007-07-05 17:02 ` [patch 01/35] pasemi: rename platform Olof Johansson
@ 2007-07-08 23:52 ` Stephen Rothwell
2007-07-09 0:18 ` Olof Johansson
0 siblings, 1 reply; 46+ messages in thread
From: Stephen Rothwell @ 2007-07-08 23:52 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 409 bytes --]
On Thu, 05 Jul 2007 12:02:34 -0500 Olof Johansson <olof@lixom.net> wrote:
>
> Rename the pasemi platform to "pasemi" to be in line with the platforms
> directory name.
This should also fix a problem further up in that file (in
pasemi_publish_devices) where we check for "machine_is(pasemi)".
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 01/35] pasemi: rename platform
2007-07-08 23:52 ` Stephen Rothwell
@ 2007-07-09 0:18 ` Olof Johansson
2007-07-09 7:23 ` Stephen Rothwell
0 siblings, 1 reply; 46+ messages in thread
From: Olof Johansson @ 2007-07-09 0:18 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linuxppc-dev
On Mon, Jul 09, 2007 at 09:52:59AM +1000, Stephen Rothwell wrote:
> On Thu, 05 Jul 2007 12:02:34 -0500 Olof Johansson <olof@lixom.net> wrote:
> >
> > Rename the pasemi platform to "pasemi" to be in line with the platforms
> > directory name.
>
> This should also fix a problem further up in that file (in
> pasemi_publish_devices) where we check for "machine_is(pasemi)".
Yup, that's how I discovered the machine name being less than intuitive.
-Olof
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 01/35] pasemi: rename platform
2007-07-09 0:18 ` Olof Johansson
@ 2007-07-09 7:23 ` Stephen Rothwell
2007-07-09 17:19 ` Olof Johansson
0 siblings, 1 reply; 46+ messages in thread
From: Stephen Rothwell @ 2007-07-09 7:23 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 518 bytes --]
On Sun, 8 Jul 2007 19:18:35 -0500 Olof Johansson <olof@lixom.net> wrote:
>
> On Mon, Jul 09, 2007 at 09:52:59AM +1000, Stephen Rothwell wrote:
> >
> > This should also fix a problem further up in that file (in
> > pasemi_publish_devices) where we check for "machine_is(pasemi)".
>
> Yup, that's how I discovered the machine name being less than intuitive.
So it is worth noting in the chnge log.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 01/35] pasemi: rename platform
2007-07-09 7:23 ` Stephen Rothwell
@ 2007-07-09 17:19 ` Olof Johansson
2007-07-09 17:21 ` Olof Johansson
0 siblings, 1 reply; 46+ messages in thread
From: Olof Johansson @ 2007-07-09 17:19 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linuxppc-dev
On Mon, Jul 09, 2007 at 05:23:02PM +1000, Stephen Rothwell wrote:
> On Sun, 8 Jul 2007 19:18:35 -0500 Olof Johansson <olof@lixom.net> wrote:
> >
> > On Mon, Jul 09, 2007 at 09:52:59AM +1000, Stephen Rothwell wrote:
> > >
> > > This should also fix a problem further up in that file (in
> > > pasemi_publish_devices) where we check for "machine_is(pasemi)".
> >
> > Yup, that's how I discovered the machine name being less than intuitive.
>
> So it is worth noting in the chnge log.
Yeah sure, but not enough to repost the patch. The only problem it causes
is that a driver introduced a little earlier (but in the same release)
won't probe until this is applied.
-Olof
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 01/35] pasemi: rename platform
2007-07-09 17:19 ` Olof Johansson
@ 2007-07-09 17:21 ` Olof Johansson
0 siblings, 0 replies; 46+ messages in thread
From: Olof Johansson @ 2007-07-09 17:21 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linuxppc-dev
On Mon, Jul 09, 2007 at 12:19:26PM -0500, Olof Johansson wrote:
> Yeah sure, but not enough to repost the patch. The only problem it causes
> is that a driver introduced a little earlier (but in the same release)
> won't probe until this is applied.
Well, the SDC drivers are affected too (RNG, cpufreq). Still, there aren't
enough mainline users of the platform for it to be a concern at this time.
-Olof
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes
2007-07-05 17:02 ` [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes Olof Johansson
@ 2007-07-26 21:25 ` Marian Balakowicz
2007-07-28 8:35 ` Olof Johansson
0 siblings, 1 reply; 46+ messages in thread
From: Marian Balakowicz @ 2007-07-26 21:25 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev
Olof,
Olof Johansson wrote:
> 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.
I have recently tried to apply a group of your MAC patches that includes the one from this email. Strangely, I got a pretty random kernel panics (or kernel freezes) when this patch is included. Panics happen in a random, places and have random causes. What I observed is that replacing newly introduced mac->iob_regs with the corresponding offset from (already ioremapped) hose->cfg_data removed the problem. So, it seems that dereferencing pointers based on a second ioremap on a subset of 0xe000_0000 addresses is problematic.
Here are the questions that come to my mind:
- I am testing on a A2 hw, what what your testing setup, anything newer than this (something closer B0 maybe), did you have a chance to try that on a A2 board?
- Is there any particular patch or set of patches/updates that this patch may depend on?
Switching from pci accessors to direct in_* out_* calls drops the guard pci spinlock. Initially, I thought that this may be the reason, but it's not, adding the spinlock is not solving the problem. But anyway, shouldn't we be using it to coordinate access?
Thanks,
Marian
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes
2007-07-26 21:25 ` Marian Balakowicz
@ 2007-07-28 8:35 ` Olof Johansson
2007-08-01 9:27 ` Marian Balakowicz
0 siblings, 1 reply; 46+ messages in thread
From: Olof Johansson @ 2007-07-28 8:35 UTC (permalink / raw)
To: Marian Balakowicz; +Cc: linuxppc-dev
Hi,
On Thu, Jul 26, 2007 at 11:25:04PM +0200, Marian Balakowicz wrote:
>
> Olof,
>
> Olof Johansson wrote:
> > 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.
>
> I have recently tried to apply a group of your MAC patches that
> includes the one from this email. Strangely, I got a pretty random
> kernel panics (or kernel freezes) when this patch is included. Panics
> happen in a random, places and have random causes. What I observed is
> that replacing newly introduced mac->iob_regs with the corresponding
> offset from (already ioremapped) hose->cfg_data removed the problem. So,
> it seems that dereferencing pointers based on a second ioremap on a
> subset of 0xe000_0000 addresses is problematic.
The problem is that the IOB register range is 8K, not 4K. I have since
fixed that bug but I didn't repost the patch series. It does cause weird
and strange errors to happen since register writes into the second 4K
would really go to another mapping somewhere else.
So, the quick fix is to always map 0x2000 in map_one_reg, the slightly better
one is to check the PCI dev and only map 2K for the IOB.
> Here are the questions that come to my mind:
>
> - I am testing on a A2 hw, what what your testing setup, anything
> newer than this (something closer B0 maybe), did you have a chance to
> try that on a A2 board?
I'm doing all of my work on A2 hardware at the moment.
> - Is there any particular patch or set of patches/updates that this
> patch may depend on?
There's a fix, but with the description above you should be able to handle it on your
own as well. I'm currently travelling on vacation, but I'll try to post something within
a few days.
> Switching from pci accessors to direct in_* out_* calls drops the
> guard pci spinlock. Initially, I thought that this may be the reason,
> but it's not, adding the spinlock is not solving the problem. But anyway,
> shouldn't we be using it to coordinate access?
The very point of this patch is to avoid doing the spinlock. There's no need
for one in this case, it's pure overhead.
-Olof
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes
2007-07-28 8:35 ` Olof Johansson
@ 2007-08-01 9:27 ` Marian Balakowicz
0 siblings, 0 replies; 46+ messages in thread
From: Marian Balakowicz @ 2007-08-01 9:27 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev
Olof Johansson wrote:
> On Thu, Jul 26, 2007 at 11:25:04PM +0200, Marian Balakowicz wrote:
>>
>> Olof Johansson wrote:
>>> 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.
>> I have recently tried to apply a group of your MAC patches that
>> includes the one from this email. Strangely, I got a pretty random
>> kernel panics (or kernel freezes) when this patch is included. Panics
>> happen in a random, places and have random causes. What I observed is
>> that replacing newly introduced mac->iob_regs with the corresponding
>> offset from (already ioremapped) hose->cfg_data removed the problem. So,
>> it seems that dereferencing pointers based on a second ioremap on a
>> subset of 0xe000_0000 addresses is problematic.
>
> The problem is that the IOB register range is 8K, not 4K. I have since
> fixed that bug but I didn't repost the patch series. It does cause weird
> and strange errors to happen since register writes into the second 4K
> would really go to another mapping somewhere else.
>
> So, the quick fix is to always map 0x2000 in map_one_reg, the slightly better
> one is to check the PCI dev and only map 2K for the IOB.
Thanks for the pointer. Using 0x2000 for IOB solves the problem.
Regards,
Marian
^ permalink raw reply [flat|nested] 46+ messages in thread
end of thread, other threads:[~2007-08-01 9:29 UTC | newest]
Thread overview: 46+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-05 17:02 [patch 00/35] PA Semi patch set Olof Johansson
2007-07-05 17:02 ` [patch 01/35] pasemi: rename platform Olof Johansson
2007-07-08 23:52 ` Stephen Rothwell
2007-07-09 0:18 ` Olof Johansson
2007-07-09 7:23 ` Stephen Rothwell
2007-07-09 17:19 ` Olof Johansson
2007-07-09 17:21 ` Olof Johansson
2007-07-05 17:02 ` [patch 02/35] PA Semi EDAC driver Olof Johansson
2007-07-05 17:02 ` [patch 03/35] Change powerpc64 ioaddr_t to u_int Olof Johansson
2007-07-05 17:02 ` [patch 04/35] pasemi_mac: Fix TX interrupt threshold Olof Johansson
2007-07-05 17:02 ` [patch 05/35] pasemi_mac: Clean TX ring in poll Olof Johansson
2007-07-05 17:02 ` [patch 06/35] pasemi_mac: Abstract out register access Olof Johansson
2007-07-05 17:02 ` [patch 07/35] pasemi_mac: stop using the pci config space accessors for register read/writes Olof Johansson
2007-07-26 21:25 ` Marian Balakowicz
2007-07-28 8:35 ` Olof Johansson
2007-08-01 9:27 ` Marian Balakowicz
2007-07-05 17:02 ` [patch 08/35] pasemi_mac: Enable L2 caching of packet headers Olof Johansson
2007-07-05 17:02 ` [patch 09/35] pasemi_mac: Simplify memcpy for short receives Olof Johansson
2007-07-05 17:02 ` [patch 10/35] pasemi_mac: Minor performance tweaks Olof Johansson
2007-07-05 17:02 ` [patch 11/35] pasemi_mac: Reduce locking when cleaning TX ring Olof Johansson
2007-07-05 17:02 ` [patch 12/35] pasemi_mac: Enable LLTX Olof Johansson
2007-07-05 17:02 ` [patch 13/35] Cleanup marvell phy driver init Olof Johansson
2007-07-05 17:02 ` [patch 14/35] Add 88E1112 PHY ID to the marvell driver Olof Johansson
2007-07-05 17:02 ` [patch 15/35] Export HID registers via sysfs Olof Johansson
2007-07-05 17:02 ` [patch 16/35] Electra ide platform glue Olof Johansson
2007-07-05 17:02 ` [patch 17/35] CF driver for PA Semi Electra Olof Johansson
2007-07-05 17:02 ` [patch 18/35] Spread IRQs among cpus by default Olof Johansson
2007-07-05 17:02 ` [patch 19/35] Improve machine check output Olof Johansson
2007-07-05 17:02 ` [patch 20/35] Remove idle_spin function pointer Olof Johansson
2007-07-05 17:02 ` [patch 21/35] Use MSR_PMM to disable profiling of the idle loop Olof Johansson
2007-07-05 17:02 ` [patch 22/35] Work around errata 4111 Olof Johansson
2007-07-05 17:02 ` [patch 23/35] Work around UART erratas Olof Johansson
2007-07-05 17:02 ` [patch 24/35] Work around errata 4628 Olof Johansson
2007-07-05 17:02 ` [patch 25/35] Work around errata 4025 Olof Johansson
2007-07-05 17:02 ` [patch 26/35] Work around errata 4713 Olof Johansson
2007-07-05 17:03 ` [patch 27/35] Work around errata 4290 Olof Johansson
2007-07-05 18:50 ` Gabriel Paubert
2007-07-05 19:26 ` Olof Johansson
2007-07-05 17:03 ` [patch 28/35] Work around errata 4712 Olof Johansson
2007-07-05 17:03 ` [patch 29/35] Work around errata 4910 Olof Johansson
2007-07-05 17:03 ` [patch 30/35] Disable PURR on pa6t Olof Johansson
2007-07-05 17:03 ` [patch 31/35] Work around errata 4161 Olof Johansson
2007-07-05 17:03 ` [patch 32/35] Dont reset openpic on init Olof Johansson
2007-07-05 17:03 ` [patch 33/35] Work around errata 5667 Olof Johansson
2007-07-05 17:03 ` [patch 34/35] Work around errata 4505 Olof Johansson
2007-07-05 17:03 ` [patch 35/35] Work around errata 5652 Olof Johansson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).