aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mpc85xx/patches-3.14/210-spi-fsl-espi-preallocate-local-buffer.patch
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2014-11-19 09:20:55 +0000
committerJohn Crispin <blogic@openwrt.org>2014-11-19 09:20:55 +0000
commitc3e4dee7574a5d6bcdcf913fa7ec5d2e61d35f45 (patch)
tree29a09118a5e8048d861b11963e1a53fdbbc03ab2 /target/linux/mpc85xx/patches-3.14/210-spi-fsl-espi-preallocate-local-buffer.patch
parent7d83bcf0bf1a66a8e956bdcb75c3e8a275b94eee (diff)
downloadupstream-c3e4dee7574a5d6bcdcf913fa7ec5d2e61d35f45.tar.gz
upstream-c3e4dee7574a5d6bcdcf913fa7ec5d2e61d35f45.tar.bz2
upstream-c3e4dee7574a5d6bcdcf913fa7ec5d2e61d35f45.zip
mpc85xx: add 3.14 kernel support for mpc85xx platform
This patch adds 3.14 kernel support for the mpc85xx platform. Works fine here with a TL-WDR4900 which seems to be the only supported device using this platform. There might be differences depending on HW version, therefore I'd ask others to test too. Changes to 3.10 missing config options added to 3.14 config file patch 001: rebased patch 100: rebased patch 110: rebased patch 120: rebased patch 130: rebased patch 140: minor adjustment patch 200: removed, change went upstream patch 210: rebased patch 220: removed, change went upstream patch 750: new, fixes an issue with ethernet port autoneg being disabled due to changes in kernel phy handling Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43308 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/mpc85xx/patches-3.14/210-spi-fsl-espi-preallocate-local-buffer.patch')
-rw-r--r--target/linux/mpc85xx/patches-3.14/210-spi-fsl-espi-preallocate-local-buffer.patch154
1 files changed, 154 insertions, 0 deletions
diff --git a/target/linux/mpc85xx/patches-3.14/210-spi-fsl-espi-preallocate-local-buffer.patch b/target/linux/mpc85xx/patches-3.14/210-spi-fsl-espi-preallocate-local-buffer.patch
new file mode 100644
index 0000000000..c095510d44
--- /dev/null
+++ b/target/linux/mpc85xx/patches-3.14/210-spi-fsl-espi-preallocate-local-buffer.patch
@@ -0,0 +1,154 @@
+From: Gabor Juhos <juhosg@openwrt.org>
+Subject: spi-fsl-espi: avoid frequent high order allocations
+
+The driver allocates 64KiB of memory fro a local buffer before
+each transfer and releases that afterwards. When the memory is
+fragmented this allocation often fails and causes a warning like
+this:
+
+ kworker/u2:2: page allocation failure: order:4, mode:0x10c0d0
+ CPU: 0 PID: 7011 Comm: kworker/u2:2 Not tainted 3.10.24 #1
+ Workqueue: ffe07000.spi mpc8xxx_spi_work
+ Call Trace:
+ [c1c6dcf0] [c0006914] show_stack+0x50/0x170 (unreliable)
+ [c1c6dd30] [c0259858] dump_stack+0x24/0x34
+ [c1c6dd40] [c00672e8] warn_alloc_failed+0x120/0x13c
+ [c1c6dd90] [c0069920] __alloc_pages_nodemask+0x574/0x5c8
+ [c1c6de20] [c0069990] __get_free_pages+0x1c/0x4c
+ [c1c6de30] [c0185174] fsl_espi_do_one_msg+0x128/0x2a0
+ [c1c6de90] [c0184290] mpc8xxx_spi_work+0x50/0x7c
+ [c1c6dea0] [c0037af8] process_one_work+0x208/0x30c
+ [c1c6dec0] [c00387a0] worker_thread+0x20c/0x308
+ [c1c6def0] [c003de60] kthread+0xa4/0xa8
+ [c1c6df40] [c000c4bc] ret_from_kernel_thread+0x5c/0x64
+
+ m25p80 spi0.0: error -12 reading SR
+ end_request: I/O error, dev mtdblock3, sector 680
+ SQUASHFS error: squashfs_read_data failed to read block 0x54a4a
+ SQUASHFS error: Unable to read data cache entry [54a4a]
+
+Preallocate the buffer from the probe routine to avoid
+this.
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/spi/spi-fsl-espi.c | 34 ++++++++++++++++------------------
+ drivers/spi/spi-fsl-lib.h | 1 +
+ 2 files changed, 17 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
+index 428dc7a..5207176 100644
+--- a/drivers/spi/spi-fsl-espi.c
++++ b/drivers/spi/spi-fsl-espi.c
+@@ -334,17 +334,13 @@ static void fsl_espi_do_trans(struct spi_message *m,
+ static void fsl_espi_cmd_trans(struct spi_message *m,
+ struct fsl_espi_transfer *trans, u8 *rx_buff)
+ {
++ struct spi_device *spi = m->spi;
++ struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+ struct spi_transfer *t;
+- u8 *local_buf;
++ u8 *local_buf = mspi->local_buf;
+ int i = 0;
+ struct fsl_espi_transfer *espi_trans = trans;
+
+- local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+- if (!local_buf) {
+- espi_trans->status = -ENOMEM;
+- return;
+- }
+-
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+ if (t->tx_buf) {
+ memcpy(local_buf + i, t->tx_buf, t->len);
+@@ -357,28 +353,23 @@ static void fsl_espi_cmd_trans(struct spi_message *m,
+ fsl_espi_do_trans(m, espi_trans);
+
+ espi_trans->actual_length = espi_trans->len;
+- kfree(local_buf);
+ }
+
+ static void fsl_espi_rw_trans(struct spi_message *m,
+ struct fsl_espi_transfer *trans, u8 *rx_buff)
+ {
++ struct spi_device *spi = m->spi;
++ struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+ struct fsl_espi_transfer *espi_trans = trans;
+ unsigned int n_tx = espi_trans->n_tx;
+ unsigned int n_rx = espi_trans->n_rx;
+ struct spi_transfer *t;
+- u8 *local_buf;
++ u8 *local_buf = mspi->local_buf;
+ u8 *rx_buf = rx_buff;
+ unsigned int trans_len;
+ unsigned int addr;
+ int i, pos, loop;
+
+- local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+- if (!local_buf) {
+- espi_trans->status = -ENOMEM;
+- return;
+- }
+-
+ for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
+ trans_len = n_rx - pos;
+ if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
+@@ -412,8 +403,6 @@ static void fsl_espi_rw_trans(struct spi_message *m,
+ else
+ espi_trans->actual_length += espi_trans->len;
+ }
+-
+- kfree(local_buf);
+ }
+
+ static void fsl_espi_do_one_msg(struct spi_message *m)
+@@ -581,6 +570,7 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
+ static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
+ {
+ iounmap(mspi->reg_base);
++ kfree(mspi->local_buf);
+ }
+
+ static struct spi_master * fsl_espi_probe(struct device *dev,
+@@ -612,10 +602,16 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
+ mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
+ mpc8xxx_spi->spi_remove = fsl_espi_remove;
+
++ mpc8xxx_spi->local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
++ if (!mpc8xxx_spi->local_buf) {
++ ret = -ENOMEM;
++ goto err_probe;
++ }
++
+ mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+ if (!mpc8xxx_spi->reg_base) {
+ ret = -ENOMEM;
+- goto err_probe;
++ goto free_buf;
+ }
+
+ reg_base = mpc8xxx_spi->reg_base;
+@@ -658,6 +654,8 @@ unreg_master:
+ free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+ free_irq:
+ iounmap(mpc8xxx_spi->reg_base);
++free_buf:
++ kfree(mpc8xxx_spi->local_buf);
+ err_probe:
+ spi_master_put(master);
+ err:
+diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h
+index 52db693..8dda68b 100644
+--- a/drivers/spi/spi-fsl-lib.h
++++ b/drivers/spi/spi-fsl-lib.h
+@@ -30,6 +30,7 @@ struct mpc8xxx_spi {
+ void *rx;
+ #ifdef CONFIG_SPI_FSL_ESPI
+ int len;
++ u8 *local_buf;
+ #endif
+
+ int subblock;
+--
+2.1.3
+