generic: drop 3.14
Signed-off-by: Luka Perkov <luka@openwrt.org> SVN-Revision: 45375
This commit is contained in:
parent
b66b0ae632
commit
8865505665
208 changed files with 0 additions and 39799 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,25 +0,0 @@
|
|||
Upstream changed the default rootfs to tmpfs when none has been passed
|
||||
to the kernel - this doesn't fit our purposes, so change it back.
|
||||
|
||||
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
|
||||
|
||||
--- a/init/do_mounts.c
|
||||
+++ b/init/do_mounts.c
|
||||
@@ -622,6 +622,7 @@ int __init init_rootfs(void)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
+#if 0
|
||||
if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
|
||||
(!root_fs_names || strstr(root_fs_names, "tmpfs"))) {
|
||||
err = shmem_init();
|
||||
@@ -629,6 +630,9 @@ int __init init_rootfs(void)
|
||||
} else {
|
||||
err = init_ramfs_fs();
|
||||
}
|
||||
+#else
|
||||
+ err = init_ramfs_fs();
|
||||
+#endif
|
||||
|
||||
if (err)
|
||||
unregister_filesystem(&rootfs_fs_type);
|
|
@ -1,42 +0,0 @@
|
|||
From a7ef1eaddbf4bd50bfee92d9dfbecadc61467bbf Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Cernekee <cernekee@gmail.com>
|
||||
Date: Mon, 20 Oct 2014 21:27:57 -0700
|
||||
Subject: [PATCH] MIPS: Allow MIPS_CPU_SCACHE to be used with different line
|
||||
sizes
|
||||
|
||||
CONFIG_MIPS_CPU_SCACHE determines whether to build sc-mips.c. However,
|
||||
it is currently hardwired to use an L1_SHIFT of 6 (64 bytes). Move the
|
||||
L1_SHIFT selection into the CPU or SoC section so that other SoCs can
|
||||
select different values.
|
||||
|
||||
Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
|
||||
Cc: f.fainelli@gmail.com
|
||||
Cc: mbizon@freebox.fr
|
||||
Cc: jogo@openwrt.org
|
||||
Cc: jfraser@broadcom.com
|
||||
Cc: linux-mips@linux-mips.org
|
||||
Cc: devicetree@vger.kernel.org
|
||||
Patchwork: https://patchwork.linux-mips.org/patch/8162/
|
||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
||||
---
|
||||
arch/mips/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -315,6 +315,7 @@ config MIPS_MALTA
|
||||
select I8259
|
||||
select MIPS_BONITO64
|
||||
select MIPS_CPU_SCACHE
|
||||
+ select MIPS_L1_CACHE_SHIFT_6
|
||||
select PCI_GT64XXX_PCI0
|
||||
select MIPS_MSC
|
||||
select SWAP_IO_SPACE
|
||||
@@ -1820,7 +1821,6 @@ config IP22_CPU_SCACHE
|
||||
config MIPS_CPU_SCACHE
|
||||
bool
|
||||
select BOARD_SCACHE
|
||||
- select MIPS_L1_CACHE_SHIFT_6
|
||||
|
||||
config R5000_CPU_SCACHE
|
||||
bool
|
|
@ -1,321 +0,0 @@
|
|||
--- a/drivers/ssb/b43_pci_bridge.c
|
||||
+++ b/drivers/ssb/b43_pci_bridge.c
|
||||
@@ -38,6 +38,7 @@ static const struct pci_device_id b43_pc
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) },
|
||||
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4351) },
|
||||
{ 0, },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
|
||||
--- a/drivers/ssb/driver_gpio.c
|
||||
+++ b/drivers/ssb/driver_gpio.c
|
||||
@@ -475,7 +475,8 @@ int ssb_gpio_unregister(struct ssb_bus *
|
||||
{
|
||||
if (ssb_chipco_available(&bus->chipco) ||
|
||||
ssb_extif_available(&bus->extif)) {
|
||||
- return gpiochip_remove(&bus->gpio);
|
||||
+ gpiochip_remove(&bus->gpio);
|
||||
+ return 0;
|
||||
} else {
|
||||
SSB_WARN_ON(1);
|
||||
}
|
||||
--- a/drivers/ssb/pci.c
|
||||
+++ b/drivers/ssb/pci.c
|
||||
@@ -326,13 +326,13 @@ err_ctlreg:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
|
||||
- u16 mask, u16 shift)
|
||||
+static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset,
|
||||
+ u16 mask, u16 shift)
|
||||
{
|
||||
u16 v;
|
||||
u8 gain;
|
||||
|
||||
- v = in[SPOFF(SSB_SPROM1_AGAIN)];
|
||||
+ v = in[SPOFF(offset)];
|
||||
gain = (v & mask) >> shift;
|
||||
if (gain == 0xFF)
|
||||
gain = 2; /* If unset use 2dBm */
|
||||
@@ -416,12 +416,14 @@ static void sprom_extract_r123(struct ss
|
||||
SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
|
||||
|
||||
/* Extract the antenna gain values. */
|
||||
- out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
|
||||
- SSB_SPROM1_AGAIN_BG,
|
||||
- SSB_SPROM1_AGAIN_BG_SHIFT);
|
||||
- out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
|
||||
- SSB_SPROM1_AGAIN_A,
|
||||
- SSB_SPROM1_AGAIN_A_SHIFT);
|
||||
+ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM1_AGAIN,
|
||||
+ SSB_SPROM1_AGAIN_BG,
|
||||
+ SSB_SPROM1_AGAIN_BG_SHIFT);
|
||||
+ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM1_AGAIN,
|
||||
+ SSB_SPROM1_AGAIN_A,
|
||||
+ SSB_SPROM1_AGAIN_A_SHIFT);
|
||||
if (out->revision >= 2)
|
||||
sprom_extract_r23(out, in);
|
||||
}
|
||||
@@ -468,7 +470,15 @@ static void sprom_extract_r458(struct ss
|
||||
|
||||
static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
|
||||
{
|
||||
+ static const u16 pwr_info_offset[] = {
|
||||
+ SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1,
|
||||
+ SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3
|
||||
+ };
|
||||
u16 il0mac_offset;
|
||||
+ int i;
|
||||
+
|
||||
+ BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
|
||||
+ ARRAY_SIZE(out->core_pwr_info));
|
||||
|
||||
if (out->revision == 4)
|
||||
il0mac_offset = SSB_SPROM4_IL0MAC;
|
||||
@@ -524,14 +534,59 @@ static void sprom_extract_r45(struct ssb
|
||||
}
|
||||
|
||||
/* Extract the antenna gain values. */
|
||||
- SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
|
||||
- SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
|
||||
- SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
|
||||
- SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
|
||||
- SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
|
||||
- SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
|
||||
- SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
|
||||
- SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
|
||||
+ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM4_AGAIN01,
|
||||
+ SSB_SPROM4_AGAIN0,
|
||||
+ SSB_SPROM4_AGAIN0_SHIFT);
|
||||
+ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM4_AGAIN01,
|
||||
+ SSB_SPROM4_AGAIN1,
|
||||
+ SSB_SPROM4_AGAIN1_SHIFT);
|
||||
+ out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM4_AGAIN23,
|
||||
+ SSB_SPROM4_AGAIN2,
|
||||
+ SSB_SPROM4_AGAIN2_SHIFT);
|
||||
+ out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM4_AGAIN23,
|
||||
+ SSB_SPROM4_AGAIN3,
|
||||
+ SSB_SPROM4_AGAIN3_SHIFT);
|
||||
+
|
||||
+ /* Extract cores power info info */
|
||||
+ for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
|
||||
+ u16 o = pwr_info_offset[i];
|
||||
+
|
||||
+ SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
|
||||
+ SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT);
|
||||
+ SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI,
|
||||
+ SSB_SPROM4_2G_MAXP, 0);
|
||||
+
|
||||
+ SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0);
|
||||
+
|
||||
+ SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
|
||||
+ SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT);
|
||||
+ SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI,
|
||||
+ SSB_SPROM4_5G_MAXP, 0);
|
||||
+ SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP,
|
||||
+ SSB_SPROM4_5GH_MAXP, 0);
|
||||
+ SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP,
|
||||
+ SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT);
|
||||
+
|
||||
+ SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0);
|
||||
+ SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0);
|
||||
+ }
|
||||
|
||||
sprom_extract_r458(out, in);
|
||||
|
||||
@@ -621,14 +676,22 @@ static void sprom_extract_r8(struct ssb_
|
||||
SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
|
||||
|
||||
/* Extract the antenna gain values. */
|
||||
- SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
|
||||
- SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
|
||||
- SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
|
||||
- SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
|
||||
- SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
|
||||
- SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
|
||||
- SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
|
||||
- SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
|
||||
+ out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM8_AGAIN01,
|
||||
+ SSB_SPROM8_AGAIN0,
|
||||
+ SSB_SPROM8_AGAIN0_SHIFT);
|
||||
+ out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM8_AGAIN01,
|
||||
+ SSB_SPROM8_AGAIN1,
|
||||
+ SSB_SPROM8_AGAIN1_SHIFT);
|
||||
+ out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM8_AGAIN23,
|
||||
+ SSB_SPROM8_AGAIN2,
|
||||
+ SSB_SPROM8_AGAIN2_SHIFT);
|
||||
+ out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in,
|
||||
+ SSB_SPROM8_AGAIN23,
|
||||
+ SSB_SPROM8_AGAIN3,
|
||||
+ SSB_SPROM8_AGAIN3_SHIFT);
|
||||
|
||||
/* Extract cores power info info */
|
||||
for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
|
||||
--- a/drivers/ssb/pcihost_wrapper.c
|
||||
+++ b/drivers/ssb/pcihost_wrapper.c
|
||||
@@ -11,15 +11,17 @@
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
+#include <linux/pm.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ssb/ssb.h>
|
||||
|
||||
|
||||
-#ifdef CONFIG_PM
|
||||
-static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+static int ssb_pcihost_suspend(struct device *d)
|
||||
{
|
||||
+ struct pci_dev *dev = to_pci_dev(d);
|
||||
struct ssb_bus *ssb = pci_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
@@ -28,17 +30,23 @@ static int ssb_pcihost_suspend(struct pc
|
||||
return err;
|
||||
pci_save_state(dev);
|
||||
pci_disable_device(dev);
|
||||
- pci_set_power_state(dev, pci_choose_state(dev, state));
|
||||
+
|
||||
+ /* if there is a wakeup enabled child device on ssb bus,
|
||||
+ enable pci wakeup posibility. */
|
||||
+ device_set_wakeup_enable(d, d->power.wakeup_path);
|
||||
+
|
||||
+ pci_prepare_to_sleep(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int ssb_pcihost_resume(struct pci_dev *dev)
|
||||
+static int ssb_pcihost_resume(struct device *d)
|
||||
{
|
||||
+ struct pci_dev *dev = to_pci_dev(d);
|
||||
struct ssb_bus *ssb = pci_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
- pci_set_power_state(dev, PCI_D0);
|
||||
+ pci_back_from_sleep(dev);
|
||||
err = pci_enable_device(dev);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -49,10 +57,12 @@ static int ssb_pcihost_resume(struct pci
|
||||
|
||||
return 0;
|
||||
}
|
||||
-#else /* CONFIG_PM */
|
||||
-# define ssb_pcihost_suspend NULL
|
||||
-# define ssb_pcihost_resume NULL
|
||||
-#endif /* CONFIG_PM */
|
||||
+
|
||||
+static const struct dev_pm_ops ssb_pcihost_pm_ops = {
|
||||
+ SET_SYSTEM_SLEEP_PM_OPS(ssb_pcihost_suspend, ssb_pcihost_resume)
|
||||
+};
|
||||
+
|
||||
+#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static int ssb_pcihost_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
@@ -115,8 +125,9 @@ int ssb_pcihost_register(struct pci_driv
|
||||
{
|
||||
driver->probe = ssb_pcihost_probe;
|
||||
driver->remove = ssb_pcihost_remove;
|
||||
- driver->suspend = ssb_pcihost_suspend;
|
||||
- driver->resume = ssb_pcihost_resume;
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+ driver->driver.pm = &ssb_pcihost_pm_ops;
|
||||
+#endif
|
||||
|
||||
return pci_register_driver(driver);
|
||||
}
|
||||
--- a/include/linux/ssb/ssb.h
|
||||
+++ b/include/linux/ssb/ssb.h
|
||||
@@ -33,6 +33,7 @@ struct ssb_sprom {
|
||||
u8 et1phyaddr; /* MII address for enet1 */
|
||||
u8 et0mdcport; /* MDIO for enet0 */
|
||||
u8 et1mdcport; /* MDIO for enet1 */
|
||||
+ u16 dev_id; /* Device ID overriding e.g. PCI ID */
|
||||
u16 board_rev; /* Board revision number from SPROM. */
|
||||
u16 board_num; /* Board number from SPROM. */
|
||||
u16 board_type; /* Board type from SPROM. */
|
||||
--- a/include/linux/ssb/ssb_regs.h
|
||||
+++ b/include/linux/ssb/ssb_regs.h
|
||||
@@ -345,6 +345,43 @@
|
||||
#define SSB_SPROM4_TXPID5GH2_SHIFT 0
|
||||
#define SSB_SPROM4_TXPID5GH3 0xFF00
|
||||
#define SSB_SPROM4_TXPID5GH3_SHIFT 8
|
||||
+
|
||||
+/* There are 4 blocks with power info sharing the same layout */
|
||||
+#define SSB_SPROM4_PWR_INFO_CORE0 0x0080
|
||||
+#define SSB_SPROM4_PWR_INFO_CORE1 0x00AE
|
||||
+#define SSB_SPROM4_PWR_INFO_CORE2 0x00DC
|
||||
+#define SSB_SPROM4_PWR_INFO_CORE3 0x010A
|
||||
+
|
||||
+#define SSB_SPROM4_2G_MAXP_ITSSI 0x00 /* 2 GHz ITSSI and 2 GHz Max Power */
|
||||
+#define SSB_SPROM4_2G_MAXP 0x00FF
|
||||
+#define SSB_SPROM4_2G_ITSSI 0xFF00
|
||||
+#define SSB_SPROM4_2G_ITSSI_SHIFT 8
|
||||
+#define SSB_SPROM4_2G_PA_0 0x02 /* 2 GHz power amp */
|
||||
+#define SSB_SPROM4_2G_PA_1 0x04
|
||||
+#define SSB_SPROM4_2G_PA_2 0x06
|
||||
+#define SSB_SPROM4_2G_PA_3 0x08
|
||||
+#define SSB_SPROM4_5G_MAXP_ITSSI 0x0A /* 5 GHz ITSSI and 5.3 GHz Max Power */
|
||||
+#define SSB_SPROM4_5G_MAXP 0x00FF
|
||||
+#define SSB_SPROM4_5G_ITSSI 0xFF00
|
||||
+#define SSB_SPROM4_5G_ITSSI_SHIFT 8
|
||||
+#define SSB_SPROM4_5GHL_MAXP 0x0C /* 5.2 GHz and 5.8 GHz Max Power */
|
||||
+#define SSB_SPROM4_5GH_MAXP 0x00FF
|
||||
+#define SSB_SPROM4_5GL_MAXP 0xFF00
|
||||
+#define SSB_SPROM4_5GL_MAXP_SHIFT 8
|
||||
+#define SSB_SPROM4_5G_PA_0 0x0E /* 5.3 GHz power amp */
|
||||
+#define SSB_SPROM4_5G_PA_1 0x10
|
||||
+#define SSB_SPROM4_5G_PA_2 0x12
|
||||
+#define SSB_SPROM4_5G_PA_3 0x14
|
||||
+#define SSB_SPROM4_5GL_PA_0 0x16 /* 5.2 GHz power amp */
|
||||
+#define SSB_SPROM4_5GL_PA_1 0x18
|
||||
+#define SSB_SPROM4_5GL_PA_2 0x1A
|
||||
+#define SSB_SPROM4_5GL_PA_3 0x1C
|
||||
+#define SSB_SPROM4_5GH_PA_0 0x1E /* 5.8 GHz power amp */
|
||||
+#define SSB_SPROM4_5GH_PA_1 0x20
|
||||
+#define SSB_SPROM4_5GH_PA_2 0x22
|
||||
+#define SSB_SPROM4_5GH_PA_3 0x24
|
||||
+
|
||||
+/* TODO: Make it deprecated */
|
||||
#define SSB_SPROM4_MAXP_BG 0x0080 /* Max Power BG in path 1 */
|
||||
#define SSB_SPROM4_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */
|
||||
#define SSB_SPROM4_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */
|
||||
--- a/arch/mips/bcm47xx/sprom.c
|
||||
+++ b/arch/mips/bcm47xx/sprom.c
|
||||
@@ -168,6 +168,7 @@ static void nvram_read_alpha2(const char
|
||||
static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
|
||||
const char *prefix, bool fallback)
|
||||
{
|
||||
+ nvram_read_u16(prefix, NULL, "devid", &sprom->dev_id, 0, fallback);
|
||||
nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff, fallback);
|
||||
nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff, fallback);
|
||||
nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff, fallback);
|
File diff suppressed because it is too large
Load diff
|
@ -1,527 +0,0 @@
|
|||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -25,22 +25,18 @@ struct bcma_bus;
|
||||
bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
|
||||
int timeout);
|
||||
void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core);
|
||||
+void bcma_init_bus(struct bcma_bus *bus);
|
||||
int bcma_bus_register(struct bcma_bus *bus);
|
||||
void bcma_bus_unregister(struct bcma_bus *bus);
|
||||
-int __init bcma_bus_early_register(struct bcma_bus *bus,
|
||||
- struct bcma_device *core_cc,
|
||||
- struct bcma_device *core_mips);
|
||||
+int __init bcma_bus_early_register(struct bcma_bus *bus);
|
||||
#ifdef CONFIG_PM
|
||||
int bcma_bus_suspend(struct bcma_bus *bus);
|
||||
int bcma_bus_resume(struct bcma_bus *bus);
|
||||
#endif
|
||||
|
||||
/* scan.c */
|
||||
+void bcma_detect_chip(struct bcma_bus *bus);
|
||||
int bcma_bus_scan(struct bcma_bus *bus);
|
||||
-int __init bcma_bus_scan_early(struct bcma_bus *bus,
|
||||
- struct bcma_device_id *match,
|
||||
- struct bcma_device *core);
|
||||
-void bcma_init_bus(struct bcma_bus *bus);
|
||||
|
||||
/* sprom.c */
|
||||
int bcma_sprom_get(struct bcma_bus *bus);
|
||||
@@ -111,6 +107,14 @@ extern int bcma_chipco_watchdog_register
|
||||
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
|
||||
void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
|
||||
+#else
|
||||
+static inline bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ return false;
|
||||
+}
|
||||
+static inline void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+}
|
||||
#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_GPIO
|
||||
--- a/drivers/bcma/driver_chipcommon.c
|
||||
+++ b/drivers/bcma/driver_chipcommon.c
|
||||
@@ -79,7 +79,9 @@ static int bcma_chipco_watchdog_ticks_pe
|
||||
|
||||
if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
||||
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
|
||||
- /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
|
||||
+ /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP
|
||||
+ * clock
|
||||
+ */
|
||||
return bcma_chipco_get_alp_clock(cc) / 4000;
|
||||
else
|
||||
/* based on 32KHz ILP clock */
|
||||
@@ -97,7 +99,8 @@ int bcma_chipco_watchdog_register(struct
|
||||
wdt.driver_data = cc;
|
||||
wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
|
||||
wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
|
||||
- wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
|
||||
+ wdt.max_timer_ms =
|
||||
+ bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
|
||||
|
||||
pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
|
||||
cc->core->bus->num, &wdt,
|
||||
@@ -175,7 +178,6 @@ void bcma_core_chipcommon_init(struct bc
|
||||
u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
|
||||
{
|
||||
u32 maxt;
|
||||
- enum bcma_clkmode clkmode;
|
||||
|
||||
maxt = bcma_chipco_watchdog_get_max_timer(cc);
|
||||
if (cc->capabilities & BCMA_CC_CAP_PMU) {
|
||||
@@ -185,8 +187,13 @@ u32 bcma_chipco_watchdog_timer_set(struc
|
||||
ticks = maxt;
|
||||
bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks);
|
||||
} else {
|
||||
- clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC;
|
||||
- bcma_core_set_clockmode(cc->core, clkmode);
|
||||
+ struct bcma_bus *bus = cc->core->bus;
|
||||
+
|
||||
+ if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 &&
|
||||
+ bus->chipinfo.id != BCMA_CHIP_ID_BCM53018)
|
||||
+ bcma_core_set_clockmode(cc->core,
|
||||
+ ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC);
|
||||
+
|
||||
if (ticks > maxt)
|
||||
ticks = maxt;
|
||||
/* instant NMI */
|
||||
@@ -335,7 +342,8 @@ void bcma_chipco_serial_init(struct bcma
|
||||
| BCMA_CC_CORECTL_UARTCLKEN);
|
||||
}
|
||||
} else {
|
||||
- bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev);
|
||||
+ bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n",
|
||||
+ ccrev);
|
||||
return;
|
||||
}
|
||||
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -145,6 +145,47 @@ static u16 bcma_pcie_mdio_writeread(stru
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
+ * Early init.
|
||||
+ **************************************************/
|
||||
+
|
||||
+static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ struct bcma_device *core = pc->core;
|
||||
+ u16 val16, core_index;
|
||||
+ uint regoff;
|
||||
+
|
||||
+ regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET);
|
||||
+ core_index = (u16)core->core_index;
|
||||
+
|
||||
+ val16 = pcicore_read16(pc, regoff);
|
||||
+ if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT)
|
||||
+ != core_index) {
|
||||
+ val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
|
||||
+ (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
|
||||
+ pcicore_write16(pc, regoff, val16);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Apply some early fixes required before accessing SPROM.
|
||||
+ * See also si_pci_fixcfg.
|
||||
+ */
|
||||
+void bcma_core_pci_early_init(struct bcma_drv_pci *pc)
|
||||
+{
|
||||
+ if (pc->early_setup_done)
|
||||
+ return;
|
||||
+
|
||||
+ pc->hostmode = bcma_core_pci_is_in_hostmode(pc);
|
||||
+ if (pc->hostmode)
|
||||
+ goto out;
|
||||
+
|
||||
+ bcma_core_pci_fixcfg(pc);
|
||||
+
|
||||
+out:
|
||||
+ pc->early_setup_done = true;
|
||||
+}
|
||||
+
|
||||
+/**************************************************
|
||||
* Workarounds.
|
||||
**************************************************/
|
||||
|
||||
@@ -175,24 +216,6 @@ static void bcma_pcicore_serdes_workarou
|
||||
tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
|
||||
}
|
||||
|
||||
-static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
|
||||
-{
|
||||
- struct bcma_device *core = pc->core;
|
||||
- u16 val16, core_index;
|
||||
- uint regoff;
|
||||
-
|
||||
- regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET);
|
||||
- core_index = (u16)core->core_index;
|
||||
-
|
||||
- val16 = pcicore_read16(pc, regoff);
|
||||
- if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT)
|
||||
- != core_index) {
|
||||
- val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
|
||||
- (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
|
||||
- pcicore_write16(pc, regoff, val16);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
|
||||
/* Needs to happen when coming out of 'standby'/'hibernate' */
|
||||
static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
|
||||
@@ -216,7 +239,6 @@ static void bcma_core_pci_config_fixup(s
|
||||
|
||||
static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
|
||||
{
|
||||
- bcma_core_pci_fixcfg(pc);
|
||||
bcma_pcicore_serdes_workaround(pc);
|
||||
bcma_core_pci_config_fixup(pc);
|
||||
}
|
||||
@@ -226,13 +248,11 @@ void bcma_core_pci_init(struct bcma_drv_
|
||||
if (pc->setup_done)
|
||||
return;
|
||||
|
||||
-#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
|
||||
- pc->hostmode = bcma_core_pci_is_in_hostmode(pc);
|
||||
+ bcma_core_pci_early_init(pc);
|
||||
+
|
||||
if (pc->hostmode)
|
||||
bcma_core_pci_hostmode_init(pc);
|
||||
-#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
|
||||
-
|
||||
- if (!pc->hostmode)
|
||||
+ else
|
||||
bcma_core_pci_clientmode_init(pc);
|
||||
}
|
||||
|
||||
--- a/drivers/bcma/host_pci.c
|
||||
+++ b/drivers/bcma/host_pci.c
|
||||
@@ -13,10 +13,12 @@
|
||||
|
||||
static void bcma_host_pci_switch_core(struct bcma_device *core)
|
||||
{
|
||||
+ int win2 = core->bus->host_is_pcie2 ?
|
||||
+ BCMA_PCIE2_BAR0_WIN2 : BCMA_PCI_BAR0_WIN2;
|
||||
+
|
||||
pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN,
|
||||
core->addr);
|
||||
- pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
|
||||
- core->wrap);
|
||||
+ pci_write_config_dword(core->bus->host_pci, win2, core->wrap);
|
||||
core->bus->mapped_core = core;
|
||||
bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id);
|
||||
}
|
||||
--- a/drivers/bcma/host_soc.c
|
||||
+++ b/drivers/bcma/host_soc.c
|
||||
@@ -193,7 +193,7 @@ int __init bcma_host_soc_init(struct bcm
|
||||
int err;
|
||||
|
||||
/* Scan bus and initialize it */
|
||||
- err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
|
||||
+ err = bcma_bus_early_register(bus);
|
||||
if (err)
|
||||
iounmap(bus->mmio);
|
||||
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -268,6 +268,18 @@ void bcma_prepare_core(struct bcma_bus *
|
||||
}
|
||||
}
|
||||
|
||||
+void bcma_init_bus(struct bcma_bus *bus)
|
||||
+{
|
||||
+ mutex_lock(&bcma_buses_mutex);
|
||||
+ bus->num = bcma_bus_next_num++;
|
||||
+ mutex_unlock(&bcma_buses_mutex);
|
||||
+
|
||||
+ INIT_LIST_HEAD(&bus->cores);
|
||||
+ bus->nr_cores = 0;
|
||||
+
|
||||
+ bcma_detect_chip(bus);
|
||||
+}
|
||||
+
|
||||
static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
|
||||
{
|
||||
int err;
|
||||
@@ -356,12 +368,19 @@ static void bcma_unregister_cores(struct
|
||||
struct bcma_device *core, *tmp;
|
||||
|
||||
list_for_each_entry_safe(core, tmp, &bus->cores, list) {
|
||||
+ if (!core->dev_registered)
|
||||
+ continue;
|
||||
list_del(&core->list);
|
||||
- if (core->dev_registered)
|
||||
- device_unregister(&core->dev);
|
||||
+ device_unregister(&core->dev);
|
||||
}
|
||||
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
platform_device_unregister(bus->drv_cc.watchdog);
|
||||
+
|
||||
+ /* Now noone uses internally-handled cores, we can free them */
|
||||
+ list_for_each_entry_safe(core, tmp, &bus->cores, list) {
|
||||
+ list_del(&core->list);
|
||||
+ kfree(core);
|
||||
+ }
|
||||
}
|
||||
|
||||
int bcma_bus_register(struct bcma_bus *bus)
|
||||
@@ -369,10 +388,6 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
int err;
|
||||
struct bcma_device *core;
|
||||
|
||||
- mutex_lock(&bcma_buses_mutex);
|
||||
- bus->num = bcma_bus_next_num++;
|
||||
- mutex_unlock(&bcma_buses_mutex);
|
||||
-
|
||||
/* Scan for devices (cores) */
|
||||
err = bcma_bus_scan(bus);
|
||||
if (err) {
|
||||
@@ -387,6 +402,13 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
bcma_core_chipcommon_early_init(&bus->drv_cc);
|
||||
}
|
||||
|
||||
+ /* Early init PCIE core */
|
||||
+ core = bcma_find_core(bus, BCMA_CORE_PCIE);
|
||||
+ if (core) {
|
||||
+ bus->drv_pci[0].core = core;
|
||||
+ bcma_core_pci_early_init(&bus->drv_pci[0]);
|
||||
+ }
|
||||
+
|
||||
/* Cores providing flash access go before SPROM init */
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
if (bcma_is_core_needed_early(core->id.id))
|
||||
@@ -459,7 +481,6 @@ int bcma_bus_register(struct bcma_bus *b
|
||||
|
||||
void bcma_bus_unregister(struct bcma_bus *bus)
|
||||
{
|
||||
- struct bcma_device *cores[3];
|
||||
int err;
|
||||
|
||||
err = bcma_gpio_unregister(&bus->drv_cc);
|
||||
@@ -470,46 +491,23 @@ void bcma_bus_unregister(struct bcma_bus
|
||||
|
||||
bcma_core_chipcommon_b_free(&bus->drv_cc_b);
|
||||
|
||||
- cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
||||
- cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
|
||||
- cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
|
||||
-
|
||||
bcma_unregister_cores(bus);
|
||||
-
|
||||
- kfree(cores[2]);
|
||||
- kfree(cores[1]);
|
||||
- kfree(cores[0]);
|
||||
}
|
||||
|
||||
-int __init bcma_bus_early_register(struct bcma_bus *bus,
|
||||
- struct bcma_device *core_cc,
|
||||
- struct bcma_device *core_mips)
|
||||
+/*
|
||||
+ * This is a special version of bus registration function designed for SoCs.
|
||||
+ * It scans bus and performs basic initialization of main cores only.
|
||||
+ * Please note it requires memory allocation, however it won't try to sleep.
|
||||
+ */
|
||||
+int __init bcma_bus_early_register(struct bcma_bus *bus)
|
||||
{
|
||||
int err;
|
||||
struct bcma_device *core;
|
||||
- struct bcma_device_id match;
|
||||
-
|
||||
- match.manuf = BCMA_MANUF_BCM;
|
||||
- match.id = bcma_cc_core_id(bus);
|
||||
- match.class = BCMA_CL_SIM;
|
||||
- match.rev = BCMA_ANY_REV;
|
||||
|
||||
- /* Scan for chip common core */
|
||||
- err = bcma_bus_scan_early(bus, &match, core_cc);
|
||||
- if (err) {
|
||||
- bcma_err(bus, "Failed to scan for common core: %d\n", err);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- match.manuf = BCMA_MANUF_MIPS;
|
||||
- match.id = BCMA_CORE_MIPS_74K;
|
||||
- match.class = BCMA_CL_SIM;
|
||||
- match.rev = BCMA_ANY_REV;
|
||||
-
|
||||
- /* Scan for mips core */
|
||||
- err = bcma_bus_scan_early(bus, &match, core_mips);
|
||||
+ /* Scan for devices (cores) */
|
||||
+ err = bcma_bus_scan(bus);
|
||||
if (err) {
|
||||
- bcma_err(bus, "Failed to scan for mips core: %d\n", err);
|
||||
+ bcma_err(bus, "Failed to scan bus: %d\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
--- a/drivers/bcma/scan.c
|
||||
+++ b/drivers/bcma/scan.c
|
||||
@@ -435,15 +435,12 @@ static int bcma_get_next_core(struct bcm
|
||||
return 0;
|
||||
}
|
||||
|
||||
-void bcma_init_bus(struct bcma_bus *bus)
|
||||
+void bcma_detect_chip(struct bcma_bus *bus)
|
||||
{
|
||||
s32 tmp;
|
||||
struct bcma_chipinfo *chipinfo = &(bus->chipinfo);
|
||||
char chip_id[8];
|
||||
|
||||
- INIT_LIST_HEAD(&bus->cores);
|
||||
- bus->nr_cores = 0;
|
||||
-
|
||||
bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
|
||||
|
||||
tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
|
||||
@@ -464,6 +461,10 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
||||
|
||||
int err, core_num = 0;
|
||||
|
||||
+ /* Skip if bus was already scanned (e.g. during early register) */
|
||||
+ if (bus->nr_cores)
|
||||
+ return 0;
|
||||
+
|
||||
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
|
||||
if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
|
||||
eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
|
||||
@@ -519,64 +520,6 @@ int bcma_bus_scan(struct bcma_bus *bus)
|
||||
out:
|
||||
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
iounmap(eromptr);
|
||||
-
|
||||
- return err;
|
||||
-}
|
||||
-
|
||||
-int __init bcma_bus_scan_early(struct bcma_bus *bus,
|
||||
- struct bcma_device_id *match,
|
||||
- struct bcma_device *core)
|
||||
-{
|
||||
- u32 erombase;
|
||||
- u32 __iomem *eromptr, *eromend;
|
||||
-
|
||||
- int err = -ENODEV;
|
||||
- int core_num = 0;
|
||||
-
|
||||
- erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
|
||||
- if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
|
||||
- eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
|
||||
- if (!eromptr)
|
||||
- return -ENOMEM;
|
||||
- } else {
|
||||
- eromptr = bus->mmio;
|
||||
- }
|
||||
-
|
||||
- eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
|
||||
-
|
||||
- bcma_scan_switch_core(bus, erombase);
|
||||
-
|
||||
- while (eromptr < eromend) {
|
||||
- memset(core, 0, sizeof(*core));
|
||||
- INIT_LIST_HEAD(&core->list);
|
||||
- core->bus = bus;
|
||||
-
|
||||
- err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
|
||||
- if (err == -ENODEV) {
|
||||
- core_num++;
|
||||
- continue;
|
||||
- } else if (err == -ENXIO)
|
||||
- continue;
|
||||
- else if (err == -ESPIPE)
|
||||
- break;
|
||||
- else if (err < 0)
|
||||
- goto out;
|
||||
-
|
||||
- core->core_index = core_num++;
|
||||
- bus->nr_cores++;
|
||||
- bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
|
||||
- core->core_index, bcma_device_name(&core->id),
|
||||
- core->id.manuf, core->id.id, core->id.rev,
|
||||
- core->id.class);
|
||||
-
|
||||
- list_add_tail(&core->list, &bus->cores);
|
||||
- err = 0;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
-out:
|
||||
- if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
- iounmap(eromptr);
|
||||
|
||||
return err;
|
||||
}
|
||||
--- a/drivers/bcma/sprom.c
|
||||
+++ b/drivers/bcma/sprom.c
|
||||
@@ -579,7 +579,8 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
||||
u16 offset = BCMA_CC_SPROM;
|
||||
u16 *sprom;
|
||||
size_t sprom_sizes[] = { SSB_SPROMSIZE_WORDS_R4,
|
||||
- SSB_SPROMSIZE_WORDS_R10, };
|
||||
+ SSB_SPROMSIZE_WORDS_R10,
|
||||
+ SSB_SPROMSIZE_WORDS_R11, };
|
||||
int i, err = 0;
|
||||
|
||||
if (!bus->drv_cc.core)
|
||||
--- a/include/linux/bcma/bcma.h
|
||||
+++ b/include/linux/bcma/bcma.h
|
||||
@@ -318,6 +318,7 @@ struct bcma_bus {
|
||||
const struct bcma_host_ops *ops;
|
||||
|
||||
enum bcma_hosttype hosttype;
|
||||
+ bool host_is_pcie2; /* Used for BCMA_HOSTTYPE_PCI only */
|
||||
union {
|
||||
/* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */
|
||||
struct pci_dev *host_pci;
|
||||
--- a/include/linux/bcma/bcma_driver_pci.h
|
||||
+++ b/include/linux/bcma/bcma_driver_pci.h
|
||||
@@ -223,6 +223,7 @@ struct bcma_drv_pci_host {
|
||||
|
||||
struct bcma_drv_pci {
|
||||
struct bcma_device *core;
|
||||
+ u8 early_setup_done:1;
|
||||
u8 setup_done:1;
|
||||
u8 hostmode:1;
|
||||
|
||||
@@ -237,6 +238,7 @@ struct bcma_drv_pci {
|
||||
#define pcicore_write16(pc, offset, val) bcma_write16((pc)->core, offset, val)
|
||||
#define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val)
|
||||
|
||||
+extern void bcma_core_pci_early_init(struct bcma_drv_pci *pc);
|
||||
extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
|
||||
extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
|
||||
struct bcma_device *core, bool enable);
|
||||
--- a/include/linux/bcma/bcma_regs.h
|
||||
+++ b/include/linux/bcma/bcma_regs.h
|
||||
@@ -64,6 +64,8 @@
|
||||
#define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */
|
||||
#define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */
|
||||
|
||||
+#define BCMA_PCIE2_BAR0_WIN2 0x70
|
||||
+
|
||||
/* SiliconBackplane Address Map.
|
||||
* All regions may not exist on all chips.
|
||||
*/
|
||||
--- a/include/linux/bcma/bcma_soc.h
|
||||
+++ b/include/linux/bcma/bcma_soc.h
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
struct bcma_soc {
|
||||
struct bcma_bus bus;
|
||||
- struct bcma_device core_cc;
|
||||
- struct bcma_device core_mips;
|
||||
};
|
||||
|
||||
int __init bcma_host_soc_register(struct bcma_soc *soc);
|
||||
--- a/include/linux/ssb/ssb_regs.h
|
||||
+++ b/include/linux/ssb/ssb_regs.h
|
||||
@@ -173,6 +173,7 @@
|
||||
#define SSB_SPROMSIZE_BYTES_R123 (SSB_SPROMSIZE_WORDS_R123 * sizeof(u16))
|
||||
#define SSB_SPROMSIZE_BYTES_R4 (SSB_SPROMSIZE_WORDS_R4 * sizeof(u16))
|
||||
#define SSB_SPROMSIZE_WORDS_R10 230
|
||||
+#define SSB_SPROMSIZE_WORDS_R11 234
|
||||
#define SSB_SPROM_BASE1 0x1000
|
||||
#define SSB_SPROM_BASE31 0x0800
|
||||
#define SSB_SPROM_REVISION 0x007E
|
|
@ -1,355 +0,0 @@
|
|||
--- a/drivers/bcma/bcma_private.h
|
||||
+++ b/drivers/bcma/bcma_private.h
|
||||
@@ -26,6 +26,7 @@ bool bcma_wait_value(struct bcma_device
|
||||
int timeout);
|
||||
void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core);
|
||||
void bcma_init_bus(struct bcma_bus *bus);
|
||||
+void bcma_unregister_cores(struct bcma_bus *bus);
|
||||
int bcma_bus_register(struct bcma_bus *bus);
|
||||
void bcma_bus_unregister(struct bcma_bus *bus);
|
||||
int __init bcma_bus_early_register(struct bcma_bus *bus);
|
||||
@@ -101,6 +102,11 @@ static inline void __exit bcma_host_soc_
|
||||
|
||||
/* driver_pci.c */
|
||||
u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
|
||||
+void bcma_core_pci_up(struct bcma_drv_pci *pc);
|
||||
+void bcma_core_pci_down(struct bcma_drv_pci *pc);
|
||||
+
|
||||
+/* driver_pcie2.c */
|
||||
+void bcma_core_pcie2_up(struct bcma_drv_pcie2 *pcie2);
|
||||
|
||||
extern int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc);
|
||||
|
||||
--- a/drivers/bcma/driver_gpio.c
|
||||
+++ b/drivers/bcma/driver_gpio.c
|
||||
@@ -76,7 +76,7 @@ static void bcma_gpio_free(struct gpio_c
|
||||
bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
|
||||
}
|
||||
|
||||
-#if IS_BUILTIN(CONFIG_BCM47XX)
|
||||
+#if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
|
||||
static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
||||
@@ -215,7 +215,7 @@ int bcma_gpio_init(struct bcma_drv_cc *c
|
||||
chip->set = bcma_gpio_set_value;
|
||||
chip->direction_input = bcma_gpio_direction_input;
|
||||
chip->direction_output = bcma_gpio_direction_output;
|
||||
-#if IS_BUILTIN(CONFIG_BCM47XX)
|
||||
+#if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
|
||||
chip->to_irq = bcma_gpio_to_irq;
|
||||
#endif
|
||||
#if IS_BUILTIN(CONFIG_OF)
|
||||
--- a/drivers/bcma/driver_pci.c
|
||||
+++ b/drivers/bcma/driver_pci.c
|
||||
@@ -282,21 +282,21 @@ void bcma_core_pci_power_save(struct bcm
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_core_pci_power_save);
|
||||
|
||||
-int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
|
||||
+int bcma_core_pci_irq_ctl(struct bcma_bus *bus, struct bcma_device *core,
|
||||
bool enable)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
u32 coremask, tmp;
|
||||
int err = 0;
|
||||
|
||||
- if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
|
||||
+ if (bus->hosttype != BCMA_HOSTTYPE_PCI) {
|
||||
/* This bcma device is not on a PCI host-bus. So the IRQs are
|
||||
* not routed through the PCI core.
|
||||
* So we must not enable routing through the PCI core. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
- pdev = pc->core->bus->host_pci;
|
||||
+ pdev = bus->host_pci;
|
||||
|
||||
err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
|
||||
if (err)
|
||||
@@ -328,28 +328,12 @@ static void bcma_core_pci_extend_L1timer
|
||||
bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
|
||||
}
|
||||
|
||||
-void bcma_core_pci_up(struct bcma_bus *bus)
|
||||
+void bcma_core_pci_up(struct bcma_drv_pci *pc)
|
||||
{
|
||||
- struct bcma_drv_pci *pc;
|
||||
-
|
||||
- if (bus->hosttype != BCMA_HOSTTYPE_PCI)
|
||||
- return;
|
||||
-
|
||||
- pc = &bus->drv_pci[0];
|
||||
-
|
||||
bcma_core_pci_extend_L1timer(pc, true);
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(bcma_core_pci_up);
|
||||
|
||||
-void bcma_core_pci_down(struct bcma_bus *bus)
|
||||
+void bcma_core_pci_down(struct bcma_drv_pci *pc)
|
||||
{
|
||||
- struct bcma_drv_pci *pc;
|
||||
-
|
||||
- if (bus->hosttype != BCMA_HOSTTYPE_PCI)
|
||||
- return;
|
||||
-
|
||||
- pc = &bus->drv_pci[0];
|
||||
-
|
||||
bcma_core_pci_extend_L1timer(pc, false);
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(bcma_core_pci_down);
|
||||
--- a/drivers/bcma/driver_pci_host.c
|
||||
+++ b/drivers/bcma/driver_pci_host.c
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/pci.h>
|
||||
+#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <asm/paccess.h>
|
||||
--- a/drivers/bcma/driver_pcie2.c
|
||||
+++ b/drivers/bcma/driver_pcie2.c
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/bcma/bcma.h>
|
||||
+#include <linux/pci.h>
|
||||
|
||||
/**************************************************
|
||||
* R/W ops.
|
||||
@@ -156,14 +157,23 @@ static void pciedev_reg_pm_clk_period(st
|
||||
|
||||
void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2)
|
||||
{
|
||||
- struct bcma_chipinfo *ci = &pcie2->core->bus->chipinfo;
|
||||
+ struct bcma_bus *bus = pcie2->core->bus;
|
||||
+ struct bcma_chipinfo *ci = &bus->chipinfo;
|
||||
u32 tmp;
|
||||
|
||||
tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54));
|
||||
if ((tmp & 0xe) >> 1 == 2)
|
||||
bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17);
|
||||
|
||||
- /* TODO: Do we need pcie_reqsize? */
|
||||
+ switch (bus->chipinfo.id) {
|
||||
+ case BCMA_CHIP_ID_BCM4360:
|
||||
+ case BCMA_CHIP_ID_BCM4352:
|
||||
+ pcie2->reqsize = 1024;
|
||||
+ break;
|
||||
+ default:
|
||||
+ pcie2->reqsize = 128;
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3)
|
||||
bcma_core_pcie2_war_delay_perst_enab(pcie2, true);
|
||||
@@ -173,3 +183,18 @@ void bcma_core_pcie2_init(struct bcma_dr
|
||||
pciedev_crwlpciegen2_180(pcie2);
|
||||
pciedev_crwlpciegen2_182(pcie2);
|
||||
}
|
||||
+
|
||||
+/**************************************************
|
||||
+ * Runtime ops.
|
||||
+ **************************************************/
|
||||
+
|
||||
+void bcma_core_pcie2_up(struct bcma_drv_pcie2 *pcie2)
|
||||
+{
|
||||
+ struct bcma_bus *bus = pcie2->core->bus;
|
||||
+ struct pci_dev *dev = bus->host_pci;
|
||||
+ int err;
|
||||
+
|
||||
+ err = pcie_set_readrq(dev, pcie2->reqsize);
|
||||
+ if (err)
|
||||
+ bcma_err(bus, "Error setting PCI_EXP_DEVCTL_READRQ: %d\n", err);
|
||||
+}
|
||||
--- a/drivers/bcma/host_pci.c
|
||||
+++ b/drivers/bcma/host_pci.c
|
||||
@@ -213,16 +213,26 @@ static int bcma_host_pci_probe(struct pc
|
||||
/* Initialize struct, detect chip */
|
||||
bcma_init_bus(bus);
|
||||
|
||||
+ /* Scan bus to find out generation of PCIe core */
|
||||
+ err = bcma_bus_scan(bus);
|
||||
+ if (err)
|
||||
+ goto err_pci_unmap_mmio;
|
||||
+
|
||||
+ if (bcma_find_core(bus, BCMA_CORE_PCIE2))
|
||||
+ bus->host_is_pcie2 = true;
|
||||
+
|
||||
/* Register */
|
||||
err = bcma_bus_register(bus);
|
||||
if (err)
|
||||
- goto err_pci_unmap_mmio;
|
||||
+ goto err_unregister_cores;
|
||||
|
||||
pci_set_drvdata(dev, bus);
|
||||
|
||||
out:
|
||||
return err;
|
||||
|
||||
+err_unregister_cores:
|
||||
+ bcma_unregister_cores(bus);
|
||||
err_pci_unmap_mmio:
|
||||
pci_iounmap(dev, bus->mmio);
|
||||
err_pci_release_regions:
|
||||
@@ -283,9 +293,12 @@ static const struct pci_device_id bcma_p
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
|
||||
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) },
|
||||
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
|
||||
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43b1) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xa8db, BCM43217 (sic!) */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43228) }, /* 0xa8dc */
|
||||
@@ -310,3 +323,31 @@ void __exit bcma_host_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&bcma_pci_bridge_driver);
|
||||
}
|
||||
+
|
||||
+/**************************************************
|
||||
+ * Runtime ops for drivers.
|
||||
+ **************************************************/
|
||||
+
|
||||
+/* See also pcicore_up */
|
||||
+void bcma_host_pci_up(struct bcma_bus *bus)
|
||||
+{
|
||||
+ if (bus->hosttype != BCMA_HOSTTYPE_PCI)
|
||||
+ return;
|
||||
+
|
||||
+ if (bus->host_is_pcie2)
|
||||
+ bcma_core_pcie2_up(&bus->drv_pcie2);
|
||||
+ else
|
||||
+ bcma_core_pci_up(&bus->drv_pci[0]);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(bcma_host_pci_up);
|
||||
+
|
||||
+/* See also pcicore_down */
|
||||
+void bcma_host_pci_down(struct bcma_bus *bus)
|
||||
+{
|
||||
+ if (bus->hosttype != BCMA_HOSTTYPE_PCI)
|
||||
+ return;
|
||||
+
|
||||
+ if (!bus->host_is_pcie2)
|
||||
+ bcma_core_pci_down(&bus->drv_pci[0]);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(bcma_host_pci_down);
|
||||
--- a/drivers/bcma/main.c
|
||||
+++ b/drivers/bcma/main.c
|
||||
@@ -363,7 +363,7 @@ static int bcma_register_devices(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void bcma_unregister_cores(struct bcma_bus *bus)
|
||||
+void bcma_unregister_cores(struct bcma_bus *bus)
|
||||
{
|
||||
struct bcma_device *core, *tmp;
|
||||
|
||||
--- a/drivers/net/wireless/b43/main.c
|
||||
+++ b/drivers/net/wireless/b43/main.c
|
||||
@@ -4650,7 +4650,7 @@ static void b43_wireless_core_exit(struc
|
||||
switch (dev->dev->bus_type) {
|
||||
#ifdef CONFIG_B43_BCMA
|
||||
case B43_BUS_BCMA:
|
||||
- bcma_core_pci_down(dev->dev->bdev->bus);
|
||||
+ bcma_host_pci_down(dev->dev->bdev->bus);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_B43_SSB
|
||||
@@ -4697,9 +4697,9 @@ static int b43_wireless_core_init(struct
|
||||
switch (dev->dev->bus_type) {
|
||||
#ifdef CONFIG_B43_BCMA
|
||||
case B43_BUS_BCMA:
|
||||
- bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
|
||||
+ bcma_core_pci_irq_ctl(dev->dev->bdev->bus,
|
||||
dev->dev->bdev, true);
|
||||
- bcma_core_pci_up(dev->dev->bdev->bus);
|
||||
+ bcma_host_pci_up(dev->dev->bdev->bus);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_B43_SSB
|
||||
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
|
||||
@@ -4669,7 +4669,7 @@ static int brcms_b_attach(struct brcms_c
|
||||
brcms_c_coredisable(wlc_hw);
|
||||
|
||||
/* Match driver "down" state */
|
||||
- bcma_core_pci_down(wlc_hw->d11core->bus);
|
||||
+ bcma_host_pci_down(wlc_hw->d11core->bus);
|
||||
|
||||
/* turn off pll and xtal to match driver "down" state */
|
||||
brcms_b_xtal(wlc_hw, OFF);
|
||||
@@ -5002,7 +5002,7 @@ static int brcms_b_up_prep(struct brcms_
|
||||
* Configure pci/pcmcia here instead of in brcms_c_attach()
|
||||
* to allow mfg hotswap: down, hotswap (chip power cycle), up.
|
||||
*/
|
||||
- bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci[0], wlc_hw->d11core,
|
||||
+ bcma_core_pci_irq_ctl(wlc_hw->d11core->bus, wlc_hw->d11core,
|
||||
true);
|
||||
|
||||
/*
|
||||
@@ -5012,12 +5012,12 @@ static int brcms_b_up_prep(struct brcms_
|
||||
*/
|
||||
if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
|
||||
/* put SB PCI in down state again */
|
||||
- bcma_core_pci_down(wlc_hw->d11core->bus);
|
||||
+ bcma_host_pci_down(wlc_hw->d11core->bus);
|
||||
brcms_b_xtal(wlc_hw, OFF);
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
- bcma_core_pci_up(wlc_hw->d11core->bus);
|
||||
+ bcma_host_pci_up(wlc_hw->d11core->bus);
|
||||
|
||||
/* reset the d11 core */
|
||||
brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
|
||||
@@ -5214,7 +5214,7 @@ static int brcms_b_down_finish(struct br
|
||||
|
||||
/* turn off primary xtal and pll */
|
||||
if (!wlc_hw->noreset) {
|
||||
- bcma_core_pci_down(wlc_hw->d11core->bus);
|
||||
+ bcma_host_pci_down(wlc_hw->d11core->bus);
|
||||
brcms_b_xtal(wlc_hw, OFF);
|
||||
}
|
||||
}
|
||||
--- a/include/linux/bcma/bcma.h
|
||||
+++ b/include/linux/bcma/bcma.h
|
||||
@@ -434,6 +434,9 @@ static inline struct bcma_device *bcma_f
|
||||
return bcma_find_core_unit(bus, coreid, 0);
|
||||
}
|
||||
|
||||
+extern void bcma_host_pci_up(struct bcma_bus *bus);
|
||||
+extern void bcma_host_pci_down(struct bcma_bus *bus);
|
||||
+
|
||||
extern bool bcma_core_is_enabled(struct bcma_device *core);
|
||||
extern void bcma_core_disable(struct bcma_device *core, u32 flags);
|
||||
extern int bcma_core_enable(struct bcma_device *core, u32 flags);
|
||||
--- a/include/linux/bcma/bcma_driver_pci.h
|
||||
+++ b/include/linux/bcma/bcma_driver_pci.h
|
||||
@@ -240,10 +240,8 @@ struct bcma_drv_pci {
|
||||
|
||||
extern void bcma_core_pci_early_init(struct bcma_drv_pci *pc);
|
||||
extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
|
||||
-extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
|
||||
+extern int bcma_core_pci_irq_ctl(struct bcma_bus *bus,
|
||||
struct bcma_device *core, bool enable);
|
||||
-extern void bcma_core_pci_up(struct bcma_bus *bus);
|
||||
-extern void bcma_core_pci_down(struct bcma_bus *bus);
|
||||
extern void bcma_core_pci_power_save(struct bcma_bus *bus, bool up);
|
||||
|
||||
extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
|
||||
--- a/include/linux/bcma/bcma_driver_pcie2.h
|
||||
+++ b/include/linux/bcma/bcma_driver_pcie2.h
|
||||
@@ -143,6 +143,8 @@
|
||||
|
||||
struct bcma_drv_pcie2 {
|
||||
struct bcma_device *core;
|
||||
+
|
||||
+ u16 reqsize;
|
||||
};
|
||||
|
||||
#define pcie2_read16(pcie2, offset) bcma_read16((pcie2)->core, offset)
|
|
@ -1,21 +0,0 @@
|
|||
From: Vadim Kochan <vadim4j@gmail.com>
|
||||
Date: Mon, 12 Jan 2015 16:34:05 +0200
|
||||
Subject: [PATCH] nl80211: Allow set network namespace by fd
|
||||
|
||||
Added new NL80211_ATTR_NETNS_FD which allows to
|
||||
set namespace via nl80211 by fd.
|
||||
|
||||
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
|
||||
--- a/net/core/net_namespace.c
|
||||
+++ b/net/core/net_namespace.c
|
||||
@@ -361,6 +361,7 @@ struct net *get_net_ns_by_fd(int fd)
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
#endif
|
||||
+EXPORT_SYMBOL_GPL(get_net_ns_by_fd);
|
||||
|
||||
struct net *get_net_ns_by_pid(pid_t pid)
|
||||
{
|
|
@ -1,829 +0,0 @@
|
|||
From 9d54c8a33eec78289b1b3f6e10874719c27ce0a7 Mon Sep 17 00:00:00 2001
|
||||
From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Date: Tue, 25 Feb 2014 13:25:22 -0300
|
||||
Subject: [PATCH] UBI: R/O block driver on top of UBI volumes
|
||||
|
||||
This commit introduces read-only block device emulation on top of UBI volumes.
|
||||
|
||||
Given UBI takes care of wear leveling and bad block management it's possible
|
||||
to add a thin layer to enable block device access to UBI volumes.
|
||||
This allows to use a block-oriented filesystem on a flash device.
|
||||
|
||||
The UBI block devices are meant to be used in conjunction with any
|
||||
regular, block-oriented file system (e.g. ext4), although it's primarily
|
||||
targeted at read-only file systems, such as squashfs.
|
||||
|
||||
Block devices are created upon user request through new ioctls:
|
||||
UBI_IOCVOLATTBLK to attach and UBI_IOCVOLDETBLK to detach.
|
||||
Also, a new UBI module parameter is added 'ubi.block'. This parameter is
|
||||
needed in order to attach a block device on boot-up time, allowing to
|
||||
mount the rootfs on a ubiblock device.
|
||||
For instance, you could have these kernel parameters:
|
||||
|
||||
ubi.mtd=5 ubi.block=0,0 root=/dev/ubiblock0_0
|
||||
|
||||
Or, if you compile ubi as a module:
|
||||
|
||||
$ modprobe ubi mtd=/dev/mtd5 block=/dev/ubi0_0
|
||||
|
||||
Artem: amend commentaries and massage the patch a little bit.
|
||||
|
||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
---
|
||||
drivers/mtd/ubi/Kconfig | 15 +
|
||||
drivers/mtd/ubi/Makefile | 1 +
|
||||
drivers/mtd/ubi/block.c | 646 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/mtd/ubi/build.c | 11 +
|
||||
drivers/mtd/ubi/cdev.c | 20 ++
|
||||
drivers/mtd/ubi/ubi.h | 14 +
|
||||
include/uapi/mtd/ubi-user.h | 11 +
|
||||
7 files changed, 718 insertions(+)
|
||||
create mode 100644 drivers/mtd/ubi/block.c
|
||||
|
||||
--- a/drivers/mtd/ubi/Kconfig
|
||||
+++ b/drivers/mtd/ubi/Kconfig
|
||||
@@ -87,4 +87,19 @@ config MTD_UBI_GLUEBI
|
||||
work on top of UBI. Do not enable this unless you use legacy
|
||||
software.
|
||||
|
||||
+config MTD_UBI_BLOCK
|
||||
+ bool "Read-only block devices on top of UBI volumes"
|
||||
+ default n
|
||||
+ help
|
||||
+ This option enables read-only UBI block devices support. UBI block
|
||||
+ devices will be layered on top of UBI volumes, which means that the
|
||||
+ UBI driver will transparently handle things like bad eraseblocks and
|
||||
+ bit-flips. You can put any block-oriented file system on top of UBI
|
||||
+ volumes in read-only mode (e.g., ext4), but it is probably most
|
||||
+ practical for read-only file systems, like squashfs.
|
||||
+
|
||||
+ When selected, this feature will be built in the UBI driver.
|
||||
+
|
||||
+ If in doubt, say "N".
|
||||
+
|
||||
endif # MTD_UBI
|
||||
--- a/drivers/mtd/ubi/Makefile
|
||||
+++ b/drivers/mtd/ubi/Makefile
|
||||
@@ -3,5 +3,6 @@ obj-$(CONFIG_MTD_UBI) += ubi.o
|
||||
ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
|
||||
ubi-y += misc.o debug.o
|
||||
ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o
|
||||
+ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o
|
||||
|
||||
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -0,0 +1,646 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2014 Ezequiel Garcia
|
||||
+ * Copyright (c) 2011 Free Electrons
|
||||
+ *
|
||||
+ * Driver parameter handling strongly based on drivers/mtd/ubi/build.c
|
||||
+ * Copyright (c) International Business Machines Corp., 2006
|
||||
+ * Copyright (c) Nokia Corporation, 2007
|
||||
+ * Authors: Artem Bityutskiy, Frank Haverkamp
|
||||
+ *
|
||||
+ * 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, version 2.
|
||||
+ *
|
||||
+ * 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.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Read-only block devices on top of UBI volumes
|
||||
+ *
|
||||
+ * A simple implementation to allow a block device to be layered on top of a
|
||||
+ * UBI volume. The implementation is provided by creating a static 1-to-1
|
||||
+ * mapping between the block device and the UBI volume.
|
||||
+ *
|
||||
+ * The addressed byte is obtained from the addressed block sector, which is
|
||||
+ * mapped linearly into the corresponding LEB:
|
||||
+ *
|
||||
+ * LEB number = addressed byte / LEB size
|
||||
+ *
|
||||
+ * This feature is compiled in the UBI core, and adds a new 'block' parameter
|
||||
+ * to allow early block device attaching. Runtime block attach/detach for UBI
|
||||
+ * volumes is provided through two new UBI ioctls: UBI_IOCVOLATTBLK and
|
||||
+ * UBI_IOCVOLDETBLK.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/list.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/vmalloc.h>
|
||||
+#include <linux/mtd/ubi.h>
|
||||
+#include <linux/workqueue.h>
|
||||
+#include <linux/blkdev.h>
|
||||
+#include <linux/hdreg.h>
|
||||
+#include <asm/div64.h>
|
||||
+
|
||||
+#include "ubi-media.h"
|
||||
+#include "ubi.h"
|
||||
+
|
||||
+/* Maximum number of supported devices */
|
||||
+#define UBIBLOCK_MAX_DEVICES 32
|
||||
+
|
||||
+/* Maximum length of the 'block=' parameter */
|
||||
+#define UBIBLOCK_PARAM_LEN 63
|
||||
+
|
||||
+/* Maximum number of comma-separated items in the 'block=' parameter */
|
||||
+#define UBIBLOCK_PARAM_COUNT 2
|
||||
+
|
||||
+struct ubiblock_param {
|
||||
+ int ubi_num;
|
||||
+ int vol_id;
|
||||
+ char name[UBIBLOCK_PARAM_LEN+1];
|
||||
+};
|
||||
+
|
||||
+/* Numbers of elements set in the @ubiblock_param array */
|
||||
+static int ubiblock_devs __initdata;
|
||||
+
|
||||
+/* MTD devices specification parameters */
|
||||
+static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata;
|
||||
+
|
||||
+struct ubiblock {
|
||||
+ struct ubi_volume_desc *desc;
|
||||
+ int ubi_num;
|
||||
+ int vol_id;
|
||||
+ int refcnt;
|
||||
+ int leb_size;
|
||||
+
|
||||
+ struct gendisk *gd;
|
||||
+ struct request_queue *rq;
|
||||
+
|
||||
+ struct workqueue_struct *wq;
|
||||
+ struct work_struct work;
|
||||
+
|
||||
+ struct mutex dev_mutex;
|
||||
+ spinlock_t queue_lock;
|
||||
+ struct list_head list;
|
||||
+};
|
||||
+
|
||||
+/* Linked list of all ubiblock instances */
|
||||
+static LIST_HEAD(ubiblock_devices);
|
||||
+static DEFINE_MUTEX(devices_mutex);
|
||||
+static int ubiblock_major;
|
||||
+
|
||||
+static int __init ubiblock_set_param(const char *val,
|
||||
+ const struct kernel_param *kp)
|
||||
+{
|
||||
+ int i, ret;
|
||||
+ size_t len;
|
||||
+ struct ubiblock_param *param;
|
||||
+ char buf[UBIBLOCK_PARAM_LEN];
|
||||
+ char *pbuf = &buf[0];
|
||||
+ char *tokens[UBIBLOCK_PARAM_COUNT];
|
||||
+
|
||||
+ if (!val)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ len = strnlen(val, UBIBLOCK_PARAM_LEN);
|
||||
+ if (len == 0) {
|
||||
+ ubi_warn("block: empty 'block=' parameter - ignored\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (len == UBIBLOCK_PARAM_LEN) {
|
||||
+ ubi_err("block: parameter \"%s\" is too long, max. is %d\n",
|
||||
+ val, UBIBLOCK_PARAM_LEN);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ strcpy(buf, val);
|
||||
+
|
||||
+ /* Get rid of the final newline */
|
||||
+ if (buf[len - 1] == '\n')
|
||||
+ buf[len - 1] = '\0';
|
||||
+
|
||||
+ for (i = 0; i < UBIBLOCK_PARAM_COUNT; i++)
|
||||
+ tokens[i] = strsep(&pbuf, ",");
|
||||
+
|
||||
+ param = &ubiblock_param[ubiblock_devs];
|
||||
+ if (tokens[1]) {
|
||||
+ /* Two parameters: can be 'ubi, vol_id' or 'ubi, vol_name' */
|
||||
+ ret = kstrtoint(tokens[0], 10, ¶m->ubi_num);
|
||||
+ if (ret < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Second param can be a number or a name */
|
||||
+ ret = kstrtoint(tokens[1], 10, ¶m->vol_id);
|
||||
+ if (ret < 0) {
|
||||
+ param->vol_id = -1;
|
||||
+ strcpy(param->name, tokens[1]);
|
||||
+ }
|
||||
+
|
||||
+ } else {
|
||||
+ /* One parameter: must be device path */
|
||||
+ strcpy(param->name, tokens[0]);
|
||||
+ param->ubi_num = -1;
|
||||
+ param->vol_id = -1;
|
||||
+ }
|
||||
+
|
||||
+ ubiblock_devs++;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct kernel_param_ops ubiblock_param_ops = {
|
||||
+ .set = ubiblock_set_param,
|
||||
+};
|
||||
+module_param_cb(block, &ubiblock_param_ops, NULL, 0);
|
||||
+MODULE_PARM_DESC(block, "Attach block devices to UBI volumes. Parameter format: block=<path|dev,num|dev,name>.\n"
|
||||
+ "Multiple \"block\" parameters may be specified.\n"
|
||||
+ "UBI volumes may be specified by their number, name, or path to the device node.\n"
|
||||
+ "Examples\n"
|
||||
+ "Using the UBI volume path:\n"
|
||||
+ "ubi.block=/dev/ubi0_0\n"
|
||||
+ "Using the UBI device, and the volume name:\n"
|
||||
+ "ubi.block=0,rootfs\n"
|
||||
+ "Using both UBI device number and UBI volume number:\n"
|
||||
+ "ubi.block=0,0\n");
|
||||
+
|
||||
+static struct ubiblock *find_dev_nolock(int ubi_num, int vol_id)
|
||||
+{
|
||||
+ struct ubiblock *dev;
|
||||
+
|
||||
+ list_for_each_entry(dev, &ubiblock_devices, list)
|
||||
+ if (dev->ubi_num == ubi_num && dev->vol_id == vol_id)
|
||||
+ return dev;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static int ubiblock_read_to_buf(struct ubiblock *dev, char *buffer,
|
||||
+ int leb, int offset, int len)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ubi_read(dev->desc, leb, buffer, offset, len);
|
||||
+ if (ret) {
|
||||
+ ubi_err("%s ubi_read error %d",
|
||||
+ dev->gd->disk_name, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int ubiblock_read(struct ubiblock *dev, char *buffer,
|
||||
+ sector_t sec, int len)
|
||||
+{
|
||||
+ int ret, leb, offset;
|
||||
+ int bytes_left = len;
|
||||
+ int to_read = len;
|
||||
+ loff_t pos = sec << 9;
|
||||
+
|
||||
+ /* Get LEB:offset address to read from */
|
||||
+ offset = do_div(pos, dev->leb_size);
|
||||
+ leb = pos;
|
||||
+
|
||||
+ while (bytes_left) {
|
||||
+ /*
|
||||
+ * We can only read one LEB at a time. Therefore if the read
|
||||
+ * length is larger than one LEB size, we split the operation.
|
||||
+ */
|
||||
+ if (offset + to_read > dev->leb_size)
|
||||
+ to_read = dev->leb_size - offset;
|
||||
+
|
||||
+ ret = ubiblock_read_to_buf(dev, buffer, leb, offset, to_read);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ buffer += to_read;
|
||||
+ bytes_left -= to_read;
|
||||
+ to_read = bytes_left;
|
||||
+ leb += 1;
|
||||
+ offset = 0;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int do_ubiblock_request(struct ubiblock *dev, struct request *req)
|
||||
+{
|
||||
+ int len, ret;
|
||||
+ sector_t sec;
|
||||
+
|
||||
+ if (req->cmd_type != REQ_TYPE_FS)
|
||||
+ return -EIO;
|
||||
+
|
||||
+ if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
|
||||
+ get_capacity(req->rq_disk))
|
||||
+ return -EIO;
|
||||
+
|
||||
+ if (rq_data_dir(req) != READ)
|
||||
+ return -ENOSYS; /* Write not implemented */
|
||||
+
|
||||
+ sec = blk_rq_pos(req);
|
||||
+ len = blk_rq_cur_bytes(req);
|
||||
+
|
||||
+ /*
|
||||
+ * Let's prevent the device from being removed while we're doing I/O
|
||||
+ * work. Notice that this means we serialize all the I/O operations,
|
||||
+ * but it's probably of no impact given the NAND core serializes
|
||||
+ * flash access anyway.
|
||||
+ */
|
||||
+ mutex_lock(&dev->dev_mutex);
|
||||
+ ret = ubiblock_read(dev, req->buffer, sec, len);
|
||||
+ mutex_unlock(&dev->dev_mutex);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void ubiblock_do_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct ubiblock *dev =
|
||||
+ container_of(work, struct ubiblock, work);
|
||||
+ struct request_queue *rq = dev->rq;
|
||||
+ struct request *req;
|
||||
+ int res;
|
||||
+
|
||||
+ spin_lock_irq(rq->queue_lock);
|
||||
+
|
||||
+ req = blk_fetch_request(rq);
|
||||
+ while (req) {
|
||||
+
|
||||
+ spin_unlock_irq(rq->queue_lock);
|
||||
+ res = do_ubiblock_request(dev, req);
|
||||
+ spin_lock_irq(rq->queue_lock);
|
||||
+
|
||||
+ /*
|
||||
+ * If we're done with this request,
|
||||
+ * we need to fetch a new one
|
||||
+ */
|
||||
+ if (!__blk_end_request_cur(req, res))
|
||||
+ req = blk_fetch_request(rq);
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock_irq(rq->queue_lock);
|
||||
+}
|
||||
+
|
||||
+static void ubiblock_request(struct request_queue *rq)
|
||||
+{
|
||||
+ struct ubiblock *dev;
|
||||
+ struct request *req;
|
||||
+
|
||||
+ dev = rq->queuedata;
|
||||
+
|
||||
+ if (!dev)
|
||||
+ while ((req = blk_fetch_request(rq)) != NULL)
|
||||
+ __blk_end_request_all(req, -ENODEV);
|
||||
+ else
|
||||
+ queue_work(dev->wq, &dev->work);
|
||||
+}
|
||||
+
|
||||
+static int ubiblock_open(struct block_device *bdev, fmode_t mode)
|
||||
+{
|
||||
+ struct ubiblock *dev = bdev->bd_disk->private_data;
|
||||
+ int ret;
|
||||
+
|
||||
+ mutex_lock(&dev->dev_mutex);
|
||||
+ if (dev->refcnt > 0) {
|
||||
+ /*
|
||||
+ * The volume is already open, just increase the reference
|
||||
+ * counter.
|
||||
+ */
|
||||
+ goto out_done;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * We want users to be aware they should only mount us as read-only.
|
||||
+ * It's just a paranoid check, as write requests will get rejected
|
||||
+ * in any case.
|
||||
+ */
|
||||
+ if (mode & FMODE_WRITE) {
|
||||
+ ret = -EPERM;
|
||||
+ goto out_unlock;
|
||||
+ }
|
||||
+
|
||||
+ dev->desc = ubi_open_volume(dev->ubi_num, dev->vol_id, UBI_READONLY);
|
||||
+ if (IS_ERR(dev->desc)) {
|
||||
+ ubi_err("%s failed to open ubi volume %d_%d",
|
||||
+ dev->gd->disk_name, dev->ubi_num, dev->vol_id);
|
||||
+ ret = PTR_ERR(dev->desc);
|
||||
+ dev->desc = NULL;
|
||||
+ goto out_unlock;
|
||||
+ }
|
||||
+
|
||||
+out_done:
|
||||
+ dev->refcnt++;
|
||||
+ mutex_unlock(&dev->dev_mutex);
|
||||
+ return 0;
|
||||
+
|
||||
+out_unlock:
|
||||
+ mutex_unlock(&dev->dev_mutex);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void ubiblock_release(struct gendisk *gd, fmode_t mode)
|
||||
+{
|
||||
+ struct ubiblock *dev = gd->private_data;
|
||||
+
|
||||
+ mutex_lock(&dev->dev_mutex);
|
||||
+ dev->refcnt--;
|
||||
+ if (dev->refcnt == 0) {
|
||||
+ ubi_close_volume(dev->desc);
|
||||
+ dev->desc = NULL;
|
||||
+ }
|
||||
+ mutex_unlock(&dev->dev_mutex);
|
||||
+}
|
||||
+
|
||||
+static int ubiblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
+{
|
||||
+ /* Some tools might require this information */
|
||||
+ geo->heads = 1;
|
||||
+ geo->cylinders = 1;
|
||||
+ geo->sectors = get_capacity(bdev->bd_disk);
|
||||
+ geo->start = 0;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct block_device_operations ubiblock_ops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .open = ubiblock_open,
|
||||
+ .release = ubiblock_release,
|
||||
+ .getgeo = ubiblock_getgeo,
|
||||
+};
|
||||
+
|
||||
+int ubiblock_add(struct ubi_volume_info *vi)
|
||||
+{
|
||||
+ struct ubiblock *dev;
|
||||
+ struct gendisk *gd;
|
||||
+ int disk_capacity;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Check that the volume isn't already handled */
|
||||
+ mutex_lock(&devices_mutex);
|
||||
+ if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
|
||||
+ mutex_unlock(&devices_mutex);
|
||||
+ return -EEXIST;
|
||||
+ }
|
||||
+ mutex_unlock(&devices_mutex);
|
||||
+
|
||||
+ dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL);
|
||||
+ if (!dev)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_init(&dev->dev_mutex);
|
||||
+
|
||||
+ dev->ubi_num = vi->ubi_num;
|
||||
+ dev->vol_id = vi->vol_id;
|
||||
+ dev->leb_size = vi->usable_leb_size;
|
||||
+
|
||||
+ /* Initialize the gendisk of this ubiblock device */
|
||||
+ gd = alloc_disk(1);
|
||||
+ if (!gd) {
|
||||
+ ubi_err("block: alloc_disk failed");
|
||||
+ ret = -ENODEV;
|
||||
+ goto out_free_dev;
|
||||
+ }
|
||||
+
|
||||
+ gd->fops = &ubiblock_ops;
|
||||
+ gd->major = ubiblock_major;
|
||||
+ gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
|
||||
+ gd->private_data = dev;
|
||||
+ sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
|
||||
+ disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
|
||||
+ set_capacity(gd, disk_capacity);
|
||||
+ dev->gd = gd;
|
||||
+
|
||||
+ spin_lock_init(&dev->queue_lock);
|
||||
+ dev->rq = blk_init_queue(ubiblock_request, &dev->queue_lock);
|
||||
+ if (!dev->rq) {
|
||||
+ ubi_err("block: blk_init_queue failed");
|
||||
+ ret = -ENODEV;
|
||||
+ goto out_put_disk;
|
||||
+ }
|
||||
+
|
||||
+ dev->rq->queuedata = dev;
|
||||
+ dev->gd->queue = dev->rq;
|
||||
+
|
||||
+ /*
|
||||
+ * Create one workqueue per volume (per registered block device).
|
||||
+ * Rembember workqueues are cheap, they're not threads.
|
||||
+ */
|
||||
+ dev->wq = alloc_workqueue(gd->disk_name, 0, 0);
|
||||
+ if (!dev->wq)
|
||||
+ goto out_free_queue;
|
||||
+ INIT_WORK(&dev->work, ubiblock_do_work);
|
||||
+
|
||||
+ mutex_lock(&devices_mutex);
|
||||
+ list_add_tail(&dev->list, &ubiblock_devices);
|
||||
+ mutex_unlock(&devices_mutex);
|
||||
+
|
||||
+ /* Must be the last step: anyone can call file ops from now on */
|
||||
+ add_disk(dev->gd);
|
||||
+ ubi_msg("%s created from ubi%d:%d(%s)",
|
||||
+ dev->gd->disk_name, dev->ubi_num, dev->vol_id, vi->name);
|
||||
+ return 0;
|
||||
+
|
||||
+out_free_queue:
|
||||
+ blk_cleanup_queue(dev->rq);
|
||||
+out_put_disk:
|
||||
+ put_disk(dev->gd);
|
||||
+out_free_dev:
|
||||
+ kfree(dev);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void ubiblock_cleanup(struct ubiblock *dev)
|
||||
+{
|
||||
+ del_gendisk(dev->gd);
|
||||
+ blk_cleanup_queue(dev->rq);
|
||||
+ ubi_msg("%s released", dev->gd->disk_name);
|
||||
+ put_disk(dev->gd);
|
||||
+}
|
||||
+
|
||||
+int ubiblock_del(struct ubi_volume_info *vi)
|
||||
+{
|
||||
+ struct ubiblock *dev;
|
||||
+
|
||||
+ mutex_lock(&devices_mutex);
|
||||
+ dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
|
||||
+ if (!dev) {
|
||||
+ mutex_unlock(&devices_mutex);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* Found a device, let's lock it so we can check if it's busy */
|
||||
+ mutex_lock(&dev->dev_mutex);
|
||||
+ if (dev->refcnt > 0) {
|
||||
+ mutex_unlock(&dev->dev_mutex);
|
||||
+ mutex_unlock(&devices_mutex);
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ /* Remove from device list */
|
||||
+ list_del(&dev->list);
|
||||
+ mutex_unlock(&devices_mutex);
|
||||
+
|
||||
+ /* Flush pending work and stop this workqueue */
|
||||
+ destroy_workqueue(dev->wq);
|
||||
+
|
||||
+ ubiblock_cleanup(dev);
|
||||
+ mutex_unlock(&dev->dev_mutex);
|
||||
+ kfree(dev);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void ubiblock_resize(struct ubi_volume_info *vi)
|
||||
+{
|
||||
+ struct ubiblock *dev;
|
||||
+ int disk_capacity;
|
||||
+
|
||||
+ /*
|
||||
+ * Need to lock the device list until we stop using the device,
|
||||
+ * otherwise the device struct might get released in 'ubiblock_del()'.
|
||||
+ */
|
||||
+ mutex_lock(&devices_mutex);
|
||||
+ dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
|
||||
+ if (!dev) {
|
||||
+ mutex_unlock(&devices_mutex);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ mutex_lock(&dev->dev_mutex);
|
||||
+ disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
|
||||
+ set_capacity(dev->gd, disk_capacity);
|
||||
+ ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size);
|
||||
+ mutex_unlock(&dev->dev_mutex);
|
||||
+ mutex_unlock(&devices_mutex);
|
||||
+}
|
||||
+
|
||||
+static int ubiblock_notify(struct notifier_block *nb,
|
||||
+ unsigned long notification_type, void *ns_ptr)
|
||||
+{
|
||||
+ struct ubi_notification *nt = ns_ptr;
|
||||
+
|
||||
+ switch (notification_type) {
|
||||
+ case UBI_VOLUME_ADDED:
|
||||
+ /*
|
||||
+ * We want to enforce explicit block device attaching for
|
||||
+ * volumes, so when a volume is added we do nothing.
|
||||
+ */
|
||||
+ break;
|
||||
+ case UBI_VOLUME_REMOVED:
|
||||
+ ubiblock_del(&nt->vi);
|
||||
+ break;
|
||||
+ case UBI_VOLUME_RESIZED:
|
||||
+ ubiblock_resize(&nt->vi);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ return NOTIFY_OK;
|
||||
+}
|
||||
+
|
||||
+static struct notifier_block ubiblock_notifier = {
|
||||
+ .notifier_call = ubiblock_notify,
|
||||
+};
|
||||
+
|
||||
+static struct ubi_volume_desc * __init
|
||||
+open_volume_desc(const char *name, int ubi_num, int vol_id)
|
||||
+{
|
||||
+ if (ubi_num == -1)
|
||||
+ /* No ubi num, name must be a vol device path */
|
||||
+ return ubi_open_volume_path(name, UBI_READONLY);
|
||||
+ else if (vol_id == -1)
|
||||
+ /* No vol_id, must be vol_name */
|
||||
+ return ubi_open_volume_nm(ubi_num, name, UBI_READONLY);
|
||||
+ else
|
||||
+ return ubi_open_volume(ubi_num, vol_id, UBI_READONLY);
|
||||
+}
|
||||
+
|
||||
+static int __init ubiblock_attach_from_param(void)
|
||||
+{
|
||||
+ int i, ret;
|
||||
+ struct ubiblock_param *p;
|
||||
+ struct ubi_volume_desc *desc;
|
||||
+ struct ubi_volume_info vi;
|
||||
+
|
||||
+ for (i = 0; i < ubiblock_devs; i++) {
|
||||
+ p = &ubiblock_param[i];
|
||||
+
|
||||
+ desc = open_volume_desc(p->name, p->ubi_num, p->vol_id);
|
||||
+ if (IS_ERR(desc)) {
|
||||
+ ubi_err("block: can't open volume, err=%ld\n",
|
||||
+ PTR_ERR(desc));
|
||||
+ ret = PTR_ERR(desc);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ ubi_get_volume_info(desc, &vi);
|
||||
+ ubi_close_volume(desc);
|
||||
+
|
||||
+ ret = ubiblock_add(&vi);
|
||||
+ if (ret) {
|
||||
+ ubi_err("block: can't add '%s' volume, err=%d\n",
|
||||
+ vi.name, ret);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void ubiblock_detach_all(void)
|
||||
+{
|
||||
+ struct ubiblock *next;
|
||||
+ struct ubiblock *dev;
|
||||
+
|
||||
+ list_for_each_entry_safe(dev, next, &ubiblock_devices, list) {
|
||||
+ /* Flush pending work and stop workqueue */
|
||||
+ destroy_workqueue(dev->wq);
|
||||
+ /* The module is being forcefully removed */
|
||||
+ WARN_ON(dev->desc);
|
||||
+ /* Remove from device list */
|
||||
+ list_del(&dev->list);
|
||||
+ ubiblock_cleanup(dev);
|
||||
+ kfree(dev);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int __init ubiblock_init(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ubiblock_major = register_blkdev(0, "ubiblock");
|
||||
+ if (ubiblock_major < 0)
|
||||
+ return ubiblock_major;
|
||||
+
|
||||
+ /* Attach block devices from 'block=' module param */
|
||||
+ ret = ubiblock_attach_from_param();
|
||||
+ if (ret)
|
||||
+ goto err_detach;
|
||||
+
|
||||
+ /*
|
||||
+ * Block devices needs to be attached to volumes explicitly
|
||||
+ * upon user request. So we ignore existing volumes.
|
||||
+ */
|
||||
+ ret = ubi_register_volume_notifier(&ubiblock_notifier, 1);
|
||||
+ if (ret)
|
||||
+ goto err_unreg;
|
||||
+ return 0;
|
||||
+
|
||||
+err_unreg:
|
||||
+ unregister_blkdev(ubiblock_major, "ubiblock");
|
||||
+err_detach:
|
||||
+ ubiblock_detach_all();
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void __exit ubiblock_exit(void)
|
||||
+{
|
||||
+ ubi_unregister_volume_notifier(&ubiblock_notifier);
|
||||
+ ubiblock_detach_all();
|
||||
+ unregister_blkdev(ubiblock_major, "ubiblock");
|
||||
+}
|
||||
--- a/drivers/mtd/ubi/build.c
|
||||
+++ b/drivers/mtd/ubi/build.c
|
||||
@@ -1298,6 +1298,15 @@ static int __init ubi_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
+ err = ubiblock_init();
|
||||
+ if (err) {
|
||||
+ ubi_err("block: cannot initialize, error %d", err);
|
||||
+
|
||||
+ /* See comment above re-ubi_is_module(). */
|
||||
+ if (ubi_is_module())
|
||||
+ goto out_detach;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
out_detach:
|
||||
@@ -1326,6 +1335,8 @@ static void __exit ubi_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
+ ubiblock_exit();
|
||||
+
|
||||
for (i = 0; i < UBI_MAX_DEVICES; i++)
|
||||
if (ubi_devices[i]) {
|
||||
mutex_lock(&ubi_devices_mutex);
|
||||
--- a/drivers/mtd/ubi/cdev.c
|
||||
+++ b/drivers/mtd/ubi/cdev.c
|
||||
@@ -561,6 +561,26 @@ static long vol_cdev_ioctl(struct file *
|
||||
break;
|
||||
}
|
||||
|
||||
+ /* Attach a block device to an UBI volume */
|
||||
+ case UBI_IOCVOLATTBLK:
|
||||
+ {
|
||||
+ struct ubi_volume_info vi;
|
||||
+
|
||||
+ ubi_get_volume_info(desc, &vi);
|
||||
+ err = ubiblock_add(&vi);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Dettach a block device from an UBI volume */
|
||||
+ case UBI_IOCVOLDETBLK:
|
||||
+ {
|
||||
+ struct ubi_volume_info vi;
|
||||
+
|
||||
+ ubi_get_volume_info(desc, &vi);
|
||||
+ err = ubiblock_del(&vi);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
default:
|
||||
err = -ENOTTY;
|
||||
break;
|
||||
--- a/drivers/mtd/ubi/ubi.h
|
||||
+++ b/drivers/mtd/ubi/ubi.h
|
||||
@@ -864,6 +864,20 @@ int ubi_update_fastmap(struct ubi_device
|
||||
int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
||||
int fm_anchor);
|
||||
|
||||
+/* block.c */
|
||||
+#ifdef CONFIG_MTD_UBI_BLOCK
|
||||
+int ubiblock_init(void);
|
||||
+void ubiblock_exit(void);
|
||||
+int ubiblock_add(struct ubi_volume_info *vi);
|
||||
+int ubiblock_del(struct ubi_volume_info *vi);
|
||||
+#else
|
||||
+static inline int ubiblock_init(void) { return 0; }
|
||||
+static inline void ubiblock_exit(void) {}
|
||||
+static inline int ubiblock_add(struct ubi_volume_info *vi) { return -ENOTTY; }
|
||||
+static inline int ubiblock_del(struct ubi_volume_info *vi) { return -ENOTTY; }
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
/*
|
||||
* ubi_rb_for_each_entry - walk an RB-tree.
|
||||
* @rb: a pointer to type 'struct rb_node' to use as a loop counter
|
||||
--- a/include/uapi/mtd/ubi-user.h
|
||||
+++ b/include/uapi/mtd/ubi-user.h
|
||||
@@ -134,6 +134,13 @@
|
||||
* used. A pointer to a &struct ubi_set_vol_prop_req object is expected to be
|
||||
* passed. The object describes which property should be set, and to which value
|
||||
* it should be set.
|
||||
+ *
|
||||
+ * Block devices on UBI volumes
|
||||
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
+ *
|
||||
+ * To attach or detach a block device from an UBI volume the %UBI_IOCVOLATTBLK
|
||||
+ * and %UBI_IOCVOLDETBLK ioctl commands should be used, respectively.
|
||||
+ * These commands take no arguments.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -191,6 +198,10 @@
|
||||
/* Set an UBI volume property */
|
||||
#define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \
|
||||
struct ubi_set_vol_prop_req)
|
||||
+/* Attach a block device to an UBI volume */
|
||||
+#define UBI_IOCVOLATTBLK _IO(UBI_VOL_IOC_MAGIC, 7)
|
||||
+/* Detach a block device from an UBI volume */
|
||||
+#define UBI_IOCVOLDETBLK _IO(UBI_VOL_IOC_MAGIC, 8)
|
||||
|
||||
/* Maximum MTD device name length supported by UBI */
|
||||
#define MAX_UBI_MTD_NAME_LEN 127
|
|
@ -1,185 +0,0 @@
|
|||
From 4d283ee2517303afa54ad6cbd9342a2f748cf509 Mon Sep 17 00:00:00 2001
|
||||
From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
Date: Tue, 4 Mar 2014 12:00:26 +0200
|
||||
Subject: [PATCH] UBI: block: do not use term "attach"
|
||||
|
||||
We already use term attach/detach for UBI->MTD relations, let's not use this
|
||||
for UBI->ubiblock relations to avoid confusion. Just use 'create' and 'remove'
|
||||
instead. E.g., "create a R/O block device on top of a UBI volume".
|
||||
|
||||
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
---
|
||||
drivers/mtd/ubi/block.c | 39 ++++++++++++++++++++-------------------
|
||||
drivers/mtd/ubi/cdev.c | 4 ++--
|
||||
drivers/mtd/ubi/ubi.h | 14 ++++++++++----
|
||||
3 files changed, 32 insertions(+), 25 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -29,10 +29,10 @@
|
||||
*
|
||||
* LEB number = addressed byte / LEB size
|
||||
*
|
||||
- * This feature is compiled in the UBI core, and adds a new 'block' parameter
|
||||
- * to allow early block device attaching. Runtime block attach/detach for UBI
|
||||
- * volumes is provided through two new UBI ioctls: UBI_IOCVOLATTBLK and
|
||||
- * UBI_IOCVOLDETBLK.
|
||||
+ * This feature is compiled in the UBI core, and adds a 'block' parameter
|
||||
+ * to allow early creation of block devices on top of UBI volumes. Runtime
|
||||
+ * block creation/removal for UBI volumes is provided through two UBI ioctls:
|
||||
+ * UBI_IOCVOLATTBLK and UBI_IOCVOLDETBLK.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
@@ -374,7 +374,7 @@ static const struct block_device_operati
|
||||
.getgeo = ubiblock_getgeo,
|
||||
};
|
||||
|
||||
-int ubiblock_add(struct ubi_volume_info *vi)
|
||||
+int ubiblock_create(struct ubi_volume_info *vi)
|
||||
{
|
||||
struct ubiblock *dev;
|
||||
struct gendisk *gd;
|
||||
@@ -464,7 +464,7 @@ static void ubiblock_cleanup(struct ubib
|
||||
put_disk(dev->gd);
|
||||
}
|
||||
|
||||
-int ubiblock_del(struct ubi_volume_info *vi)
|
||||
+int ubiblock_remove(struct ubi_volume_info *vi)
|
||||
{
|
||||
struct ubiblock *dev;
|
||||
|
||||
@@ -503,7 +503,8 @@ static void ubiblock_resize(struct ubi_v
|
||||
|
||||
/*
|
||||
* Need to lock the device list until we stop using the device,
|
||||
- * otherwise the device struct might get released in 'ubiblock_del()'.
|
||||
+ * otherwise the device struct might get released in
|
||||
+ * 'ubiblock_remove()'.
|
||||
*/
|
||||
mutex_lock(&devices_mutex);
|
||||
dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
|
||||
@@ -528,12 +529,12 @@ static int ubiblock_notify(struct notifi
|
||||
switch (notification_type) {
|
||||
case UBI_VOLUME_ADDED:
|
||||
/*
|
||||
- * We want to enforce explicit block device attaching for
|
||||
+ * We want to enforce explicit block device creation for
|
||||
* volumes, so when a volume is added we do nothing.
|
||||
*/
|
||||
break;
|
||||
case UBI_VOLUME_REMOVED:
|
||||
- ubiblock_del(&nt->vi);
|
||||
+ ubiblock_remove(&nt->vi);
|
||||
break;
|
||||
case UBI_VOLUME_RESIZED:
|
||||
ubiblock_resize(&nt->vi);
|
||||
@@ -561,7 +562,7 @@ open_volume_desc(const char *name, int u
|
||||
return ubi_open_volume(ubi_num, vol_id, UBI_READONLY);
|
||||
}
|
||||
|
||||
-static int __init ubiblock_attach_from_param(void)
|
||||
+static int __init ubiblock_create_from_param(void)
|
||||
{
|
||||
int i, ret;
|
||||
struct ubiblock_param *p;
|
||||
@@ -582,7 +583,7 @@ static int __init ubiblock_attach_from_p
|
||||
ubi_get_volume_info(desc, &vi);
|
||||
ubi_close_volume(desc);
|
||||
|
||||
- ret = ubiblock_add(&vi);
|
||||
+ ret = ubiblock_create(&vi);
|
||||
if (ret) {
|
||||
ubi_err("block: can't add '%s' volume, err=%d\n",
|
||||
vi.name, ret);
|
||||
@@ -592,7 +593,7 @@ static int __init ubiblock_attach_from_p
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void ubiblock_detach_all(void)
|
||||
+static void ubiblock_remove_all(void)
|
||||
{
|
||||
struct ubiblock *next;
|
||||
struct ubiblock *dev;
|
||||
@@ -618,13 +619,13 @@ int __init ubiblock_init(void)
|
||||
return ubiblock_major;
|
||||
|
||||
/* Attach block devices from 'block=' module param */
|
||||
- ret = ubiblock_attach_from_param();
|
||||
+ ret = ubiblock_create_from_param();
|
||||
if (ret)
|
||||
- goto err_detach;
|
||||
+ goto err_remove;
|
||||
|
||||
/*
|
||||
- * Block devices needs to be attached to volumes explicitly
|
||||
- * upon user request. So we ignore existing volumes.
|
||||
+ * Block devices are only created upon user requests, so we ignore
|
||||
+ * existing volumes.
|
||||
*/
|
||||
ret = ubi_register_volume_notifier(&ubiblock_notifier, 1);
|
||||
if (ret)
|
||||
@@ -633,14 +634,14 @@ int __init ubiblock_init(void)
|
||||
|
||||
err_unreg:
|
||||
unregister_blkdev(ubiblock_major, "ubiblock");
|
||||
-err_detach:
|
||||
- ubiblock_detach_all();
|
||||
+err_remove:
|
||||
+ ubiblock_remove_all();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit ubiblock_exit(void)
|
||||
{
|
||||
ubi_unregister_volume_notifier(&ubiblock_notifier);
|
||||
- ubiblock_detach_all();
|
||||
+ ubiblock_remove_all();
|
||||
unregister_blkdev(ubiblock_major, "ubiblock");
|
||||
}
|
||||
--- a/drivers/mtd/ubi/cdev.c
|
||||
+++ b/drivers/mtd/ubi/cdev.c
|
||||
@@ -567,7 +567,7 @@ static long vol_cdev_ioctl(struct file *
|
||||
struct ubi_volume_info vi;
|
||||
|
||||
ubi_get_volume_info(desc, &vi);
|
||||
- err = ubiblock_add(&vi);
|
||||
+ err = ubiblock_create(&vi);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -577,7 +577,7 @@ static long vol_cdev_ioctl(struct file *
|
||||
struct ubi_volume_info vi;
|
||||
|
||||
ubi_get_volume_info(desc, &vi);
|
||||
- err = ubiblock_del(&vi);
|
||||
+ err = ubiblock_remove(&vi);
|
||||
break;
|
||||
}
|
||||
|
||||
--- a/drivers/mtd/ubi/ubi.h
|
||||
+++ b/drivers/mtd/ubi/ubi.h
|
||||
@@ -868,13 +868,19 @@ int ubi_scan_fastmap(struct ubi_device *
|
||||
#ifdef CONFIG_MTD_UBI_BLOCK
|
||||
int ubiblock_init(void);
|
||||
void ubiblock_exit(void);
|
||||
-int ubiblock_add(struct ubi_volume_info *vi);
|
||||
-int ubiblock_del(struct ubi_volume_info *vi);
|
||||
+int ubiblock_create(struct ubi_volume_info *vi);
|
||||
+int ubiblock_remove(struct ubi_volume_info *vi);
|
||||
#else
|
||||
static inline int ubiblock_init(void) { return 0; }
|
||||
static inline void ubiblock_exit(void) {}
|
||||
-static inline int ubiblock_add(struct ubi_volume_info *vi) { return -ENOTTY; }
|
||||
-static inline int ubiblock_del(struct ubi_volume_info *vi) { return -ENOTTY; }
|
||||
+static inline int ubiblock_create(struct ubi_volume_info *vi)
|
||||
+{
|
||||
+ return -ENOTTY;
|
||||
+}
|
||||
+static inline int ubiblock_remove(struct ubi_volume_info *vi)
|
||||
+{
|
||||
+ return -ENOTTY;
|
||||
+}
|
||||
#endif
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
From ca2b722d1ab5bc3ffc34b5995248968cd8a7cb6f Mon Sep 17 00:00:00 2001
|
||||
From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Date: Mon, 3 Mar 2014 13:42:38 -0300
|
||||
Subject: [PATCH] UBI: block: Mark init-only symbol as __initdata
|
||||
|
||||
ubiblock_param_ops should be marked as __init as it's only used to set
|
||||
a driver parameter on insertion time. This commit fixes the following:
|
||||
|
||||
WARNING: drivers/mtd/built-in.o(.text+0x653ac): Section mismatch in
|
||||
reference from the variable ubiblock_param_ops to the function
|
||||
.init.text:ubiblock_set_param()
|
||||
|
||||
The function ubiblock_param_ops() references the function __init
|
||||
ubiblock_set_param(). This is often because ubiblock_param_ops lacks a
|
||||
__init annotation or the annotation of ubiblock_set_param is wrong.
|
||||
|
||||
Given gcc errors if the struct is marked const __initdata, this commit
|
||||
drops the const mark from it.
|
||||
|
||||
Reported-by: kbuild test robot <fengguang.wu@intel.com>
|
||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
---
|
||||
drivers/mtd/ubi/block.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -156,7 +156,7 @@ static int __init ubiblock_set_param(con
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static const struct kernel_param_ops ubiblock_param_ops = {
|
||||
+static struct kernel_param_ops ubiblock_param_ops __initdata = {
|
||||
.set = ubiblock_set_param,
|
||||
};
|
||||
module_param_cb(block, &ubiblock_param_ops, NULL, 0);
|
|
@ -1,28 +0,0 @@
|
|||
From 9981e14ab2f7c6a4d2bb45e51a6371964919837d Mon Sep 17 00:00:00 2001
|
||||
From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Date: Mon, 3 Mar 2014 13:42:39 -0300
|
||||
Subject: [PATCH] UBI: block: Use 'u64' for the 64-bit dividend
|
||||
|
||||
Fixes the following warning on ARCH=avr32:
|
||||
|
||||
drivers/mtd/ubi/block.c: In function 'ubiblock_read':
|
||||
drivers/mtd/ubi/block.c:207: warning: comparison of distinct pointer types lacks a cast
|
||||
|
||||
Reported-by: kbuild test robot <fengguang.wu@intel.com>
|
||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
---
|
||||
drivers/mtd/ubi/block.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -201,7 +201,7 @@ static int ubiblock_read(struct ubiblock
|
||||
int ret, leb, offset;
|
||||
int bytes_left = len;
|
||||
int to_read = len;
|
||||
- loff_t pos = sec << 9;
|
||||
+ u64 pos = sec << 9;
|
||||
|
||||
/* Get LEB:offset address to read from */
|
||||
offset = do_div(pos, dev->leb_size);
|
|
@ -1,83 +0,0 @@
|
|||
From 8af871887fcba470ff9265c65cff7d14d9e0e3f9 Mon Sep 17 00:00:00 2001
|
||||
From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
Date: Wed, 5 Mar 2014 13:01:56 +0200
|
||||
Subject: [PATCH] UBI: rename block device ioctls
|
||||
|
||||
Rename the UBI_IOCVOLATTBLK and UBI_IOCVOLDETBLK to UBI_IOCVOLCRBLK and
|
||||
UBI_IOCVOLRMBLK, because we do not use terms "attach" and "detach" for the R/O
|
||||
block devices on top of UBI volumes. Instead, we use terms "create" and
|
||||
"remove". This patch also amends the related commentaries.
|
||||
|
||||
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
Acked-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
---
|
||||
drivers/mtd/ubi/block.c | 2 +-
|
||||
drivers/mtd/ubi/cdev.c | 8 ++++----
|
||||
include/uapi/mtd/ubi-user.h | 14 +++++++-------
|
||||
3 files changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -32,7 +32,7 @@
|
||||
* This feature is compiled in the UBI core, and adds a 'block' parameter
|
||||
* to allow early creation of block devices on top of UBI volumes. Runtime
|
||||
* block creation/removal for UBI volumes is provided through two UBI ioctls:
|
||||
- * UBI_IOCVOLATTBLK and UBI_IOCVOLDETBLK.
|
||||
+ * UBI_IOCVOLCRBLK and UBI_IOCVOLRMBLK.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
--- a/drivers/mtd/ubi/cdev.c
|
||||
+++ b/drivers/mtd/ubi/cdev.c
|
||||
@@ -561,8 +561,8 @@ static long vol_cdev_ioctl(struct file *
|
||||
break;
|
||||
}
|
||||
|
||||
- /* Attach a block device to an UBI volume */
|
||||
- case UBI_IOCVOLATTBLK:
|
||||
+ /* Create a R/O block device on top of the UBI volume */
|
||||
+ case UBI_IOCVOLCRBLK:
|
||||
{
|
||||
struct ubi_volume_info vi;
|
||||
|
||||
@@ -571,8 +571,8 @@ static long vol_cdev_ioctl(struct file *
|
||||
break;
|
||||
}
|
||||
|
||||
- /* Dettach a block device from an UBI volume */
|
||||
- case UBI_IOCVOLDETBLK:
|
||||
+ /* Remove the R/O block device */
|
||||
+ case UBI_IOCVOLRMBLK:
|
||||
{
|
||||
struct ubi_volume_info vi;
|
||||
|
||||
--- a/include/uapi/mtd/ubi-user.h
|
||||
+++ b/include/uapi/mtd/ubi-user.h
|
||||
@@ -138,9 +138,9 @@
|
||||
* Block devices on UBI volumes
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
- * To attach or detach a block device from an UBI volume the %UBI_IOCVOLATTBLK
|
||||
- * and %UBI_IOCVOLDETBLK ioctl commands should be used, respectively.
|
||||
- * These commands take no arguments.
|
||||
+ * To create or remove a R/O block device on top of an UBI volume the
|
||||
+ * %UBI_IOCVOLCRBLK and %UBI_IOCVOLRMBLK ioctl commands should be used,
|
||||
+ * respectively. These commands take no arguments.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -198,10 +198,10 @@
|
||||
/* Set an UBI volume property */
|
||||
#define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \
|
||||
struct ubi_set_vol_prop_req)
|
||||
-/* Attach a block device to an UBI volume */
|
||||
-#define UBI_IOCVOLATTBLK _IO(UBI_VOL_IOC_MAGIC, 7)
|
||||
-/* Detach a block device from an UBI volume */
|
||||
-#define UBI_IOCVOLDETBLK _IO(UBI_VOL_IOC_MAGIC, 8)
|
||||
+/* Create a R/O block device on top of an UBI volume */
|
||||
+#define UBI_IOCVOLCRBLK _IO(UBI_VOL_IOC_MAGIC, 7)
|
||||
+/* Remove the R/O block device */
|
||||
+#define UBI_IOCVOLRMBLK _IO(UBI_VOL_IOC_MAGIC, 8)
|
||||
|
||||
/* Maximum MTD device name length supported by UBI */
|
||||
#define MAX_UBI_MTD_NAME_LEN 127
|
|
@ -1,30 +0,0 @@
|
|||
From d56030ac25d383218045c5d87e98e0494d6af3ad Mon Sep 17 00:00:00 2001
|
||||
From: Richard Weinberger <richard@nod.at>
|
||||
Date: Wed, 19 Mar 2014 11:43:22 +0100
|
||||
Subject: [PATCH] UBI: block: Remove __initdata from ubiblock_param_ops
|
||||
|
||||
You cannot mark these parameters as __initdata.
|
||||
Otherwise the data is gone upon module exit.
|
||||
|
||||
Fixes:
|
||||
[ 172.045465] BUG: unable to handle kernel paging request at ffffffffa001db38
|
||||
[ 172.046020] IP: [<ffffffff81067aa4>] destroy_params+0x24/0x50
|
||||
|
||||
Signed-off-by: Richard Weinberger <richard@nod.at>
|
||||
Acked-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
---
|
||||
drivers/mtd/ubi/block.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -156,7 +156,7 @@ static int __init ubiblock_set_param(con
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static struct kernel_param_ops ubiblock_param_ops __initdata = {
|
||||
+static struct kernel_param_ops ubiblock_param_ops = {
|
||||
.set = ubiblock_set_param,
|
||||
};
|
||||
module_param_cb(block, &ubiblock_param_ops, NULL, 0);
|
|
@ -1,25 +0,0 @@
|
|||
From bebfef150e0b8fa68704cddacf05b8c26462d565 Mon Sep 17 00:00:00 2001
|
||||
From: Kees Cook <keescook@chromium.org>
|
||||
Date: Mon, 7 Apr 2014 21:44:07 -0700
|
||||
Subject: [PATCH] UBI: avoid workqueue format string leak
|
||||
|
||||
When building the name for the workqueue thread, make sure a format
|
||||
string cannot leak in from the disk name.
|
||||
|
||||
Signed-off-by: Kees Cook <keescook@chromium.org>
|
||||
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
---
|
||||
drivers/mtd/ubi/block.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -431,7 +431,7 @@ int ubiblock_create(struct ubi_volume_in
|
||||
* Create one workqueue per volume (per registered block device).
|
||||
* Rembember workqueues are cheap, they're not threads.
|
||||
*/
|
||||
- dev->wq = alloc_workqueue(gd->disk_name, 0, 0);
|
||||
+ dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name);
|
||||
if (!dev->wq)
|
||||
goto out_free_queue;
|
||||
INIT_WORK(&dev->work, ubiblock_do_work);
|
|
@ -1,58 +0,0 @@
|
|||
From 463c5eedb4a13b9aa91f05498a0f2c20bd03f8c4 Mon Sep 17 00:00:00 2001
|
||||
From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Date: Wed, 5 Mar 2014 11:16:14 -0300
|
||||
Subject: [PATCH] UBI: make UBI_IOCVOLCRBLK take a parameter for future usage
|
||||
|
||||
In order to allow a future ioctl parameter, such as a creation flag,
|
||||
we change the UBI_IOCVOLCRBLK so it accepts a struct ubi_blkcreate_req.
|
||||
For the time being the structure is not in use, but fully reserved.
|
||||
|
||||
This ABI change is still possible and harmless, because the ioctl has just
|
||||
been introduced and there's no userspace program which uses it.
|
||||
|
||||
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
|
||||
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
|
||||
---
|
||||
include/uapi/mtd/ubi-user.h | 19 +++++++++++++++----
|
||||
1 file changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/include/uapi/mtd/ubi-user.h
|
||||
+++ b/include/uapi/mtd/ubi-user.h
|
||||
@@ -138,9 +138,12 @@
|
||||
* Block devices on UBI volumes
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
- * To create or remove a R/O block device on top of an UBI volume the
|
||||
- * %UBI_IOCVOLCRBLK and %UBI_IOCVOLRMBLK ioctl commands should be used,
|
||||
- * respectively. These commands take no arguments.
|
||||
+ * To create a R/O block device on top of an UBI volume the %UBI_IOCVOLCRBLK
|
||||
+ * should be used. A pointer to a &struct ubi_blkcreate_req object is expected
|
||||
+ * to be passed, which is not used and reserved for future usage.
|
||||
+ *
|
||||
+ * Conversely, to remove a block device the %UBI_IOCVOLRMBLK should be used,
|
||||
+ * which takes no arguments.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -199,7 +202,7 @@
|
||||
#define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \
|
||||
struct ubi_set_vol_prop_req)
|
||||
/* Create a R/O block device on top of an UBI volume */
|
||||
-#define UBI_IOCVOLCRBLK _IO(UBI_VOL_IOC_MAGIC, 7)
|
||||
+#define UBI_IOCVOLCRBLK _IOW(UBI_VOL_IOC_MAGIC, 7, struct ubi_blkcreate_req)
|
||||
/* Remove the R/O block device */
|
||||
#define UBI_IOCVOLRMBLK _IO(UBI_VOL_IOC_MAGIC, 8)
|
||||
|
||||
@@ -431,4 +434,12 @@ struct ubi_set_vol_prop_req {
|
||||
__u64 value;
|
||||
} __packed;
|
||||
|
||||
+/**
|
||||
+ * struct ubi_blkcreate_req - a data structure used in block creation requests.
|
||||
+ * @padding: reserved for future, not used, has to be zeroed
|
||||
+ */
|
||||
+struct ubi_blkcreate_req {
|
||||
+ __s8 padding[128];
|
||||
+} __packed;
|
||||
+
|
||||
#endif /* __UBI_USER_H__ */
|
|
@ -1,59 +0,0 @@
|
|||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -150,7 +150,7 @@ config MTD_BCM63XX_PARTS
|
||||
|
||||
config MTD_BCM47XX_PARTS
|
||||
tristate "BCM47XX partitioning support"
|
||||
- depends on BCM47XX
|
||||
+ depends on BCM47XX || ARCH_BCM_5301X
|
||||
help
|
||||
This provides partitions parser for devices based on BCM47xx
|
||||
boards.
|
||||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
-#include <bcm47xx_nvram.h>
|
||||
|
||||
/* 10 parts were found on sflash on Netgear WNDR4500 */
|
||||
#define BCM47XXPART_MAX_PARTS 12
|
||||
@@ -30,6 +29,7 @@
|
||||
#define BOARD_DATA_MAGIC2 0xBD0D0BBD
|
||||
#define CFE_MAGIC 0x43464531 /* 1EFC */
|
||||
#define FACTORY_MAGIC 0x59544346 /* FCTY */
|
||||
+#define NVRAM_HEADER 0x48534C46 /* FLSH */
|
||||
#define POT_MAGIC1 0x54544f50 /* POTT */
|
||||
#define POT_MAGIC2 0x504f /* OP */
|
||||
#define ML_MAGIC1 0x39685a42
|
||||
@@ -91,7 +91,7 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
if (offset >= 0x2000000)
|
||||
break;
|
||||
|
||||
- if (curr_part > BCM47XXPART_MAX_PARTS) {
|
||||
+ if (curr_part >= BCM47XXPART_MAX_PARTS) {
|
||||
pr_warn("Reached maximum number of partitions, scanning stopped!\n");
|
||||
break;
|
||||
}
|
||||
@@ -147,6 +147,11 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
|
||||
/* TRX */
|
||||
if (buf[0x000 / 4] == TRX_MAGIC) {
|
||||
+ if (BCM47XXPART_MAX_PARTS - curr_part < 4) {
|
||||
+ pr_warn("Not enough partitions left to register trx, scanning stopped!\n");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
trx = (struct trx_header *)buf;
|
||||
|
||||
trx_part = curr_part;
|
||||
@@ -212,7 +217,7 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
|
||||
/* Look for NVRAM at the end of the last block. */
|
||||
for (i = 0; i < ARRAY_SIZE(possible_nvram_sizes); i++) {
|
||||
- if (curr_part > BCM47XXPART_MAX_PARTS) {
|
||||
+ if (curr_part >= BCM47XXPART_MAX_PARTS) {
|
||||
pr_warn("Reached maximum number of partitions, scanning stopped!\n");
|
||||
break;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -199,6 +199,16 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
continue;
|
||||
}
|
||||
|
||||
+ /* New (ARM?) devices may have NVRAM in some middle block. Last
|
||||
+ * block will be checked later, so skip it.
|
||||
+ */
|
||||
+ if (offset != master->size - blocksize &&
|
||||
+ buf[0x000 / 4] == NVRAM_HEADER) {
|
||||
+ bcm47xxpart_add_part(&parts[curr_part++], "nvram",
|
||||
+ offset, 0);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
/* Read middle of the block */
|
||||
if (mtd_read(master, offset + 0x8000, 0x4,
|
||||
&bytes_read, (uint8_t *)buf) < 0) {
|
|
@ -1,50 +0,0 @@
|
|||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -15,8 +15,12 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
-/* 10 parts were found on sflash on Netgear WNDR4500 */
|
||||
-#define BCM47XXPART_MAX_PARTS 12
|
||||
+/*
|
||||
+ * NAND flash on Netgear R6250 was verified to contain 15 partitions.
|
||||
+ * This will result in allocating too big array for some old devices, but the
|
||||
+ * memory will be freed soon anyway (see mtd_device_parse_register).
|
||||
+ */
|
||||
+#define BCM47XXPART_MAX_PARTS 20
|
||||
|
||||
/*
|
||||
* Amount of bytes we read when analyzing each block of flash memory.
|
||||
@@ -168,18 +172,26 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
i++;
|
||||
}
|
||||
|
||||
- bcm47xxpart_add_part(&parts[curr_part++], "linux",
|
||||
- offset + trx->offset[i], 0);
|
||||
- i++;
|
||||
+ if (trx->offset[i]) {
|
||||
+ bcm47xxpart_add_part(&parts[curr_part++],
|
||||
+ "linux",
|
||||
+ offset + trx->offset[i],
|
||||
+ 0);
|
||||
+ i++;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* Pure rootfs size is known and can be calculated as:
|
||||
* trx->length - trx->offset[i]. We don't fill it as
|
||||
* we want to have jffs2 (overlay) in the same mtd.
|
||||
*/
|
||||
- bcm47xxpart_add_part(&parts[curr_part++], "rootfs",
|
||||
- offset + trx->offset[i], 0);
|
||||
- i++;
|
||||
+ if (trx->offset[i]) {
|
||||
+ bcm47xxpart_add_part(&parts[curr_part++],
|
||||
+ "rootfs",
|
||||
+ offset + trx->offset[i],
|
||||
+ 0);
|
||||
+ i++;
|
||||
+ }
|
||||
|
||||
last_trx_part = curr_part - 1;
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
+#include <uapi/linux/magic.h>
|
||||
+
|
||||
/*
|
||||
* NAND flash on Netgear R6250 was verified to contain 15 partitions.
|
||||
* This will result in allocating too big array for some old devices, but the
|
||||
@@ -39,7 +41,8 @@
|
||||
#define ML_MAGIC1 0x39685a42
|
||||
#define ML_MAGIC2 0x26594131
|
||||
#define TRX_MAGIC 0x30524448
|
||||
-#define SQSH_MAGIC 0x71736873 /* shsq */
|
||||
+#define SHSQ_MAGIC 0x71736873 /* shsq (weird ZTE H218N endianness) */
|
||||
+#define UBI_EC_MAGIC 0x23494255 /* UBI# */
|
||||
|
||||
struct trx_header {
|
||||
uint32_t magic;
|
||||
@@ -50,7 +53,7 @@ struct trx_header {
|
||||
uint32_t offset[3];
|
||||
} __packed;
|
||||
|
||||
-static void bcm47xxpart_add_part(struct mtd_partition *part, char *name,
|
||||
+static void bcm47xxpart_add_part(struct mtd_partition *part, const char *name,
|
||||
u64 offset, uint32_t mask_flags)
|
||||
{
|
||||
part->name = name;
|
||||
@@ -58,6 +61,26 @@ static void bcm47xxpart_add_part(struct
|
||||
part->mask_flags = mask_flags;
|
||||
}
|
||||
|
||||
+static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master,
|
||||
+ size_t offset)
|
||||
+{
|
||||
+ uint32_t buf;
|
||||
+ size_t bytes_read;
|
||||
+
|
||||
+ if (mtd_read(master, offset, sizeof(buf), &bytes_read,
|
||||
+ (uint8_t *)&buf) < 0) {
|
||||
+ pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
|
||||
+ offset);
|
||||
+ goto out_default;
|
||||
+ }
|
||||
+
|
||||
+ if (buf == UBI_EC_MAGIC)
|
||||
+ return "ubi";
|
||||
+
|
||||
+out_default:
|
||||
+ return "rootfs";
|
||||
+}
|
||||
+
|
||||
static int bcm47xxpart_parse(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
@@ -73,8 +96,12 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
int last_trx_part = -1;
|
||||
int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, };
|
||||
|
||||
- if (blocksize <= 0x10000)
|
||||
- blocksize = 0x10000;
|
||||
+ /*
|
||||
+ * Some really old flashes (like AT45DB*) had smaller erasesize-s, but
|
||||
+ * partitions were aligned to at least 0x1000 anyway.
|
||||
+ */
|
||||
+ if (blocksize < 0x1000)
|
||||
+ blocksize = 0x1000;
|
||||
|
||||
/* Alloc */
|
||||
parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS,
|
||||
@@ -186,8 +213,11 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
* we want to have jffs2 (overlay) in the same mtd.
|
||||
*/
|
||||
if (trx->offset[i]) {
|
||||
+ const char *name;
|
||||
+
|
||||
+ name = bcm47xxpart_trx_data_part_name(master, offset + trx->offset[i]);
|
||||
bcm47xxpart_add_part(&parts[curr_part++],
|
||||
- "rootfs",
|
||||
+ name,
|
||||
offset + trx->offset[i],
|
||||
0);
|
||||
i++;
|
||||
@@ -205,7 +235,8 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
}
|
||||
|
||||
/* Squashfs on devices not using TRX */
|
||||
- if (buf[0x000 / 4] == SQSH_MAGIC) {
|
||||
+ if (le32_to_cpu(buf[0x000 / 4]) == SQUASHFS_MAGIC ||
|
||||
+ buf[0x000 / 4] == SHSQ_MAGIC) {
|
||||
bcm47xxpart_add_part(&parts[curr_part++], "rootfs",
|
||||
offset, 0);
|
||||
continue;
|
|
@ -1,323 +0,0 @@
|
|||
From 61ab9efddf51cbc0d57356a4d650785cf5721fbe Mon Sep 17 00:00:00 2001
|
||||
From: Ricardo Ribalda <ricardo.ribalda@gmail.com>
|
||||
Date: Mon, 4 Aug 2014 11:11:49 +0200
|
||||
Subject: [PATCH] net/usb/hso: Add support for Option GTM671WFS
|
||||
|
||||
After this patch:
|
||||
|
||||
[ 32.985530] hso: drivers/net/usb/hso.c: Option Wireless
|
||||
[ 33.000452] hso 2-1.4:1.7: Not our interface
|
||||
[ 33.001849] usbcore: registered new interface driver hso
|
||||
|
||||
root@qt5022:~# ls /dev/ttyHS*
|
||||
/dev/ttyHS0 /dev/ttyHS1 /dev/ttyHS2 /dev/ttyHS3 /dev/ttyHS4
|
||||
/dev/ttyHS5
|
||||
|
||||
root@qt5022:~# lsusb -d 0af0: -vvv
|
||||
|
||||
Bus 002 Device 003: ID 0af0:9200 Option
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 255 Vendor Specific Class
|
||||
bDeviceSubClass 255 Vendor Specific Subclass
|
||||
bDeviceProtocol 255 Vendor Specific Protocol
|
||||
bMaxPacketSize0 64
|
||||
idVendor 0x0af0 Option
|
||||
idProduct 0x9200
|
||||
bcdDevice 0.00
|
||||
iManufacturer 3 Option N.V.
|
||||
iProduct 2 Globetrotter HSUPA Modem
|
||||
iSerial 0
|
||||
bNumConfigurations 1
|
||||
Configuration Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 2
|
||||
wTotalLength 200
|
||||
bNumInterfaces 8
|
||||
bConfigurationValue 1
|
||||
iConfiguration 1 Option Configuration
|
||||
bmAttributes 0xe0
|
||||
Self Powered
|
||||
Remote Wakeup
|
||||
MaxPower 100mA
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 0
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x81 EP 1 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x01 EP 1 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 1
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x82 EP 2 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x02 EP 2 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 2
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x83 EP 3 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x03 EP 3 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 3
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x84 EP 4 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x04 EP 4 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 4
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x85 EP 5 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x05 EP 5 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 5
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x06 EP 6 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x86 EP 6 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 6
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 3
|
||||
bInterfaceClass 255 Vendor Specific Class
|
||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x87 EP 7 IN
|
||||
bmAttributes 3
|
||||
Transfer Type Interrupt
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0040 1x 64 bytes
|
||||
bInterval 5
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x88 EP 8 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x07 EP 7 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 32
|
||||
Interface Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 4
|
||||
bInterfaceNumber 7
|
||||
bAlternateSetting 0
|
||||
bNumEndpoints 2
|
||||
bInterfaceClass 8 Mass Storage
|
||||
bInterfaceSubClass 6 SCSI
|
||||
bInterfaceProtocol 80 Bulk-Only
|
||||
iInterface 0
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x08 EP 8 OUT
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 1
|
||||
Endpoint Descriptor:
|
||||
bLength 7
|
||||
bDescriptorType 5
|
||||
bEndpointAddress 0x89 EP 9 IN
|
||||
bmAttributes 2
|
||||
Transfer Type Bulk
|
||||
Synch Type None
|
||||
Usage Type Data
|
||||
wMaxPacketSize 0x0200 1x 512 bytes
|
||||
bInterval 1
|
||||
Device Qualifier (for other device speed):
|
||||
bLength 10
|
||||
bDescriptorType 6
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 255 Vendor Specific Class
|
||||
bDeviceSubClass 255 Vendor Specific Subclass
|
||||
bDeviceProtocol 255 Vendor Specific Protocol
|
||||
bMaxPacketSize0 64
|
||||
bNumConfigurations 1
|
||||
Device Status: 0x0001
|
||||
Self Powered
|
||||
|
||||
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
|
||||
Acked-by: Dan Williams <dcbw@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/usb/hso.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/usb/hso.c
|
||||
+++ b/drivers/net/usb/hso.c
|
||||
@@ -469,6 +469,7 @@ static const struct usb_device_id hso_id
|
||||
{USB_DEVICE(0x0af0, 0x8800)},
|
||||
{USB_DEVICE(0x0af0, 0x8900)},
|
||||
{USB_DEVICE(0x0af0, 0x9000)},
|
||||
+ {USB_DEVICE(0x0af0, 0x9200)}, /* Option GTM671WFS */
|
||||
{USB_DEVICE(0x0af0, 0xd035)},
|
||||
{USB_DEVICE(0x0af0, 0xd055)},
|
||||
{USB_DEVICE(0x0af0, 0xd155)},
|
|
@ -1,10 +0,0 @@
|
|||
--- a/arch/arm/boot/compressed/decompress.c
|
||||
+++ b/arch/arm/boot/compressed/decompress.c
|
||||
@@ -48,6 +48,7 @@ extern char * strstr(const char * s1, co
|
||||
#ifdef CONFIG_KERNEL_XZ
|
||||
#define memmove memmove
|
||||
#define memcpy memcpy
|
||||
+extern char * strstr(const char *, const char *);
|
||||
#include "../../../../lib/decompress_unxz.c"
|
||||
#endif
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
From 0db3db45f5bd6df4bdc03bbd5dec672e16164c4e Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 12 Nov 2012 12:31:55 +0100
|
||||
Subject: [PATCH] MIPS: decompressor: fix build failure on memcpy() in
|
||||
decompress.c
|
||||
|
||||
The decompress.c file includes linux/kernel.h which causes the following
|
||||
inclusion chain to be pulled:
|
||||
linux/kernel.h ->
|
||||
linux/dynamic_debug.h ->
|
||||
linux/string.h ->
|
||||
asm/string.h
|
||||
|
||||
We end up having a the GCC builtin + architecture specific memcpy() expanding
|
||||
into this:
|
||||
|
||||
void *({ size_t __len = (size_t n); void *__ret; if
|
||||
(__builtin_constant_p(size_t n) && __len >= 64) __ret = memcpy((void *dest),
|
||||
(const void *src), __len); else __ret = __builtin_memcpy((void *dest), (const
|
||||
void *src), __len); __ret; })
|
||||
{
|
||||
[memcpy implementation in decompress.c starts here]
|
||||
int i;
|
||||
const char *s = src;
|
||||
char *d = dest;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
d[i] = s[i];
|
||||
return dest;
|
||||
}
|
||||
|
||||
raising the following compilation error:
|
||||
arch/mips/boot/compressed/decompress.c:46:8: error: expected identifier or '('
|
||||
before '{' token
|
||||
|
||||
There are at least three possibilities to fix this issue:
|
||||
|
||||
1) define _LINUX_STRING_H_ at the beginning of decompress.c to prevent
|
||||
further linux/string.h definitions and declarations from being used, and add
|
||||
an explicit strstr() declaration for linux/dynamic_debug.h
|
||||
|
||||
2) remove the inclusion of linux/kernel.h because we actually use no definition
|
||||
or declaration from this header file
|
||||
|
||||
3) undefine memcpy or re-define memcpy to memcpy thus resulting in picking up
|
||||
the local memcpy() implementation to this compilation unit
|
||||
|
||||
This patch uses the second option which is the less intrusive one.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
arch/mips/boot/compressed/decompress.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/arch/mips/boot/compressed/decompress.c
|
||||
+++ b/arch/mips/boot/compressed/decompress.c
|
||||
@@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
-#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
|
@ -1,22 +0,0 @@
|
|||
--- a/arch/mips/boot/compressed/string.c
|
||||
+++ b/arch/mips/boot/compressed/string.c
|
||||
@@ -26,3 +26,19 @@ void *memset(void *s, int c, size_t n)
|
||||
ss[i] = c;
|
||||
return s;
|
||||
}
|
||||
+
|
||||
+void *memmove(void *__dest, __const void *__src, size_t count)
|
||||
+{
|
||||
+ unsigned char *d = __dest;
|
||||
+ const unsigned char *s = __src;
|
||||
+
|
||||
+ if (__dest == __src)
|
||||
+ return __dest;
|
||||
+
|
||||
+ if (__dest < __src)
|
||||
+ return memcpy(__dest, __src, count);
|
||||
+
|
||||
+ while (count--)
|
||||
+ d[count] = s[count];
|
||||
+ return __dest;
|
||||
+}
|
|
@ -1,122 +0,0 @@
|
|||
Backport essential fixes from 3.15
|
||||
|
||||
From Linux 3.10 on this driver required platform data to load, which makes it
|
||||
unusable in OpenWRT. This commit backports the following fixes:
|
||||
* Move to regulator framework for scaling
|
||||
* Fix device-removal path
|
||||
This commit should not be moved to newer kernel versions!
|
||||
|
||||
Signed-off-by: Hartmut Knaack <knaack.h@gmx.de>
|
||||
---
|
||||
--- a/drivers/staging/iio/adc/ad799x_core.c
|
||||
+++ b/drivers/staging/iio/adc/ad799x_core.c
|
||||
@@ -179,7 +179,10 @@ static int ad799x_read_raw(struct iio_de
|
||||
RES_MASK(chan->scan_type.realbits);
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
- *val = st->int_vref_mv;
|
||||
+ ret = regulator_get_voltage(st->vref);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ *val = ret / 1000;
|
||||
*val2 = chan->scan_type.realbits;
|
||||
return IIO_VAL_FRACTIONAL_LOG2;
|
||||
}
|
||||
@@ -533,7 +536,6 @@ static int ad799x_probe(struct i2c_clien
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
- struct ad799x_platform_data *pdata = client->dev.platform_data;
|
||||
struct ad799x_state *st;
|
||||
struct iio_dev *indio_dev;
|
||||
|
||||
@@ -551,17 +553,21 @@ static int ad799x_probe(struct i2c_clien
|
||||
|
||||
/* TODO: Add pdata options for filtering and bit delay */
|
||||
|
||||
- if (!pdata)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- st->int_vref_mv = pdata->vref_mv;
|
||||
-
|
||||
st->reg = devm_regulator_get(&client->dev, "vcc");
|
||||
- if (!IS_ERR(st->reg)) {
|
||||
- ret = regulator_enable(st->reg);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
+ if (IS_ERR(st->reg))
|
||||
+ return PTR_ERR(st->reg);
|
||||
+ ret = regulator_enable(st->reg);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ st->vref = devm_regulator_get(&client->dev, "vref");
|
||||
+ if (IS_ERR(st->vref)) {
|
||||
+ ret = PTR_ERR(st->vref);
|
||||
+ goto error_disable_reg;
|
||||
}
|
||||
+ ret = regulator_enable(st->vref);
|
||||
+ if (ret)
|
||||
+ goto error_disable_reg;
|
||||
+
|
||||
st->client = client;
|
||||
|
||||
indio_dev->dev.parent = &client->dev;
|
||||
@@ -574,7 +580,7 @@ static int ad799x_probe(struct i2c_clien
|
||||
|
||||
ret = ad799x_register_ring_funcs_and_init(indio_dev);
|
||||
if (ret)
|
||||
- goto error_disable_reg;
|
||||
+ goto error_disable_vref;
|
||||
|
||||
if (client->irq > 0) {
|
||||
ret = request_threaded_irq(client->irq,
|
||||
@@ -598,9 +604,10 @@ error_free_irq:
|
||||
free_irq(client->irq, indio_dev);
|
||||
error_cleanup_ring:
|
||||
ad799x_ring_cleanup(indio_dev);
|
||||
+error_disable_vref:
|
||||
+ regulator_disable(st->vref);
|
||||
error_disable_reg:
|
||||
- if (!IS_ERR(st->reg))
|
||||
- regulator_disable(st->reg);
|
||||
+ regulator_disable(st->reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -615,8 +622,8 @@ static int ad799x_remove(struct i2c_clie
|
||||
free_irq(client->irq, indio_dev);
|
||||
|
||||
ad799x_ring_cleanup(indio_dev);
|
||||
- if (!IS_ERR(st->reg))
|
||||
- regulator_disable(st->reg);
|
||||
+ regulator_disable(st->vref);
|
||||
+ regulator_disable(st->reg);
|
||||
kfree(st->rx_buf);
|
||||
|
||||
return 0;
|
||||
--- a/drivers/staging/iio/adc/ad799x.h
|
||||
+++ b/drivers/staging/iio/adc/ad799x.h
|
||||
@@ -95,7 +95,7 @@ struct ad799x_state {
|
||||
struct i2c_client *client;
|
||||
const struct ad799x_chip_info *chip_info;
|
||||
struct regulator *reg;
|
||||
- u16 int_vref_mv;
|
||||
+ struct regulator *vref;
|
||||
unsigned id;
|
||||
u16 config;
|
||||
|
||||
@@ -103,14 +103,6 @@ struct ad799x_state {
|
||||
unsigned int transfer_size;
|
||||
};
|
||||
|
||||
-/*
|
||||
- * TODO: struct ad799x_platform_data needs to go into include/linux/iio
|
||||
- */
|
||||
-
|
||||
-struct ad799x_platform_data {
|
||||
- u16 vref_mv;
|
||||
-};
|
||||
-
|
||||
#ifdef CONFIG_AD799X_RING_BUFFER
|
||||
int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev);
|
||||
void ad799x_ring_cleanup(struct iio_dev *indio_dev);
|
|
@ -1,71 +0,0 @@
|
|||
commit 797ac07137d9ae8572008e21e6123a9ae17dae50
|
||||
Author: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Date: Mon Feb 17 13:34:02 2014 -0800
|
||||
|
||||
net: phy: move PHY software reset to genphy_soft_reset
|
||||
|
||||
As pointed out by Shaohui, this function is generic for 10/100/1000
|
||||
PHYs, but 10G PHYs might have a slightly different reset sequence which
|
||||
prevents most of them from using this function.
|
||||
|
||||
Move the BMCR_RESET based software resent sequence to
|
||||
genphy_soft_reset() in preparation for allowing PHY drivers to implement
|
||||
a soft_reset() callback.
|
||||
|
||||
Reported-by: Shaohui Xie <Shaohui.Xie@freescale.com>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -539,11 +539,7 @@ int phy_init_hw(struct phy_device *phyde
|
||||
if (!phydev->drv || !phydev->drv->config_init)
|
||||
return 0;
|
||||
|
||||
- ret = phy_write(phydev, MII_BMCR, BMCR_RESET);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
-
|
||||
- ret = phy_poll_reset(phydev);
|
||||
+ ret = genphy_soft_reset(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -1029,6 +1025,27 @@ static int gen10g_read_status(struct phy
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * genphy_soft_reset - software reset the PHY via BMCR_RESET bit
|
||||
+ * @phydev: target phy_device struct
|
||||
+ *
|
||||
+ * Description: Perform a software PHY reset using the standard
|
||||
+ * BMCR_RESET bit and poll for the reset bit to be cleared.
|
||||
+ *
|
||||
+ * Returns: 0 on success, < 0 on failure
|
||||
+ */
|
||||
+int genphy_soft_reset(struct phy_device *phydev)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = phy_write(phydev, MII_BMCR, BMCR_RESET);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return phy_poll_reset(phydev);
|
||||
+}
|
||||
+EXPORT_SYMBOL(genphy_soft_reset);
|
||||
+
|
||||
static int genphy_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int val;
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -616,6 +616,7 @@ int genphy_update_link(struct phy_device
|
||||
int genphy_read_status(struct phy_device *phydev);
|
||||
int genphy_suspend(struct phy_device *phydev);
|
||||
int genphy_resume(struct phy_device *phydev);
|
||||
+int genphy_soft_reset(struct phy_device *phydev);
|
||||
void phy_driver_unregister(struct phy_driver *drv);
|
||||
void phy_drivers_unregister(struct phy_driver *drv, int n);
|
||||
int phy_driver_register(struct phy_driver *new_driver);
|
|
@ -1,81 +0,0 @@
|
|||
commit 9df81dd7583d14862d0cfb673a941b261f3b2112
|
||||
Author: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Date: Mon Feb 17 13:34:03 2014 -0800
|
||||
|
||||
net: phy: allow PHY drivers to implement their own software reset
|
||||
|
||||
As pointed out by Shaohui, most 10G PHYs out there have a non-standard
|
||||
compliant software reset sequence, eventually something much more
|
||||
complex than just toggling the BMCR_RESET bit. Allow PHY driver to
|
||||
implement their own soft_reset() callback to deal with that. If no
|
||||
callback is provided, call into genphy_soft_reset() which makes sure the
|
||||
existing behavior is kept intact.
|
||||
|
||||
Reported-by: Shaohui Xie <Shaohui.Xie@freescale.com>
|
||||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
|
||||
--- a/drivers/net/phy/phy_device.c
|
||||
+++ b/drivers/net/phy/phy_device.c
|
||||
@@ -534,12 +534,16 @@ static int phy_poll_reset(struct phy_dev
|
||||
|
||||
int phy_init_hw(struct phy_device *phydev)
|
||||
{
|
||||
- int ret;
|
||||
+ int ret = 0;
|
||||
|
||||
if (!phydev->drv || !phydev->drv->config_init)
|
||||
return 0;
|
||||
|
||||
- ret = genphy_soft_reset(phydev);
|
||||
+ if (phydev->drv->soft_reset)
|
||||
+ ret = phydev->drv->soft_reset(phydev);
|
||||
+ else
|
||||
+ ret = genphy_soft_reset(phydev);
|
||||
+
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -1092,6 +1096,12 @@ static int genphy_config_init(struct phy
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int gen10g_soft_reset(struct phy_device *phydev)
|
||||
+{
|
||||
+ /* Do nothing for now */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int gen10g_config_init(struct phy_device *phydev)
|
||||
{
|
||||
/* Temporarily just say we support everything */
|
||||
@@ -1266,6 +1276,7 @@ static struct phy_driver genphy_driver[]
|
||||
.phy_id = 0xffffffff,
|
||||
.phy_id_mask = 0xffffffff,
|
||||
.name = "Generic PHY",
|
||||
+ .soft_reset = genphy_soft_reset,
|
||||
.config_init = genphy_config_init,
|
||||
.features = 0,
|
||||
.config_aneg = genphy_config_aneg,
|
||||
@@ -1277,6 +1288,7 @@ static struct phy_driver genphy_driver[]
|
||||
.phy_id = 0xffffffff,
|
||||
.phy_id_mask = 0xffffffff,
|
||||
.name = "Generic 10G PHY",
|
||||
+ .soft_reset = gen10g_soft_reset,
|
||||
.config_init = gen10g_config_init,
|
||||
.features = 0,
|
||||
.config_aneg = gen10g_config_aneg,
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -394,6 +394,11 @@ struct phy_driver {
|
||||
u32 flags;
|
||||
|
||||
/*
|
||||
+ * Called to issue a PHY software reset
|
||||
+ */
|
||||
+ int (*soft_reset)(struct phy_device *phydev);
|
||||
+
|
||||
+ /*
|
||||
* Called to initialize the PHY,
|
||||
* including after a reset
|
||||
*/
|
|
@ -1,35 +0,0 @@
|
|||
From: Balakumaran Kannan <kumaran.4353@gmail.com>
|
||||
Date: Thu, 24 Apr 2014 08:22:47 +0530
|
||||
Subject: [PATCH] net phy: Check for aneg completion before setting state to
|
||||
PHY_RUNNING
|
||||
|
||||
phy_state_machine should check whether auto-negotiatin is completed
|
||||
before changing phydev->state from PHY_NOLINK to PHY_RUNNING. If
|
||||
auto-negotiation is not completed phydev->state should be set to
|
||||
PHY_AN.
|
||||
|
||||
Signed-off-by: Balakumaran Kannan <kumaran.4353@gmail.com>
|
||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
|
||||
--- a/drivers/net/phy/phy.c
|
||||
+++ b/drivers/net/phy/phy.c
|
||||
@@ -744,6 +744,17 @@ void phy_state_machine(struct work_struc
|
||||
break;
|
||||
|
||||
if (phydev->link) {
|
||||
+ if (AUTONEG_ENABLE == phydev->autoneg) {
|
||||
+ err = phy_aneg_done(phydev);
|
||||
+ if (err < 0)
|
||||
+ break;
|
||||
+
|
||||
+ if (!err) {
|
||||
+ phydev->state = PHY_AN;
|
||||
+ phydev->link_timeout = PHY_AN_TIMEOUT;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
phydev->state = PHY_RUNNING;
|
||||
netif_carrier_on(phydev->attached_dev);
|
||||
phydev->adjust_link(phydev->attached_dev);
|
|
@ -1,68 +0,0 @@
|
|||
--- a/drivers/net/phy/phy.c
|
||||
+++ b/drivers/net/phy/phy.c
|
||||
@@ -690,7 +690,7 @@ void phy_state_machine(struct work_struc
|
||||
struct delayed_work *dwork = to_delayed_work(work);
|
||||
struct phy_device *phydev =
|
||||
container_of(dwork, struct phy_device, state_queue);
|
||||
- int needs_aneg = 0, do_suspend = 0;
|
||||
+ bool needs_aneg = false, do_suspend = false, do_resume = false;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
@@ -702,7 +702,7 @@ void phy_state_machine(struct work_struc
|
||||
case PHY_PENDING:
|
||||
break;
|
||||
case PHY_UP:
|
||||
- needs_aneg = 1;
|
||||
+ needs_aneg = true;
|
||||
|
||||
phydev->link_timeout = PHY_AN_TIMEOUT;
|
||||
|
||||
@@ -732,7 +732,7 @@ void phy_state_machine(struct work_struc
|
||||
phydev->adjust_link(phydev->attached_dev);
|
||||
|
||||
} else if (0 == phydev->link_timeout--) {
|
||||
- needs_aneg = 1;
|
||||
+ needs_aneg = true;
|
||||
/* If we have the magic_aneg bit, we try again */
|
||||
if (phydev->drv->flags & PHY_HAS_MAGICANEG)
|
||||
break;
|
||||
@@ -770,7 +770,7 @@ void phy_state_machine(struct work_struc
|
||||
netif_carrier_on(phydev->attached_dev);
|
||||
} else {
|
||||
if (0 == phydev->link_timeout--)
|
||||
- needs_aneg = 1;
|
||||
+ needs_aneg = true;
|
||||
}
|
||||
|
||||
phydev->adjust_link(phydev->attached_dev);
|
||||
@@ -806,7 +806,7 @@ void phy_state_machine(struct work_struc
|
||||
phydev->link = 0;
|
||||
netif_carrier_off(phydev->attached_dev);
|
||||
phydev->adjust_link(phydev->attached_dev);
|
||||
- do_suspend = 1;
|
||||
+ do_suspend = true;
|
||||
}
|
||||
break;
|
||||
case PHY_RESUMING:
|
||||
@@ -855,6 +855,7 @@ void phy_state_machine(struct work_struc
|
||||
}
|
||||
phydev->adjust_link(phydev->attached_dev);
|
||||
}
|
||||
+ do_resume = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -862,9 +863,10 @@ void phy_state_machine(struct work_struc
|
||||
|
||||
if (needs_aneg)
|
||||
err = phy_start_aneg(phydev);
|
||||
-
|
||||
- if (do_suspend)
|
||||
+ else if (do_suspend)
|
||||
phy_suspend(phydev);
|
||||
+ else if (do_resume)
|
||||
+ phy_resume(phydev);
|
||||
|
||||
if (err < 0)
|
||||
phy_error(phydev);
|
|
@ -1,44 +0,0 @@
|
|||
From 6216642f200258708e47170ff14ba8ecb486f4f0 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 18 Jan 2015 19:49:58 +0100
|
||||
Subject: [PATCH] bgmac: register napi before the device
|
||||
|
||||
napi should get registered before the netdev and not after.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bgmac.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bgmac.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bgmac.c
|
||||
@@ -1515,6 +1515,8 @@ static int bgmac_probe(struct bcma_devic
|
||||
if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
|
||||
bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n");
|
||||
|
||||
+ netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
|
||||
+
|
||||
err = bgmac_mii_register(bgmac);
|
||||
if (err) {
|
||||
bgmac_err(bgmac, "Cannot register MDIO\n");
|
||||
@@ -1529,8 +1531,6 @@ static int bgmac_probe(struct bcma_devic
|
||||
|
||||
netif_carrier_off(net_dev);
|
||||
|
||||
- netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
|
||||
-
|
||||
return 0;
|
||||
|
||||
err_mii_unregister:
|
||||
@@ -1549,9 +1549,9 @@ static void bgmac_remove(struct bcma_dev
|
||||
{
|
||||
struct bgmac *bgmac = bcma_get_drvdata(core);
|
||||
|
||||
- netif_napi_del(&bgmac->napi);
|
||||
unregister_netdev(bgmac->net_dev);
|
||||
bgmac_mii_unregister(bgmac);
|
||||
+ netif_napi_del(&bgmac->napi);
|
||||
bgmac_dma_free(bgmac);
|
||||
bcma_set_drvdata(core, NULL);
|
||||
free_netdev(bgmac->net_dev);
|
|
@ -1,30 +0,0 @@
|
|||
From 43f159c60a99318b1ef7d1d7c16c4dfdd06bfd90 Mon Sep 17 00:00:00 2001
|
||||
From: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Date: Sun, 18 Jan 2015 19:49:59 +0100
|
||||
Subject: [PATCH] bgmac: activate irqs only if there is nothing to poll
|
||||
|
||||
IRQs should only get activated when there is nothing to poll in the
|
||||
queue any more and to after every poll.
|
||||
|
||||
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/broadcom/bgmac.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/broadcom/bgmac.c
|
||||
+++ b/drivers/net/ethernet/broadcom/bgmac.c
|
||||
@@ -1167,10 +1167,10 @@ static int bgmac_poll(struct napi_struct
|
||||
bgmac->int_status = 0;
|
||||
}
|
||||
|
||||
- if (handled < weight)
|
||||
+ if (handled < weight) {
|
||||
napi_complete(napi);
|
||||
-
|
||||
- bgmac_chip_intrs_on(bgmac);
|
||||
+ bgmac_chip_intrs_on(bgmac);
|
||||
+ }
|
||||
|
||||
return handled;
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
commit 5596732fa8c14139018ecda8356eabbfb599d830
|
||||
Author: Steffen Klassert <steffen.klassert@secunet.com>
|
||||
Date: Mon Apr 7 08:08:52 2014 +0200
|
||||
|
||||
xfrm: Fix crash with ipv6 IPsec tunnel and NAT.
|
||||
|
||||
The ipv6 xfrm output path is not aware that packets can be
|
||||
rerouted by NAT to not use IPsec. We crash in this case
|
||||
because we expect to have a xfrm state at the dst_entry.
|
||||
This crash happens if the ipv6 layer does IPsec and NAT
|
||||
or if we have an interfamily IPsec tunnel with ipv4 NAT.
|
||||
|
||||
We fix this by checking for a NAT rerouted packet in each
|
||||
address family and dst_output() to the new destination
|
||||
in this case.
|
||||
|
||||
Reported-by: Martin Pelikan <martin.pelikan@gmail.com>
|
||||
Tested-by: Martin Pelikan <martin.pelikan@gmail.com>
|
||||
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
|
||||
|
||||
--- a/net/ipv4/xfrm4_output.c
|
||||
+++ b/net/ipv4/xfrm4_output.c
|
||||
@@ -62,10 +62,7 @@ int xfrm4_prepare_output(struct xfrm_sta
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
||||
- IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED;
|
||||
-
|
||||
- skb->protocol = htons(ETH_P_IP);
|
||||
+ IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
|
||||
|
||||
return x->outer_mode->output2(x, skb);
|
||||
}
|
||||
@@ -73,27 +70,34 @@ EXPORT_SYMBOL(xfrm4_prepare_output);
|
||||
|
||||
int xfrm4_output_finish(struct sk_buff *skb)
|
||||
{
|
||||
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
|
||||
+ skb->protocol = htons(ETH_P_IP);
|
||||
+
|
||||
+#ifdef CONFIG_NETFILTER
|
||||
+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
|
||||
+#endif
|
||||
+
|
||||
+ return xfrm_output(skb);
|
||||
+}
|
||||
+
|
||||
+static int __xfrm4_output(struct sk_buff *skb)
|
||||
+{
|
||||
+ struct xfrm_state *x = skb_dst(skb)->xfrm;
|
||||
+
|
||||
#ifdef CONFIG_NETFILTER
|
||||
- if (!skb_dst(skb)->xfrm) {
|
||||
+ if (!x) {
|
||||
IPCB(skb)->flags |= IPSKB_REROUTED;
|
||||
return dst_output(skb);
|
||||
}
|
||||
-
|
||||
- IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
|
||||
#endif
|
||||
|
||||
- skb->protocol = htons(ETH_P_IP);
|
||||
- return xfrm_output(skb);
|
||||
+ return x->outer_mode->afinfo->output_finish(skb);
|
||||
}
|
||||
|
||||
int xfrm4_output(struct sk_buff *skb)
|
||||
{
|
||||
- struct dst_entry *dst = skb_dst(skb);
|
||||
- struct xfrm_state *x = dst->xfrm;
|
||||
-
|
||||
return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb,
|
||||
- NULL, dst->dev,
|
||||
- x->outer_mode->afinfo->output_finish,
|
||||
+ NULL, skb_dst(skb)->dev, __xfrm4_output,
|
||||
!(IPCB(skb)->flags & IPSKB_REROUTED));
|
||||
}
|
||||
|
||||
--- a/net/ipv6/xfrm6_output.c
|
||||
+++ b/net/ipv6/xfrm6_output.c
|
||||
@@ -114,12 +114,6 @@ int xfrm6_prepare_output(struct xfrm_sta
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
|
||||
-#ifdef CONFIG_NETFILTER
|
||||
- IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
|
||||
-#endif
|
||||
-
|
||||
- skb->protocol = htons(ETH_P_IPV6);
|
||||
skb->local_df = 1;
|
||||
|
||||
return x->outer_mode->output2(x, skb);
|
||||
@@ -128,11 +122,13 @@ EXPORT_SYMBOL(xfrm6_prepare_output);
|
||||
|
||||
int xfrm6_output_finish(struct sk_buff *skb)
|
||||
{
|
||||
+ memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
|
||||
+ skb->protocol = htons(ETH_P_IPV6);
|
||||
+
|
||||
#ifdef CONFIG_NETFILTER
|
||||
IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
|
||||
#endif
|
||||
|
||||
- skb->protocol = htons(ETH_P_IPV6);
|
||||
return xfrm_output(skb);
|
||||
}
|
||||
|
||||
@@ -142,6 +138,13 @@ static int __xfrm6_output(struct sk_buff
|
||||
struct xfrm_state *x = dst->xfrm;
|
||||
int mtu;
|
||||
|
||||
+#ifdef CONFIG_NETFILTER
|
||||
+ if (!x) {
|
||||
+ IP6CB(skb)->flags |= IP6SKB_REROUTED;
|
||||
+ return dst_output(skb);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (skb->protocol == htons(ETH_P_IPV6))
|
||||
mtu = ip6_skb_dst_mtu(skb);
|
||||
else
|
||||
@@ -165,6 +168,7 @@ static int __xfrm6_output(struct sk_buff
|
||||
|
||||
int xfrm6_output(struct sk_buff *skb)
|
||||
{
|
||||
- return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL,
|
||||
- skb_dst(skb)->dev, __xfrm6_output);
|
||||
+ return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb,
|
||||
+ NULL, skb_dst(skb)->dev, __xfrm6_output,
|
||||
+ !(IP6CB(skb)->flags & IP6SKB_REROUTED));
|
||||
}
|
|
@ -1,508 +0,0 @@
|
|||
Subject: netfilter: conntrack: cache route for forwarded connections
|
||||
|
||||
... to avoid per-packet FIB lookup if possible.
|
||||
|
||||
The cached dst is re-used provided the input interface
|
||||
is the same as that of the previous packet in the same direction.
|
||||
|
||||
If not, the cached dst is invalidated.
|
||||
|
||||
For ipv6 we also need to store sernum, else dst_check doesn't work,
|
||||
pointed out by Eric Dumazet.
|
||||
|
||||
This should speed up forwarding when conntrack is already in use
|
||||
anyway, especially when using reverse path filtering -- active RPF
|
||||
enforces two FIB lookups for each packet.
|
||||
|
||||
Before the routing cache removal this didn't matter since RPF was performed
|
||||
only when route cache didn't yield a result; but without route cache it
|
||||
comes at higher price.
|
||||
|
||||
Julian Anastasov suggested to add NETDEV_UNREGISTER handler to
|
||||
avoid holding on to dsts of 'frozen' conntracks.
|
||||
|
||||
Signed-off-by: Florian Westphal <fw@strlen.de>
|
||||
|
||||
--- a/include/net/netfilter/nf_conntrack_extend.h
|
||||
+++ b/include/net/netfilter/nf_conntrack_extend.h
|
||||
@@ -30,6 +30,9 @@ enum nf_ct_ext_id {
|
||||
#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
|
||||
NF_CT_EXT_SYNPROXY,
|
||||
#endif
|
||||
+#if IS_ENABLED(CONFIG_NF_CONNTRACK_RTCACHE)
|
||||
+ NF_CT_EXT_RTCACHE,
|
||||
+#endif
|
||||
NF_CT_EXT_NUM,
|
||||
};
|
||||
|
||||
@@ -43,6 +46,7 @@ enum nf_ct_ext_id {
|
||||
#define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout
|
||||
#define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels
|
||||
#define NF_CT_EXT_SYNPROXY_TYPE struct nf_conn_synproxy
|
||||
+#define NF_CT_EXT_RTCACHE_TYPE struct nf_conn_rtcache
|
||||
|
||||
/* Extensions: optional stuff which isn't permanently in struct. */
|
||||
struct nf_ct_ext {
|
||||
--- /dev/null
|
||||
+++ b/include/net/netfilter/nf_conntrack_rtcache.h
|
||||
@@ -0,0 +1,34 @@
|
||||
+#include <linux/gfp.h>
|
||||
+#include <net/netfilter/nf_conntrack.h>
|
||||
+#include <net/netfilter/nf_conntrack_extend.h>
|
||||
+
|
||||
+struct dst_entry;
|
||||
+
|
||||
+struct nf_conn_dst_cache {
|
||||
+ struct dst_entry *dst;
|
||||
+ int iif;
|
||||
+#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
|
||||
+ u32 cookie;
|
||||
+#endif
|
||||
+
|
||||
+};
|
||||
+
|
||||
+struct nf_conn_rtcache {
|
||||
+ struct nf_conn_dst_cache cached_dst[IP_CT_DIR_MAX];
|
||||
+};
|
||||
+
|
||||
+static inline
|
||||
+struct nf_conn_rtcache *nf_ct_rtcache_find(const struct nf_conn *ct)
|
||||
+{
|
||||
+#if IS_ENABLED(CONFIG_NF_CONNTRACK_RTCACHE)
|
||||
+ return nf_ct_ext_find(ct, NF_CT_EXT_RTCACHE);
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int nf_conn_rtcache_iif_get(const struct nf_conn_rtcache *rtc,
|
||||
+ enum ip_conntrack_dir dir)
|
||||
+{
|
||||
+ return rtc->cached_dst[dir].iif;
|
||||
+}
|
||||
--- a/net/netfilter/Kconfig
|
||||
+++ b/net/netfilter/Kconfig
|
||||
@@ -103,6 +103,18 @@ config NF_CONNTRACK_EVENTS
|
||||
|
||||
If unsure, say `N'.
|
||||
|
||||
+config NF_CONNTRACK_RTCACHE
|
||||
+ tristate "Cache route entries in conntrack objects"
|
||||
+ depends on NETFILTER_ADVANCED
|
||||
+ depends on NF_CONNTRACK
|
||||
+ help
|
||||
+ If this option is enabled, the connection tracking code will
|
||||
+ cache routing information for each connection that is being
|
||||
+ forwarded, at a cost of 32 bytes per conntrack object.
|
||||
+
|
||||
+ To compile it as a module, choose M here. If unsure, say N.
|
||||
+ The module will be called nf_conntrack_rtcache.
|
||||
+
|
||||
config NF_CONNTRACK_TIMEOUT
|
||||
bool 'Connection tracking timeout'
|
||||
depends on NETFILTER_ADVANCED
|
||||
--- a/net/netfilter/Makefile
|
||||
+++ b/net/netfilter/Makefile
|
||||
@@ -18,6 +18,9 @@ obj-$(CONFIG_NETFILTER_NETLINK_LOG) += n
|
||||
# connection tracking
|
||||
obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
|
||||
|
||||
+# optional conntrack route cache extension
|
||||
+obj-$(CONFIG_NF_CONNTRACK_RTCACHE) += nf_conntrack_rtcache.o
|
||||
+
|
||||
# SCTP protocol connection tracking
|
||||
obj-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
|
||||
obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
|
||||
--- /dev/null
|
||||
+++ b/net/netfilter/nf_conntrack_rtcache.c
|
||||
@@ -0,0 +1,390 @@
|
||||
+/* route cache for netfilter.
|
||||
+ *
|
||||
+ * (C) 2014 Red Hat GmbH
|
||||
+ *
|
||||
+ * 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.
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/netfilter.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+#include <linux/stddef.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <linux/export.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+#include <net/dst.h>
|
||||
+
|
||||
+#include <net/netfilter/nf_conntrack.h>
|
||||
+#include <net/netfilter/nf_conntrack_core.h>
|
||||
+#include <net/netfilter/nf_conntrack_extend.h>
|
||||
+#include <net/netfilter/nf_conntrack_rtcache.h>
|
||||
+
|
||||
+#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
|
||||
+#include <net/ip6_fib.h>
|
||||
+#endif
|
||||
+
|
||||
+static void __nf_conn_rtcache_destroy(struct nf_conn_rtcache *rtc,
|
||||
+ enum ip_conntrack_dir dir)
|
||||
+{
|
||||
+ struct dst_entry *dst = rtc->cached_dst[dir].dst;
|
||||
+
|
||||
+ dst_release(dst);
|
||||
+}
|
||||
+
|
||||
+static void nf_conn_rtcache_destroy(struct nf_conn *ct)
|
||||
+{
|
||||
+ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct);
|
||||
+
|
||||
+ if (!rtc)
|
||||
+ return;
|
||||
+
|
||||
+ __nf_conn_rtcache_destroy(rtc, IP_CT_DIR_ORIGINAL);
|
||||
+ __nf_conn_rtcache_destroy(rtc, IP_CT_DIR_REPLY);
|
||||
+}
|
||||
+
|
||||
+static void nf_ct_rtcache_ext_add(struct nf_conn *ct)
|
||||
+{
|
||||
+ struct nf_conn_rtcache *rtc;
|
||||
+
|
||||
+ rtc = nf_ct_ext_add(ct, NF_CT_EXT_RTCACHE, GFP_ATOMIC);
|
||||
+ if (rtc) {
|
||||
+ rtc->cached_dst[IP_CT_DIR_ORIGINAL].iif = -1;
|
||||
+ rtc->cached_dst[IP_CT_DIR_ORIGINAL].dst = NULL;
|
||||
+ rtc->cached_dst[IP_CT_DIR_REPLY].iif = -1;
|
||||
+ rtc->cached_dst[IP_CT_DIR_REPLY].dst = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct nf_conn_rtcache *nf_ct_rtcache_find_usable(struct nf_conn *ct)
|
||||
+{
|
||||
+ if (nf_ct_is_untracked(ct))
|
||||
+ return NULL;
|
||||
+ return nf_ct_rtcache_find(ct);
|
||||
+}
|
||||
+
|
||||
+static struct dst_entry *
|
||||
+nf_conn_rtcache_dst_get(const struct nf_conn_rtcache *rtc,
|
||||
+ enum ip_conntrack_dir dir)
|
||||
+{
|
||||
+ return rtc->cached_dst[dir].dst;
|
||||
+}
|
||||
+
|
||||
+static u32 nf_rtcache_get_cookie(int pf, const struct dst_entry *dst)
|
||||
+{
|
||||
+#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
|
||||
+ if (pf == NFPROTO_IPV6) {
|
||||
+ const struct rt6_info *rt = (const struct rt6_info *)dst;
|
||||
+
|
||||
+ if (rt->rt6i_node)
|
||||
+ return (u32)rt->rt6i_node->fn_sernum;
|
||||
+ }
|
||||
+#endif
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void nf_conn_rtcache_dst_set(int pf,
|
||||
+ struct nf_conn_rtcache *rtc,
|
||||
+ struct dst_entry *dst,
|
||||
+ enum ip_conntrack_dir dir, int iif)
|
||||
+{
|
||||
+ if (rtc->cached_dst[dir].iif != iif)
|
||||
+ rtc->cached_dst[dir].iif = iif;
|
||||
+
|
||||
+ if (rtc->cached_dst[dir].dst != dst) {
|
||||
+ struct dst_entry *old;
|
||||
+
|
||||
+ dst_hold(dst);
|
||||
+
|
||||
+ old = xchg(&rtc->cached_dst[dir].dst, dst);
|
||||
+ dst_release(old);
|
||||
+
|
||||
+#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
|
||||
+ if (pf == NFPROTO_IPV6)
|
||||
+ rtc->cached_dst[dir].cookie =
|
||||
+ nf_rtcache_get_cookie(pf, dst);
|
||||
+#endif
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void nf_conn_rtcache_dst_obsolete(struct nf_conn_rtcache *rtc,
|
||||
+ enum ip_conntrack_dir dir)
|
||||
+{
|
||||
+ struct dst_entry *old;
|
||||
+
|
||||
+ pr_debug("Invalidate iif %d for dir %d on cache %p\n",
|
||||
+ rtc->cached_dst[dir].iif, dir, rtc);
|
||||
+
|
||||
+ old = xchg(&rtc->cached_dst[dir].dst, NULL);
|
||||
+ dst_release(old);
|
||||
+ rtc->cached_dst[dir].iif = -1;
|
||||
+}
|
||||
+
|
||||
+static unsigned int nf_rtcache_in(const struct nf_hook_ops *ops,
|
||||
+ struct sk_buff *skb,
|
||||
+ const struct net_device *in,
|
||||
+ const struct net_device *out,
|
||||
+ int (*okfn)(struct sk_buff *))
|
||||
+{
|
||||
+ struct nf_conn_rtcache *rtc;
|
||||
+ enum ip_conntrack_info ctinfo;
|
||||
+ enum ip_conntrack_dir dir;
|
||||
+ struct dst_entry *dst;
|
||||
+ struct nf_conn *ct;
|
||||
+ int iif;
|
||||
+ u32 cookie;
|
||||
+
|
||||
+ if (skb_dst(skb) || skb->sk)
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
+ ct = nf_ct_get(skb, &ctinfo);
|
||||
+ if (!ct)
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
+ rtc = nf_ct_rtcache_find_usable(ct);
|
||||
+ if (!rtc)
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
+ /* if iif changes, don't use cache and let ip stack
|
||||
+ * do route lookup.
|
||||
+ *
|
||||
+ * If rp_filter is enabled it might toss skb, so
|
||||
+ * we don't want to avoid these checks.
|
||||
+ */
|
||||
+ dir = CTINFO2DIR(ctinfo);
|
||||
+ iif = nf_conn_rtcache_iif_get(rtc, dir);
|
||||
+ if (in->ifindex != iif) {
|
||||
+ pr_debug("ct %p, iif %d, cached iif %d, skip cached entry\n",
|
||||
+ ct, iif, in->ifindex);
|
||||
+ return NF_ACCEPT;
|
||||
+ }
|
||||
+ dst = nf_conn_rtcache_dst_get(rtc, dir);
|
||||
+ if (dst == NULL)
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
+ cookie = nf_rtcache_get_cookie(ops->pf, dst);
|
||||
+
|
||||
+ dst = dst_check(dst, cookie);
|
||||
+ pr_debug("obtained dst %p for skb %p, cookie %d\n", dst, skb, cookie);
|
||||
+ if (likely(dst))
|
||||
+ skb_dst_set_noref_force(skb, dst);
|
||||
+ else
|
||||
+ nf_conn_rtcache_dst_obsolete(rtc, dir);
|
||||
+
|
||||
+ return NF_ACCEPT;
|
||||
+}
|
||||
+
|
||||
+static unsigned int nf_rtcache_forward(const struct nf_hook_ops *ops,
|
||||
+ struct sk_buff *skb,
|
||||
+ const struct net_device *in,
|
||||
+ const struct net_device *out,
|
||||
+ int (*okfn)(struct sk_buff *))
|
||||
+{
|
||||
+ struct nf_conn_rtcache *rtc;
|
||||
+ enum ip_conntrack_info ctinfo;
|
||||
+ enum ip_conntrack_dir dir;
|
||||
+ struct nf_conn *ct;
|
||||
+ struct dst_entry *dst = skb_dst(skb);
|
||||
+ int iif;
|
||||
+
|
||||
+ ct = nf_ct_get(skb, &ctinfo);
|
||||
+ if (!ct)
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
+ if (dst && dst_xfrm(dst))
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
+ if (!nf_ct_is_confirmed(ct)) {
|
||||
+ if (WARN_ON(nf_ct_rtcache_find(ct)))
|
||||
+ return NF_ACCEPT;
|
||||
+ nf_ct_rtcache_ext_add(ct);
|
||||
+ return NF_ACCEPT;
|
||||
+ }
|
||||
+
|
||||
+ rtc = nf_ct_rtcache_find_usable(ct);
|
||||
+ if (!rtc)
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
+ dir = CTINFO2DIR(ctinfo);
|
||||
+ iif = nf_conn_rtcache_iif_get(rtc, dir);
|
||||
+ pr_debug("ct %p, skb %p, dir %d, iif %d, cached iif %d\n",
|
||||
+ ct, skb, dir, iif, in->ifindex);
|
||||
+ if (likely(in->ifindex == iif))
|
||||
+ return NF_ACCEPT;
|
||||
+
|
||||
+ nf_conn_rtcache_dst_set(ops->pf, rtc, skb_dst(skb), dir, in->ifindex);
|
||||
+ return NF_ACCEPT;
|
||||
+}
|
||||
+
|
||||
+static int nf_rtcache_dst_remove(struct nf_conn *ct, void *data)
|
||||
+{
|
||||
+ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct);
|
||||
+ struct net_device *dev = data;
|
||||
+
|
||||
+ if (!rtc)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (dev->ifindex == rtc->cached_dst[IP_CT_DIR_ORIGINAL].iif ||
|
||||
+ dev->ifindex == rtc->cached_dst[IP_CT_DIR_REPLY].iif) {
|
||||
+ nf_conn_rtcache_dst_obsolete(rtc, IP_CT_DIR_ORIGINAL);
|
||||
+ nf_conn_rtcache_dst_obsolete(rtc, IP_CT_DIR_REPLY);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int nf_rtcache_netdev_event(struct notifier_block *this,
|
||||
+ unsigned long event, void *ptr)
|
||||
+{
|
||||
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
+ struct net *net = dev_net(dev);
|
||||
+
|
||||
+ if (event == NETDEV_DOWN)
|
||||
+ nf_ct_iterate_cleanup(net, nf_rtcache_dst_remove, dev, 0, 0);
|
||||
+
|
||||
+ return NOTIFY_DONE;
|
||||
+}
|
||||
+
|
||||
+static struct notifier_block nf_rtcache_notifier = {
|
||||
+ .notifier_call = nf_rtcache_netdev_event,
|
||||
+};
|
||||
+
|
||||
+static struct nf_hook_ops rtcache_ops[] = {
|
||||
+ {
|
||||
+ .hook = nf_rtcache_in,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .pf = NFPROTO_IPV4,
|
||||
+ .hooknum = NF_INET_PRE_ROUTING,
|
||||
+ .priority = NF_IP_PRI_LAST,
|
||||
+ },
|
||||
+ {
|
||||
+ .hook = nf_rtcache_forward,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .pf = NFPROTO_IPV4,
|
||||
+ .hooknum = NF_INET_FORWARD,
|
||||
+ .priority = NF_IP_PRI_LAST,
|
||||
+ },
|
||||
+#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV6)
|
||||
+ {
|
||||
+ .hook = nf_rtcache_in,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .pf = NFPROTO_IPV6,
|
||||
+ .hooknum = NF_INET_PRE_ROUTING,
|
||||
+ .priority = NF_IP_PRI_LAST,
|
||||
+ },
|
||||
+ {
|
||||
+ .hook = nf_rtcache_forward,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .pf = NFPROTO_IPV6,
|
||||
+ .hooknum = NF_INET_FORWARD,
|
||||
+ .priority = NF_IP_PRI_LAST,
|
||||
+ },
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct nf_ct_ext_type rtcache_extend __read_mostly = {
|
||||
+ .len = sizeof(struct nf_conn_rtcache),
|
||||
+ .align = __alignof__(struct nf_conn_rtcache),
|
||||
+ .id = NF_CT_EXT_RTCACHE,
|
||||
+ .destroy = nf_conn_rtcache_destroy,
|
||||
+};
|
||||
+
|
||||
+static int __init nf_conntrack_rtcache_init(void)
|
||||
+{
|
||||
+ int ret = nf_ct_extend_register(&rtcache_extend);
|
||||
+
|
||||
+ if (ret < 0) {
|
||||
+ pr_err("nf_conntrack_rtcache: Unable to register extension\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = nf_register_hooks(rtcache_ops, ARRAY_SIZE(rtcache_ops));
|
||||
+ if (ret < 0) {
|
||||
+ nf_ct_extend_unregister(&rtcache_extend);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = register_netdevice_notifier(&nf_rtcache_notifier);
|
||||
+ if (ret) {
|
||||
+ nf_unregister_hooks(rtcache_ops, ARRAY_SIZE(rtcache_ops));
|
||||
+ nf_ct_extend_unregister(&rtcache_extend);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int nf_rtcache_ext_remove(struct nf_conn *ct, void *data)
|
||||
+{
|
||||
+ struct nf_conn_rtcache *rtc = nf_ct_rtcache_find(ct);
|
||||
+
|
||||
+ return rtc != NULL;
|
||||
+}
|
||||
+
|
||||
+static bool __exit nf_conntrack_rtcache_wait_for_dying(struct net *net)
|
||||
+{
|
||||
+ bool wait = false;
|
||||
+ int cpu;
|
||||
+
|
||||
+ for_each_possible_cpu(cpu) {
|
||||
+ struct nf_conntrack_tuple_hash *h;
|
||||
+ struct hlist_nulls_node *n;
|
||||
+ struct nf_conn *ct;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ spin_lock_bh(&nf_conntrack_lock);
|
||||
+
|
||||
+ hlist_nulls_for_each_entry(h, n, &net->ct.dying, hnnode) {
|
||||
+ ct = nf_ct_tuplehash_to_ctrack(h);
|
||||
+ if (nf_ct_rtcache_find(ct) != NULL) {
|
||||
+ wait = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ spin_unlock_bh(&nf_conntrack_lock);
|
||||
+ rcu_read_unlock();
|
||||
+ }
|
||||
+
|
||||
+ return wait;
|
||||
+}
|
||||
+
|
||||
+static void __exit nf_conntrack_rtcache_fini(void)
|
||||
+{
|
||||
+ struct net *net;
|
||||
+ int count = 0;
|
||||
+
|
||||
+ /* remove hooks so no new connections get rtcache extension */
|
||||
+ nf_unregister_hooks(rtcache_ops, ARRAY_SIZE(rtcache_ops));
|
||||
+
|
||||
+ synchronize_net();
|
||||
+
|
||||
+ unregister_netdevice_notifier(&nf_rtcache_notifier);
|
||||
+
|
||||
+ rtnl_lock();
|
||||
+
|
||||
+ /* zap all conntracks with rtcache extension */
|
||||
+ for_each_net(net)
|
||||
+ nf_ct_iterate_cleanup(net, nf_rtcache_ext_remove, NULL, 0, 0);
|
||||
+
|
||||
+ for_each_net(net) {
|
||||
+ /* .. and make sure they're gone from dying list, too */
|
||||
+ while (nf_conntrack_rtcache_wait_for_dying(net)) {
|
||||
+ msleep(200);
|
||||
+ WARN_ONCE(++count > 25, "Waiting for all rtcache conntracks to go away\n");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ rtnl_unlock();
|
||||
+ synchronize_net();
|
||||
+ nf_ct_extend_unregister(&rtcache_extend);
|
||||
+}
|
||||
+module_init(nf_conntrack_rtcache_init);
|
||||
+module_exit(nf_conntrack_rtcache_fini);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
|
||||
+MODULE_DESCRIPTION("Conntrack route cache extension");
|
File diff suppressed because it is too large
Load diff
|
@ -1,81 +0,0 @@
|
|||
From 1e311820ec3055e3f08e687de6564692a7cec675 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Fainelli <florian@openwrt.org>
|
||||
Date: Mon, 28 Jan 2013 20:06:29 +0100
|
||||
Subject: [PATCH 11/12] USB: EHCI: add ignore_oc flag to disable overcurrent
|
||||
checking
|
||||
|
||||
This patch adds an ignore_oc flag which can be set by EHCI controller
|
||||
not supporting or wanting to disable overcurrent checking. The EHCI
|
||||
platform data in include/linux/usb/ehci_pdriver.h is also augmented to
|
||||
take advantage of this new flag.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
---
|
||||
drivers/usb/host/ehci-hcd.c | 2 +-
|
||||
drivers/usb/host/ehci-hub.c | 4 ++--
|
||||
drivers/usb/host/ehci-platform.c | 1 +
|
||||
drivers/usb/host/ehci.h | 1 +
|
||||
include/linux/usb/ehci_pdriver.h | 1 +
|
||||
5 files changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/usb/host/ehci-hcd.c
|
||||
+++ b/drivers/usb/host/ehci-hcd.c
|
||||
@@ -633,7 +633,7 @@ static int ehci_run (struct usb_hcd *hcd
|
||||
"USB %x.%x started, EHCI %x.%02x%s\n",
|
||||
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
|
||||
temp >> 8, temp & 0xff,
|
||||
- ignore_oc ? ", overcurrent ignored" : "");
|
||||
+ (ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : "");
|
||||
|
||||
ehci_writel(ehci, INTR_MASK,
|
||||
&ehci->regs->intr_enable); /* Turn On Interrupts */
|
||||
--- a/drivers/usb/host/ehci-hub.c
|
||||
+++ b/drivers/usb/host/ehci-hub.c
|
||||
@@ -641,7 +641,7 @@ ehci_hub_status_data (struct usb_hcd *hc
|
||||
* always set, seem to clear PORT_OCC and PORT_CSC when writing to
|
||||
* PORT_POWER; that's surprising, but maybe within-spec.
|
||||
*/
|
||||
- if (!ignore_oc)
|
||||
+ if (!ignore_oc && !ehci->ignore_oc)
|
||||
mask = PORT_CSC | PORT_PEC | PORT_OCC;
|
||||
else
|
||||
mask = PORT_CSC | PORT_PEC;
|
||||
@@ -1001,7 +1001,7 @@ static int ehci_hub_control (
|
||||
if (temp & PORT_PEC)
|
||||
status |= USB_PORT_STAT_C_ENABLE << 16;
|
||||
|
||||
- if ((temp & PORT_OCC) && !ignore_oc){
|
||||
+ if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){
|
||||
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
|
||||
|
||||
/*
|
||||
--- a/drivers/usb/host/ehci-platform.c
|
||||
+++ b/drivers/usb/host/ehci-platform.c
|
||||
@@ -47,6 +47,7 @@ static int ehci_platform_reset(struct us
|
||||
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
|
||||
ehci->big_endian_desc = pdata->big_endian_desc;
|
||||
ehci->big_endian_mmio = pdata->big_endian_mmio;
|
||||
+ ehci->ignore_oc = pdata->ignore_oc;
|
||||
|
||||
if (pdata->pre_setup) {
|
||||
retval = pdata->pre_setup(hcd);
|
||||
--- a/drivers/usb/host/ehci.h
|
||||
+++ b/drivers/usb/host/ehci.h
|
||||
@@ -226,6 +226,7 @@ struct ehci_hcd { /* one per controlle
|
||||
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
|
||||
unsigned need_oc_pp_cycle:1; /* MPC834X port power */
|
||||
unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
|
||||
+ unsigned ignore_oc:1;
|
||||
|
||||
/* required for usb32 quirk */
|
||||
#define OHCI_CTRL_HCFS (3 << 6)
|
||||
--- a/include/linux/usb/ehci_pdriver.h
|
||||
+++ b/include/linux/usb/ehci_pdriver.h
|
||||
@@ -45,6 +45,7 @@ struct usb_ehci_pdata {
|
||||
unsigned big_endian_desc:1;
|
||||
unsigned big_endian_mmio:1;
|
||||
unsigned no_io_watchdog:1;
|
||||
+ unsigned ignore_oc:1;
|
||||
|
||||
/* Turn on all power and clocks */
|
||||
int (*power_on)(struct platform_device *pdev);
|
|
@ -1,54 +0,0 @@
|
|||
From: Stephen Hemminger <stephen@networkplumber.org>
|
||||
Subject: bridge: allow receiption on disabled port
|
||||
|
||||
When an ethernet device is enslaved to a bridge, and the bridge STP
|
||||
detects loss of carrier (or operational state down), then normally
|
||||
packet receiption is blocked.
|
||||
|
||||
This breaks control applications like WPA which maybe expecting to
|
||||
receive packets to negotiate to bring link up. The bridge needs to
|
||||
block forwarding packets from these disabled ports, but there is no
|
||||
hard requirement to not allow local packet delivery.
|
||||
|
||||
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
|
||||
--- a/net/bridge/br_input.c
|
||||
+++ b/net/bridge/br_input.c
|
||||
@@ -145,11 +145,13 @@ drop:
|
||||
static int br_handle_local_finish(struct sk_buff *skb)
|
||||
{
|
||||
struct net_bridge_port *p = br_port_get_rcu(skb->dev);
|
||||
- u16 vid = 0;
|
||||
+ if (p->state != BR_STATE_DISABLED) {
|
||||
+ u16 vid = 0;
|
||||
|
||||
- /* check if vlan is allowed, to avoid spoofing */
|
||||
- if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid))
|
||||
- br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false);
|
||||
+ /* check if vlan is allowed, to avoid spoofing */
|
||||
+ if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid))
|
||||
+ br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false);
|
||||
+ }
|
||||
return 0; /* process further */
|
||||
}
|
||||
|
||||
@@ -219,6 +221,18 @@ rx_handler_result_t br_handle_frame(stru
|
||||
|
||||
forward:
|
||||
switch (p->state) {
|
||||
+ case BR_STATE_DISABLED:
|
||||
+ if (ether_addr_equal(p->br->dev->dev_addr, dest))
|
||||
+ skb->pkt_type = PACKET_HOST;
|
||||
+
|
||||
+ if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
|
||||
+ br_handle_local_finish))
|
||||
+ break;
|
||||
+
|
||||
+ BR_INPUT_SKB_CB(skb)->brdev = p->br->dev;
|
||||
+ br_pass_frame_up(skb);
|
||||
+ break;
|
||||
+
|
||||
case BR_STATE_FORWARDING:
|
||||
rhook = rcu_dereference(br_should_route_hook);
|
||||
if (rhook) {
|
|
@ -1,679 +0,0 @@
|
|||
From 2c58080407554e1bac8fd50d23cb02420524caed Mon Sep 17 00:00:00 2001
|
||||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Date: Mon, 12 Aug 2013 12:50:22 +0200
|
||||
Subject: [PATCH] MIPS: partially inline dma ops
|
||||
|
||||
Several DMA ops are no-op on many platforms, and the indirection through
|
||||
the mips_dma_map_ops function table is causing the compiler to emit
|
||||
unnecessary code.
|
||||
|
||||
Inlining visibly improves network performance in my tests (on a 24Kc
|
||||
based system), and also slightly reduces code size of a few drivers.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
arch/mips/Kconfig | 4 +
|
||||
arch/mips/include/asm/dma-mapping.h | 360 +++++++++++++++++++++++++++++++++++-
|
||||
arch/mips/mm/dma-default.c | 163 ++--------------
|
||||
3 files changed, 373 insertions(+), 154 deletions(-)
|
||||
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -1621,6 +1621,9 @@ config SYS_HAS_CPU_XLR
|
||||
config SYS_HAS_CPU_XLP
|
||||
bool
|
||||
|
||||
+config SYS_HAS_DMA_OPS
|
||||
+ bool
|
||||
+
|
||||
#
|
||||
# CPU may reorder R->R, R->W, W->R, W->W
|
||||
# Reordering beyond LL and SC is handled in WEAK_REORDERING_BEYOND_LLSC
|
||||
--- a/arch/mips/include/asm/dma-mapping.h
|
||||
+++ b/arch/mips/include/asm/dma-mapping.h
|
||||
@@ -1,9 +1,16 @@
|
||||
#ifndef _ASM_DMA_MAPPING_H
|
||||
#define _ASM_DMA_MAPPING_H
|
||||
|
||||
+#include <linux/kmemcheck.h>
|
||||
+#include <linux/bug.h>
|
||||
+#include <linux/scatterlist.h>
|
||||
+#include <linux/dma-debug.h>
|
||||
+#include <linux/dma-attrs.h>
|
||||
+
|
||||
#include <asm/scatterlist.h>
|
||||
#include <asm/dma-coherence.h>
|
||||
#include <asm/cache.h>
|
||||
+#include <asm/cpu-type.h>
|
||||
#include <asm-generic/dma-coherent.h>
|
||||
|
||||
#ifndef CONFIG_SGI_IP27 /* Kludge to fix 2.6.39 build for IP27 */
|
||||
@@ -12,12 +19,48 @@
|
||||
|
||||
extern struct dma_map_ops *mips_dma_map_ops;
|
||||
|
||||
+void __dma_sync(struct page *page, unsigned long offset, size_t size,
|
||||
+ enum dma_data_direction direction);
|
||||
+void *mips_dma_alloc_coherent(struct device *dev, size_t size,
|
||||
+ dma_addr_t *dma_handle, gfp_t gfp,
|
||||
+ struct dma_attrs *attrs);
|
||||
+void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
|
||||
+ dma_addr_t dma_handle, struct dma_attrs *attrs);
|
||||
+
|
||||
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
|
||||
{
|
||||
+#ifdef CONFIG_SYS_HAS_DMA_OPS
|
||||
if (dev && dev->archdata.dma_ops)
|
||||
return dev->archdata.dma_ops;
|
||||
else
|
||||
return mips_dma_map_ops;
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Warning on the terminology - Linux calls an uncached area coherent;
|
||||
+ * MIPS terminology calls memory areas with hardware maintained coherency
|
||||
+ * coherent.
|
||||
+ */
|
||||
+
|
||||
+static inline int cpu_needs_post_dma_flush(struct device *dev)
|
||||
+{
|
||||
+#ifndef CONFIG_SYS_HAS_CPU_R10000
|
||||
+ return 0;
|
||||
+#endif
|
||||
+ return !plat_device_is_coherent(dev) &&
|
||||
+ (boot_cpu_type() == CPU_R10000 ||
|
||||
+ boot_cpu_type() == CPU_R12000 ||
|
||||
+ boot_cpu_type() == CPU_BMIPS5000);
|
||||
+}
|
||||
+
|
||||
+static inline struct page *dma_addr_to_page(struct device *dev,
|
||||
+ dma_addr_t dma_addr)
|
||||
+{
|
||||
+ return pfn_to_page(
|
||||
+ plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
|
||||
@@ -30,12 +73,312 @@ static inline bool dma_capable(struct de
|
||||
|
||||
static inline void dma_mark_clean(void *addr, size_t size) {}
|
||||
|
||||
-#include <asm-generic/dma-mapping-common.h>
|
||||
+static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
|
||||
+ size_t size,
|
||||
+ enum dma_data_direction dir,
|
||||
+ struct dma_attrs *attrs)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+ unsigned long offset = (unsigned long)ptr & ~PAGE_MASK;
|
||||
+ struct page *page = virt_to_page(ptr);
|
||||
+ dma_addr_t addr;
|
||||
+
|
||||
+ kmemcheck_mark_initialized(ptr, size);
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops) {
|
||||
+ addr = ops->map_page(dev, page, offset, size, dir, attrs);
|
||||
+ } else {
|
||||
+ if (!plat_device_is_coherent(dev))
|
||||
+ __dma_sync(page, offset, size, dir);
|
||||
+
|
||||
+ addr = plat_map_dma_mem_page(dev, page) + offset;
|
||||
+ }
|
||||
+ debug_dma_map_page(dev, page, offset, size, dir, addr, true);
|
||||
+ return addr;
|
||||
+}
|
||||
+
|
||||
+static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
|
||||
+ size_t size,
|
||||
+ enum dma_data_direction dir,
|
||||
+ struct dma_attrs *attrs)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops) {
|
||||
+ ops->unmap_page(dev, addr, size, dir, attrs);
|
||||
+ } else {
|
||||
+ if (cpu_needs_post_dma_flush(dev))
|
||||
+ __dma_sync(dma_addr_to_page(dev, addr),
|
||||
+ addr & ~PAGE_MASK, size, dir);
|
||||
+
|
||||
+ plat_unmap_dma_mem(dev, addr, size, dir);
|
||||
+ }
|
||||
+ debug_dma_unmap_page(dev, addr, size, dir, true);
|
||||
+}
|
||||
+
|
||||
+static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
|
||||
+ int nents, enum dma_data_direction dir,
|
||||
+ struct dma_attrs *attrs)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+ int i, ents;
|
||||
+ struct scatterlist *s;
|
||||
+
|
||||
+ for_each_sg(sg, s, nents, i)
|
||||
+ kmemcheck_mark_initialized(sg_virt(s), s->length);
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops) {
|
||||
+ ents = ops->map_sg(dev, sg, nents, dir, attrs);
|
||||
+ } else {
|
||||
+ for_each_sg(sg, s, nents, i) {
|
||||
+ struct page *page = sg_page(s);
|
||||
+
|
||||
+ if (!plat_device_is_coherent(dev))
|
||||
+ __dma_sync(page, s->offset, s->length, dir);
|
||||
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
|
||||
+ s->dma_length = s->length;
|
||||
+#endif
|
||||
+ s->dma_address =
|
||||
+ plat_map_dma_mem_page(dev, page) + s->offset;
|
||||
+ }
|
||||
+ ents = nents;
|
||||
+ }
|
||||
+ debug_dma_map_sg(dev, sg, nents, ents, dir);
|
||||
+
|
||||
+ return ents;
|
||||
+}
|
||||
+
|
||||
+static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
|
||||
+ int nents, enum dma_data_direction dir,
|
||||
+ struct dma_attrs *attrs)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+ struct scatterlist *s;
|
||||
+ int i;
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ debug_dma_unmap_sg(dev, sg, nents, dir);
|
||||
+ if (ops) {
|
||||
+ ops->unmap_sg(dev, sg, nents, dir, attrs);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for_each_sg(sg, s, nents, i) {
|
||||
+ if (!plat_device_is_coherent(dev) && dir != DMA_TO_DEVICE)
|
||||
+ __dma_sync(sg_page(s), s->offset, s->length, dir);
|
||||
+ plat_unmap_dma_mem(dev, s->dma_address, s->length, dir);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
+ size_t offset, size_t size,
|
||||
+ enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+ dma_addr_t addr;
|
||||
+
|
||||
+ kmemcheck_mark_initialized(page_address(page) + offset, size);
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops) {
|
||||
+ addr = ops->map_page(dev, page, offset, size, dir, NULL);
|
||||
+ } else {
|
||||
+ if (!plat_device_is_coherent(dev))
|
||||
+ __dma_sync(page, offset, size, dir);
|
||||
+
|
||||
+ addr = plat_map_dma_mem_page(dev, page) + offset;
|
||||
+ }
|
||||
+ debug_dma_map_page(dev, page, offset, size, dir, addr, false);
|
||||
+
|
||||
+ return addr;
|
||||
+}
|
||||
+
|
||||
+static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
|
||||
+ size_t size, enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops) {
|
||||
+ ops->unmap_page(dev, addr, size, dir, NULL);
|
||||
+ } else {
|
||||
+ if (cpu_needs_post_dma_flush(dev))
|
||||
+ __dma_sync(dma_addr_to_page(dev, addr),
|
||||
+ addr & ~PAGE_MASK, size, dir);
|
||||
+
|
||||
+ plat_unmap_dma_mem(dev, addr, size, dir);
|
||||
+ }
|
||||
+ debug_dma_unmap_page(dev, addr, size, dir, false);
|
||||
+}
|
||||
+
|
||||
+static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
|
||||
+ size_t size,
|
||||
+ enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops)
|
||||
+ ops->sync_single_for_cpu(dev, addr, size, dir);
|
||||
+ else if (cpu_needs_post_dma_flush(dev))
|
||||
+ __dma_sync(dma_addr_to_page(dev, addr),
|
||||
+ addr & ~PAGE_MASK, size, dir);
|
||||
+ debug_dma_sync_single_for_cpu(dev, addr, size, dir);
|
||||
+}
|
||||
+
|
||||
+static inline void dma_sync_single_for_device(struct device *dev,
|
||||
+ dma_addr_t addr, size_t size,
|
||||
+ enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops)
|
||||
+ ops->sync_single_for_device(dev, addr, size, dir);
|
||||
+ else if (!plat_device_is_coherent(dev))
|
||||
+ __dma_sync(dma_addr_to_page(dev, addr),
|
||||
+ addr & ~PAGE_MASK, size, dir);
|
||||
+ debug_dma_sync_single_for_device(dev, addr, size, dir);
|
||||
+}
|
||||
+
|
||||
+static inline void dma_sync_single_range_for_cpu(struct device *dev,
|
||||
+ dma_addr_t addr,
|
||||
+ unsigned long offset,
|
||||
+ size_t size,
|
||||
+ enum dma_data_direction dir)
|
||||
+{
|
||||
+ const struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops)
|
||||
+ ops->sync_single_for_cpu(dev, addr + offset, size, dir);
|
||||
+ else if (cpu_needs_post_dma_flush(dev))
|
||||
+ __dma_sync(dma_addr_to_page(dev, addr + offset),
|
||||
+ (addr + offset) & ~PAGE_MASK, size, dir);
|
||||
+ debug_dma_sync_single_range_for_cpu(dev, addr, offset, size, dir);
|
||||
+}
|
||||
+
|
||||
+static inline void dma_sync_single_range_for_device(struct device *dev,
|
||||
+ dma_addr_t addr,
|
||||
+ unsigned long offset,
|
||||
+ size_t size,
|
||||
+ enum dma_data_direction dir)
|
||||
+{
|
||||
+ const struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops)
|
||||
+ ops->sync_single_for_device(dev, addr + offset, size, dir);
|
||||
+ else if (!plat_device_is_coherent(dev))
|
||||
+ __dma_sync(dma_addr_to_page(dev, addr + offset),
|
||||
+ (addr + offset) & ~PAGE_MASK, size, dir);
|
||||
+ debug_dma_sync_single_range_for_device(dev, addr, offset, size, dir);
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
|
||||
+ int nelems, enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+ struct scatterlist *s;
|
||||
+ int i;
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops)
|
||||
+ ops->sync_sg_for_cpu(dev, sg, nelems, dir);
|
||||
+ else if (cpu_needs_post_dma_flush(dev)) {
|
||||
+ for_each_sg(sg, s, nelems, i)
|
||||
+ __dma_sync(sg_page(s), s->offset, s->length, dir);
|
||||
+ }
|
||||
+ debug_dma_sync_sg_for_cpu(dev, sg, nelems, dir);
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
|
||||
+ int nelems, enum dma_data_direction dir)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+ struct scatterlist *s;
|
||||
+ int i;
|
||||
+
|
||||
+ BUG_ON(!valid_dma_direction(dir));
|
||||
+ if (ops)
|
||||
+ ops->sync_sg_for_device(dev, sg, nelems, dir);
|
||||
+ else if (!plat_device_is_coherent(dev)) {
|
||||
+ for_each_sg(sg, s, nelems, i)
|
||||
+ __dma_sync(sg_page(s), s->offset, s->length, dir);
|
||||
+ }
|
||||
+ debug_dma_sync_sg_for_device(dev, sg, nelems, dir);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
|
||||
+#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
|
||||
+#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
|
||||
+#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
|
||||
+
|
||||
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
|
||||
+ void *cpu_addr, dma_addr_t dma_addr, size_t size);
|
||||
+
|
||||
+/**
|
||||
+ * dma_mmap_attrs - map a coherent DMA allocation into user space
|
||||
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
|
||||
+ * @vma: vm_area_struct describing requested user mapping
|
||||
+ * @cpu_addr: kernel CPU-view address returned from dma_alloc_attrs
|
||||
+ * @handle: device-view address returned from dma_alloc_attrs
|
||||
+ * @size: size of memory originally requested in dma_alloc_attrs
|
||||
+ * @attrs: attributes of mapping properties requested in dma_alloc_attrs
|
||||
+ *
|
||||
+ * Map a coherent DMA buffer previously allocated by dma_alloc_attrs
|
||||
+ * into user space. The coherent DMA buffer must not be freed by the
|
||||
+ * driver until the user space mapping has been released.
|
||||
+ */
|
||||
+static inline int
|
||||
+dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
|
||||
+ dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+ BUG_ON(!ops);
|
||||
+ if (ops && ops->mmap)
|
||||
+ return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
|
||||
+ return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
|
||||
+}
|
||||
+
|
||||
+#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL)
|
||||
+
|
||||
+static inline int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
|
||||
+ void *cpu_addr, dma_addr_t dma_addr, size_t size)
|
||||
+{
|
||||
+ DEFINE_DMA_ATTRS(attrs);
|
||||
+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
|
||||
+ return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
|
||||
+ void *cpu_addr, dma_addr_t dma_addr, size_t size);
|
||||
+
|
||||
+static inline int
|
||||
+dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
|
||||
+ dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
|
||||
+{
|
||||
+ struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
+ BUG_ON(!ops);
|
||||
+ if (ops && ops->get_sgtable)
|
||||
+ return ops->get_sgtable(dev, sgt, cpu_addr, dma_addr, size,
|
||||
+ attrs);
|
||||
+ return dma_common_get_sgtable(dev, sgt, cpu_addr, dma_addr, size);
|
||||
+}
|
||||
+
|
||||
+#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, NULL)
|
||||
+
|
||||
|
||||
static inline int dma_supported(struct device *dev, u64 mask)
|
||||
{
|
||||
struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
- return ops->dma_supported(dev, mask);
|
||||
+ if (ops)
|
||||
+ return ops->dma_supported(dev, mask);
|
||||
+ return plat_dma_supported(dev, mask);
|
||||
}
|
||||
|
||||
static inline int dma_mapping_error(struct device *dev, u64 mask)
|
||||
@@ -43,7 +386,9 @@ static inline int dma_mapping_error(stru
|
||||
struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
|
||||
debug_dma_mapping_error(dev, mask);
|
||||
- return ops->mapping_error(dev, mask);
|
||||
+ if (ops)
|
||||
+ return ops->mapping_error(dev, mask);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -69,7 +414,11 @@ static inline void *dma_alloc_attrs(stru
|
||||
void *ret;
|
||||
struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
|
||||
- ret = ops->alloc(dev, size, dma_handle, gfp, attrs);
|
||||
+ if (ops)
|
||||
+ ret = ops->alloc(dev, size, dma_handle, gfp, attrs);
|
||||
+ else
|
||||
+ ret = mips_dma_alloc_coherent(dev, size, dma_handle, gfp,
|
||||
+ attrs);
|
||||
|
||||
debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
|
||||
|
||||
@@ -84,7 +433,10 @@ static inline void dma_free_attrs(struct
|
||||
{
|
||||
struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
|
||||
- ops->free(dev, size, vaddr, dma_handle, attrs);
|
||||
+ if (ops)
|
||||
+ ops->free(dev, size, vaddr, dma_handle, attrs);
|
||||
+ else
|
||||
+ mips_dma_free_coherent(dev, size, vaddr, dma_handle, attrs);
|
||||
|
||||
debug_dma_free_coherent(dev, size, vaddr, dma_handle);
|
||||
}
|
||||
--- a/arch/mips/mm/dma-default.c
|
||||
+++ b/arch/mips/mm/dma-default.c
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#ifdef CONFIG_DMA_MAYBE_COHERENT
|
||||
int coherentio = 0; /* User defined DMA coherency from command line. */
|
||||
-EXPORT_SYMBOL_GPL(coherentio);
|
||||
+EXPORT_SYMBOL(coherentio);
|
||||
int hw_coherentio = 0; /* Actual hardware supported DMA coherency setting. */
|
||||
|
||||
static int __init setcoherentio(char *str)
|
||||
@@ -45,30 +45,6 @@ static int __init setnocoherentio(char *
|
||||
early_param("nocoherentio", setnocoherentio);
|
||||
#endif
|
||||
|
||||
-static inline struct page *dma_addr_to_page(struct device *dev,
|
||||
- dma_addr_t dma_addr)
|
||||
-{
|
||||
- return pfn_to_page(
|
||||
- plat_dma_addr_to_phys(dev, dma_addr) >> PAGE_SHIFT);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * The affected CPUs below in 'cpu_needs_post_dma_flush()' can
|
||||
- * speculatively fill random cachelines with stale data at any time,
|
||||
- * requiring an extra flush post-DMA.
|
||||
- *
|
||||
- * Warning on the terminology - Linux calls an uncached area coherent;
|
||||
- * MIPS terminology calls memory areas with hardware maintained coherency
|
||||
- * coherent.
|
||||
- */
|
||||
-static inline int cpu_needs_post_dma_flush(struct device *dev)
|
||||
-{
|
||||
- return !plat_device_is_coherent(dev) &&
|
||||
- (boot_cpu_type() == CPU_R10000 ||
|
||||
- boot_cpu_type() == CPU_R12000 ||
|
||||
- boot_cpu_type() == CPU_BMIPS5000);
|
||||
-}
|
||||
-
|
||||
static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
|
||||
{
|
||||
gfp_t dma_flag;
|
||||
@@ -124,8 +100,9 @@ void *dma_alloc_noncoherent(struct devic
|
||||
}
|
||||
EXPORT_SYMBOL(dma_alloc_noncoherent);
|
||||
|
||||
-static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
|
||||
- dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
|
||||
+void *mips_dma_alloc_coherent(struct device *dev, size_t size,
|
||||
+ dma_addr_t *dma_handle, gfp_t gfp,
|
||||
+ struct dma_attrs *attrs)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
@@ -149,6 +126,7 @@ static void *mips_dma_alloc_coherent(str
|
||||
|
||||
return ret;
|
||||
}
|
||||
+EXPORT_SYMBOL(mips_dma_alloc_coherent);
|
||||
|
||||
|
||||
void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
|
||||
@@ -159,8 +137,8 @@ void dma_free_noncoherent(struct device
|
||||
}
|
||||
EXPORT_SYMBOL(dma_free_noncoherent);
|
||||
|
||||
-static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
|
||||
- dma_addr_t dma_handle, struct dma_attrs *attrs)
|
||||
+void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
|
||||
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
|
||||
{
|
||||
unsigned long addr = (unsigned long) vaddr;
|
||||
int order = get_order(size);
|
||||
@@ -175,6 +153,7 @@ static void mips_dma_free_coherent(struc
|
||||
|
||||
free_pages(addr, get_order(size));
|
||||
}
|
||||
+EXPORT_SYMBOL(mips_dma_free_coherent);
|
||||
|
||||
static inline void __dma_sync_virtual(void *addr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
@@ -203,8 +182,8 @@ static inline void __dma_sync_virtual(vo
|
||||
* If highmem is not configured then the bulk of this loop gets
|
||||
* optimized out.
|
||||
*/
|
||||
-static inline void __dma_sync(struct page *page,
|
||||
- unsigned long offset, size_t size, enum dma_data_direction direction)
|
||||
+void __dma_sync(struct page *page, unsigned long offset, size_t size,
|
||||
+ enum dma_data_direction direction)
|
||||
{
|
||||
size_t left = size;
|
||||
|
||||
@@ -233,108 +212,7 @@ static inline void __dma_sync(struct pag
|
||||
left -= len;
|
||||
} while (left);
|
||||
}
|
||||
-
|
||||
-static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
|
||||
- size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
|
||||
-{
|
||||
- if (cpu_needs_post_dma_flush(dev))
|
||||
- __dma_sync(dma_addr_to_page(dev, dma_addr),
|
||||
- dma_addr & ~PAGE_MASK, size, direction);
|
||||
-
|
||||
- plat_unmap_dma_mem(dev, dma_addr, size, direction);
|
||||
-}
|
||||
-
|
||||
-static int mips_dma_map_sg(struct device *dev, struct scatterlist *sg,
|
||||
- int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- for (i = 0; i < nents; i++, sg++) {
|
||||
- if (!plat_device_is_coherent(dev))
|
||||
- __dma_sync(sg_page(sg), sg->offset, sg->length,
|
||||
- direction);
|
||||
-#ifdef CONFIG_NEED_SG_DMA_LENGTH
|
||||
- sg->dma_length = sg->length;
|
||||
-#endif
|
||||
- sg->dma_address = plat_map_dma_mem_page(dev, sg_page(sg)) +
|
||||
- sg->offset;
|
||||
- }
|
||||
-
|
||||
- return nents;
|
||||
-}
|
||||
-
|
||||
-static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page,
|
||||
- unsigned long offset, size_t size, enum dma_data_direction direction,
|
||||
- struct dma_attrs *attrs)
|
||||
-{
|
||||
- if (!plat_device_is_coherent(dev))
|
||||
- __dma_sync(page, offset, size, direction);
|
||||
-
|
||||
- return plat_map_dma_mem_page(dev, page) + offset;
|
||||
-}
|
||||
-
|
||||
-static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
|
||||
- int nhwentries, enum dma_data_direction direction,
|
||||
- struct dma_attrs *attrs)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- for (i = 0; i < nhwentries; i++, sg++) {
|
||||
- if (!plat_device_is_coherent(dev) &&
|
||||
- direction != DMA_TO_DEVICE)
|
||||
- __dma_sync(sg_page(sg), sg->offset, sg->length,
|
||||
- direction);
|
||||
- plat_unmap_dma_mem(dev, sg->dma_address, sg->length, direction);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void mips_dma_sync_single_for_cpu(struct device *dev,
|
||||
- dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
|
||||
-{
|
||||
- if (cpu_needs_post_dma_flush(dev))
|
||||
- __dma_sync(dma_addr_to_page(dev, dma_handle),
|
||||
- dma_handle & ~PAGE_MASK, size, direction);
|
||||
-}
|
||||
-
|
||||
-static void mips_dma_sync_single_for_device(struct device *dev,
|
||||
- dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
|
||||
-{
|
||||
- if (!plat_device_is_coherent(dev))
|
||||
- __dma_sync(dma_addr_to_page(dev, dma_handle),
|
||||
- dma_handle & ~PAGE_MASK, size, direction);
|
||||
-}
|
||||
-
|
||||
-static void mips_dma_sync_sg_for_cpu(struct device *dev,
|
||||
- struct scatterlist *sg, int nelems, enum dma_data_direction direction)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- if (cpu_needs_post_dma_flush(dev))
|
||||
- for (i = 0; i < nelems; i++, sg++)
|
||||
- __dma_sync(sg_page(sg), sg->offset, sg->length,
|
||||
- direction);
|
||||
-}
|
||||
-
|
||||
-static void mips_dma_sync_sg_for_device(struct device *dev,
|
||||
- struct scatterlist *sg, int nelems, enum dma_data_direction direction)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- if (!plat_device_is_coherent(dev))
|
||||
- for (i = 0; i < nelems; i++, sg++)
|
||||
- __dma_sync(sg_page(sg), sg->offset, sg->length,
|
||||
- direction);
|
||||
-}
|
||||
-
|
||||
-int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int mips_dma_supported(struct device *dev, u64 mask)
|
||||
-{
|
||||
- return plat_dma_supported(dev, mask);
|
||||
-}
|
||||
+EXPORT_SYMBOL(__dma_sync);
|
||||
|
||||
void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
@@ -347,23 +225,10 @@ void dma_cache_sync(struct device *dev,
|
||||
|
||||
EXPORT_SYMBOL(dma_cache_sync);
|
||||
|
||||
-static struct dma_map_ops mips_default_dma_map_ops = {
|
||||
- .alloc = mips_dma_alloc_coherent,
|
||||
- .free = mips_dma_free_coherent,
|
||||
- .map_page = mips_dma_map_page,
|
||||
- .unmap_page = mips_dma_unmap_page,
|
||||
- .map_sg = mips_dma_map_sg,
|
||||
- .unmap_sg = mips_dma_unmap_sg,
|
||||
- .sync_single_for_cpu = mips_dma_sync_single_for_cpu,
|
||||
- .sync_single_for_device = mips_dma_sync_single_for_device,
|
||||
- .sync_sg_for_cpu = mips_dma_sync_sg_for_cpu,
|
||||
- .sync_sg_for_device = mips_dma_sync_sg_for_device,
|
||||
- .mapping_error = mips_dma_mapping_error,
|
||||
- .dma_supported = mips_dma_supported
|
||||
-};
|
||||
-
|
||||
-struct dma_map_ops *mips_dma_map_ops = &mips_default_dma_map_ops;
|
||||
+#ifdef CONFIG_SYS_HAS_DMA_OPS
|
||||
+struct dma_map_ops *mips_dma_map_ops = NULL;
|
||||
EXPORT_SYMBOL(mips_dma_map_ops);
|
||||
+#endif
|
||||
|
||||
#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
--- a/scripts/setlocalversion
|
||||
+++ b/scripts/setlocalversion
|
||||
@@ -165,7 +165,7 @@ else
|
||||
# annotated or signed tagged state (as git describe only
|
||||
# looks at signed or annotated tags - git tag -a/-s) and
|
||||
# LOCALVERSION= is not specified
|
||||
- if test "${LOCALVERSION+set}" != "set"; then
|
||||
+ if test "${CONFIG_LOCALVERSION+set}" != "set"; then
|
||||
scm=$(scm_version --short)
|
||||
res="$res${scm:++}"
|
||||
fi
|
|
@ -1,14 +0,0 @@
|
|||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -580,9 +580,9 @@ endif # $(dot-config)
|
||||
all: vmlinux
|
||||
|
||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||
-KBUILD_CFLAGS += -Os $(call cc-disable-warning,maybe-uninitialized,)
|
||||
+KBUILD_CFLAGS += -Os $(EXTRA_OPTIMIZATION) $(call cc-disable-warning,maybe-uninitialized,)
|
||||
else
|
||||
-KBUILD_CFLAGS += -O2
|
||||
+KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch $(EXTRA_OPTIMIZATION)
|
||||
endif
|
||||
|
||||
include $(srctree)/arch/$(SRCARCH)/Makefile
|
|
@ -1,11 +0,0 @@
|
|||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -388,7 +388,7 @@ KBUILD_CFLAGS_KERNEL :=
|
||||
KBUILD_AFLAGS := -D__ASSEMBLY__
|
||||
KBUILD_AFLAGS_MODULE := -DMODULE
|
||||
KBUILD_CFLAGS_MODULE := -DMODULE
|
||||
-KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
|
||||
+KBUILD_LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds $(if $(CONFIG_PROFILING),,-s)
|
||||
|
||||
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
|
||||
KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
|
|
@ -1,108 +0,0 @@
|
|||
--- a/scripts/kallsyms.c
|
||||
+++ b/scripts/kallsyms.c
|
||||
@@ -54,6 +54,7 @@ static struct text_range text_ranges[] =
|
||||
static struct sym_entry *table;
|
||||
static unsigned int table_size, table_cnt;
|
||||
static int all_symbols = 0;
|
||||
+static int uncompressed = 0;
|
||||
static char symbol_prefix_char = '\0';
|
||||
static unsigned long long kernel_start_addr = 0;
|
||||
|
||||
@@ -373,6 +374,9 @@ static void write_src(void)
|
||||
|
||||
free(markers);
|
||||
|
||||
+ if (uncompressed)
|
||||
+ return;
|
||||
+
|
||||
output_label("kallsyms_token_table");
|
||||
off = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
@@ -431,6 +435,9 @@ static void *find_token(unsigned char *s
|
||||
{
|
||||
int i;
|
||||
|
||||
+ if (uncompressed)
|
||||
+ return NULL;
|
||||
+
|
||||
for (i = 0; i < len - 1; i++) {
|
||||
if (str[i] == token[0] && str[i+1] == token[1])
|
||||
return &str[i];
|
||||
@@ -503,6 +510,9 @@ static void optimize_result(void)
|
||||
{
|
||||
int i, best;
|
||||
|
||||
+ if (uncompressed)
|
||||
+ return;
|
||||
+
|
||||
/* using the '\0' symbol last allows compress_symbols to use standard
|
||||
* fast string functions */
|
||||
for (i = 255; i >= 0; i--) {
|
||||
@@ -662,7 +672,9 @@ int main(int argc, char **argv)
|
||||
} else if (strncmp(argv[i], "--page-offset=", 14) == 0) {
|
||||
const char *p = &argv[i][14];
|
||||
kernel_start_addr = strtoull(p, NULL, 16);
|
||||
- } else
|
||||
+ } else if (strcmp(argv[i], "--uncompressed") == 0)
|
||||
+ uncompressed = 1;
|
||||
+ else
|
||||
usage();
|
||||
}
|
||||
} else if (argc != 1)
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -1270,6 +1270,17 @@ config SYSCTL_ARCH_UNALIGN_ALLOW
|
||||
the unaligned access emulation.
|
||||
see arch/parisc/kernel/unaligned.c for reference
|
||||
|
||||
+config KALLSYMS_UNCOMPRESSED
|
||||
+ bool "Keep kallsyms uncompressed"
|
||||
+ depends on KALLSYMS
|
||||
+ help
|
||||
+ Normally kallsyms contains compressed symbols (using a token table),
|
||||
+ reducing the uncompressed kernel image size. Keeping the symbol table
|
||||
+ uncompressed significantly improves the size of this part in compressed
|
||||
+ kernel images.
|
||||
+
|
||||
+ Say N unless you need compressed kernel images to be small.
|
||||
+
|
||||
config HAVE_PCSPKR_PLATFORM
|
||||
bool
|
||||
|
||||
--- a/scripts/link-vmlinux.sh
|
||||
+++ b/scripts/link-vmlinux.sh
|
||||
@@ -86,6 +86,10 @@ kallsyms()
|
||||
kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
|
||||
fi
|
||||
|
||||
+ if [ -n "${CONFIG_KALLSYMS_UNCOMPRESSED}" ]; then
|
||||
+ kallsymopt="${kallsymopt} --uncompressed"
|
||||
+ fi
|
||||
+
|
||||
local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \
|
||||
${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
|
||||
|
||||
--- a/kernel/kallsyms.c
|
||||
+++ b/kernel/kallsyms.c
|
||||
@@ -108,6 +108,11 @@ static unsigned int kallsyms_expand_symb
|
||||
* For every byte on the compressed symbol data, copy the table
|
||||
* entry for that byte.
|
||||
*/
|
||||
+#ifdef CONFIG_KALLSYMS_UNCOMPRESSED
|
||||
+ memcpy(result, data + 1, len - 1);
|
||||
+ result += len - 1;
|
||||
+ len = 0;
|
||||
+#endif
|
||||
while (len) {
|
||||
tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
|
||||
data++;
|
||||
@@ -140,6 +145,9 @@ tail:
|
||||
*/
|
||||
static char kallsyms_get_symbol_type(unsigned int off)
|
||||
{
|
||||
+#ifdef CONFIG_KALLSYMS_UNCOMPRESSED
|
||||
+ return kallsyms_names[off + 1];
|
||||
+#endif
|
||||
/*
|
||||
* Get just the first code, look it up in the token table,
|
||||
* and return the first char from this token.
|
|
@ -1,200 +0,0 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
Subject: [PATCH] build: add a hack for removing non-essential module info
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
---
|
||||
--- a/include/linux/module.h
|
||||
+++ b/include/linux/module.h
|
||||
@@ -82,7 +82,7 @@ void sort_extable(struct exception_table
|
||||
void sort_main_extable(void);
|
||||
void trim_init_extable(struct module *m);
|
||||
|
||||
-#ifdef MODULE
|
||||
+#if defined(MODULE) && !defined(CONFIG_MODULE_STRIPPED)
|
||||
#define MODULE_GENERIC_TABLE(gtype, name) \
|
||||
extern const struct gtype##_id __mod_##gtype##_table \
|
||||
__attribute__ ((unused, alias(__stringify(name))))
|
||||
@@ -93,9 +93,10 @@ extern const struct gtype##_id __mod_##g
|
||||
|
||||
/* Generic info of form tag = "info" */
|
||||
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
|
||||
+#define MODULE_INFO_STRIP(tag, info) __MODULE_INFO_STRIP(tag, tag, info)
|
||||
|
||||
/* For userspace: you can also call me... */
|
||||
-#define MODULE_ALIAS(_alias) MODULE_INFO(alias, _alias)
|
||||
+#define MODULE_ALIAS(_alias) MODULE_INFO_STRIP(alias, _alias)
|
||||
|
||||
/* Soft module dependencies. See man modprobe.d for details.
|
||||
* Example: MODULE_SOFTDEP("pre: module-foo module-bar post: module-baz")
|
||||
@@ -136,10 +137,10 @@ extern const struct gtype##_id __mod_##g
|
||||
* Author(s), use "Name <email>" or just "Name", for multiple
|
||||
* authors use multiple MODULE_AUTHOR() statements/lines.
|
||||
*/
|
||||
-#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
|
||||
+#define MODULE_AUTHOR(_author) MODULE_INFO_STRIP(author, _author)
|
||||
|
||||
/* What your module does. */
|
||||
-#define MODULE_DESCRIPTION(_description) MODULE_INFO(description, _description)
|
||||
+#define MODULE_DESCRIPTION(_description) MODULE_INFO_STRIP(description, _description)
|
||||
|
||||
#define MODULE_DEVICE_TABLE(type, name) \
|
||||
MODULE_GENERIC_TABLE(type##_device, name)
|
||||
@@ -162,7 +163,9 @@ extern const struct gtype##_id __mod_##g
|
||||
*/
|
||||
|
||||
#if defined(MODULE) || !defined(CONFIG_SYSFS)
|
||||
-#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
|
||||
+#define MODULE_VERSION(_version) MODULE_INFO_STRIP(version, _version)
|
||||
+#elif defined(CONFIG_MODULE_STRIPPED)
|
||||
+#define MODULE_VERSION(_version) __MODULE_INFO_DISABLED(version)
|
||||
#else
|
||||
#define MODULE_VERSION(_version) \
|
||||
static struct module_version_attribute ___modver_attr = { \
|
||||
@@ -184,7 +187,7 @@ extern const struct gtype##_id __mod_##g
|
||||
/* Optional firmware file (or files) needed by the module
|
||||
* format is simply firmware file name. Multiple firmware
|
||||
* files require multiple MODULE_FIRMWARE() specifiers */
|
||||
-#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware)
|
||||
+#define MODULE_FIRMWARE(_firmware) MODULE_INFO_STRIP(firmware, _firmware)
|
||||
|
||||
/* Given an address, look for it in the exception tables */
|
||||
const struct exception_table_entry *search_exception_tables(unsigned long add);
|
||||
--- a/include/linux/moduleparam.h
|
||||
+++ b/include/linux/moduleparam.h
|
||||
@@ -16,6 +16,16 @@
|
||||
/* Chosen so that structs with an unsigned long line up. */
|
||||
#define MAX_PARAM_PREFIX_LEN (64 - sizeof(unsigned long))
|
||||
|
||||
+/* This struct is here for syntactic coherency, it is not used */
|
||||
+#define __MODULE_INFO_DISABLED(name) \
|
||||
+ struct __UNIQUE_ID(name) {}
|
||||
+
|
||||
+#ifdef CONFIG_MODULE_STRIPPED
|
||||
+#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO_DISABLED(name)
|
||||
+#else
|
||||
+#define __MODULE_INFO_STRIP(tag, name, info) __MODULE_INFO(tag, name, info)
|
||||
+#endif
|
||||
+
|
||||
#ifdef MODULE
|
||||
#define __MODULE_INFO(tag, name, info) \
|
||||
static const char __UNIQUE_ID(name)[] \
|
||||
@@ -23,8 +33,7 @@ static const char __UNIQUE_ID(name)[]
|
||||
= __stringify(tag) "=" info
|
||||
#else /* !MODULE */
|
||||
/* This struct is here for syntactic coherency, it is not used */
|
||||
-#define __MODULE_INFO(tag, name, info) \
|
||||
- struct __UNIQUE_ID(name) {}
|
||||
+#define __MODULE_INFO(tag, name, info) __MODULE_INFO_DISABLED(name)
|
||||
#endif
|
||||
#define __MODULE_PARM_TYPE(name, _type) \
|
||||
__MODULE_INFO(parmtype, name##type, #name ":" _type)
|
||||
@@ -32,7 +41,7 @@ static const char __UNIQUE_ID(name)[]
|
||||
/* One for each parameter, describing how to use it. Some files do
|
||||
multiple of these per line, so can't just use MODULE_INFO. */
|
||||
#define MODULE_PARM_DESC(_parm, desc) \
|
||||
- __MODULE_INFO(parm, _parm, #_parm ":" desc)
|
||||
+ __MODULE_INFO_STRIP(parm, _parm, #_parm ":" desc)
|
||||
|
||||
struct kernel_param;
|
||||
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -1831,6 +1831,13 @@ config MODULE_SIG_HASH
|
||||
default "sha384" if MODULE_SIG_SHA384
|
||||
default "sha512" if MODULE_SIG_SHA512
|
||||
|
||||
+config MODULE_STRIPPED
|
||||
+ bool "Reduce module size"
|
||||
+ depends on MODULES
|
||||
+ help
|
||||
+ Remove module parameter descriptions, author info, version, aliases,
|
||||
+ device tables, etc.
|
||||
+
|
||||
endif # MODULES
|
||||
|
||||
config INIT_ALL_POSSIBLE
|
||||
--- a/kernel/module.c
|
||||
+++ b/kernel/module.c
|
||||
@@ -2663,6 +2663,7 @@ static struct module *setup_load_info(st
|
||||
|
||||
static int check_modinfo(struct module *mod, struct load_info *info, int flags)
|
||||
{
|
||||
+#ifndef CONFIG_MODULE_STRIPPED
|
||||
const char *modmagic = get_modinfo(info, "vermagic");
|
||||
int err;
|
||||
|
||||
@@ -2688,6 +2689,7 @@ static int check_modinfo(struct module *
|
||||
pr_warn("%s: module is from the staging directory, the quality "
|
||||
"is unknown, you have been warned.\n", mod->name);
|
||||
}
|
||||
+#endif
|
||||
|
||||
/* Set up license info based on the info section */
|
||||
set_license(mod, get_modinfo(info, "license"));
|
||||
--- a/scripts/mod/modpost.c
|
||||
+++ b/scripts/mod/modpost.c
|
||||
@@ -1734,7 +1734,9 @@ static void read_symbols(char *modname)
|
||||
symname = info.strtab + sym->st_name;
|
||||
|
||||
handle_modversions(mod, &info, sym, symname);
|
||||
+#ifndef CONFIG_MODULE_STRIPPED
|
||||
handle_moddevtable(mod, &info, sym, symname);
|
||||
+#endif
|
||||
}
|
||||
if (!is_vmlinux(modname) ||
|
||||
(is_vmlinux(modname) && vmlinux_section_warnings))
|
||||
@@ -1878,7 +1880,9 @@ static void add_header(struct buffer *b,
|
||||
buf_printf(b, "#include <linux/vermagic.h>\n");
|
||||
buf_printf(b, "#include <linux/compiler.h>\n");
|
||||
buf_printf(b, "\n");
|
||||
+#ifndef CONFIG_MODULE_STRIPPED
|
||||
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
|
||||
+#endif
|
||||
buf_printf(b, "\n");
|
||||
buf_printf(b, "__visible struct module __this_module\n");
|
||||
buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
|
||||
@@ -1895,16 +1899,20 @@ static void add_header(struct buffer *b,
|
||||
|
||||
static void add_intree_flag(struct buffer *b, int is_intree)
|
||||
{
|
||||
+#ifndef CONFIG_MODULE_STRIPPED
|
||||
if (is_intree)
|
||||
buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n");
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void add_staging_flag(struct buffer *b, const char *name)
|
||||
{
|
||||
+#ifndef CONFIG_MODULE_STRIPPED
|
||||
static const char *staging_dir = "drivers/staging";
|
||||
|
||||
if (strncmp(staging_dir, name, strlen(staging_dir)) == 0)
|
||||
buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n");
|
||||
+#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1997,11 +2005,13 @@ static void add_depends(struct buffer *b
|
||||
|
||||
static void add_srcversion(struct buffer *b, struct module *mod)
|
||||
{
|
||||
+#ifndef CONFIG_MODULE_STRIPPED
|
||||
if (mod->srcversion[0]) {
|
||||
buf_printf(b, "\n");
|
||||
buf_printf(b, "MODULE_INFO(srcversion, \"%s\");\n",
|
||||
mod->srcversion);
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void write_if_changed(struct buffer *b, const char *fname)
|
||||
@@ -2230,7 +2240,9 @@ int main(int argc, char **argv)
|
||||
add_staging_flag(&buf, mod->name);
|
||||
err |= add_versions(&buf, mod);
|
||||
add_depends(&buf, mod, modules);
|
||||
+#ifndef CONFIG_MODULE_STRIPPED
|
||||
add_moddevtable(&buf, mod);
|
||||
+#endif
|
||||
add_srcversion(&buf, mod);
|
||||
|
||||
sprintf(fname, "%s.mod.c", mod->name);
|
File diff suppressed because it is too large
Load diff
|
@ -1,51 +0,0 @@
|
|||
--- a/tools/include/tools/be_byteshift.h
|
||||
+++ b/tools/include/tools/be_byteshift.h
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef _TOOLS_BE_BYTESHIFT_H
|
||||
#define _TOOLS_BE_BYTESHIFT_H
|
||||
|
||||
+#ifndef __linux__
|
||||
+#include "linux_types.h"
|
||||
+#endif
|
||||
+
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint16_t __get_unaligned_be16(const uint8_t *p)
|
||||
--- a/tools/include/tools/le_byteshift.h
|
||||
+++ b/tools/include/tools/le_byteshift.h
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef _TOOLS_LE_BYTESHIFT_H
|
||||
#define _TOOLS_LE_BYTESHIFT_H
|
||||
|
||||
+#ifndef __linux__
|
||||
+#include "linux_types.h"
|
||||
+#endif
|
||||
+
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint16_t __get_unaligned_le16(const uint8_t *p)
|
||||
--- /dev/null
|
||||
+++ b/tools/include/tools/linux_types.h
|
||||
@@ -0,0 +1,22 @@
|
||||
+#ifndef __LINUX_TYPES_H
|
||||
+#define __LINUX_TYPES_H
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+typedef uint8_t __u8;
|
||||
+typedef uint8_t __be8;
|
||||
+typedef uint8_t __le8;
|
||||
+
|
||||
+typedef uint16_t __u16;
|
||||
+typedef uint16_t __be16;
|
||||
+typedef uint16_t __le16;
|
||||
+
|
||||
+typedef uint32_t __u32;
|
||||
+typedef uint32_t __be32;
|
||||
+typedef uint32_t __le32;
|
||||
+
|
||||
+typedef uint64_t __u64;
|
||||
+typedef uint64_t __be64;
|
||||
+typedef uint64_t __le64;
|
||||
+
|
||||
+#endif
|
|
@ -1,540 +0,0 @@
|
|||
From: Felix Fietkau <nbd@openwrt.org>
|
||||
|
||||
use -ffunction-sections, -fdata-sections and --gc-sections --sort-section=name
|
||||
|
||||
In combination with kernel symbol export stripping this significantly reduces
|
||||
the kernel image size. Used on both ARM and MIPS architectures.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
|
||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
---
|
||||
|
||||
--- a/arch/mips/Makefile
|
||||
+++ b/arch/mips/Makefile
|
||||
@@ -89,10 +89,14 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
|
||||
#
|
||||
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
|
||||
cflags-y += -msoft-float
|
||||
-LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
|
||||
+LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections --sort-section=name
|
||||
KBUILD_AFLAGS_MODULE += -mlong-calls
|
||||
KBUILD_CFLAGS_MODULE += -mlong-calls
|
||||
|
||||
+ifndef CONFIG_FUNCTION_TRACER
|
||||
+KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
|
||||
+endif
|
||||
+
|
||||
cflags-y += -ffreestanding
|
||||
|
||||
#
|
||||
--- a/arch/mips/kernel/vmlinux.lds.S
|
||||
+++ b/arch/mips/kernel/vmlinux.lds.S
|
||||
@@ -67,7 +67,7 @@ SECTIONS
|
||||
/* Exception table for data bus errors */
|
||||
__dbe_table : {
|
||||
__start___dbe_table = .;
|
||||
- *(__dbe_table)
|
||||
+ KEEP(*(__dbe_table))
|
||||
__stop___dbe_table = .;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
.mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) {
|
||||
__mips_machines_start = .;
|
||||
- *(.mips.machines.init)
|
||||
+ KEEP(*(.mips.machines.init))
|
||||
__mips_machines_end = .;
|
||||
}
|
||||
|
||||
--- a/include/asm-generic/vmlinux.lds.h
|
||||
+++ b/include/asm-generic/vmlinux.lds.h
|
||||
@@ -87,7 +87,7 @@
|
||||
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
||||
#define MCOUNT_REC() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__start_mcount_loc) = .; \
|
||||
- *(__mcount_loc) \
|
||||
+ KEEP(*(__mcount_loc)) \
|
||||
VMLINUX_SYMBOL(__stop_mcount_loc) = .;
|
||||
#else
|
||||
#define MCOUNT_REC()
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
#ifdef CONFIG_TRACE_BRANCH_PROFILING
|
||||
#define LIKELY_PROFILE() VMLINUX_SYMBOL(__start_annotated_branch_profile) = .; \
|
||||
- *(_ftrace_annotated_branch) \
|
||||
+ KEEP(*(_ftrace_annotated_branch)) \
|
||||
VMLINUX_SYMBOL(__stop_annotated_branch_profile) = .;
|
||||
#else
|
||||
#define LIKELY_PROFILE()
|
||||
@@ -103,7 +103,7 @@
|
||||
|
||||
#ifdef CONFIG_PROFILE_ALL_BRANCHES
|
||||
#define BRANCH_PROFILE() VMLINUX_SYMBOL(__start_branch_profile) = .; \
|
||||
- *(_ftrace_branch) \
|
||||
+ KEEP(*(_ftrace_branch)) \
|
||||
VMLINUX_SYMBOL(__stop_branch_profile) = .;
|
||||
#else
|
||||
#define BRANCH_PROFILE()
|
||||
@@ -112,7 +112,7 @@
|
||||
#ifdef CONFIG_EVENT_TRACING
|
||||
#define FTRACE_EVENTS() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__start_ftrace_events) = .; \
|
||||
- *(_ftrace_events) \
|
||||
+ KEEP(*(_ftrace_events)) \
|
||||
VMLINUX_SYMBOL(__stop_ftrace_events) = .;
|
||||
#else
|
||||
#define FTRACE_EVENTS()
|
||||
@@ -120,7 +120,7 @@
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
#define TRACE_PRINTKS() VMLINUX_SYMBOL(__start___trace_bprintk_fmt) = .; \
|
||||
- *(__trace_printk_fmt) /* Trace_printk fmt' pointer */ \
|
||||
+ KEEP(*(__trace_printk_fmt)) /* Trace_printk fmt' pointer */ \
|
||||
VMLINUX_SYMBOL(__stop___trace_bprintk_fmt) = .;
|
||||
#define TRACEPOINT_STR() VMLINUX_SYMBOL(__start___tracepoint_str) = .; \
|
||||
*(__tracepoint_str) /* Trace_printk fmt' pointer */ \
|
||||
@@ -133,7 +133,7 @@
|
||||
#ifdef CONFIG_FTRACE_SYSCALLS
|
||||
#define TRACE_SYSCALLS() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__start_syscalls_metadata) = .; \
|
||||
- *(__syscalls_metadata) \
|
||||
+ KEEP(*(__syscalls_metadata)) \
|
||||
VMLINUX_SYMBOL(__stop_syscalls_metadata) = .;
|
||||
#else
|
||||
#define TRACE_SYSCALLS()
|
||||
@@ -142,8 +142,8 @@
|
||||
#ifdef CONFIG_CLKSRC_OF
|
||||
#define CLKSRC_OF_TABLES() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__clksrc_of_table) = .; \
|
||||
- *(__clksrc_of_table) \
|
||||
- *(__clksrc_of_table_end)
|
||||
+ KEEP(*(__clksrc_of_table)) \
|
||||
+ KEEP(*(__clksrc_of_table_end))
|
||||
#else
|
||||
#define CLKSRC_OF_TABLES()
|
||||
#endif
|
||||
@@ -152,8 +152,8 @@
|
||||
#define IRQCHIP_OF_MATCH_TABLE() \
|
||||
. = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__irqchip_begin) = .; \
|
||||
- *(__irqchip_of_table) \
|
||||
- *(__irqchip_of_end)
|
||||
+ KEEP(*(__irqchip_of_table)) \
|
||||
+ KEEP(*(__irqchip_of_end))
|
||||
#else
|
||||
#define IRQCHIP_OF_MATCH_TABLE()
|
||||
#endif
|
||||
@@ -161,8 +161,8 @@
|
||||
#ifdef CONFIG_COMMON_CLK
|
||||
#define CLK_OF_TABLES() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__clk_of_table) = .; \
|
||||
- *(__clk_of_table) \
|
||||
- *(__clk_of_table_end)
|
||||
+ KEEP(*(__clk_of_table)) \
|
||||
+ KEEP(*(__clk_of_table_end))
|
||||
#else
|
||||
#define CLK_OF_TABLES()
|
||||
#endif
|
||||
@@ -170,7 +170,7 @@
|
||||
#define KERNEL_DTB() \
|
||||
STRUCT_ALIGN(); \
|
||||
VMLINUX_SYMBOL(__dtb_start) = .; \
|
||||
- *(.dtb.init.rodata) \
|
||||
+ KEEP(*(.dtb.init.rodata)) \
|
||||
VMLINUX_SYMBOL(__dtb_end) = .;
|
||||
|
||||
/* .data section */
|
||||
@@ -186,16 +186,17 @@
|
||||
/* implement dynamic printk debug */ \
|
||||
. = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__start___jump_table) = .; \
|
||||
- *(__jump_table) \
|
||||
+ KEEP(*(__jump_table)) \
|
||||
VMLINUX_SYMBOL(__stop___jump_table) = .; \
|
||||
. = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__start___verbose) = .; \
|
||||
- *(__verbose) \
|
||||
+ KEEP(*(__verbose)) \
|
||||
VMLINUX_SYMBOL(__stop___verbose) = .; \
|
||||
LIKELY_PROFILE() \
|
||||
BRANCH_PROFILE() \
|
||||
TRACE_PRINTKS() \
|
||||
- TRACEPOINT_STR()
|
||||
+ TRACEPOINT_STR() \
|
||||
+ *(.data.[a-zA-Z_]*)
|
||||
|
||||
/*
|
||||
* Data section helpers
|
||||
@@ -249,32 +250,32 @@
|
||||
/* PCI quirks */ \
|
||||
.pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
|
||||
- *(.pci_fixup_early) \
|
||||
+ KEEP(*(.pci_fixup_early)) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \
|
||||
VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \
|
||||
- *(.pci_fixup_header) \
|
||||
+ KEEP(*(.pci_fixup_header)) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \
|
||||
VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \
|
||||
- *(.pci_fixup_final) \
|
||||
+ KEEP(*(.pci_fixup_final)) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \
|
||||
VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \
|
||||
- *(.pci_fixup_enable) \
|
||||
+ KEEP(*(.pci_fixup_enable)) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
|
||||
VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \
|
||||
- *(.pci_fixup_resume) \
|
||||
+ KEEP(*(.pci_fixup_resume)) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \
|
||||
VMLINUX_SYMBOL(__start_pci_fixups_resume_early) = .; \
|
||||
- *(.pci_fixup_resume_early) \
|
||||
+ KEEP(*(.pci_fixup_resume_early)) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_resume_early) = .; \
|
||||
VMLINUX_SYMBOL(__start_pci_fixups_suspend) = .; \
|
||||
- *(.pci_fixup_suspend) \
|
||||
+ KEEP(*(.pci_fixup_suspend)) \
|
||||
VMLINUX_SYMBOL(__end_pci_fixups_suspend) = .; \
|
||||
} \
|
||||
\
|
||||
/* Built-in firmware blobs */ \
|
||||
.builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start_builtin_fw) = .; \
|
||||
- *(.builtin_fw) \
|
||||
+ KEEP(*(.builtin_fw)) \
|
||||
VMLINUX_SYMBOL(__end_builtin_fw) = .; \
|
||||
} \
|
||||
\
|
||||
@@ -283,49 +284,49 @@
|
||||
/* Kernel symbol table: Normal symbols */ \
|
||||
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab) = .; \
|
||||
- *(SORT(___ksymtab+*)) \
|
||||
+ KEEP(*(SORT(___ksymtab+*))) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-only symbols */ \
|
||||
__ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
|
||||
- *(SORT(___ksymtab_gpl+*)) \
|
||||
+ KEEP(*(SORT(___ksymtab_gpl+*))) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: Normal unused symbols */ \
|
||||
__ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \
|
||||
- *(SORT(___ksymtab_unused+*)) \
|
||||
+ KEEP(*(SORT(___ksymtab_unused+*))) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-only unused symbols */ \
|
||||
__ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \
|
||||
- *(SORT(___ksymtab_unused_gpl+*)) \
|
||||
+ KEEP(*(SORT(___ksymtab_unused_gpl+*))) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-future-only symbols */ \
|
||||
__ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
|
||||
- *(SORT(___ksymtab_gpl_future+*)) \
|
||||
+ KEEP(*(SORT(___ksymtab_gpl_future+*))) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: Normal symbols */ \
|
||||
__kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___kcrctab) = .; \
|
||||
- *(SORT(___kcrctab+*)) \
|
||||
+ KEEP(*(SORT(___kcrctab+*))) \
|
||||
VMLINUX_SYMBOL(__stop___kcrctab) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-only symbols */ \
|
||||
__kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \
|
||||
- *(SORT(___kcrctab_gpl+*)) \
|
||||
+ KEEP(*(SORT(___kcrctab_gpl+*))) \
|
||||
VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
@@ -339,14 +340,14 @@
|
||||
/* Kernel symbol table: GPL-only unused symbols */ \
|
||||
__kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \
|
||||
- *(SORT(___kcrctab_unused_gpl+*)) \
|
||||
+ KEEP(*(SORT(___kcrctab_unused_gpl+*))) \
|
||||
VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-future-only symbols */ \
|
||||
__kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \
|
||||
- *(SORT(___kcrctab_gpl_future+*)) \
|
||||
+ KEEP(*(SORT(___kcrctab_gpl_future+*))) \
|
||||
VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \
|
||||
} \
|
||||
\
|
||||
@@ -365,14 +366,14 @@
|
||||
/* Built-in module parameters. */ \
|
||||
__param : AT(ADDR(__param) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___param) = .; \
|
||||
- *(__param) \
|
||||
+ KEEP(*(__param)) \
|
||||
VMLINUX_SYMBOL(__stop___param) = .; \
|
||||
} \
|
||||
\
|
||||
/* Built-in module versions. */ \
|
||||
__modver : AT(ADDR(__modver) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___modver) = .; \
|
||||
- *(__modver) \
|
||||
+ KEEP(*(__modver)) \
|
||||
VMLINUX_SYMBOL(__stop___modver) = .; \
|
||||
. = ALIGN((align)); \
|
||||
VMLINUX_SYMBOL(__end_rodata) = .; \
|
||||
@@ -428,7 +429,7 @@
|
||||
#define ENTRY_TEXT \
|
||||
ALIGN_FUNCTION(); \
|
||||
VMLINUX_SYMBOL(__entry_text_start) = .; \
|
||||
- *(.entry.text) \
|
||||
+ KEEP(*(.entry.text)) \
|
||||
VMLINUX_SYMBOL(__entry_text_end) = .;
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
@@ -456,7 +457,7 @@
|
||||
. = ALIGN(align); \
|
||||
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ex_table) = .; \
|
||||
- *(__ex_table) \
|
||||
+ KEEP(*(__ex_table)) \
|
||||
VMLINUX_SYMBOL(__stop___ex_table) = .; \
|
||||
}
|
||||
|
||||
@@ -472,8 +473,8 @@
|
||||
#ifdef CONFIG_CONSTRUCTORS
|
||||
#define KERNEL_CTORS() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__ctors_start) = .; \
|
||||
- *(.ctors) \
|
||||
- *(.init_array) \
|
||||
+ KEEP(*(.ctors)) \
|
||||
+ KEEP(*(.init_array)) \
|
||||
VMLINUX_SYMBOL(__ctors_end) = .;
|
||||
#else
|
||||
#define KERNEL_CTORS()
|
||||
@@ -517,7 +518,7 @@
|
||||
#define SBSS(sbss_align) \
|
||||
. = ALIGN(sbss_align); \
|
||||
.sbss : AT(ADDR(.sbss) - LOAD_OFFSET) { \
|
||||
- *(.sbss) \
|
||||
+ *(.sbss .sbss.*) \
|
||||
*(.scommon) \
|
||||
}
|
||||
|
||||
@@ -535,7 +536,7 @@
|
||||
BSS_FIRST_SECTIONS \
|
||||
*(.bss..page_aligned) \
|
||||
*(.dynbss) \
|
||||
- *(.bss) \
|
||||
+ *(.bss .bss.*) \
|
||||
*(COMMON) \
|
||||
}
|
||||
|
||||
@@ -584,7 +585,7 @@
|
||||
. = ALIGN(8); \
|
||||
__bug_table : AT(ADDR(__bug_table) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___bug_table) = .; \
|
||||
- *(__bug_table) \
|
||||
+ KEEP(*(__bug_table)) \
|
||||
VMLINUX_SYMBOL(__stop___bug_table) = .; \
|
||||
}
|
||||
#else
|
||||
@@ -596,7 +597,7 @@
|
||||
. = ALIGN(4); \
|
||||
.tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__tracedata_start) = .; \
|
||||
- *(.tracedata) \
|
||||
+ KEEP(*(.tracedata)) \
|
||||
VMLINUX_SYMBOL(__tracedata_end) = .; \
|
||||
}
|
||||
#else
|
||||
@@ -613,17 +614,17 @@
|
||||
#define INIT_SETUP(initsetup_align) \
|
||||
. = ALIGN(initsetup_align); \
|
||||
VMLINUX_SYMBOL(__setup_start) = .; \
|
||||
- *(.init.setup) \
|
||||
+ KEEP(*(.init.setup)) \
|
||||
VMLINUX_SYMBOL(__setup_end) = .;
|
||||
|
||||
#define INIT_CALLS_LEVEL(level) \
|
||||
VMLINUX_SYMBOL(__initcall##level##_start) = .; \
|
||||
- *(.initcall##level##.init) \
|
||||
- *(.initcall##level##s.init) \
|
||||
+ KEEP(*(.initcall##level##.init)) \
|
||||
+ KEEP(*(.initcall##level##s.init)) \
|
||||
|
||||
#define INIT_CALLS \
|
||||
VMLINUX_SYMBOL(__initcall_start) = .; \
|
||||
- *(.initcallearly.init) \
|
||||
+ KEEP(*(.initcallearly.init)) \
|
||||
INIT_CALLS_LEVEL(0) \
|
||||
INIT_CALLS_LEVEL(1) \
|
||||
INIT_CALLS_LEVEL(2) \
|
||||
@@ -637,21 +638,21 @@
|
||||
|
||||
#define CON_INITCALL \
|
||||
VMLINUX_SYMBOL(__con_initcall_start) = .; \
|
||||
- *(.con_initcall.init) \
|
||||
+ KEEP(*(.con_initcall.init)) \
|
||||
VMLINUX_SYMBOL(__con_initcall_end) = .;
|
||||
|
||||
#define SECURITY_INITCALL \
|
||||
VMLINUX_SYMBOL(__security_initcall_start) = .; \
|
||||
- *(.security_initcall.init) \
|
||||
+ KEEP(*(.security_initcall.init)) \
|
||||
VMLINUX_SYMBOL(__security_initcall_end) = .;
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
#define INIT_RAM_FS \
|
||||
. = ALIGN(4); \
|
||||
VMLINUX_SYMBOL(__initramfs_start) = .; \
|
||||
- *(.init.ramfs) \
|
||||
+ KEEP(*(.init.ramfs)) \
|
||||
. = ALIGN(8); \
|
||||
- *(.init.ramfs.info)
|
||||
+ KEEP(*(.init.ramfs.info))
|
||||
#else
|
||||
#define INIT_RAM_FS
|
||||
#endif
|
||||
--- a/arch/arm/Makefile
|
||||
+++ b/arch/arm/Makefile
|
||||
@@ -18,11 +18,16 @@ ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
|
||||
LDFLAGS_vmlinux += --be8
|
||||
LDFLAGS_MODULE += --be8
|
||||
endif
|
||||
+LDFLAGS_vmlinux += --gc-sections --sort-section=name
|
||||
|
||||
OBJCOPYFLAGS :=-O binary -R .comment -S
|
||||
GZFLAGS :=-9
|
||||
#KBUILD_CFLAGS +=-pipe
|
||||
|
||||
+ifndef CONFIG_FUNCTION_TRACER
|
||||
+KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
|
||||
+endif
|
||||
+
|
||||
# Never generate .eh_frame
|
||||
KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)
|
||||
|
||||
--- a/arch/arm/kernel/vmlinux.lds.S
|
||||
+++ b/arch/arm/kernel/vmlinux.lds.S
|
||||
@@ -12,13 +12,13 @@
|
||||
#define PROC_INFO \
|
||||
. = ALIGN(4); \
|
||||
VMLINUX_SYMBOL(__proc_info_begin) = .; \
|
||||
- *(.proc.info.init) \
|
||||
+ KEEP(*(.proc.info.init)) \
|
||||
VMLINUX_SYMBOL(__proc_info_end) = .;
|
||||
|
||||
#define IDMAP_TEXT \
|
||||
ALIGN_FUNCTION(); \
|
||||
VMLINUX_SYMBOL(__idmap_text_start) = .; \
|
||||
- *(.idmap.text) \
|
||||
+ KEEP(*(.idmap.text)) \
|
||||
VMLINUX_SYMBOL(__idmap_text_end) = .; \
|
||||
. = ALIGN(32); \
|
||||
VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \
|
||||
@@ -93,7 +93,7 @@ SECTIONS
|
||||
.text : { /* Real text segment */
|
||||
_stext = .; /* Text and read-only data */
|
||||
__exception_text_start = .;
|
||||
- *(.exception.text)
|
||||
+ KEEP(*(.exception.text))
|
||||
__exception_text_end = .;
|
||||
IRQENTRY_TEXT
|
||||
TEXT_TEXT
|
||||
@@ -118,7 +118,7 @@ SECTIONS
|
||||
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
|
||||
__start___ex_table = .;
|
||||
#ifdef CONFIG_MMU
|
||||
- *(__ex_table)
|
||||
+ KEEP(*(__ex_table))
|
||||
#endif
|
||||
__stop___ex_table = .;
|
||||
}
|
||||
@@ -130,12 +130,12 @@ SECTIONS
|
||||
. = ALIGN(8);
|
||||
.ARM.unwind_idx : {
|
||||
__start_unwind_idx = .;
|
||||
- *(.ARM.exidx*)
|
||||
+ KEEP(*(.ARM.exidx*))
|
||||
__stop_unwind_idx = .;
|
||||
}
|
||||
.ARM.unwind_tab : {
|
||||
__start_unwind_tab = .;
|
||||
- *(.ARM.extab*)
|
||||
+ KEEP(*(.ARM.extab*))
|
||||
__stop_unwind_tab = .;
|
||||
}
|
||||
#endif
|
||||
@@ -154,14 +154,14 @@ SECTIONS
|
||||
*/
|
||||
__vectors_start = .;
|
||||
.vectors 0 : AT(__vectors_start) {
|
||||
- *(.vectors)
|
||||
+ KEEP(*(.vectors))
|
||||
}
|
||||
. = __vectors_start + SIZEOF(.vectors);
|
||||
__vectors_end = .;
|
||||
|
||||
__stubs_start = .;
|
||||
.stubs 0x1000 : AT(__stubs_start) {
|
||||
- *(.stubs)
|
||||
+ KEEP(*(.stubs))
|
||||
}
|
||||
. = __stubs_start + SIZEOF(.stubs);
|
||||
__stubs_end = .;
|
||||
@@ -175,24 +175,24 @@ SECTIONS
|
||||
}
|
||||
.init.arch.info : {
|
||||
__arch_info_begin = .;
|
||||
- *(.arch.info.init)
|
||||
+ KEEP(*(.arch.info.init))
|
||||
__arch_info_end = .;
|
||||
}
|
||||
.init.tagtable : {
|
||||
__tagtable_begin = .;
|
||||
- *(.taglist.init)
|
||||
+ KEEP(*(.taglist.init))
|
||||
__tagtable_end = .;
|
||||
}
|
||||
#ifdef CONFIG_SMP_ON_UP
|
||||
.init.smpalt : {
|
||||
__smpalt_begin = .;
|
||||
- *(.alt.smp.init)
|
||||
+ KEEP(*(.alt.smp.init))
|
||||
__smpalt_end = .;
|
||||
}
|
||||
#endif
|
||||
.init.pv_table : {
|
||||
__pv_table_begin = .;
|
||||
- *(.pv_table)
|
||||
+ KEEP(*(.pv_table))
|
||||
__pv_table_end = .;
|
||||
}
|
||||
.init.data : {
|
||||
--- a/arch/arm/boot/compressed/Makefile
|
||||
+++ b/arch/arm/boot/compressed/Makefile
|
||||
@@ -120,6 +120,7 @@ ifeq ($(CONFIG_FUNCTION_TRACER),y)
|
||||
ORIG_CFLAGS := $(KBUILD_CFLAGS)
|
||||
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
|
||||
endif
|
||||
+KBUILD_CFLAGS_KERNEL := $(patsubst -f%-sections,,$(KBUILD_CFLAGS_KERNEL))
|
||||
|
||||
ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj)
|
||||
asflags-y := -DZIMAGE
|
|
@ -1,88 +0,0 @@
|
|||
--- a/include/asm-generic/vmlinux.lds.h
|
||||
+++ b/include/asm-generic/vmlinux.lds.h
|
||||
@@ -52,6 +52,16 @@
|
||||
#define LOAD_OFFSET 0
|
||||
#endif
|
||||
|
||||
+#ifndef SYMTAB_KEEP
|
||||
+#define SYMTAB_KEEP KEEP(*(SORT(___ksymtab+*)))
|
||||
+#define SYMTAB_KEEP_GPL KEEP(*(SORT(___ksymtab_gpl+*)))
|
||||
+#endif
|
||||
+
|
||||
+#ifndef SYMTAB_DISCARD
|
||||
+#define SYMTAB_DISCARD
|
||||
+#define SYMTAB_DISCARD_GPL
|
||||
+#endif
|
||||
+
|
||||
#include <linux/export.h>
|
||||
|
||||
/* Align . to a 8 byte boundary equals to maximum function alignment. */
|
||||
@@ -284,14 +294,14 @@
|
||||
/* Kernel symbol table: Normal symbols */ \
|
||||
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab) = .; \
|
||||
- KEEP(*(SORT(___ksymtab+*))) \
|
||||
+ SYMTAB_KEEP \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-only symbols */ \
|
||||
__ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \
|
||||
- KEEP(*(SORT(___ksymtab_gpl+*))) \
|
||||
+ SYMTAB_KEEP_GPL \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
@@ -353,7 +363,7 @@
|
||||
\
|
||||
/* Kernel symbol table: strings */ \
|
||||
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
|
||||
- *(__ksymtab_strings) \
|
||||
+ *(__ksymtab_strings+*) \
|
||||
} \
|
||||
\
|
||||
/* __*init sections */ \
|
||||
@@ -671,6 +681,8 @@
|
||||
EXIT_TEXT \
|
||||
EXIT_DATA \
|
||||
EXIT_CALL \
|
||||
+ SYMTAB_DISCARD \
|
||||
+ SYMTAB_DISCARD_GPL \
|
||||
*(.discard) \
|
||||
*(.discard.*) \
|
||||
}
|
||||
--- a/scripts/Makefile.build
|
||||
+++ b/scripts/Makefile.build
|
||||
@@ -349,7 +349,7 @@ targets += $(extra-y) $(MAKECMDGOALS) $(
|
||||
# Linker scripts preprocessor (.lds.S -> .lds)
|
||||
# ---------------------------------------------------------------------------
|
||||
quiet_cmd_cpp_lds_S = LDS $@
|
||||
- cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \
|
||||
+ cmd_cpp_lds_S = $(CPP) $(EXTRA_LDSFLAGS) $(cpp_flags) -P -C -U$(ARCH) \
|
||||
-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
|
||||
|
||||
$(obj)/%.lds: $(src)/%.lds.S FORCE
|
||||
--- a/include/linux/export.h
|
||||
+++ b/include/linux/export.h
|
||||
@@ -52,12 +52,19 @@ extern struct module __this_module;
|
||||
#define __CRC_SYMBOL(sym, sec)
|
||||
#endif
|
||||
|
||||
+#ifdef MODULE
|
||||
+#define __EXPORT_SUFFIX(sym)
|
||||
+#else
|
||||
+#define __EXPORT_SUFFIX(sym) "+" #sym
|
||||
+#endif
|
||||
+
|
||||
/* For every exported symbol, place a struct in the __ksymtab section */
|
||||
#define __EXPORT_SYMBOL(sym, sec) \
|
||||
extern typeof(sym) sym; \
|
||||
__CRC_SYMBOL(sym, sec) \
|
||||
static const char __kstrtab_##sym[] \
|
||||
- __attribute__((section("__ksymtab_strings"), aligned(1))) \
|
||||
+ __attribute__((section("__ksymtab_strings" \
|
||||
+ __EXPORT_SUFFIX(sym)), aligned(1))) \
|
||||
= VMLINUX_SYMBOL_STR(sym); \
|
||||
extern const struct kernel_symbol __ksymtab_##sym; \
|
||||
__visible const struct kernel_symbol __ksymtab_##sym \
|
|
@ -1,58 +0,0 @@
|
|||
--- a/scripts/Makefile.lib
|
||||
+++ b/scripts/Makefile.lib
|
||||
@@ -304,7 +304,7 @@ cmd_bzip2 = (cat $(filter-out FORCE,$^)
|
||||
|
||||
quiet_cmd_lzma = LZMA $@
|
||||
cmd_lzma = (cat $(filter-out FORCE,$^) | \
|
||||
- lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
|
||||
+ lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
|
||||
(rm -f $@ ; false)
|
||||
|
||||
quiet_cmd_lzo = LZO $@
|
||||
--- a/scripts/gen_initramfs_list.sh
|
||||
+++ b/scripts/gen_initramfs_list.sh
|
||||
@@ -226,7 +226,7 @@ cpio_list=
|
||||
output="/dev/stdout"
|
||||
output_file=""
|
||||
is_cpio_compressed=
|
||||
-compr="gzip -n -9 -f"
|
||||
+compr="gzip -n -9 -f -"
|
||||
|
||||
arg="$1"
|
||||
case "$arg" in
|
||||
@@ -242,13 +242,13 @@ case "$arg" in
|
||||
output=${cpio_list}
|
||||
echo "$output_file" | grep -q "\.gz$" \
|
||||
&& [ -x "`which gzip 2> /dev/null`" ] \
|
||||
- && compr="gzip -n -9 -f"
|
||||
+ && compr="gzip -n -9 -f -"
|
||||
echo "$output_file" | grep -q "\.bz2$" \
|
||||
&& [ -x "`which bzip2 2> /dev/null`" ] \
|
||||
- && compr="bzip2 -9 -f"
|
||||
+ && compr="bzip2 -9 -f -"
|
||||
echo "$output_file" | grep -q "\.lzma$" \
|
||||
&& [ -x "`which lzma 2> /dev/null`" ] \
|
||||
- && compr="lzma -9 -f"
|
||||
+ && compr="lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so"
|
||||
echo "$output_file" | grep -q "\.xz$" \
|
||||
&& [ -x "`which xz 2> /dev/null`" ] \
|
||||
&& compr="xz --check=crc32 --lzma2=dict=1MiB"
|
||||
@@ -315,7 +315,7 @@ if [ ! -z ${output_file} ]; then
|
||||
if [ "${is_cpio_compressed}" = "compressed" ]; then
|
||||
cat ${cpio_tfile} > ${output_file}
|
||||
else
|
||||
- (cat ${cpio_tfile} | ${compr} - > ${output_file}) \
|
||||
+ (cat ${cpio_tfile} | ${compr} > ${output_file}) \
|
||||
|| (rm -f ${output_file} ; false)
|
||||
fi
|
||||
[ -z ${cpio_file} ] && rm ${cpio_tfile}
|
||||
--- a/lib/decompress.c
|
||||
+++ b/lib/decompress.c
|
||||
@@ -47,6 +47,7 @@ static const struct compress_format comp
|
||||
{ {037, 0236}, "gzip", gunzip },
|
||||
{ {0x42, 0x5a}, "bzip2", bunzip2 },
|
||||
{ {0x5d, 0x00}, "lzma", unlzma },
|
||||
+ { {0x6d, 0x00}, "lzma-openwrt", unlzma },
|
||||
{ {0xfd, 0x37}, "xz", unxz },
|
||||
{ {0x89, 0x4c}, "lzo", unlzo },
|
||||
{ {0x02, 0x21}, "lz4", unlz4 },
|
|
@ -1,18 +0,0 @@
|
|||
--- a/net/netfilter/Kconfig
|
||||
+++ b/net/netfilter/Kconfig
|
||||
@@ -207,7 +207,6 @@ config NF_CONNTRACK_FTP
|
||||
|
||||
config NF_CONNTRACK_H323
|
||||
tristate "H.323 protocol support"
|
||||
- depends on (IPV6 || IPV6=n)
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
H.323 is a VoIP signalling protocol from ITU-T. As one of the most
|
||||
@@ -883,7 +882,6 @@ config NETFILTER_XT_TARGET_SECMARK
|
||||
|
||||
config NETFILTER_XT_TARGET_TCPMSS
|
||||
tristate '"TCPMSS" target support'
|
||||
- depends on (IPV6 || IPV6=n)
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
---help---
|
||||
This option adds a `TCPMSS' target, which allows you to alter the
|
|
@ -1,18 +0,0 @@
|
|||
--- a/sound/core/Kconfig
|
||||
+++ b/sound/core/Kconfig
|
||||
@@ -10,13 +10,13 @@ config SND_DMAENGINE_PCM
|
||||
tristate
|
||||
|
||||
config SND_HWDEP
|
||||
- tristate
|
||||
+ tristate "Sound hardware support"
|
||||
|
||||
config SND_RAWMIDI
|
||||
tristate
|
||||
|
||||
config SND_COMPRESS_OFFLOAD
|
||||
- tristate
|
||||
+ tristate "Compression offloading support"
|
||||
|
||||
# To be effective this also requires INPUT - users should say:
|
||||
# select SND_JACK if INPUT=y || INPUT=SND
|
|
@ -1,10 +0,0 @@
|
|||
--- a/drivers/crypto/Kconfig
|
||||
+++ b/drivers/crypto/Kconfig
|
||||
@@ -164,6 +164,7 @@ config CRYPTO_DEV_MV_CESA
|
||||
depends on PLAT_ORION
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_AES
|
||||
+ select CRYPTO_HASH2
|
||||
select CRYPTO_BLKCIPHER2
|
||||
select CRYPTO_HASH
|
||||
help
|
|
@ -1,29 +0,0 @@
|
|||
--- a/drivers/ssb/Kconfig
|
||||
+++ b/drivers/ssb/Kconfig
|
||||
@@ -29,6 +29,7 @@ config SSB_SPROM
|
||||
config SSB_BLOCKIO
|
||||
bool
|
||||
depends on SSB
|
||||
+ default y
|
||||
|
||||
config SSB_PCIHOST_POSSIBLE
|
||||
bool
|
||||
@@ -49,7 +50,7 @@ config SSB_PCIHOST
|
||||
config SSB_B43_PCI_BRIDGE
|
||||
bool
|
||||
depends on SSB_PCIHOST
|
||||
- default n
|
||||
+ default y
|
||||
|
||||
config SSB_PCMCIAHOST_POSSIBLE
|
||||
bool
|
||||
--- a/drivers/bcma/Kconfig
|
||||
+++ b/drivers/bcma/Kconfig
|
||||
@@ -17,6 +17,7 @@ config BCMA
|
||||
config BCMA_BLOCKIO
|
||||
bool
|
||||
depends on BCMA
|
||||
+ default y
|
||||
|
||||
config BCMA_HOST_PCI_POSSIBLE
|
||||
bool
|
|
@ -1,23 +0,0 @@
|
|||
--- a/lib/Kconfig
|
||||
+++ b/lib/Kconfig
|
||||
@@ -308,16 +308,16 @@ config BCH_CONST_T
|
||||
# Textsearch support is select'ed if needed
|
||||
#
|
||||
config TEXTSEARCH
|
||||
- boolean
|
||||
+ boolean "Textsearch support"
|
||||
|
||||
config TEXTSEARCH_KMP
|
||||
- tristate
|
||||
+ tristate "Textsearch KMP"
|
||||
|
||||
config TEXTSEARCH_BM
|
||||
- tristate
|
||||
+ tristate "Textsearch BM"
|
||||
|
||||
config TEXTSEARCH_FSM
|
||||
- tristate
|
||||
+ tristate "Textsearch FSM"
|
||||
|
||||
config BTREE
|
||||
boolean
|
|
@ -1,31 +0,0 @@
|
|||
--- a/net/wireless/Kconfig
|
||||
+++ b/net/wireless/Kconfig
|
||||
@@ -140,7 +140,7 @@ config CFG80211_WEXT
|
||||
extensions with cfg80211-based drivers.
|
||||
|
||||
config LIB80211
|
||||
- tristate
|
||||
+ tristate "LIB80211"
|
||||
default n
|
||||
help
|
||||
This options enables a library of common routines used
|
||||
@@ -149,13 +149,16 @@ config LIB80211
|
||||
Drivers should select this themselves if needed.
|
||||
|
||||
config LIB80211_CRYPT_WEP
|
||||
- tristate
|
||||
+ tristate "LIB80211_CRYPT_WEP"
|
||||
+ select LIB80211
|
||||
|
||||
config LIB80211_CRYPT_CCMP
|
||||
- tristate
|
||||
+ tristate "LIB80211_CRYPT_CCMP"
|
||||
+ select LIB80211
|
||||
|
||||
config LIB80211_CRYPT_TKIP
|
||||
- tristate
|
||||
+ tristate "LIB80211_CRYPT_TKIP"
|
||||
+ select LIB80211
|
||||
|
||||
config LIB80211_DEBUG
|
||||
bool "lib80211 debugging messages"
|
|
@ -1,47 +0,0 @@
|
|||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -31,7 +31,7 @@ config CRYPTO_FIPS
|
||||
this is.
|
||||
|
||||
config CRYPTO_ALGAPI
|
||||
- tristate
|
||||
+ tristate "ALGAPI"
|
||||
select CRYPTO_ALGAPI2
|
||||
help
|
||||
This option provides the API for cryptographic algorithms.
|
||||
@@ -40,7 +40,7 @@ config CRYPTO_ALGAPI2
|
||||
tristate
|
||||
|
||||
config CRYPTO_AEAD
|
||||
- tristate
|
||||
+ tristate "AEAD"
|
||||
select CRYPTO_AEAD2
|
||||
select CRYPTO_ALGAPI
|
||||
|
||||
@@ -49,7 +49,7 @@ config CRYPTO_AEAD2
|
||||
select CRYPTO_ALGAPI2
|
||||
|
||||
config CRYPTO_BLKCIPHER
|
||||
- tristate
|
||||
+ tristate "BLKCIPHER"
|
||||
select CRYPTO_BLKCIPHER2
|
||||
select CRYPTO_ALGAPI
|
||||
|
||||
@@ -60,7 +60,7 @@ config CRYPTO_BLKCIPHER2
|
||||
select CRYPTO_WORKQUEUE
|
||||
|
||||
config CRYPTO_HASH
|
||||
- tristate
|
||||
+ tristate "HASH"
|
||||
select CRYPTO_HASH2
|
||||
select CRYPTO_ALGAPI
|
||||
|
||||
@@ -69,7 +69,7 @@ config CRYPTO_HASH2
|
||||
select CRYPTO_ALGAPI2
|
||||
|
||||
config CRYPTO_RNG
|
||||
- tristate
|
||||
+ tristate "RNG"
|
||||
select CRYPTO_RNG2
|
||||
select CRYPTO_ALGAPI
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
--- a/net/wireless/Kconfig
|
||||
+++ b/net/wireless/Kconfig
|
||||
@@ -1,5 +1,5 @@
|
||||
config WIRELESS_EXT
|
||||
- bool
|
||||
+ bool "Wireless extensions"
|
||||
|
||||
config WEXT_CORE
|
||||
def_bool y
|
||||
@@ -11,10 +11,10 @@ config WEXT_PROC
|
||||
depends on WEXT_CORE
|
||||
|
||||
config WEXT_SPY
|
||||
- bool
|
||||
+ bool "WEXT_SPY"
|
||||
|
||||
config WEXT_PRIV
|
||||
- bool
|
||||
+ bool "WEXT_PRIV"
|
||||
|
||||
config CFG80211
|
||||
tristate "cfg80211 - wireless configuration API"
|
|
@ -1,11 +0,0 @@
|
|||
--- a/net/netfilter/Kconfig
|
||||
+++ b/net/netfilter/Kconfig
|
||||
@@ -2,7 +2,7 @@ menu "Core Netfilter Configuration"
|
||||
depends on NET && INET && NETFILTER
|
||||
|
||||
config NETFILTER_NETLINK
|
||||
- tristate
|
||||
+ tristate "Netfilter NFNETLINK interface"
|
||||
|
||||
config NETFILTER_NETLINK_ACCT
|
||||
tristate "Netfilter NFACCT over NFNETLINK interface"
|
|
@ -1,76 +0,0 @@
|
|||
--- a/drivers/base/regmap/Kconfig
|
||||
+++ b/drivers/base/regmap/Kconfig
|
||||
@@ -3,23 +3,28 @@
|
||||
# subsystems should select the appropriate symbols.
|
||||
|
||||
config REGMAP
|
||||
- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_MMIO || REGMAP_IRQ)
|
||||
select LZO_COMPRESS
|
||||
select LZO_DECOMPRESS
|
||||
select IRQ_DOMAIN if REGMAP_IRQ
|
||||
- bool
|
||||
+ tristate "Regmap"
|
||||
|
||||
config REGMAP_I2C
|
||||
- tristate
|
||||
+ select REGMAP
|
||||
+ tristate "Regmap I2C"
|
||||
|
||||
config REGMAP_SPI
|
||||
- tristate
|
||||
+ select REGMAP
|
||||
+ depends on SPI_MASTER
|
||||
+ tristate "Regmap SPI"
|
||||
|
||||
config REGMAP_SPMI
|
||||
+ select REGMAP
|
||||
tristate
|
||||
|
||||
config REGMAP_MMIO
|
||||
+ select REGMAP
|
||||
tristate
|
||||
|
||||
config REGMAP_IRQ
|
||||
+ select REGMAP
|
||||
bool
|
||||
--- a/include/linux/regmap.h
|
||||
+++ b/include/linux/regmap.h
|
||||
@@ -49,7 +49,7 @@ struct reg_default {
|
||||
unsigned int def;
|
||||
};
|
||||
|
||||
-#ifdef CONFIG_REGMAP
|
||||
+#if IS_ENABLED(CONFIG_REGMAP)
|
||||
|
||||
enum regmap_endian {
|
||||
/* Unspecified -> 0 -> Backwards compatible default */
|
||||
--- a/drivers/base/regmap/Makefile
|
||||
+++ b/drivers/base/regmap/Makefile
|
||||
@@ -1,6 +1,8 @@
|
||||
-obj-$(CONFIG_REGMAP) += regmap.o regcache.o
|
||||
-obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o
|
||||
-obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
|
||||
+regmap-core-objs = regmap.o regcache.o regcache-rbtree.o regcache-lzo.o regcache-flat.o
|
||||
+ifdef CONFIG_DEBUG_FS
|
||||
+regmap-core-objs += regmap-debugfs.o
|
||||
+endif
|
||||
+obj-$(CONFIG_REGMAP) += regmap-core.o
|
||||
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
|
||||
obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
|
||||
obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o
|
||||
--- a/drivers/base/regmap/regmap.c
|
||||
+++ b/drivers/base/regmap/regmap.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/rbtree.h>
|
||||
@@ -2252,3 +2253,5 @@ static int __init regmap_initcall(void)
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(regmap_initcall);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
|
@ -1,37 +0,0 @@
|
|||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -95,10 +95,10 @@ config CRYPTO_MANAGER
|
||||
|
||||
config CRYPTO_MANAGER2
|
||||
def_tristate CRYPTO_MANAGER || (CRYPTO_MANAGER!=n && CRYPTO_ALGAPI=y)
|
||||
- select CRYPTO_AEAD2
|
||||
- select CRYPTO_HASH2
|
||||
- select CRYPTO_BLKCIPHER2
|
||||
- select CRYPTO_PCOMP2
|
||||
+ select CRYPTO_AEAD2 if !CRYPTO_MANAGER_DISABLE_TESTS
|
||||
+ select CRYPTO_HASH2 if !CRYPTO_MANAGER_DISABLE_TESTS
|
||||
+ select CRYPTO_BLKCIPHER2 if !CRYPTO_MANAGER_DISABLE_TESTS
|
||||
+ select CRYPTO_PCOMP2 if !CRYPTO_MANAGER_DISABLE_TESTS
|
||||
|
||||
config CRYPTO_USER
|
||||
tristate "Userspace cryptographic algorithm configuration"
|
||||
--- a/crypto/algboss.c
|
||||
+++ b/crypto/algboss.c
|
||||
@@ -248,6 +248,9 @@ static int cryptomgr_schedule_test(struc
|
||||
type = alg->cra_flags;
|
||||
|
||||
/* This piece of crap needs to disappear into per-type test hooks. */
|
||||
+#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
|
||||
+ type |= CRYPTO_ALG_TESTED;
|
||||
+#else
|
||||
if ((!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
|
||||
CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
|
||||
((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
|
||||
@@ -256,6 +259,7 @@ static int cryptomgr_schedule_test(struc
|
||||
(!((type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) &&
|
||||
alg->cra_type == &crypto_nivaead_type && alg->cra_aead.ivsize))
|
||||
type |= CRYPTO_ALG_TESTED;
|
||||
+#endif
|
||||
|
||||
param->type = type;
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
--- a/lib/Kconfig
|
||||
+++ b/lib/Kconfig
|
||||
@@ -193,16 +193,16 @@ config RANDOM32_SELFTEST
|
||||
# compression support is select'ed if needed
|
||||
#
|
||||
config ZLIB_INFLATE
|
||||
- tristate
|
||||
+ tristate "ZLIB inflate support"
|
||||
|
||||
config ZLIB_DEFLATE
|
||||
- tristate
|
||||
+ tristate "ZLIB deflate support"
|
||||
|
||||
config LZO_COMPRESS
|
||||
- tristate
|
||||
+ tristate "LZO compress support"
|
||||
|
||||
config LZO_DECOMPRESS
|
||||
- tristate
|
||||
+ tristate "LZO decompress support"
|
||||
|
||||
config LZ4_COMPRESS
|
||||
tristate
|
|
@ -1,39 +0,0 @@
|
|||
From: Mark Miller <mark@mirell.org>
|
||||
|
||||
This exposes the CONFIG_BOOT_RAW symbol in Kconfig. This is needed on
|
||||
certain Broadcom chipsets running CFE in order to load the kernel.
|
||||
|
||||
Signed-off-by: Mark Miller <mark@mirell.org>
|
||||
Acked-by: Rob Landley <rob@landley.net>
|
||||
---
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -853,9 +853,6 @@ config FW_ARC
|
||||
config ARCH_MAY_HAVE_PC_FDC
|
||||
bool
|
||||
|
||||
-config BOOT_RAW
|
||||
- bool
|
||||
-
|
||||
config CEVT_BCM1480
|
||||
bool
|
||||
|
||||
@@ -2384,6 +2381,18 @@ config USE_OF
|
||||
select OF_EARLY_FLATTREE
|
||||
select IRQ_DOMAIN
|
||||
|
||||
+config BOOT_RAW
|
||||
+ bool "Enable the kernel to be executed from the load address"
|
||||
+ default n
|
||||
+ help
|
||||
+ Allow the kernel to be executed from the load address for
|
||||
+ bootloaders which cannot read the ELF format. This places
|
||||
+ a jump to start_kernel at the load address.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
+
|
||||
+
|
||||
endmenu
|
||||
|
||||
config LOCKDEP_SUPPORT
|
|
@ -1,28 +0,0 @@
|
|||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -947,6 +947,10 @@ config SYNC_R4K
|
||||
config MIPS_MACHINE
|
||||
def_bool n
|
||||
|
||||
+config IMAGE_CMDLINE_HACK
|
||||
+ bool "OpenWrt specific image command line hack"
|
||||
+ default n
|
||||
+
|
||||
config NO_IOPORT
|
||||
def_bool n
|
||||
|
||||
--- a/arch/mips/kernel/head.S
|
||||
+++ b/arch/mips/kernel/head.S
|
||||
@@ -101,6 +101,12 @@ FEXPORT(__kernel_entry)
|
||||
j kernel_entry
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_IMAGE_CMDLINE_HACK
|
||||
+ .ascii "CMDLINE:"
|
||||
+EXPORT(__image_cmdline)
|
||||
+ .fill 0x400
|
||||
+#endif /* CONFIG_IMAGE_CMDLINE_HACK */
|
||||
+
|
||||
__REF
|
||||
|
||||
NESTED(kernel_entry, 16, sp) # kernel entry point
|
|
@ -1,11 +0,0 @@
|
|||
--- a/arch/mips/Makefile
|
||||
+++ b/arch/mips/Makefile
|
||||
@@ -87,7 +87,7 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
|
||||
# machines may also. Since BFD is incredibly buggy with respect to
|
||||
# crossformat linking we rely on the elf2ecoff tool for format conversion.
|
||||
#
|
||||
-cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
|
||||
+cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
|
||||
cflags-y += -msoft-float
|
||||
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections --sort-section=name
|
||||
KBUILD_AFLAGS_MODULE += -mlong-calls
|
|
@ -1,160 +0,0 @@
|
|||
MIPS: allow disabling the kernel FPU emulator
|
||||
|
||||
This patch allows turning off the in-kernel Algorithmics
|
||||
FPU emulator support, which allows one to save a couple of
|
||||
precious blocks on an embedded system.
|
||||
|
||||
Signed-off-by: Florian Fainelli <florian@openwrt.org>
|
||||
--
|
||||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -935,6 +935,17 @@ config I8259
|
||||
config MIPS_BONITO64
|
||||
bool
|
||||
|
||||
+config MIPS_FPU_EMU
|
||||
+ bool "Enable FPU emulation"
|
||||
+ default y
|
||||
+ help
|
||||
+ This option allows building a kernel with or without the Algorithmics
|
||||
+ FPU emulator enabled. Turning off this option results in a kernel which
|
||||
+ does not catch floating operations exceptions. Make sure that your toolchain
|
||||
+ is configured to enable software floating point emulation in that case.
|
||||
+
|
||||
+ If unsure say Y here.
|
||||
+
|
||||
config MIPS_MSC
|
||||
bool
|
||||
|
||||
--- a/arch/mips/math-emu/Makefile
|
||||
+++ b/arch/mips/math-emu/Makefile
|
||||
@@ -2,10 +2,12 @@
|
||||
# Makefile for the Linux/MIPS kernel FPU emulation.
|
||||
#
|
||||
|
||||
-obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
|
||||
+obj-y := kernel_linkage.o
|
||||
+
|
||||
+obj-$(CONFIG_MIPS_FPU_EMU) += ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
|
||||
ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
|
||||
dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
|
||||
dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
|
||||
sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
|
||||
sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
|
||||
- dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o
|
||||
+ dp_sqrt.o sp_sqrt.o dsemul.o cp1emu.o
|
||||
--- a/arch/mips/math-emu/kernel_linkage.c
|
||||
+++ b/arch/mips/math-emu/kernel_linkage.c
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#define SIGNALLING_NAN 0x7ff800007ff80000LL
|
||||
|
||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
||||
void fpu_emulator_init_fpu(void)
|
||||
{
|
||||
static int first = 1;
|
||||
@@ -115,3 +116,36 @@ int fpu_emulator_restore_context32(struc
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#else
|
||||
+
|
||||
+void fpu_emulator_init_fpu(void)
|
||||
+{
|
||||
+ printk(KERN_INFO "FPU emulator disabled, make sure your toolchain"
|
||||
+ "was compiled with software floating point support (soft-float)\n");
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+int fpu_emulator_save_context(struct sigcontext __user *sc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int fpu_emulator_restore_context(struct sigcontext __user *sc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_64BIT
|
||||
+int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif /* CONFIG_64BIT */
|
||||
+
|
||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
||||
--- a/arch/mips/include/asm/fpu_emulator.h
|
||||
+++ b/arch/mips/include/asm/fpu_emulator.h
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <asm/inst.h>
|
||||
#include <asm/local.h>
|
||||
|
||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
||||
+
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
struct mips_fpu_emulator_stats {
|
||||
@@ -60,6 +62,38 @@ extern int fpu_emulator_cop1Handler(stru
|
||||
int process_fpemu_return(int sig, void __user *fault_addr);
|
||||
int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
||||
unsigned long *contpc);
|
||||
+#else
|
||||
+static inline int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
|
||||
+ unsigned long cpc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int do_dsemulret(struct pt_regs *xcp)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int fpu_emulator_cop1Handler(struct pt_regs *xcp,
|
||||
+ struct mips_fpu_struct *ctx,
|
||||
+ int has_fpu,
|
||||
+ void *__user *fault_addr)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int process_fpemu_return(int sig, void __user *fault_addr)
|
||||
+{
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static inline int mm_isBranchInstr(struct pt_regs *regs,
|
||||
+ struct mm_decoded_insn dec_insn,
|
||||
+ unsigned long *contpc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
||||
|
||||
/*
|
||||
* Instruction inserted following the badinst to further tag the sequence
|
||||
--- a/arch/mips/kernel/traps.c
|
||||
+++ b/arch/mips/kernel/traps.c
|
||||
@@ -701,6 +701,7 @@ asmlinkage void do_ov(struct pt_regs *re
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
||||
int process_fpemu_return(int sig, void __user *fault_addr)
|
||||
{
|
||||
if (sig == SIGSEGV || sig == SIGBUS) {
|
||||
@@ -724,6 +725,7 @@ int process_fpemu_return(int sig, void _
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
||||
|
||||
/*
|
||||
* XXX Delayed fp exceptions when doing a lazy ctx switch XXX
|
|
@ -1,352 +0,0 @@
|
|||
--- a/arch/mips/Makefile
|
||||
+++ b/arch/mips/Makefile
|
||||
@@ -90,8 +90,13 @@ all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlin
|
||||
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -mno-branch-likely
|
||||
cflags-y += -msoft-float
|
||||
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --gc-sections --sort-section=name
|
||||
+ifdef CONFIG_64BIT
|
||||
KBUILD_AFLAGS_MODULE += -mlong-calls
|
||||
KBUILD_CFLAGS_MODULE += -mlong-calls
|
||||
+else
|
||||
+KBUILD_AFLAGS_MODULE += -mno-long-calls
|
||||
+KBUILD_CFLAGS_MODULE += -mno-long-calls
|
||||
+endif
|
||||
|
||||
ifndef CONFIG_FUNCTION_TRACER
|
||||
KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
|
||||
--- a/arch/mips/include/asm/module.h
|
||||
+++ b/arch/mips/include/asm/module.h
|
||||
@@ -11,6 +11,11 @@ struct mod_arch_specific {
|
||||
const struct exception_table_entry *dbe_start;
|
||||
const struct exception_table_entry *dbe_end;
|
||||
struct mips_hi16 *r_mips_hi16_list;
|
||||
+
|
||||
+ void *phys_plt_tbl;
|
||||
+ void *virt_plt_tbl;
|
||||
+ unsigned int phys_plt_offset;
|
||||
+ unsigned int virt_plt_offset;
|
||||
};
|
||||
|
||||
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
|
||||
--- a/arch/mips/kernel/module.c
|
||||
+++ b/arch/mips/kernel/module.c
|
||||
@@ -43,14 +43,222 @@ struct mips_hi16 {
|
||||
static LIST_HEAD(dbe_list);
|
||||
static DEFINE_SPINLOCK(dbe_lock);
|
||||
|
||||
-#ifdef MODULE_START
|
||||
+/*
|
||||
+ * Get the potential max trampolines size required of the init and
|
||||
+ * non-init sections. Only used if we cannot find enough contiguous
|
||||
+ * physically mapped memory to put the module into.
|
||||
+ */
|
||||
+static unsigned int
|
||||
+get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
|
||||
+ const char *secstrings, unsigned int symindex, bool is_init)
|
||||
+{
|
||||
+ unsigned long ret = 0;
|
||||
+ unsigned int i, j;
|
||||
+ Elf_Sym *syms;
|
||||
+
|
||||
+ /* Everything marked ALLOC (this includes the exported symbols) */
|
||||
+ for (i = 1; i < hdr->e_shnum; ++i) {
|
||||
+ unsigned int info = sechdrs[i].sh_info;
|
||||
+
|
||||
+ if (sechdrs[i].sh_type != SHT_REL
|
||||
+ && sechdrs[i].sh_type != SHT_RELA)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Not a valid relocation section? */
|
||||
+ if (info >= hdr->e_shnum)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Don't bother with non-allocated sections */
|
||||
+ if (!(sechdrs[info].sh_flags & SHF_ALLOC))
|
||||
+ continue;
|
||||
+
|
||||
+ /* If it's called *.init*, and we're not init, we're
|
||||
+ not interested */
|
||||
+ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
|
||||
+ != is_init)
|
||||
+ continue;
|
||||
+
|
||||
+ syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
|
||||
+ if (sechdrs[i].sh_type == SHT_REL) {
|
||||
+ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
|
||||
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rel);
|
||||
+
|
||||
+ for (j = 0; j < size; ++j) {
|
||||
+ Elf_Sym *sym;
|
||||
+
|
||||
+ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
|
||||
+ continue;
|
||||
+
|
||||
+ sym = syms + ELF_MIPS_R_SYM(rel[j]);
|
||||
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
|
||||
+ continue;
|
||||
+
|
||||
+ ret += 4 * sizeof(int);
|
||||
+ }
|
||||
+ } else {
|
||||
+ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
|
||||
+ unsigned int size = sechdrs[i].sh_size / sizeof(*rela);
|
||||
+
|
||||
+ for (j = 0; j < size; ++j) {
|
||||
+ Elf_Sym *sym;
|
||||
+
|
||||
+ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
|
||||
+ continue;
|
||||
+
|
||||
+ sym = syms + ELF_MIPS_R_SYM(rela[j]);
|
||||
+ if (!is_init && sym->st_shndx != SHN_UNDEF)
|
||||
+ continue;
|
||||
+
|
||||
+ ret += 4 * sizeof(int);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+#ifndef MODULE_START
|
||||
+static void *alloc_phys(unsigned long size)
|
||||
+{
|
||||
+ unsigned order;
|
||||
+ struct page *page;
|
||||
+ struct page *p;
|
||||
+
|
||||
+ size = PAGE_ALIGN(size);
|
||||
+ order = get_order(size);
|
||||
+
|
||||
+ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN |
|
||||
+ __GFP_THISNODE, order);
|
||||
+ if (!page)
|
||||
+ return NULL;
|
||||
+
|
||||
+ split_page(page, order);
|
||||
+
|
||||
+ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
|
||||
+ __free_page(p);
|
||||
+
|
||||
+ return page_address(page);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static void free_phys(void *ptr, unsigned long size)
|
||||
+{
|
||||
+ struct page *page;
|
||||
+ struct page *end;
|
||||
+
|
||||
+ page = virt_to_page(ptr);
|
||||
+ end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
|
||||
+
|
||||
+ for (; page < end; ++page)
|
||||
+ __free_page(page);
|
||||
+}
|
||||
+
|
||||
+
|
||||
void *module_alloc(unsigned long size)
|
||||
{
|
||||
+#ifdef MODULE_START
|
||||
return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
|
||||
GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
|
||||
__builtin_return_address(0));
|
||||
+#else
|
||||
+ void *ptr;
|
||||
+
|
||||
+ if (size == 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ ptr = alloc_phys(size);
|
||||
+
|
||||
+ /* If we failed to allocate physically contiguous memory,
|
||||
+ * fall back to regular vmalloc. The module loader code will
|
||||
+ * create jump tables to handle long jumps */
|
||||
+ if (!ptr)
|
||||
+ return vmalloc(size);
|
||||
+
|
||||
+ return ptr;
|
||||
+#endif
|
||||
}
|
||||
+
|
||||
+static inline bool is_phys_addr(void *ptr)
|
||||
+{
|
||||
+#ifdef CONFIG_64BIT
|
||||
+ return (KSEGX((unsigned long)ptr) == CKSEG0);
|
||||
+#else
|
||||
+ return (KSEGX(ptr) == KSEG0);
|
||||
#endif
|
||||
+}
|
||||
+
|
||||
+/* Free memory returned from module_alloc */
|
||||
+void module_free(struct module *mod, void *module_region)
|
||||
+{
|
||||
+ if (is_phys_addr(module_region)) {
|
||||
+ if (mod->module_init == module_region)
|
||||
+ free_phys(module_region, mod->init_size);
|
||||
+ else if (mod->module_core == module_region)
|
||||
+ free_phys(module_region, mod->core_size);
|
||||
+ else
|
||||
+ BUG();
|
||||
+ } else {
|
||||
+ vfree(module_region);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void *__module_alloc(int size, bool phys)
|
||||
+{
|
||||
+ void *ptr;
|
||||
+
|
||||
+ if (phys)
|
||||
+ ptr = kmalloc(size, GFP_KERNEL);
|
||||
+ else
|
||||
+ ptr = vmalloc(size);
|
||||
+ return ptr;
|
||||
+}
|
||||
+
|
||||
+static void __module_free(void *ptr)
|
||||
+{
|
||||
+ if (is_phys_addr(ptr))
|
||||
+ kfree(ptr);
|
||||
+ else
|
||||
+ vfree(ptr);
|
||||
+}
|
||||
+
|
||||
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
|
||||
+ char *secstrings, struct module *mod)
|
||||
+{
|
||||
+ unsigned int symindex = 0;
|
||||
+ unsigned int core_size, init_size;
|
||||
+ int i;
|
||||
+
|
||||
+ mod->arch.phys_plt_offset = 0;
|
||||
+ mod->arch.virt_plt_offset = 0;
|
||||
+ mod->arch.phys_plt_tbl = NULL;
|
||||
+ mod->arch.virt_plt_tbl = NULL;
|
||||
+
|
||||
+ if (IS_ENABLED(CONFIG_64BIT))
|
||||
+ return 0;
|
||||
+
|
||||
+ for (i = 1; i < hdr->e_shnum; i++)
|
||||
+ if (sechdrs[i].sh_type == SHT_SYMTAB)
|
||||
+ symindex = i;
|
||||
+
|
||||
+ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false);
|
||||
+ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true);
|
||||
+
|
||||
+ if ((core_size + init_size) == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1);
|
||||
+ if (!mod->arch.phys_plt_tbl)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0);
|
||||
+ if (!mod->arch.virt_plt_tbl) {
|
||||
+ __module_free(mod->arch.phys_plt_tbl);
|
||||
+ mod->arch.phys_plt_tbl = NULL;
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
|
||||
int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
|
||||
{
|
||||
@@ -64,8 +272,39 @@ static int apply_r_mips_32_rel(struct mo
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
|
||||
+ void *start, Elf_Addr v)
|
||||
+{
|
||||
+ unsigned *tramp = start + *plt_offset;
|
||||
+ *plt_offset += 4 * sizeof(int);
|
||||
+
|
||||
+ /* adjust carry for addiu */
|
||||
+ if (v & 0x00008000)
|
||||
+ v += 0x10000;
|
||||
+
|
||||
+ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */
|
||||
+ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */
|
||||
+ tramp[2] = 0x03200008; /* jr t9 */
|
||||
+ tramp[3] = 0x00000000; /* nop */
|
||||
+
|
||||
+ return (Elf_Addr) tramp;
|
||||
+}
|
||||
+
|
||||
+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v)
|
||||
+{
|
||||
+ if (is_phys_addr(location))
|
||||
+ return add_plt_entry_to(&me->arch.phys_plt_offset,
|
||||
+ me->arch.phys_plt_tbl, v);
|
||||
+ else
|
||||
+ return add_plt_entry_to(&me->arch.virt_plt_offset,
|
||||
+ me->arch.virt_plt_tbl, v);
|
||||
+
|
||||
+}
|
||||
+
|
||||
static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
|
||||
{
|
||||
+ u32 ofs = *location & 0x03ffffff;
|
||||
+
|
||||
if (v % 4) {
|
||||
pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
|
||||
me->name);
|
||||
@@ -73,14 +312,17 @@ static int apply_r_mips_26_rel(struct mo
|
||||
}
|
||||
|
||||
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
|
||||
- printk(KERN_ERR
|
||||
- "module %s: relocation overflow\n",
|
||||
- me->name);
|
||||
- return -ENOEXEC;
|
||||
+ v = add_plt_entry(me, location, v + (ofs << 2));
|
||||
+ if (!v) {
|
||||
+ printk(KERN_ERR
|
||||
+ "module %s: relocation overflow\n", me->name);
|
||||
+ return -ENOEXEC;
|
||||
+ }
|
||||
+ ofs = 0;
|
||||
}
|
||||
|
||||
*location = (*location & ~0x03ffffff) |
|
||||
- ((*location + (v >> 2)) & 0x03ffffff);
|
||||
+ ((ofs + (v >> 2)) & 0x03ffffff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -287,11 +529,32 @@ int module_finalize(const Elf_Ehdr *hdr,
|
||||
list_add(&me->arch.dbe_list, &dbe_list);
|
||||
spin_unlock_irq(&dbe_lock);
|
||||
}
|
||||
+
|
||||
+ /* Get rid of the fixup trampoline if we're running the module
|
||||
+ * from physically mapped address space */
|
||||
+ if (me->arch.phys_plt_offset == 0) {
|
||||
+ __module_free(me->arch.phys_plt_tbl);
|
||||
+ me->arch.phys_plt_tbl = NULL;
|
||||
+ }
|
||||
+ if (me->arch.virt_plt_offset == 0) {
|
||||
+ __module_free(me->arch.virt_plt_tbl);
|
||||
+ me->arch.virt_plt_tbl = NULL;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
void module_arch_cleanup(struct module *mod)
|
||||
{
|
||||
+ if (mod->arch.phys_plt_tbl) {
|
||||
+ __module_free(mod->arch.phys_plt_tbl);
|
||||
+ mod->arch.phys_plt_tbl = NULL;
|
||||
+ }
|
||||
+ if (mod->arch.virt_plt_tbl) {
|
||||
+ __module_free(mod->arch.virt_plt_tbl);
|
||||
+ mod->arch.virt_plt_tbl = NULL;
|
||||
+ }
|
||||
+
|
||||
spin_lock_irq(&dbe_lock);
|
||||
list_del(&mod->arch.dbe_list);
|
||||
spin_unlock_irq(&dbe_lock);
|
|
@ -1,83 +0,0 @@
|
|||
--- a/arch/mips/include/asm/string.h
|
||||
+++ b/arch/mips/include/asm/string.h
|
||||
@@ -133,11 +133,44 @@ strncmp(__const__ char *__cs, __const__
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
extern void *memset(void *__s, int __c, size_t __count);
|
||||
+#define memset(__s, __c, len) \
|
||||
+({ \
|
||||
+ size_t __len = (len); \
|
||||
+ void *__ret; \
|
||||
+ if (__builtin_constant_p(len) && __len >= 64) \
|
||||
+ __ret = memset((__s), (__c), __len); \
|
||||
+ else \
|
||||
+ __ret = __builtin_memset((__s), (__c), __len); \
|
||||
+ __ret; \
|
||||
+})
|
||||
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
|
||||
+#define memcpy(dst, src, len) \
|
||||
+({ \
|
||||
+ size_t __len = (len); \
|
||||
+ void *__ret; \
|
||||
+ if (__builtin_constant_p(len) && __len >= 64) \
|
||||
+ __ret = memcpy((dst), (src), __len); \
|
||||
+ else \
|
||||
+ __ret = __builtin_memcpy((dst), (src), __len); \
|
||||
+ __ret; \
|
||||
+})
|
||||
|
||||
#define __HAVE_ARCH_MEMMOVE
|
||||
extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
|
||||
+#define memmove(dst, src, len) \
|
||||
+({ \
|
||||
+ size_t __len = (len); \
|
||||
+ void *__ret; \
|
||||
+ if (__builtin_constant_p(len) && __len >= 64) \
|
||||
+ __ret = memmove((dst), (src), __len); \
|
||||
+ else \
|
||||
+ __ret = __builtin_memmove((dst), (src), __len); \
|
||||
+ __ret; \
|
||||
+})
|
||||
+
|
||||
+#define __HAVE_ARCH_MEMCMP
|
||||
+#define memcmp(src1, src2, len) __builtin_memcmp((src1), (src2), (len))
|
||||
|
||||
#endif /* _ASM_STRING_H */
|
||||
--- a/arch/mips/lib/Makefile
|
||||
+++ b/arch/mips/lib/Makefile
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \
|
||||
mips-atomic.o strlen_user.o strncpy_user.o \
|
||||
- strnlen_user.o uncached.o
|
||||
+ strnlen_user.o uncached.o memcmp.o
|
||||
|
||||
obj-y += iomap.o
|
||||
obj-$(CONFIG_PCI) += iomap-pci.o
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/lib/memcmp.c
|
||||
@@ -0,0 +1,22 @@
|
||||
+/*
|
||||
+ * copied from linux/lib/string.c
|
||||
+ *
|
||||
+ * Copyright (C) 1991, 1992 Linus Torvalds
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/string.h>
|
||||
+
|
||||
+#undef memcmp
|
||||
+int memcmp(const void *cs, const void *ct, size_t count)
|
||||
+{
|
||||
+ const unsigned char *su1, *su2;
|
||||
+ int res = 0;
|
||||
+
|
||||
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
|
||||
+ if ((res = *su1 - *su2) != 0)
|
||||
+ break;
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL(memcmp);
|
||||
+
|
|
@ -1,32 +0,0 @@
|
|||
--- a/arch/mips/mm/cache.c
|
||||
+++ b/arch/mips/mm/cache.c
|
||||
@@ -38,6 +38,7 @@ void (*__flush_kernel_vmap_range)(unsign
|
||||
void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
|
||||
|
||||
EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
|
||||
+EXPORT_SYMBOL(__flush_cache_all);
|
||||
|
||||
/* MIPS specific cache operations */
|
||||
void (*flush_cache_sigtramp)(unsigned long addr);
|
||||
--- a/fs/fuse/dev.c
|
||||
+++ b/fs/fuse/dev.c
|
||||
@@ -20,6 +20,9 @@
|
||||
#include <linux/swap.h>
|
||||
#include <linux/splice.h>
|
||||
#include <linux/aio.h>
|
||||
+#ifdef CONFIG_MIPS
|
||||
+#include <asm/cacheflush.h>
|
||||
+#endif
|
||||
|
||||
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
|
||||
MODULE_ALIAS("devname:fuse");
|
||||
@@ -759,6 +762,9 @@ static int fuse_copy_fill(struct fuse_co
|
||||
static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
|
||||
{
|
||||
unsigned ncpy = min(*size, cs->len);
|
||||
+#ifdef CONFIG_MIPS
|
||||
+ __flush_cache_all();
|
||||
+#endif
|
||||
if (val) {
|
||||
if (cs->write)
|
||||
memcpy(cs->buf, *val, ncpy);
|
|
@ -1,13 +0,0 @@
|
|||
--- a/arch/arm/kernel/module.c
|
||||
+++ b/arch/arm/kernel/module.c
|
||||
@@ -83,6 +83,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
+ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) &&
|
||||
+ ELF_ST_BIND(sym->st_info) == STB_WEAK)
|
||||
+ continue;
|
||||
+
|
||||
loc = dstsec->sh_addr + rel->r_offset;
|
||||
|
||||
switch (ELF32_R_TYPE(rel->r_info)) {
|
|
@ -1,31 +0,0 @@
|
|||
Upstream doesn't optimize the kernel and bootwrappers for ppc44x because
|
||||
they still want to support gcc 3.3 -- well, we don't.
|
||||
|
||||
--- a/arch/powerpc/Makefile
|
||||
+++ b/arch/powerpc/Makefile
|
||||
@@ -191,7 +191,8 @@ ifeq ($(CONFIG_FUNCTION_TRACER),y)
|
||||
KBUILD_CFLAGS += -mno-sched-epilog
|
||||
endif
|
||||
|
||||
-cpu-as-$(CONFIG_4xx) += -Wa,-m405
|
||||
+cpu-as-$(CONFIG_40x) += -Wa,-m405
|
||||
+cpu-as-$(CONFIG_44x) += -Wa,-m440
|
||||
cpu-as-$(CONFIG_ALTIVEC) += -Wa,-maltivec
|
||||
cpu-as-$(CONFIG_E200) += -Wa,-me200
|
||||
|
||||
--- a/arch/powerpc/boot/Makefile
|
||||
+++ b/arch/powerpc/boot/Makefile
|
||||
@@ -39,10 +39,10 @@ BOOTCFLAGS += -I$(obj) -I$(srctree)/$(ob
|
||||
DTC_FLAGS ?= -p 1024
|
||||
|
||||
$(obj)/4xx.o: BOOTCFLAGS += -mcpu=405
|
||||
-$(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
|
||||
+$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
|
||||
$(obj)/cuboot-hotfoot.o: BOOTCFLAGS += -mcpu=405
|
||||
-$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
|
||||
-$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
|
||||
+$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=440
|
||||
+$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=440
|
||||
$(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
|
||||
$(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405
|
|
@ -1,10 +0,0 @@
|
|||
--- a/arch/powerpc/Makefile
|
||||
+++ b/arch/powerpc/Makefile
|
||||
@@ -158,7 +158,6 @@ CPP = $(CC) -E $(KBUILD_CFLAGS)
|
||||
|
||||
CHECKFLAGS += -m$(CONFIG_WORD_SIZE) -D__powerpc__ -D__powerpc$(CONFIG_WORD_SIZE)__
|
||||
|
||||
-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
|
||||
|
||||
# No AltiVec or VSX instructions when building kernel
|
||||
KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
|
|
@ -1,171 +0,0 @@
|
|||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -12,6 +12,23 @@ menuconfig MTD
|
||||
|
||||
if MTD
|
||||
|
||||
+menu "OpenWrt specific MTD options"
|
||||
+
|
||||
+config MTD_ROOTFS_ROOT_DEV
|
||||
+ bool "Automatically set 'rootfs' partition to be root filesystem"
|
||||
+ default y
|
||||
+
|
||||
+config MTD_SPLIT_FIRMWARE
|
||||
+ bool "Automatically split firmware partition for kernel+rootfs"
|
||||
+ default y
|
||||
+
|
||||
+config MTD_SPLIT_FIRMWARE_NAME
|
||||
+ string "Firmware partition name"
|
||||
+ depends on MTD_SPLIT_FIRMWARE
|
||||
+ default "firmware"
|
||||
+
|
||||
+endmenu
|
||||
+
|
||||
config MTD_TESTS
|
||||
tristate "MTD tests support (DANGEROUS)"
|
||||
depends on m
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -29,9 +29,11 @@
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
+#include <linux/magic.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "mtdcore.h"
|
||||
+#include "mtdsplit/mtdsplit.h"
|
||||
|
||||
/* Our partition linked list */
|
||||
static LIST_HEAD(mtd_partitions);
|
||||
@@ -45,13 +47,14 @@ struct mtd_part {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
+static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part);
|
||||
+
|
||||
/*
|
||||
* Given a pointer to the MTD object in the mtd_part structure, we can retrieve
|
||||
* the pointer to that structure with this macro.
|
||||
*/
|
||||
#define PART(x) ((struct mtd_part *)(x))
|
||||
|
||||
-
|
||||
/*
|
||||
* MTD methods which simply translate the effective address and pass through
|
||||
* to the _real_ device.
|
||||
@@ -534,8 +537,10 @@ out_register:
|
||||
return slave;
|
||||
}
|
||||
|
||||
-int mtd_add_partition(struct mtd_info *master, const char *name,
|
||||
- long long offset, long long length)
|
||||
+
|
||||
+static int
|
||||
+__mtd_add_partition(struct mtd_info *master, const char *name,
|
||||
+ long long offset, long long length, bool dup_check)
|
||||
{
|
||||
struct mtd_partition part;
|
||||
struct mtd_part *p, *new;
|
||||
@@ -567,21 +572,24 @@ int mtd_add_partition(struct mtd_info *m
|
||||
end = offset + length;
|
||||
|
||||
mutex_lock(&mtd_partitions_mutex);
|
||||
- list_for_each_entry(p, &mtd_partitions, list)
|
||||
- if (p->master == master) {
|
||||
- if ((start >= p->offset) &&
|
||||
- (start < (p->offset + p->mtd.size)))
|
||||
- goto err_inv;
|
||||
-
|
||||
- if ((end >= p->offset) &&
|
||||
- (end < (p->offset + p->mtd.size)))
|
||||
- goto err_inv;
|
||||
- }
|
||||
+ if (dup_check) {
|
||||
+ list_for_each_entry(p, &mtd_partitions, list)
|
||||
+ if (p->master == master) {
|
||||
+ if ((start >= p->offset) &&
|
||||
+ (start < (p->offset + p->mtd.size)))
|
||||
+ goto err_inv;
|
||||
+
|
||||
+ if ((end >= p->offset) &&
|
||||
+ (end < (p->offset + p->mtd.size)))
|
||||
+ goto err_inv;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
list_add(&new->list, &mtd_partitions);
|
||||
mutex_unlock(&mtd_partitions_mutex);
|
||||
|
||||
add_mtd_device(&new->mtd);
|
||||
+ mtd_partition_split(master, new);
|
||||
|
||||
return ret;
|
||||
err_inv:
|
||||
@@ -591,6 +599,12 @@ err_inv:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_add_partition);
|
||||
|
||||
+int mtd_add_partition(struct mtd_info *master, const char *name,
|
||||
+ long long offset, long long length)
|
||||
+{
|
||||
+ return __mtd_add_partition(master, name, offset, length, true);
|
||||
+}
|
||||
+
|
||||
int mtd_del_partition(struct mtd_info *master, int partno)
|
||||
{
|
||||
struct mtd_part *slave, *next;
|
||||
@@ -614,6 +628,35 @@ int mtd_del_partition(struct mtd_info *m
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_del_partition);
|
||||
|
||||
+#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME
|
||||
+#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME
|
||||
+#else
|
||||
+#define SPLIT_FIRMWARE_NAME "unused"
|
||||
+#endif
|
||||
+
|
||||
+static void split_firmware(struct mtd_info *master, struct mtd_part *part)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+void __weak arch_split_mtd_part(struct mtd_info *master, const char *name,
|
||||
+ int offset, int size)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part)
|
||||
+{
|
||||
+ static int rootfs_found = 0;
|
||||
+
|
||||
+ if (rootfs_found)
|
||||
+ return;
|
||||
+
|
||||
+ if (!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) &&
|
||||
+ config_enabled(CONFIG_MTD_SPLIT_FIRMWARE))
|
||||
+ split_firmware(master, part);
|
||||
+
|
||||
+ arch_split_mtd_part(master, part->mtd.name, part->offset,
|
||||
+ part->mtd.size);
|
||||
+}
|
||||
/*
|
||||
* This function, given a master MTD object and a partition table, creates
|
||||
* and registers slave MTD objects which are bound to the master according to
|
||||
@@ -643,6 +686,7 @@ int add_mtd_partitions(struct mtd_info *
|
||||
mutex_unlock(&mtd_partitions_mutex);
|
||||
|
||||
add_mtd_device(&slave->mtd);
|
||||
+ mtd_partition_split(master, slave);
|
||||
|
||||
cur_offset = slave->offset + slave->mtd.size;
|
||||
}
|
||||
--- a/include/linux/mtd/partitions.h
|
||||
+++ b/include/linux/mtd/partitions.h
|
||||
@@ -84,5 +84,7 @@ int mtd_add_partition(struct mtd_info *m
|
||||
long long offset, long long length);
|
||||
int mtd_del_partition(struct mtd_info *master, int partno);
|
||||
uint64_t mtd_get_device_size(const struct mtd_info *mtd);
|
||||
+extern void __weak arch_split_mtd_part(struct mtd_info *master,
|
||||
+ const char *name, int offset, int size);
|
||||
|
||||
#endif
|
|
@ -1,113 +0,0 @@
|
|||
From 02cff0ccaa6d364f5c1eeea83f47ac80ccc967d4 Mon Sep 17 00:00:00 2001
|
||||
From: Gabor Juhos <juhosg@openwrt.org>
|
||||
Date: Tue, 3 Sep 2013 18:11:50 +0200
|
||||
Subject: [PATCH] mtd: add support for different partition parser types
|
||||
|
||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
---
|
||||
drivers/mtd/mtdpart.c | 56 ++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/mtd/partitions.h | 11 ++++++++
|
||||
2 files changed, 67 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -716,6 +716,30 @@ static struct mtd_part_parser *get_parti
|
||||
|
||||
#define put_partition_parser(p) do { module_put((p)->owner); } while (0)
|
||||
|
||||
+static struct mtd_part_parser *
|
||||
+get_partition_parser_by_type(enum mtd_parser_type type,
|
||||
+ struct mtd_part_parser *start)
|
||||
+{
|
||||
+ struct mtd_part_parser *p, *ret = NULL;
|
||||
+
|
||||
+ spin_lock(&part_parser_lock);
|
||||
+
|
||||
+ p = list_prepare_entry(start, &part_parsers, list);
|
||||
+ if (start)
|
||||
+ put_partition_parser(start);
|
||||
+
|
||||
+ list_for_each_entry_continue(p, &part_parsers, list) {
|
||||
+ if (p->type == type && try_module_get(p->owner)) {
|
||||
+ ret = p;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock(&part_parser_lock);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void register_mtd_parser(struct mtd_part_parser *p)
|
||||
{
|
||||
spin_lock(&part_parser_lock);
|
||||
@@ -789,6 +813,38 @@ int parse_mtd_partitions(struct mtd_info
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int parse_mtd_partitions_by_type(struct mtd_info *master,
|
||||
+ enum mtd_parser_type type,
|
||||
+ struct mtd_partition **pparts,
|
||||
+ struct mtd_part_parser_data *data)
|
||||
+{
|
||||
+ struct mtd_part_parser *prev = NULL;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ while (1) {
|
||||
+ struct mtd_part_parser *parser;
|
||||
+
|
||||
+ parser = get_partition_parser_by_type(type, prev);
|
||||
+ if (!parser)
|
||||
+ break;
|
||||
+
|
||||
+ ret = (*parser->parse_fn)(master, pparts, data);
|
||||
+
|
||||
+ if (ret > 0) {
|
||||
+ put_partition_parser(parser);
|
||||
+ printk(KERN_NOTICE
|
||||
+ "%d %s partitions found on MTD device %s\n",
|
||||
+ ret, parser->name, master->name);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ prev = parser;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(parse_mtd_partitions_by_type);
|
||||
+
|
||||
int mtd_is_partition(const struct mtd_info *mtd)
|
||||
{
|
||||
struct mtd_part *part;
|
||||
--- a/include/linux/mtd/partitions.h
|
||||
+++ b/include/linux/mtd/partitions.h
|
||||
@@ -68,12 +68,17 @@ struct mtd_part_parser_data {
|
||||
* Functions dealing with the various ways of partitioning the space
|
||||
*/
|
||||
|
||||
+enum mtd_parser_type {
|
||||
+ MTD_PARSER_TYPE_DEVICE = 0,
|
||||
+};
|
||||
+
|
||||
struct mtd_part_parser {
|
||||
struct list_head list;
|
||||
struct module *owner;
|
||||
const char *name;
|
||||
int (*parse_fn)(struct mtd_info *, struct mtd_partition **,
|
||||
struct mtd_part_parser_data *);
|
||||
+ enum mtd_parser_type type;
|
||||
};
|
||||
|
||||
extern void register_mtd_parser(struct mtd_part_parser *parser);
|
||||
@@ -87,4 +92,9 @@ uint64_t mtd_get_device_size(const struc
|
||||
extern void __weak arch_split_mtd_part(struct mtd_info *master,
|
||||
const char *name, int offset, int size);
|
||||
|
||||
+int parse_mtd_partitions_by_type(struct mtd_info *master,
|
||||
+ enum mtd_parser_type type,
|
||||
+ struct mtd_partition **pparts,
|
||||
+ struct mtd_part_parser_data *data);
|
||||
+
|
||||
#endif
|
|
@ -1,72 +0,0 @@
|
|||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -628,6 +628,37 @@ int mtd_del_partition(struct mtd_info *m
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_del_partition);
|
||||
|
||||
+static int
|
||||
+run_parsers_by_type(struct mtd_part *slave, enum mtd_parser_type type)
|
||||
+{
|
||||
+ struct mtd_partition *parts;
|
||||
+ int nr_parts;
|
||||
+ int i;
|
||||
+
|
||||
+ nr_parts = parse_mtd_partitions_by_type(&slave->mtd, type, &parts,
|
||||
+ NULL);
|
||||
+ if (nr_parts <= 0)
|
||||
+ return nr_parts;
|
||||
+
|
||||
+ if (WARN_ON(!parts))
|
||||
+ return 0;
|
||||
+
|
||||
+ for (i = 0; i < nr_parts; i++) {
|
||||
+ /* adjust partition offsets */
|
||||
+ parts[i].offset += slave->offset;
|
||||
+
|
||||
+ __mtd_add_partition(slave->master,
|
||||
+ parts[i].name,
|
||||
+ parts[i].offset,
|
||||
+ parts[i].size,
|
||||
+ false);
|
||||
+ }
|
||||
+
|
||||
+ kfree(parts);
|
||||
+
|
||||
+ return nr_parts;
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME
|
||||
#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME
|
||||
#else
|
||||
@@ -636,6 +667,7 @@ EXPORT_SYMBOL_GPL(mtd_del_partition);
|
||||
|
||||
static void split_firmware(struct mtd_info *master, struct mtd_part *part)
|
||||
{
|
||||
+ run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE);
|
||||
}
|
||||
|
||||
void __weak arch_split_mtd_part(struct mtd_info *master, const char *name,
|
||||
@@ -650,6 +682,12 @@ static void mtd_partition_split(struct m
|
||||
if (rootfs_found)
|
||||
return;
|
||||
|
||||
+ if (!strcmp(part->mtd.name, "rootfs")) {
|
||||
+ run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS);
|
||||
+
|
||||
+ rootfs_found = 1;
|
||||
+ }
|
||||
+
|
||||
if (!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) &&
|
||||
config_enabled(CONFIG_MTD_SPLIT_FIRMWARE))
|
||||
split_firmware(master, part);
|
||||
--- a/include/linux/mtd/partitions.h
|
||||
+++ b/include/linux/mtd/partitions.h
|
||||
@@ -70,6 +70,8 @@ struct mtd_part_parser_data {
|
||||
|
||||
enum mtd_parser_type {
|
||||
MTD_PARSER_TYPE_DEVICE = 0,
|
||||
+ MTD_PARSER_TYPE_ROOTFS,
|
||||
+ MTD_PARSER_TYPE_FIRMWARE,
|
||||
};
|
||||
|
||||
struct mtd_part_parser {
|
|
@ -1,22 +0,0 @@
|
|||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -27,6 +27,8 @@ config MTD_SPLIT_FIRMWARE_NAME
|
||||
depends on MTD_SPLIT_FIRMWARE
|
||||
default "firmware"
|
||||
|
||||
+source "drivers/mtd/mtdsplit/Kconfig"
|
||||
+
|
||||
endmenu
|
||||
|
||||
config MTD_TESTS
|
||||
--- a/drivers/mtd/Makefile
|
||||
+++ b/drivers/mtd/Makefile
|
||||
@@ -6,6 +6,8 @@
|
||||
obj-$(CONFIG_MTD) += mtd.o
|
||||
mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o
|
||||
|
||||
+obj-$(CONFIG_MTD_SPLIT) += mtdsplit/
|
||||
+
|
||||
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
||||
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
|
@ -1,101 +0,0 @@
|
|||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -434,14 +434,12 @@ static struct mtd_part *allocate_partiti
|
||||
if (slave->offset == MTDPART_OFS_APPEND)
|
||||
slave->offset = cur_offset;
|
||||
if (slave->offset == MTDPART_OFS_NXTBLK) {
|
||||
- slave->offset = cur_offset;
|
||||
- if (mtd_mod_by_eb(cur_offset, master) != 0) {
|
||||
- /* Round up to next erasesize */
|
||||
- slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize;
|
||||
+ /* Round up to next erasesize */
|
||||
+ slave->offset = mtd_roundup_to_eb(cur_offset, master);
|
||||
+ if (slave->offset != cur_offset)
|
||||
printk(KERN_NOTICE "Moving partition %d: "
|
||||
"0x%012llx -> 0x%012llx\n", partno,
|
||||
(unsigned long long)cur_offset, (unsigned long long)slave->offset);
|
||||
- }
|
||||
}
|
||||
if (slave->offset == MTDPART_OFS_RETAIN) {
|
||||
slave->offset = cur_offset;
|
||||
@@ -659,6 +657,17 @@ run_parsers_by_type(struct mtd_part *sla
|
||||
return nr_parts;
|
||||
}
|
||||
|
||||
+static inline unsigned long
|
||||
+mtd_pad_erasesize(struct mtd_info *mtd, int offset, int len)
|
||||
+{
|
||||
+ unsigned long mask = mtd->erasesize - 1;
|
||||
+
|
||||
+ len += offset & mask;
|
||||
+ len = (len + mask) & ~mask;
|
||||
+ len -= offset & mask;
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME
|
||||
#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME
|
||||
#else
|
||||
@@ -900,6 +909,24 @@ int mtd_is_partition(const struct mtd_in
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_is_partition);
|
||||
|
||||
+struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd)
|
||||
+{
|
||||
+ if (!mtd_is_partition(mtd))
|
||||
+ return (struct mtd_info *)mtd;
|
||||
+
|
||||
+ return PART(mtd)->master;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(mtdpart_get_master);
|
||||
+
|
||||
+uint64_t mtdpart_get_offset(const struct mtd_info *mtd)
|
||||
+{
|
||||
+ if (!mtd_is_partition(mtd))
|
||||
+ return 0;
|
||||
+
|
||||
+ return PART(mtd)->offset;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(mtdpart_get_offset);
|
||||
+
|
||||
/* Returns the size of the entire flash chip */
|
||||
uint64_t mtd_get_device_size(const struct mtd_info *mtd)
|
||||
{
|
||||
--- a/include/linux/mtd/partitions.h
|
||||
+++ b/include/linux/mtd/partitions.h
|
||||
@@ -90,6 +90,8 @@ int mtd_is_partition(const struct mtd_in
|
||||
int mtd_add_partition(struct mtd_info *master, const char *name,
|
||||
long long offset, long long length);
|
||||
int mtd_del_partition(struct mtd_info *master, int partno);
|
||||
+struct mtd_info *mtdpart_get_master(const struct mtd_info *mtd);
|
||||
+uint64_t mtdpart_get_offset(const struct mtd_info *mtd);
|
||||
uint64_t mtd_get_device_size(const struct mtd_info *mtd);
|
||||
extern void __weak arch_split_mtd_part(struct mtd_info *master,
|
||||
const char *name, int offset, int size);
|
||||
--- a/include/linux/mtd/mtd.h
|
||||
+++ b/include/linux/mtd/mtd.h
|
||||
@@ -331,6 +331,24 @@ static inline uint32_t mtd_mod_by_eb(uin
|
||||
return do_div(sz, mtd->erasesize);
|
||||
}
|
||||
|
||||
+static inline uint64_t mtd_roundup_to_eb(uint64_t sz, struct mtd_info *mtd)
|
||||
+{
|
||||
+ if (mtd_mod_by_eb(sz, mtd) == 0)
|
||||
+ return sz;
|
||||
+
|
||||
+ /* Round up to next erase block */
|
||||
+ return (mtd_div_by_eb(sz, mtd) + 1) * mtd->erasesize;
|
||||
+}
|
||||
+
|
||||
+static inline uint64_t mtd_rounddown_to_eb(uint64_t sz, struct mtd_info *mtd)
|
||||
+{
|
||||
+ if (mtd_mod_by_eb(sz, mtd) == 0)
|
||||
+ return sz;
|
||||
+
|
||||
+ /* Round down to the start of the current erase block */
|
||||
+ return (mtd_div_by_eb(sz, mtd)) * mtd->erasesize;
|
||||
+}
|
||||
+
|
||||
static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd)
|
||||
{
|
||||
if (mtd->writesize_shift)
|
|
@ -1,70 +0,0 @@
|
|||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -27,6 +27,11 @@ config MTD_SPLIT_FIRMWARE_NAME
|
||||
depends on MTD_SPLIT_FIRMWARE
|
||||
default "firmware"
|
||||
|
||||
+config MTD_UIMAGE_SPLIT
|
||||
+ bool "Enable split support for firmware partitions containing a uImage"
|
||||
+ depends on MTD_SPLIT_FIRMWARE
|
||||
+ default y
|
||||
+
|
||||
source "drivers/mtd/mtdsplit/Kconfig"
|
||||
|
||||
endmenu
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -668,6 +668,37 @@ mtd_pad_erasesize(struct mtd_info *mtd,
|
||||
return len;
|
||||
}
|
||||
|
||||
+#define UBOOT_MAGIC 0x27051956
|
||||
+
|
||||
+static void split_uimage(struct mtd_info *master, struct mtd_part *part)
|
||||
+{
|
||||
+ struct {
|
||||
+ __be32 magic;
|
||||
+ __be32 pad[2];
|
||||
+ __be32 size;
|
||||
+ } hdr;
|
||||
+ size_t len;
|
||||
+
|
||||
+ if (mtd_read(master, part->offset, sizeof(hdr), &len, (void *) &hdr))
|
||||
+ return;
|
||||
+
|
||||
+ if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC))
|
||||
+ return;
|
||||
+
|
||||
+ len = be32_to_cpu(hdr.size) + 0x40;
|
||||
+ len = mtd_pad_erasesize(master, part->offset, len);
|
||||
+ if (len + master->erasesize > part->mtd.size)
|
||||
+ return;
|
||||
+
|
||||
+ if (config_enabled(CONFIG_MTD_SPLIT_UIMAGE_FW))
|
||||
+ pr_err("Dedicated partitioner didn't split firmware partition, please fill a bug report!\n");
|
||||
+ else
|
||||
+ pr_warn("Support for built-in firmware splitter will be removed, please use CONFIG_MTD_SPLIT_UIMAGE_FW\n");
|
||||
+
|
||||
+ __mtd_add_partition(master, "rootfs", part->offset + len,
|
||||
+ part->mtd.size - len, false);
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_MTD_SPLIT_FIRMWARE_NAME
|
||||
#define SPLIT_FIRMWARE_NAME CONFIG_MTD_SPLIT_FIRMWARE_NAME
|
||||
#else
|
||||
@@ -676,7 +707,14 @@ mtd_pad_erasesize(struct mtd_info *mtd,
|
||||
|
||||
static void split_firmware(struct mtd_info *master, struct mtd_part *part)
|
||||
{
|
||||
- run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = run_parsers_by_type(part, MTD_PARSER_TYPE_FIRMWARE);
|
||||
+ if (ret > 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (config_enabled(CONFIG_MTD_UIMAGE_SPLIT))
|
||||
+ split_uimage(master, part);
|
||||
}
|
||||
|
||||
void __weak arch_split_mtd_part(struct mtd_info *master, const char *name,
|
|
@ -1,76 +0,0 @@
|
|||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -18,6 +18,11 @@ config MTD_ROOTFS_ROOT_DEV
|
||||
bool "Automatically set 'rootfs' partition to be root filesystem"
|
||||
default y
|
||||
|
||||
+config MTD_ROOTFS_SPLIT
|
||||
+ bool "Automatically split 'rootfs' partition for squashfs"
|
||||
+ select MTD_SPLIT
|
||||
+ default y
|
||||
+
|
||||
config MTD_SPLIT_FIRMWARE
|
||||
bool "Automatically split firmware partition for kernel+rootfs"
|
||||
default y
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -668,6 +668,47 @@ mtd_pad_erasesize(struct mtd_info *mtd,
|
||||
return len;
|
||||
}
|
||||
|
||||
+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
|
||||
+{
|
||||
+ size_t squashfs_len;
|
||||
+ int len, ret;
|
||||
+
|
||||
+ ret = mtd_get_squashfs_len(master, offset, &squashfs_len);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ len = mtd_pad_erasesize(master, offset, squashfs_len);
|
||||
+ *split_offset = offset + len;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void split_rootfs_data(struct mtd_info *master, struct mtd_part *part)
|
||||
+{
|
||||
+ unsigned int split_offset = 0;
|
||||
+ unsigned int split_size;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = split_squashfs(master, part->offset, &split_offset);
|
||||
+ if (ret)
|
||||
+ return;
|
||||
+
|
||||
+ if (split_offset <= 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (config_enabled(CONFIG_MTD_SPLIT_SQUASHFS_ROOT))
|
||||
+ pr_err("Dedicated partitioner didn't create \"rootfs_data\" partition, please fill a bug report!\n");
|
||||
+ else
|
||||
+ pr_warn("Support for built-in \"rootfs_data\" splitter will be removed, please use CONFIG_MTD_SPLIT_SQUASHFS_ROOT\n");
|
||||
+
|
||||
+ split_size = part->mtd.size - (split_offset - part->offset);
|
||||
+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=0x%x, len=0x%x\n",
|
||||
+ ROOTFS_SPLIT_NAME, split_offset, split_size);
|
||||
+
|
||||
+ __mtd_add_partition(master, ROOTFS_SPLIT_NAME, split_offset,
|
||||
+ split_size, false);
|
||||
+}
|
||||
+
|
||||
#define UBOOT_MAGIC 0x27051956
|
||||
|
||||
static void split_uimage(struct mtd_info *master, struct mtd_part *part)
|
||||
@@ -730,7 +771,10 @@ static void mtd_partition_split(struct m
|
||||
return;
|
||||
|
||||
if (!strcmp(part->mtd.name, "rootfs")) {
|
||||
- run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS);
|
||||
+ int num = run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS);
|
||||
+
|
||||
+ if (num <= 0 && config_enabled(CONFIG_MTD_ROOTFS_SPLIT))
|
||||
+ split_rootfs_data(master, part);
|
||||
|
||||
rootfs_found = 1;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
--- a/include/linux/mtd/partitions.h
|
||||
+++ b/include/linux/mtd/partitions.h
|
||||
@@ -35,6 +35,7 @@
|
||||
* Note: writeable partitions require their size and offset be
|
||||
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
|
||||
*/
|
||||
+struct mtd_info;
|
||||
|
||||
struct mtd_partition {
|
||||
const char *name; /* identifier string */
|
||||
@@ -50,7 +51,6 @@ struct mtd_partition {
|
||||
#define MTDPART_SIZ_FULL (0)
|
||||
|
||||
|
||||
-struct mtd_info;
|
||||
struct device_node;
|
||||
|
||||
/**
|
|
@ -1,146 +0,0 @@
|
|||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "mtdcore.h"
|
||||
#include "mtdsplit/mtdsplit.h"
|
||||
|
||||
+#define MTD_ERASE_PARTIAL 0x8000 /* partition only covers parts of an erase block */
|
||||
+
|
||||
/* Our partition linked list */
|
||||
static LIST_HEAD(mtd_partitions);
|
||||
static DEFINE_MUTEX(mtd_partitions_mutex);
|
||||
@@ -231,13 +233,61 @@ static int part_erase(struct mtd_info *m
|
||||
struct mtd_part *part = PART(mtd);
|
||||
int ret;
|
||||
|
||||
+
|
||||
+ instr->partial_start = false;
|
||||
+ if (mtd->flags & MTD_ERASE_PARTIAL) {
|
||||
+ size_t readlen = 0;
|
||||
+ u64 mtd_ofs;
|
||||
+
|
||||
+ instr->erase_buf = kmalloc(part->master->erasesize, GFP_ATOMIC);
|
||||
+ if (!instr->erase_buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mtd_ofs = part->offset + instr->addr;
|
||||
+ instr->erase_buf_ofs = do_div(mtd_ofs, part->master->erasesize);
|
||||
+
|
||||
+ if (instr->erase_buf_ofs > 0) {
|
||||
+ instr->addr -= instr->erase_buf_ofs;
|
||||
+ ret = mtd_read(part->master,
|
||||
+ instr->addr + part->offset,
|
||||
+ part->master->erasesize,
|
||||
+ &readlen, instr->erase_buf);
|
||||
+
|
||||
+ instr->len += instr->erase_buf_ofs;
|
||||
+ instr->partial_start = true;
|
||||
+ } else {
|
||||
+ mtd_ofs = part->offset + part->mtd.size;
|
||||
+ instr->erase_buf_ofs = part->master->erasesize -
|
||||
+ do_div(mtd_ofs, part->master->erasesize);
|
||||
+
|
||||
+ if (instr->erase_buf_ofs > 0) {
|
||||
+ instr->len += instr->erase_buf_ofs;
|
||||
+ ret = mtd_read(part->master,
|
||||
+ part->offset + instr->addr +
|
||||
+ instr->len - part->master->erasesize,
|
||||
+ part->master->erasesize, &readlen,
|
||||
+ instr->erase_buf);
|
||||
+ } else {
|
||||
+ ret = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ if (ret < 0) {
|
||||
+ kfree(instr->erase_buf);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
instr->addr += part->offset;
|
||||
ret = part->master->_erase(part->master, instr);
|
||||
if (ret) {
|
||||
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
|
||||
instr->fail_addr -= part->offset;
|
||||
instr->addr -= part->offset;
|
||||
+ if (mtd->flags & MTD_ERASE_PARTIAL)
|
||||
+ kfree(instr->erase_buf);
|
||||
}
|
||||
+
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -245,7 +295,25 @@ void mtd_erase_callback(struct erase_inf
|
||||
{
|
||||
if (instr->mtd->_erase == part_erase) {
|
||||
struct mtd_part *part = PART(instr->mtd);
|
||||
+ size_t wrlen = 0;
|
||||
|
||||
+ if (instr->mtd->flags & MTD_ERASE_PARTIAL) {
|
||||
+ if (instr->partial_start) {
|
||||
+ part->master->_write(part->master,
|
||||
+ instr->addr, instr->erase_buf_ofs,
|
||||
+ &wrlen, instr->erase_buf);
|
||||
+ instr->addr += instr->erase_buf_ofs;
|
||||
+ } else {
|
||||
+ instr->len -= instr->erase_buf_ofs;
|
||||
+ part->master->_write(part->master,
|
||||
+ instr->addr + instr->len,
|
||||
+ instr->erase_buf_ofs, &wrlen,
|
||||
+ instr->erase_buf +
|
||||
+ part->master->erasesize -
|
||||
+ instr->erase_buf_ofs);
|
||||
+ }
|
||||
+ kfree(instr->erase_buf);
|
||||
+ }
|
||||
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
|
||||
instr->fail_addr -= part->offset;
|
||||
instr->addr -= part->offset;
|
||||
@@ -503,18 +571,24 @@ static struct mtd_part *allocate_partiti
|
||||
if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
mtd_mod_by_eb(slave->offset, &slave->mtd)) {
|
||||
/* Doesn't start on a boundary of major erase size */
|
||||
- /* FIXME: Let it be writable if it is on a boundary of
|
||||
- * _minor_ erase size though */
|
||||
- slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
|
||||
- part->name);
|
||||
+ slave->mtd.flags |= MTD_ERASE_PARTIAL;
|
||||
+ if (((u32) slave->mtd.size) > master->erasesize)
|
||||
+ slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
+ else
|
||||
+ slave->mtd.erasesize = slave->mtd.size;
|
||||
}
|
||||
if ((slave->mtd.flags & MTD_WRITEABLE) &&
|
||||
- mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
|
||||
- slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
|
||||
- part->name);
|
||||
+ mtd_mod_by_eb(slave->offset + slave->mtd.size, &slave->mtd)) {
|
||||
+ slave->mtd.flags |= MTD_ERASE_PARTIAL;
|
||||
+
|
||||
+ if ((u32) slave->mtd.size > master->erasesize)
|
||||
+ slave->mtd.flags &= ~MTD_WRITEABLE;
|
||||
+ else
|
||||
+ slave->mtd.erasesize = slave->mtd.size;
|
||||
}
|
||||
+ if ((slave->mtd.flags & (MTD_ERASE_PARTIAL|MTD_WRITEABLE)) == MTD_ERASE_PARTIAL)
|
||||
+ printk(KERN_WARNING"mtd: partition \"%s\" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only\n",
|
||||
+ part->name);
|
||||
|
||||
slave->mtd.ecclayout = master->ecclayout;
|
||||
slave->mtd.ecc_step_size = master->ecc_step_size;
|
||||
--- a/include/linux/mtd/mtd.h
|
||||
+++ b/include/linux/mtd/mtd.h
|
||||
@@ -55,6 +55,10 @@ struct erase_info {
|
||||
u_long priv;
|
||||
u_char state;
|
||||
struct erase_info *next;
|
||||
+
|
||||
+ u8 *erase_buf;
|
||||
+ u32 erase_buf_ofs;
|
||||
+ bool partial_start;
|
||||
};
|
||||
|
||||
struct mtd_erase_region_info {
|
|
@ -1,18 +0,0 @@
|
|||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -332,7 +332,14 @@ static int part_lock(struct mtd_info *mt
|
||||
static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
struct mtd_part *part = PART(mtd);
|
||||
- return part->master->_unlock(part->master, ofs + part->offset, len);
|
||||
+
|
||||
+ ofs += part->offset;
|
||||
+ if (mtd->flags & MTD_ERASE_PARTIAL) {
|
||||
+ /* round up len to next erasesize and round down offset to prev block */
|
||||
+ len = (mtd_div_by_eb(len, part->master) + 1) * part->master->erasesize;
|
||||
+ ofs &= ~(part->master->erasesize - 1);
|
||||
+ }
|
||||
+ return part->master->_unlock(part->master, ofs, len);
|
||||
}
|
||||
|
||||
static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|
@ -1,30 +0,0 @@
|
|||
--- a/drivers/mtd/redboot.c
|
||||
+++ b/drivers/mtd/redboot.c
|
||||
@@ -265,14 +265,21 @@ static int parse_redboot_partitions(stru
|
||||
#endif
|
||||
names += strlen(names)+1;
|
||||
|
||||
-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||
if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
|
||||
- i++;
|
||||
- parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
||||
- parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
||||
- parts[i].name = nullname;
|
||||
- }
|
||||
+ if (!strcmp(parts[i].name, "rootfs")) {
|
||||
+ parts[i].size = fl->next->img->flash_base;
|
||||
+ parts[i].size &= ~(master->erasesize - 1);
|
||||
+ parts[i].size -= parts[i].offset;
|
||||
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
||||
+ nrparts--;
|
||||
+ } else {
|
||||
+ i++;
|
||||
+ parts[i].offset = parts[i-1].size + parts[i-1].offset;
|
||||
+ parts[i].size = fl->next->img->flash_base - parts[i].offset;
|
||||
+ parts[i].name = nullname;
|
||||
#endif
|
||||
+ }
|
||||
+ }
|
||||
tmp_fl = fl;
|
||||
fl = fl->next;
|
||||
kfree(tmp_fl);
|
|
@ -1,35 +0,0 @@
|
|||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -184,6 +184,22 @@ config MTD_BCM47XX_PARTS
|
||||
This provides partitions parser for devices based on BCM47xx
|
||||
boards.
|
||||
|
||||
+config MTD_MYLOADER_PARTS
|
||||
+ tristate "MyLoader partition parsing"
|
||||
+ depends on ADM5120 || ATH79
|
||||
+ ---help---
|
||||
+ MyLoader is a bootloader which allows the user to define partitions
|
||||
+ in flash devices, by putting a table in the second erase block
|
||||
+ on the device, similar to a partition table. This table gives the
|
||||
+ offsets and lengths of the user defined partitions.
|
||||
+
|
||||
+ If you need code which can detect and parse these tables, and
|
||||
+ register MTD 'partitions' corresponding to each image detected,
|
||||
+ enable this option.
|
||||
+
|
||||
+ You will still need the parsing functions to be called by the driver
|
||||
+ for your particular device. It won't happen automatically.
|
||||
+
|
||||
comment "User Modules And Translation Layers"
|
||||
|
||||
#
|
||||
--- a/drivers/mtd/Makefile
|
||||
+++ b/drivers/mtd/Makefile
|
||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
|
||||
obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
|
||||
obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
|
||||
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
|
||||
|
||||
# 'Users' - code which presents functionality to userspace.
|
||||
obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
|
|
@ -1,34 +0,0 @@
|
|||
From 841e59ba3e496d86ca5f069204d5e5c1ad43c01d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Tue, 27 Jan 2015 22:29:21 +0100
|
||||
Subject: [PATCH] mtd: bcm47xxpart: support for Xiaomi specific board_data
|
||||
partition
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
drivers/mtd/bcm47xxpart.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -33,6 +33,7 @@
|
||||
/* Magics */
|
||||
#define BOARD_DATA_MAGIC 0x5246504D /* MPFR */
|
||||
#define BOARD_DATA_MAGIC2 0xBD0D0BBD
|
||||
+#define BOARD_DATA_XIAOMI_MAGIC 0x474D4442 /* GMDB */
|
||||
#define CFE_MAGIC 0x43464531 /* 1EFC */
|
||||
#define FACTORY_MAGIC 0x59544346 /* FCTY */
|
||||
#define NVRAM_HEADER 0x48534C46 /* FLSH */
|
||||
@@ -261,7 +262,8 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
}
|
||||
|
||||
/* Some devices (ex. WNDR3700v3) don't have a standard 'MPFR' */
|
||||
- if (buf[0x000 / 4] == BOARD_DATA_MAGIC2) {
|
||||
+ if (buf[0x000 / 4] == BOARD_DATA_MAGIC2 ||
|
||||
+ le32_to_cpu(buf[0x000 / 4]) == BOARD_DATA_XIAOMI_MAGIC) {
|
||||
bcm47xxpart_add_part(&parts[curr_part++], "board_data",
|
||||
offset, MTD_WRITEABLE);
|
||||
continue;
|
|
@ -1,42 +0,0 @@
|
|||
From fd54aa583296f9adfb1f519affbc10ba521eb809 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
||||
Date: Wed, 28 Jan 2015 22:14:41 +0100
|
||||
Subject: [PATCH] mtd: bcm47xxpart: detect T_Meter partition
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It can be found on many Netgear devices. It consists of many 0x30 blocks
|
||||
starting with 4D 54.
|
||||
|
||||
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
||||
---
|
||||
drivers/mtd/bcm47xxpart.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/bcm47xxpart.c
|
||||
+++ b/drivers/mtd/bcm47xxpart.c
|
||||
@@ -39,6 +39,7 @@
|
||||
#define NVRAM_HEADER 0x48534C46 /* FLSH */
|
||||
#define POT_MAGIC1 0x54544f50 /* POTT */
|
||||
#define POT_MAGIC2 0x504f /* OP */
|
||||
+#define T_METER_MAGIC 0x4D540000 /* MT */
|
||||
#define ML_MAGIC1 0x39685a42
|
||||
#define ML_MAGIC2 0x26594131
|
||||
#define TRX_MAGIC 0x30524448
|
||||
@@ -176,6 +177,15 @@ static int bcm47xxpart_parse(struct mtd_
|
||||
MTD_WRITEABLE);
|
||||
continue;
|
||||
}
|
||||
+
|
||||
+ /* T_Meter */
|
||||
+ if ((le32_to_cpu(buf[0x000 / 4]) & 0xFFFF0000) == T_METER_MAGIC &&
|
||||
+ (le32_to_cpu(buf[0x030 / 4]) & 0xFFFF0000) == T_METER_MAGIC &&
|
||||
+ (le32_to_cpu(buf[0x060 / 4]) & 0xFFFF0000) == T_METER_MAGIC) {
|
||||
+ bcm47xxpart_add_part(&parts[curr_part++], "T_Meter", offset,
|
||||
+ MTD_WRITEABLE);
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
/* TRX */
|
||||
if (buf[0x000 / 4] == TRX_MAGIC) {
|
|
@ -1,107 +0,0 @@
|
|||
--- a/drivers/mtd/devices/block2mtd.c
|
||||
+++ b/drivers/mtd/devices/block2mtd.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -210,11 +211,12 @@ static void block2mtd_free_device(struct
|
||||
|
||||
|
||||
/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||
-static struct block2mtd_dev *add_device(char *devname, int erase_size)
|
||||
+static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
|
||||
{
|
||||
const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
|
||||
struct block_device *bdev;
|
||||
struct block2mtd_dev *dev;
|
||||
+ struct mtd_partition *part;
|
||||
char *name;
|
||||
|
||||
if (!devname)
|
||||
@@ -253,13 +255,16 @@ static struct block2mtd_dev *add_device(
|
||||
|
||||
/* Setup the MTD structure */
|
||||
/* make the name contain the block device in */
|
||||
- name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
|
||||
+ if (!mtdname)
|
||||
+ mtdname = devname;
|
||||
+ name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
|
||||
if (!name)
|
||||
goto devinit_err;
|
||||
|
||||
+ strcpy(name, mtdname);
|
||||
dev->mtd.name = name;
|
||||
|
||||
- dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
|
||||
+ dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1);
|
||||
dev->mtd.erasesize = erase_size;
|
||||
dev->mtd.writesize = 1;
|
||||
dev->mtd.writebufsize = PAGE_SIZE;
|
||||
@@ -272,15 +277,18 @@ static struct block2mtd_dev *add_device(
|
||||
dev->mtd.priv = dev;
|
||||
dev->mtd.owner = THIS_MODULE;
|
||||
|
||||
- if (mtd_device_register(&dev->mtd, NULL, 0)) {
|
||||
+ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
|
||||
+ part->name = name;
|
||||
+ part->offset = 0;
|
||||
+ part->size = dev->mtd.size;
|
||||
+ if (mtd_device_register(&dev->mtd, part, 1)) {
|
||||
/* Device didn't get added, so free the entry */
|
||||
goto devinit_err;
|
||||
}
|
||||
list_add(&dev->list, &blkmtd_device_list);
|
||||
pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
|
||||
dev->mtd.index,
|
||||
- dev->mtd.name + strlen("block2mtd: "),
|
||||
- dev->mtd.erasesize >> 10, dev->mtd.erasesize);
|
||||
+ mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize);
|
||||
return dev;
|
||||
|
||||
devinit_err:
|
||||
@@ -347,9 +355,9 @@ static char block2mtd_paramline[80 + 12]
|
||||
|
||||
static int block2mtd_setup2(const char *val)
|
||||
{
|
||||
- char buf[80 + 12]; /* 80 for device, 12 for erase size */
|
||||
+ char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */
|
||||
char *str = buf;
|
||||
- char *token[2];
|
||||
+ char *token[3];
|
||||
char *name;
|
||||
size_t erase_size = PAGE_SIZE;
|
||||
int i, ret;
|
||||
@@ -362,7 +370,7 @@ static int block2mtd_setup2(const char *
|
||||
strcpy(str, val);
|
||||
kill_final_newline(str);
|
||||
|
||||
- for (i = 0; i < 2; i++)
|
||||
+ for (i = 0; i < 3; i++)
|
||||
token[i] = strsep(&str, ",");
|
||||
|
||||
if (str) {
|
||||
@@ -388,8 +396,10 @@ static int block2mtd_setup2(const char *
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+ if (token[2] && (strlen(token[2]) + 1 > 80))
|
||||
+ pr_err("mtd device name too long\n");
|
||||
|
||||
- add_device(name, erase_size);
|
||||
+ add_device(name, erase_size, token[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -423,7 +433,7 @@ static int block2mtd_setup(const char *v
|
||||
|
||||
|
||||
module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
|
||||
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
|
||||
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
|
||||
|
||||
static int __init block2mtd_init(void)
|
||||
{
|
|
@ -1,108 +0,0 @@
|
|||
--- a/drivers/mtd/devices/block2mtd.c
|
||||
+++ b/drivers/mtd/devices/block2mtd.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
+#include <linux/delay.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/bio.h>
|
||||
@@ -211,13 +212,14 @@ static void block2mtd_free_device(struct
|
||||
|
||||
|
||||
/* FIXME: ensure that mtd->size % erase_size == 0 */
|
||||
-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
|
||||
+static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname, int timeout)
|
||||
{
|
||||
const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
|
||||
- struct block_device *bdev;
|
||||
+ struct block_device *bdev = ERR_PTR(-ENODEV);
|
||||
struct block2mtd_dev *dev;
|
||||
struct mtd_partition *part;
|
||||
char *name;
|
||||
+ int i;
|
||||
|
||||
if (!devname)
|
||||
return NULL;
|
||||
@@ -228,15 +230,20 @@ static struct block2mtd_dev *add_device(
|
||||
|
||||
/* Get a handle on the device */
|
||||
bdev = blkdev_get_by_path(devname, mode, dev);
|
||||
+
|
||||
#ifndef MODULE
|
||||
- if (IS_ERR(bdev)) {
|
||||
+ for (i = 0; IS_ERR(bdev) && i <= timeout; i++) {
|
||||
+ dev_t devt;
|
||||
|
||||
- /* We might not have rootfs mounted at this point. Try
|
||||
- to resolve the device name by other means. */
|
||||
+ if (i)
|
||||
+ msleep(1000);
|
||||
+ wait_for_device_probe();
|
||||
+
|
||||
+ devt = name_to_dev_t(devname);
|
||||
+ if (!devt)
|
||||
+ continue;
|
||||
|
||||
- dev_t devt = name_to_dev_t(devname);
|
||||
- if (devt)
|
||||
- bdev = blkdev_get_by_dev(devt, mode, dev);
|
||||
+ bdev = blkdev_get_by_dev(devt, mode, dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -355,11 +362,12 @@ static char block2mtd_paramline[80 + 12]
|
||||
|
||||
static int block2mtd_setup2(const char *val)
|
||||
{
|
||||
- char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */
|
||||
+ char buf[80 + 12 + 80 + 8]; /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
|
||||
char *str = buf;
|
||||
- char *token[3];
|
||||
+ char *token[4];
|
||||
char *name;
|
||||
size_t erase_size = PAGE_SIZE;
|
||||
+ unsigned long timeout = 0;
|
||||
int i, ret;
|
||||
|
||||
if (strnlen(val, sizeof(buf)) >= sizeof(buf)) {
|
||||
@@ -370,7 +378,7 @@ static int block2mtd_setup2(const char *
|
||||
strcpy(str, val);
|
||||
kill_final_newline(str);
|
||||
|
||||
- for (i = 0; i < 3; i++)
|
||||
+ for (i = 0; i < 4; i++)
|
||||
token[i] = strsep(&str, ",");
|
||||
|
||||
if (str) {
|
||||
@@ -399,7 +407,10 @@ static int block2mtd_setup2(const char *
|
||||
if (token[2] && (strlen(token[2]) + 1 > 80))
|
||||
pr_err("mtd device name too long\n");
|
||||
|
||||
- add_device(name, erase_size, token[2]);
|
||||
+ if (token[3] && kstrtoul(token[3], 0, &timeout))
|
||||
+ pr_err("invalid timeout\n");
|
||||
+
|
||||
+ add_device(name, erase_size, token[2], timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -433,7 +444,7 @@ static int block2mtd_setup(const char *v
|
||||
|
||||
|
||||
module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
|
||||
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
|
||||
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>[,<timeout>]]]\"");
|
||||
|
||||
static int __init block2mtd_init(void)
|
||||
{
|
||||
@@ -467,7 +478,7 @@ static void block2mtd_exit(void)
|
||||
}
|
||||
|
||||
|
||||
-module_init(block2mtd_init);
|
||||
+late_initcall(block2mtd_init);
|
||||
module_exit(block2mtd_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1,37 +0,0 @@
|
|||
---
|
||||
drivers/mtd/nand/plat_nand.c | 13 ++++++++++++-
|
||||
include/linux/mtd/nand.h | 1 +
|
||||
2 files changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/linux/mtd/nand.h
|
||||
+++ b/include/linux/mtd/nand.h
|
||||
@@ -756,6 +756,7 @@ struct platform_nand_chip {
|
||||
unsigned int options;
|
||||
unsigned int bbt_options;
|
||||
const char **part_probe_types;
|
||||
+ int (*chip_fixup)(struct mtd_info *mtd);
|
||||
};
|
||||
|
||||
/* Keep gcc happy */
|
||||
--- a/drivers/mtd/nand/plat_nand.c
|
||||
+++ b/drivers/mtd/nand/plat_nand.c
|
||||
@@ -90,7 +90,18 @@ static int plat_nand_probe(struct platfo
|
||||
}
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
- if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
|
||||
+ if (nand_scan_ident(&data->mtd, pdata->chip.nr_chips, NULL)) {
|
||||
+ err = -ENXIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (pdata->chip.chip_fixup) {
|
||||
+ err = pdata->chip.chip_fixup(&data->mtd);
|
||||
+ if (err)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (nand_scan_tail(&data->mtd)) {
|
||||
err = -ENXIO;
|
||||
goto out;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
--- a/drivers/mtd/nand/nand_ecc.c
|
||||
+++ b/drivers/mtd/nand/nand_ecc.c
|
||||
@@ -507,7 +507,7 @@ int __nand_correct_data(unsigned char *b
|
||||
return 1; /* error in ECC data; no action needed */
|
||||
|
||||
pr_err("%s: uncorrectable ECC error", __func__);
|
||||
- return -1;
|
||||
+ return -EBADMSG;
|
||||
}
|
||||
EXPORT_SYMBOL(__nand_correct_data);
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
@@ -780,7 +780,7 @@ static int get_chip(struct map_info *map
|
||||
return 0;
|
||||
|
||||
case FL_ERASING:
|
||||
- if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
|
||||
+ if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
|
||||
!(mode == FL_READY || mode == FL_POINT ||
|
||||
(mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
|
||||
goto sleep;
|
|
@ -1,18 +0,0 @@
|
|||
From: George Kashperko <george@znau.edu.ua>
|
||||
|
||||
Issue map read after Write Buffer Load command to ensure chip is ready
|
||||
to receive data.
|
||||
Signed-off-by: George Kashperko <george@znau.edu.ua>
|
||||
---
|
||||
drivers/mtd/chips/cfi_cmdset_0002.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
||||
@@ -1498,6 +1498,7 @@ static int __xipram do_write_buffer(stru
|
||||
|
||||
/* Write Buffer Load */
|
||||
map_write(map, CMD(0x25), cmd_adr);
|
||||
+ (void) map_read(map, cmd_adr);
|
||||
|
||||
chip->state = FL_WRITING_TO_BUFFER;
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
--- a/drivers/mtd/devices/Kconfig
|
||||
+++ b/drivers/mtd/devices/Kconfig
|
||||
@@ -102,6 +102,14 @@ config MTD_SPEAR_SMI
|
||||
help
|
||||
This enable SNOR support on SPEAR platforms using SMI controller
|
||||
|
||||
+config M25PXX_PREFER_SMALL_SECTOR_ERASE
|
||||
+ bool "Prefer small sector erase"
|
||||
+ depends on MTD_M25P80
|
||||
+ default y
|
||||
+ help
|
||||
+ This option enables use of the small erase sectors if that is
|
||||
+ supported by the flash chip.
|
||||
+
|
||||
config MTD_SST25L
|
||||
tristate "Support SST25L (non JEDEC) SPI Flash chips"
|
||||
depends on SPI_MASTER
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -90,6 +90,12 @@
|
||||
|
||||
#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16)
|
||||
|
||||
+#ifdef CONFIG_M25PXX_PREFER_SMALL_SECTOR_ERASE
|
||||
+#define PREFER_SMALL_SECTOR_ERASE 1
|
||||
+#else
|
||||
+#define PREFER_SMALL_SECTOR_ERASE 0
|
||||
+#endif
|
||||
+
|
||||
/****************************************************************************/
|
||||
|
||||
enum read_type {
|
||||
@@ -1192,7 +1198,7 @@ static int m25p_probe(struct spi_device
|
||||
flash->mtd._write = m25p80_write;
|
||||
|
||||
/* prefer "small sector" erase if possible */
|
||||
- if (info->flags & SECT_4K) {
|
||||
+ if (PREFER_SMALL_SECTOR_ERASE && (info->flags & SECT_4K)) {
|
||||
flash->erase_opcode = OPCODE_BE_4K;
|
||||
flash->mtd.erasesize = 4096;
|
||||
} else if (info->flags & SECT_4K_PMC) {
|
|
@ -1,20 +0,0 @@
|
|||
From eef9dfc4e821408af1af13aa0cc707fc496fb7c6 Mon Sep 17 00:00:00 2001
|
||||
From: Gabor Juhos <juhosg@openwrt.org>
|
||||
Date: Wed, 11 Dec 2013 19:05:59 +0100
|
||||
Subject: [PATCH] m25p80: add support for the Winbond W25X05 flash
|
||||
|
||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -1022,6 +1022,7 @@ static const struct spi_device_id m25p_i
|
||||
{ "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) },
|
||||
|
||||
/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
|
||||
+ { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) },
|
||||
{ "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
|
||||
{ "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
|
||||
{ "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
|
|
@ -1,20 +0,0 @@
|
|||
From 0233dcb52eefa0b29250a6d8a58b3143790df57d Mon Sep 17 00:00:00 2001
|
||||
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
Date: Wed, 11 Jun 2014 02:23:00 +0400
|
||||
Subject: [PATCH] mtd: m25p80: add support for EON EN25QH128
|
||||
|
||||
Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
|
||||
---
|
||||
drivers/mtd/devices/m25p80.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/mtd/devices/m25p80.c
|
||||
+++ b/drivers/mtd/devices/m25p80.c
|
||||
@@ -909,6 +909,7 @@ static const struct spi_device_id m25p_i
|
||||
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
|
||||
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
|
||||
{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
|
||||
+ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
|
||||
{ "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
|
||||
|
||||
/* ESMT */
|
|
@ -1,26 +0,0 @@
|
|||
--- a/drivers/mtd/mtdcore.c
|
||||
+++ b/drivers/mtd/mtdcore.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/root_dev.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
@@ -414,6 +415,15 @@ int add_mtd_device(struct mtd_info *mtd)
|
||||
of this try_ nonsense, and no bitching about it
|
||||
either. :) */
|
||||
__module_get(THIS_MODULE);
|
||||
+
|
||||
+ if (!strcmp(mtd->name, "rootfs") &&
|
||||
+ config_enabled(CONFIG_MTD_ROOTFS_ROOT_DEV) &&
|
||||
+ ROOT_DEV == 0) {
|
||||
+ pr_notice("mtd: device %d (%s) set to be root filesystem\n",
|
||||
+ mtd->index, mtd->name);
|
||||
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
fail_added:
|
|
@ -1,51 +0,0 @@
|
|||
--- a/drivers/mtd/ubi/attach.c
|
||||
+++ b/drivers/mtd/ubi/attach.c
|
||||
@@ -800,6 +800,13 @@ out_unlock:
|
||||
return err;
|
||||
}
|
||||
|
||||
+static bool ec_hdr_has_eof(struct ubi_ec_hdr *ech)
|
||||
+{
|
||||
+ return ech->padding1[0] == 'E' &&
|
||||
+ ech->padding1[1] == 'O' &&
|
||||
+ ech->padding1[2] == 'F';
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* scan_peb - scan and process UBI headers of a PEB.
|
||||
* @ubi: UBI device description object
|
||||
@@ -830,9 +837,21 @@ static int scan_peb(struct ubi_device *u
|
||||
return 0;
|
||||
}
|
||||
|
||||
- err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
|
||||
- if (err < 0)
|
||||
- return err;
|
||||
+ if (!ai->eof_found) {
|
||||
+ err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
|
||||
+ if (err < 0)
|
||||
+ return err;
|
||||
+
|
||||
+ if (ec_hdr_has_eof(ech)) {
|
||||
+ ubi_msg("EOF marker found, PEBs from %d will be erased",
|
||||
+ pnum);
|
||||
+ ai->eof_found = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (ai->eof_found)
|
||||
+ err = UBI_IO_FF_BITFLIPS;
|
||||
+
|
||||
switch (err) {
|
||||
case 0:
|
||||
break;
|
||||
--- a/drivers/mtd/ubi/ubi.h
|
||||
+++ b/drivers/mtd/ubi/ubi.h
|
||||
@@ -701,6 +701,7 @@ struct ubi_attach_info {
|
||||
int mean_ec;
|
||||
uint64_t ec_sum;
|
||||
int ec_count;
|
||||
+ bool eof_found;
|
||||
struct kmem_cache *aeb_slab_cache;
|
||||
};
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
From 8a52e4100d7c3a4a1dfddfa02b8864a9b0068c13 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Sat, 17 May 2014 03:36:18 +0200
|
||||
Subject: [PATCH 1/5] ubi: auto-attach mtd device named "ubi" or "data" on boot
|
||||
To: openwrt-devel@lists.openwrt.org
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/mtd/ubi/build.c | 36 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 36 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/ubi/build.c
|
||||
+++ b/drivers/mtd/ubi/build.c
|
||||
@@ -1209,6 +1209,49 @@ static struct mtd_info * __init open_mtd
|
||||
return mtd;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * This function tries attaching mtd partitions named either "ubi" or "data"
|
||||
+ * during boot.
|
||||
+ */
|
||||
+static void __init ubi_auto_attach(void)
|
||||
+{
|
||||
+ int err;
|
||||
+ struct mtd_info *mtd;
|
||||
+
|
||||
+ /* try attaching mtd device named "ubi" or "data" */
|
||||
+ mtd = open_mtd_device("ubi");
|
||||
+ if (IS_ERR(mtd))
|
||||
+ mtd = open_mtd_device("data");
|
||||
+
|
||||
+ if (!IS_ERR(mtd)) {
|
||||
+ size_t len;
|
||||
+ char magic[4];
|
||||
+
|
||||
+ /* check for a valid ubi magic */
|
||||
+ err = mtd_read(mtd, 0, 4, &len, (void *) magic);
|
||||
+ if (!err && len == 4 && strncmp(magic, "UBI#", 4)) {
|
||||
+ ubi_err("no valid UBI magic found inside mtd%d", mtd->index);
|
||||
+ put_mtd_device(mtd);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* auto-add only media types where UBI makes sense */
|
||||
+ if (mtd->type == MTD_NANDFLASH ||
|
||||
+ mtd->type == MTD_NORFLASH ||
|
||||
+ mtd->type == MTD_DATAFLASH ||
|
||||
+ mtd->type == MTD_MLCNANDFLASH) {
|
||||
+ mutex_lock(&ubi_devices_mutex);
|
||||
+ ubi_msg("auto-attach mtd%d", mtd->index);
|
||||
+ err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0);
|
||||
+ mutex_unlock(&ubi_devices_mutex);
|
||||
+ if (err < 0) {
|
||||
+ ubi_err("cannot attach mtd%d", mtd->index);
|
||||
+ put_mtd_device(mtd);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int __init ubi_init(void)
|
||||
{
|
||||
int err, i, k;
|
||||
@@ -1298,6 +1341,12 @@ static int __init ubi_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* auto-attach mtd devices only if built-in to the kernel and no ubi.mtd
|
||||
+ * parameter was given */
|
||||
+ if (config_enabled(CONFIG_MTD_ROOTFS_ROOT_DEV) &&
|
||||
+ !ubi_is_module() && !mtd_devs)
|
||||
+ ubi_auto_attach();
|
||||
+
|
||||
err = ubiblock_init();
|
||||
if (err) {
|
||||
ubi_err("block: cannot initialize, error %d", err);
|
|
@ -1,69 +0,0 @@
|
|||
From 0f3966579815f889bb2fcb4846152c35f65e79c4 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Thu, 15 May 2014 21:06:33 +0200
|
||||
Subject: [PATCH 2/5] ubi: auto-create ubiblock device for rootfs
|
||||
To: openwrt-devel@lists.openwrt.org
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/mtd/ubi/block.c | 42 ++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 42 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -593,6 +593,44 @@ static int __init ubiblock_create_from_p
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#define UBIFS_NODE_MAGIC 0x06101831
|
||||
+static inline int ubi_vol_is_ubifs(struct ubi_volume_desc *desc)
|
||||
+{
|
||||
+ int ret;
|
||||
+ uint32_t magic_of, magic;
|
||||
+ ret = ubi_read(desc, 0, (char *)&magic_of, 0, 4);
|
||||
+ if (ret)
|
||||
+ return 0;
|
||||
+ magic = le32_to_cpu(magic_of);
|
||||
+ return magic == UBIFS_NODE_MAGIC;
|
||||
+}
|
||||
+
|
||||
+static void __init ubiblock_create_auto_rootfs(void)
|
||||
+{
|
||||
+ int ubi_num, ret, is_ubifs;
|
||||
+ struct ubi_volume_desc *desc;
|
||||
+ struct ubi_volume_info vi;
|
||||
+
|
||||
+ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) {
|
||||
+ desc = ubi_open_volume_nm(ubi_num, "rootfs", UBI_READONLY);
|
||||
+ if (IS_ERR(desc))
|
||||
+ continue;
|
||||
+
|
||||
+ ubi_get_volume_info(desc, &vi);
|
||||
+ is_ubifs = ubi_vol_is_ubifs(desc);
|
||||
+ ubi_close_volume(desc);
|
||||
+ if (is_ubifs)
|
||||
+ break;
|
||||
+
|
||||
+ ret = ubiblock_create(&vi);
|
||||
+ if (ret)
|
||||
+ ubi_err("block: can't add '%s' volume, err=%d\n",
|
||||
+ vi.name, ret);
|
||||
+ /* always break if we get here */
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void ubiblock_remove_all(void)
|
||||
{
|
||||
struct ubiblock *next;
|
||||
@@ -623,6 +661,10 @@ int __init ubiblock_init(void)
|
||||
if (ret)
|
||||
goto err_remove;
|
||||
|
||||
+ /* auto-attach "rootfs" volume if existing and non-ubifs */
|
||||
+ if (config_enabled(CONFIG_MTD_ROOTFS_ROOT_DEV))
|
||||
+ ubiblock_create_auto_rootfs();
|
||||
+
|
||||
/*
|
||||
* Block devices are only created upon user requests, so we ignore
|
||||
* existing volumes.
|
|
@ -1,53 +0,0 @@
|
|||
From eea9e1785e4c05c2a3444506aabafa0ae958538f Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Sat, 17 May 2014 03:35:02 +0200
|
||||
Subject: [PATCH 4/5] try auto-mounting ubi0:rootfs in init/do_mounts.c
|
||||
To: openwrt-devel@lists.openwrt.org
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
init/do_mounts.c | 26 +++++++++++++++++++++++++-
|
||||
1 file changed, 25 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/init/do_mounts.c
|
||||
+++ b/init/do_mounts.c
|
||||
@@ -432,7 +432,27 @@ retry:
|
||||
out:
|
||||
put_page(page);
|
||||
}
|
||||
-
|
||||
+
|
||||
+static int __init mount_ubi_rootfs(void)
|
||||
+{
|
||||
+ int flags = MS_SILENT;
|
||||
+ int err, tried = 0;
|
||||
+
|
||||
+ while (tried < 2) {
|
||||
+ err = do_mount_root("ubi0:rootfs", "ubifs", flags, \
|
||||
+ root_mount_data);
|
||||
+ switch (err) {
|
||||
+ case -EACCES:
|
||||
+ flags |= MS_RDONLY;
|
||||
+ tried++;
|
||||
+ default:
|
||||
+ return err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_ROOT_NFS
|
||||
|
||||
#define NFSROOT_TIMEOUT_MIN 5
|
||||
@@ -526,6 +546,10 @@ void __init mount_root(void)
|
||||
change_floppy("root floppy");
|
||||
}
|
||||
#endif
|
||||
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
|
||||
+ if (!mount_ubi_rootfs())
|
||||
+ return;
|
||||
+#endif
|
||||
#ifdef CONFIG_BLOCK
|
||||
create_dev("/dev/root", ROOT_DEV);
|
||||
mount_block_root("/dev/root", root_mountflags);
|
|
@ -1,37 +0,0 @@
|
|||
From cd68d1b12b5ea4c01a664c064179ada42bf55d3d Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Golle <daniel@makrotopia.org>
|
||||
Date: Thu, 15 May 2014 20:55:42 +0200
|
||||
Subject: [PATCH 5/5] ubi: set ROOT_DEV to ubiblock "rootfs" if unset
|
||||
To: openwrt-devel@lists.openwrt.org
|
||||
|
||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
---
|
||||
drivers/mtd/ubi/block.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/mtd/ubi/block.c
|
||||
+++ b/drivers/mtd/ubi/block.c
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <asm/div64.h>
|
||||
+#include <linux/root_dev.h>
|
||||
|
||||
#include "ubi-media.h"
|
||||
#include "ubi.h"
|
||||
@@ -444,6 +445,15 @@ int ubiblock_create(struct ubi_volume_in
|
||||
add_disk(dev->gd);
|
||||
ubi_msg("%s created from ubi%d:%d(%s)",
|
||||
dev->gd->disk_name, dev->ubi_num, dev->vol_id, vi->name);
|
||||
+
|
||||
+ if (!strcmp(vi->name, "rootfs") &&
|
||||
+ config_enabled(CONFIG_MTD_ROOTFS_ROOT_DEV) &&
|
||||
+ ROOT_DEV == 0) {
|
||||
+ pr_notice("ubiblock: device ubiblock%d_%d (%s) set to be root filesystem\n",
|
||||
+ dev->ubi_num, dev->vol_id, vi->name);
|
||||
+ ROOT_DEV = MKDEV(gd->major, gd->first_minor);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
|
||||
out_free_queue:
|
|
@ -1,18 +0,0 @@
|
|||
--- a/fs/Kconfig
|
||||
+++ b/fs/Kconfig
|
||||
@@ -39,6 +39,7 @@ source "fs/gfs2/Kconfig"
|
||||
source "fs/ocfs2/Kconfig"
|
||||
source "fs/btrfs/Kconfig"
|
||||
source "fs/nilfs2/Kconfig"
|
||||
+source "fs/yaffs2/Kconfig"
|
||||
|
||||
endif # BLOCK
|
||||
|
||||
--- a/fs/Makefile
|
||||
+++ b/fs/Makefile
|
||||
@@ -126,3 +126,5 @@ obj-y += exofs/ # Multiple modules
|
||||
obj-$(CONFIG_CEPH_FS) += ceph/
|
||||
obj-$(CONFIG_PSTORE) += pstore/
|
||||
obj-$(CONFIG_EFIVAR_FS) += efivarfs/
|
||||
+obj-$(CONFIG_YAFFS_FS) += yaffs2/
|
||||
+
|
|
@ -1,38 +0,0 @@
|
|||
--- a/fs/yaffs2/yaffs_vfs.c
|
||||
+++ b/fs/yaffs2/yaffs_vfs.c
|
||||
@@ -738,7 +738,7 @@ static int yaffs_file_flush(struct file
|
||||
|
||||
yaffs_gross_lock(dev);
|
||||
|
||||
- yaffs_flush_file(obj, 1, 0);
|
||||
+ yaffs_flush_file(obj, 1, 0, 1);
|
||||
|
||||
yaffs_gross_unlock(dev);
|
||||
|
||||
@@ -768,7 +768,7 @@ static int yaffs_sync_object(struct file
|
||||
yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
|
||||
"yaffs_sync_object");
|
||||
yaffs_gross_lock(dev);
|
||||
- yaffs_flush_file(obj, 1, datasync);
|
||||
+ yaffs_flush_file(obj, 1, datasync, 1);
|
||||
yaffs_gross_unlock(dev);
|
||||
return 0;
|
||||
}
|
||||
@@ -2187,7 +2187,7 @@ static void yaffs_flush_inodes(struct su
|
||||
yaffs_trace(YAFFS_TRACE_OS,
|
||||
"flushing obj %d",
|
||||
obj->obj_id);
|
||||
- yaffs_flush_file(obj, 1, 0);
|
||||
+ yaffs_flush_file(obj, 1, 0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct sup
|
||||
|
||||
yaffs_flush_inodes(sb);
|
||||
yaffs_update_dirty_dirs(dev);
|
||||
- yaffs_flush_whole_cache(dev);
|
||||
+ yaffs_flush_whole_cache(dev, 1);
|
||||
if (do_checkpoint)
|
||||
yaffs_checkpoint_save(dev);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue